3

I've been reverse engineering a PE executable and I came across a behavior that I can't understand. The executable uses both shell32.dll and profapi.dll. I see that shell32.dll delay loads a function in profapi.dll using an ordinal value (I verified this by looking at the delay load import table of shell32.dll). However, profapi.dll does not export any functions as it doesn't even have an export table. I'm examining the delay import and export sections of these DLLs using the Python library pefile. I'm using profapi.dll version 6.1.7600.16385 (as reported by the file properties) on Windows 7.

From what I understand, to load a function by ordinal or name from profapi.dll, you still need access to profapi.dll's export table. Is there another way through which profapi.dll could expose the addresses of its functions, or am I missing something?

EDIT: It looks like it was an issue with pefile parsing the DLL. I was indeed able to examine the export section using IDApro. I am leaving the question up to highlight what looks like a potential bug in pefile. I am using pefile version 1.2.10-139.

2

profapi.dll should certainly have an Export Table. For example, here's the Export Table from profapi.dll version 6.3.9600.16384:

There is an export table in .text at 0x10001000

The Export Tables (interpreted .text section contents)

Export Flags                    0
Time/Date stamp                 52157da7
Major/Minor                     0/0
Name                            00001060 profapi.dll
Ordinal Base                    101
Number in:
        Export Address Table            0000000e
        [Name Pointer/Ordinal] Table    00000000
Table Addresses
        Export Address Table            00001028
        Name Pointer Table              00000000
        Ordinal Table                   00000000

Export Address Table -- Ordinal Base 101
        [   0] +base[ 101] 2b24 Export RVA
        [   1] +base[ 102] 25c2 Export RVA
        [   2] +base[ 103] 3cd9 Export RVA
        [   3] +base[ 104] 1089 Export RVA
        [   4] +base[ 105] 4a8b Export RVA
        [   5] +base[ 106] 49b2 Export RVA
        [   6] +base[ 107] 42ae Export RVA
        [   7] +base[ 108] 4643 Export RVA
        [   8] +base[ 109] 45ce Export RVA
        [   9] +base[ 110] 4592 Export RVA
        [  10] +base[ 111] 3dc3 Export RVA
        [  11] +base[ 112] 4318 Export RVA
        [  12] +base[ 113] 428d Export RVA
        [  13] +base[ 114] 3bcd Export RVA

I just checked version 6.1.7600.16385 from Windows 7 and confirmed that it too has an Export Table, from which it exports 6 functions by ordinal. If the Python library you're using isn't seeing these functions then it's due to a bug in the Python library (or potentially your usage of it).

For what it's worth, this is a known issue in older versions of the pefile library and was fixed about a year ago. Perhaps you're using an outdated version?

  • I'm using profapi.dll version 6.1.7600.16385 (as reported by the file properties). I'm using the Python library pefile to list the export table entries of profapi.dll. Also, this suggests that profapi.dll does not have an export section: win7dll.info/profapi_dll.html. Looking at the entire PE dump produced by pefile, I see that there is indeed a valid entry in the RVA of IMAGE_DIRECTORY_ENTRY_EXPORT, but I see that I'm getting a parsing error with pefile saying "RVA AddressOfNames in the export directory points to an invalid address". I'm not sure if this is a pefile parsing error. – redraga Nov 14 '14 at 21:54
  • 1
    EDIT: It looks like it's an issue with pefile. I was indeed able to locate the export section of profapi.dll using IDAPro. I have updated the original question with a note mentioning what appears to be a bug in pefile. – redraga Nov 14 '14 at 22:04
  • You made your edit at the same time I made mine -- glad we came to the same conclusion :) – Jason Geffner Nov 14 '14 at 22:10
  • See the last paragraph in my answer regarding the pefile update. – Jason Geffner Nov 14 '14 at 22:14
  • It looks like pefile does not parse the export section since both Name pointer table and Ordinal pointer table are NULL, and it uses this information to walk the EAT. I know I can change pefile's behavior by directly walking the EAT based on the number of exported functions to get function pointer addresses, but I'm more interested in knowing why the Name and Ordinal table pointers are NULL in profapi. Also, how does the loader patch the exported functions? I'm not sure if this is right place to post this. I can make a separate question later if needed. – redraga Nov 17 '14 at 20:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.