News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Jump table question

Started by donkey, April 28, 2011, 08:56:19 PM

Previous topic - Next topic

Ramon Sala

 Edgard,

Great! Congratulations!

Ramon
Greetings from Catalonia

donkey

Quote from: dancho on April 30, 2011, 09:16:57 AM
@donkey
from your code :

.NEXTSECTION
invoke lstrcmpi,esi,".idata"
test eax,eax
jnz >.NOTOURS
mov eax,[esi+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,edi
ret

.NOTOURS
add esi,SIZEOF IMAGE_SECTION_HEADER
dec ebx
jnz .NEXTSECTION


why do you presume that section name will be '.idata' ?
in fasm I can name it what ever I want...
shoudn't be better to check DataDirectory array in IMAGE_OPTIONAL_HEADER for import table address ?



It is for GoAsm, the import directory entry is always called .idata. I did try to get the RVA from the IMAGE_DATA_DIRECTORY structure and use that but the value I was getting was wrong. For example:

// EBX holds the address of the IMAGE_OPTIONAL_HEADER
mov eax,ebx
add eax, 104 // import directory
mov eax,[eax+IMAGE_DATA_DIRECTORY.VirtualAddress]
add eax,[hInst]


The result is 0x00409188 while the address I'm looking for is 0x00409000. The following is a dump of the IMAGE_DATA_DIRECTORY.VirtualAddress entries in my test executable. None of them are particularly useful (Import address table is correct however I don't need that) though I could round the Import Table entry down to the nearest page boundary to get the proper result searching for idata gives it directly.

Export table = 0x00400000
Import table = 0x00409188
Resource table = 0x00407000
Exception table = 0x00400000
Certificate table = 0x00400000
Base relocation table = 0x00400000
Debugging information = 0x00408000
Architecture-specific data = 0x00400000
Global pointer register = 0x00400000
Thread local storage table = 0x00400000
Load configuration table = 0x00400000
Bound import table = 0x00400000)
Import address table = 0x00409278
Delay import descriptor = 0x00400000
The CLR header = 0x00400000
Reserved = 0x00400000
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

This appears to work, it assumes that the section table entries are in reverse order to the data directory entries, which appears to be the case. Since the export table can exist it is checked and the routine adjusts which section header it reads:

GetJumpTable FRAME hInst
uses esi,edi,ebx

// Get the IMAGE_NT_HEADERS structure
mov ebx,[hInst]
mov edi,ebx
add ebx,[ebx+IMAGE_DOS_HEADER.e_lfanew]

// Get the offset of the first IMAGE_DATA_DIRECTORY entry
mov esi,[ebx+IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader]
and esi,0xFFFF
add esi,ebx
// jump past the IMAGE_FILE_HEADER and signature ("PE\0\0")
add esi, SIZEOF IMAGE_FILE_HEADER + 4

mov eax,[ebx+IMAGE_NT_HEADERS.OptionalHeader.DataDirectory]
movzx ebx,W[ebx+IMAGE_NT_HEADERS.FileHeader.NumberOfSections]
dec ebx
test eax,eax
jz >
// Take the second last entry if an export table exists
// otherwise take the last entry
dec ebx
:

