
特定のWindows APIを異なるAPIで難読化する
静的/動的解析ツールからPEインポートを難読化(隠蔽)します。
これは非常に単純です。例えば、VirtualProtect を使用していて、それを Sleep で難読化したいとします。ツールはIATを操作して、VirtualProtect を指すサンクが代わりに Sleep を指すようにします。ファイルの実行時に、Windowsローダーは VirtualProtect の代わりに Sleep をロードし、実行をエントリポイントに移します。そこから実行はシェルコードにリダイレクトされ、ツールが事前に配置したシェルコードが VirtualProtect のアドレスを見つけ、ローダーが以前に割り当てた Sleep のアドレスを置き換えるために使用します。
#include <cobf.hpp>
int main() {
cobf obf_file = cobf("sample.exe");
obf_file.load_pe();
obf_file.obf_sym("kernel32.dll", "SetLastError", "Beep");
obf_file.obf_sym("kernel32.dll", "GetLastError", "GetACP");
obf_file.generate("sample_obfuscated.exe");
obf_file.unload_pe();
return 0;
};
config.ini)を指定します。cobf.exe <input file> <out file> [config file]; Template for the config file:
; * Sections can be written as:
; [dll_name]
; old_sym=new_sym
; * The dll name is case insensitive, but
; the old and the new symbols are not.
; * You can use the wildcard on both the
; dll name and the old symbol.
; * You can use '#' at the start of
; the old or the new symbol to flag
; an ordinal.
; * The new symbol should be exported
; by the dll so the windows loader can resolve it.
; For example:
; * Obfuscating all of the symbols
; imported from user32.dll with ordinal 1600.
[user32.dll]
*=#1600
; * Obfuscating symbols imported from both
; kernel32.dll and kernelbase.dll with Sleep.
[kernel*.dll]
*=Sleep
; * Obfuscating fprintf with exit.
[*]
fprintf=exit
このコードサンプルをビルドします
#include <windows.h>
#include <stdio.h>
int main() {
SetLastError(5);
printf("Last error is %d\n", GetLastError());
return 0;
};
ビルド後、kernel32のインポートは以下のようになります

では、SetLastError と GetLastError の両方を Beep と GetACP で難読化しましょう(実際にはkernel32の任意のAPIで問題ありません。まったくインポートされていなくても構いません)。
使用した設定は以下の通りです
[kernel32.dll]
SetLastError=Beep
GetLastError=GetACP
以下が出力です(上記のようにライブラリを直接使用することもできます)。

再度kernel32のインポートを見てみましょう

SetLastError や GetLastError は存在しません
2つのファイルが正常に動作することを確認します

IDA HexRays Decompiler

IDA Debugger

Ghidra

ApiMonitor

これは、すべての静的解析ツールがIATに記述されたAPI名に依存しているためであり、示したように操作可能だからです。
ApiMonitorの場合、IATフッキングを使用しているため、同じ問題が存在します。
一方、x64dbgのようなツールでは、表示されるAPI名は実際に呼び出されているものにのみ依存します(IATに書かれているものではありません)。

.cobf という名前の新しいRWXセクションを作成します。git clone https://github.com/d35ha/CallObfuscator で取得してください。