# Write-up picoCTF - droids
## droids 0

Xem source code bằng `jadx`.

`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`.

## droids 1

Decomplie file bằng `apktool` rồi tìm password ở `res/values/strings.xml`.


## droids 2


`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()
```

## droids 3


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.

`dill(v7)` check input nếu input đúng thì gọi `sumac()` để trả flag.




```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


`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`.

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.


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
```



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}
```