---
tags: CS 2022 Fall, 程式安全
author: Ching367436
---
# [0x05] Reverse II
slide: https://drive.google.com/drive/folders/1ZC6mdxIzcLsnGJ7j8S4emGsiY_LRNlKt?usp=sharing
lecture: https://youtu.be/1EAV4XeQ8C4
<style>
img {
box-shadow: 0px 0px 15px #000;
}
</style>
### [LAB] AMessageBox

點開發現會輸入 flag 會跑出 `messageBox`
#### 下斷點
來到 `x64dbg > Symbols > user32.dll`

把跟 `messageBox` 有關的地方先放斷點

看到停在一個神奇的地方
繼續執行
撞到斷點

那是 `messageBoxA`
#### `Call Stack`
來追 `Call Stack`

來到 `amessagebox_904ac0c699abc2f6.00F3110B`
#### `amessagebox_904ac0c699abc2f6.00F3110B`

看到 `call AMessageBox` 的上面可以看到確認 `flag` 的比較

會把輸入的 `flag` 操作後跟 `flag_enc` 比較
所以只要把 `flag_enc` 拉出來
進行反操作就可以得到原本的 `flag`

#### `solve`
##### `AMessageBox/exp.py`
```python
# xor 87
dump = bytearray([x ^ 0x87 for x in dump])
# rol 3
dump = bytearray([rotate_right(x, 3) for x in dump])
print(dump)
# bytearray(b'FLAG{8699314d319802ef792b7babac9da58a}\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0')
```
### [LAB] IAT Hook
#### `main`

先由 `:20` 知道 `flag` 長度可能是 $26$
進入 `:17`
#### `sub_7FF6EE5E1AC0`

看到 `:8` 對 `ModuleName` 做了一些事情
然後 `GetModuleHandleA(ModuleName)`
`:8` 可能是對 `ModuleName` 解密
#### `:8`
修好可以發現真的是解密

這邊直接動態分析

<!--  -->
發現 `ModuleName` 是 `kernel32.dll`
之後從 `x64dbg` 觀察 `:9` `GetProcAddres` 的第二個 `argument`
看到是 `GetProcAddres`

從 `ida` 也可以看到一樣的事

所以 `:9` 的回傳值會是 `GetProcAddres` 的地址

`GetProcAddres_0` 之後也會繼續被呼叫

`:10` 是 `GetModuleHandleA`


`:11` 是 `VirtualProtect`

`:12` 是 `user32.dll`

最後是 `MessageBoxA`
回到 `main`
#### `main`
<!--  -->

然後進 `:25`
#### `:25`

看到 `MessageBoxA` 被換成 `sub_7FF6DE9913A2` 了
更名為 `myMsgBx`
進去看看
#### `myMsgBx`

整理一下看到檢查 `flag` 的邏輯
只要把 `flag_enc` 多 `encrypt` 一次就會得到原本的 `flag`
##### `IAT Hook/solve.cpp`
```cpp
int main ()
{
char aWrong[10] = "Wrong\0";
int key_len = strlen(aWrong);
encrypt(flag_enc, aWrong, 0x1Au, key_len);
for (int j = 0; j < 26; ++j )
{
cout << flag_enc[j];
}
// output: FLAG{IAT_HoOk,MessageBoxA}
}
```
### [LAB] GetProcAddress
#### `main`

看到 `:24` 猜測 `flag` 長度為 39
直接來動態分析
發現如果用 `ARM Windows` 跑會在 `:25` 出錯
所以換用 `x86_64`
發現可以正常跑

把 `flag_enc` `key` 拉出啦解密看看
##### `GetProcAddress/sol.cpp`
```cpp
for (int j = 0; j < 39; ++j)
{
cout << (char)(key[j] ^ flag_enc[8 * j]);
}
// output: FLAG{Just_a_customized_GetProcAddress!}
```
### [HW] ooxx
先試著用用看
覺得他應該是要我們下贏

結果發現遊戲有 `bug`
#### `WinMain`

`:10,13` 看起來像是畫線
https://learn.microsoft.com/en-us/windows/win32/gdiplus/-gdiplus-drawing-a-line-use
叫他 `drawLine`
到跑到 `:17` 的時候會出現一個視窗
先叫他 `showWindow`
#### `showWindow`
看起來是 `Windows GDI`


看到不斷地於 `:32,36` 徘徊
https://learn.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues
回到 `WinMain`
觀察 `argument` 可以猜測出一些事情
經過猜測可以得到以下結果

下斷點於 `eventListener`
發現下期的時候會碰到斷點
所以是 `eventListener` 沒錯

#### `eventListener`

進入 `:9` `dword_7FF62374D338`

看到棋盤了
`2` 代表 `x`
`1` 代表 `o`
`0` 代表 空著

打開 `Hex View` 把棋盤第二行的第一個改成 `1 (o)`

然後按下棋盤的第二排第三個
那樣就可以拿下第二行


贏了!
```
FLAG{Y0u_Won_A_gaM3_yoU_cOuldn0T_pO5s16ly_w1n}
```
### [HW] trojan
#### `WinMain`

點進 `:8` `127.0.0.1`
#### `127.0.0.1`
來到了 `.rdata`
看到了很像密碼的東西

進入很像密碼的東西的 `xrefs`
#### `sub_140001560`

#### `:20`
`:20` 進去修一修可以看出是 `encrypt`

回去上一層
進入 `:13`
#### `:13`

繼續進去

進入 `:8`

看到是比較兩個參數
所以知道 `:13` 是 `check_not_equal`
回到 `:13` 的上一層

先把這個 func 命名為 `send_and_recv_enc_msg`
決定先來看看 `log_65a0163d1ae2e798.pcapng`
#### `log_65a0163d1ae2e798.pcapng`

看到了跟 `send_and_recv_enc_msg:12` 中一樣的字串
`send_and_recv_enc_msg:13,15` 的地方則是確認收到的訊息是否跟 `cDqr0hUUz1` 一樣
如果一樣會繼續執行下面的內容:
先把 `len (4 bytes)` 送給對方
這對應到了下圖畫起來的部分

`0x00025980`
接著會先把 `msg` 加密然後送出
就試著把 `log_65a0163d1ae2e798.pcapng` 的東西解密看看吧
先檢查一下 dump 出來的資料 `size`
```sh
Dump size: 153984
```
對應到了上面的 `len (0x00025980)`
所以正確
試著解密
因為是使用 `xor` 加密
所以在加密一次就是解密
##### `trojan/sol.py`
```python
with open("result.png", "wb") as f:
f.write(encrypt(dump))
```
#### `result.png`

```
FLAG{r3v3R53_cPp_15_pAInfUl}
```