View Full Version : what registers do WINAPI-CALLs depends on?
if i call an API-function like MessageBoxA, i get the return value in EAX and the stack will be cleaned by an appropriate ret instruction through the api-function.
API functions use __stdcall callingconvention, does this mean, that _always_ only EAX contains valuable informations for the caller, or are sometimes other registers important too?
nikolatesla20
May 3rd, 2004, 09:30
_stdcall means all parameters to a function are pushed on the stack and the function uses ESP / and or EBP for parameter values/referencing, and the return value is in EAX. Other registers are usually saved/restored, in other words, unaffected.
-nt20
dELTA
May 3rd, 2004, 10:16
Here's some other useful registry preservation information for win32 asm coding:
http://board.win32asmcommunity.net/showthread.php?threadid=12679
thx for the hints, but i did not get it to work.
i have written some code, which acts like a stub or proxy.
i try to do this:
- hook GetProcAddress
- any GetProcAddress returns this stubcode, which calls the expected function
the problem is, that it does not work for every function and i dont know why.
and this is the stubcode:
Code:
;save initialreturnaddr in TLS
mov eax, esp
push eax
mov eax, tlsindex
push eax
call TlsSetValue
;remove initialreturnaddr and push new one
add esp, 4
push newret
jmp original ;execute originalcode
;newret:
push eax ;save returnvalue
push signature
call vtrace ;call some displaystuff
add esp, 4 ;remove params
;restore old initialreturnaddr
mov eax, tlsindex
push eax
call TlsGetValue
mov ecx, eax
pop eax ;restore returnval
jmp ecx ;jump to initialreturnaddr
nikolatesla20
May 6th, 2004, 14:14
Quote:
[Originally Posted by 0rp]thx for the hints, but i did not get it to work.
i have written some code, which acts like a stub or proxy.
i try to do this:
- hook GetProcAddress
- any GetProcAddress returns this stubcode, which calls the expected function
the problem is, that it does not work for every function and i dont know why.
and this is the stubcode:
Code:
;save initialreturnaddr in TLS
mov eax, esp
push eax
mov eax, tlsindex
push eax
call TlsSetValue
;remove initialreturnaddr and push new one
add esp, 4
push newret
jmp original ;execute originalcode
;newret:
push eax ;save returnvalue
push signature
call vtrace ;call some displaystuff
add esp, 4 ;remove params
;restore old initialreturnaddr
mov eax, tlsindex
push eax
call TlsGetValue
mov ecx, eax
pop eax ;restore returnval
jmp ecx ;jump to initialreturnaddr
|
You should never do JMP instructions to some unknown address, the reason is JMPS can only go so far depending on the type of jump ! For example, a short jump is only able to go 255 bytes away. ALso, JMP instructions are calcuated by the NEXT BYTE, so you have to actually calcuate them if you are changing them dynamically, you can't just plug in a number. They are way too inflexible for what you need to do here.
A much better and more effective technique that will always work is to do a PUSH , RET combo. For example:
PUSH <address value>
RET
Using this you can go anywhere in the 4Gig memory space without any problems.
Also, you do not need to "save" the return address at the beginning of your routine! All you have to do is push your own return address on the stack (just push the address of where your function is) and do a RET. What I mean is this: The params get pushed. Now, overwrite the part of code that calls GetProcAddress with your own routine address. As long as your routine keeps the stack clean then at the end of the routine all you need to do is another PUSH <address of GetProcAddress> , RET and the parameters will even be still in the right place.
Like so:
If you want your code to run after GetProcAddress is called, then:
PUSH <address of your routine>
PUSH <address of GetProcAddress>
RET
So what happens is you push two return addresses, The RET will pop off and navigate to GetProcAddress. When GetProcAddress gets done, it's RET will pop off an execute your routine. Then you can have another PUSH RET at the end of your routine to return to the orignal code.
If you want your code to run BEFORE GetProcAddress:
PUSH <GetProcAddress>
PUSH <address of your proc>
RET
It's that simple. Just use PUSH , RET combos everywhere and you never have to worry about offsets or anything like that.
-nt20
ok, i replaced the jmps with push/ret, but i get the same result.
some apps work without any problems, other app crash immediately
Quote:
[Originally Posted by nikolatesla20]
Also, you do not need to "save" the return address at the beginning of your routine! All you have to do is push your own return address on the stack (just push the address of where your function is) and do a RET.
|
if i do not replace the initial return addr, the expected api function wouldn't return to my proxy code (the api function would return directly to the caller).
is it possible, that the problems are caused by my registermanipulations (ax, cx) ?
nikolatesla20
May 7th, 2004, 08:51
Yes, whenever I create a hook routine I always do a pushad/popad combo in my routine, so I don't have to worry about screwing the registers.
Do a pushad as the first command (after you do a mov ebp, esp - otherwise you will have a harder time getting the params. Use ebp to get to params as usual) like so:
push ebp
mov ebp, esp
pushad
<your code - use ebp+XX to get to params. First param ebp+08>
popad
leave (same as mov esp, ebp - pop ebp)
push <return address>
ret
This is the format I always use to make my hook routines 100% safe and easy to hook, cause no offset calculations required, unless you are calling an API yourself too, then of course you have to find its address, etc. But this will keep your regs. safe.
-nt20
the stubcode is now:
Code:
mov ecx, [esp]
mov tlsval, ecx //__declspec(thread)
add esp, 4
push newret
push original
ret
//newret:
mov ecx, tlsval
push ecx
ret
only ECX is modified, but i get the same result. some MFC apps work, some simply crash.
if i use this code, it seems to work always:
Code:
mov ecx, 0 //modify ECX too, but no problem here
push original
ret
do you have any idea, whats now wrong?
did you debug what kind of crash it was? I'm a bit curious as to what makes it crash.
Try putting an int 3 in your routine to single step each cases until you see a buggy one.
Aside: you could try to change your routine to another register (eax); ecx is usually to "this" pointer passed between functions in c++.
Quote:
[Originally Posted by doug]did you debug what kind of crash it was? I'm a bit curious as to what makes it crash.
Try putting an int 3 in your routine to single step each cases until you see a buggy one. |
GetOpenFileNameA() is one of these functions, that always crash with an "accessviolation while reading" exception, somwhere deep in the comdlg.dll and i still don't know why.
this code works flawlessly, so the only difference is the modified return, by what the expected call will return to my proxycode.
Code:
mov ecx, 0 //testing purposes
push original
ret
maybe i should give up now
nikolatesla20
May 11th, 2004, 19:27
I still don't know why you want to store away anything in ecx. You shouldn't have to - you should use the stack for everything you need. If you use the right combo of push / rets / pops you can get this to work no problem.
Also, why are you playing with tls storage , it's too complicated and could be dangerous, just use normal asm. tls could be unreliable, who knows what windows is doing with it behind u.
-nt20
the stack looks like this, if my code is called:
param0
param1
...
paramX
retaddr
all i could do now, is to jump directly to the expected function, and everything would work, but i'm also interested in the returnval of the expected function. to get this value, i have to replace the initial retaddr with one, that points to my code, and after this code, i need the initial return addr, so i need to save it, but where? i can't push it, because of the parameters.
if i declare a global var with __declspec(thread), every thread has its own 'instance', thats why i use it to save the initial return.
hm
maybe the problem is, that i use only one place to save the initial return val, but what if one hooked function calls another one? then the tls val would be overwritten.
i should use a stack like tls-structure
doug
May 12th, 2004, 19:11
well, if you can, pm me :
- the target
- your code
- small txt file explaining what you do.
it works now, even with GetOpenFileName
this is the code: http://pro.n5home.net/inject.cpp.html
nikolatesla20
May 13th, 2004, 09:04
Quote:
[Originally Posted by 0rp]it works now, even with GetOpenFileName

this is the code: http://pro.n5home.net/inject.cpp.html |
Are you using a named pipe to shuttle data back and forth? Neat idea.
Only problem would be you should use a random name in case you ever release the tool, so it can't be detected.
-nt20
thx
i plan to write a tool, wich shows GetProcAddress-ed API-calls with its callstack (retrieved through the StackWalk-API). maybe this helps to reverse packed tools.
do you think this makes sense ? i mean, there are _a lot_ of api monitors, but do they capture runtime loaded api calls ?
Powered by vBulletin® Version 4.2.2 Copyright © 2018 vBulletin Solutions, Inc. All rights reserved.