运行内存中的exe(一)

0x01

主要功能, 加载一个exe到 一个内存中, 并运行这块内存


0x02

有限制条件, EXE必须具有重定位表, 否则运行失败!!


截图

360截图20180131004731846.jpg

pid模块还没写完

想把进程移植到指定的 PID中运行!


0x03 关键代码

(有参考价值的代码,  重定位表的修复,  导入表的修复)



001// 20180118_20.cpp : Defines the entry point for the application.
002//
003 
004#include "stdafx.h"
005#include "resource.h"
006#include "DebugTool.h"
007#include "PEOperate.h"
008#include <tlhelp32.h> 
009#include <stdio.h>
010#include <stdlib.h>
011 
012 
013//获取程序的OEP
014VOID GetExeOEP(LPVOID pFileBuffer,DWORD &entryPoint)
015{
016    PIMAGE_DOS_HEADER pDosHeader = NULL;
017    PIMAGE_NT_HEADERS pNTHeader = NULL;
018    PIMAGE_FILE_HEADER pPEHeader = NULL;
019    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
020    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
021     
022    if(!pFileBuffer)
023    {
024        printf("文件读取失败\n");
025        return;
026    }
027     
028    //MZ标志
029    if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE)
030    {
031        printf("不是有效的MZ标志\n");
032        free(pFileBuffer);
033        return;
034    }
035     
036    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
037     
038    //打印DOS头
039    printf("------------DOS头------------\n");
040    printf("MZ标志: %x\n",pDosHeader->e_magic);
041    printf("PE偏移: %x\n",pDosHeader->e_lfanew);
042     
043    //判断是否是有效的PE
044    if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE)
045    {
046        printf("不是有效的PE标志\n");
047        free(pFileBuffer);
048        return;
049    }
050     
051    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
052     
053    //打印NT头
054    printf("------------NT头------------\n");
055    printf("Signature: %x\n",pNTHeader->Signature);
056    pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
057    printf("------------标准PE头--------\n");
058    printf("Machine: %x\n",pPEHeader->Machine);
059    printf("节的数量: %x\n",pPEHeader->NumberOfSections);
060    printf("SizeOfOptionHeaders: %x\n",pPEHeader->SizeOfOptionalHeader);
061     
062    //可选择PE头
063    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
064    printf("------------OPTION_PE头--------\n");
065    printf("Machine: %x \n",pOptionHeader->Magic);
066    printf("OEP: %x \n",pOptionHeader->AddressOfEntryPoint);
067    printf("ImageBase: %x \n",pOptionHeader->ImageBase);
068    printf("SectionAlignment: %x \n",pOptionHeader->SectionAlignment);
069    printf("FileAlignment: %x \n",pOptionHeader->FileAlignment);
070    printf("SizeOfImage: %x \n",pOptionHeader->SizeOfImage);
071    printf("SizeOfHeaders: %x \n",pOptionHeader->SizeOfHeaders);
072     
073 
074    entryPoint = pOptionHeader->AddressOfEntryPoint;
075}
076 
077 
078//导入表修正函数;
079//LPVOID pFileBuffer
080//BOOL FixImport(PIMAGE_IMPORT_DESCRIPTOR pimport_addr,DWORD reImageBase)
081//PIMAGE_IMPORT_DESCRIPTOR pimport_addr
082BOOL FixImport(LPVOID pFileBuffer,DWORD imagebase)
083{
084    if(!pFileBuffer)
085    {
086        printf("文件读取失败\n");
087        return FALSE;
088    }
089     
090    PIMAGE_DOS_HEADER pDosHeader = NULL;
091    PIMAGE_NT_HEADERS pNTHeader = NULL;
092    PIMAGE_FILE_HEADER pPEHeader = NULL;
093    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
094    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
095    PIMAGE_SECTION_HEADER pSectionHeader_ADD = NULL;
096    PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
097    //Header信息
098    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
099    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
100    pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
101    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
102    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
103    pDataDirectory = pOptionHeader->DataDirectory;
104 
105    //确定导入表
106    IMAGE_DATA_DIRECTORY pImportDirectory = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
107     
108    DWORD ImportVirtualAddress = pImportDirectory.VirtualAddress;
109    DWORD ImportFoa = RVAToFileOffset(pFileBuffer,ImportVirtualAddress);
110 
111    printf("ImportVirtualAddress: %x \n",ImportVirtualAddress);
112    printf("Size: %x \n",pImportDirectory.Size);
113    printf("ImportFoa: %x \n",ImportFoa);
114 
115    //输出所有的导入表
116    //PIMAGE_THUNK_DATA32 pThunkData = NULL;
117    //第一个导入表
118    PIMAGE_IMPORT_DESCRIPTOR pImp = NULL;
119    pImp = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + ImportVirtualAddress);  
120     
121 
122    PIMAGE_THUNK_DATA pOrgThunk, pFirstThunk;
123    PIMAGE_IMPORT_BY_NAME pImportName;
124 
125    OutputDebugStringF("-----------import table info------------");
126 
127    while (NULL != pImp->OriginalFirstThunk) {
128        pImp->Name += imagebase;
129 
130        OutputDebugStringF("DLL: %s", pImp->Name);
131 
132        FARPROC fpFun;
133        HINSTANCE hInstance = LoadLibraryA((LPCSTR)pImp->Name);
134        if (NULL == hInstance) {
135            OutputDebugStringF("Load library %s failed, error: %d\n", pImp->Name, GetLastError());
136            return FALSE;
137        }
138 
139        pOrgThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->OriginalFirstThunk);
140        pFirstThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->FirstThunk);
141 
142        while (NULL != *(DWORD *)pOrgThunk) {
143            if (pOrgThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32) {
144                fpFun = GetProcAddress(hInstance, (LPCSTR)(pOrgThunk->u1.Ordinal & 0x0000ffff));
145            }
146            else {
147                //这里调试有问题(调试问题)
148                pImportName = (PIMAGE_IMPORT_BY_NAME)((DWORD)imagebase + (DWORD)(pOrgThunk->u1.AddressOfData));
149                fpFun = GetProcAddress(hInstance, (LPCSTR)pImportName->Name);
150            }
151            pFirstThunk->u1.Ordinal = (LONG)fpFun;
152            ++pFirstThunk;
153            ++pOrgThunk;
154        }
155        FreeLibrary(hInstance);
156        ++pImp;
157    }
158    return TRUE;
159}
160 
161 
162 
163//根据重定位表对,内存模块进行重定位;
164//LPVOID pFileBuffer
165//BOOL RelocPemodule(PIMAGE_BASE_RELOCATION prelocBase, DWORD reImageBase ,int offsetReloc)
166BOOL RelocPemodule(LPVOID pFileBuffer, DWORD reImageBase ,int offsetReloc)
167{
168     
169    if(!pFileBuffer)
170    {
171        printf("文件读取失败\n");
172        return FALSE;
173    }
174     
175    PIMAGE_DOS_HEADER pDosHeader = NULL;
176    PIMAGE_NT_HEADERS pNTHeader = NULL;
177    PIMAGE_FILE_HEADER pPEHeader = NULL;
178    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
179    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
180    PIMAGE_DATA_DIRECTORY DataDirectory=NULL;
181     
182    //Header信息
183    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
184    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
185    pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
186    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
187    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
188     
189    //定位Directory_Data;
190    DataDirectory = pOptionHeader->DataDirectory;
191     
192    //重定位表
193    printf("IMAGE_DIRECTORY_ENTRY_BASERELOC: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
194        DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
195     
196    //DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva)
197     
198    DWORD FoA = RVAToFileOffset(pFileBuffer,0x2df10);
199     
200    DWORD BaseReloc_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
201    DWORD BaseReloc_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
202    FoA = RVAToFileOffset(pFileBuffer,BaseReloc_Directory_Address);
203     
204     
205    //定位到第一个重定位块
206    PIMAGE_BASE_RELOCATION prelocBase = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + BaseReloc_Directory_Address);
207 
208 
209    DWORD reloca_addr,count, offset, type;
210    WORD *item = NULL ;
211    while(prelocBase->VirtualAddress!=NULL)
212    {
213        reloca_addr=prelocBase->VirtualAddress+reImageBase;  //要被重定位的数据的地址部分;
214        count=(prelocBase->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1;      //数组每项大小两个字节,除以2,即为数组项目个数;
215        item= (WORD *)((char*)prelocBase+sizeof(IMAGE_BASE_RELOCATION));     //数组项目的开始地址;
216        for(int i=0; i<(int)count;i++)  //每个重定位表中有N项;
217        {
218            offset = item[i] & 0x0fff ;   //低12位,重定位地址;
219            type = item[i] >> 12 ;    //重定位类型;
220            if(type==3)
221            {
222                *(DWORD*)(reloca_addr+offset)+=offsetReloc;   //重定位地址加上  便宜量;
223                //PDWORD myAddress = (PDWORD)(reloca_addr+offset);
224                //*myAddress = *myAddress + offsetReloc;
225                //修改数据:
226                /*
227                PDWORD myAddress = (PDWORD)((DWORD)pFileBuffer + changeFoa);
228                *myAddress = *myAddress - 0x10000000 + 0x20000000;
229                */
230 
231            }
232        }
233        prelocBase=(PIMAGE_BASE_RELOCATION)(item+count); //指针指向下一个重定位结构;
234    }
235    return TRUE;
236}
237 
238//获取进程的ImageBase,ImageSize
239BOOL GetProcessImageInfo(LPSTR szExePath, DWORD &ImageBase, DWORD &ImageSize,DWORD &processId)
240{
241    HANDLE hProSnapshot =NULL;      //进程快照句柄
242    DWORD dwIdx=0;
243    TCHAR szPath[MAX_PATH];         //进程路径
244    HANDLE hModSnapshot=NULL;   //模块快照句柄   
245    TCHAR szPID[10];                        //PID
246    PROCESSENTRY32 pe32={0};
247    MODULEENTRY32 me32 = {0};
248    hProSnapshot =CreateToolhelp32Snapshot(TH32CS_SNAPALL,0);
249    if(hProSnapshot==INVALID_HANDLE_VALUE)
250    {
251        return FALSE;
252    }
253    TCHAR szBaseAddr[10]={0};               //镜像基址
254    TCHAR szBaseSize[10]={0};               //镜像大小
255    DWORD dwPID = 0;
256     
257    pe32.dwSize =sizeof(pe32);
258    BOOL fOk =Process32First(hProSnapshot,&pe32);
259    for (; fOk; fOk =Process32Next(hProSnapshot,&pe32),dwIdx++)
260    {
261        //StringCchPrintf(szPID,sizeof(szPID),_T("%08x"),pe32.th32ProcessID);
262        //sprintf(szPID,"%d",pe32.th32ProcessID);
263        if(strcmp(szExePath,pe32.szExeFile)==0)
264        {
265            sprintf(szPID,"%d",pe32.th32ProcessID);
266            processId = atoi(szPID);
267            hModSnapshot =CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pe32.th32ProcessID);
268            if (hModSnapshot !=INVALID_HANDLE_VALUE)
269            {
270                ZeroMemory(&me32,sizeof(me32));
271                me32.dwSize = sizeof(me32);
272                if(Module32First(hModSnapshot, &me32) && pe32.th32ProcessID !=0)
273                {
274                     
275                    sprintf(szBaseAddr,"%d",me32.modBaseAddr);
276                    sprintf(szBaseSize,"%d",me32.modBaseSize);
277                    sprintf(szPath,"%s",pe32.szExeFile);
278                    ImageBase = atoi(szBaseAddr);
279                    ImageSize = atoi(szBaseSize);
280                     
281                    //OutputDebugStringF("szPath: %s 11111111 ",pe32.szExeFile);
282                    return TRUE;
283 
284                }else{
285                    OutputDebugStringF("GetProcessImageInfo: Error.... ");
286                     
287                }
288            }else{
289                OutputDebugStringF("GetProcessImageInfo: Error.... ");
290            }
291        }
292         
293    }
294    OutputDebugStringF("GetProcessImageInfo: Error.... ");
295    return FALSE;
296}
297 
298 
299//注入功能代码到指定的进程
300VOID InjectEXE(HWND hwndDlg)
301{
302    //运行要注入的EXE
303    HWND hEditExePath = GetDlgItem(hwndDlg,IDC_EDIT_EXEPATH);
304    TCHAR szExePath[256]={0};
305    GetDlgItemText(hwndDlg,IDC_EDIT_EXEPATH,szExePath,256);
306    if(szExePath == NULL)
307    {
308        MessageBox(0,"Exe路径未填写","错误01",0);
309        return;
310    }
311    OutputDebugStringF("ExePath: %s ",szExePath);
312     
313    //创建exe进程
314    STARTUPINFO si={0};
315    si.cb = sizeof(STARTUPINFO);
316    si.lpDesktop=TEXT("gyarmy");
317    PROCESS_INFORMATION pi={0};
318    //TCHAR szFileName[] = "c://ipmsg.exe";
319    CreateProcess(NULL,
320        szExePath,
321        NULL,
322        NULL,
323        FALSE,
324        CREATE_NEW_CONSOLE,
325        NULL,
326        NULL,
327        &si,
328        &pi);
329    OutputDebugStringF("Process: %d,%d ",pi.hProcess,pi.hThread);
330     
331    //得到EXE的镜像
332    DWORD processImageBase = 0;
333    DWORD processImageSize = 0;
334    DWORD processId = 0;
335    Sleep(1000);
336    BOOL isInfo = GetProcessImageInfo(szExePath,processImageBase,processImageSize,processId);
337    if(!isInfo){
338        MessageBox(0,"Exe没有获取ImageInfo","错误02",0);
339        return;
340    }
341    OutputDebugStringF("Process: %08X,%08X , %d",processImageBase,processImageSize,processId);
342     
343    //开辟一个空间,将数据copy一份
344    LPVOID pFileBuffer = NULL;
345    pFileBuffer = malloc(processImageSize);
346    memset(pFileBuffer,0,processImageSize);
347    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,processId);
348    OutputDebugStringF("hProcess: %d",(DWORD)hProcess);
349 
350 
351    if(hProcess==NULL)
352    {
353        MessageBox(0,"打开Exe进程失败","错误03",0);
354        return;
355    }
356    DWORD dwNumberOfBytesRead;
357    BOOL isReadAll  = ReadProcessMemory(hProcess,(LPCVOID)processImageBase,pFileBuffer,processImageSize,&dwNumberOfBytesRead);
358    if(!isReadAll)
359    {
360            MessageBox(0,"读取Exe进程失败","错误04",0);
361        return;
362    }
363     
364    //1 重定位表修复
365    RelocPemodule(pFileBuffer,(DWORD)pFileBuffer,(DWORD)pFileBuffer-processImageBase);
366 
367    //2 IAT表修复
368    FixImport(pFileBuffer,(DWORD)pFileBuffer);
369     
370    //3 跳转到EIP
371    //entryPoint
372    DWORD entrypoint = 0;
373    GetExeOEP(pFileBuffer,entrypoint);
374 
375    int PEStartpoint = (int)pFileBuffer+(int)entrypoint;
376    OutputDebugStringF("entrypoint: %08X",(DWORD)entrypoint);
377    OutputDebugStringF("PEStartpoint: %08X",(DWORD)PEStartpoint);
378 
379    //结束原来的进程
380    TerminateProcess(pi.hProcess,0);
381 
382    //程序跳到入口点开始执行程序;
383     
384    __asm{
385        jmp PEStartpoint
386    }
387    /*
388    Sleep(1000);
389    TerminateProcess(pi.hProcess,0);   
390    */
391}
392 
393 
394BOOL CALLBACK MainDialogProc(
395  HWND hwndDlg,  // handle to dialog box
396  UINT uMsg,     // message
397  WPARAM wParam, // first message parameter
398  LPARAM lParam  // second message parameter
399)
400{
401    switch(uMsg)
402    {
403    case WM_INITDIALOG:
404        {
405            SetDlgItemText(hwndDlg,IDC_EDIT_EXEPATH,TEXT("back.exe"));
406            break;
407        }
408    case WM_CLOSE:
409        {
410            EndDialog(hwndDlg,0);
411            break;
412        }
413    case WM_COMMAND:
414        {
415            switch(LOWORD(wParam))
416            {
417            case IDC_BUTTON_INJECT:
418                {
419                    //MessageBox(0,0,0,0);
420                    //OutputDebugStringF("output: %d ,%d",1,1);
421                    InjectEXE(hwndDlg);
422                    break;
423                }
424            }
425 
426            break;
427        }
428    }
429 
430    return FALSE;
431}
432 
433 
434int APIENTRY WinMain(HINSTANCE hInstance,
435                     HINSTANCE hPrevInstance,
436                     LPSTR     lpCmdLine,
437                     int       nCmdShow)
438{
439    // TODO: Place code here.
440    EnableDebugPrivilege(TRUE);
441    DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDialogProc);
442     
443    return 0;
444}


源代码下载:


20180129_01.rar



原文链接: 运行内存中的exe(一) 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://www.gyarmy.com/?post=388 )

发表评论

0则评论给“运行内存中的exe(一)”