本帖最后由 30659653 于 2019-8-26 22:57 编辑
大家好,我是竹子。这次介绍一个DLL远程注入的传统方法。适合有较少C语言基础的朋友学习。如果你学习的是易语言一样可以看懂原理,用易语言来制作(如果你是模块-注入 这样一行完成,那么打扰了),毕竟懂了原理才能更快进步。
建议在win8以下系统调试,虚拟机也可以,win8以上需要管理员运行甚至有其他问题。更强大的注入会在以后讲解。最近挺多朋友问DLL是啥,dll注入是咋注入的,反正没事就给讲了一下,正好发个帖子一起看看吧,有讲的不好的地方可以一起探讨,大牛勿喷。欢迎大家私聊
如果大家有需要可以讲一下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()//在目标进程中申请内存
该函数申请内存成功之后,会返回一个新内存区域的首地址。
到此为止,主要的函数和思路已经讲完了,接下来设计界面和写代码。
将DLL的完整路径和进程名称填入,点击注入按钮之后,按钮事件代码如下。
其中GetProcessId()和InjectDll是自写函数,便于后期调试,也可以不写这两个,直接把所有代码写在按钮之下。
[C++] 纯文本查看 复制代码 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()的具体内容如下:
[C++] 纯文本查看 复制代码 [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()代码如下:
[C++] 纯文本查看 复制代码 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);
}
功能和软件已经完成。接下来找一个记事本程序进行测试。弹出正常。
需要的可以自行下载。有啥问题可以私聊或者留言。
|