ll");
Param.KernelLoadLibrary = (LOADLIBRARY)GetProcAddress((HINSTANCE)Param.KernelHandle, "LoadLibraryA");
Param.KernelGetProcAddress = (GETPROCADDRESS)GetProcAddress((HINSTANCE)Param.KernelHandle, "GetProcAddress");
printf("获取到Kernel32.dll = 0x%08X \n", Param.KernelHandle);
printf("获取到KernelLoadLibrary = 0x%08X \n", Param.KernelLoadLibrary);
printf("获取到GetProcAddress = 0x%08X \n", Param.KernelGetProcAddress);
system("pause");
return 0;
}
这段代码没有任何难度,相信读者能够理解其实先的核心原理,当读者运行此段代码,则会分别输出Kernel32.dll
,LoadLibraryA
及GetProcAddress
这三个模块函数的基址,输出效果如下图所示;
1.12.2 进程注入MsgBox弹窗
通过进程注入功能将一个具有自定位功能的函数的机器码注入到远程进程中,并运行输出一个弹窗,该功能的输出形式与前几章中的内容很相似,但却有本质的不同,首先前几章内容中我们注入的数据为纯粹的ShellCode
代码,此类代码的缺陷在于一旦被生成则在注入时无法动态更改参数,而本章实现的注入技术则是动态填充内存并注入,从实用价值上来说本章中所演示的注入技术将更加通用及灵活。
动态弹窗的注入技术同样需要定义关键函数指针,如下将分别定义三个函数指针,这些API函数的函数指针类型定义:
- LOADLIBRARY:LoadLibrary函数的函数指针类型,用于将动态链接库(DLL)加载到调用进程的地址空间中。
- GETPROCADDRESS:GetProcAddress函数的函数指针类型,用于从DLL中检索导出函数或变量的地址。
- MESSAGEBOX:MessageBox函数的函数指针类型,用于创建、显示和操作消息框。WINAPI调用约定指定了如何传递函数参数和清理堆栈。
这些函数指针类型通常用于动态加载DLL和运行时链接导出函数。通过使用这些函数指针,程序可以在运行时获取函数地址并动态调用它们。
// Kernel32 调用约定定义
typedef HMODULE(WINAPI* LOADLIBRARY)(LPCTSTR lpFileName);
typedef FARPROC(WINAPI* GETPROCADDRESS) (HMODULE hModule, LPCSTR lpProcName);
// User32 中针对MessageBox的调用约定定义
typedef int(WINAPI* MESSAGEBOX)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
接着我们需要定义一个ShellParametros
结构体,该结构体的作用是用与传递参数到子线程MyShell(ShellParametros* ptr)
中以供其使用,当然读者也可以使用普通变量形式,只是普通变量在参数传递时没有传递结构方便快捷,如下从结构中可看出,我们分别传递kernel32.dll
,LoadLibrary
,GetProcAddress
及MessageBoxA
的函数地址,并附带有该函数弹窗User_MsgBox
的提示信息;
typedef struct _ShellBase
{
// 针对Kernel32的操作
HANDLE Kernel32Base;
char KernelString[20]; // kernel32.dll
LOADLIBRARY Kernel_LoadLibrary;
GETPROCADDRESS Kernel_GetProcAddress;
// 针对User32的操作
HANDLE User32Base;
char UserString[20]; // 存储 user32.dll 字符串
char User_MsgBox[20]; // 存储 MessageBoxA 字符串
// 输出一段话
char Text[32];
}ShellParametros;
接着就是关于__stdcall MyShell(ShellParametros*);
函数的封装,这是一个用于远程线程的函数定义,函数名为MyShell
,采用__stdcall
调用约定。该函数的参数是一个名为ptr
的指向ShellParametros
结构体的指针。
函数的实现包括以下步骤:
- 1.通过调用
ptr->Kernel_LoadLibrary
函数动态加载指定的Kernel32
和User32
库,并将它们的句柄保存在ptr->Kernel32Base
和ptr->User32Base
变量中。
- 1.使用
ptr->Kernel_GetProcAddress
函数获取 User32
库中名为 ptr->User_MsgBox
的导出函数的地址,并将其转换为 MESSAGEBOX
函数指针类型的变量 msgbox
。
- 1.调用
msgbox
函数,显示 ptr->Text
变量中保存的文本内容。
该函数的作用是在远程线程中动态加载Kernel32
和User32
库,并调用User32
库中的MessageBox
函数显示指定的文本内容。
void __stdcall MyShell(ShellParametros*);
// 定义远程线程函数
void __stdcall MyShell(ShellParametros* ptr)
{
ptr->Kernel32Base = (HANDLE)(*ptr->Kernel_LoadLibrary)(ptr->KernelString);
ptr->User32Base = (HANDLE)(*ptr->Kernel_LoadLibrary)(ptr->UserString);
// printf("动态获取到Kernel32基地址 = %x \n", ptr->Kernel32Base);
// printf("动态获取到User32基地址 = %x \n", ptr->User32Base);
// MESSAGEBOX msgbox = (MESSAGEBOX)(*ptr->KernelGetProcAddress)((HINSTANCE)ptr->UserHandle, "MessageBoxA");
MESSAGEBOX msgbox = (MESSAGEBOX)(*ptr->Kernel_GetProcAddress)((HINSTANCE)ptr->User32Base, ptr->User_MsgBo