源码是c++代码翻译过来的, 所以, 那些指针读写的偏移我就不做过多的讲解…..
那些偏移都是对应某个成员…. 众所周知, 易语言的数据类型是个坑, 所以, 申请一块空间当成一个结构使用了
愿意研究的话, 结构是这个
typedef struct CALL_ARGUMENT_DATA { PFN_RtlInitUnicodeString fnRtlInitUnicodeString; // 加载unicode字符串 PFN_LdrLoadDll fnLdrLoadDll; // 加载dll的函数 // 下面5个是 LdrLoadDll 需要使用的数据, DllName通过RtlInitUnicodeString来提供被 LdrLoadDll 使用 WCHAR DllName[260]; // dll完整路径 PWCHAR DllPath; // LdrLoadDll第一个参数, Dll路径, 可以为0 ULONG Flags; // LdrLoadDll第二个参数, 标识 UNICODE_STRING UnicodeString; // LdrLoadDll第三个参数, dll路径 UNICODE_STRING 结构 HANDLE hModule; // LdrLoadDll第四个参数, 模块地址, 注入后模块地址保存到这里 // 下面这些成员是获取函数地址使用的数据 PFN_LdrGetProcedureAddress fnLdrGetProcedureAddress; // 获取函数地址 PFN_RtlInitAnsiString fnRtlInitAnsiString; // 加载ansi字符串 ANSI_STRING AnsiString; // 获取函数名的ansi字符串结构 ULONG Ordinal; // LdrGetProcedureAddress 第三个参数 PFN_CallFun fun; // LdrGetProcedureAddress第四个参数, 被调用的函数名 函数原型, GetProcAddress() 得到的函数 PFN_MessageBox pfn_MessageBox; // 信息框函数地址 BOOL isDebug; // 是否调试, 调试的话就弹出信息框 char funName[260]; // 被调用的函数名 DWORD funArg; // 传递到被调用的函数参数 LPVOID funRet; // 被调用函数的返回值 char argData[2000]; // 传递到函数里的数据, 参数数据最大支持2000个字节 }*LPCALL_ARGUMENT_DATA;
注入流程:
1. 创建远程线程
2. 注入一段代码到目标进程里执行
3. 这段代码调用 LdrLoadDll 加载dll
4. 调用 LdrGetProcedureAddress 获取函数地址, 然后调用, 返回
2021-12-17 更新
使用了eWOW64Ext //www.sanye.cx/?id=12671
1. 注入32位进程只能使用32位的dll
2. 注入64位进程只能使用64位的dll
支持注入任务管理器