I am a Beginner in x86 Assembly Language. I am writing a code for reading a thread's stack in VC++. I have inserted some assembly code in between. So here's the problem:
I get the function's return address from its stack frame. No before this return address there should be a CALL statement. So I extract out the bytes before the return address.
Sometimes it a near call like E8 ff ff ff d8. My objective is to calculate the function's base address. So for the above statement I subtract the offset 0x28 from the function's return address to get its base address (where it resides in memory).
The problem is I don't know how to calculate this for a FAR call. I have been trying to find out how to do it for some time now. So I have extracted out the first 5 bytes before the return address and they are
ff 75 08 ff d2 <return_addr>
I think this stands for CALL ecx (ff d2) but I am not sure. I will be very grateful if someone can tell me what kind of CALL statement is this and how I can calculate the function's base address from this kind of call.
14 replies to this topic
#1
Posted 03 January 2011 - 11:27 AM
|
|
|
#2
Posted 05 January 2011 - 12:50 AM
Intel Developer Manuals
There are two volumes dedicated to the instruction set; 2B contains an opcode map at the end that you can easily use to find out the mnemonic for a sequence of bytes. As for your byte sequence, it's
The address after a call instruction is the call address, not the return address. In the case you presented above, you need to know the value in EDX to know what the address of the function being called is.
There are two volumes dedicated to the instruction set; 2B contains an opcode map at the end that you can easily use to find out the mnemonic for a sequence of bytes. As for your byte sequence, it's
FF7508 push DWORD [ebp + 8] FFD2 calln edx
The address after a call instruction is the call address, not the return address. In the case you presented above, you need to know the value in EDX to know what the address of the function being called is.
sudo rm -rf /
#3
Posted 05 January 2011 - 04:27 PM
There are also these manuals:
Intel Architecture Software Developer's Manual, Volume 1: Basic Architecture
Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual
Intel Architecture Software Developer's Manual Volume 3: System Programming
I don't know much differences between these manuals and the ones on the Intel Developer Manuals page, but these are just three I know of.
Intel Architecture Software Developer's Manual, Volume 1: Basic Architecture
Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference Manual
Intel Architecture Software Developer's Manual Volume 3: System Programming
I don't know much differences between these manuals and the ones on the Intel Developer Manuals page, but these are just three I know of.
#4
Posted 05 January 2011 - 04:40 PM
Maybe something like this?:
(Although this is for near calls; I think it's a little bit similar with far calls (isn't it?).)
mov edx, function call edx ;; .....some more code..... function: call .start .start: pop eax ;; The address of the function 'function' ;; Do whatever with eax ;; .....some code..... ;; Just issue the return instruction, to return from 'function': ret
(Although this is for near calls; I think it's a little bit similar with far calls (isn't it?).)
#5
Posted 05 January 2011 - 06:48 PM
Make sure to put the return address back or else you'll return to some random location and probably segfault. A better way would be:
call start ; function address is now in EAX ; ... start: mov eax, [esp] ret
sudo rm -rf /
#6
Posted 05 January 2011 - 08:37 PM
Well, yes, but I don't really care about the return address in the "jmp .start" case:
You are right about that, though; maybe something like:
call function function: call .start ;; start of 'function'; the call instruction pushes EIP to the stack and jumps to 'function.start' or just '.start' (NASM syntax). .start: pop eax ;; Since I don't really care much about that value and since I just want to ;; return back to the instruction that's right after "call function," I just POP it and just use the value. ;; That way, when I use the RET instruction, I return not to the place where I said "call .start," but ;; to the place where I said "call function," which is what I want to do. ret
You are right about that, though; maybe something like:
call function function: call .start .start: mov eax, [esp] add esp, 4 retmight make a little bit more sense.
#7
Posted 05 January 2011 - 08:42 PM
No, you don't want to do that. By using add esp, 4 or pop eax you're discarding the return address the processor pushed onto the stack. This means that whatever is next on the stack will be treated as the return address, and who knows what value that could be.
sudo rm -rf /
#8
Posted 05 January 2011 - 09:26 PM
push dword ..... ;; stack: ;; dd ..... call function function: ;; stack: ;; dd ..... ;; dd some_address call .start .start: ;; stack: ;; dd ..... ;; dd some_address ;; dd .start mov eax, [esp] ;; Do the job that involves the address. ;; stack: ;; dd ..... ;; dd some_address ;; dd .start ;; We want to return back to some_address, not to .start, so ;;;; we need to adjust esp to the address that points to the pointer to some_address. add esp, 4 ;; stack: ;; dd ..... ;; dd some_address ;;; Okay, now that the stack is where we want it to be, we can return. ret 4Isn't it like that?
#9
Posted 05 January 2011 - 09:27 PM
I mean if I know that the next value is the address to return to then I use that value (don't I?).
#10
Posted 05 January 2011 - 09:42 PM
Again, your code will make the program segfault. Allow me to explain something; let's say you have a function foo() that takes one integer parameter. For the sake of argument let's say that the size of an integer and a pointer are both 4 bytes. When calling foo(), the stack looks like this:
To pass arguments to functions, you don't want to have to repeatedly set up and clean up the stack, so you can use ESP as your argument pointer when calling. All you need to know beforehand is
- The largest number of bytes' worth of arguments you pass to any function
- The total number of bytes' worth of local variables you have in your function
. <-- EBP is usually somewhere up here . . 123456 <return address> <-- ESPIf you pop the return address off, then you have:
. <-- EBP . . 123456 <-- ESPWhen you try to return the processor performs the equivalent of mov eip, [esp] which means that it'll jump to memory location 123456, which is probably not where you want to go. If you want a function to be able to determine the address of the currently executing instruction, then you need to do this in your code:
call .here .here: pop eax
To pass arguments to functions, you don't want to have to repeatedly set up and clean up the stack, so you can use ESP as your argument pointer when calling. All you need to know beforehand is
- The largest number of bytes' worth of arguments you pass to any function
- The total number of bytes' worth of local variables you have in your function
%define MYFUNC_MAXARGS 12 %define MYFUNC_MAXLOCALS 8 %define MYFUNC_STACKSZ ((MYFUNC_MAXARGS + MYFUNC_MAXLOCALSIZE)*4) myfunc: push ebp mov ebp, esp sub esp, MYFUNC_STACKSZ add esp, MYFUNC_STACKSZ pop ebp ret
sudo rm -rf /
#11
Posted 05 January 2011 - 10:30 PM
But I tried things like:
push dword lbl1 ret lbl1:And, as far as I can remember, they did work.
#12
Posted 05 January 2011 - 11:23 PM
Yes, that'll work, but all it does is jump to that label. Just make sure you use only ret, not retf or ret n where n is the number of bytes to pop off the stack when returning.
If you want the address of a function you might as well do something like
If you want the address of a function you might as well do something like
myfunc: ; ... blah .... ret foo: mov eax, myfunc ; ...
sudo rm -rf /
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users


Sign In
Create Account

Back to top









