Jump to content
Tuts 4 You

Any Tutorials For Calling Functions?


GNIREENIGNE

Recommended Posts

GNIREENIGNE

When dealing with real examples, it's often difficult to determine what needs to be done in order to satisfy the parameters of the call. One of the previous links posted in this thread talks about the various registers that get pushed on to the stack - but that relates to the prologue, of which is a non-critical component when calling a function from a separate thread. That said, is there a method that can be followed for determining these requirements? I would assume that every situation is going to be different, but are there any tips or tricks that can be used to reduce my current method of trial-and-error guessing?

Thanks.

Link to comment

You check if ecx and edx is set, yes -> fastcall

Only ecx -> thiscall

no ecx but add esp,XX after call (caller cleanup) -> cdecl

no ecx and no cleanup, and called function has either many pops before return or RET XX -> stdcall

Then u break at the function entry, count the ammount of arguments (how many are cleaned up after call) and try to find out which one means what

  • Like 1
Link to comment
GNIREENIGNE

Thanks, Pancake.

Okay, so, in one of my previous examples, eax was pushed on to the stack, then a value was copied to the ecx register just before the call. However, after the call, only ecx was popped off the stack. In an example like this, that would mean only 1 argument needed to be satisfied, yet, the eax push was required before the call. Based on your reply, it seems like a good way to identify the calling procedure, but how does it help me with determining how to satisfy the arguments of the call? It seems confusing.

Thanks.

Edited by GNIREENIGNE
Link to comment

;) pop ecx is a common compiler hack

add esp,4 is a 3 byte instruction (83 C4 04)

Read calling conventions carefully again: You will see that eax serves a purpose of result holder (so 'return 7;" in C results in mov eax,7 ret), ecx and edx registers CAN BE MODIFIED by the called function. There is no guarantee that they will be valid after you call other function. ebx for example has to be saved by called. So conclusion: you can be sure that ebx,esp,ebp value will be proper. But not edx and ecx - save them yourself if u need to. And then back to the add esp,4:

So if we can instead pop ecx which takes just 1 byte, why not? Compiler knows that ecx will be invalid after function call, then why not make stack cleanup (with 1 dword) much more effectively? Pop ecx will reduce the size of stack cleanup from 3 to 1 instruction and ecx is invalid anyways.

Post is kinda messy because head hurts me right now, hope i helped ;)

Edited by Pancake
  • Like 2
Link to comment
GNIREENIGNE

Thanks a lot, Pancake. Although I feel more confused after reading that, I am understanding a little bit more, even if only a little at a time. I appreciate you for writing that up and explaining it to me. I will continue to try to wrap my head around this.

Thanks.

Link to comment
GNIREENIGNE

Ok...so using a live example, we have a 64-bit target. How would I know what to do in order to call this:

7FEE01F5969 - CC                    - int 3
7FEE01F596A - CC                    - int 3
7FEE01F596B - CC                    - int 3
7FEE01F596C - CC                    - int 3
7FEE01F596D - CC                    - int 3
7FEE01F596E - CC                    - int 3
7FEE01F596F - CC                    - int 3
7FEE01F5970 - 48 89 5C 24 08        - mov [rsp+08],rbx
7FEE01F5975 - 48 89 74 24 10        - mov [rsp+10],rsi
7FEE01F597A - 48 89 7C 24 18        - mov [rsp+18],rdi
7FEE01F597F - 55                    - push rbp
7FEE01F5980 - 41 54                 - push r12
7FEE01F5982 - 41 55                 - push r13
7FEE01F5984 - 48 8B EC              - mov rbp,rsp
7FEE01F5987 - 48 83 EC 70           - sub rsp,70 { 112 }
7FEE01F598B - 0F29 74 24 60         - movaps [rsp+60],xmm6
7FEE01F5990 - 48 8B D9              - mov rbx,rcx
7FEE01F5993 - E8 A85B6F00           - call 7FEE08EB540    ///////Need to call this
7FEE01F5998 - E8 A39D6300           - call 7FEE082F740
7FEE01F599D - 45 33 ED              - xor r13d,r13d
7FEE01F59A0 - 41 83 CC FF           - or r12d,-01 { 255 }
7FEE01F59A4 - 83 F8 01              - cmp eax,01 { 1 }
7FEE01F59A7 - 75 74                 - jne 7FEE01F5A1D
7FEE01F59A9 - 41 8B FD              - mov edi,r13d

I have tried several different things, to no avail. According to the x64 calling conventions, arguments are passed in registers RCX, RDX, R8 & R9. Based on the above, I tried pushing RCX before the call, as well as using sub rsp,70, but that didn't work.

