PE读写
// 仿PE文件.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <malloc.h>
?
/*將文件從硬盤讀取到緩沖區(qū)中
參數(shù)1 :文件路徑 參數(shù)2:接受讀取數(shù)據(jù)的緩沖區(qū)的地址的指針【指針的指針】
讀取成功返回文件的長度 讀取失敗則返回0
*/
//int ReadFileToBuffer(IN LPSTR FilePath,OUT LPVOID* PFileBuffer);
?
//接下來將EXE從文件緩沖區(qū)拷貝到內(nèi)存鏡像緩沖區(qū)中
//DWORD CopyFileBufferToImageBuffer(IN LPSTR FileBuffer,OUT LPVOID* PImageBuffer);
int main(int argc, char* argv[])
{
char* FilePath1="E:/notepad++.exe"; //讀入的文件路勁
DWORD FileLength=0;
FILE* InputStream=NULL;
void* pFileBuffer=NULL;
InputStream=fopen(FilePath1,"rb");//打開文件流
?
if(FilePath1=NULL){
printf("文件為空\n");
return 0;
}
int nseek=fseek(InputStream,0,SEEK_END);//將文件流指針指向文件末尾
if(nseek!=0){
printf("設(shè)置文件位置指針失敗\n");
fclose(InputStream);
return 0;
}
FileLength=ftell(InputStream);
printf("the lentgth of the exe is %d Byte\n",FileLength);
//重新設(shè)置文件位置指針指向文件首
fseek(InputStream,0,SEEK_SET);
pFileBuffer=(void*)malloc(FileLength);
if(pFileBuffer==NULL){
printf("文件緩沖區(qū)申請失敗\n");
fclose(InputStream);
return 0;
}
memset(pFileBuffer,0,FileLength);
int n=fread(pFileBuffer,FileLength,1,InputStream);
if(n==0){
printf("文件讀取失敗\n");
free(pFileBuffer);
fclose(InputStream);
return 0;
}
//接下來將EXE從文件緩沖區(qū)拷貝到內(nèi)存鏡像緩沖區(qū)中
?
PIMAGE_DOS_HEADER pDosHeader=NULL;
PIMAGE_NT_HEADERS pNTHeaders=NULL;
PIMAGE_FILE_HEADER pPEHeader=NULL;
PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL;
PIMAGE_SECTION_HEADER pSectionHeader=NULL;
//判斷文件緩沖區(qū)是否有效
if(pFileBuffer==NULL){
printf("文件緩沖區(qū)指針無效\n");
return 0;
}
//判斷該文件是否是PE文件
if(*((PWORD)pFileBuffer)!=IMAGE_DOS_SIGNATURE){
printf("不是有效的DOS文件\n");
return 0;
}
pDosHeader=(PIMAGE_DOS_HEADER)(pFileBuffer);
if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew))!=IMAGE_NT_SIGNATURE){ //這里注意:FileBuffer是一個指針,也就是一個地址,所以轉(zhuǎn)型為DWROD與pDosHeader->e_lfanew相加
printf("該文件不是有效的PE文件");
return 0;
}
printf("DOS的開始地址是:%x\n",pDosHeader);
//NT頭指針
pNTHeaders=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
printf("NT的開始地址是:%x\n",pNTHeaders);
//PE頭指針等于NT頭指針加四
pPEHeader=(PIMAGE_FILE_HEADER)(((DWORD)pFileBuffer+pDosHeader->e_lfanew)+4);
printf("PE的開始地址是:%x\n",pPEHeader);
//血的教訓(xùn),一個指針加上一個整數(shù),加上的實際的大小是該指針表示的數(shù)據(jù)類型【去掉一個*】乘以整數(shù)
pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);//指針在加數(shù)時務(wù)必將其轉(zhuǎn)化為整形
printf("optional的開始地址是:%x\n",pOptionalHeader);
pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pPEHeader->SizeOfOptionalHeader);
printf("section表的開始地址是:%x\n",pSectionHeader);
//根據(jù)SIZE_OF_IMAGE來分配內(nèi)存緩沖區(qū)的大小,雖然每一個應(yīng)用程序在理論上都擁有獨立的4GB虛擬內(nèi)存,但是還是根據(jù)SIZE FOF IMAGE來分配內(nèi)存大小
LPVOID pImageBuffer=NULL;
pImageBuffer=malloc(pOptionalHeader->SizeOfImage);
printf("%x\n",pOptionalHeader->SizeOfImage);
if(pImageBuffer==NULL){
printf("分配內(nèi)存鏡像文件失敗\n");
}
memset(pImageBuffer,0,pOptionalHeader->SizeOfImage);
//開始從文件緩沖區(qū)拷貝到鏡像緩沖區(qū)中 1:第一步:將所有的頭拷貝到鏡像緩沖區(qū)中 DosHeader+NTHeader+SectionHeader
memcpy(pImageBuffer,pFileBuffer,pOptionalHeader->SizeOfHeaders);
//第二步:循環(huán)將區(qū)塊拷貝到IMAGBUFFER中
PIMAGE_SECTION_HEADER pTempSectionHeader=pSectionHeader;
for(int i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++){
memcpy((void*)((DWORD)pImageBuffer+pTempSectionHeader->VirtualAddress),(void*)((DWORD)pDosHeader+pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
}
PIMAGE_DOS_HEADER pImageDosHeader=NULL;
PIMAGE_NT_HEADERS pImageNTHeaders=NULL;
PIMAGE_FILE_HEADER pImagePEHeader=NULL;
PIMAGE_OPTIONAL_HEADER pImageOptionalHeader=NULL;
PIMAGE_SECTION_HEADER pImageSectionHeader=NULL;
pImageDosHeader=(PIMAGE_DOS_HEADER)pImageBuffer;
printf("IMAGE中DOS頭的首地址是:%x\n",pImageDosHeader);
pImageNTHeaders=(PIMAGE_NT_HEADERS)((DWORD)pImageDosHeader+pImageDosHeader->e_lfanew);
printf("IMAGE中NT頭的首地址是:%x\n",pImageNTHeaders);
pImagePEHeader=(PIMAGE_FILE_HEADER)((DWORD)pImageNTHeaders+4);
printf("IMAGE中PE頭的首地址是:%x\n",pImagePEHeader);
pImageOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pImagePEHeader+IMAGE_SIZEOF_FILE_HEADER);
printf("IMAGE中OPTIONAL頭的首地址是:%x\n",pImageOptionalHeader);
pImageSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pImageOptionalHeader+pImagePEHeader->SizeOfOptionalHeader);
//重新申請一塊文件緩沖區(qū),將鏡像中的可執(zhí)行程序還原到文件緩沖區(qū)中
LPVOID pNewFileBuffer=NULL;
pNewFileBuffer=malloc(FileLength);
if(pNewFileBuffer==NULL){
printf("重新申請文件緩沖區(qū)失敗\n");
return 0;
}
memset(pNewFileBuffer,0,FileLength);
//第一步:將第一部分拷貝到新的文件緩沖區(qū)中DOSHEADER+NTHEADER+SECTIONHEADER
memcpy(pNewFileBuffer,pImageDosHeader,pImageOptionalHeader->SizeOfHeaders);
//第二步:循環(huán)將各個區(qū)塊拷貝到新的文件緩沖區(qū)中
//用一個臨時指針來完成pImageSectionHeader指針的自增變化
PIMAGE_SECTION_HEADER pTempImageSectionHeader=NULL;
pTempImageSectionHeader=pImageSectionHeader;
for(i=0;i<pImagePEHeader->NumberOfSections;i++,pTempImageSectionHeader++){
memcpy((void*)((DWORD)pNewFileBuffer+pTempImageSectionHeader->PointerToRawData),(void*)((DWORD)pImageDosHeader+pTempImageSectionHeader->VirtualAddress),pTempImageSectionHeader->SizeOfRawData);
}
//將還原后的文件緩沖區(qū)寫到一個文件中,并測試是有可以運行
char* FilePath2="E:/zhuhao3.exe"; //文件輸出路徑
FILE* OutputStream=NULL;
OutputStream=fopen(FilePath2,"w+");
fwrite(pFileBuffer,FileLength,1,OutputStream);
char* pchar;
char arry[]="zhuhao";
pchar=arry;
int a=3;
return 0;
}
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhuh102/p/6130624.html
總結(jié)
- 上一篇: 微信小程序篇(微信小程序的支付)
- 下一篇: FreeCodeCamp 中级算法(个人