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

dedndave

here's another one where they padded between Register and Scope   :lol
Public Type SYMBOL_INFO
 SizeOfStruct As Long
 TypeIndex As Long
 Reserved(1 To 2) As Currency
 Index As Long
 size As Long
 ModBase As Currency
 Flags As Long
 Value As Currency
 Address As Currency
 Register As Long
 padding As Long
 Scope As Long
 Tag As Long
 NameLen As Long
 MaxNameLen As Long
End Type


http://www.codeguru.com/forum/showthread.php?t=303118

dedndave

and another that reports a discrepancy between ansi and unicode docs

http://jpassing.com/2008/02/19/glitch-in-documentation-of-symbol_info/

this structure has all kinds of problems - lol

donkey

Hi Dave,

The correct structure, properly aligned is:

SYMBOL_INFO STRUCT
SizeOfStruct DD
TypeIndex DD
Reserved DQ 2 DUP
Index DD
Size DD
ModBase DQ
Flags DD
Reserved2 DD
Value DQ
Address DQ
Register DD
Scope DD
Tag DD
NameLen DD
MaxNameLen DD
Name DB 4 DUP
ENDS


The example code at MSDN shows that the SizeOfStruct member is filled with SIZEOF SYMBOL_INFO, allowing for the padding of Name to 4 bytes that is 88 bytes:

All members that are verifiable (SizeOfStruct, ModBase, Flags, Address, Tag, NameLen, MaxNameLen and Name) are correct with this version of the structure. It will be corrected in the GoAsm header files in the next upload on Sunday.

Edgar
"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 is the final version of FindSymbol as it will appear in my application if anyone is interested. It uses the SYMBOL_INFO above.

DATA SECTION
SymName DB 256 DUP (?)
ModName DB 256 DUP (?)
Displ DD ?

CODE SECTION
push [GetWindowLongA]
pop eax
add eax,5
invoke FindSymbol,-1,eax,offset SymName,offset ModName,offset Displ

FindSymbol FRAME hProcess, pAddress, pszSymbol, pszModule, pdwDisplacment
LOCAL pSymInfo:D
LOCAL SymModInfo:IMAGEHLP_MODULE64

invoke CoTaskMemAlloc,SIZEOF SYMBOL_INFO+MAX_SYM_NAME-4
mov [pSymInfo],eax
mov D[eax+SYMBOL_INFO.MaxNameLen],MAX_SYM_NAME
mov D[eax+SYMBOL_INFO.SizeOfStruct],SIZEOF SYMBOL_INFO

// invade process, load all modules
invoke SymInitialize,[hProcess],0, TRUE

invoke SymFromAddr,[hProcess],[pAddress],0,[pdwDisplacment],[pSymInfo]
mov eax,[pSymInfo]
add eax,SYMBOL_INFO.Name
invoke lstrcpy,[pszSymbol],eax

mov D[SymModInfo.SizeOfStruct],SIZEOF IMAGEHLP_MODULE64
invoke SymGetModuleInfo64,[hProcess],[pAddress],0,offset SymModInfo
lea edx,SymModInfo+IMAGEHLP_MODULE64.ModuleName
invoke lstrcpy,[pszModule],edx

// Shut it down
invoke SymCleanup,[hProcess]
invoke CoTaskMemFree,[pSymInfo]

xor eax,eax
RET

ENDF


Output of the above test:

Line 130: SymName = GetWindowLongA
Line 131: ModName = USER32
Line 132: [Displ] = 5 (0x00000005)


Now I have to map this to GoAsm and MASM jump 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

dedndave

Matt Pietrek has written some articles regarding DbgHelp that you may find useful
http://blog.csdn.net/is01sjjj/archive/2007/12/25/1966545.aspx

reading through that article, i see that he has written a demo program with well-commented source
http://www.wheaty.net/
in the downloads section...
http://www.wheaty.net/DbgHelpDemo.zip

i don't know how i got to this one - lol
but, it tells you some of the values of the Register member
http://msdn.microsoft.com/en-au/library/a0fcdkb9%28VS.71%29.aspx

donkey

Thanks Dave,

I occasionally exchange emails with the author of DbgHelp at Microsoft (he has some funny stories about how he managed to get it redistributable), I just don't like to bother him too much with questions that appear to be more about the language I am writing in than functional issues. Good articles and I like Pietrek, he doesn't clog up the works with a lot of useless information, I'll read through them.

The CV_ register members are defined in cvconst.h in my headers.
"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

Ramon Sala

Hi Edgard,

Here is the SIMBOL_INFO struct as defined in the Windows SDK v7.1:

typedef struct _SYMBOL_INFO {
    ULONG       SizeOfStruct;
    ULONG       TypeIndex;        // Type Index of symbol
    ULONG64     Reserved[2];
    ULONG       Index;
    ULONG       Size;
    ULONG64     ModBase;          // Base Address of module comtaining this symbol
    ULONG       Flags;
    ULONG64     Value;            // Value of symbol, ValuePresent should be 1
    ULONG64     Address;          // Address of symbol including base address of module
    ULONG       Register;         // register holding value or pointer to value
    ULONG       Scope;            // scope of the symbol
    ULONG       Tag;              // pdb classification
    ULONG       NameLen;          // Actual length of name
    ULONG       MaxNameLen;
    CHAR        Name[1];          // Name of symbol
} SYMBOL_INFO, *PSYMBOL_INFO;

