跟着滴水三期学了很长时间了,本着,每一点都要吃透的精神,跟“读文件到内存(拉伸),再读回文件(压缩回来)”杠了一天。先看看按着老师的架构写的代码吧(老师的代码有很多问题(可能是我太菜了吧),踩了很多坑,最后自己推翻重写,全改过来了。)
先看看全部函数的声明
#include <windows.h>
#include <stdio.h>
#define FilePath_In "d://test.exe"
#define FilePath_Out "d://test_new.exe"
#define messageBoxAddr 0x77E5425F
#define shellCodeLength 0x12
extern BYTE shellCode[];
DWORD ReadPEFile(IN LPSTR lpszFile, OUT LPVOID *pFileBuffer);
VOID ReturnAllPEInfo(IN LPVOID pFileBuffer);
DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer, OUT LPVOID *pImageBuffer);
DWORD CopyImageBufferToNewFileBuffer(IN LPVOID pImageBuffer, OUT LPVOID *pNewFileBuffer);
BOOL NewFileBufferToFile(IN LPVOID pNewFileBuffer, size_t size, OUT LPSTR lpszFile);
之后就是函数实现啦
#include "stdafx.h"
#include "global.h"
#include <stdio.h>
#include <windows.h>
#include <iostream>
//_CRT_SECURE_NO_WARNINGS
using namespace std;
BYTE shellCode[] = {
0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
0xE8, 0x00, 0x00, 0x00, 0x00,
0xE9, 0x00, 0x00, 0x00, 0x00
};
DWORD ReadPEFile(
IN LPSTR lpszFile,
OUT LPVOID *pFileBuffer
){
FILE *pFile = NULL;
DWORD fileSize = 0;
LPVOID pTempFileBuffer = NULL;
pFile = fopen(lpszFile, "rb");
if(!pFile){
printf("fopen打开EXE文件失败...");
return ERROR;
}
fseek(pFile, 0, SEEK_END);
fileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
pTempFileBuffer = malloc(fileSize);
memset(pTempFileBuffer,0x00,fileSize);
if(!pTempFileBuffer){
printf("pTempFileBuffer空间申请失败...");
fclose(pFile);
return ERROR;
}
size_t n = fread(pTempFileBuffer, fileSize, 1, pFile);
if(!n){
printf("fread数据读取失败...");
free(pTempFileBuffer);
fclose(pFile);
return ERROR;
}
*pFileBuffer = pTempFileBuffer;
pTempFileBuffer = NULL;
fclose(pFile);
return fileSize;
}
VOID ReturnAllPEInfo(
IN LPVOID pFileBuffer
){
PIMAGE_DOS_HEADER idh = NULL;
PIMAGE_NT_HEADERS inh = NULL;
PIMAGE_FILE_HEADER ifh = NULL;
PIMAGE_OPTIONAL_HEADER ioh = NULL;
PIMAGE_SECTION_HEADER ish = NULL;
idh = (PIMAGE_DOS_HEADER)pFileBuffer;
inh = (PIMAGE_NT_HEADERS)((BYTE *)pFileBuffer + idh->e_lfanew);
ifh = (PIMAGE_FILE_HEADER)((BYTE *)inh + sizeof(DWORD));
ioh = (PIMAGE_OPTIONAL_HEADER)((BYTE *)ifh + IMAGE_SIZEOF_FILE_HEADER);
ish = (PIMAGE_SECTION_HEADER)((BYTE *)ioh + ifh->SizeOfOptionalHeader);
cout << hex << "-----------IMAGE_DOS_HEADER_BASE---------" << endl;
cout << hex << "|-e_magic = " << idh->e_magic << endl;
cout << hex << "|-e_lfanew = " << idh->e_lfanew << endl;
cout << hex << "|" << endl;
cout << hex << "|------------------IMAGE_NT_HEADERS_BASE-----------------" << endl;
cout << hex << "|-signature = " << IMAGE_NT_SIGNATURE << endl;
cout << hex << "|" << endl;
cout << hex << "|---------IMAGE_FILE_HEADER_BASE---------" << endl;
cout << hex << "||-Machine = " << ifh->Machine << endl;
cout << hex << "||-NumberOfSections = " << ifh->NumberOfSections << endl;
cout << hex << "||-TimeDataStamp = " << ifh->TimeDateStamp << endl;
cout << hex << "||-PointerToSymbolicTable = " << ifh->PointerToSymbolTable << endl;
cout << hex << "||-NumberOfSymbols = " << ifh->NumberOfSymbols << endl;
cout << hex << "||-SizeOfOptionalHeader = " << ifh->SizeOfOptionalHeader << endl;
cout << hex << "||-Characteristics = " << ifh->Characteristics << endl;
cout << hex << "||" << endl;
cout << hex << "||-----------IMAGE_OPTIONAL_HEADER---------" << endl;
cout << hex << "||-Magic = " << ioh->Magic << endl;
printf( "||-MajorLinkerVersion = %x\n", ioh->MajorLinkerVersion);
printf( "||-MinorLinkerVersion = %x\n", ioh->MinorLinkerVersion);
cout << hex << "||-SizeOfCode = " << ioh->SizeOfCode << endl;
cout << hex << "||-SizeOfInitializedData = " << ioh->SizeOfInitializedData << endl;
cout << hex << "||-SizeOfUninitializedData = " << ioh->SizeOfUninitializedData << endl;
cout << hex << "||-AddressOfEntryPoint = " << ioh->AddressOfEntryPoint << endl;
cout << hex << "||-BaseOfCode = " << ioh->BaseOfCode << endl;
cout << hex << "||-BaseOfData = " << ioh->BaseOfData << endl;
cout << hex << "||"<< endl;
cout << hex << "||-----------NT 结构增加的领域---------" << endl;
cout << hex << "||-ImageBase = " << ioh->ImageBase << endl;
cout << hex << "||-SectionAlignment = " << ioh->SectionAlignment << endl;
cout << hex << "||-FileAlignment = " << ioh->FileAlignment << endl;
cout << hex << "||-MajorOperatingSystemVersion = " << ioh->MajorOperatingSystemVersion << endl;
cout << hex << "||-MinorOperatingSystemVersion = " << ioh->MinorOperatingSystemVersion << endl;
cout << hex << "||-MajorImageVersion = " << ioh->MajorImageVersion << endl;
cout << hex << "||-MinorImageVersion = " << ioh->MinorImageVersion << endl;
cout << hex << "||-MajorSubsystemVersion = " << ioh->MajorSubsystemVersion << endl;
cout << hex << "||-MinorSubsystemVersion = " << ioh->MinorSubsystemVersion << endl;
cout << hex << "||-Win32VersionValue = " << ioh->Win32VersionValue << endl;
cout << hex << "||-SizeOfImage = " << ioh->SizeOfImage << endl;
cout << hex << "||-SizeOfHeaders = " << ioh->SizeOfHeaders << endl;
cout << hex << "||-CheckSum = " << ioh->CheckSum << endl;
cout << hex << "||-Subsystem = " << ioh->Subsystem << endl;
cout << hex << "||-DllCharacteristics = " << ioh->DllCharacteristics << endl;
cout << hex << "||-SizeOfStackReserve = " << ioh->SizeOfStackReserve << endl;
cout << hex << "||-SizeOfStackCommit = " << ioh->SizeOfStackCommit << endl;
cout << hex << "||-SizeOfHeapReserve = " << ioh->SizeOfHeapReserve << endl;
cout << hex << "||-SizeOfHeapCommit = " << ioh->SizeOfHeapCommit << endl;
cout << hex << "||-LoaderFlags = " << ioh->LoaderFlags << endl;
cout << hex << "||-NumberOfRvaAndSizes = " << ioh->NumberOfRvaAndSizes << endl;
cout << hex << "|" << endl;
cout << hex << "|-------PE结构大小----------------------" << endl;
cout << hex << "|-sizeof(IMAGE_DOS_HEADER) = " << sizeof(IMAGE_DOS_HEADER)<< endl;
cout << hex << "|-sizeof(IMAGE_FILE_HEADER) = " << sizeof(IMAGE_FILE_HEADER) << endl;
cout << hex << "|-sizeof(IMAGE_OPTIONAL_HEADER) = " << sizeof(IMAGE_OPTIONAL_HEADER) << endl;
cout << hex << "|-realSizeof(IMAGE_OPTIONAL_HEADER) = " << sizeof(IMAGE_OPTIONAL_HEADER) << endl;
cout << hex << "|-sizeof(IMAGE_NT_HEADERS) = " << sizeof(IMAGE_NT_HEADERS) << endl;
cout << hex << "|" << endl;
cout << hex << "|-------文件中PE头基址----------------------" << endl;
cout << hex << "|-IMAGE_DOS_HEADER_BASE = " << (void *)((BYTE *)idh - (BYTE *)idh) << endl;
cout << hex << "|-IMAGE_NT_HEADERS_BASE = " << (void *)((BYTE *)inh - (BYTE *)idh) << endl;
cout << hex << "|-IMAGE_FILE_HEADER_BASE = " << (void *)((BYTE *)ifh - (BYTE *)idh) << endl;
cout << hex << "|-IMAGE_OPTIONAL_HEADER_BASE = " << (void *)((BYTE *)ioh - (BYTE *)idh) << endl;
cout << hex << "|" << endl;
for(int i = 0; i < ifh->NumberOfSections; i ++){
char *postion = (char *)((char *)ioh + ifh->SizeOfOptionalHeader + (sizeof(IMAGE_SECTION_HEADER) * i));
if(*postion == 0x00){
break;
}
IMAGE_SECTION_HEADER *ish = (IMAGE_SECTION_HEADER*)postion;
cout << hex << "|----------------------------------------"<< endl;
cout << hex << "|---------------节表"<< i + 1 << "--------------" << endl;
cout << hex << "||-SectionName = " << ish->Name << endl;
cout << hex << "||-BaseAddress = " << (void *)((char *)postion - (char *)idh) << endl;
cout << hex << "||-MemoryBaseAddress = " << (void *)(char *)postion << endl;
printf( "||-VirtualSize = %x\n", ish->Misc);
cout << hex << "||-VirtualAddress = " << ish->VirtualAddress << endl;
cout << hex << "||-SizeOfRawData = " << ish->SizeOfRawData << endl;
cout << hex << "||-PointerToRawData = " << ish->PointerToRawData << endl;
cout << hex << "||-PointerToRelocations = " << ish->PointerToRelocations << endl;
cout << hex << "||-PointerToLinenumbers = " << ish->PointerToLinenumbers << endl;
cout << hex << "||-NumberOfRelocation = " << ish->NumberOfRelocations << endl;
cout << hex << "||-NumberOfLinenumbers = " << ish->NumberOfLinenumbers << endl;
cout << hex << "||-Characteristics = " << ish->Characteristics << endl;
}
cout << hex << "|----------------------------------------"<< endl;
return;
}
DWORD CopyFileBufferToImageBuffer(
IN LPVOID pFileBuffer,
OUT LPVOID *pImageBuffer
){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
LPVOID pTempFileBuffer = NULL;
if(pFileBuffer ==NULL){
printf("pFileBuffer缓冲区指针出错...\n");
return ERROR;
}
//判断是否含有有效MZ和PE标志
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*((PDWORD)((BYTE *)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}
//找到所有PE文件结构的头地址
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pFileBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);
//根据SizeOfImage申请空间哦
pTempFileBuffer = malloc(pOptionHeader->SizeOfImage);
if(!pTempFileBuffer){
printf("pTempFileBuffer空间申请失败...");
return ERROR;
}
memset(pTempFileBuffer, 0, pOptionHeader->SizeOfImage);
memcpy(pTempFileBuffer, pDosHeader, pOptionHeader->SizeOfHeaders);
for(DWORD i = 0; i < pFileHeader->NumberOfSections; i++){
memcpy((PVOID)((BYTE *)pTempFileBuffer + (pSectionHeader + i)->VirtualAddress), (PVOID)((BYTE *)pDosHeader + (pSectionHeader + i)->PointerToRawData), (pSectionHeader + i)->SizeOfRawData);
}
*pImageBuffer = pTempFileBuffer;
pTempFileBuffer = NULL;
return pOptionHeader->SizeOfImage;
}
DWORD CopyImageBufferToNewFileBuffer(
IN LPVOID pImageBuffer,
OUT LPVOID *pNewFileBuffer
){
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pFileHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
if(pImageBuffer ==NULL){
printf("pImageBuffer缓冲区指针出错...\n");
return ERROR;
}
//判断是否含有有效MZ和PE标志
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE){
printf("无有效的MZ标志\n");
return ERROR;
}
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((BYTE *)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("无有效的PE标志\n");
return ERROR;
}
//找到所有PE文件结构的头地址
pNTHeader = (PIMAGE_NT_HEADERS)((BYTE *)pImageBuffer + pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER)((BYTE *)pNTHeader + sizeof(DWORD));
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((BYTE *)pFileHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((BYTE *)pOptionHeader + pFileHeader->SizeOfOptionalHeader);
for(DWORD i = 0; i < pFileHeader->NumberOfSections; i++){
cout << "pSectionHeader->Name = " << (pSectionHeader + i)->Name << endl;
memcpy((PVOID)((BYTE *)pDosHeader + (pSectionHeader + i)->PointerToRawData), (PVOID)((BYTE *)pImageBuffer + (pSectionHeader + i)->VirtualAddress), (pSectionHeader + i)->SizeOfRawData);
}
*pNewFileBuffer = pImageBuffer;
pImageBuffer = NULL;
return pOptionHeader->SizeOfImage;
}
BOOL NewFileBufferToFile(
IN LPVOID pNewFileBuffer,
size_t size,
OUT LPSTR lpszFile
){
if(pNewFileBuffer == NULL){
printf("pNewFileBuffer缓冲区出差...\n");
return ERROR;
}
FILE *pFile = NULL;
size_t fileSize = size;
pFile = fopen(lpszFile, "wb");
if(!pFile){
printf("fopen保存EXE文件失败...\n");
return ERROR;
}
size_t n = fwrite(pNewFileBuffer, fileSize, 1, pFile);
if(!n){
printf("fwrite数据写入失败...\n");
fclose(pFile);
return ERROR;
}
fclose(pFile);
return TRUE;
}
之后就是调用了
// test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "global.h"
int _tmain(int argc, _TCHAR* argv[]){
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
LPVOID pNewFileBuffer = NULL;
ReadPEFile(FilePath_In, &pFileBuffer);
//ReturnAllPEInfo(pFileBuffer);
CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
DWORD FileSize = CopyImageBufferToNewFileBuffer(pImageBuffer, &pNewFileBuffer);
NewFileBufferToFile(pNewFileBuffer, FileSize, FilePath_Out);
printf("为防止闪屏消失,请手动按任意键结束...");
getchar();
return 0;
}
一起学习的小伙伴可以互相关注,一起学习,一起加油噢!
这个系列会一直更新,最重要的是,想练习前面的小伙伴,记得自己写Hello World来测试。