mov eax,SIZEOF IMAGE_SECTION_HEADER
mul ebx
add eax,esi
mov eax,[eax+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,edi
ret
endf


I'm just not sure about the ordering of the IMAGE_SECTION_HEADER structures, are they always in the same order ?
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dancho

@donkey
could you compile and attach some small exe for further testing,
atm Im programming small tool for processing exe files and
I would really like to see what number would I get...

thx

donkey

Hi dancho,

This routine can't really be used for other processes since it involves reading the process memory and that can be sticky even using ReadProcessMemory. I can try to work something out but that is outside of the scope of my current project which needs to get the information from itself. Not sure if I can get to it this weekend though.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dancho

@donkey
no problem at all,I understand...
btw

Quote
I'm just not sure about the ordering of the IMAGE_SECTION_HEADER structures, are they always in the same order ?

as far as I can say from my tests it is always from low to high VirtualAddress values...
something like this ( for exe type )
.bss
.code
.rdata
.data
.idata
.rsrc
.reloc

donkey

Hi dancho,

That's what I was afraid of, there is no entry that I can find that will match the section header entry to the data directory entry. I'll have to keep digging...
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dancho

@donkey
this is copy/paste from the first resource I read about pe (  LUEVELSMEYER's description about PE file format ) and I think
that nicely fits here  :bg

There is one section header for each section, and each data directory
will point to one of the sections (several data directories may point to
the same section, and there may be sections without data directory
pointing to them
).

donkey

Hi dancho,

This should find the table no matter what the ordering is or name. This routine keeps getting smaller, I like it :)

GetJumpTable FRAME hInst

mov edx,[hInst]
add edx,[edx+IMAGE_DOS_HEADER.e_lfanew]

lea eax,[edx + IMAGE_NT_HEADERS.OptionalHeader + 104]
invoke ImageRvaToSection,edx,0,[eax+IMAGE_DATA_DIRECTORY.VirtualAddress]

mov eax,[eax+IMAGE_SECTION_HEADER.VirtualAddress]
add eax, [hInst]
ret
ENDF


In GoAsm it returns the correct entry.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dancho

@donkey
nice one,dbghelp functions FTW,
I should really study more Debugging and Error Handling section of sdk ... :U



donkey

Well, lots of work for nothing I guess, the SymAddSymbol function returns no error but the new symbols don't appear in the symbol table when I dump it. The docs say the function adds a virtual symbol to the symbol table but I can't figure out how to access it. I was hoping to add API references directly to the symbol table in GoAsm (MASM already does this) but I've pretty much given up on the idea. Did learn quite a bit along the way though.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave


donkey

I guess I should explain a little more clearly what I was experimenting with the jump table for. This is the disassembly using WinDbg of a GoAsm jump table:

00409000 ff2578924000            jmp     dword ptr [MainModule!LastSymbol+0x2e34 (00409278)]
00409006 ff257c924000            jmp     dword ptr [MainModule!LastSymbol+0x2e38 (0040927c)]
0040900c ff2580924000            jmp     dword ptr [MainModule!LastSymbol+0x2e3c (00409280)]
00409012 ff2584924000            jmp     dword ptr [MainModule!LastSymbol+0x2e40 (00409284)]
00409018 ff2588924000            jmp     dword ptr [MainModule!LastSymbol+0x2e44 (00409288)]
0040901e ff258c924000            jmp     dword ptr [MainModule!LastSymbol+0x2e48 (0040928c)]


GoAsm does not assign symbols to the addresses, for example 0x00409278 is the offset of the fixed up address of GetModuleHandleA, 0x00409000 is the address of the entry in the jump table that is called when you use CALL GetModuleHandleA. In MASM the symbol GetModuleHandleA is in the symbol table with the address 0x00409000 and the symbol _imp_GetModuleHandleA is added with the address 0x00409278. In this way WinDbg can properly display the call instruction as CALL GetModuleHandleA. In GoAsm it will display something like call MainModule!LastSymbol+0x2bbc (00409000) which is a bit tough to read. I was trying to add the symbol GetModuleHandleA with an address of 0x00409000 in order to make the output more readable. Unfortunately it doesn't work as WinDbg's IDebugControl interface seems to ignore the virtual symbols I add. Truly unfortunate since I had high hopes for this method, I might end up being forced to write a complete disassembler in order to get it looking the way I want or use Beatrix's BeaEngine, which I've found to be exceptional and does both 32 and 64 bit.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dedndave

maybe you can get the info from the PE file (i.e. an "unloaded" copy of it)
easy enough to get its' path and name   :P
you cannot (easily) write to the file while it's being executed, but should be able to read it

donkey

Hey Dave,

I can get all of the information I need its just that I can't pass it on the the debugger (WinDbg). WinDbg doesn't seem to have the facility to add virtual symbols and though DbgHelp can do that, WinDbg ignores them. BeaEngine is probably the route I'm going to take, it has a lot of flexibility and though it doesn't handle labels, I can always sub them in from the tables.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable