CreateProcess注入方法

2023-05-16

采用 CreateProcess 的方法,实现起来比较复杂,但没有上面几种方法的局限性。且可以用其他工 具( VC 等)调试注入的 DLL 。下面进行介绍. 原理如下:

1
   CreateProcess CREATE_SUSPENDED )启动目标进程。
2
   找到目标进程的入口,用 ImageHlp 中的函数可以实现。
3
   将目标进程入口的代码保存起来。
4
   在目标进程的入口写入 LoadLibrary MyDll )实现 Dll 的注入。
5
   ResumeThread 运行目标进程。
6
   目标进程就运行了 LoadLibrary MyDll ),实现 DLL 的注入。
7
   目标进程运行完 LoadLibrary(MyDll) 后,将原来的代码写回目标进程的入口。
8
   目标进程 Jmp 至原来的入口,继续运行程序。

从原理上可以看出, DLL 的注入在目标进程的开始就运行了,而且不是用 Debug 的方案,这样,就 没有上面方案的局限性了。该方案的关键在 6 7 8 三步,实现方法需要监视进程和 DLL 合作。下 面,结合代码进行分析。

在监视进程中,创建 FileMapping ,用来保存目标进程的入口代码,同时保证 DLL 中可以访问。在 7 步实现将原目标代码写回目标进程的入口。

[c-sharp]  view plain copy
  1. // 监视程序和DLL共用的结构体  
  2. #pragma pack (push ,1) // 保证下面的结构体采用BYTE对齐(必须)  
  3. typedef struct   
  4. {  
  5.        BYTE      int_PUSHAD;         // pushad        0x60         
  6.        BYTE      int_PUSH;             // push &szDLL     0x68  
  7.        DWORD push_Value;           //            &szDLL = "ApiSpy.dll"的path  
  8.        BYTE      int_MOVEAX;              //  move eax &LoadLibrary  0xB8  
  9.        DWORD eax_Value;             //     &LoadLibrary  
  10.        WORD    call_eax;         //     call eax    0xD0FF(FF D0) (LoadLibrary  
  11. ("ApiSpy.dll");  
  12.        BYTE      jmp_MOVEAX;             //     move eax &ReplaceOldCode  0xB8         
  13.        DWORD jmp_Value;             //     JMP的参数  
  14.        WORD    jmp_eax;        //     jmp eax   0xE0FF(FF E0) jmp ReplaceOldCode;  
  15.        char szDLL[MAX_PATH]; //  "ApiSpy.dll"的FullPath  
  16. }INJECT_LOADLIBRARY_CODE, *LPINJECT_CODE;  
  17. #pragma pack (pop , 1)  


上面结构体的代码为汇编代码,对应的汇编为:
[cpp]  view plain copy
  1. pushad  
  2. push szDll  
  3. mov eax, &LoadLibraryA  
  4. call eax  // 实现调用LoadLibrary(szDll)的代码  
  5. mov eax, oldentry  
  6. jmp eax // 实现在LoadLibrary运行完后, 跳至目标进程的入口继续运行  
  7. // FileMaping的结构体  
  8. typedef struct   
  9. {  
  10.        LPBYTE  lpEntryPoint;   // 目标进程的入口地址  
  11.        BYTE      oldcode[sizeof(INJECT_CODE)];        // 目标进程的代码保存  
  12. }SPY_MEM_SHARE, * LPSPY_MEM_SHARE;  


准备工作:

第一步:用 CreateProcess CREATE_SUSPENDED )启动目标进程。


[cpp]  view plain copy
  1. // 用CreateProcess启动一个暂停的目标进程  
  2. CreateProcessA(0, szRunFile, 0, 0, FALSE, CREATE_SUSPENDED  
  3.                             0, NULL, &stInfo,  
  4.                             &m_proInfo) ;  




// 
找到目标进程的入口点,函数如下

第二步:找到目标进程的入口,用 ImageHlp 中的函数可以实现。

