0

I'm following a tutorial to get a better understanding of how things are passed around through stack frames, but they're working on a x86 system and I'm on x64.

when they've reached the step

   sub    esp, 0x10
=> mov    eax, DWORD PTR [ebp+0xC]
   add    eax, 0x4

They're able to see the address the pointer is pointing to. Checking the value, they get the address

0xbffff6d6

Then running x/s on that address returns the string value, which in this case should be the location of the program '/root/Desktop/00byte'

Where things are different for me is on x64 my instructions say

   sub    rsp, 0x10
   mov    DWORD PTR [rbp-0x4], edi
   mov    QWORD PTR [rbp-0x10], rsi
=> mov    rax, QWORD PTR [rbp-0x10]
   add    rax, 0x8

We've both assembled the same code and set our breakpoints on the same line, but on different platforms and I wanted to know how I'd be able to get the address from this point. I had assumed running

x/x $rax

would return the address of the pointer but instead it returns

0x55

Am I wrong to think the address of the pointer is stored in rax at this point? And if so, how would I get the address from this point.

I can provide more information if needed. We're both using gcc to compile and gdb to debug and using the same arguments when building the program.

I also tried checking the value in $rbp-16 but that only returns:

0xa8

So I'm not sure where the address is stored at this point in a way that I could examine based on the instructions I have.

*here's the code, we both put our breakpoints after the line where main() is declared:

#include <stdio.h>
#include <string.h>
void echo(char *message)
{
char buffer[100];
strcpy(buffer,message);
printf(buffer);
}
int main(int argc, char *argv[])
{
echo(argv[1]);
}

an argument is passed to the program and I'm observing how that argument moves through the stack.

1
  • This argument gets passed via register. Take a look at x64 calling conventions. – arrowd Mar 21 '18 at 4:42
1

[ebp+0x0c] is an argument to the function
[rbp-0x10] is a local to the function

so first of all you are comparing different things

i assume you are on the main() function because your echo function() takes only one argument so you cant refer a valid argument with [ebp+0xc] in that case

if you are on main then [ebp+0x0c] is char **argv

i am on windbg and i can get it like

0:000> da  @@c++(*(char **)argv)
004e8ac0  "x86.exe"

you are on gdb it appears and you can use x/s *(char **)argv or may be (ebp+0xc) play with it

the diassembly of the function main would be similar to (disassemble main in gdb instead of uf .)

0:000> uf .
    9 00f91040 55              push    ebp
    9 00f91041 8bec            mov     ebp,esp
   10 00f91043 b804000000      mov     eax,4
   10 00f91048 c1e000          shl     eax,0
   10 00f9104b 8b4d0c          mov     ecx,dword ptr [ebp+0Ch] <<< (char **)argv
   10 00f9104e 8b1401          mov     edx,dword ptr [ecx+eax] <<<<<<<
argv[1] pointer arithmetic ecx = 4 same as your add eax,4
   10 00f91051 52              push    edx
   10 00f91052 e8a9ffffff      call    x86!echo (00f91000)
   10 00f91057 83c404          add     esp,4
   11 00f9105a 33c0            xor     eax,eax
   11 00f9105c 5d              pop     ebp
   11 00f9105d c3              ret

the function echo needs the first argument passed to the binary

0:000> ?? (char *)argv[0]
char * 0x00258b4c
 "x86.exe"
0:000> ?? (char *)argv[1]
char * 0x00258b54
 "this is the first argument passed saniboy"

which incidentally you can also print with x/s in gdb

0:000> da /c 100 @edx
00258b54  "this is the first argument passed saniboy"

the same code compiled for x64 and disassembled main as follows

0:000> uf x64!main

    9 00000001`40001060 4889542410      mov     qword ptr [rsp+10h],rdx
    9 00000001`40001065 894c2408        mov     dword ptr [rsp+8],ecx
    9 00000001`40001069 4883ec28        sub     rsp,28h
   10 00000001`4000106d b808000000      mov     eax,8
   10 00000001`40001072 486bc001        imul    rax,rax,1
   10 00000001`40001076 488b4c2438      mov     rcx,qword ptr [rsp+38h]
   10 00000001`4000107b 488b0c01        mov     rcx,qword ptr [rcx+rax]
   10 00000001`4000107f e87cffffff      call    x64!echo (00000001`40001000)
   11 00000001`40001084 33c0            xor     eax,eax
   11 00000001`40001086 4883c428        add     rsp,28h
   11 00000001`4000108a c3              ret

x64 passes first 4 arguments via registers and does not use stack for passing arguments

you can find a similar document to this microsoft specific document on passing parameters

so your first argument will be in rcx

x/s $rcx

you cannot go and compare line by line they wont match

1
  • Thank you for this explanation! I know I'm late on the response+accepting the answer so apologies for that. I've learned a lot since I posted this question and your answer makes complete sense now. It seems overwhelming at first but once you get used to reading it it's not so bad! – saniboy Apr 25 '18 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.