0

I have an application that I am auditing that runs code from an imported DLL. Said DLL itself has imports. Specifically, during execution there's a point where the following is called (EIP is in said DLL):

68DC6648:    jmp dword ptr ds:[68DD21C8h]
68DC664E:    nop
68DC664f:    nop

I performed

disasm /all /disasm X:\path\to\dll\myDll.dll

On the DLL in an attempt to determine where [68DD21C8] goes to. Mosdef appears as though it is a part of a thunk table for relocations or IAT. My assumption sppears to be correct, as I find [68DD21C8] under the .reloc header under a section called BASE RELOCATIONS:

BASE RELOCATIONS #4
...    ...        ...
6000 RVA,    10C SizeOfBlock
...    ...        ...
64A    HIGHLOW    68DD21C8

The preferred image base is:

68DC0000 image base (68DC0000 to 68DD7FFFF)

Also, the DLL entrypoint appears to be 68DC1000.

My question is: how do I determine the memory address for [68DD21C8] and its relative code/disassembly?

I tried baseaddr + RVA + ordinal to get: 68DC0000 + 6000 + 64A == 68DC664A

However, it falls within range of my disassembled code. In my disassembly from dumpbin, 68DC664A isn't a valid address and would lie between the previously stated thunk!

68DC6648:    jmp dword ptr ds:[68DD21C8h] ;<--contains 68DC664A!!!
68DC664E:    nop
68DC664f:    nop

I double checked I have my maths right and searched around, found this previous answer on stack exchange, but it only verified my math above was correct

1 Answer 1

1

If you have set a proper _NT_SYMBOL_PATH dumpbin uses the symbols if they exist and provide you a name of the import instead of hex

the example below shows alls that have resolved names instead of hex for windows calc.exe

C:\>dumpbin /disasm c:\WINDOWS\system32\calc.exe | grep -i "jmp.*\["
  01004A9B: FF 24 85 FA 50 00  jmp         dword ptr [eax*4+10050FAh]
  01007BC8: FF 25 7C 10 00 01  jmp         dword ptr [__imp__LocalFree@4]
  0101263C: FF 25 BC 11 00 01  jmp         dword ptr [__imp____CxxFrameHandler]
  01012670: FF 25 C0 11 00 01  jmp         dword ptr [__imp___CxxThrowException@8]
  010127A4: FF 25 E4 11 00 01  jmp         dword ptr [__imp___XcptFilter]

in case there are no symbols

C:\>dumpbin /disasm c:\usedll.exe | grep -i "jmp.*\["
  0040106E: FF 25 0C 20 40 00  jmp         dword ptr ds:[0040200Ch]
  00401074: FF 25 00 20 40 00  jmp         dword ptr ds:[00402000h]
  0040107A: FF 25 04 20 40 00  jmp         dword ptr ds:[00402004h]
  00401080: FF 25 08 20 40 00  jmp         dword ptr ds:[00402008h]
  00401086: FF 25 14 20 40 00  jmp         dword ptr ds:[00402014h]

you can view the raw data at the address (if it is an imported address it would be an unresolved first thunk ) windows loader fills it when it is loading the exe dump bin does not resolve it

C:\>dumpbin /RAWDATA:4,6 c:\usedll.exe | grep 402000
  00402000: 00002082 00002090 000020A2 00002074 00000000 000020C0

to resolve this manually you should parse the import table 00002082 will point to an import 00002090 will point to another import in x.dll etc 00000000 is a seperator 20c0 will point to an import in y.dll and so on name of x.dll , y.dll z.dll will also be the part of import table

here is a complete import table of a non symbol exe

C:\>dumpbin /RAWDATA:4 c:\usedll.exe | grep -A 14 402000
  00402000: 00002082 00002090 000020A2 00002074  . ... ..ó ..t ..
  00402010: 00000000 000020C0 00000000 00002058  ....└ ......X ..
  00402020: 00000000 00000000 000020B2 00002000  ........▓ ... ..
  00402030: 0000206C 00000000 00000000 000020CE  l ..........╬ ..
  00402040: 00002014 00000000 00000000 00000000  . ..............
  00402050: 00000000 00000000 00002082 00002090  ......... ... ..
  00402060: 000020A2 00002074 00000000 000020C0  ó ..t ......└ ..
  00402070: 00000000 78450075 72507469 7365636F  ....u.ExitProces
  00402080: 00A20073 65657246 7262694C 00797261  s.ó.FreeLibrary.
  00402090: 65470129 6F725074 64644163 73736572  ).GetProcAddress
  004020A0: 01A90000 64616F4C 7262694C 41797261  ..⌐.LoadLibraryA
  004020B0: 454B0000 4C454E52 642E3233 00006C6C  ..KERNEL32.dll..
  004020C0: 654D01BB 67617373 786F4265 53550041  ╗.MessageBoxA.US
  004020D0: 32335245 6C6C642E 00 00              ER32.dll..

