windows 混淆外部 API 调用 C++

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6642980/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 17:23:06  来源:igfitidea点击:

Obfuscate External API Calls C++

c++windowswinapi

提问by Mudasir Khan

I have a code in C++ that calls functions from external library. The function I called is CreateProcesslike below.

我有一个 C++ 代码,它调用外部库中的函数。我调用的函数是CreateProcess,如下所示。

CreateProcess(NULL,pProcessName,NULL,NULL,false,CREATE_SUSPENDED,
      NULL,NULL,&suStartUpInformation,&piProcessInformation)

Now when I compile the code and dissemble it, the assembly shows the plain text as CreateProcess(args1, args2, ...). Is there any way to obfuscate or encrypt the function call to API so that if someone dissembles it then he won't ever know which functions are called.

现在,当我编译代码并对其进行反汇编时,程序集将纯文本显示为CreateProcess(args1, args2, ...)。有什么方法可以混淆或加密对 API 的函数调用,以便如果有人对其进行了反汇编,那么他将永远不知道调用了哪些函数。

Thanks!

谢谢!

回答by Necrolis

Any function that is imported by name will always have the name embedded into the binary (in the import descriptor thunk to be exact), the detailed parameter info is gotten from the pdbs as Steve mentioned (however analysing debuggers like ollydbg can deduce args, due to the symbol name being available). The only ways to avoid this is to either encrypt to IAT (using 3rd party packers/virtualizers/binary protection systems etc, like enigma) or use a custom version of GetModuleHandle(basically just a PEB spelunking tool) and GetProcAddress(a PE spelunking tool this time), then by storing all the api calls you need as runtime encrypted strings, you can then call whatever you need without plain text giving you away (securerom does this, though it uses GetProcAddressdirectly, along with some binary obfuscation).

任何按名称导入的函数都将始终将名称嵌入到二进制文件中(确切地说是在导入描述符 thunk 中),详细的参数信息是从 pdbs 中获取的,正如史蒂夫提到的(但是,分析像 ollydbg 这样的调试器可以推断出 args,由于到可用的符号名称)。避免这种情况的唯一方法是加密到 IAT(使用 3rd 方加壳器/虚拟化器/二进制保护系统等,例如 enigma)或使用自定义版本GetModuleHandle(基本上只是一个 PEB 探索工具)和GetProcAddress(这次是一个 PE 探索工具) ),然后通过将您需要的所有 api 调用存储为运行时加密字符串,然后您可以调用您需要的任何内容,而不会泄露纯文本(securerom 会这样做,尽管它GetProcAddress直接使用,以及一些二进制混淆)。

Update:

更新:

for compile-time 'obfuscated' strings, you can use something like this (really simple, but it should be portable, if you use C++0x, this is a lot easier):

对于编译时“混淆”字符串,您可以使用这样的东西(真的很简单,但它应该是可移植的,如果您使用 C++0x,这会容易得多):

#define c(x) char((x) - 1) //really simple, complexity is up to the coder
#define un(x) char((x) + 1)

typedef int (WINAPI* MSGBOX)(HWND, LPCSTR, LPCSTR, UINT);
const int ORD_MASK = 0x10101010;    
const char szMessageBoxA[] = {c('M'),c('e'),c('s'),c('s'),c('a'),c('g'),c('e'),c('B'),c('o'),c('x'),c('A')};


FARPROC GetProcAddressEncrypted(HMODULE hModule, const char* szName, BOOL bOrd = FALSE)
{
    if(bOrd)
        return GetProcAddress(hModule,reinterpret_cast<const char*>(reinterpret_cast<int>(szName) ^ ORD_MASK)); //this requires that ordinals be stored as ordinal ^ ORD_MASK

    char szFunc[128] = {'
//Ok here you can see.
//I am passing DLL name(user32.dll) and DLL function(MessageBoxA) as String
//So I can also perform Encrypt & Decrypt operation on Strings and obfuscate it. 
//Like i can encrypt the string "user32.dll" and at runtime decrypt it and pass it as 
//an argument to "LoadLibraryA" and same for the Function name "MessageBoxA".
//The code is compiled in DevC++ 4.9.9.2.

#include <windows.h>
#include <iostream>
using namespace std;

void HelloWorld()
{
        char* szMessage = "Hello World!";
        char* szCaption = "Hello!";
        HMODULE hModule         = LoadLibraryA( "user32.dll" );
        FARPROC fFuncProc       = GetProcAddress( hModule, "MessageBoxA" );
        ( ( int ( WINAPI *)( HWND, LPCSTR, LPCSTR, UINT ) ) fFuncProc )( 0, szMessage, szCaption, 0 );
}
int main()
{
    HelloWorld();
}
'}; for(int i = 0; *szName; i++) szFunc[i] = uc(*szName++); return GetProcAddress(hModule,szName); } MSGBOX pfMsgBox = static_cast<MSGBOX>(GetProcAddressEncrypted(GetHandleEncrypted(szUser32),szMessageBox));

Optionally you may want to use MSVC's EncodePointerto hide the values in the global function pointers (just remember to use DecodePointerwhen you call them).

或者,您可能希望使用 MSVCEncodePointer来隐藏全局函数指针中的值(请记住DecodePointer在调用它们时使用)。

note: code is untested, as its just off the top of my head

注意:代码未经测试,因为它就在我的头顶上

回答by ysdx

You might use dynamic linking. In Windows, use LoadLibrary, LoadLibraryEx, GetProcAddress. Now in you code, include some form in obfuscated form of name instead of the real lib/symbol names and unofuscate it at runtime.

您可能会使用动态链接。在 Windows 中,使用 LoadLibrary、LoadLibraryEx、GetProcAddress。现在,在您的代码中,以混淆的名称形式包含一些形式,而不是真正的 lib/符号名称,并在运行时对其进行混淆。

You might want to use dynamic dispatch (function pointers) so that the function called cannot be deduced easily from the code.

您可能希望使用动态分派(函数指针),以便无法从代码中轻松推断出被调用的函数。

You might delegate the work of calling this function to another thread (using some IPC mechanism).

您可以将调用此函数的工作委托给另一个线程(使用某些 IPC 机制)。

But it's quite useless, using a debugger it will very simple to find that this function has been called. And it will be very simple to detect that a process has been created.

但是它很没用,使用调试器很容易发现这个函数被调用了。并且很容易检测到一个进程已经被创建。

回答by Mudasir Khan

Ok! here is the solution. Lets say I want to call "MessageBoxA" from "user32.dll". So here is how I will do it using LoadLibraryA& GetProcAddress.

好的!这是解决方案。假设我想从“user32.dll”调用“MessageBoxA”。所以这里是我将如何使用LoadLibraryAGetProcAddress来做到这一点。

##代码##