PHASE 2: DIRECT THE EXECUTION FLOW TO EXECUTE THE MALICIOUS CODE: REPLACING THE RETURN ADDRESS M. Pourzandi - INSE 6140 26 First step: finding where the return address is To replace the return address we need first to find out where it is in the stack If this address is replaced with the address of executable code, the execution can be controlled to jump to that specific address M. Pourzandi - INSE 6140 27 Tools (1): BASH Since so much of hacking is rooted in exploitation and experimentation, the ability to quickly try different things is vital. The BASH shell and Perl (or Python these days) are common on most machines and are all that is needed to experiment with exploitation. Perl is an interpreted programming language with a print command that is particularly suited to generating long sequences of characters Info: Beginner’s introduction to Perl: http://www.perl.com/pub/2000/10/begperl1.html M. Pourzandi - INSE 6140 28 Tools (2): Perl Perl can be used to execute instructions on the command line by using the -e switch: Repeat 20 times ASCII code of ‘A’ in hex String concatenation with ‘.’ An entire shell command can be executed like a function, returning its output in place. This is done by surrounding the command with parentheses and prefixing a dollar sign. M. Pourzandi - INSE 6140 29 Review the overflow_example.c M. Pourzandi - INSE 6140 INSE 6140 – Buffer Overflow 30 30 Overflow Buffer Generation with Perl – overflow_example.c argv(1) is a string with 30 ‘A’ characters Calculate the distance between buffer_two and value. Reset the number of character so as to overwrite value with “ABCD” ASCII code of ‘ABCD’ in hex M. Pourzandi - INSE 6140 31 Review auth_overflow2.c Difference from auth_overflow.c: the sequence of the two statements are reversed. M. Pourzandi - INSE 6140 32 Overflow Buffer Generation with Perl – auth_overflow2.c Check the number of arguments, and print usage What if we overwrite the return address with 0x080484bf? M. Pourzandi - INSE 6140 33 Overwrite Return Address – auth_overflow2.c If the return address is overwritten with the address containing the Access Granted message, this block of instructions will be executed. The exact distance between the return address and the start of the password_buffer can change due to different compiler versions and different optimization flags. As long as the start of the buffer is aligned with DWORDs on the stack, this mutability can be accounted for by simply repeating the return address many times. Address of “Access Granted” message in little-endian format M. Pourzandi - INSE 6140 34 Question One way of protecting the system against buffer overflow is called NX: non executable memory section (stack, heap). If NX was deployed a) b) The attack as described in previous slide will not be successful The attack as described in previous slide will be successful M. Pourzandi - INSE 6140 35 notesearch.c – Buffer overflow Target Target of Buffer Overflow M. Pourzandi - INSE 6140 36 Second step: injecting your own code So, we managed to execute some code inside the existing program even though it was not intended by the programmer Previous buffer overflow attacks, e.g., exploitation of overflow_exampe.c and auth_overflow2.c, limited to using instructions that exist in the original program Limited functionality and not flexible What about injecting your own code and execute it? M. Pourzandi - INSE 6140 37 Tools (1): Shellcode In computer security, a shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is called "shellcode" because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode. (Wikipedia) M. Pourzandi - INSE 6140 38 Tools (2): Shellcode The exploitation of notesearch (i.e., exploit_notesearch.c) injects its own instructions into memory and then returns execution to these instructions to be executed These instructions called shellcode tell the program to restore privileges and open a shell prompt It is especially devastating when the targeted program is executed under higher privileges, e.g., in the case of notesearch.c, although the original intention of this program is to limit such privileges to only accessing a specific data file. This technique allows the program to do things it was never programmed to do, e.g., gain a root shell, while it's still running with elevated privileges. M. Pourzandi - INSE 6140 39 Tools (3): NOP Instruction NOP instructions are sometimes used to waste computational cycles for timing purposes. NOP sled can assist with this difficult chicanery. NOP is an assembly instruction that is short for no operation. On the x86 architecture, the NOP instruction is equivalent to the hex byte 0x90. INSE 6140 – Buffer Overflow 40 Tools (4): Usage of NOP Instruction In exploit_notesearch.c, NOP instructions are used as a fudge factor. A large array (or sled) of these NOP instructions are created and placed before the shellcode; If the EIP register points to any address found in the NOP sled, it will increment while executing each NOP instruction, one at a time, until it finally reaches the shellcode. This means that as long as the return address is overwritten with any address found in the NOP sled, the EIP register will slide down the sled to the shellcode, which will execute properly. NOP sled Shellcode Repeated return address INSE 6140 – Buffer Overflow 41 Finding the return address The difficulty of finding the exact location of the return address is eased by using the repeated return address technique. But this return address must point to the shellcode located in the buffer. This means the actual address must be known ahead of time, before it even goes into memory. This can be a difficult prediction to try to make with a dynamically changing stack. INSE 6140 – Buffer Overflow 42 Building the exploit for notesearch: exploit_notesearch.c Shellcode Writing shellcode and NOPs in the memory M. Pourzandi - INSE 6140 43 Building the exploit for notesearch: exploit_notesearch.c Generating a command string that will execute the notesearch program with a command-line argument between single quotes System function is used to execute the command string M. Pourzandi - INSE 6140 44 exploit_notesearch.c – debug before calling memset() before calling memcpy() after calling memcpy() M. Pourzandi - INSE 6140 45 exploit_notesearch.c – debug Overwrite the buffer with the value in ret M. Pourzandi - INSE 6140 46 exploit_notesearch.c – debug Write NOP instructions into the buffer M. Pourzandi - INSE 6140 47 Almost finished attack payload Write shellcode into the buffer M. Pourzandi - INSE 6140 48 Experimenting to find the ret value In exploit_notesearch.c, the address of the variable i in main()'s stack frame is used as a point of reference. Then an offset (i.e., 270) is subtracted from that value. The easiest way to determine this offset is experimentally. With helps from BASH commands, different offsets can quickly be tested. M. Pourzandi - INSE 6140 49 BASH Commands M. Pourzandi - INSE 6140 50 Testing Offset Using BASH Commands After testing offset from 0 to 300 with step 30, the attack succeeds when offset = 210 or 240. M. Pourzandi - INSE 6140 51 References [1] Chapter 3, Hacking: The Art of Exploitation, 2nd edition, by Jon Erickson, 2008. [2] Return-oriented Programming: Exploitation without Code Injection, E. Buchanan, R. Roemer, S. Savage, H. Shacham, University of California, San Diego [3] Introduction to return oriented programming (ROP), By Alex Reece, Visited Jan 2015 http://codearcana.com/posts/2013/05/28/introduction-to-returnoriented-programming-rop.html [4] Frankstein: Stitching malware from benign binaries, V. Mohan, K.W. Hamlen, University of Texas at Dallas M. Pourzandi - INSE 6140 52