<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            原文地址:http://drops.wooyun.org/binary/5831

            又一期的wargame來了,這一期的wargame主要側重于逆向,基本上在gdb下把程序的思路弄清楚了,再利用一些簡單的滲透溢出技巧,就可以成功了。 Let's go!

            依然是老方法,在游戲behemoth首頁可以找到登陸的服務器的賬號和密碼。ssh登陸上去,開始我們的wargame之旅。

            level 0


            登陸服務器,在游戲文件夾/behemoth下可以看到全部的可執行程序,首先執行./behemoth0,這是這一關待解決的程序。

            behemoth_level0_login

            程序讓我們輸入一個密碼,估計是將我們輸入的密碼和某個固定的密碼做匹配,可能是加密后最匹配,誰知道它怎么做。gdb走起。

            behemoth_level0_disassemble

            從反匯編的代碼可能看到兩個令人激動的函數,一個是memfrob(),通過找男人(man)知道,這個函數是將輸入的指定長度的字符串中的字符與數字42做異或,既然是異或操作,就是可逆的。另一個函數是strcmp(),這個函數才是最令人激動的,從整個程序流程大概看到,程序通過scanf()獲取用戶輸入,然后通過memfrob()做異或處理,然后再送入strcmp()做匹配,所以,我們只要在strcmp()函數調用處下斷點,然后查看棧內容就可以得到真正的密碼了。

            behemoth_level0_passwd

            程序需要輸入的密碼是eatmyshorts,執行程序,這一關就過去了。

            behemoth_level0_crack

            level 1


            這一關程序也是要求輸入一個密碼,無法得到準備密碼,還是要gdb走起。

            behemoth_level1_login

            behemoth_level1_disassemble

            好吧,從逆向出來的匯編代碼看,程序很簡單,使用gets()得到用戶輸入,然后puts()輸出"Authentication failure.\nSorry."提示結束就可以了,沒有匹配,也就是沒有正確的密碼。不過從gets()這是一個不安全的函數,這里也沒有邊界檢查,說明存在緩沖區溢出漏洞,這是可以利用的。

            behemoth_level1_overflow

            通過驗證,確實存在緩沖區溢出漏洞,下面就是如何利用這個漏洞了,這個溢出利用前面的wargame已經玩得很多了。

            behemoth_level1_crack

            level 2


            這里程序執行似乎是要創建某個文件,多次執行發現,每次創建的文件名似乎都不相同,應該是跟pid相關。

            behemoth_level2_login

            還是看匯編代碼比較容易理解程序的執行意圖。

            behemoth_level2_disassemble

            對反匯編代碼做個大概解釋,執行的流程如下

            #!c
            id = getpid()
            s = lstat("touch " + str(id))
            if(s & 0xf000 == 0x8000){
                unlink(str(id);
                system("touch " + ID);
            }
            sleep(0x7d0);
            system("cat  " + str(id));
            

            程序在當前目錄下嘗試查找以自己pid為名的文件,如果不存在的話,就建立該文件,然后執行一個很長時間的sleep(),然后再打開文件。這里沒有輸入,不存在溢出,也沒有其它很明顯的漏洞。sleep(a_long_time)這個函數調用似乎沒有辦法越過,也沒法通過修改.got.plt來嘗試將sleep()替換成其它的函數。后來再參考了網上的類似writeup,發現這里在調用system()的時候使用的是相對路徑,既然是相對路徑,那么這個路徑就是我們可以控制的,通過修改PATH環境變量,這樣就可以使程序在路徑搜索的時候,先搜索我們指定的路徑,這樣就可以將touch程序替換成我們想要執行的程序,比如執行生成一個*shell*。這樣就順利通過這一關了。

            behemoth_level2_crack

            這里需要注意路徑和偽 touch 程序的權限問題,開始我一直失敗就是因為權限配置的不對,浪費了不少時間按。

            level 3


            這里還是有一個輸入,既然有輸入就有可能有溢出點。

            behemoth_level3_login

            從程序執行的結果來看,程序打印了我們的輸入,猜測可能有緩沖區溢出,或者是格式化字符串漏洞,經過驗證,確實有格式化字符串漏洞,這樣就很容易了,基本上不需要看匯編代碼就可以搞定了。

            behemoth_level3_test_offset

            從上面的測試我們發現,字符串存儲地址是在當前棧的第六個偏移的地方,即0x18(%esp),這個值在gdb中也是可以看到的。接下來就是構造攻擊程序了。我將shellcode放在環境變量中。

            behemoth_level3_gdb_test

            如上圖所示,環境變量即shellcode保存在0xffffd78c中,可能存在一點偏移,不過我們有Nop sledReturn Address處保存著程序原來的返回地址,我們需要將它修改為shellcode

            behemoth_level3_crack_attack

            這里執行的cat是為了防止管道關閉,在前面的wargame也使用了這個方法。其中需要注意的是,管道的右邊,一開始我使用的是相對路徑,導致總是沒法得到正確的結果,也不知道問題出現在哪里,后來無意中使用了絕對路徑,才搞定的。這里不知道為什么,等我之后看看管道的具體原理再做記錄。

            behemoth_level3_crack_ret

            level 4


            這里執行的結果就給了一個提示,PID not found!,看樣子程序又是跟PID相關了。

            behemoth_level4_login

            從反匯編出來的代碼可以大概了解到程序的執行流程。

            behemoth_level4_disassemble

            behemoth_level4_disassemble_2

            程序首先打開/tmp/pid文件,然后sleep(1)一秒,然后將文件內容輸出,這樣我們只要將文件軟鏈接到密碼文件,就可以讓程序打開密碼文件,同時輸出文件內容了。難點在于,我們如何知道程序的pid,雖然linux 下 pid 是遞增的,但是這也無法保證每次增加的就是 1 個單位。于是,我想到了一個不優雅的方法,我們先建立大量的可能的pid軟鏈接文件,然后一直執行程序,執行程序的pid會落到我們建立的文件范圍內的。

            behemoth4.py

            #!python
            #!/usr/bin/env python
            #coding=utf-8
            
            import sys, os
            passwd_file = "/etc/behemoth_pass/behemoth5"
            
            if len(sys.argv) < 2:
                    print "usage %s [start pid num]"
                    sys.exit(-1)
            try:
                    start_pid = int(sys.argv[1])
            except ValueError:
                    print "usage %s [start pid num]"
                    sys.exit(-1)
            
            # 建立 50 個符號鏈接文件
            for i in range(50):
                    os.popen("ln -s " + passwd_file + " /tmp/" + str(i+start_pid))
            
            # 執行 1000 次程序
            for i in range(1000):
                    ret = os.popen("/behemoth/behemoth4")
                    ret = ret.read()
                    if not "not" in ret:
                            print ret
                            break
            
            # 刪除所有建立的文件
            for i in range(50):
                    os.popen("rm /tmp/" + str(i+start_pid))
            

            主要是python下獲取子進程的pid太麻煩了,要不然這個爆破的代碼可以寫得更優雅一點。不過不影響結果,依然爆破出來了。這里需要注意的是,start pid即程序的參數應該要選得大一點,因為程序里面建立符號鏈接文件啟動了不少子進程,我這里在原來的基礎上增加了500個數,否則容易越過。

            behemoth_level4_crack

            level 5


            這一關執行程序沒有任何輸出,沒有提示,還是直接看反匯編出來的代碼吧。代碼

            behemoth_level5_disassemble_0

            behemoth_level5_disassemble_1

            behemoth_level5_disassemble_2

            behemoth_level5_disassemble_3

            behemoth_level5_disassemble_4

            可以看到,程序首先打開了密碼文件/etc/behemoth_pass/behemoth6,然后建立了localhost:1337socket,再用sendto函數將文件內容發送出去。程序的流程很明顯了,接下來我們只要監聽本地端口1337就可以收到密碼了。需要注意的是sendto是用UDP協議發送的,需要監聽該端口的UDP數據包。

            使用瑞士軍刀nc進行監聽,然后在另外一個shell中執行程序,nc就會輸出收到的UDP數據包內容了。

            shell 1 behemoth_level5_listen

            shell 2 behemoth_level5_sendto

            shell 1 behemoth_level5_crack

            level 6


            這一關有兩個可執行程序,執行程序都沒有得到任何有意義的結果,還是直接看反匯編出來的代碼吧。

            behemoth_level6_disassemble

            behemoth_level6_memory

            第一個主程序與第二個程序/behemoth/behemoth6_reader建立一個管道,然后通過管道讀取,如果讀到的內容等于HelloKitty,這樣就會執行execl(),建立一個shell。我們再看看第二個程序。第二個程序,執行就會輸出Couldn't open shellcode.txt!,看樣子是要建立一個名為shellcode.txt的文件,具體還是看看匯編代碼吧。

            behemoth_level6_reader

            程序首先打開一個名為shellcode.txt的文件,然后將文件內容讀取到動態申請的存儲區,最后跳轉到動態存儲區,執行讀取到的內容。這樣就很容易理解了,我們在shellcode.txt文件中存放一段shellcode,這段shellcode只執行一個任務,就是向標準輸出stdout打印一段字符串HelloKitty就可以了。

            section .text
            global _start
            _start:
                    mov ax, 0x7974          ; ty
                    movzx eax, ax           ; zero-extend ax to 32bits
                    push eax
                    push 0x74694b6f         ; oKit
                    push 0x6c6c6548         ; Hell
                    mov ecx, esp
                    xor ebx, ebx
                    inc ebx
                    xor edx, edx
                    mov dl, 10
                    xor eax, eax
                    mov al, 4
                    int 80h
            
                    ; exit(0)
                    xor ebx, ebx
                    xor eax, eax
                    mov al, 1
                    int 80h
            

            上面就是我寫的輸出HelloKittyshellcode程序,匯編之后就可以得到可用的shellcode程序了。需要注意的是,behemoth6_reader程序使用的也是相對路徑,既然是相對路徑,就是我們可以控制的。在/tmp下建立文件夾behemoth6,將當前文件夾設置為/tmp/behemoth6,在該目錄下操作就可以了。

            behemoth_level6_crack

            level 7


            這一關的程序也是執行沒有任何輸出,所以說這次的wargame主要還是看逆向能力,基本上能逆向出來程序流程,后面的問題都很容易就可以解決了。匯編出來的程序很長,就不貼了。

            唯一可能有點難度的是,在匯編代碼中有兩次調用call 0x8048420 <[email protected]>這一個函數,男人(man)告訴說,這個函數一般是<ctype.h>中的函數如isspace()isalpha()等調用的,也就是在程序里執行的是類似的檢測,再加上從其它的代碼總體來看,得到結論。該程序檢測argv[1]中是否有Non-alpha字符存在,如果有的話那么就有可能是shellcode,這樣就提示錯誤。如圖所示,

            behemoth_level7_login

            如上圖所示,第一次執行時,argv[1]中有字符,存在,于是程序報錯,提示可能有shellcode存在。

            不過程序只是檢測argv[1]中前256個字符,這樣我們只需要用alpha字符填充前面256個位置就可以了,后面可以進行緩沖區溢出利用。不過程序中將全部的環境變量都清空了,這就意味著我們不能將shellcode放置在環境變量中,需要找其它的地方存放,同時一開始,我將shellcode放在argv[1]字符串中的尾部,加上Nop sled,執行的時候提示Illegal Struction,猜測可能棧不可執行。最終我使用return-to-libc,將返回地址修改成system()函數的地址,同時將參數/bin/sh放置在argv[2]中,加上一定的猜測,最終搞定了。

            behemoth_level7_crack

            end of the game


            又完成一期wargame了,現在的難度不是很大,都是一些很基礎的逆向、溢出的知識,不過作為一個新手,我深深地知道打好基礎才是最重要的,后面依然有很多好玩的。盡請期待~

            想了解更多關于wargame的內容,請參考這里

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线