總之我終於擊敗惰性開始寫writeup了,去年剛開始接觸資安的時候好像還不知道AIS3,所以這是第一次參加AIS3,總之本來想好好解逆向結果解不出來只有12名,培訓時間還跟我要去日本的時間完美的重疊了,慘。
web1 其實這題在幹嘛我忘記了
web2 $msg = "" ;if (isset ($_POST ["username" ]) and isset ($_POST ["password" ])){ $username = (string )$_POST ["username" ]; $password = (string )$_POST ["password" ]; $success = false ; foreach ($db as $row ) { if ($username == $row ["username" ] and md5 ($password ) == $row ["password" ]) { $msg = "Successful login as $username . Here's your flag: " .$flag ; $success = true ; break ; } } if (!$success ) { $msg = "Invalid username or password." ; } }
這題要求登入一個用php寫得簡單網頁,php做的就是用你的username去找他本來就寫好的一串md5 hash然後把你輸入的password也做md5之後使用 ==
做比較,不難發現是php弱比較的利用,仔細看就會發現有一個md5 hash是 0e
開頭,把對應的username還有 QNKCDZO
當作密碼就會拿到flag了。
web3 這題根本是從eduCTF拿過來再利用吧哈哈哈 總之是LFI(local file inclusion)的漏洞,flag在哪我失憶了。
web4 這題也有LFI的漏洞,不過靠LFI把index.php拉出來會發現他把一個upload的功能隱藏起來,從網址進去之後會發現它是一個只能上傳jpg圖片的功能,然後會告訴你上傳之後亂數產生的檔名,但是只是單純過濾副檔名,所以用phar搭配LFI的漏洞可以做出web shell,再來就只是拿flag而已。
Pwn1 這題你輸入什麼他就直接跳到那裡執行這樣,有個function叫做youcanseeme,跳過去執行就好了,值得注意的是因為scanf吃到空白會停止,而剛好function的開頭位址會讓scnaf只吃到一半,所以要往後跳一點。
Pwn2 用C++寫的一支程式,雖然是PE檔案格式,結果這題連分析也不用就知道要怎樣做了,關鍵在
struct user { char name[20 ]; int pass; } ais3_user;
因為C++中這種struct的記憶體會連在一起,所以輸入name的時候多敲幾個把pass壓過去就好了。
Reverse1 直接執行,中間會產生flag。
Reverse2 這題給了rev2和encrypted兩個檔案,encrypted是被rev2加密的flag ,rev2加密的方式是用srand(time(NULL))之後,然後使用rand()來加密,程式內有顯示這支程式建立的時間是台灣時間 6/26。 因為time(NULL)實際上傳回的是目前的unix timestamp,srand再以此做出亂數表,因此把6/26的unix timestamp開始一直用srand做出亂數表,然後跟encrypted做xor然後檢查是不是flag就好了。
Crypto1 這題的flag被三個數值做xor,不過不需要做出個別值,因為xor之後完全沒有差別,因為知道flag是AIS3開頭,所以把xor的值解出來後把剩下的部分也xor出來就好了
#include <stdio.h> #include <string.h> int main () { int val1 = ?????????, val2 = ?????????, val3 = ???????, val4 = ??????, i, *ptr; char flag[29 ] = "????????????????????????????" ; for (i = 0 , ptr = (int *)flag ; i < 7 ; ++i) printf ("%d\n" , ptr[i] ^ val1 ^ val2 ^ val3 ^ val4); return 0 ; }
Crypto2 因為用了ECB mode ,所以每個區塊間沒有關聯,而且加密用的key也不會換,造成cut & paste attack。
Crypto3 & Crypto4 sha1 collision,這兩題滿有趣的。 在做比較的時候使用的是 ===
而不是 ==
所以不能用陣列的方法繞過,因此就是利用google在2月時找到的sha1碰撞,把兩個文件作為username還有password傳入。 Crypto4 則是利用string() parse的時候會被\00
截斷,加入題目要求的字串,而最後一個條件則是sha1的結果開頭要是f00d
,只要在文件後面加入一堆\00
,結果就會不一樣,所以就寫個腳本自動檢查就好了。
<?php include ("flag.php" );if (isset ($_GET ["source" ])) { show_source (__FILE__ ); exit (); } function startsWith ($haystack , $needle ) { $length = strlen ($needle ); return (substr ($haystack , 0 , $length ) === $needle ); } if (isset ($_POST ["username" ]) and isset ($_POST ["password" ])){ $username = (string )$_POST ["username" ]; $password = (string )$_POST ["password" ]; $h1 = sha1 ($username ); $h2 = sha1 ($password ); if ($username == $password ) { $msg = "Your password can not be your username." ; } else if ($h1 === $h2 ) { $msg = "Flag1: $flag1 " ; if (strpos ($username , "Snoopy_do_not_like_cats_hahahaha" ) !== false and strpos ($password , "ddaa_is_PHD" ) !== false and startsWith ($h1 , "f00d" )) { $msg .= "</br>" ; $msg .= "Flag2: $flag2 " ; } } else { $msg = "Invalid password." ; } } ?>
MISC2 就只顯示了I've sent you something :)
,網頁註解裡面有一個img的tag <img src='sudoku.png'>
,把註解拿開後會顯示一張數獨的圖片: 然後我以為這題是steganography,結果跟原圖根本就連一bit都沒差別啊。 用curl看header才會發現:
decode後就會得到S74G32.php
,進去後會看到一張png:
總之我的膝蓋告訴我flag一定在白色的地方,因為他九成是png:
MISC4 這題要ssh到一台主機,然後權限很低,flag就在眼前但是不能cat。 有三個檔案flag、shell、shell.c,shell.c長這樣:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> int filter(char* cmd){ int r=0; r += strstr(cmd, "=")!=0; r += strstr(cmd, "PATH")!=0; r += strstr(cmd, "export")!=0; r += strstr(cmd, "/")!=0; r += strstr(cmd, "\\")!=0; r += strstr(cmd, "`")!=0; r += strstr(cmd, "flag")!=0; return r; } extern char** environ; void delete_env(){ char** p; for(p=environ; *p; p++) memset(*p, 0, strlen(*p)); } int main(int argc, char* argv[], char** envp){ setregid(getegid(), -1); if(argc < 2) { return 0; } delete_env(); putenv("PATH=/this_is_not_a_valid_path"); if(filter(argv[1])) return 0; printf("%s\n", argv[1]); system( argv[1] ); return 0; }
總之只能用sh內建的指令echo跟pwd啥的,加上一些神奇的東西就變成: