技术编程|自动重构Meterpreter绕过杀软·续( 二 )


首先 , 必须为API MessageBoxA定义一个函数指针 。在开始之前 , 让我们分享一个小技巧 , 以帮助那些不熟悉C的人了解C语言中函数指针的语法:
(*
)(arg1, arg2, ...);
如你所见 , 除了星号(*)运算符(因为它是一个函数指针)和括号外 , 它与定义函数的语法相同 。
现在 , 我们需要MessageBox的原型 , 该原型可以从Windows SDK的winuser.h中复制粘贴 , 也可以直接从MSDN复制:int MessageBox(HWNDhWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINTuType);
现在 , 可以使用正确的信息更新上述函数指针语法:int (*_MessageBoxA)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);
MSDN告诉我们 , 此函数由User32.dll导出:

技术编程|自动重构Meterpreter绕过杀软·续
本文插图

因此 , 应用程序必须首先加载此库:HANDLE hUser32 = LoadLibrary("User32.dll");
然后 , 可以最终使用GetProcAddress将正确的地址赋值给上面定义的函数指针:_MessageBoxA fMessageBoxA = (_MessageBoxA) GetProcAddress(hUser32, "MessageBoxA");
从上述代码位置开始 , 必须将原始示例改为调用fMessageBoxA而不是MessageBoxA , 如下所示:#include
typedef int (*_MessageBoxA)(HWNDhWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINTuType);int main(int argc, char** argv) {HANDLE hUser32 = LoadLibraryA("User32.dll");_MessageBoxA fMessageBoxA = (_MessageBoxA) GetProcAddress(hUser32, "MessageBoxA");fMessageBoxA(NULL, "Test", "Something", MB_OK);return 0;}
使用数据类型HWND , LPCTSTR和UINT需要在头文件中包含Windows.h。如预期的那样 , 编译并运行此简单示例会生成一个警报框:

技术编程|自动重构Meterpreter绕过杀软·续
本文插图

最终修改
当然 , 运行strings命令搜索toto.exe仍然会看到字符串User32.dll和MessageBoxA 。因此 , 理想情况下 , 应该对这些字符串进行加密 , 前面文章中提到的简单混淆技巧运用到此处足以绕过杀软的检测 。所以 , 最终的结果是:#include
typedef int (*_MessageBoxA)(HWNDhWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINTuType);int main(int argc, char** argv) {char user32[] = {'U','s','e','r','3','2','.','d','l','l',0};HANDLE hUser32 = LoadLibraryA(user32);char messabox[] = {'M','e','s','s','a','g','e','B','o','x','A',0};_MessageBoxA fMessageBoxA = (_MessageBoxA) GetProcAddress(hUser32, messabox);fMessageBoxA(NULL, "Test", "Something", MB_OK);return 0;}
这次 , 使用strings和rabin2都无法找到该字符串(尽管逆向工程师肯定会找到):?x86_64-w64-mingw32-gcc test.c -o /tmp/toto.exe?strings /tmp/toto.exe | grep MessageBox?rabin2 -zz /tmp/toto.exe | grep MessageBox?
自动化源代码重构
上一篇文章中大篇幅描述的方法同样可以用于重构现在的代码库 , 以便可疑API在运行时加载 , 并从导入表中删除其条目 。为此 , 我们将基于libTooling实现以下工作 。
让我们按以下步骤分解此任务:为前面的原始示例生成抽象语法树 。这是了解如何操纵节点以替换函数调用所必需的 。 使用ASTMatcher在代码库中找到给定API的所有函数调用 。 用另一个函数标识符替换所有调用 。 在每个函数调用之前插入LoadLibrary/GetprocAddressAPI调用 。 检查它是否有效 。 广泛化和混淆所有可疑API 。 MessageBox应用程序的抽象语法树
要查看原始MessageBox应用程序的Clang抽象语法树 , 可以使用以下脚本(根据环境不同需要调整Windows SDK的路径):WIN_INCLUDE="/Users/vladimir/dev/avcleaner"CLANG_PATH="/usr/local/Cellar/llvm/9.0.1"clang -cc1 -ast-dump "$1" -D "_WIN64" -D "_UNICODE" -D "UNICODE" -D "_WINSOCK_DEPRECATED_NO_WARNINGS"\"-I" "$CLANG_PATH/include" \"-I" "$CLANG_PATH" \"-I" "$WIN_INCLUDE/Include/msvc-14.15.26726-include"\"-I" "$WIN_INCLUDE/Include/10.0.17134.0/ucrt" \"-I" "$WIN_INCLUDE/Include/10.0.17134.0/shared" \"-I" "$WIN_INCLUDE/Include/10.0.17134.0/um" \"-I" "$WIN_INCLUDE/Include/10.0.17134.0/winrt" \"-fdeprecated-macro" \"-w" \"-fdebug-compilation-dir"\"-fno-use-cxa-atexit" "-fms-extensions" "-fms-compatibility" \"-fms-compatibility-version=19.15.26726" "-std=c++14" "-fdelayed-template-parsing" "-fobjc-runtime=gcc" "-fcxx-exceptions" "-fexceptions" "-fseh-exceptions" "-fdiagnostics-show-option" "-fcolor-diagnostics" "-x" "c++"


推荐阅读