---
tags: CS 2022 Fall, 程式安全
---
# [0x06] Reverse III
slide: https://drive.google.com/drive/folders/1ZC6mdxIzcLsnGJ7j8S4emGsiY_LRNlKt?usp=sharing
lecture: https://youtu.be/4-hgyiCV3ZA
### Exception
#### `main`

跳到 `main` `xrefs`
#### `.pdata`


```cpp
typedef struct _RUNTIME_FUNCTION {
ULONG BeginAddress;
ULONG EndAddress;
ULONG UnwindData;
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
```
來到 `main` 的 `UnwindData` 指的地方
#### `_UNWIND_INFO`
先做好 `SCOPE_RECORD`
<!-- ^r use image base as offset base -->

然後放到 `main` 的 `UnwindData` 的下面

回到 `main_0`
#### `main_0`


看到 2 個處以 0 的地方
那邊會有 `exception`
分別標上 `exception1` `exception2`
可以發現對應到上面 `_UNWIND_INFO` 的`SCOPE_RECORD`
<!-- https://learn.microsoft.com/en-us/cpp/cpp/try-except-statement?view=msvc-170
-->
```c
// win32.h
#define EXCEPTION_EXECUTE_HANDLER 1
#define EXCEPTION_CONTINUE_SEARCH 0
#define EXCEPTION_CONTINUE_EXECUTION -1
```

由以上資料
我們知道 `exception` 發生後會跳到那邊了
來看看 `exception1` 發生後會跳到的位置
#### `exception1` `jumpTarget`

大概就是進行下面這樣的操作
```c
for (int i = 0; i < 38; i++)
{
flag_inp[i] ^= key + i;
}
```
至於 `key` 的值我們可以往上看
於 `main` `unwine_info` 的 `_C_specific_handler`

我們了解到了 `key` 會是 `rax`

`rax` 的值則會是 `0xBE`
實際跑起來也確實如此

接著來看 `exception2` 的 `jumpTarget`
#### `exception2` `continue_exec`


做的事情大概像這樣
```c
for (int i = 0; i < 38; i++)
{
flag_inp[i] += key + i;
}
```
其中 `key` 會是 `0xEF`

之後就是正常的執行後面 `IDA` 有成功反編譯出來的的迴圈

所以之後把 `flag_enc` 拉出來解密即可
#### `Exception/sol.cpp`
```cpp
for (int i = 0; i < 38; i++)
{
unsigned char key = 0xEF;
flag_enc[i] -= key + i;
}
for (int i = 0; i < 38; i++)
{
unsigned char key = 0xBE;
flag_enc[i] ^= key + i;
}
// output flag
for (int i = 0; i < 38; i++)
{
cout << flag_enc[i];
}
// output: FLAG{__C_specific_handler_is_hooked:O}
```
<!-- https://learn.microsoft.com/en-us/cpp/cpp/writing-an-exception-filter?view=msvc-170
-->
<!-- https://learn.microsoft.com/en-us/windows/win32/debug/exception-handler-syntax
-->
### [LAB] TLS Callback
從 `IDA` 可以看到城市一開始會有三次的 `TLS Callback`

#### `TlsCalllback1`
這個做的是把 `key` 進行 `funcs` 的操作

#### `TlsCalllback2`
這個做的事把 `funcs[3]` 的東西往左 `rotate`


#### `main`

由於上面的 `TlsCallback`
所以 `main` 裏面用到的 `funcs` `key` 都會跟一開始的不同
只要把 `TlsCallback` 操作後的 `funcs` `key` 拉出來然後就可以解密了

#### `TLS Callback/sol.cpp`
```cpp
for (int i = 0; i < 58; i++)
{
flag_enc[i] -= key[i & 3];
(funcs[i % 3u])(flag_enc[i]);
}
// output
for (int i = 0; i < 58; i++)
{
cout << (unsigned char)flag_enc[i];
}
// output: FLAG{The_first_TLS_callback_function_is_called_two_times!}
```
### [LAB] Meow
#### `main`

由 `:9,10` 可以知道 `flag` 長度可能為 39
進入 `sub_401604`
#### `sub_401604`

看到了一些 `GetProcAddress` 整理一下
之後把 `sub_401604` 命名為 `getProcAddresses`
回到 `main`

進入 `sub_401884`
#### `sub_401884`

進入 `sub_401550`
#### `sub_401550`

已經知道這是把一個 `exe` 解密了
把這個 `exe` 透過動態分析直接取出解密後的樣子
把函式取名為 `decrypt_exe`
回到上一層
#### `sub_401884`
修一修可以看出


`:21` 取得了`自己這個執行檔`的位置
`:22` 把`自己這個執行檔`跑起來 第6個參數 `4` 表示 `CREATE_SUSPENDED`
之後用 `exe` 把 `自己這個執行檔` 記憶體中的東西換掉
所以到了 `:53` 會恢復執行的東西變成 `exe`
回到 `main`

進入 `sub_401723`
#### `sub_401723` `exe`
##### `sub_401723`


##### `exe`

可以看到 `sub_401723:28` 會先把 `flag_inp` 傳給 `exe:19`
然後 `exe:21` 會對 `flag_inp` 做一些事 (`sub_401550`)
然後 `exe:24` 會把 `flag_inp` 回傳給 `sub_401723:32`
來看看 `sub_401550` 對 `flag_inp` 做了什麼事
#### `sub_401550`

很明顯的
這裡做的事加密 `flag_inp`
回到 `main`

進入 `sub_401C37`
#### `sub_401C37`

是很一般的 `check_flag`
所以這裡只要把 `flag_enc` 拉出來
把上面的加密倒過來做就會得到 `flag`
##### `Meow/sol.cpp`
這邊的部分我先把 `encrypt` 的部分複製貼上
然後 `copilot` 會幫忙寫好 `decrypt`
然後把 `check_flag` 的部分複製貼上
然後 `copilot` 會幫忙寫好 `output_flag`
這邊只要呼叫 `output_flag`
出來的就會是答案
```cpp
int main ()
{
output_flag();
// output: FLAG{pr0c355_h0ll0w1ng_4nd_n4m3d_p1p35}
}
```
順帶議題
這題的 `key` 是 `meow` 的 `base64`
### [HW] dropper
#### DIE

看到有被包殼
先解殼
```sh
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2022
UPX 4.0.0 Markus Oberhumer, Laszlo Molnar & John Reiser Oct 28th 2022
File size Ratio Format Name
-------------------- ------ ----------- -----------
39424 <- 16896 42.86% win64/pe dropper_43741eb13c4a767e.exe
Unpacked 1 file.
```
#### `main`


動態分析發現跑道這會跳到其他的地方
來看看是什麼地方

原來跑去 `kernel32.sleep(0x9AEC800)` 了
所以這裡才會跑這麼久
把他 patch 成 `sleep(1)`
往下走到 `00007FF60FE92DC5`
然後觀察一下參數
結果 `flag` 就在裡面 `5: [rsp+20]`
那就直接把 `flag` 拿走咯 ~~

```
5: [rsp+20] 000001D60364D2C0 000001D60364D2C0 "FLAG{H3r3_U_G0_iT_Is_UR_flAg}"
```