VC 不同版本代码注入的改进

简介: 在上篇文章中 《VC 不同版本代码注入的区别》 ,我们想要对目标进程进行代码的注入,由于 Debug 版编译生成的代码和 Release 版编译生成的代码有些不同(Debug 版编译后,调用函数时会有一条 jmp 指令,而 Release 没有),因此,通过 #ifdef 这样的宏来区别 VC 是以 Debug 版方式编译,还是通过 Release 版方式编译,从而编译不同的代码来针对不同的版本进行了处理。

在上篇文章中 《VC 不同版本代码注入的区别》 ,我们想要对目标进程进行代码的注入,由于 Debug 版编译生成的代码和 Release 版编译生成的代码有些不同(Debug 版编译后,调用函数时会有一条 jmp 指令,而 Release 没有),因此,通过 #ifdef 这样的宏来区别 VC 是以 Debug 版方式编译,还是通过 Release 版方式编译,从而编译不同的代码来针对不同的版本进行了处理。代码如下:

#ifdef DEBUGDWORDdwAddr= (DWORD)Inject;
DWORDdwOffset=*(DWORD*)((PBYTE)dwAddr+1);
dwInjectAddr=dwAddr+5+dwOffset;
#elsedwInjectAddr= (DWORD)Inject;
#endif

这样虽然解决了问题,但是实际中还是有些不够完善的地方。

我们向目标进程注入代码的时候,我这里给了一个固定的注入代码的长度,代码如下:

LPVOIDlpBase=VirtualAllocEx(hProcess, NULL, 0x4096, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, lpBase, (LPCVOID)Inject, 0x4096, NULL);

从上面的代码中可以看出,我给的长度是固定的 0x4096,而实际上真正注入的代码也就几十个字节。

那么实际我们想要计算一下代码的长度后再进行计算,那也由此想到,我们把要注入的代码放到完成注入功能的代码的后面就可以了。这样有两个好处,方便计算注入代码的长度,而且也不用区分是 Debug 版和 Release 版的差异了。

实现的具体代码如下:

voidRemoteCall()
{
HWNDhWnd= ::FindWindow(NULL, L"XXXXXX");
DWORDdwPid=0;
    ::GetWindowThreadProcessId(hWnd, &dwPid);
HANDLEhProcess=OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
LPVOIDlpBase=VirtualAllocEx(hProcess, NULL, 0x4096, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
DWORDdwInjectAddr=0;
DWORDdwCodeLen=0;
__asm    {
leaeax, STARTmovdwInjectAddr, eaxleaeax, ENDsubeax, dwInjectAddrmovdwCodeLen, eax    }
WriteProcessMemory(hProcess, lpBase, (LPCVOID)dwInjectAddr, dwCodeLen, NULL);
DWORDdwTid;
HANDLEhRemoteProcess=CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpBase, NULL, 0, &dwTid);
WaitForSingleObject(hRemoteProcess, INFINITE);
CloseHandle(hRemoteProcess);
CloseHandle(hProcess);
return;
START:
__asm    {
pushad// 一段简单的汇编popadret    }
END:
return;
}

在上面的代码中,实际代码只执行到第一个 return 语句处,而要注入到目标进程的代码放到 START 和 END 标签之内,这段代码是不会被执行的。START 标签可以表明要注入代码的起始地址,END 标签和 START 标签可以得到实际注入代码的长度。整个计算过程,是在上面的内联汇编中完成的,代码如下:

__asm{
leaeax, STARTmovdwInjectAddr, eaxleaeax, ENDsubeax, dwInjectAddrmovdwCodeLen, eax}

代码中 dwInjectAddr 是注入代码的起始地址,dwCodeLen 是注入代码的长度,非常的简单。这样做,就无需考虑编译的版本,也无需计算 jmp 指令的偏移了,省去了很多事情。






相关文章
|
25天前
|
XML C# 数据格式
掌握了在Windows平台上查看DLL依赖的方法
掌握了在Windows平台上查看DLL依赖的方法
169 4
|
C++ Windows
C++ --- Dll文件的生成与调用(二)之动态库注入技术
C++ --- Dll文件的生成与调用(二)之动态库注入技术
156 0
|
监控 安全 虚拟化
DLL注入的环境构建
DLL注入的环境构建
VC 不同版本代码注入的区别
VC 不同版本代码注入的区别
63 0
|
编译器 C++ Windows
Qt程序运行依赖环境打包方法:windeployqt方法
3分钟学会Qt程序运行依赖环境打包方法:windeployqt方法!
496 0
Qt程序运行依赖环境打包方法:windeployqt方法
visual studio编写C#代码时“未能从程序集.....中加载类型”和“找不到方法”的一种可能的解决办法
编译前报错:$exception    {"未能从程序集“XSW.MySQLDAL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中加载类型“XSW.MySQLDAL.EnterpriseLibraryProductDAL”。
1746 0
|
安全 编译器 C语言