鱼C论坛

 找回密码
 立即注册

模拟Windows加载器的过程

热度 1已有 507 次阅读2016-10-26 16:13

#define  _CRT_SECURE_NO_WARNINGS
#include "windows.h"
#include <stdio.h>



 long readFile(IN const char* szFilePath, OUT void ** BaseAddr)
{
FILE * fd = fopen(szFilePath, "rb");
long fileSize = 0;
void *  tmpBuffer = NULL;
if (fd == NULL)
{
printf("不是有效的EXE文件");
return 0;
}

fseek(fd, 0, SEEK_END);

fileSize = ftell(fd);
fseek(fd, 0, SEEK_SET);

tmpBuffer = (void*)malloc(fileSize);

memset(tmpBuffer, 0, fileSize);
fread(tmpBuffer, sizeof(char), fileSize, fd);
*BaseAddr = tmpBuffer;
tmpBuffer = NULL;
fclose(fd);
return 1;
}

 BOOL MentoFile(LPVOID MenAddr, OUT PSTR szOutfilePath,size_t fielSize)
 {
FILE *fd = fopen(szOutfilePath, "wb+");
if (fd == NULL)
{
printf("打开EXE文件失败");
return 0;
}
fwrite(MenAddr, fielSize, 1, fd);

fclose(fd);
//释放没有用处的内存
free(MenAddr);
MenAddr = NULL;
return 1;

 }

 DWORD FileToBuffer(IN LPVOID FBufferAddr, OUT LPVOID* MBufferAddr)
 {
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pEHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
 
LPVOID tmpBuffer = NULL;

if (FBufferAddr == NULL)
{
printf("缓冲区指针无效");
return 0;
}

if (*(PWORD)FBufferAddr != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志");
free(FBufferAddr);
FBufferAddr = NULL;
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)FBufferAddr;

if (*(PWORD)((DWORD)FBufferAddr + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志");
free(FBufferAddr);
FBufferAddr = NULL;
return 0;
}

//NT头
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)FBufferAddr + pDosHeader->e_lfanew);
 
//pe头
pEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);

//可选pe头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pEHeader + IMAGE_SIZEOF_FILE_HEADER);

//第一个目录节指针
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pEHeader->SizeOfOptionalHeader);

//根据sizeOfImage分配内存空间
tmpBuffer = (LPVOID)malloc(pOptionHeader->SizeOfImage);

if (tmpBuffer == NULL)
{
 
printf("内存分配失败");  //如果分配内存失败就没有必要进行下去了,释放原来分配的内存
free(FBufferAddr);
FBufferAddr = NULL;
return 0;
}
 
//初始化缓冲区
memset(tmpBuffer, 0, pOptionHeader->SizeOfImage);

//根据sizeOfHeader拷贝头
memcpy(tmpBuffer, FBufferAddr, pOptionHeader->SizeOfHeaders);

//根据节表进行拷贝
PIMAGE_SECTION_HEADER ptmpSection = pSectionHeader;
for (int i = 0; i < pEHeader->NumberOfSections; i++, ptmpSection++)
{
memcpy((LPVOID)((DWORD)tmpBuffer + ptmpSection->VirtualAddress), (LPVOID)((DWORD)FBufferAddr + ptmpSection->PointerToRawData), ptmpSection->SizeOfRawData);
}
free(FBufferAddr); //拷贝完数据之后 将旧的内存释放
FBufferAddr = NULL;
*MBufferAddr = tmpBuffer;
return pOptionHeader->SizeOfImage;
 }

 DWORD BufferTofileBuffer(IN LPVOID oldBufferAddr, OUT LPVOID *NewBufferAddr)
 {
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pEHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_SECTION_HEADER ptmpSection = NULL;

DWORD fileSize = 0;
DWORD numberSection = 0;
LPVOID tmpBuffer = NULL;

if (oldBufferAddr == NULL)
{
printf("缓冲区指针无效");
return 0;
}

if (*(PWORD)oldBufferAddr != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志");
free(oldBufferAddr);
oldBufferAddr = NULL;
return 0;
}

pDosHeader = (PIMAGE_DOS_HEADER)oldBufferAddr;

if (*(PWORD)((DWORD)oldBufferAddr + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志");
free(oldBufferAddr);
oldBufferAddr = NULL;
return 0;
}

//NT头
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)oldBufferAddr + pDosHeader->e_lfanew);

//pe头
pEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);

//可选pe头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pEHeader + IMAGE_SIZEOF_FILE_HEADER);

//第一个目录节指针
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pEHeader->SizeOfOptionalHeader);

//j计算文件大小
numberSection = pEHeader->NumberOfSections;
//在节表中找到最后一个节的位置
ptmpSection =pSectionHeader + (numberSection-1);
//从最后一个节中文件偏移开始
fileSize = (DWORD)ptmpSection->PointerToRawData + ptmpSection->SizeOfRawData;

tmpBuffer = (LPVOID)malloc(pOptionHeader->SizeOfImage);

if (tmpBuffer == NULL)
{

printf("内存分配失败");  //如果分配内存失败就没有必要进行下去了,释放原来分配的内存
free(oldBufferAddr);
oldBufferAddr = NULL;
return 0;
}

//初始化缓冲区
memset(tmpBuffer, 0, fileSize);

//根据sizeOfHeader拷贝头
memcpy(tmpBuffer, oldBufferAddr, pOptionHeader->SizeOfHeaders);

//根据节表进行拷贝
 ptmpSection = pSectionHeader;
for (int i = 0; i < pEHeader->NumberOfSections; i++, ptmpSection++)
{
memcpy((LPVOID)((DWORD)tmpBuffer + ptmpSection->PointerToRawData), (LPVOID)((DWORD)oldBufferAddr + ptmpSection->VirtualAddress), ptmpSection->SizeOfRawData);
}

free(oldBufferAddr);
oldBufferAddr = NULL;

*NewBufferAddr = tmpBuffer;

return fileSize;
 }

#include "pe.h"
#include <stdio.h>


#define  FILE_IN  "D:\\java\\飞鸽传书.exe"
#define  FILE_OUT  "D:\\java\\飞鸽传书_1.exe"
 int main(void)
 {
LPVOID fileBuffer = NULL;
LPVOID MemBuffer = NULL;
LPVOID NewBufferAddr = NULL;
DWORD len = 0;
readFile(FILE_IN, &fileBuffer);
FileToBuffer(fileBuffer, &MemBuffer);
len = BufferTofileBuffer(MemBuffer, &NewBufferAddr);
MentoFile(NewBufferAddr, FILE_OUT, len);
printf("hello ....");
return 0;
 }

路过

雷人

握手
1

鲜花

鸡蛋

刚表态过的朋友 (1 人)

全部作者的其他最新日志

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-26 05:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部