I'm busy following a tutorial where the author uses DUMPBIN to list exports, and OllyDbg to get the assembly code for an exported function. How would I find the functions code in the complete disassemly, given that the export tables RVA's don't correspond to real addresses in the disassembly.
A pretty good good indicator for a function, at least for programs written in high level languages is code that sets up a stack frame.
If you know the compiler that has been used to generate the code in question you should be able to find out what to look for.
Example
$ cat main.c
int main(int argc, char **argv) {
return 1;
}
$ gcc -m32 -S main.c
$ cat main.s
.file "main.c"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
movl $1, %eax
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (Debian 4.3.3-4) 4.3.3"
.section .note.GNU-stack,"",@progbits
In my example, the movl %esp, %ebp instruction is the last instruction of that setup code.
The commercial disassembler IDA Pro for which a free-as-in-beer version is available for download does a pretty good job of automatically finding functions.
A RVA is a relocatable virtual address. To find the real address in the process space you need to know the base address where the module was loaded in the process. Add that base address to the RVA and you have the real address. I haven't used ollydbg but I'd be astounded if it didn't supply the base address for the modules loaded in the process to which it was attached. If for some reason it doesn't supply that info, you can get it by using procexp.exe from the sysinternal tools.