typedef struct _SYMBOL_INFOW {
    ULONG       SizeOfStruct;
    ULONG       TypeIndex;        // Type Index of symbol
    ULONG64     Reserved[2];
    ULONG       Index;
    ULONG       Size;
    ULONG64     ModBase;          // Base Address of module comtaining this symbol
    ULONG       Flags;
    ULONG64     Value;            // Value of symbol, ValuePresent should be 1
    ULONG64     Address;          // Address of symbol including base address of module
    ULONG       Register;         // register holding value or pointer to value
    ULONG       Scope;            // scope of the symbol
    ULONG       Tag;              // pdb classification
    ULONG       NameLen;          // Actual length of name
    ULONG       MaxNameLen;
    WCHAR       Name[1];          // Name of symbol
} SYMBOL_INFOW, *PSYMBOL_INFOW;


SizeOfStruct
    The size of the structure, in bytes. This member must be set to sizeof(SYMBOL_INFO). Note that the total size of the data is the SizeOfStruct + (MaxNameLen - 1) * sizeof(TCHAR). The reason to subtract one is that the first character in the name is accounted for in the size of the structure.



I hope it can help you.

Ramon
Greetings from Catalonia

donkey

Hi Ramon,

Yes, I have that structure, however using it without the padding for alignment after Flags and without padding Name to 4 bytes will cause it to fail (Value must be aligned to begin on a 8 byte boundary within the structure). Also if you count the bytes, there are 81 bytes allocated in that structure however, all Sym functions that use SYMBOL_INFO will fail if SizeOfStruct is not 88. This was the issue I was having with searching symbols.
"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

drizz

The truth cannot be learned ... it can only be recognized.

Ramon Sala

Greetings from Catalonia

donkey

Hi Ramon,

Yeah it really threw me for a loop as well. Without knowing why I kept getting "Invalid parameter" errors and everything seemed perfect until I saw Michael's test program. Ah well, it will be fixed in the next update of the headers. For now I have the code that walks the jump table and gets the CALL addresses for the entry in the table (the JMP XXXX entry not the actual import table). I haven't done the building of my table yet but hockey is about to start so I'm done for today.

WalkJumpTable FRAME hProcess
uses ebx,edi,esi
LOCAL Displacement:D
LOCAL pSymInfo:D
LOCAL SymModInfo:IMAGEHLP_MODULE64

invoke CoTaskMemAlloc,SIZEOF SYMBOL_INFO+MAX_SYM_NAME-4
mov [pSymInfo],eax
mov D[eax+SYMBOL_INFO.MaxNameLen],MAX_SYM_NAME
mov D[eax+SYMBOL_INFO.SizeOfStruct],SIZEOF SYMBOL_INFO

invoke SymInitialize,[hProcess],0, TRUE

// Trick to get the jump table address - Thanks Jeremy !
jmp >JMPTABLEREL
JUMPTABLETEST: call GetModuleHandle
JMPTABLEREL:
mov ebx,[JUMPTABLETEST+1]
add ebx,offset JMPTABLEREL
and ebx,0xFFFFF000

.NEXTENTRY
mov ax,[ebx]
cmp ax,0x25FF
jne >>.EXIT
mov eax,[ebx+2]
mov eax,[eax]

push eax
invoke SymFromAddr,[hProcess],eax,0,offset Displacement,[pSymInfo]
test eax,eax
pop eax
jz >>.NOSYM
mov esi,[pSymInfo]
add esi,SYMBOL_INFO.Name

mov D[SymModInfo.SizeOfStruct],SIZEOF IMAGEHLP_MODULE64
invoke SymGetModuleInfo64,[hProcess],eax,0,offset SymModInfo
lea edi,SymModInfo+IMAGEHLP_MODULE64.ModuleName

invoke AddSymbolToCallTable,esi,edi,ebx

.NOSYM
add ebx,6
jmp .NEXTENTRY
.EXIT

invoke SymCleanup,[hProcess]
invoke CoTaskMemFree,[pSymInfo]
ret
endf


This will pass the symbol, module and address of the jump table entry address to a function called AddSymbolToCallTable (on the todo list).

Edgar
"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

#26
Although the method to get the address of the jump table works every time, it looks too much like a kludge to me and is not easily portable to other assemblers. Since the section that the jump table is in is .idata, we can find that sections address by parsing from the address of hInstance. This routine will return the address of the jump table in EAX or zero if it was not found. Haven't tried it on MASM yet but I will later this weekend or if someone wants to rewrite it for MASM and try it I'd appreciate knowing whether it works or not.

invoke GetModuleHandle, 0
invoke GetJumpTable,eax

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
add esi, SIZEOF IMAGE_FILE_HEADER + 4

movzx ebx,W[ebx+IMAGE_NT_HEADERS.FileHeader.NumberOfSections]

// ESI now points to an array of IMAGE_SECTION_HEADER structures so walk them
// EBX holds the number of entries in the array

.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

xor eax,eax
ret
ENDF
"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

MichaelW

Quote from: donkey on April 29, 2011, 05:27:34 PM
I'm not quite sure about the output you posted, there are some values that don't make sense to me, for example size of Reserved should be 16 bytes (2 x DQ).

Sorry, I somehow posted the output for some earlier version of the code. I have updated my post. The structure is padded ahead of the Value member to place it at an 8-byte alignment, and padded at the end to make the size a multiple of 8 bytes.
eschew obfuscation

donkey

Quote from: MichaelW on April 30, 2011, 03:07:36 AM
Quote from: donkey on April 29, 2011, 05:27:34 PM
I'm not quite sure about the output you posted, there are some values that don't make sense to me, for example size of Reserved should be 16 bytes (2 x DQ).

Sorry, I somehow posted the output for some earlier version of the code. I have updated my post. The structure is padded ahead of the Value member to place it at an 8-byte alignment, and padded at the end to make the size a multiple of 8 bytes.


Thanks Michael,

That confirms what I thought, that I needed to add 4 bytes of padding between Flags and Value and extend Name to 4 bytes.
"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
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 ?