一、什么是動態API
在C2免殺領域中,“動態API” 主要指的是繞過靜態檢測的一種技術手段,其本質是運行時動態解析和調用Windows API函數,而不是在程序編譯階段就明確引用這些API。這種方式可以有效躲避靜態分析工具和殺軟的簽名識別。
為什么使用動態API?
靜態殺軟和EDR會掃描程序中是否包含可疑API(比如 CreateRemoteThread
、VirtualAllocEx
、WriteProcessMemory
等),一旦在導入表(IAT)或代碼段中發現這些函數,就可能被標記為惡意。通過動態API調用,這些函數不會直接出現在導入表中,也不會以明文字符串形式出現,提高了免殺能力。
什么是IAT導入表?
在Windows可執行文件(如 .exe
或 .dll
)中,導入表(IAT,Import Address Table) 是PE結構中的一個關鍵部分,它告訴操作系統這個程序運行時需要哪些外部模塊(DLL)和函數(API),并在加載時將它們的地址填入到程序中可調用的位置。一句話定義:IAT 是Windows程序用于調用外部DLL函數的一張“函數地址表”,由操作系統在加載時填充。?
舉個直觀的例子,假設你的程序要使用 Windows 的 MessageBoxA
函數,它位于 user32.dll
中。編譯后 (靜態導入),在PE文件頭的導入表中,會列出DLL名、函數名;加載時操作系統的PE加載器會加載user32.dll,查找MessageBoxA函數的內存地址,并把這個地址寫入到你的程序的IAT表項。然后你的代碼中對MessageBoxA的調用,實際上是跳轉到這個表項。
因此,殺軟和EDR能直接查看IAT,看你的程序調用了哪些函數(如上圖),一旦發現這些敏感API,程序可能立即被標記為惡意; 通過動態API可以繞過IAT暴露。
二、免殺效果展示
這里用C++寫一個簡單的喝水提醒的程序,代碼如下:
#include <windows.h>
#include <iostream>
#include <thread>
#include <chrono>void remindToDrinkWater() {while (true) {// 等待1小時(3600秒)//std::this_thread::sleep_for(std::chrono::hours(1));std::this_thread::sleep_for(std::chrono::seconds(10));// 彈出消息框提醒喝水MessageBoxA(NULL, "該喝水了!", "喝水提醒", MB_OK | MB_ICONINFORMATION);}
}int main() {// 啟動提醒喝水的線程std::thread reminderThread(remindToDrinkWater);// 主線程保持運行reminderThread.join();return 0;
}
運行測試,功能正常
再復制一份,加上動態API解析和調用代碼
#include <windows.h>
#include <thread>
#include <chrono>
#include <iostream>typedef int (WINAPI* MessageBoxAFunc)(HWND, LPCSTR, LPCSTR, UINT);void remindToDrinkWater() {// 獲取 user32.dll 的模塊句柄HMODULE hUser32 = LoadLibraryA("user32.dll");if (!hUser32) {std::cerr << "無法加載 user32.dll" << std::endl;return;}// 動態獲取 MessageBoxA 函數地址MessageBoxAFunc pMessageBoxA = (MessageBoxAFunc)GetProcAddress(hUser32, "MessageBoxA");if (!pMessageBoxA) {std::cerr << "無法獲取 MessageBoxA 函數地址" << std::endl;return;}while (true) {std::this_thread::sleep_for(std::chrono::seconds(10)); // 測試用:每10秒提醒一次pMessageBoxA(NULL, "該喝水了!", "喝水提醒", MB_OK | MB_ICONINFORMATION);}
}int main() {std::thread reminder(remindToDrinkWater);reminder.join(); // 等待線程結束(實際永遠運行)return 0;
}
運行測試,功能正常
將兩個程序均編譯出來
使用StudyPE+對比一下兩者的導入表,發現右邊使用動態API技術的程序比左邊少了user32.dll,所以IAT不可能存在MessageBoxA函數
放到360下檢測
運行測試,正常
三、結尾
免殺效果通常受多方面影響,沒有哪一種技術或者手段能夠通吃,通常需要多種手段結合才能最終實現免殺;其次,實戰中面臨的環境也不一樣,不同的殺軟效果也不一樣,具體問題還需具體分析。本系列文章以技術的實現為主,驗證時講究點到為止,以此表達一項技術的有效性。?