Jump to content

Question about CALL statement

- - - - -

  • Please log in to reply
14 replies to this topic

#1
Bruce

Bruce

    Newbie

  • Members
  • Pip
  • 1 posts
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.

#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
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

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
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
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.

#4
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
Maybe something like this?:
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
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
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
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
Well, yes, but I don't really care about the return address in the "jmp .start" case:
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 

ret 
might make a little bit more sense.

#7
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
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
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
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 4 
Isn't it like that?

#9
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
I mean if I know that the next value is the address to return to then I use that value (don't I?).

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
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:


.                   <-- EBP is usually somewhere up here

.

.

123456

<return address>    <-- ESP

If you pop the return address off, then you have:

.                   <-- EBP

.

.

123456              <-- ESP

When 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
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,251 posts
  • Location:C:\Countries\US
But I tried things like:
push dword lbl1 

ret 

lbl1: 
And, as far as I can remember, they did work.

#12
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
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

myfunc:

    ; ... blah ....

    ret


foo:

    mov     eax, myfunc

    ; ...


sudo rm -rf /




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users