[cpp]  view plain copy
  1. pEntryPoint = GetExeEntryPoint(szRunFile);  
  2. LPBYTE  GetExeEntryPoint(char *filename)  
  3. {  
  4.        PIMAGE_NT_HEADERS      pNTHeader;  
  5.        DWORD pEntryPoint;  
  6.        PLOADED_IMAGE       pImage;  
  7.        pImage = ImageLoad(filename, NULL);  
  8.        if(pImage == NULL)  
  9.               return NULL;  
  10.        pNTHeader = pImage->FileHeader;  
  11.        pEntryPoint = pNTHeader->OptionalHeader.AddressOfEntryPoint + pNTHeader-  
  12. >OptionalHeader.ImageBase;  
  13.        ImageUnload(pImage);  
  14.        return (LPBYTE)pEntryPoint;  
  15. }  
  16. // 创建FileMapping  
  17. hMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,  
  18.        PAGE_READWRITE,    0, sizeof(SPY_MEM_SHARE), “MyDllMapView”);  




//  保存目标进程的代码

第三步:将目标进程入口的代码保存起来。
[cpp]  view plain copy
  1. LPSPY_MEM_SHARE   lpMap = pMapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);  
  2. ReadProcessMemory(m_proInfo.hProcess, pEntryPoint,  
  3.                     &lpMap->oldcode, sizeof(INJECT_CODE),  
  4.                      &cBytesMoved);  
  5.        lpMap->lpEntryPoint = pEntryPoint;  


//  第四步:在目标进程的入口写入 LoadLibrary MyDll )实现 Dll 的注入。


[c-sharp]  view plain copy
  1. // 准备注入DLL的代码  
  2.        INJECT_CODE     newCode;  
  3. // 写入MyDll―――用全路径  
  4.        lstrcpy(newCode.szDLL, szMyDll);  
  5. // 准备硬代码(汇编代码)  
  6.        newCode.int_PUSHAD = 0x60;      
  7.        newCode.int_PUSH = 0x68;  
  8.        newCode.int_MOVEAX = 0xB8;  
  9.        newCode.call_eax = 0xD0FF;  
  10.        newCode.jmp_MOVEAX = 0xB8;  
  11.        newCode.jmp_eax = 0xE0FF;  
  12.        newCode.eax_Value = (DWORD)&LoadLibrary;  
  13.        newCode.push_Value=(pEntryPoint + offsetof(INJECT_CODE,szDLL));  
  14. // 将硬代码写入目标进程的入口  
  15. // 修改内存属性  
  16. DWORD dwNewFlg, dwOldFlg;  
  17. dwNewFlg = PAGE_READWRITE;  
  18. VirtualProtectEx(m_proInfo.hProcess, (LPVOID)pEntryPoint, sizeof(DWORD), dwNewFlg, &dwOldFlg);  
  19. WriteProcessMemory(m_proInfo.hProcess, pEntryPoint, &newCode, sizeof(newCode), NULL);//&dwWrited);  
  20. VirtualProtectEx(proInfo.hProcess, (LPVOID)pEntryPoint, sizeof(DWORD), dwOldFlg, &dwNewFlg);  
  21. // 释放FileMaping  注意,不是Closehandle(hMap)  
  22. UnmapViewOfFile(lpMap);  


// 
继续目标进程的运行

第五步:用 ResumeThread 运行目标进程。

[cpp]  view plain copy
  1. ResumeThread(m_proInfo.hThread);  




在监视进程中就结束了自己的任务,剩下的第 6 7 8 步就需要在 Dll DllMain 中进行配合。

DLL
中用来保存数据的结构体

[cpp]  view plain copy
  1. typedef struct  
  2. {  
  3.          DWORD    lpEntryPoint;  
  4.          DWORD    OldAddr;  
  5.          DWORD    OldCode[4];  
  6. }JMP_CODE,* LPJMP_CODE;  
  7. static JMP_CODE  _lpCode;  



//  DllMain DLL_PROCESS_ATTACH 中调用 InitApiSpy 函数

// 
在该函数中实现第 6 7 8



第六步:目标进程就运行了 LoadLibrary MyDll ),实现 DLL 的注入。

[c-sharp]  view plain copy
  1. int    WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved)  
  2. {  
  3.        switch(dwReason)  
  4.        {  
  5.        case DLL_PROCESS_ATTACH:  
  6.               return InitApiSpy();  
  7. ……  
  8. // InitApiSpy函数的实现  
  9. BOOL WINAPI InitApiSpy()  
  10. {  
  11.        HANDLE hMap;  
  12.        LPSPY_MEM_SHARE   lpMem;  
  13.        DWORD dwSize;  
  14.        BOOL     rc;  
  15.        BYTE*    lpByte;  
  16.        // 取得FileMapping的句柄  
  17.        hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, “MyDllMapView”);  
  18.        if(hMap)  
  19.        {  
  20.               lpMem = (LPSPY_MEM_SHARE)MapViewOfFile(hMap,  
  21.                                                                         
  22. FILE_MAP_ALL_ACCESS,  
  23.                                                                       0, 0, 0);  
  24.               if(lpMem)  
  25.               {  

第七步:目标进程运行完 LoadLibrary(MyDll) 后,将原来的代码写回目标进程的入口。
[cpp]  view plain copy
  1.                      // 恢复目标进程的入口代码  
  2. // 得到mov eax, value代码的地址  
  3.                      _lpCode.OldAddr = (DWORD)((BYTE*)lpMem->lpEntryPoint + offsetof(INJECT_CODE, jmp_MOVEAX));  
  4.                      _lpCode.lpEntryPoint = (DWORD)lpMem->lpEntryPoint;  
  5.                      // 保存LoadLibrary()后面的代码  
  6.                      memcpy(&_lpCode.OldCode, (BYTE*)lpMem->oldcode + offsetof(INJECT_CODE, jmp_MOVEAX), 2*sizeof(DWORD));  
  7.                      // 恢复目标进程的入口代码  
  8.                      rc = WriteProcessMemory(GetCurrentProcess(), lpMem->lpEntryPoint, lpMem->oldcode, sizeof(INJECT_CODE), &dwSize);  
  9.                      lpByte = (BYTE*)lpMem->lpEntryPoint + offsetof(INJECT_CODE, jmp_MOVEAX);  
  10.                      UnmapViewOfFile(lpMem);  
  11.               }  
  12.               CloseHandle(hMap);  
  13.        }  
  14. // 实现自己Dll的其他功能,如导入表的替换  
  15. //     ……  
  16. // 将LoadLibrary后面的代码写为转入处理程序中  
  17. // 指令为:mov eax, objAddress  
  18. //         jmp eax  
  19.        {  
  20.               BYTE*    lpMovEax;  
  21.               DWORD*      lpMovEaxValu;  
  22.               WORD*  lpJmp;  
  23.               DWORD fNew, fOld;  
  24.               fNew = PAGE_READWRITE;  
  25.               lpMovEax = lpByte;  
  26.               VirtualProtect(lpMovEax, 2*sizeof(DWORD), fNew, &fOld);  
  27.               *lpMovEax = 0xB8;  
  28.               lpMovEaxValu = (DWORD*)(lpMovEax + 1);  
  29.               *lpMovEaxValu = (DWORD)&DoJmpEntryPoint;  
  30.               lpJmp = (WORD*)(lpMovEax + 5);  
  31.               *lpJmp = 0xE0FF;  // (FF E0)  
  32.               VirtualProtect(lpMovEax, 2*sizeof(DWORD), fOld, &fNew);  
  33.        }  
  34.        return TRUE;  
  35. }  
  36. // 转入处理程序  
  37. DWORD*      lpMovEax;  
  38. DWORD fNew, fOld;  
  39. void __declspec(naked) DoJmpEntryPoint ()  
  40. {  
  41.   // 恢复LoadLibrary后面的代码  
  42.        _gfNew = PAGE_READWRITE;  
  43.        _glpMovEax = (DWORD*)_lpCode.OldAddr;  
  44.        VirtualProtect(_glpMovEax, 2*sizeof(DWORD), _gfNew, &_gfOld);  
  45.        *_glpMovEax = _lpCode.OldCode[0];  
  46.        *(_glpMovEax + 1) = _lpCode.OldCode[1];  
  47.        VirtualProtect(_glpMovEax, 2*sizeof(DWORD), _gfOld, &_gfNew);  


第八步:目标进程 Jmp 至原来的入口,继续运行程序。
[cpp]  view plain copy
  1. // 跳至目标代码的入口  
  2.        _asm       popad  
  3.        _asm       jmp _lpCode.lpEntryPoint  
  4. }  

这样就实现了原来的目标,将 DLL 的注入放在目标进程的入口运行,实现了目标进程运行之前运行 我们的注入 Dll 的功能。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CreateProcess注入方法 的相关文章

  • CreateProcess注入方法

    采用 CreateProcess 的方法 xff0c 实现起来比较复杂 xff0c 但没有上面几种方法的局限性 且可以用其他工 具 xff08 VC 等 xff09 调试注入的 DLL 下面进行介绍 原理如下 xff1a 1 xff0e 用
  • CreateProcess 在 Windows 7 下不会创建额外的控制台窗口?

    我正在尝试使用 CreateProcess 运行一个进程 并在单独的控制台窗口中独立运行它 我可以使用 system 函数来实现这一点 但我更喜欢 CreateProcess 因为它使我可以指定环境和工作目录 获取进程的句柄 以及在需要时通
  • 如何确定生成的进程何时准备就绪? (使用 CreateProcess() 和 FindWindow())

    这应该很简单 我正在创建一个程序 该程序使用 win32 生成一个进程CreateProcess 功能 加载此进程后 我使用以下命令找到它的窗口FindWindow并使用它发送消息SendMessage 问题是 我如何知道该窗口何时准备好接
  • forking() 和 CreateProcess()

    forking 和 CreateProcess 带有所有必需的参数 对于 Linux 和 WinXP 来说分别是一样的吗 如果它们不同 那么有人可以解释这两种情况下发生的情况的差异吗 Thanks 他们在不同的系统上做不同的事情 Creat
  • 从 PHP 执行程序会挂起 APACHE

    您好 提前感谢您的关注 在过去的两周里 我一直在与一些让我发疯的事情作斗争 我的 Windows 机器上安装了 APACHE 2 2 22 和 PHP 5 4 3 我试图从 PHP 脚本调用一个程序 该脚本同时调用另一个程序 这两个程序都是
  • 如何在没有 P/Invoke 的情况下从 C# 创建挂起进程?

    WinAPI CreateProcess 具有标志 CREATE SUSPENDED 因此可以在执行某些操作之前将进程附加到 JobObject 然后为其主线程调用 ResumeThread 我发现寻找解决方案的唯一方法是这个帖子11年前写
  • CreateProcess 和 CreatePipe 在 VC++ 中执行进程并以字符串形式返回输出

    我正在尝试使用CreateProcess and CreatePipe从 Visual Studio 2010 中的 Windows Forms C CLR 应用程序中执行进程 在我的 Windows 表单应用程序中 我想执行一个子进程 控
  • 如何用 C 语言向子进程传递输入并检索输出

    我在 Windows 中有一个 exe 程序 它在终端中的工作原理如下 gt program exe parameter01 file entry01 user types entry01 output01 entry02 user typ
  • 如何在CreateProcess实例化的命令中使用或扩展环境变量?

    下面的代码利用CreateProcess使用环境变量运行命令 在这里 它尝试运行notepad APPDATA test txt 如果我跑notepad APPDATA test txt直接在Windows CMD APPDATA 将被扩展
  • CreateProcess API 的安全问题

    客观的 我正在尝试将一些文件从客户端发送到服务器 我正在使用 rsync 来传输数据 我正在使用 CreateProcess APi 并传递 rsync 路径以及参数 正面案例 当我从本地驱动器 如 C 发送数据时 我的 Windows 安
  • AppCertDlls:病毒导致 Win32 上的进程创建速度减慢

    大约两个月来 我在 Windows XP Home SP3 上遭受了严重的进程创建惩罚 这个问题在创建大量进程的任务中最为明显且烦人 例如 shell 脚本 顺便说一句 Cygwin 上的 bash 脚本 Makefile 或解压 IzPa
  • 使用 CreateProcess 运行批处理文件

    我正在尝试使用 CreateProcess 启动一个新的环境块并在新的环境块中运行批处理文件 我已经阅读了 CreateProcess 的 msdn 示例 并得出了如下所示的代码 发生了什么 它将打开新的命令提示符 并停在那里 由于某种原因
  • C++ 从 CreateProcess() 获取 UTF-8 输出

    我无法让它工作 所以我得到 UTF 8 输出CreateProcess into wstring 目前我正在运行此方法来执行此操作 但没有 UTF 8 输出 HANDLE g hChildStd OUT Rd NULL HANDLE g h
  • subprocess.Popen 如何在 Windows 上与 shell=False 一起使用?

    我想了解如何子进程 Popen https docs python org 3 library subprocess html subprocess Popen在 Windows 上工作时shell False 特别是 底层算法如何考虑环境
  • 为什么 CreateProcess 在 Windows Server 2003 64 位中失败?

    我们有一个 32 位应用程序 它在其进程中启动其他 32 位应用程序 该应用程序在其他 64 位平台上运行良好 但在 Windows Server 2003 64 位平台上 我们在尝试启动应用程序时遇到错误 error 193 not a
  • Win32 - 作为普通用户进程启动最高可用子进程

    假设您的 Windows 用户帐户位于 Admin 组中 启用了 UAC 并且您正在以普通用户权限运行某些程序 A A从不要求提升 也从未得到提升 现在假设 A 想要启动程序 B 该程序的清单中具有 HighestAvailable 如果
  • CreateProcess 执行 Windows 命令

    我正在尝试使用 CreateProcess 函数执行 dos 命令 LPWSTR cmd LPWSTR QString C windows system32 cmd exe subst DLetter mountPath utf16 STA
  • createprocess默认暂停[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我在 dl
  • 使用CreateProcess调用exe文件?

    一直尝试从我的 Visual Studio C 应用程序调用 Truecrypt exe 但是CreateProcess只是不工作 GetLastError shows 127 目的是调用exe不显示命令窗口 请帮忙 我尝试过搜索并阅读Cr
  • 在调试器下运行时,AssignProcessToJobObject 失败并出现“访问被拒绝”错误

    You do AssignProcessToJobObject并且仅当您在调试器中运行时才会因 访问被拒绝 而失败 为什么是这样 这个问题让我困惑了大约30分钟 首先 您可能需要在您的应用程序中嵌入一个 UAC 清单 正如这里所建议的 ht

随机推荐

  • Linux服务器 安装Pytorch GPU版本

    实验室服务器重做系统之后 xff0c 之间搭建的Python环境已甚嚣尘上 xff0c 只好从头再来 但是过程中遇到很多莫名其妙的bug xff0c 特此立章记录 xff0c 望对他人有所帮助 作为一个深度学习的初学者 xff0c 个人对所
  • 鼠标悬停效果 PPT制作

    鼠标悬停效果实现 在制作PPT时 xff0c 有时候需要实现鼠标的悬停效果 xff0c 即将鼠标放置在某个按钮或图片上 xff0c 实现动态变化的效果 目标是 xff1a 当鼠标悬停在一些人物名字上时 xff0c 出现该人物的个人信息 具体
  • 谷歌学术——下载论文

    一些同学在找论文的时候 xff0c 在学校数据库找不到 xff0c 因此可以使用谷歌学术来找 但是国内被墙了 xff0c 无法访问 xff0c 所以可以使用镜像服务器 首先进入谷歌镜像 xff1a 镜像网站 xff08 https ac s
  • Ubuntu 22.04 安装vm-tools

    安装过程一路心酸 xff0c 大家慎重 在Vmware中新建虚拟机之后 xff0c 发现没有办法传输文件和进行随窗口的视图变化 xff0c 打算安装vm tools 但是在Ubuntu 22 04 中 xff0c 如果使用Vmware自带的
  • LD文件 详解

    ld 组合了许多对象文件和归档文件 xff0c 重新定位它们的数据并绑定符号引用 通常编译程序的最后一步是运行 ld 每个可加载或可分配的输出节都有两个地址 第一个是 VMA xff0c 即虚拟内存地址 这是运行输出文件时该节所拥有的地址
  • 【Linux0.11 源码历险记 2】《保护模式》

    继续跟着stup s 来看 xff1a lidt idt 48 load idt with 0 0 lgdt gdt 48 load gdt with whatever appropriate idt 48 word 0 idt limit
  • 【Linux0.11 源码历险记 3】《开启分页》

    下面我们就正式进入head s 的代码 xff1a text globl idt gdt pg dir tmp floppy area pg dir startup 32 movl 0x10 eax mov ax ds mov ax es
  • HttpClient使用HttpGet进行json数据传输

    JSON字符串需要用urlencoding编码对绝大多数HTTP client而言 xff0c URL长度都有上限 xff0c 所以不能传太大的JSON xff0c 一般而言几K应该没问题 xff0c 但是再长点就不好说了 import j
  • 【Linux 内核技术】RCU

    在阅读linux 3 10版本的socket 一节源码时 xff0c 遇到了一个 span class token function rcu dereference span span class token punctuation spa
  • 选择题改错

    一 单选 1 2 以下程序的运行结果是 xff08 xff09 int main void printf 34 s 5 3s n 34 34 computer 34 34 computer 34 return 0 A A computer
  • 安装程序的安装界面为乱码的问题

    有的时候程序的安装界面为乱码 xff0c 多出在msi程序中 xff0c 这其实是AppLocale的bug导致的 xff0c 解决的办法不用删除AppLocale xff0c 只需要到c windows AppPatch下 xff0c 删
  • 周星馳 電影經典對白

    周星馳 電影經典對白 http www jd bbs com viewthread php tid 61 1209979 amp extra 61 page 3D1 1 曾經有一份真誠的愛擺在我的面前 xff0c 但是我沒有珍惜 xff0c
  • Eclipse环境搭建

    Eclipse 环境搭建 C 43 43 还没有写完 xff5e xff5e xff5e xff5e 最近 xff0c 在作一个项目 xff0c 要求所有的软件 xff0c 包括操作系统 开发工具 等 xff0c 所有的软件都要使用正版的
  • 为什么要学习python

    时隔多年以后 xff0c 我又回归CSDN了 xff0c 回来学习学习 刚开始工作的时候 xff0c 在CSDN这里找各种资源 xff0c 各种学习 xff0c 请教 xff0c 等等 xff0c 确实学到了不少 也许是因为自己是做嵌入式开
  • 汇编

    hu bi n 1 动词 xff0c 把资料或文章等编辑在一起 2 名词 xff0c 编辑在一起的资料 xff0c 文献 汇编简介 汇编语言 Assembly Language 是面向机器的程序设计语言 汇编语言中 xff0c 用助记符 M
  • 杨石头智立方47:你我都必须学习的十大管理原则

    http blog sina com cn s blog 4ce6ecc60100fy5v html tj 61 1 一 素养 蓝斯登原则 xff1a 在你往上爬的时候 xff0c 一定要保持梯子的整洁 xff0c 否则你下来时可能会滑倒
  • Media change: lase insert the disc labled

    在Debian中使用apt get安装软件包时经常会提示让你插入netinst的光盘 xff1a Media change please insert the disc labeled 当没有时就无法进行安装了 xff0c 这时可以打开文件
  • Source Insight使用教程

    作为一个开放源代码的操作系统 xff0c Linux 附带的源代码库使得广大爱好者有了一个广泛学习 深入钻研的机会 xff0c 特别是Linux 内核的组织极为复杂 xff0c 同时 xff0c 又不能像windows 平台的程序一样 xf
  • 注册表ShellIconOverlayIdentifiers中没有svn相关的选项

    此问题最初是由于svn不显示Icon入手排查的 打开注册表 HKEY LOCAL MACHINE SOFTWARE Microsoft Windows CurrentVersion Explorer ShellIconOverlayIden
  • CreateProcess注入方法

    采用 CreateProcess 的方法 xff0c 实现起来比较复杂 xff0c 但没有上面几种方法的局限性 且可以用其他工 具 xff08 VC 等 xff09 调试注入的 DLL 下面进行介绍 原理如下 xff1a 1 xff0e 用