you can observe 20b2 and 20ce pointing to kernel32.dll and user32.dll respectively

edit

the address in your query does not point to an import table it is part of reloc or a fixup
fixups do not jump between modules they fall within the module being examined

C:\>dumpbin /RELOCATIONS c:\WINDOWS\system32\kernel32.dll | head -n 11 | tail -3

BASE RELOCATIONS #4
    1000 RVA,       70 SizeOfBlock
     62C  HIGHLOW            7C810B50

C:\>dumpbin /Rawdata:4 c:\WINDOWS\system32\kernel32.dll | grep -i 7c801620
  7C801620: 00000000 90909090 68146A90 7C810B50  .........j.hP..|

notice 7c810b50  if the dll is loaded in preferred imagebase this wont change

if the image base is changed loader will find the dword at imagebase+rva+offset 
subtract the preferred imagebase and add the new imagebase to that result and
patch the dword to point to correct location 

suppose the preferrred imagebase of 7c800000 wasn't available and dll was loaded at 7d800000 
loader will fetch the dword 7c810b50 at 7d80162c subtract 7c800000 from it result = 10b50 
add 7d800000 and patch 7c810b50 to 7d810b50 

in the query
you say

68DC6648:    jmp dword ptr ds:[68DD21C8h] ;<--contains 68DC664A!!!

that means it is jumping to the middle of the opcode disassembling 68dc66fa you get

xxxxx       68 DC664A90     PUSH    904A66DC
xxxxx       90              NOP

you may need something better than dumpbin to deal with obfuscation

edit

regarding your comment about import parsing no the offsets have nothing to do with base + rva + xxx
they do not point to any remote module no reference to any import module address exist in the importing module
(just take a step back and think what would happen if the dll in the import
table was rebased ?? where the exe is going to look for ?? get the idea??)

in the import table pasted above 2082,2090,20a2,2074 points to 4 imports from first dll 20c0 points to 1 import from second dll this is firstthunk that will be replaced by the loader with actual import address

import table is denoted in pe header->optinal header->datadir[1]

0:000> dt ntdll!_IMAGE_NT_HEADERS -y opt.datadi[1]. 4000b0
   +0x018 OptionalHeader : 
      +0x060 DataDirectory  : [1] 
         +0x000 VirtualAddress : 0x201c
         +0x004 Size           : 0x3c

see 201c and size 3c that is 15 dwords see below for splitup

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
  union   {
    DWORD   Characteristics;
    DWORD   OriginalFirstThunk;   <-----00002058,0000206c,00000000
  } DUMMYUNIONNAME;
  DWORD   TimeDateStamp;    <-----------00000000,00000000,00000000
  DWORD   ForwarderChain;   <-----------00000000,00000000,00000000
  DWORD   Name;             <-----------000020b2,000020ce,00000000 
  DWORD   FirstThunk;       <-----------00002000,00002014,00000000
} IMAGE_IMPORT_DESCRIPTOR;
the last is a null entry that means 5 dwords that are 00000000

the original firstthunk a copy of first thunk stays as it is the orignal first thunk gets modified by loader loader loads the specified dll using an internal function of LoadLibrary()--->LdrLoadDll() and uses an internal api of GetProcAddress to fetch the importAddress and patches the OriignalFirstThunk

the module being examined has no inkling about the addresses you cant manually calculate anything about a remote dll import from import table

4
  • So i ran dumpbin /RAWDATA:4 myDll.dll and checked the dumpbin raw data dump and I think I understand. So each contiguous series of bytes not separated by 0's (e.g. 2082, 2090, 20A2, 2074) represents imports from another DLL, and I would have to note the order of contiguous bytes to tell which specific DLL and import its' referring to? Last, in your example, the 2082 can be used to calculate the memory address in its DLL in the same manner as above, e.g. dll base addr + RVA + ord (in this case, 2082) ?
    – grepNstepN
    Nov 2, 2015 at 20:39
  • makes sense. thats why they call it fixing up relocations. thanks blabb, spot on! I tried to RTFM but you made more sense msdn.microsoft.com/en-us/library/ms809762.aspx
    – grepNstepN
    Nov 2, 2015 at 21:03
  • no import table offsets cannot be used to parse any address from remote module i added some details about how import parsing is done take a look
    – blabb
    Nov 3, 2015 at 5:29
  • That helped immensely! I started to manually parse the array of IMAGE_IMPORT_DESCRIPTOR structures my dll had and I made sense of it. Also found out Iczelion had a tut on that. I'll have a beer for ya at the end of the day mate
    – grepNstepN
    Nov 4, 2015 at 16:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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