流沙团
运行内存中的exe(一)
2018-1-31 流沙团


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









发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容