运行内存中的exe(一)

0x01

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


0x02

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


截图

360截图20180131004731846.jpg

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;
}




源代码下载:


20180129_01.rar



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

发表评论

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