Search code examples
c++winapiportable-executable

Finding function offset from file from RVA


I want to find a function inside my .exe, and memcpy it somewhere else.

I have used the IDIA SDK to parse the .pdb file for my .exe, which contains a simple function named "myFunction", which simply performs an assembly "ret", just for demonstration purposes.

if (pTable->QueryInterface(__uuidof(IDiaEnumSymbols), (void**) &pUnknown) == S_OK) {
            printf("Supports Symbol module\n");
            CComPtr<IDiaSymbol> pSymbol;

            for (LONG i = 0; i < blongTableCount; i++)
            {
                if (pUnknown->Item(i, &pSymbol) != S_OK) {
                    fprintf(stderr, "Error: pUnknown->Item");
                }
                
                BOOL isFunction;
                if (pSymbol->get_function(&isFunction) == S_OK) {
                    if (isFunction == TRUE) {

                        BSTR symName;
                        if (pSymbol->get_name(&symName) == S_OK) {
                            printf("Symbol name: %S\n", symName);
                            
                            ULONGLONG length;
                            if (pSymbol->get_length(&length) == S_OK) {
                                printf("Length of symbol: %I64u\n", length);
                            }
                            DWORD ret;
                            if (pSymbol->get_locationType(&ret) == S_OK) {
                                switch (ret) {
                                    case LocIsStatic:
                                        printf("LocIsStatic\n");
                                        break;
                                    case LocIsThisRel:
                                        printf("LocIsThisRel\n");
                                        break;
                                }
                            }
                            if (pSymbol->get_relativeVirtualAddress(&ret) == S_OK) {
                                printf("RVA: 0x%0.5x\n", ret);
                            }
                            ULONGLONG va;
                            if (pSymbol->get_virtualAddress(&va) == S_OK) {
                                printf("VA: %I64u\n", va);
                            }
                        }
                    }
                }
                
                pSymbol = NULL;

            }
        }

This produces, among other things, the following relevant output:

Symbol name: ?myFunction@@YAXXZ
Length of Symbol: 44
LocIsStatic
RVA: 0x119e0
VA: 72160

The VA and RVA values are always the same, for some reason.

I then loaded my .exe file on IDA disassembler, and I found at the address 0x4119e0 the sequence of 44 bytes, along with 4 "white-space" bytes with the value "CC CC CC CC".

Therefore, what I want to do is to find the offset from my file on disk, using the RVA (0x119e0).

On this question (getting offset in file from RVA), the following formula is used:

off = section_off + (rva - section_rva).

However, in my case, I am confused as to what values to use in this formula. 0x119e0 corresponds to 72,160, meanwhile my entire .exe file is only 40,448 bytes long.


Solution

  • The formula you gave is not what is described in the answer to the question you linked. The answer to that question is, however, correct; you need to find which section contains the RVA of interest, and then add the difference between that RVA and the RVA corresponding to the start (i.e. first byte) of that section to the file offset corresponding to the start of the section.

    In other words

    off = section_off + (rva - section_rva).