AIS3 pre-exam Writeup(2021) === 排名:152 Scoreboard:https://drive.google.com/file/d/1v-5ag_sQdVHTxWPLj-7hM-akwcJ-prdq/view?usp=sharing Welcome --- #### Cat Slayer ᶠᵃᵏᵉ | Nekogoroshi 手動爆破 pwd = 2025830455298 flag:AIS3{H1n4m1z4w4_Sh0k0gun} Misc --- #### Microcheese (這題是結束後解出來的) ```python= if choice == '0': pile = int(input('which pile do you choose? ')) count = int(input('how many stones do you remove? ')) if not game.make_move(pile, count): print_error('that is not a valid move!') continue elif choice == '1': game_str = game.save() digest = hash.hexdigest(game_str.encode()) print('you game has been saved! here is your saved game:') print(game_str + ':' + digest) return elif choice == '2': break ``` 可以發現選擇0,1,2以外的選項就可以只讓電腦拿走石頭 等到最後我們再把最後一顆石頭拿走就可以拿到flag了 不知道為什麼,我在賽中進到遊戲時第一步選3會出現 ``` oops i died ``` 然後程式就停止了 賽後發現要先正常的走一步(選0) 之後選3就可以正常跳過了 ![](https://i.imgur.com/zjKmAg0.png) 可以發現 程式印出了 ``` you removed 1 stones from pile 0 ``` 但pile 0的石頭數量卻沒有減少 反覆操作 當只剩一堆有石頭時 出手把石頭拿完就贏了 ![](https://i.imgur.com/ilVhvyB.png) 由於印出flag的函數是作者寫的 因此在本機無法印出flag #### blind (結束後看writeup解出) ```c= #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/syscall.h> int syscall_black_list[] = {}; void make_a_syscall() { unsigned long long rax, rdi, rsi, rdx; scanf("%llu %llu %llu %llu", &rax, &rdi, &rsi, &rdx); syscall(rax, rdi, rsi, rdx); } int main() { setvbuf(stdin, 0, 2, 0); setvbuf(stdout, 0, 2, 0); puts("You can call a system call, then I will open the flag for you."); puts("Input: [rax] [rdi] [rsi] [rdx]"); close(1); make_a_syscall(); int fd = open("flag", O_RDONLY); char flag[0x100]; size_t flag_len = read(fd, flag, 0xff); write(1, flag, flag_len); return 0; } ``` 可以看到他用close(1); 把stdout關掉 導致flag印不出來 只要想辦法把stdout改成1就可以拿到flag 可以透過dup2(2,1)把stderr的fd(File Descriptor)複製給stdout 讓它的值變成1就可以拿到flag 對照syscall table可知輸入33 2 1 0可以拿到flag 參考資料 https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md https://stackoverflow.com/a/58890557 Crypto --- #### microchip 明文和密文的長度一樣 每4個字一組 彼此互不影響 又知key[i]<96 flag前四位是AIS3 所以可以算key 然後逆著解回去就好了 程式碼如下 ```python= cipher = "&sJ=`A*;HZdoD>'i&sJ=D-i#U>fYuy'yuyfyuG)<" key = [ 69 , 42 , 87, 10 ] token=0 idx=0 flag="" for i in cipher: token=int(token) idx=int(idx) token = idx % 4 i = ord( i ) - 32 i=int(i) if( i - key[token] < 0 ): i+=96 i-=key[token] i += 32 flag = flag + chr(i) idx += 1 print(flag) ``` flag: AIS3{w31c0me_t0_AIS3_cryptoO0O0o0Ooo0} Reverse --- #### piano 反組譯piano.dll後拿到(出來的程式碼大約200多行 這邊只列出關鍵的部分) ``` private bool isValid() { List<int> list = new List<int> { 14, 17, 20, 21, 22, 21, 19, 18, 12, 6, 11, 16, 15, 14 }; List<int> list2 = new List<int> { 0, -3, 0, -1, 0, 1, 1, 0, 6, 0, -5, 0, 1, 0 }; for (int i = 0; i < 14; i++) { if (notes[i] + notes[(i + 1) % 14] != list[i]) { return false; } if (notes[i] - notes[(i + 1) % 14] != list2[i]) { return false; } } return true; } ``` 解個方程式後會拿到幾個數字 打開piano.exe後用正確的順序彈就過了 flag: AIS3{7wink1e_tw1nkl3_l1ttl3_574r_1n_C_5h4rp} #### 🐰 Peekora 🥒 結束後看writeup解出 用 ``` python3 -m pickletools -a flag_checker.pkl ``` 可以disassemble題目給的.pkl檔案 MARK 做標記 GET 把東西push到stack上 REDUCE 很像是搞成一個function PUT 從stack上拿東西 但不會pop 然後硬讀 ``` MARK Push markobject onto the stack. 708: g GET 1 Read an object from the memo and push it on the stack. 711: ( MARK Push markobject onto the stack. 712: g GET 4 Read an object from the memo and push it on the stack. 715: S STRING '__eq__' Push a Python string object. 725: t TUPLE (MARK at 711) Build a tuple out of the topmost stack slice, after markobject. 726: R REDUCE Push an object built from a callable and an argument tuple. 727: ( MARK Push markobject onto the stack. 728: g GET 1 Read an object from the memo and push it on the stack. 731: ( MARK Push markobject onto the stack. 732: g GET 0 Read an object from the memo and push it on the stack. 735: S STRING '__getitem__' Push a Python string object. 750: t TUPLE (MARK at 731) Build a tuple out of the topmost stack slice, after markobject. 751: R REDUCE Push an object built from a callable and an argument tuple. 752: ( MARK Push markobject onto the stack. 753: I INT 13 Push an integer or bool. 757: t TUPLE (MARK at 752) Build a tuple out of the topmost stack slice, after markobject. 758: R REDUCE Push an object built from a callable and an argument tuple. 759: t TUPLE (MARK at 727) Build a tuple out of the topmost stack slice, after markobject. 760: R REDUCE Push an object built from a callable and an argument tuple. 761: t TUPLE (MARK at 707) Build a tuple out of the topmost stack slice, after markobject. 762: R REDUCE //memo4 == imput[1] == input[13] ``` ``` MARK Push markobject onto the stack. 523: g GET 1 Read an object from the memo and push it on the stack. 526: ( MARK Push markobject onto the stack. 527: g GET 1 Read an object from the memo and push it on the stack. 530: ( MARK Push markobject onto the stack. 531: g GET 0 Read an object from the memo and push it on the stack. 534: S STRING '__getitem__' Push a Python string object. 549: t TUPLE (MARK at 530) Build a tuple out of the topmost stack slice, after markobject. 550: R REDUCE Push an object built from a callable and an argument tuple. 551: ( MARK Push markobject onto the stack. 552: I INT 5 Push an integer or bool. 555: t TUPLE (MARK at 551) Build a tuple out of the topmost stack slice, after markobject. 556: R REDUCE Push an object built from a callable and an argument tuple. 557: S STRING '__eq__' Push a Python string object. 567: t TUPLE (MARK at 526) Build a tuple out of the topmost stack slice, after markobject. 568: R REDUCE Push an object built from a callable and an argument tuple. 569: ( MARK Push markobject onto the stack. 570: V UNICODE 'd' Push a Python Unicode string object. 573: t TUPLE (MARK at 569) Build a tuple out of the topmost stack slice, after markobject. 574: R REDUCE Push an object built from a callable and an argument tuple. 575: t TUPLE (MARK at 522) Build a tuple out of the topmost stack slice, after markobject. 576: R REDUCE Push an object built from a callable and an argument tuple. 577: ( MARK Push markobject onto the stack. 578: t TUPLE (MARK at 577) Build a tuple out of the topmost stack slice, after markobject. 579: R REDUCE //input[5] == 'd' ``` 讀完得到flag AIS3{dAmwjzphIj}