0x01
主要功能, 加载一个exe到 一个内存中, 并运行这块内存
0x02
有限制条件, EXE必须具有重定位表, 否则运行失败!!
截图
pid模块还没写完
想把进程移植到指定的 PID中运行!
0x03 关键代码
(有参考价值的代码, 重定位表的修复, 导入表的修复)
// 20180118_20.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #include "DebugTool.h" #include "PEOperate.h" #include <tlhelp32.h> #include <stdio.h> #include <stdlib.h> //获取程序的OEP VOID GetExeOEP(LPVOID pFileBuffer,DWORD &entryPoint) { PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; if(!pFileBuffer) { printf("文件读取失败\n"); return; } //MZ标志 if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE) { printf("不是有效的MZ标志\n"); free(pFileBuffer); return; } pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; //打印DOS头 printf("------------DOS头------------\n"); printf("MZ标志: %x\n",pDosHeader->e_magic); printf("PE偏移: %x\n",pDosHeader->e_lfanew); //判断是否是有效的PE if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE) { printf("不是有效的PE标志\n"); free(pFileBuffer); return; } pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); //打印NT头 printf("------------NT头------------\n"); printf("Signature: %x\n",pNTHeader->Signature); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); printf("------------标准PE头--------\n"); printf("Machine: %x\n",pPEHeader->Machine); printf("节的数量: %x\n",pPEHeader->NumberOfSections); printf("SizeOfOptionHeaders: %x\n",pPEHeader->SizeOfOptionalHeader); //可选择PE头 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); printf("------------OPTION_PE头--------\n"); printf("Machine: %x \n",pOptionHeader->Magic); printf("OEP: %x \n",pOptionHeader->AddressOfEntryPoint); printf("ImageBase: %x \n",pOptionHeader->ImageBase); printf("SectionAlignment: %x \n",pOptionHeader->SectionAlignment); printf("FileAlignment: %x \n",pOptionHeader->FileAlignment); printf("SizeOfImage: %x \n",pOptionHeader->SizeOfImage); printf("SizeOfHeaders: %x \n",pOptionHeader->SizeOfHeaders); entryPoint = pOptionHeader->AddressOfEntryPoint; } //导入表修正函数; //LPVOID pFileBuffer //BOOL FixImport(PIMAGE_IMPORT_DESCRIPTOR pimport_addr,DWORD reImageBase) //PIMAGE_IMPORT_DESCRIPTOR pimport_addr BOOL FixImport(LPVOID pFileBuffer,DWORD imagebase) { if(!pFileBuffer) { printf("文件读取失败\n"); return FALSE; } PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader_ADD = NULL; PIMAGE_DATA_DIRECTORY pDataDirectory = NULL; //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); pDataDirectory = pOptionHeader->DataDirectory; //确定导入表 IMAGE_DATA_DIRECTORY pImportDirectory = pDataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; DWORD ImportVirtualAddress = pImportDirectory.VirtualAddress; DWORD ImportFoa = RVAToFileOffset(pFileBuffer,ImportVirtualAddress); printf("ImportVirtualAddress: %x \n",ImportVirtualAddress); printf("Size: %x \n",pImportDirectory.Size); printf("ImportFoa: %x \n",ImportFoa); //输出所有的导入表 //PIMAGE_THUNK_DATA32 pThunkData = NULL; //第一个导入表 PIMAGE_IMPORT_DESCRIPTOR pImp = NULL; pImp = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + ImportVirtualAddress); PIMAGE_THUNK_DATA pOrgThunk, pFirstThunk; PIMAGE_IMPORT_BY_NAME pImportName; OutputDebugStringF("-----------import table info------------"); while (NULL != pImp->OriginalFirstThunk) { pImp->Name += imagebase; OutputDebugStringF("DLL: %s", pImp->Name); FARPROC fpFun; HINSTANCE hInstance = LoadLibraryA((LPCSTR)pImp->Name); if (NULL == hInstance) { OutputDebugStringF("Load library %s failed, error: %d\n", pImp->Name, GetLastError()); return FALSE; } pOrgThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->OriginalFirstThunk); pFirstThunk = (PIMAGE_THUNK_DATA)(imagebase + pImp->FirstThunk); while (NULL != *(DWORD *)pOrgThunk) { if (pOrgThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32) { fpFun = GetProcAddress(hInstance, (LPCSTR)(pOrgThunk->u1.Ordinal & 0x0000ffff)); } else { //这里调试有问题(调试问题) pImportName = (PIMAGE_IMPORT_BY_NAME)((DWORD)imagebase + (DWORD)(pOrgThunk->u1.AddressOfData)); fpFun = GetProcAddress(hInstance, (LPCSTR)pImportName->Name); } pFirstThunk->u1.Ordinal = (LONG)fpFun; ++pFirstThunk; ++pOrgThunk; } FreeLibrary(hInstance); ++pImp; } return TRUE; } //根据重定位表对,内存模块进行重定位; //LPVOID pFileBuffer //BOOL RelocPemodule(PIMAGE_BASE_RELOCATION prelocBase, DWORD reImageBase ,int offsetReloc) BOOL RelocPemodule(LPVOID pFileBuffer, DWORD reImageBase ,int offsetReloc) { if(!pFileBuffer) { printf("文件读取失败\n"); return FALSE; } PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; PIMAGE_DATA_DIRECTORY DataDirectory=NULL; //Header信息 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader); //定位Directory_Data; DataDirectory = pOptionHeader->DataDirectory; //重定位表 printf("IMAGE_DIRECTORY_ENTRY_BASERELOC: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size); //DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva) DWORD FoA = RVAToFileOffset(pFileBuffer,0x2df10); DWORD BaseReloc_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; DWORD BaseReloc_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; FoA = RVAToFileOffset(pFileBuffer,BaseReloc_Directory_Address); //定位到第一个重定位块 PIMAGE_BASE_RELOCATION prelocBase = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + BaseReloc_Directory_Address); DWORD reloca_addr,count, offset, type; WORD *item = NULL ; while(prelocBase->VirtualAddress!=NULL) { reloca_addr=prelocBase->VirtualAddress+reImageBase; //要被重定位的数据的地址部分; count=(prelocBase->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1; //数组每项大小两个字节,除以2,即为数组项目个数; item= (WORD *)((char*)prelocBase+sizeof(IMAGE_BASE_RELOCATION)); //数组项目的开始地址; for(int i=0; i<(int)count;i++) //每个重定位表中有N项; { offset = item[i] & 0x0fff ; //低12位,重定位地址; type = item[i] >> 12 ; //重定位类型; if(type==3) { *(DWORD*)(reloca_addr+offset)+=offsetReloc; //重定位地址加上 便宜量; //PDWORD myAddress = (PDWORD)(reloca_addr+offset); //*myAddress = *myAddress + offsetReloc; //修改数据: /* PDWORD myAddress = (PDWORD)((DWORD)pFileBuffer + changeFoa); *myAddress = *myAddress - 0x10000000 + 0x20000000; */ } } prelocBase=(PIMAGE_BASE_RELOCATION)(item+count); //指针指向下一个重定位结构; } return TRUE; } //获取进程的ImageBase,ImageSize BOOL GetProcessImageInfo(LPSTR szExePath, DWORD &ImageBase, DWORD &ImageSize,DWORD &processId) { HANDLE hProSnapshot =NULL; //进程快照句柄 DWORD dwIdx=0; TCHAR szPath[MAX_PATH]; //进程路径 HANDLE hModSnapshot=NULL; //模块快照句柄 TCHAR szPID[10]; //PID PROCESSENTRY32 pe32={0}; MODULEENTRY32 me32 = {0}; hProSnapshot =CreateToolhelp32Snapshot(TH32CS_SNAPALL,0); if(hProSnapshot==INVALID_HANDLE_VALUE) { return FALSE; } TCHAR szBaseAddr[10]={0}; //镜像基址 TCHAR szBaseSize[10]={0}; //镜像大小 DWORD dwPID = 0; pe32.dwSize =sizeof(pe32); BOOL fOk =Process32First(hProSnapshot,&pe32); for (; fOk; fOk =Process32Next(hProSnapshot,&pe32),dwIdx++) { //StringCchPrintf(szPID,sizeof(szPID),_T("%08x"),pe32.th32ProcessID); //sprintf(szPID,"%d",pe32.th32ProcessID); if(strcmp(szExePath,pe32.szExeFile)==0) { sprintf(szPID,"%d",pe32.th32ProcessID); processId = atoi(szPID); hModSnapshot =CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pe32.th32ProcessID); if (hModSnapshot !=INVALID_HANDLE_VALUE) { ZeroMemory(&me32,sizeof(me32)); me32.dwSize = sizeof(me32); if(Module32First(hModSnapshot, &me32) && pe32.th32ProcessID !=0) { sprintf(szBaseAddr,"%d",me32.modBaseAddr); sprintf(szBaseSize,"%d",me32.modBaseSize); sprintf(szPath,"%s",pe32.szExeFile); ImageBase = atoi(szBaseAddr); ImageSize = atoi(szBaseSize); //OutputDebugStringF("szPath: %s 11111111 ",pe32.szExeFile); return TRUE; }else{ OutputDebugStringF("GetProcessImageInfo: Error.... "); } }else{ OutputDebugStringF("GetProcessImageInfo: Error.... "); } } } OutputDebugStringF("GetProcessImageInfo: Error.... "); return FALSE; } //注入功能代码到指定的进程 VOID InjectEXE(HWND hwndDlg) { //运行要注入的EXE HWND hEditExePath = GetDlgItem(hwndDlg,IDC_EDIT_EXEPATH); TCHAR szExePath[256]={0}; GetDlgItemText(hwndDlg,IDC_EDIT_EXEPATH,szExePath,256); if(szExePath == NULL) { MessageBox(0,"Exe路径未填写","错误01",0); return; } OutputDebugStringF("ExePath: %s ",szExePath); //创建exe进程 STARTUPINFO si={0}; si.cb = sizeof(STARTUPINFO); si.lpDesktop=TEXT("gyarmy"); PROCESS_INFORMATION pi={0}; //TCHAR szFileName[] = "c://ipmsg.exe"; CreateProcess(NULL, szExePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); OutputDebugStringF("Process: %d,%d ",pi.hProcess,pi.hThread); //得到EXE的镜像 DWORD processImageBase = 0; DWORD processImageSize = 0; DWORD processId = 0; Sleep(1000); BOOL isInfo = GetProcessImageInfo(szExePath,processImageBase,processImageSize,processId); if(!isInfo){ MessageBox(0,"Exe没有获取ImageInfo","错误02",0); return; } OutputDebugStringF("Process: %08X,%08X , %d",processImageBase,processImageSize,processId); //开辟一个空间,将数据copy一份 LPVOID pFileBuffer = NULL; pFileBuffer = malloc(processImageSize); memset(pFileBuffer,0,processImageSize); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,processId); OutputDebugStringF("hProcess: %d",(DWORD)hProcess); if(hProcess==NULL) { MessageBox(0,"打开Exe进程失败","错误03",0); return; } DWORD dwNumberOfBytesRead; BOOL isReadAll = ReadProcessMemory(hProcess,(LPCVOID)processImageBase,pFileBuffer,processImageSize,&dwNumberOfBytesRead); if(!isReadAll) { MessageBox(0,"读取Exe进程失败","错误04",0); return; } //1 重定位表修复 RelocPemodule(pFileBuffer,(DWORD)pFileBuffer,(DWORD)pFileBuffer-processImageBase); //2 IAT表修复 FixImport(pFileBuffer,(DWORD)pFileBuffer); //3 跳转到EIP //entryPoint DWORD entrypoint = 0; GetExeOEP(pFileBuffer,entrypoint); int PEStartpoint = (int)pFileBuffer+(int)entrypoint; OutputDebugStringF("entrypoint: %08X",(DWORD)entrypoint); OutputDebugStringF("PEStartpoint: %08X",(DWORD)PEStartpoint); //结束原来的进程 TerminateProcess(pi.hProcess,0); //程序跳到入口点开始执行程序; __asm{ jmp PEStartpoint } /* Sleep(1000); TerminateProcess(pi.hProcess,0); */ } BOOL CALLBACK MainDialogProc( HWND hwndDlg, // handle to dialog box UINT uMsg, // message WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ) { switch(uMsg) { case WM_INITDIALOG: { SetDlgItemText(hwndDlg,IDC_EDIT_EXEPATH,TEXT("back.exe")); break; } case WM_CLOSE: { EndDialog(hwndDlg,0); break; } case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_BUTTON_INJECT: { //MessageBox(0,0,0,0); //OutputDebugStringF("output: %d ,%d",1,1); InjectEXE(hwndDlg); break; } } break; } } return FALSE; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { // TODO: Place code here. EnableDebugPrivilege(TRUE); DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,MainDialogProc); return 0; }
源代码下载:
0则评论给“运行内存中的exe(一)”