常见注入手法第三讲,远程线程注入
一丶远程线程注入的讲解
远程线程注入的原理,我会写一个远程线程开发的例子
我们总共需要几步
/*1.查找窗口,获取窗口句柄*/ /*2.根据窗口句柄,获得进程的PID*/ /*3.根据进程的PID,获得进程的句柄*/ /*4.根据进程的句柄,给进程申请额外内存空间*/ /*5.调用WriteProcessMemory,给进程写入DLL的路径*/ /*6.创建远程线程,执行我们的代码*/ /*7.调用退出代码,释放远程线程的dll*/
每一步单独讲解
我们新建一个MFC 对话框程序,添加一个按钮,这个按钮专门响应注入的实现
第一步: 查找窗口,获得窗口句柄(采用WindowsAPI FindWindow,传入窗口名称,然后找到则返回对应的窗口句柄)
HWND hWnd = FindWindow("","计算器"); if(NULL == hWnd) { return; //失败则返回 }
第二步: 根据窗口句柄,查找进程PID (调用 GetWindowThreadProcessId API,传入窗口句柄,然后通过第二个参数把进程的PID给我们的参数)
/*2.根据窗口句柄,获得进程的PID*/ DWORD DwPid = 0; GetWindowThreadProcessId(hWnd,&DwPid); //这个函数会返回线程的ID,但是我们不关心,所以没有加返回值
第三步: 根据进程PID,返回进程的句柄(OpenProcess,参数一,权限 参数二,句柄是否继承,参数三,进程的pid)
/*3.根据进程的PID,获得进程的句柄*/ HANDLE hProHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,DwPid); //参数一,选择所有权限,参数二,不继承给false,参数三,给我们上面获得的pid的值 if(NULL == hProHandle) { return; }
第四步: 给远程进程申请空间,并且返回空间的首地址(调用的API 是VirtualAllocEx)
/*4.根据进程的句柄,给进程申请额外内存空间*/ LPVOID lpAddr = VirtualAllocEx(hProHandle,NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE); if(NULL == lpAddr) { return ; }
VirtualAllocEx说明:
第一个参数: 进程的句柄
第二个参数: 指定位置分配内存,给NULL为默认帮我们找块地方申请内存(不过这个地址会返回,所以不关心)
第三个参数: 内存分配多大,我们给了4096个字节大小,也就是一个分页(1000H)
第四个参数: 是否立即申请,还是保留这块内存,只能给我们用,但是还没申请,我们选择立即申请
第五个参数: 权限,你申请的这块内存是什么内存,只能读,还是只能写,还是只能执行,我们选择全部,可读可写可执行
第五步:调用WriteProcessMemory将我们的Dll路径,写入到远程进程中
/*5.调用WriteProcessMemory,给进程写入DLL的路径*/ char szBuf[MAX_PATH] = {NULL}; GetCurrentDirectory(sizeof(szBuf),szBuf); //这三行代码主要是拼接我们的DLL,DLL是我们自己写的 strcat(szBuf,"StaticDll.dll"); //DLL这里就不写了,用我的吧,我会发上去的
BOOL bRet = WriteProcessMemory(hProHandle,lpAddr,szBuf,strlen(szBuf)+1,NULL); if(!bRet) { return; }
WriteProcessMemory讲解:
第一个参数: 进程的句柄,可以用我们上面的OpenProcess返回的
第二个参数: 你要写入的地址,地址使我们VirtualAllocEx申请之后返回的(就是你要往哪个地址写内容)
第三个参数: 你写入的内容是什么,写入的内容使我们的Dll路径,上面已经拼接好了
第四个参数: 你写入的内容的大小是多大,这里我们用strlen求出来了
第五个参数: 实际写入的个数,我们不关心,如果你想知道,则定义一个变量,然后 取地址传入即可,因为是个指针
第六步: 远程进程开辟线程,调用LoadLibrary,加载我们的dll,而你们知道,当dll被加载的时候,会有信息
所以我们在我们的dll里面写入我们自己的代码,比如这个dll被加载的时候,我们执行我们的代码,
这里我的代码就是找到计算器,然后给它加个菜单,并且响应消息
HANDLE hThreadHandle = CreateRemoteThread(hProHandle, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibrary, lpAddr, 0, NULL);
核心代码就在这里,我们必须要知道,我们现在加载我们的DLL,而我们的DLL被加载的时候,就要执行自己的代码
所以这个时候就可以执行代码了
CreateRemoteThread讲解:
第一个参数: 进程的句柄(你要往哪个进程开辟线程)
第二个参数: 安全属性,句柄可否继承,不需要给NULL
第三个参数: 栈的大小,给0则默认
第四个参数: 函数执行,我们要开辟线程,开辟的线程叫做loadLibrary
第五个参数: 开辟线程传入的参数,我们知道,线程只有一个参数,而现在正好load也是一个参数,所以加载的参数就是我们的
写入远程进程内存的dll路径,而dll路径一旦启动,则会执行自己的代码(核心,一定掌握)
第六个参数: 创建的标志,默认给0
第七个参数: 线程的ID,不需要知道,给NULL
我们尝试一下是否可以成功注入计算器,并且加入菜单
已经成功注入了.对于完整的代码,我会放到课堂资料中,但是这几步,一定要亲自手动弄明白
(备注: 我是使用VC++6.0编写代码,是MFC程序,当然你也可以用高版本,参考我这个,是一样的
对于DLL,我也会发,你们可以自己去写自己的DLL,比如一个空DLL会有DLL main,也就是dll的入口点
当第一次加载的时候会来信息什么的,所以可以在里面写代码.dll靠自己,这里只提供思路)
给计算器加入菜单的 DLL代码 简单如下(或者自己写) 文章来自 https://www.cnblogs.com/csnd/p/11697798.html
#include <windows.h> #include <tchar.h> #include <shellapi.h> #define IDM_TEST 12345 WNDPROC lpfnOldProc = 0; LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return CallWindowProc(lpfnOldProc, hWnd, message, wParam, lParam); } DWORD WINAPI ThreadProc(PVOID pParam) { HWND hwnd = FindWindow(NULL, _T("计算器")); HMENU hMenu = GetMenu(hwnd); AppendMenu(hMenu, MF_STRING, IDM_TEST, _T("注入菜单")); SetMenu(hwnd, hMenu); lpfnOldProc = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc); return 0; } BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CreateThread(NULL,0,ThreadProc,NULL,0,NULL); case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/7898189.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能. QQ群: