Log in

View Full Version : Is there a generic method to determine generic type and number of parameters passed?


BanMe
July 15th, 2010, 18:19
Ie how could I determine the number of parameters a function uses at runtime(I know I have to load as data file or a mapped file and directly read the functions bytes is there another way?),any thoughts on this in a programming sense?

_genuine
July 16th, 2010, 02:29
Hmm, as far as parameter lists go, i would imagine one would need to understand how to stack is setup for a particular function, as you know when a function returns, depending on its calling convention the stack will be cleaned using a combination of push's and ADD's. I would write a alittle test case if i were you, write a few functions taking and returning diferent data types, then pop it in IDA then a debugger, and try and make sense of the logic IDA uses, I'm alittle rusty so i don't want to say too much out of fear of providing false information

Edit:
Yes, just as arc said, it's alot more difficult to determine these things because of the few calling conventions and different programming techniques, You'd need a very mature disassembling engine for such a task. I wrote a small test case and then all the questions arose

Code:

#include <iostream>

using namespace std;

int myfunc( int a, int b, int c )
{
return ( a+b+c );
}
double myfunc2( double a, double b )
{
if( b != 0 )
{
return ( a/b );
}
else
return ( 0.0f );
}
int main()
{
//Call func 1
int i = myfunc( 3,4,6 );
double j = ( 24.5, 5.5 );
return 0;
}


cl file.cpp /EHsc /MT

arc_
July 16th, 2010, 02:37
The number of parameters of a compiled function is quite hard to determine. For example, is it cdecl, stdcall, or thiscall (extra parameter in ecx)? Or even fastcall (arguments in registers instead of on the stack)? Even a highly advanced disassembler like IDA can still sometimes get it wrong.

As for the type of parameters, well, that's even harder and may in fact be impossible to do automatically. Imagine a function that just passes its 32-bit parameters on to another function, maybe even a virtual function. Are those parameters ints? floats? pointers? Who knows...

BanMe
July 16th, 2010, 12:42
Quote:

Yes, just as arc said, it's alot more difficult to determine these things because of the few calling conventions and different programming techniques, You'd need a very mature disassembling engine for such a task.


That is true, I do have to know alot of about various calling methods and be able to check and double check if a functions meats the criteria of 'known' calling types, if these know types fail to recognize something then it should be noted and xref'd back to calle to see if that has a recognizable 'conventional behavior' about it...

That being said..genuine took a step without me, and looked at wikipedia..

So I guess I'll use it to with a small update.. to use both functions..

Code:

int i = myfunc( 3,4,6 );
double j = myfunc2( 24.5, 5.5 );
return 0;


So this is a somewhat good example, it needs a bit more but this is a starting point

After compiling this with VC++ 2k5 on xp sp3(x86)..

code for myfunc...

Code:

004111E0 > 55 PUSH EBP
004111E1 8BEC MOV EBP,ESP
004111E3 81EC C0000000 SUB ESP,0C0
004111E9 53 PUSH EBX
004111EA 56 PUSH ESI
004111EB 57 PUSH EDI
004111EC 8DBD 40FFFFFF LEA EDI,DWORD PTR SS:[EBP-C0]
004111F2 B9 30000000 MOV ECX,30
004111F7 B8 CCCCCCCC MOV EAX,CCCCCCCC
004111FC F3:AB REP STOS DWORD PTR ES:[EDI]
004111FE 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]//param 1 to eax
00411201 0345 0C ADD EAX,DWORD PTR SS:[EBP+C]//add param 2 to eax
00411204 0345 10 ADD EAX,DWORD PTR SS:[EBP+10]//add param 3 to eax...
00411207 5F POP EDI
00411208 5E POP ESI
00411209 5B POP EBX
0041120A 8BE5 MOV ESP,EBP
0041120C 5D POP EBP
0041120D C3 RETN


This one is relatively easy to analyze visually to see 3 params, so that recognition falls under recognizable EBP code patters and the code would need to know those patters..this one has 3.... The Next Fuction is not so easily decipherable visually unless you know asm..

code for myfunc2
Code:

00411220 > 55 PUSH EBP
00411221 8BEC MOV EBP,ESP
00411223 81EC C0000000 SUB ESP,0C0
00411229 53 PUSH EBX
0041122A 56 PUSH ESI
0041122B 57 PUSH EDI
0041122C 8DBD 40FFFFFF LEA EDI,DWORD PTR SS:[EBP-C0]
00411232 B9 30000000 MOV ECX,30
00411237 B8 CCCCCCCC MOV EAX,CCCCCCCC
0041123C F3:AB REP STOS DWORD PTR ES:[EDI]
0041123E D9EE FLDZ
00411240 DC5D 10 FCOMP QWORD PTR SS:[EBP+10]//compare b 0
00411243 DFE0 FSTSW AX
00411245 F6C4 44 TEST AH,44
00411248 7B 0A JPO SHORT Test01.00411254//jmp to return 0
0041124A DD45 08 FLD QWORD PTR SS:[EBP+8]//parameter 1
0041124D DC75 10 FDIV QWORD PTR SS:[EBP+10]//div par1 by par2..
00411250 EB 04 JMP SHORT Test01.00411256
00411252 EB 02 JMP SHORT Test01.00411256
00411254 D9EE FLDZ
00411256 5F POP EDI
00411257 5E POP ESI
00411258 5B POP EBX
00411259 8BE5 MOV ESP,EBP
0041125B 5D POP EBP
0041125C C3 RETN

a funny double jmp appears ? minus the 'else'...

So this is still based on EBP patters, this also includes the FLD and FDIV EBP instructions.. the more patters I see the more I think to look at the callee, maybe this could make it easier, then checking various conditions all at once if double positives occur those cases need further handling....

I ended up with compiled code that looked like this for main..
I added visual analysis comments of what patters I see and would look for..
Code:

