直接运行内存中的程序

来源:互联网 发布:doom4优化 编辑:程序博客网 时间:2024/05/16 12:34
     哈哈,想不到有人居然把这种代码也搞出来了。
    Windows的PE加载器在启动程序的时候,会将磁盘上的文件加载到内存,然后做很多操作,如函数导入表重定位,变量预处理之类的。这位仁兄等于是自己写了一个PE加载器。直接将内存中的程序启动。记得以前的“红色代码”病毒也有相同的特性。
    直接启动内存中的程序相当于加了一个壳,可以把程序加密保存,运行时解密到内存,然后启动,不过对于增加破解难度还要稍微复杂点。否则人家把内存中的进程DUMP出来然后修复导入表就被拖出来了。

代码自己改吧

#include "stdafx.h"      typedef IMAGE_SECTION_HEADER (*PIMAGE_SECTION_HEADERS)[1];     // 计算对齐后的大小   unsigned long GetAlignedSize(unsigned long Origin, unsigned long Alignment)   {       return (Origin + Alignment - 1) / Alignment * Alignment;   }     // 计算加载pe并对齐需要占用多少内存   // 未直接使用OptionalHeader.SizeOfImage作为结果是因为据说有的编译器生成的exe这个值会填0   unsigned long CalcTotalImageSize(PIMAGE_DOS_HEADER MzH                                    , unsigned long FileLen                                    , PIMAGE_NT_HEADERS peH                                    , PIMAGE_SECTION_HEADERS peSecH)   {       unsigned long res;       // 计算pe头的大小       res = GetAlignedSize( peH->OptionalHeader.SizeOfHeaders           , peH->OptionalHeader.SectionAlignment           );         // 计算所有节的大小       for( int i = 0; i < peH->FileHeader.NumberOfSections; ++i)       {           // 超出文件范围           if(peSecH[i]->PointerToRawData + peSecH[i]->SizeOfRawData > FileLen)               return 0;           else if(peSecH[i]->VirtualAddress)//计算对齐后某节的大小           {               if(peSecH[i]->Misc.VirtualSize)               {                   res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->Misc.VirtualSize                       , peH->OptionalHeader.SectionAlignment                       );               }               else              {                   res = GetAlignedSize( peSecH[i]->VirtualAddress + peSecH[i]->SizeOfRawData                       , peH->OptionalHeader.SectionAlignment                       );               }           }           else if( peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData )           {               res += GetAlignedSize( peSecH[i]->SizeOfRawData                   , peH->OptionalHeader.SectionAlignment                   );           }           else          {               res += GetAlignedSize( peSecH[i]->Misc.VirtualSize                   , peH->OptionalHeader.SectionAlignment                   );           }// if_else       }// for              return res;   }           // 加载pe到内存并对齐所有节   BOOL AlignPEToMem( void *Buf                     , long Len                     , PIMAGE_NT_HEADERS &peH                     , PIMAGE_SECTION_HEADERS &peSecH                     , void *&Mem                     , unsigned long &ImageSize)   {       PIMAGE_DOS_HEADER SrcMz;// DOS头       PIMAGE_NT_HEADERS SrcPeH;// PE头       PIMAGE_SECTION_HEADERS SrcPeSecH;// 节表              SrcMz = (PIMAGE_DOS_HEADER)Buf;         if( Len < sizeof(IMAGE_DOS_HEADER) )            return FALSE;              if( SrcMz->e_magic != IMAGE_DOS_SIGNATURE )           return FALSE;              if( Len < SrcMz->e_lfanew + (long)sizeof(IMAGE_NT_HEADERS) )           return FALSE;         SrcPeH = (PIMAGE_NT_HEADERS)((int)SrcMz + SrcMz->e_lfanew);       if( SrcPeH->Signature != IMAGE_NT_SIGNATURE )           return FALSE;         if( (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_DLL) ||           (SrcPeH->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE == 0) ||           (SrcPeH->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER)) )       {           return FALSE;       }           SrcPeSecH = (PIMAGE_SECTION_HEADERS)((int)SrcPeH + sizeof(IMAGE_NT_HEADERS));       ImageSize = CalcTotalImageSize( SrcMz, Len, SrcPeH, SrcPeSecH);         if( ImageSize == 0 )           return FALSE;              Mem = VirtualAlloc( NULL, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE); // 分配内存       if( Mem != NULL )       {           // 计算需要复制的PE头字节数           unsigned long l = SrcPeH->OptionalHeader.SizeOfHeaders;           for( int i = 0; i < SrcPeH->FileHeader.NumberOfSections; ++i)           {               if( (SrcPeSecH[i]->PointerToRawData) &&                   (SrcPeSecH[i]->PointerToRawData < l) )               {                   l = SrcPeSecH[i]->PointerToRawData;               }           }           memmove( Mem, SrcMz, l);           peH = (PIMAGE_NT_HEADERS)((int)Mem + ((PIMAGE_DOS_HEADER)Mem)->e_lfanew);           peSecH = (PIMAGE_SECTION_HEADERS)((int)peH + sizeof(IMAGE_NT_HEADERS));             void *Pt = (void *)((unsigned long)Mem                + GetAlignedSize( peH->OptionalHeader.SizeOfHeaders               , peH->OptionalHeader.SectionAlignment)               );             for( i = 0; i < peH->FileHeader.NumberOfSections; ++i)           {               // 定位该节在内存中的位置               if(peSecH[i]->VirtualAddress)                   Pt = (void *)((unsigned long)Mem + peSecH[i]->VirtualAddress);                 if(peSecH[i]->SizeOfRawData)               {                   // 复制数据到内存                   memmove(Pt, (const void *)((unsigned long)(SrcMz) + peSecH[i]->PointerToRawData), peSecH[i]->SizeOfRawData);                   if(peSecH[i]->Misc.VirtualSize < peSecH[i]->SizeOfRawData)                       Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->SizeOfRawData, peH->OptionalHeader.SectionAlignment));                   else // pt 定位到下一节开始位置                       Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));               }               else              {                   Pt = (void *)((unsigned long)Pt + GetAlignedSize(peSecH[i]->Misc.VirtualSize, peH->OptionalHeader.SectionAlignment));               }           }       }       return TRUE;   }         typedef void *(__stdcall *pfVirtualAllocEx)(unsigned long, void *, unsigned long, unsigned long, unsigned long);   pfVirtualAllocEx MyVirtualAllocEx = NULL;     BOOL IsNT()   {       return MyVirtualAllocEx!=NULL;   }     // 生成外壳程序命令行   char *PrepareShellExe(char *CmdParam, unsigned long BaseAddr, unsigned long ImageSize)   {       if(IsNT())       {           char *Buf = new char[256];           memset(Buf, 0, 256);           GetModuleFileName(0, Buf, 256);           strcat(Buf, CmdParam);           return Buf; // 请记得释放内存;-)       }       else      {           // Win98下的处理请参考原文;-)           // http://community.csdn.net/Expert/topic/4416/4416252.xml?temp=8.709133E-03           return NULL;       }   }     // 是否包含可重定向列表   BOOL HasRelocationTable(PIMAGE_NT_HEADERS peH)   {       return (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)           && (peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);   }           #pragma pack(push, 1)   typedef struct{       unsigned long VirtualAddress;       unsigned long SizeOfBlock;   } *PImageBaseRelocation;   #pragma pack(pop)     // 重定向PE用到的地址   void DoRelocation(PIMAGE_NT_HEADERS peH, void *OldBase, void *NewBase)   {       unsigned long Delta = (unsigned long)NewBase - peH->OptionalHeader.ImageBase;       PImageBaseRelocation p = (PImageBaseRelocation)((unsigned long)OldBase            + peH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);       while(p->VirtualAddress + p->SizeOfBlock)       {           unsigned short *pw = (unsigned short *)((int)p + sizeof(*p));           for(unsigned int i=1; i <= (p->SizeOfBlock - sizeof(*p)) / 2; ++i)           {               if((*pw) & 0xF000 == 0x3000){                   unsigned long *t = (unsigned long *)((unsigned long)(OldBase) + p->VirtualAddress + ((*pw) & 0x0FFF));                   *t += Delta;               }               ++pw;           }           p = (PImageBaseRelocation)pw;       }   }     // 卸载原外壳占用内存   BOOL UnloadShell(HANDLE ProcHnd, unsigned long BaseAddr)   {       typedef unsigned long (__stdcall *pfZwUnmapViewOfSection)(unsigned long, unsigned long);       pfZwUnmapViewOfSection ZwUnmapViewOfSection = NULL;       BOOL res = FALSE;       HMODULE m = LoadLibrary("ntdll.dll");       if(m){           ZwUnmapViewOfSection = (pfZwUnmapViewOfSection)GetProcAddress(m, "ZwUnmapViewOfSection");           if(ZwUnmapViewOfSection)               res = (ZwUnmapViewOfSection((unsigned long)ProcHnd, BaseAddr) == 0);           FreeLibrary(m);       }       return res;   }     // 创建外壳进程并获取其基址、大小和当前运行状态   BOOL CreateChild(char *Cmd, CONTEXT &Ctx, HANDLE &ProcHnd, HANDLE &ThrdHnd,                     unsigned long &ProcId, unsigned long &BaseAddr, unsigned long &ImageSize)   {       STARTUPINFOA si;       PROCESS_INFORMATION pi;       unsigned long old;       MEMORY_BASIC_INFORMATION MemInfo;       memset(&si, 0, sizeof(si));       memset(&pi, 0, sizeof(pi));       si.cb = sizeof(si);              BOOL res = CreateProcess(NULL, Cmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); // 以挂起方式运行进程;       if(res){           ProcHnd = pi.hProcess;           ThrdHnd = pi.hThread;           ProcId = pi.dwProcessId;           // 获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址           Ctx.ContextFlags = CONTEXT_FULL;           GetThreadContext(ThrdHnd, &Ctx);           ReadProcessMemory(ProcHnd, (void *)(Ctx.Ebx+8), &BaseAddr, sizeof(unsigned long), &old); // 读取加载基址           void *p = (void *)BaseAddr;           // 计算外壳进程占有的内存           while(VirtualQueryEx(ProcHnd, p, &MemInfo, sizeof(MemInfo)))           {               if(MemInfo.State = MEM_FREE) break;               p = (void *)((unsigned long)p + MemInfo.RegionSize);           }           ImageSize = (unsigned long)p - (unsigned long)BaseAddr;       }       return res;   }     // 创建外壳进程并用目标进程替换它然后执行   HANDLE AttachPE(char *CmdParam, PIMAGE_NT_HEADERS peH, PIMAGE_SECTION_HEADERS peSecH,                    void *Ptr, unsigned long ImageSize, unsigned long &ProcId)   {       HANDLE res = INVALID_HANDLE_VALUE;       CONTEXT Ctx;       HANDLE Thrd;       unsigned long Addr, Size;       char *s = PrepareShellExe(CmdParam, peH->OptionalHeader.ImageBase, ImageSize);       if(s==NULL) return res;       if(CreateChild(s, Ctx, res, Thrd, ProcId, Addr, Size)){           void *p = NULL;           unsigned long old;           if((peH->OptionalHeader.ImageBase == Addr) && (Size >= ImageSize)){// 外壳进程可以容纳目标进程并且加载地址一致               p = (void *)Addr;               VirtualProtectEx(res, p, Size, PAGE_EXECUTE_READWRITE, &old);           }           else if(IsNT()){               if(UnloadShell(res, Addr)){// 卸载外壳进程占有内存                   p = MyVirtualAllocEx((unsigned long)res, (void *)peH->OptionalHeader.ImageBase, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);               }               if((p == NULL) && HasRelocationTable(peH)){// 分配内存失败并且目标进程支持重定向                   p = MyVirtualAllocEx((unsigned long)res, NULL, ImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);                   if(p) DoRelocation(peH, Ptr, p); // 重定向               }           }           if(p){               WriteProcessMemory(res, (void *)(Ctx.Ebx+8), &p, sizeof(DWORD), &old); // 重置目标进程运行环境中的基址               peH->OptionalHeader.ImageBase = (unsigned long)p;               if(WriteProcessMemory(res, p, Ptr, ImageSize, &old)){// 复制PE数据到目标进程                   Ctx.ContextFlags = CONTEXT_FULL;                   if((unsigned long)p == Addr)                       Ctx.Eax = peH->OptionalHeader.ImageBase + peH->OptionalHeader.AddressOfEntryPoint; // 重置运行环境中的入口地址                   else                      Ctx.Eax = (unsigned long)p + peH->OptionalHeader.AddressOfEntryPoint;                   SetThreadContext(Thrd, &Ctx);// 更新运行环境                   ResumeThread(Thrd);// 执行                   CloseHandle(Thrd);               }               else{// 加载失败,杀掉外壳进程                   TerminateProcess(res, 0);                   CloseHandle(Thrd);                   CloseHandle(res);                   res = INVALID_HANDLE_VALUE;               }           }           else{// 加载失败,杀掉外壳进程               TerminateProcess(res, 0);               CloseHandle(Thrd);               CloseHandle(res);               res = INVALID_HANDLE_VALUE;           }       }       delete[] s;       return res;   }            /*******************************************************\  { ******************************************************* }  { *                 从内存中加载并运行exe               * }  { ******************************************************* }  { * 参数:                                                }  { * Buffer: 内存中的exe地址                               }  { * Len: 内存中exe占用长度                                }  { * CmdParam: 命令行参数(不包含exe文件名的剩余命令行参数)}  { * ProcessId: 返回的进程Id                               }  { * 返回值: 如果成功则返回进程的Handle(ProcessHandle),   }  {            如果失败则返回INVALID_HANDLE_VALUE           }  { ******************************************************* }   \*******************************************************/  HANDLE MemExecute(void *ABuffer, long Len, char *CmdParam, unsigned long *ProcessId)   {       HANDLE res = INVALID_HANDLE_VALUE;       PIMAGE_NT_HEADERS peH;       PIMAGE_SECTION_HEADERS peSecH;       void *Ptr;       unsigned long peSz;       if(AlignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz))       {           res = AttachPE(CmdParam, peH, peSecH, Ptr, peSz, *ProcessId);           VirtualFree(Ptr, peSz, MEM_DECOMMIT);       }       return res;   }     // 初始化   class CInit   {   public:       CInit()       {           MyVirtualAllocEx = (pfVirtualAllocEx)GetProcAddress(GetModuleHandle("Kernel32.dll"), "VirtualAllocEx");       }   }Init;           int APIENTRY WinMain(HINSTANCE hInstance,                        HINSTANCE hPrevInstance,                        LPSTR     lpCmdLine,                        int       nCmdShow)   {       HANDLE hFile = NULL;       hFile = ::CreateFile( "f:\\SourceFromCsdn2.exe"          , FILE_ALL_ACCESS           , 0           , NULL           , OPEN_EXISTING           , FILE_ATTRIBUTE_NORMAL           , NULL           );       if( hFile == INVALID_HANDLE_VALUE )           return -1;         ::SetFilePointer( hFile, 0, NULL, FILE_BEGIN);       DWORD dwFileSize = ::GetFileSize( hFile, NULL);         LPBYTE pBuf = new BYTE[dwFileSize];       memset( pBuf, 0, dwFileSize);         DWORD dwNumberOfBytesRead = 0;       ::ReadFile( hFile           , pBuf           , dwFileSize           , &dwNumberOfBytesRead           , NULL           );         ::CloseHandle(hFile);              unsigned long ulProcessId = 0;       MemExecute( pBuf, dwFileSize, "", &ulProcessId);       delete[] pBuf;                return 0;   }   


原创粉丝点击