天气与日历 切换到窄版

 找回密码
 立即注册

QQ登录

只需一步,快速开始

【好消息,好消息,好消息】VIP会员可以发表文章赚积分啦 !
查看: 490|回复: 0

[C++教程] VC2015,C++内存中运行EXE文件

[复制链接]

3188

主题

4

回帖

3290

积分

管理员

积分
3290
发表于 2024-2-26 13:14:52 | 显示全部楼层 |阅读模式
VC2015,C++内存中运行EXE文件


项目中所用的源码主要源自于网络,修正一些错误后,源码如下,此源码在VC6中可以正常编译,
但在VC2015中,就会出现一些错误,本项目源码已经把错误修正,可以正常编译并运行,感兴趣的可以下载。
本例中默认调用C:\111.EXE,测试时,请在这个位置放一个可以正常打开的程序,运行本例程序即可正常调用。
主要源码如下:

  1. #include "stdafx.h"
  2. #include "stdio.h"
  3. #include "windows.h"

  4. typedef IMAGE_SECTION_HEADER(*PIMAGE_SECTION_HEADERS)[1];

  5. // 计算对齐后的大小   
  6. unsigned long GetAlignedSize(unsigned long Origin, unsigned long Alignment)
  7. {
  8.         return (Origin + Alignment - 1) / Alignment * Alignment;
  9. }

  10. // 计算加载pe并对齐需要占用多少内存   
  11. // 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0   
  12. unsigned long CalcTotalImageSize(PIMAGE_DOS_HEADER MzH
  13.         , unsigned long FileLen
  14.         , PIMAGE_NT_HEADERS peH
  15.         , PIMAGE_SECTION_HEADERS peSecH)
  16. {
  17.         unsigned long res;
  18.         // 计算pe头的大小   
  19.         res = GetAlignedSize(peH->OptionalHeader.SizeOfHeaders
  20.                 , peH->OptionalHeader.SectionAlignment
  21.         );

  22.         // 计算所有节的大小   
  23.         for (int i = 0; i < peH->FileHeader.NumberOfSections; ++i)
  24.         {
  25.                 // 超出文件范围   
  26.                 if (peSecH[i]->PointerToRawData + peSecH[i]->SizeOfRawData > FileLen)
  27.                         return 0;
  28.                 else if (peSecH[i]->VirtualAddress)//计算对齐后某节的大小   
  29.                 {
  30.                         if (peSecH[i]->Misc.VirtualSize)
  31.                         {
  32.                                 res = GetAlignedSize(peSecH[i]->VirtualAddress + peSecH[i]->Misc.VirtualSize
  33.                                         , peH->OptionalHeader.SectionAlignment
  34.                                 );
  35.                         }
  36.                         else
  37.                         {
  38.                                 res = GetAlignedSize(peSecH[i]->VirtualAddress + peSecH[i]->SizeOfRawData
  39.                                         , peH->OptionalHeader.SectionAlignment
  40.                                 );
  41.                         }
  42.                 }
  43.                 else if (peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData)
  44.                 {
  45.                         res += GetAlignedSize(peSecH[i]->SizeOfRawData
  46.                                 , peH->OptionalHeader.SectionAlignment
  47.                         );
  48.                 }
  49.                 else
  50.                 {
  51.                         res += GetAlignedSize(peSecH[i]->Misc.VirtualSize
  52.                                 , peH->OptionalHeader.SectionAlignment
  53.                         );
  54.                 }// if_else   
  55.         }// for   

  56.         return res;
  57. }




  58. // 加载pe到内存并对齐所有节   
  59. BOOL AlignPEToMem(void *Buf
  60.         , long Len
  61.         , PIMAGE_NT_HEADERS &peH
  62.         , PIMAGE_SECTION_HEADERS &peSecH
  63.         , void *&Mem
  64.         , unsigned long &ImageSize)
  65. {
  66.         PIMAGE_DOS_HEADER SrcMz;// DOS头   
  67.         PIMAGE_NT_HEADERS SrcPeH;// PE头   
  68.         PIMAGE_SECTION_HEADERS SrcPeSecH;// 节表   

  69.         SrcMz = (PIMAGE_DOS_HEADER)Buf;

  70.         if (Len < sizeof(IMAGE_DOS_HEADER))
  71.                 return FALSE;

  72.         if (SrcMz->e_magic != IMAGE_DOS_SIGNATURE)
  73.                 return FALSE;

  74.         if (Len < SrcMz->e_lfanew + (long)sizeof(IMAGE_NT_HEADERS))
  75.                 return FALSE;

  76.         SrcPeH = (PIMAGE_NT_HEADERS)((int)SrcMz + SrcMz->e_lfanew);
  77.         if (SrcPeH->Signature != IMAGE_NT_SIGNATURE)
  78.                 return FALSE;

  79.         if ((SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL) ||
  80.                 (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0) ||
  81.                 (SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)))
  82.         {
  83.                 return FALSE;
  84.         }


  85.         SrcPeSecH = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS));
  86.         ImageSize = CalcTotalImageSize(SrcMz, Len, SrcPeH, SrcPeSecH);

  87.         if (ImageSize == 0)
  88.                 return FALSE;

  89.         Mem = VirtualAlloc(NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存   
  90.         if (Mem != NULL)
  91.         {
  92.                 // 计算需要复制的PE头字节数   
  93.                 unsigned long l = SrcPeH->OptionalHeader.SizeOfHeaders;
  94.                 for (int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i)
  95.                 {
  96.                         if ((SrcPeSecH[i]->PointerToRawData) && (SrcPeSecH[i]->PointerToRawData < l))
  97.                         {
  98.                                 l = SrcPeSecH[i]->PointerToRawData;
  99.                         }
  100.                 }
  101.                 memmove(Mem, SrcMz, l);
  102.                 peH = (PIMAGE_NT_HEADERS)((int)Mem + ((PIMAGE_DOS_HEADER)Mem)->e_lfanew);
  103.                 peSecH = (PIMAGE_SECTION_HEADERS)((int)peH + sizeof(IMAGE_NT_HEADERS));

  104.                 void *Pt = (void *)((unsigned long)Mem
  105.                         + GetAlignedSize(peH->OptionalHeader.SizeOfHeaders
  106.                                 , peH->OptionalHeader.SectionAlignment)
  107.                         );

  108.                 for (int i = 0; i < peH->FileHeader.NumberOfSections; ++i)
  109.                 {
  110.                         // 定位该节在内存中的位置   
  111.                         if (peSecH[i]->VirtualAddress)
  112.                                 Pt = (void *)((unsigned long)Mem + peSecH[i]->VirtualAddress);

  113.                         if (peSecH[i]->SizeOfRawData)
  114.                         {
  115.                                 // 复制数据到内存   
  116.                                 memmove(Pt, (const void *)((unsigned long)(SrcMz)+peSecH[i]->PointerToRawData), peSecH[i]->SizeOfRawData);
  117.                                 if (peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData)
  118.                                         Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->SizeOfRawData, peH->OptionalHeader.SectionAlignment));
  119.                                 else // pt 定位到下一节开始位置   
  120.                                         Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));
  121.                         }
  122.                         else
  123.                         {
  124.                                 Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));
  125.                         }
  126.                 }
  127.         }
  128.         return TRUE;
  129. }



  130. typedef void *(__stdcall *pfVirtualAllocEx)(unsigned long, void *, unsigned long, unsigned long, unsigned long);
  131. pfVirtualAllocEx MyVirtualAllocEx = NULL;

  132. BOOL IsNT()
  133. {
  134.         return MyVirtualAllocEx != NULL;
  135. }

  136. // 生成外壳程序命令行   
  137. char *PrepareShellExe(char *CmdParam, unsigned long BaseAddr, unsigned long ImageSize)
  138. {
  139.         if (IsNT())
  140.         {
  141.                 char *Buf = new char[256];
  142.                 memset(Buf, 0, 256);
  143.                 GetModuleFileName(0, Buf, 256);
  144.                 strcat(Buf, CmdParam);
  145.                 return Buf; // 请记得释放内存;-)   
  146.         }
  147.         else
  148.         {
  149.                 // Win98下的处理请参考原文;-)   
  150.                 // http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03   
  151.                 return NULL;
  152.         }
  153. }

  154. // 是否包含可重定向列表   
  155. BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)
  156. {
  157.         return (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
  158.                 && (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
  159. }




  160. #pragma pack(push, 1)   
  161. typedef struct ImageBaseRelocation {
  162.         unsigned long VirtualAddress;
  163.         unsigned long SizeOfBlock;
  164. }*PImageBaseRelocation;
  165. #pragma pack(pop)   

  166. // 重定向PE用到的地址   
  167. void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase)
  168. {
  169.         unsigned long Delta = (unsigned long)NewBase - peH->OptionalHeader.ImageBase;
  170.         PImageBaseRelocation p = (PImageBaseRelocation)((unsigned long)OldBase
  171.                 + peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
  172.         while (p->VirtualAddress + p->SizeOfBlock)
  173.         {
  174.                 unsigned short *pw = (unsigned short *)((int)p + sizeof(*p));
  175.                 for (unsigned int i = 1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i)
  176.                 {
  177.                         if ((*pw) & 0xF000 == 0x3000) {
  178.                                 unsigned long *t = (unsigned long *)((unsigned long)(OldBase)+p->VirtualAddress + ((*pw) & 0x0FFF));
  179.                                 *t += Delta;
  180.                         }
  181.                         ++pw;
  182.                 }
  183.                 p = (PImageBaseRelocation)pw;
  184.         }
  185. }

  186. // 卸载原外壳占用内存   
  187. BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)
  188. {
  189.         typedef unsigned long(__stdcall *pfZwUnmapViewOfSection)(unsigned long, unsigned long);
  190.         pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;
  191.         BOOL res = FALSE;
  192.         HMODULE m = LoadLibrary("ntdll.dll");
  193.         if (m) {
  194.                 ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");
  195.                 if (ZwUnmapViewOfSection)
  196.                         res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);
  197.                 FreeLibrary(m);
  198.         }
  199.         return res;
  200. }

  201. // 创建外壳进程并获取其基址、大小和当前运行状态   
  202. BOOL CreateChild(char *Cmd, CONTEXT &Ctx, HANDLE &ProcHnd, HANDLE &ThrdHnd,
  203.         unsigned long &ProcId, unsigned long &BaseAddr, unsigned long &ImageSize)
  204. {
  205.         STARTUPINFOA si;
  206.         PROCESS_INFORMATION pi;
  207.         unsigned long old;
  208.         MEMORY_BASIC_INFORMATION MemInfo;
  209.         memset(&si, 0, sizeof(si));
  210.         memset(&pi, 0, sizeof(pi));
  211.         si.cb = sizeof(si);

  212.         BOOL res = CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); // 以挂起方式运行进程;   
  213.         if (res) {
  214.                 ProcHnd = pi.hProcess;
  215.                 ThrdHnd = pi.hThread;
  216.                 ProcId = pi.dwProcessId;
  217.                 // 获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址   
  218.                 Ctx.ContextFlags = CONTEXT_FULL;
  219.                 GetThreadContext(ThrdHnd, &Ctx);
  220.                 ReadProcessMemory(ProcHnd, (void *)(Ctx.Ebx + 8), &BaseAddr, sizeof(unsigned long), &old); // 读取加载基址   
  221.                 void *p = (void *)BaseAddr;
  222.                 // 计算外壳进程占有的内存   
  223.                 while (VirtualQueryEx(ProcHnd, p, &MemInfo, sizeof(MemInfo)))
  224.                 {
  225.                         if (MemInfo.State = MEM_FREE) break;
  226.                         p = (void *)((unsigned long)p + MemInfo.RegionSize);
  227.                 }
  228.                 ImageSize = (unsigned long)p - (unsigned long)BaseAddr;
  229.         }
  230.         return res;
  231. }

  232. // 创建外壳进程并用目标进程替换它然后执行   
  233. HANDLE AttachPE(char *CmdParam, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH,
  234.         void *Ptr, unsigned long ImageSize, unsigned long &ProcId)
  235. {
  236.         HANDLE res = INVALID_HANDLE_VALUE;
  237.         CONTEXT Ctx;
  238.         HANDLE Thrd;
  239.         unsigned long Addr, Size;
  240.         char *s = PrepareShellExe(CmdParam, peH->OptionalHeader.ImageBase, ImageSize);
  241.         if (s == NULL) return res;
  242.         if (CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size)) {
  243.                 void *p = NULL;
  244.                 unsigned long old;
  245.                 if ((peH->OptionalHeader.ImageBase == Addr) && (Size >= ImageSize)) {// 外壳进程可以容纳目标进程并且加载地址一致   
  246.                         p = (void *)Addr;
  247.                         VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE, &old);
  248.                 }
  249.                 else if (IsNT()) {
  250.                         if (UnloadShell(res, Addr)) {// 卸载外壳进程占有内存   
  251.                                 p = MyVirtualAllocEx((unsigned long)res, (void *)peH->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  252.                         }
  253.                         if ((p == NULL) && HasRelocationTable(peH)) {// 分配内存失败并且目标进程支持重定向   
  254.                                 p = MyVirtualAllocEx((unsigned long)res, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  255.                                 if (p) DoRelocation(peH, Ptr, p); // 重定向   
  256.                         }
  257.                 }
  258.                 if (p) {
  259.                         WriteProcessMemory(res, (void *)(Ctx.Ebx + 8), &p, sizeof(DWORD), &old); // 重置目标进程运行环境中的基址   
  260.                         peH->OptionalHeader.ImageBase = (unsigned long)p;
  261.                         if (WriteProcessMemory(res, p, Ptr, ImageSize, &old)) {// 复制PE数据到目标进程   
  262.                                 Ctx.ContextFlags = CONTEXT_FULL;
  263.                                 if ((unsigned long)p == Addr)
  264.                                         Ctx.Eax = peH->OptionalHeader.ImageBase + peH->OptionalHeader.AddressOfEntryPoint; // 重置运行环境中的入口地址   
  265.                                 else
  266.                                         Ctx.Eax = (unsigned long)p + peH->OptionalHeader.AddressOfEntryPoint;
  267.                                 SetThreadContext(Thrd, &Ctx);// 更新运行环境   
  268.                                 ResumeThread(Thrd);// 执行   
  269.                                 CloseHandle(Thrd);
  270.                         }
  271.                         else {// 加载失败,杀掉外壳进程   
  272.                                 TerminateProcess(res, 0);
  273.                                 CloseHandle(Thrd);
  274.                                 CloseHandle(res);
  275.                                 res = INVALID_HANDLE_VALUE;
  276.                         }
  277.                 }
  278.                 else {// 加载失败,杀掉外壳进程   
  279.                         TerminateProcess(res, 0);
  280.                         CloseHandle(Thrd);
  281.                         CloseHandle(res);
  282.                         res = INVALID_HANDLE_VALUE;
  283.                 }
  284.         }
  285.         delete[] s;
  286.         return res;
  287. }




  288. /*******************************************************\
  289. { ******************************************************* }
  290. { *                 从内存中加载并运行exe               * }
  291. { ******************************************************* }
  292. { * 参数:                                                }
  293. { * Buffer: 内存中的exe地址                               }
  294. { * Len: 内存中exe占用长度                                }
  295. { * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数)}
  296. { * ProcessId: 返回的进程Id                               }
  297. { * 返回值: 如果成功则返回进程的Handle(ProcessHandle),   }
  298. {            如果失败则返回INVALID_HANDLE_VALUE           }
  299. { ******************************************************* }
  300. \*******************************************************/
  301. HANDLE MemExecute(void *ABuffer, long Len, char *CmdParam, unsigned long *ProcessId)
  302. {
  303.         HANDLE res = INVALID_HANDLE_VALUE;
  304.         PIMAGE_NT_HEADERS peH;
  305.         PIMAGE_SECTION_HEADERS peSecH;
  306.         void *Ptr;
  307.         unsigned long peSz;
  308.         if (AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))
  309.         {
  310.                 res = AttachPE(CmdParam, peH, peSecH, Ptr, peSz, *ProcessId);
  311.                 VirtualFree(Ptr, peSz, MEM_DECOMMIT);
  312.         }
  313.         return res;
  314. }

  315. // 初始化   
  316. class CInit
  317. {
  318. public:
  319.         CInit()
  320.         {
  321.                 MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(GetModuleHandle("Kernel32.dll"), "VirtualAllocEx");
  322.         }
  323. }Init;




  324. int APIENTRY WinMain(HINSTANCE hInstance,
  325.         HINSTANCE hPrevInstance,
  326.         LPSTR     lpCmdLine,
  327.         int       nCmdShow)
  328. {
  329.         HANDLE hFile = NULL;
  330.         hFile = CreateFile("c:\\111.exe", GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);

  331.         if (hFile == INVALID_HANDLE_VALUE)
  332.                 return -1;
  333.         ::SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
  334.         DWORD dwFileSize = ::GetFileSize(hFile, NULL);

  335.         LPBYTE pBuf = new BYTE[dwFileSize];
  336.         memset(pBuf, 0, dwFileSize);

  337.         DWORD dwNumberOfBytesRead = 0;
  338.         ::ReadFile(hFile
  339.                 , pBuf
  340.                 , dwFileSize
  341.                 , &dwNumberOfBytesRead
  342.                 , NULL
  343.         );

  344.         ::CloseHandle(hFile);

  345.         unsigned long ulProcessId = 0;
  346.         MemExecute(pBuf, dwFileSize, "", &ulProcessId);
  347.         delete[] pBuf;


  348.         return 0;
  349. }
复制代码


资源下载.txt

108 Bytes, 下载次数: 1

售价: 15 金钱  [记录]  [购买]

VC2015,C++内存中运行EXE文件

相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员5折;永久VIP免费
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
快速回复 返回顶部 返回列表