🦊Back to NiNi's Den

AIS3 pre-exam write up

Word count: 1.4kReading time: 6 min
2017/07/15 Share

總之我終於擊敗惰性開始寫writeup了,去年剛開始接觸資安的時候好像還不知道AIS3,所以這是第一次參加AIS3,總之本來想好好解逆向結果解不出來只有12名,培訓時間還跟我要去日本的時間完美的重疊了,慘。

web1

其實這題在幹嘛我忘記了

web2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$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檔案格式,結果這題連分析也不用就知道要怎樣做了,關鍵在

1
2
3
4
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出來就好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
	#include <stdio.h>
#include <string.h>

int main()
{
int val1 = ?????????, val2 = ?????????, val3 = ???????, val4 = ??????, i, *ptr;
char flag[29] = "????????????????????????????"; // Hint: The flag begins with AIS3

for(i = 0, ptr = (int*)flag ; i < 7 ; ++i)
printf("%d\n", ptr[i] ^ val1 ^ val2 ^ val3 ^ val4);

/*
964600246
1376627084
1208859320
1482862807
1326295511
1181531558
2003814564
*/

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,結果就會不一樣,所以就寫個腳本自動檢查就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?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啥的,加上一些神奇的東西就變成:

Original Author: Terrynini

Original link: http://blog.terrynini.tw/tw/2017-AIS3-pre-exam-write-up/

Publish at: July 15th 2017, 3:22:24

Copyright: This article is licensed under CC BY-NC 4.0

CATALOG
  1. 1. web1
  2. 2. web2
  3. 3. web3
  4. 4. web4
  5. 5. Pwn1
  6. 6. Pwn2
  7. 7. Reverse1
  8. 8. Reverse2
  9. 9. Crypto1
  10. 10. Crypto2
  11. 11. Crypto3 & Crypto4
  12. 12. MISC2
  13. 13. MISC4