# Write-up picoCTF - droids ## droids 0 ![image](https://hackmd.io/_uploads/BkAZh1NBbe.png) Xem source code bằng `jadx`. ![image](https://hackmd.io/_uploads/B1Ih2y4rZg.png) `Log.i("PICO", paprika(input))` in kết quả của paprika(input) ra logcat. ```java public void buttonClick(View view) { String content = this.text_input.getText().toString(); this.text_bottom.setText(FlagstaffHill.getFlag(content, this.ctx)); } ``` Nhấn button trong `MainActivity` sẽ in ra flag trong log. Mở logcat ra để xem dùng lệnh: `adb logcat`. ![image](https://hackmd.io/_uploads/ByngAJ4rbe.png) ## droids 1 ![image](https://hackmd.io/_uploads/SynbAkNSWx.png) Decomplie file bằng `apktool` rồi tìm password ở `res/values/strings.xml`. ![image](https://hackmd.io/_uploads/ByerRJEr-x.png) ![image](https://hackmd.io/_uploads/SyNHAyErWe.png) ## droids 2 ![image](https://hackmd.io/_uploads/HJSLAJVBZe.png) ![image](https://hackmd.io/_uploads/B1zw0kNBWx.png) `FlagstaffHill` xử lý password bằng logic đơn giản. ```python def solve_password(): witches = ["weatherwax", "ogg", "garlick", "nitt", "aching", "dismass"] second = 3 - 3 third = (3 // 3) + second fourth = (third + third) - second fifth = 3 + fourth sixth = (fifth + second) - third indices = [fifth, third, second, sixth, 3, fourth] password = ".".join([witches[i] for i in indices]) print(f"{password}") if __name__ == "__main__": solve_password() ``` ![image](https://hackmd.io/_uploads/r1UGJgErbx.png) ## droids 3 ![image](https://hackmd.io/_uploads/H1ZE1e4rZe.png) ![image](https://hackmd.io/_uploads/SJr8kgNrZg.png) Trong `FlagstaffHill` hàm `yep()` xử lý input nhưng không được gọi. Nơi xử lý logic password là `native` cụ thể là hàm `cilantro()`. Decomplie file bằng `apktool`. Mở `lib/x86/libhellojni.so` bằng IDA hoặc ghidra. ![image](https://hackmd.io/_uploads/SJx16gl4Bbx.png) `dill(v7)` check input nếu input đúng thì gọi `sumac()` để trả flag. ![image](https://hackmd.io/_uploads/SkombxEBbx.png) ![image](https://hackmd.io/_uploads/ryeV-xEBbg.png) ![image](https://hackmd.io/_uploads/HkI4blNHZg.png) ![image](https://hackmd.io/_uploads/H1kSbxNBWg.png) ```python def solve(): #.rodata (unk_1C41) encrypted_data = [ 0x11, 0x0E, 0x02, 0x06, 0x2D, 0x39, 0x2F, 0x08, 0x07, 0x00, 0x1D, 0x49, 0x03, 0x12, 0x15, 0x47, 0x0F, 0x43, 0x1A, 0x10, 0x01, 0x08, 0x1A, 0x04, 0x09, 0x1A ] key = "againmissing" key_bytes = [ord(c) for c in key] key_len = len(key_bytes) flag = "" for i in range(len(encrypted_data)): char_code = encrypted_data[i] ^ key_bytes[i % key_len] flag += chr(char_code) print(f"{flag}") if __name__ == "__main__": solve() #picoCTF{tis.but.a.scratch} ``` ## droids 4 ![image](https://hackmd.io/_uploads/Skg9blNS-e.png) ![image](https://hackmd.io/_uploads/HJLcWgEBZg.png) `FlagstaffHill` cho password là `alphabetsoup` nhưng nhìn về `return` thì nếu nhập đúng password thì nó chỉ trả về `call it`. ![image](https://hackmd.io/_uploads/B1pxMeVr-e.png) Hàm `cardamom()` không được gọi nên làm tương tự câu trên. Mở file `lib/x86/libhellojni.so` bằng IDA. ![image](https://hackmd.io/_uploads/BkopMeNBbx.png) ![image](https://hackmd.io/_uploads/BJsCMx4BWg.png) Reverse ra key của hàm `chervil()` `v6` khởi tạo là `aaa` `v5`, `v4`, `v3` cũng được khởi tạo từ một vùng nhớ cố định (`strdup` sao chép chuỗi từ vùng nhớ gốc sang một vùng nhớ mới heap). Do cả 3 biến `v5`, `v4`, `v3` đều lấy dữ liệu từ cùng một phép tính `offset`, nên chúng đều bắt đầu bằng `aaa`. Cuối cùng cộng các kí tự trong mảng lại sau khi thay đổi logic. ```python def reverse_chervil(): base = "aaa" def shift(s, ops): s = list(s) for idx, val in ops.items(): s[idx] = chr(ord(s[idx]) + val) return "".join(s) v6 = shift(base, {0: 4, 1: 19, 2: 18}) # ets v5 = shift(base, {0: 7, 2: 1}) # hab v4 = shift(base, {1: 11, 2: 15}) # alp v3 = shift(base, {0: 14, 1: 20, 2: 15}) # oup password = v4 + v5 + v6 + v3 return password if __name__ == "__main__": print(reverse_chervil()) #alphabetsoup ``` ![image](https://hackmd.io/_uploads/ryH4Qg4B-g.png) ![image](https://hackmd.io/_uploads/By8kXeNrWx.png) ![image](https://hackmd.io/_uploads/BkVg7xErZg.png) Logic cũng tương tự câu trên nếu `chervil()` check input đúng thì `pepper()` sẽ được gọi và trả flag. ```python def solve_final_flag(): #.rodata:00001C5C encrypted_data = [ 0x11, 0x05, 0x13, 0x07, 0x22, 0x36, 0x23, 0x0F, 0x1D, 0x00, 0x01, 0x5E, 0x11, 0x0D, 0x02, 0x1C, 0x08, 0x01, 0x10, 0x18, 0x12, 0x1D, 0x19, 0x09, 0x4F, 0x1F, 0x19, 0x04, 0x0D, 0x1B, 0x18 ] key = "alphabetsoup" key_bytes = [ord(c) for c in key] key_len = len(key_bytes) flag = "" for i in range(len(encrypted_data)): char_code = encrypted_data[i] ^ key_bytes[i % key_len] flag += chr(char_code) print(f"{flag}") if __name__ == "__main__": solve_final_flag() #picoCTF{not.particularly.silly} ```