00411270 > 55 PUSH EBP
00411271 8BEC MOV EBP,ESP
00411273 81EC DC000000 SUB ESP,0DC
00411279 53 PUSH EBX
0041127A 56 PUSH ESI
0041127B 57 PUSH EDI
0041127C 8DBD 24FFFFFF LEA EDI,DWORD PTR SS:[EBP-DC]
00411282 B9 37000000 MOV ECX,37
00411287 B8 CCCCCCCC MOV EAX,CCCCCCCC
0041128C F3:AB REP STOS DWORD PTR ES:[EDI]
0041128E 6A 06 PUSH 6
00411290 6A 04 PUSH 4
00411292 6A 03 PUSH 3//3numeric pushes o0
00411294 E8 07FEFFFF CALL Test01.004110A0// then call myfunc
00411299 83C4 0C ADD ESP,0C//oh a verifier 0xc/0x4 = 0x3
0041129C 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
0041129F 83EC 08 SUB ESP,8//sub esp qword
004112A2 DD05 00414100FLD QWORD PTR DS:[__real@401600000000000>
004112A8 DD1C24 FSTP QWORD PTR SS:[ESP]//fill esp
004112AB 83EC 08 SUB ESP,8//sub another qword
004112AE DD05 F0404100 FLD QWORD PTR DS:[__real@403880000000000>
004112B4 DD1C24 FSTP QWORD PTR SS:[ESP]//fill esp
004112B7 E8 ADFDFFFF CALL Test01.00411069//myfunc2
004112BC 83C4 10 ADD ESP,10//a verifier 10/8 = 2
004112BF DD5D E8 FSTP QWORD PTR SS:[EBP-18]
004112C2 33C0 XOR EAX,EAX
004112C4 5F POP EDI
004112C5 5E POP ESI
004112C6 5B POP EBX
004112C7 81C4 DC000000 ADD ESP,0DC
004112CD 3BEC CMP EBP,ESP
004112CF E8 D6FDFFFF CALL Test01.004110AA
004112D4 8BE5 MOV ESP,EBP
004112D6 5D POP EBP
004112D7 C3 RETN


So to check function for cdecl you check the callee after call for cleanup of stack then you 'might' be able to 'guess at' the size and number based on basic mathmatic computations....

stdcall..is next

BanMe
July 16th, 2010, 13:32
so with slight modification of code we end up with stdcall

Code:

int __stdcall myfunc( int a, int b, int c )
double __stdcall myfunc2( double a, double b )


so stdcall myfunc
Code:

004111E0 > 55 PUSH EBP
004111E1 8BEC MOV EBP,ESP
004111E3 81EC C0000000 SUB ESP,0C0
004111E9 53 PUSH EBX
004111EA 56 PUSH ESI
004111EB 57 PUSH EDI
004111EC 8DBD 40FFFFFF LEA EDI,DWORD PTR SS:[EBP-C0]
004111F2 B9 30000000 MOV ECX,30
004111F7 B8 CCCCCCCC MOV EAX,CCCCCCCC
004111FC F3:AB REP STOS DWORD PTR ES:[EDI]
004111FE 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]//same as before
00411201 0345 0C ADD EAX,DWORD PTR SS:[EBP+C]
00411204 0345 10 ADD EAX,DWORD PTR SS:[EBP+10]
00411207 5F POP EDI
00411208 5E POP ESI
00411209 5B POP EBX
0041120A 8BE5 MOV ESP,EBP
0041120C 5D POP EBP
0041120D C2 0C00 RETN 0C//this is different


stdcall code for myfunc2
Code:

00411220 > 55 PUSH EBP
00411221 8BEC MOV EBP,ESP
00411223 81EC C0000000 SUB ESP,0C0
00411229 53 PUSH EBX
0041122A 56 PUSH ESI
0041122B 57 PUSH EDI
0041122C 8DBD 40FFFFFF LEA EDI,DWORD PTR SS:[EBP-C0]
00411232 B9 30000000 MOV ECX,30
00411237 B8 CCCCCCCC MOV EAX,CCCCCCCC
0041123C F3:AB REP STOS DWORD PTR ES:[EDI]
0041123E D9EE FLDZ
00411240 DC5D 10 FCOMP QWORD PTR SS:[EBP+10]
00411243 DFE0 FSTSW AX
00411245 F6C4 44 TEST AH,44
00411248 7B 08 JPO SHORT Test01.00411252
0041124A DD45 08 FLD QWORD PTR SS:[EBP+8]
0041124D DC75 10 FDIV QWORD PTR SS:[EBP+10]
00411250 EB 02 JMP SHORT Test01.00411254
00411252 D9EE FLDZ
00411254 5F POP EDI
00411255 5E POP ESI
00411256 5B POP EBX
00411257 8BE5 MOV ESP,EBP
00411259 5D POP EBP
0041125A C2 1000 RETN 10

This is the same as before and the same difference as noted above(including noted fix from prev.).. So will the callee hold any thing useful for us lets check

Code:

00411270 > 55 PUSH EBP
00411271 8BEC MOV EBP,ESP
00411273 81EC DC000000 SUB ESP,0DC
00411279 53 PUSH EBX
0041127A 56 PUSH ESI
0041127B 57 PUSH EDI
0041127C 8DBD 24FFFFFF LEA EDI,DWORD PTR SS:[EBP-DC]
00411282 B9 37000000 MOV ECX,37
00411287 B8 CCCCCCCC MOV EAX,CCCCCCCC
0041128C F3:AB REP STOS DWORD PTR ES:[EDI]
0041128E 6A 06 PUSH 6//same pushes as before
00411290 6A 04 PUSH 4
00411292 6A 03 PUSH 3
00411294 E8 07FEFFFF CALL Test01.004110A0
//no cleaning of stack this is not (cdecl) check for stdcall next..
00411299 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX
0041129C 83EC 08 SUB ESP,8//same
0041129F DD05 00414100 FLD QWORD PTR DS:[__real@401600000000000>
004112A5 DD1C24 FSTP QWORD PTR SS:[ESP]
004112A8 83EC 08 SUB ESP,8//same
004112AB DD05 F0404100 FLD QWORD PTR DS:[__real@403880000000000>
004112B1 DD1C24 FSTP QWORD PTR SS:[ESP]
004112B4 E8 B0FDFFFF CALL Test01.00411069
//no cleaning, check stdcall next
004112B9 DD5D E8 FSTP QWORD PTR SS:[EBP-18]
004112BC 33C0 XOR EAX,EAX
004112BE 5F POP EDI
004112BF 5E POP ESI
004112C0 5B POP EBX
004112C1 81C4 DC000000 ADD ESP,0DC
004112C7 3BEC CMP EBP,ESP
004112C9 E8 DCFDFFFF CALL Test01.004110AA
004112CE 8BE5 MOV ESP,EBP
004112D0 5D POP EBP
004112D1 C3 RETN


So analyzing stdcall relies on checking for stack cleanup after call for both (cdecl and stdcall)if it there it might be cdecl if not it might be stdcall. to do verification you keep track of params while at callee and then div param size by retn 0xn to get num of params.

fastcall

another slight mod and we get 'fastcall'..

myfunc fast call...
Code:

004111E0 > 55 PUSH EBP
004111E1 8BEC MOV EBP,ESP
004111E3 81EC D8000000 SUB ESP,0D8
004111E9 53 PUSH EBX
004111EA 56 PUSH ESI
004111EB 57 PUSH EDI
004111EC 51 PUSH ECX
004111ED 8DBD 28FFFFFF LEA EDI,DWORD PTR SS:[EBP-D8]
004111F3 B9 36000000 MOV ECX,36
004111F8 B8 CCCCCCCC MOV EAX,CCCCCCCC
004111FD F3:AB REP STOS DWORD PTR ES:[EDI]
004111FF 59 POP ECX
00411200 8955 EC MOV DWORD PTR SS:[EBP-14],EDX
00411203 894D F8 MOV DWORD PTR SS:[EBP-8],ECX
00411206 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
00411209 0345 EC ADD EAX,DWORD PTR SS:[EBP-14]
0041120C 0345 08 ADD EAX,DWORD PTR SS:[EBP+8]
0041120F 5F POP EDI
00411210 5E POP ESI
00411211 5B POP EBX
00411212 8BE5 MOV ESP,EBP
00411214 5D POP EBP
00411215 C2 0400 RETN 4


I'm not to sure what to do in this case.. :/

the funny part is that myfunc2 doesnt really change from the stdcall convention..
Code:

00411230 > 55 PUSH EBP
00411231 8BEC MOV EBP,ESP
00411233 81EC C0000000 SUB ESP,0C0
00411239 53 PUSH EBX
0041123A 56 PUSH ESI
0041123B 57 PUSH EDI
0041123C 51 PUSH ECX
0041123D 8DBD 40FFFFFF LEA EDI,DWORD PTR SS:[EBP-C0]
00411243 B9 30000000 MOV ECX,30
00411248 B8 CCCCCCCC MOV EAX,CCCCCCCC
0041124D F3:AB REP STOS DWORD PTR ES:[EDI]
0041124F 59 POP ECX
00411250 D9EE FLDZ
00411252 DC5D 10 FCOMP QWORD PTR SS:[EBP+10]
00411255 DFE0 FSTSW AX
00411257 F6C4 44 TEST AH,44
0041125A 7B 08 JPO SHORT Test01.00411264
0041125C DD45 08 FLD QWORD PTR SS:[EBP+8]
0041125F DC75 10 FDIV QWORD PTR SS:[EBP+10]
00411262 EB 02 JMP SHORT Test01.00411266
00411264 D9EE FLDZ
00411266 5F POP EDI
00411267 5E POP ESI
00411268 5B POP EBX
00411269 8BE5 MOV ESP,EBP
0041126B 5D POP EBP
0041126C C2 1000 RETN 10


But Main does change.. a little..and provides a little insight..
Code:

00411280 > 55 PUSH EBP
00411281 8BEC MOV EBP,ESP
00411283 81EC DC000000 SUB ESP,0DC
00411289 53 PUSH EBX
0041128A 56 PUSH ESI
0041128B 57 PUSH EDI
0041128C 51 PUSH ECX
0041128D 8DBD 24FFFFFF LEA EDI,DWORD PTR SS:[EBP-DC]
00411293 B9 37000000 MOV ECX,37
00411298 B8 CCCCCCCC MOV EAX,CCCCCCCC
0041129D F3:AB REP STOS DWORD PTR ES:[EDI]
0041129F 59 POP ECX
004112A0 6A 06 PUSH 6//1 stack push
004112A2 BA 04000000 MOV EDX,4//1 in edx
004112A7 B9 03000000 MOV ECX,3//1 in ecx
004112AC E8 DBFDFFFF CALL Test01.0041108C
004112B1 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX//return in eax...
004112B4 83EC 08 SUB ESP,8
004112B7 DD05 00414100 FLD QWORD PTR DS:[__real@401600000000000>
004112BD DD1C24 FSTP QWORD PTR SS:[ESP]
004112C0 83EC 08 SUB ESP,8
004112C3 DD05 F0404100 FLD QWORD PTR DS:[__real@403880000000000>
004112C9 DD1C24 FSTP QWORD PTR SS:[ESP]
004112CC E8 A7FDFFFF CALL Test01.00411078
004112D1 DD5D E8 FSTP QWORD PTR SS:[EBP-18]
004112D4 33C0 XOR EAX,EAX
004112D6 5F POP EDI
004112D7 5E POP ESI
004112D8 5B POP EBX
004112D9 81C4 DC000000 ADD ESP,0DC
004112DF 3BEC CMP EBP,ESP
004112E1 E8 C9FDFFFF CALL Test01.004110AF
004112E6 8BE5 MOV ESP,EBP
004112E8 5D POP EBP
004112E9 C3 RETN


not a very reliable method for identifing __fastcall but its a start I guess...:[

BanMe
July 16th, 2010, 14:16
Quote:

As for the type of parameters, well, that's even harder and may in fact be impossible to do automatically. Imagine a function that just passes its 32-bit parameters on to another function, maybe even a virtual function. Are those parameters ints? floats? pointers? Who knows...


well the key isnt to know the exact type, just the type shown through thorough analysis.

But this does bring up a valid point..If a pointer is passed to a function as a output mechanism how would one determine its 'general size' staticly. we can discuss various methods but definitly, im going to try the simple ones first

regards BanMe

BanMe
July 19th, 2010, 00:35
Im still open to other ideas,I mean I know I have to do as thorough of a disassembly job as possible(staticly),did oleh self code known dll functions into olly, I dont think that applies to 'unknown' dll's... Starts looking at olly with olly..Also is there 'any' other code out there that does enumerate parameters in assembled code and attempts to determine size?

regards BanMe

disavowed
July 19th, 2010, 00:58
Quote:
[Originally Posted by BanMe;87319]did oleh self code known dll functions into olly


Yes, he did. There's a precompiled list of all known DLL functions in OllyDbg's resource section.

BanMe
July 19th, 2010, 09:59
Thank you clarifying that for 'known' dll's, but how is it done with unknown dll's is what I meant. Thats the section of olly I am looking for, hopefully it will shed some light on this.. :d

regards BanMe

BanMe
July 22nd, 2010, 12:30
Boomerang, is its name and its got some damn interesting source code.. sadly it all uses classes but the techniques are clearly defined and easy to understand.

http://boomerang.sourceforge.net/

regards BanMe

Kayaker
July 23rd, 2010, 15:06
Maybe have a look at the algo here

http://burrowscode.wordpress.com/2010/02/22/exporting-non-exported-functions-in-windows-pes-part-3-of-3/

Quote:
...an algorithm to determine exactly the number of variables that a function expects to be passed to it...


Kayaker

BanMe
July 23rd, 2010, 21:49
Great... Hit me with that small and simple python function after almost getting done.. no matter I still like the micro length disassembler in boomerang..although I'm not to great at classes, I guess I get a crash course at removing QT4 support from the code..any pointers on this regard?

Blagodarenko
August 19th, 2010, 01:21
I've been solved this problem not so far. All I found is:
1. There is no meens to recover origianal prototype, becouse __usercall convention exitsts etc.
2. We can build usefull prototype that can be used to call common module function.

I have wrote in my blog(http://artem.ufoctf.ru/?p=247&lang=en) about it.After that I have developed tool that:

1. Generate functions prototypes.
2. Make module SDK ( prototypes and addresses )
3. Load test that using SDK into analyzed process.

The tool is availiable here: http://ufoctf.ru/ufoblog/en/maiway-2/.

I still have some trubles with trackimg parameters in stack.

Blagodarenko
August 19th, 2010, 01:26
__fastcall and __usercall is the most difficalt to determinate. Some ideas about parameters that passed throuth registers: http://artem.ufoctf.ru/?p=236&lang=en.

BanMe
August 19th, 2010, 23:21
Wonderful to see a nice tool like that and thanks for the pointers to fast call..
kayakers posting is going to be indeed influential in dynamicly analyzing things and combined with bit more time this is going to work. And I mean seriously if I cant do it the 'nice' analytical way',can't I just cause a 'segment fault' like memalyze and gather information accordingly ..I bet I could emulate the driver to, but I dont have all the KD knowledge for that yet.There are still other ways and I will find them..

sabbato753
August 20th, 2010, 07:57
Quote:
[Originally Posted by Blagodarenko;87562]I've been solved this problem not so far. All I found is:
1. There is no meens to recover origianal prototype, becouse __usercall convention exitsts etc.
2. We can build usefull prototype that can be used to call common module function.

I have wrote in my blog(http://artem.ufoctf.ru/?p=247&lang=en) about it.After that I have developed tool that:

1. Generate functions prototypes.
2. Make module SDK ( prototypes and addresses )
3. Load test that using SDK into analyzed process.

The tool is availiable here: http://ufoctf.ru/ufoblog/en/maiway-2/.

I still have some trubles with trackimg parameters in stack.


I just had to drop a "thanks" in this thread as well, Blagodarenko. I'm reading your blog now, and am quite impressed. Thanks for more tools, it's guys like you (and Ricardo and kayaker and several others) that inspire those of us who are new to learn more. Tools and tutorials help us so much to hopefully contribute to the scene one day ourselves.

Sorry, I know that "thanks" posts aren't really within forum rules, but since you're new to posting here, maybe they'll let it slide...

Woodmann
August 20th, 2010, 19:26
Hey,

"Thanks" are absolutely acceptable.

Woodmann

Indy
August 21st, 2010, 10:34
http://www.wasm.ru/forum/viewtopic.php?id=38339 ("http://www.wasm.ru/forum/viewtopic.php?id=38339")

BanMe
August 21st, 2010, 19:55
That's what I like to see.damn I love asm...compact clean and right to the point...

Indy
August 22nd, 2010, 02:31
BanMe
The engine has a size of less than 3K. You can not solve this problem more optimal way
2335

BanMe
August 22nd, 2010, 10:54
Who says it has to be more 'optimal' way, you see that is where you captured it wrong...Someone out there is lookin to one up you,but I am only after the understanding of the concepts involved and how 'various' people attack the problems. This allows me to have ideas about how to attack 'current problems' and I always store the knowledge away for future problems. But to be clear a more 'Optimal way' could be something as simple as changing a few asm instructions to better optimize the code,or it could be using the code from a position of greater flexibility..But needless to say you are right otherwise..

Indy
August 22nd, 2010, 18:10
BanMe
Quote:
But to be clear a more 'Optimal way' could be something as simple as changing a few asm instructions to better optimize the code,or it could be using the code from a position of greater flexibility..

Optimal size, structure(mutation independent) and flexibility(disclosure of branching).

Suggest a better solution.

BanMe
August 24th, 2010, 00:10
I cannot do better then what you have done, I agree.But that still leaves the question of what are the 'types' passed into said function..Maybe if you and Blagodarenko molded something together this would almost suit my needs ..But seeing how that 'may' never happen,I will continue on in with this information (still being analyzed (btw)), thanks for that lil bit.

regards BanMe

BanMe
August 24th, 2010, 04:40
His code is most interesting, it makes me read the manuel and does some things I've not seen before in asm(most notably the __imp_ directive in the code I see, but I dont quite grasp the dump in source though... It's just not to easy to understand all of it yet..though im working on it :d

might there be a dll version of this.. :d

Maximus
August 24th, 2010, 05:34
hmmm i do not understand one thing: the gp engine is just to perform analysis of __stdcall/__pascal/__cdecl calling conventions, or is it capable of identifying __fastcall/__msfastcall calling conventions as well?

The first is not very interesting, the second is *very* interesting, at least to me.

Could you explain your approach to the latter problem, if the engine can be used for register-passing converntions?

Thanks,
Maximus

Indy
August 24th, 2010, 11:39
Quote:
the gp engine is just to perform analysis of __stdcall/__pascal/__cdecl calling conventions, or is it capable of identifying __fastcall/__msfastcall calling conventions as well?

"GP" engine is the base engine(GCBE) from permutator creates a graph and tracing it:
http://files.virustech.org/indy/Code/XcptGp/ ("http://files.virustech.org/indy/Code/XcptGp/")
http://files.virustech.org/indy/Code/GCBE/ ("http://files.virustech.org/indy/Code/GCBE/")
The code determines the number of function parameters, as you see it is a trivial search instructions RetX in the graph:
Code:
; +
; o !GP_PARSE_SEPARATE
;
GpTraceCallback:
%GET_CURRENT_GRAPH_ENTRY
GpTraceCallbackInternal proc uses ebx esi edi GpEntry:PVOID, ArgsCount:PVOID
mov esi,GpEntry
mov ebx,ArgsCount
test dword ptr [esi + EhEntryType],TYPE_MASK ; !HEADER_TYPE_LINE
jne Exit
cmp dword ptr [ebx],-1
mov edi,BLOCK_HEADER._Size[esi]
mov esi,BLOCK_HEADER.Address[esi]
jne Exit
Ip:
invoke QueryPrefixLength, Esi
movzx ecx,byte ptr [esi + eax]
cmp cl,0C3H ; retn
je ip_ret
cmp cl,0CBH ; retf
je ip_ret
cmp cl,0C2H ; retn x
je ip_ret_x
cmp cl,0CAh ; retf x
je ip_ret_x
Call VirXasm32
test eax,eax
jz Exit
add esi,eax
sub edi,eax
ja Ip
Exit:
ret
ip_ret:
xor eax,eax
jmp Store
ip_ret_x:
movzx eax,word ptr [esi + eax + 1]
Store:
shr eax,2
mov dword ptr [ebx],eax
jmp Exit
GpTraceCallbackInternal endp

GpQueryRoutineArgsNumber proc GpBase:PVOID, ArgsCount:PULONG
mov eax,ArgsCount
mov dword ptr [eax],-1
push eax
%GET_GRAPH_ENTRY GpTraceCallback
push eax
push GpBase
Call GpTrace
ret
GpQueryRoutineArgsNumber endp

Some projects in this sample can solve quite complex problems, such as the search procedure begins, or search for the caller in the chain of stack frames.
Quote:
might there be a dll version of this..

This code is designed in a special way. Code mutable and hence does not depend on base and not using relocs(fixups). He also all sufficient, so it makes no sense to put this code in the module.

mak
August 24th, 2010, 13:45
Indy

I don't like C++ language as an assembler, but such code would be more universal if it was in C++

P.S. You have already switched to abroad