欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DLL远程注入代码详解

程序员文章站 2024-03-02 12:00:58
...

DLL远程注入代码详解

首先,四个你要知道的东西:
1.“远程线程‘’是指跨进程,而不是跨计算机。
2.计算机每个进程的地址空间都是独立隔离的。
3.简单说,进程A在进程B创建一个线程就叫远程线程。
4.多用在木马外Gua等注入,dll文件的运行不会单独创建一个进程,它的运行被加载到进程的地址空间中,因此其隐蔽性相对较好。

主要的函数如下:
- 一. CreatRemoteThread()//创建远程线程

在这个函数调用中主要有三个参数以及伴随的三个问题:
1.第四个参数lpStartAddress,指定进程中的线程函数的地址,稍微解释一下就是,你要在目标进程中注入的功能函数的地址。我们用到的函数是LoadLibrary(加载DLL用的)。
2.第五个参数lpParameter,他是dll的具体地址,是loadlibrary的参数,也要传入目标进程中进行存储,(问题:)就需要在目标进程中开辟合适大小的空间来保存。

首先解释解决第一个问题,因为是注入DLL,所以我们需要在目标进程中调用loadlibrary(dll)这个函数来加载dll。那么如何将loadlibrary放到目标进程呢??Loadlibrary是系统中的Kernel32.dll的导出函数,因此他存在于目标进程中,同时kernel32.dll在任何进程中的加载位置都是相同的,也就是说LoadLibraryA()在任何进程中的位置都是相同的。问题变简单了,只需要找到kernel32.dll,找到之后再找library就完成。
然后解决第二个问题,如何将LoadLibrary函数的参数,即dll文件的完整路径传入目标进程内存。问题变简单了,调用我们的第二个函数,如下详细:

  • 二. WriteProcessMemory()

/*
注意:该函数功能十分强大,比如在**方面,用该函数可以实现一个内存补丁;在开发方面,用该函数可以修改制定进程中指定的值(比如在游戏中修改属性);
*/
使用该函数可以将DLL文件的完整路径加载到目标进程中,这样就可以使用LoadLibrary()函数来加载指定的DLL文件了。
如上两个问题已经解决,那么有没有人考虑过,DLL文件路径价值再到目标进程中的哪个位置?第三个问题来了,关于dll文件路径存放在哪里。就是接下来的函数发挥作用:

  • 三. VirtualAllocEx()//在目标进程中申请内存

该函数申请内存成功之后,会返回一个新内存区域的首地址。
到此为止,主要的函数和思路已经讲完了,接下来设计界面和写代码。
其中GetProcessId()和InjectDll是自写函数,便于后期调试,也可以不写这两个,直接把所有代码写在按钮之下。

void CMFCApplication13Dlg::OnBnClickedButton1()
{
        CString szDLLName;
        CString szProcessName;
        DWORD dwpid = 0;
 
        GetDlgItemText(IDC_EDIT1,szDLLName);
        GetDlgItemText(IDC_EDIT2, szProcessName);
 
        //通过进程名获得pid,自定义函数GetProcId
        dwpid = GetProcId(szProcessName);
 
        //HANDLE Fhandle=FindWindow(NULL,szProcessName);
        //dwpid = GetProcessId(Fhandle);
 
 
        //注入szDLLName到dwpid
        InjectDll(dwpid,szDLLName);
}

GetProcessId()的具体内容如下:

[mw_shl_code=cpp,true]DWORD CMFCApplication13Dlg::GetProcId(CString szProcessName)
{
BOOL bRet;
PROCESSENTRY32 pe32;
HANDLE hSnap;
 
char* str = (LPSTR)(LPCTSTR)szProcessName;
//获取当前进程快照
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
pe32.dwSize = sizeof(pe32);
bRet = Process32First(hSnap,&pe32);//从第一个进程开始判断
 
while (bRet)
{
//strupr转换为大写,便于字符串对比,strcmp对比两个进程名称
if (strcmp(strupr(pe32.szExeFile),
strupr(str)) == 0)
{
return pe32.th32ProcessID;//找到
}
 
bRet = Process32Next(hSnap,&pe32);//下一个进程
}
 
return 0;
}

InjectDll()代码如下:

void CMFCApplication13Dlg::InjectDll(DWORD dwPid, CString szDllName)
{
        if (dwPid == 0 || strlen(szDllName) == 0)
        {
                return;
        }
 
        char* pFunName = "LoadLibraryA";//要在进程中寻找的函数名
 
        //打开目标进程,返回目标进程的句柄
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
 
        if (hProcess == NULL)
        {
                return;
        }
 
        //欲注入的DLL文件路径的长度
        int nDllLen = strlen(szDllName) + sizeof(char);
 
        //在目标进程申请一块长度为nDllLen的内存空间,存储dll路径,作为LoadLibraryA()的参数
        PVOID pDllAddr = VirtualAllocEx(hProcess,NULL,nDllLen,MEM_COMMIT,PAGE_READWRITE);
         
        if (pDllAddr == NULL)
        {
                CloseHandle(hProcess);
                return;
        }
 
        DWORD dwWriteNum = 0;
         
        //将欲注入DLL的路径写入在目标进程申请的空间中
        WriteProcessMemory(hProcess,pDllAddr,szDllName,nDllLen,&dwWriteNum);
         
        //其中的一个问题已经完成,就是dll在目标进程中的存储问题。下面是解决在目标进程中获取LoadLibraryA的地址问题
 
        /*获取LoadLibraryA()的地址。这个函数位于kernel32.dll中,kernel在任何进程中的加载位置都是相同的,也就是说LoadLibraryA()
在任何进程中的位置都是相同的。*/
        FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"),pFunName);
 
        //创建远程线程
        HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)pFunAddr,pDllAddr,0,NULL);
 
        WaitForSingleObject(hThread,INFINITE);
 
        CloseHandle(hThread);
        CloseHandle(hProcess);
}

功能和软件已经完成(我用的MFC添加了几个按钮,请自行设计界面,本篇文章只介绍代码)。
DLL远程注入代码详解
接下来找一个记事本程序进行注入测试,会发现弹出窗口表示注入成功

相关标签: C++