【发布时间】:2015-09-10 10:57:51
【问题描述】:
我有一点关于反射 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() 有效,对吗?但由于填充零的块大小错误,我相信它只是部分归零。
【问题讨论】:
-
那么,通过编写您自己的 ld.so 等价物,这仅仅是在 Windows 上模拟 *NIX 共享对象的一次非常复杂的尝试吗?哦,你不能在调试器中检查大小和可能部分归零的内存吗?
-
sizeof(p_Func1)肯定是指针的大小,而不是指向的函数。我不知道获得代码大小的可靠方法。崩溃本身可能是因为您没有足够的权限写入代码空间。各种防病毒功能可能会阻止您这样做。 -
这样做的目的是,我可以在注入时从 x 个函数中选择随机函数,这些函数将在代码中使用。我想将其余的函数归零,这些函数不是随机选择的。我对用类似 c 的语言进行编码非常陌生,特别是与记忆动作相关,所以我不知道你在说什么@Useless,我很抱歉。我不确定我什至知道如何使用调试器来做到这一点,但只有 8 个字节被清零应该是合乎逻辑的,因为这是指针的大小。手头的问题是让函数的大小归零。
-
@PriitJõe - 所以你是在专门询问Task.2?
-
我仍然不明白你通过将函数代码归零来实现什么 - 它不会释放内存,你不能调用它,如果你不调用它为什么内存清零有关系吗?