這一關就是一個簡單的游戲介紹,當然,還有明文的賬號密碼。打開網頁就能看到,不再敘述。
使用上一關得到的賬號和密碼,ssh
登陸到目標機器。
在主目錄下面,我們可以發現一個.backup
文件夾,進入文件夾,發現了一個html
文件,看樣子是瀏覽器收藏夾文件。我猜測密碼應該是在文件中以明文形式出現,用關鍵字leviathan
進行搜索,立刻就能得到密碼。the password for leviathan1 is rioGegei8m
。這道題應該就是讓你熟悉命令的。
使用上一個level得到的密碼,ssh到下一個level。在這關的home
目錄里面,我們看到一個名為check
的set-uid
程序,執行程序,看看程序執行結果。
程序要求我們輸入一個密碼,好吧。我不知道該輸入什么,猜想程序應該是將我們的輸入和某個密碼做比較,然后再執行。隨便輸入一個,觀察結果。
打開GDB
神器,看看它內部到底是個什么東西。
從圖中我們可以看看出來,程序三次調用getchar()
,猜想,password
應該是三個字符。strcmp()
函數的一個參數是我們輸入的字符的存儲起始地址,另一個地址是0x18(%esp)
,程序一開始在這里存儲了一個值0x786573
,然后將兩個地址作為實參送入strcmp()
,所以猜想,這里0x18(%esp)
就是我們需要的密碼。這個值正好是sex
的十六進制格式,于是,得到密碼是sex
。輸入程序,得到下一個level的密碼。
在這個level的home
目錄里面,依然是一個set-uid
的程序,執行程序得到如下結果,還是要使用神器gdb
。
使用gdb
打開程序,這個程序主函數反匯編出來的結果有點長,不過貌似沒有看到子函數調用,只有一個主函數。
這個程序首先進行了參數檢查,如果沒有命令行參數輸入,則打印出錯信息,然后退出。之后使用access()
進行文件權限檢查,如果沒有權限,則打印出錯信息,然后退出。然后再使用system()
函數執行/bin/cat fileinput
這個命令。
access()
的手冊,access() checks whether the calling process can access the file pathname. If **pathname** is a symbolic link, it is dereferenced.
這就意味著我們不能利用符號鏈接
來過這個權限檢查。
從gdb
的反匯編代碼,我們可以得到,程序使用輸入的命令行參數構造了/bin/cat argv[1]
這個字符串,然后送入system()
這個函數執行。于是我猜想到構造這么一個字符串/bin/cat < /etc/leviathan_pass/leviathan2
。這樣就可以通過權限檢查,然后得到密碼了。
<file
file->/etc/leviathan_pass/leviathan2
這樣,系統進行權限檢查的時候,則檢查的是<file
這個文件的權限,但是執行命令的時候卻是/bin/cat < file
這個命令。
還是一個set-uid
程序,老流程走起,打開程序,看看它是那個小怪。
還是要gdb
走起啊。
這里的strcmp()
函數為什么調用我沒有理解,或許是為了干擾吧,在main()
函數中有一個do_stuff()
函數調用,整個程序的邏輯應該在這個函數里面。
可以看到,在do_stuff()
函數中有strcmp()
和system()
等比較,strcmp()
的其中一個實參來自于fgets()
函數的返回結果,另一個參數存儲在-0x117(%ebp)
,從圖中可以看出來,存儲在-0x117(%ebp)
的參數就是待匹配的密碼。
將密碼輸入到程序中,就可以得到一個shell,進而得到下一個level的密碼。
好吧,這一個level的文件在.trash
文件夾中了,依舊是熟悉的流程。
從程序輸出看,應該是密碼被轉換成二進制輸出了,或者是加密之后轉換成二進制輸出,這個還是得要祭起gdb
神器來幫忙了。
從這個循環過程中,我們可以看到,程序對密碼的每個字符,從最高位(符號位)開始計算,每次輸出一個字符0
或者字符1
,所以可以得到,該bin
程序是將密文的每個字符轉換成二進制格式輸出。單步調試的時候,程序在調用fopen("/etc/leviathan_pass/leviathan5", "r")
的時候返回錯誤,導致調試無法進行。看來,直接查看內存獲得密碼的方法是行不通了,只能寫腳本,處理程序的輸出了。
#!python
#!/usr/bin/env python
#coding=utf-8
if __name__ == "__main__":
try:
fp = open("log.txt", "r")
except:
print "file open error"
for i in range(12):
byte = fp.read(9).strip()
value = (int(byte, 2)) & 0xFF
#print value
char = chr(value)
print char,
python
代碼寫得不是一丁點的丑,實在是因為用得不多!
把密碼中的空格剔除就是正確的密碼了。
還是熟悉的流程,熟悉的味道。
似乎/tmp/file.log
這個路徑被硬編碼到了程序中了,還是要看看這個程序到底做了什么事情。
確實是被硬編碼到了程序中去了,嘗試著在該路徑下建立一個指向密碼文件的符號鏈接文件,發現居然成功了。
好吧,這一個level實在是有點開玩笑啊。。。。
哈哈,這個level似乎有不一樣的味道,雖然還是熟悉的流程。
這里,這個set-uid
程序需要輸入一個4 digit code
,懶得再去用gdb
反匯編了,我估計也不太好反,做了混淆應該。干脆就來個爆破吧。
#!python
#!/usr/bin/env python
#coding=utf-8
import os
for pincode in range(10000):
cmd = "~/leviathan6 %04d" %(pincode)
# for debug
#print "test %s" %(cmd)
ret = os.popen(cmd).read()
if ret.find("Wrong") == -1:
print "maybe success in %s" %(cmd)
程序在7123
那里停止了,我猜想是跑到了shell
里面去了。嘗試了一下,果然是這樣的。
ssh
登陸到level 7
好吧,我純粹是為了混一個邀請碼,才寫這個writeup
的。要不然我肯定遵守這個規則!
Bingo!這個wargame
就這樣結束了,題目確實挺簡單的,完全是為了新手學習,知道怎么玩wargames
。
更多關于wargames
的信息,請參考這里!