zl程序教程

您现在的位置是:首页 >  后端

当前栏目

使用C#调用系统API实现内存注入的代码

2023-06-13 09:14:29 时间
复制代码代码如下:

//首先导入命名空间
usingSystem.Runtime.InteropServices;
///<summary>
///在指定进程的虚拟地址空间中保留或开辟一段区域..除非MEM_RESET被使用,否则将该内存区域初始化为0.
///</summary>
///<paramname="process">需要在其中分配空间的进程的句柄.这个句柄必须拥有PROCESS_VM_OPERATION访问权限</param>
///<paramname="pAddress">想要获取的地址区域.一般用NULL自动分配</param>
///<paramname="size">要分配的内存大小.字节单位.注意实际分配的内存大小是页内存大小的整数倍</param>
///<paramname="type">内存分配的类型</param>
///<paramname="protect">内存页保护</param>
///<returns>执行成功就返回分配内存的首地址,失败返回0。</returns>
[DllImport("kernel32.dll")]//声明API函数
publicstaticexternintVirtualAllocEx(IntPtrprocess,intpAddress,intsize,inttype,intprotect);
///<summary>
///写入某一进程的内存区域。入口区必须可以访问,否则操作将失败
///</summary>
///<paramname="process">进程句柄</param>
///<paramname="baseAddress">要写的内存首地址</param>
///<paramname="buffer">指向要写的数据的指针(数据当前存放地址)。</param>
///<paramname="nSize">要写入的字节数。</param>
///<paramname="lpNumberOfBytesWritten">实际数据的长度</param>
///<returns>非零表示成功,零表示失败</returns>
[DllImport("kernel32.dll")]
publicstaticexternintWriteProcessMemory(IntPtrprocess,intbaseAddress,stringbuffer,intnSize,intlpNumberOfBytesWritten);
///<summary>
///检索指定的动态链接库(DLL)中的输出库函数地址
///</summary>
///<paramname="hModule">DLL模块句柄包含此函数的DLL模块的句柄。LoadLibrary或者GetModuleHandle函数可以返回此句柄。</param>
///<paramname="lpProcName">函数名包含函数名的以NULL结尾的字符串,或者指定函数的序数值。如果此参数是一个序数值,它必须在一个字的底字节,高字节必须为0。</param>
///<returns>调用成功,返回DLL中的输出函数地址,调用失败,返回0。得到进一步的错误信息,调用函数GetLastError。</returns>
[DllImport("kernel32.dll")]
publicstaticexternintGetProcAddress(inthModule,stringlpProcName);
///<summary>
///获取一个应用程序或动态链接库的模块句柄
///</summary>
///<paramname="moduleName">指定模块名,这通常是与模块的文件名相同的一个名字</param>
///<returns>如执行成功成功,则返回模块句柄。零表示失败</returns>
[DllImport("kernel32.dll")]
publicstaticexternintGetModuleHandleA(stringmoduleName);
///<summary>
///创建一个在其它进程地址空间中运行的线程(也称:创建远程线程).
///</summary>
///<paramname="process">目标进程的句柄</param>
///<paramname="threadAttributes">指向线程的安全描述结构体的指针,一般设置为0,表示使用默认的安全级别</param>
///<paramname="stackSize">线程堆栈大小,一般设置为0,表示使用默认的大小,一般为1M</param>
///<paramname="startAddress">线程函数的地址</param>
///<paramname="parameter">传给线程函数的参数</param>
///<paramname="creationFlags">线程的创建方式(0表示线程创建后立即运行CREATE_SUSPENDED0x00000004以挂起方式创建创建不会运行,直到调用ResumeThread函数)</param>
///<paramname="threadid">指向所创建线程句柄的指针,如果创建失败,该参数为0</param>
///<returns>如果调用成功,返回新线程句柄,失败返回0</returns>
[DllImport("kernel32.dll")]
publicstaticexternintCreateRemoteThread(IntPtrprocess,intthreadAttributes,intstackSize,intstartAddress,intparameter,intcreationFlags,intthreadid);

复制代码代码如下:

///<summary>
///根据进程名称获取进程
///</summary>
///<paramname="ProcessName">进程名称</param>
///<returns></returns>
publicProcessGetProcessByName(stringProcessName)
{
//取得所有进程
Process[]pname=Process.GetProcesses();
//遍历进程
foreach(Processnameinpname)
{
//如果查找到进程名称返回
if(name.ProcessName.ToLower().IndexOf(ProcessName)!=-1)
returnname;
}
returnnull;
}

复制代码代码如下:
publicvoidkillDll()
{
stringdllName="c:\\text.dll";
intdlllength=dllName.Length+1;
//这里以记事本为例
ProcessprocessName=GetProcessByName("notepad");
//如果查找到记事本进程,那么下面开始注入
if(processName!=null)
{
//申请内存空间,执行成功就返回分配内存的首地址,不成功就是0。
intbaseaddress=VirtualAllocEx(processName.Handle,0,dlllength,4096,4);
if(baseaddress==0)
{
MessageBox.Show("申请内存空间失败!");
return;
}
//写内存
intresult=WriteProcessMemory(processName.Handle,baseaddress,dllName,dlllength,0);
if(result==0)
{
MessageBox.Show("写内存失败!");
return;
}
//取得loadlibarary在kernek32.dll地址
intprocAddress=GetProcAddress(GetModuleHandleA("Kernel32"),"LoadLibraryA");
if(procAddress==0)
{
MessageBox.Show("无法取得函数的入口点!");
return;
}
//创建远程线程。
result=CreateRemoteThread(processName.Handle,0,0,0,baseaddress,0,0);
if(result==0)
{
MessageBox.Show("创建远程线程失败!");
return;
}
else
MessageBox.Show("已成功注入dll!");
}
}