Thanks.

 

Edited by GNIREENIGNE
Link to comment
GNIREENIGNE

Can anyone point me in the right direction? I assume that I need to set a breakpoint on the call that I'm interested in and look at the register values. But how do I know which arguments to pass? Do I just pass them all? What about the call stack...should I be looking at that? I feel like I'm close to figuring this out, but I just can't seem to put the missing pieces together.

I appreciate any help.

Thanks.

Link to comment

It's impossible to give relevant answer to your question without seeing how the function at address 7FEE08EB540 looks like.

 

  • Like 1
Link to comment
GNIREENIGNE

Thanks for replying, kao.

So you need to see inside the call in order to call it? I wasn't aware of that. Is that the case if I am calling from a separate thread as well? I was thinking that the prologue/epilogue of the call is handled by the call itself, so I just assumed that it was only necessary to give importance to the data for the sub-routine where the call resides. I hope you can have patience with my newbieness.  :)

Unfortunately, I have since deleted this game from my computer, but I will reinstall it and provide whatever info you need, because I'd really like to figure this out...even if it's for a different target, it really doesn't matter to me.

I'll provide more screenshots as soon as I can. (I have to take my Uncle to the VA Hospital shortly, so it may not be for a few hours)

I really appreciate your help.

Thanks.

Edited by GNIREENIGNE
Link to comment
18 minutes ago, GNIREENIGNE said:

So you need to see inside the call in order to call it? I wasn't aware of that.

I need to see inside the call in order to learn how to call it. :) Just like you need to open an unmarked box to learn what's inside it. From outside you can only tell that the box is heavy, made from black plastic and has a lid - but you have no idea what's inside.

No worries, take your time.

 

  • Like 1
Link to comment
GNIREENIGNE

Awesome...I really appreciate your help, kao.

So, here is a screenshot with a breakpoint on the call, as well as a screenshot with a breakpoint inside the call. I hope this helps. Please let me know if you need anything else. Thanks, again.

6-7-2016 3-03-20 PM.png6-7-2016 3-03-27 PM.png

Edited by GNIREENIGNE
Link to comment

It looks like RCX register is used (at address 7FEE08EB55B). RDX, R8, R9 are not saved before call instruction (at address 7FEE08EB55E), so you can assume they are not used. XMM registers also seem to be not used.

So, you should be able to call your function by code like this:

mov rcx, {correct value here}
call 7FEE08EB540

I can't tell you how to get the correct RCX value, that code is not present in your screenshots.

Edited by kao
  • Like 1
Link to comment
GNIREENIGNE

Great! This is making a lot of sense.

When I set a breakpoint on the call, it shows the value of RCX address on the right (58A87070). Is that not what you mean? Unfortunately, the value of RCX is not static. How do I get this information? Do I need to backtrace to see where the value is set first?

Thanks!

Edited by GNIREENIGNE
Link to comment
30 minutes ago, GNIREENIGNE said:

Do I need to backtrace to see where the value is set first?

Pretty much, yeah.

  • Like 1
Link to comment
GNIREENIGNE

I haven't posted back here yet because I'm still working on this. I don't know if I'll be able to figure it out or not. The bad thing is, the section of code that I'm interested in, only gets executed at startup...so it makes it all the more difficult to do what I need.

I will post my findings whenever I have something more meaningful to share...or I will just fail miserably and post that. :D

Thanks, again!

Link to comment

Just create own exe file and reverse it. Thats the easiest way to learn it. Play around with conventions, arguments and you will quickly pick it up

  • Like 1
Link to comment
GNIREENIGNE

Thanks, Pancake.

Yeah, I have just been practicing with any program that I happen to be messing with at the time. Since I don't have any programming background, it's easier for me. I wanted to try the example above because I knew that it would be challenging, so, if I can figure it out, I should be able to do most of the easier ones. :)

 

Link to comment
GNIREENIGNE

Update:

I have managed to execute the call by setting ecx and jumping to the start of the sub-routine where the call resides via a separate thread.

7FEE01F5993 - E8 A85B6F00 - call 7FEE08EB540   //////////  I was able to execute this call by setting ecx properly and jumping to the start of the sub-routine where this call resides

However, calling the sub-routine in lieu of jumping to it, using the exact same method, caused the target to crash. Since this was performed via a separate thread and not from within any of the utilized modules, I am confused as to why one way is successful while the other is not, seeing as they are performing the same actions (so I thought).

Anyone have any ideas as to why this is so?

Thanks!

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...