c ++将函数的内存归零
c++ zero out memory of a function
我对反射dll注入有一点想法。如果你不知道反射dll注入是什么,你可以在这里查看:https://github.com/stephenfewer/ReflectiveDLLInjection
基本上是将 dll 加载到内存,然后将内存注入目标进程 - 至少那是 afaik 发生的事情。我可能是错的,但这并不重要。
任务
- 查找给定函数的内存地址
- 找到给定函数的大小
- 使用
SecureZeroMemory()
将内存归零
代码
#include "ReflectiveLoader.h"
extern HINSTANCE hAppInstance;
void Function1() { MessageBoxA(NULL, "Function 1 called!", "Test", MB_OK); }
void Function2() { MessageBoxA(NULL, "Function 2 called!", "Test", MB_OK); }
void Function3() { MessageBoxA(NULL, "Function 3 called!", "Test", MB_OK); }
void GetMemoryInformation()
{
void(*p_Func1)() = &Function1;
void(*p_Func2)() = &Function2;
void(*p_Func3)() = &Function3;
char buffer[300];
sprintf(buffer, "Function1 - Address: %p | Size: %zu \nFunction2 - Address: %p | Size: %zu \nFunction3 - Address: %p | Size: %zu",
p_Func1, sizeof(p_Func1),
p_Func2, sizeof(p_Func2),
p_Func3, sizeof(p_Func3)
);
MessageBoxA(NULL, buffer, "Memory information", MB_OK);
}
void ZeroMemoryFunctions()
{
void(*p_Func2)() = &Function2;
void(*p_Func3)() = &Function3;
SecureZeroMemory(p_Func2, sizeof(p_Func2));
SecureZeroMemory(p_Func3, sizeof(p_Func3));
}
DWORD WINAPI MainThread(LPVOID PARAMS)
{
MessageBoxA(NULL, "Main thread initialized!", "Entry", MB_OK);
for (;;)
{
if (GetAsyncKeyState(0x31) & 0x8000) Function1(); // key 1
if (GetAsyncKeyState(0x32) & 0x8000) Function2(); // key 2
if (GetAsyncKeyState(0x33) & 0x8000) Function3(); // key 3
if (GetAsyncKeyState(VK_UP) & 0x8000) GetMemoryInformation();
if (GetAsyncKeyState(VK_DOWN) & 0x8000) ZeroMemoryFunctions();
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) MessageBoxA(NULL, "Main thread closed!", "Exit", MB_OK), ExitThread(0);
Sleep(100);
}
}
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_QUERY_HMODULE:
if( lpReserved != NULL )
*(HMODULE *)lpReserved = hAppInstance;
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
MessageBoxA( NULL, "Reflective Dll injected!", "Injected", MB_OK );
CreateThread(0, 0, &MainThread, 0, 0, 0);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}
它有什么作用?
- 键1到3,调用显示简单消息框的指定函数
- 向上箭头显示一个消息框,其中包含每个函数的函数地址和大小
- 向下箭头将函数
Function2()
和 Function3()
归零
- Escape正常退出主线程
问题
我对内存相关的编码很陌生,所以我很确定我做错了什么。
我认为我以错误的方式获取了函数的大小,而是获取了指向函数的指针的大小,对吗?
其次,如果我调用 ZeroMemoryFunctions()
并按下键 1,它会起作用。当我按下键 2 或 3 时,目标进程崩溃,导致函数内存清零。这意味着 SecureZeroMemory()
有效,对吗?但是由于用零填充的块大小错误,我相信它只是部分归零。
你这里有几个问题:
- 您不更改内存保护(它可以/应该被读取+执行),您需要使其可写,例如
VirtualProtect
- 获取函数大小不是一件容易的事。函数可以/将被编译器分解成多个部分,有些可能会被内联等。
可能的解决方案
从最简单到最难(正确实施)排序。
- 将您的函数移动到 PE 文件中的单独部分。 (例如在 msvc 中使用
alloc_text
)
- 在函数后插入辅助存根,这样您就可以将它们用作 'size' 标记。 (见注释 1)。
- 使用
capstone
等反汇编程序在运行时确定函数的大小
注1:
使用这样的构造:
void function_to_erase()
{
// your logic here
}
void function_to_erase_helper()
{
// empty
}
您可以通过从您的函数中减去辅助函数的地址来确定 function_to_erase
的大小,if,并且仅当您强制编译器不对这些函数重新排序时函数。 (Project properties->Linker->Optimization->Function Order
)
我对反射dll注入有一点想法。如果你不知道反射dll注入是什么,你可以在这里查看:https://github.com/stephenfewer/ReflectiveDLLInjection
基本上是将 dll 加载到内存,然后将内存注入目标进程 - 至少那是 afaik 发生的事情。我可能是错的,但这并不重要。
任务
- 查找给定函数的内存地址
- 找到给定函数的大小
- 使用
SecureZeroMemory()
将内存归零
代码
#include "ReflectiveLoader.h"
extern HINSTANCE hAppInstance;
void Function1() { MessageBoxA(NULL, "Function 1 called!", "Test", MB_OK); }
void Function2() { MessageBoxA(NULL, "Function 2 called!", "Test", MB_OK); }
void Function3() { MessageBoxA(NULL, "Function 3 called!", "Test", MB_OK); }
void GetMemoryInformation()
{
void(*p_Func1)() = &Function1;
void(*p_Func2)() = &Function2;
void(*p_Func3)() = &Function3;
char buffer[300];
sprintf(buffer, "Function1 - Address: %p | Size: %zu \nFunction2 - Address: %p | Size: %zu \nFunction3 - Address: %p | Size: %zu",
p_Func1, sizeof(p_Func1),
p_Func2, sizeof(p_Func2),
p_Func3, sizeof(p_Func3)
);
MessageBoxA(NULL, buffer, "Memory information", MB_OK);
}
void ZeroMemoryFunctions()
{
void(*p_Func2)() = &Function2;
void(*p_Func3)() = &Function3;
SecureZeroMemory(p_Func2, sizeof(p_Func2));
SecureZeroMemory(p_Func3, sizeof(p_Func3));
}
DWORD WINAPI MainThread(LPVOID PARAMS)
{
MessageBoxA(NULL, "Main thread initialized!", "Entry", MB_OK);
for (;;)
{
if (GetAsyncKeyState(0x31) & 0x8000) Function1(); // key 1
if (GetAsyncKeyState(0x32) & 0x8000) Function2(); // key 2
if (GetAsyncKeyState(0x33) & 0x8000) Function3(); // key 3
if (GetAsyncKeyState(VK_UP) & 0x8000) GetMemoryInformation();
if (GetAsyncKeyState(VK_DOWN) & 0x8000) ZeroMemoryFunctions();
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) MessageBoxA(NULL, "Main thread closed!", "Exit", MB_OK), ExitThread(0);
Sleep(100);
}
}
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
BOOL bReturnValue = TRUE;
switch( dwReason )
{
case DLL_QUERY_HMODULE:
if( lpReserved != NULL )
*(HMODULE *)lpReserved = hAppInstance;
break;
case DLL_PROCESS_ATTACH:
hAppInstance = hinstDLL;
MessageBoxA( NULL, "Reflective Dll injected!", "Injected", MB_OK );
CreateThread(0, 0, &MainThread, 0, 0, 0);
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return bReturnValue;
}
它有什么作用?
- 键1到3,调用显示简单消息框的指定函数
- 向上箭头显示一个消息框,其中包含每个函数的函数地址和大小
- 向下箭头将函数
Function2()
和Function3()
归零
- Escape正常退出主线程
问题
我对内存相关的编码很陌生,所以我很确定我做错了什么。
我认为我以错误的方式获取了函数的大小,而是获取了指向函数的指针的大小,对吗?
其次,如果我调用 ZeroMemoryFunctions()
并按下键 1,它会起作用。当我按下键 2 或 3 时,目标进程崩溃,导致函数内存清零。这意味着 SecureZeroMemory()
有效,对吗?但是由于用零填充的块大小错误,我相信它只是部分归零。
你这里有几个问题:
- 您不更改内存保护(它可以/应该被读取+执行),您需要使其可写,例如
VirtualProtect
- 获取函数大小不是一件容易的事。函数可以/将被编译器分解成多个部分,有些可能会被内联等。
可能的解决方案
从最简单到最难(正确实施)排序。
- 将您的函数移动到 PE 文件中的单独部分。 (例如在 msvc 中使用
alloc_text
) - 在函数后插入辅助存根,这样您就可以将它们用作 'size' 标记。 (见注释 1)。
- 使用
capstone
等反汇编程序在运行时确定函数的大小
注1:
使用这样的构造:
void function_to_erase()
{
// your logic here
}
void function_to_erase_helper()
{
// empty
}
您可以通过从您的函数中减去辅助函数的地址来确定 function_to_erase
的大小,if,并且仅当您强制编译器不对这些函数重新排序时函数。 (Project properties->Linker->Optimization->Function Order
)