GNIREENIGNE Posted June 1, 2016 Author Posted June 1, 2016 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.
Pancake Posted June 1, 2016 Posted June 1, 2016 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 1
GNIREENIGNE Posted June 1, 2016 Author Posted June 1, 2016 (edited) 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 June 1, 2016 by GNIREENIGNE
Pancake Posted June 1, 2016 Posted June 1, 2016 (edited) 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 June 1, 2016 by Pancake 2
GNIREENIGNE Posted June 2, 2016 Author Posted June 2, 2016 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.
GNIREENIGNE Posted June 2, 2016 Author Posted June 2, 2016 (edited) 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 June 2, 2016 by GNIREENIGNE
GNIREENIGNE Posted June 7, 2016 Author Posted June 7, 2016 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.
kao Posted June 7, 2016 Posted June 7, 2016 It's impossible to give relevant answer to your question without seeing how the function at address 7FEE08EB540 looks like. 1
GNIREENIGNE Posted June 7, 2016 Author Posted June 7, 2016 (edited) 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 June 7, 2016 by GNIREENIGNE
kao Posted June 7, 2016 Posted June 7, 2016 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. 1
GNIREENIGNE Posted June 7, 2016 Author Posted June 7, 2016 (edited) 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. Edited June 7, 2016 by GNIREENIGNE
kao Posted June 7, 2016 Posted June 7, 2016 (edited) 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 June 7, 2016 by kao 1
GNIREENIGNE Posted June 7, 2016 Author Posted June 7, 2016 (edited) 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 June 7, 2016 by GNIREENIGNE
kao Posted June 7, 2016 Posted June 7, 2016 30 minutes ago, GNIREENIGNE said: Do I need to backtrace to see where the value is set first? Pretty much, yeah. 1
GNIREENIGNE Posted June 8, 2016 Author Posted June 8, 2016 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. Thanks, again!
Pancake Posted June 8, 2016 Posted June 8, 2016 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 1
GNIREENIGNE Posted June 8, 2016 Author Posted June 8, 2016 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.
oped Posted June 9, 2016 Posted June 9, 2016 http://beginners.re This book should cover the basics. See: Chapter 64 Arguments passing methods (calling conventions) 1
GNIREENIGNE Posted June 14, 2016 Author Posted June 14, 2016 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!
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now