[C] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <Dbghelp.h>
// 打印指定PE文件的一些信息
int PrintPEInfo()
{
HANDLE hFile;
IMAGE_DOS_HEADER ImageDosHeader;
IMAGE_NT_HEADERS ImageNtHeader;
IMAGE_SECTION_HEADER *pImageSectionHeader;
BOOL bStatus;
DWORD dwRetSize;
LARGE_INTEGER FileOffset;
// 打开目标文件
hFile = CreateFile(L"C:\\Users\\Administrator\\Desktop\\target.exe",
FILE_ALL_ACCESS,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile error:%d\n", GetLastError());
return 1;
}
// 将PE文件的DOS头部的内容读到结构体ImageDosHeader中
bStatus = ReadFile(hFile,
&ImageDosHeader,
sizeof(IMAGE_DOS_HEADER),
&dwRetSize,
NULL);
if (bStatus == FALSE)
{
printf("Read image_dos_header failed:%d\n", GetLastError());
goto cleanup;
}
// 打印MZ和PE头偏移量
printf("ImageDosHeader.e_magic:%s\nImageDosHeader.e_lfanew:%X\n", &ImageDosHeader.e_magic, ImageDosHeader.e_lfanew);
// 设置文件的读写指针
FileOffset.QuadPart = ImageDosHeader.e_lfanew;
bStatus = SetFilePointerEx(hFile, FileOffset, NULL, FILE_BEGIN);
if (bStatus == FALSE)
{
printf("SetFilePointerEx error:%d\n", GetLastError());
goto cleanup;
}
// 读取PE头
bStatus = ReadFile(hFile,
&ImageNtHeader,
sizeof(IMAGE_NT_HEADERS),
&dwRetSize,
NULL);
if (bStatus == FALSE)
{
printf("ReadFile PE error:%d\n", GetLastError());
goto cleanup;
}
// 打印“PE”
printf("ImageNtHeader.Signature:%s\n", &ImageNtHeader.Signature);
// 打印镜像基址
printf("ImageBase:%x\n", ImageNtHeader.OptionalHeader.ImageBase);
// 打印区块的数量
printf("ImageNtHeader.FileHeader.NumberOfSections:%d\n", ImageNtHeader.FileHeader.NumberOfSections);
FileOffset.QuadPart = FileOffset.QuadPart + sizeof(IMAGE_NT_HEADERS);
bStatus = SetFilePointerEx(hFile, FileOffset, NULL, FILE_BEGIN);
if (bStatus == FALSE)
{
printf("SetFilePointerEx error:%d\n", GetLastError());
goto cleanup;
}
// 用一个数组来承载描述每个区块的信息,便于到时候打印
pImageSectionHeader = (IMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections);
if (pImageSectionHeader == NULL)
{
printf("pImageSectionHeader malloc error:%d\n", GetLastError());
goto cleanup;
}
bStatus = ReadFile(hFile,
pImageSectionHeader,
sizeof(IMAGE_SECTION_HEADER)*ImageNtHeader.FileHeader.NumberOfSections,
&dwRetSize,
NULL);
if (bStatus == FALSE)
{
printf("Read image_section_header error:%d\n", GetLastError());
free(pImageSectionHeader);
goto cleanup;
}
// 把区块的名字打印出来
for (int i = 0; i < ImageNtHeader.FileHeader.NumberOfSections; i++)
{
printf("pImageSectionHeader[%d]:%s\n", i + 1, pImageSectionHeader[i].Name);
}
free(pImageSectionHeader);
cleanup:
CloseHandle(hFile);
return 0;
}
// 改写一小部分的DOS stub
void WritePE()
{
HANDLE hFile;
DWORD dwRetSize;
char buffer[1024];
char me[] = "Watermelon is watermelon, forever is forever!";
LARGE_INTEGER FileOffset;
BOOL bStatus;
hFile = CreateFile(L"C:\\Users\\Administrator\\Desktop\\target.exe",
FILE_ALL_ACCESS,
FILE_SHARE_WRITE,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("[WritePE] CreateFile error:%d\n", GetLastError());
goto cleanup;
}
bStatus = ReadFile(hFile,
buffer,
0x100,
&dwRetSize,
NULL);
if (bStatus = FALSE)
{
printf("[WritePE] ReadFile error:%d\n", GetLastError());
goto cleanup;
}
for (int i = 0; i < 0x100; i++)
{
if (buffer[i] == 'T' && buffer[i + 1] == 'h' && buffer[i + 2] == 'i' && buffer[i + 3] == 's')
{
FileOffset.QuadPart = i;
break;
}
}
// 重置文件指针
SetFilePointerEx(hFile,
FileOffset,
NULL,
FILE_BEGIN);
bStatus = WriteFile(hFile,
me,
strlen(me),
&dwRetSize,
NULL);
if (bStatus == FALSE)
{
printf("[WritePE] WriteFile error:%d\n", GetLastError());
goto cleanup;
}
printf("WriteFile has done...\n");
cleanup:
CloseHandle(hFile);
}
// 读取导入表,打印函数
void PrintPEFunction()
{
HANDLE hFile = CreateFile(L"C:\\Users\\Administrator\\Desktop\\target.exe",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("[test] CreateFile errror:%d\n", GetLastError());
return;
}
// 创建文件映射,使用内存来找导入表
HANDLE hMap = CreateFileMapping(hFile, NULL,
PAGE_READONLY,
0,
0,
NULL);
if (hMap == INVALID_HANDLE_VALUE)
{
printf("[test] CreateFileMapping error:%d\n", GetLastError());
goto clean;
}
UCHAR *lpBaseAddress = (UCHAR*)MapViewOfFile(hMap,
FILE_MAP_READ, 0, 0, 0);
if (lpBaseAddress == NULL)
{
printf("[test] MapViewOfFile error:%d\n", GetLastError());
goto cleanup;
}
PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)(lpBaseAddress + pImageDosHeader->e_lfanew);
// 获取导入表的RVA
DWORD VirtualAddress = pImageNtHeader->OptionalHeader.DataDirectory[1].VirtualAddress;
if (VirtualAddress == 0)
{
printf("VirtualAddress为0,请更换别的PE文件或者联系我:[email]starlight_chou@163.com[/email]");
goto cleanup;
}
// 获取导入表地址
PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa(pImageNtHeader,
lpBaseAddress,
VirtualAddress,
NULL);
IMAGE_IMPORT_DESCRIPTOR iid;
IMAGE_THUNK_DATA thunk;
// 由于以0(NULL)结尾,所以我们在这里置零
memset(&iid, 0, sizeof(IMAGE_IMPORT_DESCRIPTOR));
memset(&thunk, 0, sizeof(IMAGE_THUNK_DATA));
// 开始进行遍历
for (int i = 0; memcmp(pImportTable + i, &iid, sizeof(IMAGE_IMPORT_DESCRIPTOR)); i++)
{
// 获取dll名字,见32位PE结构表
printf("\n第%d个DLL,名称:%s\n", i+1, (CHAR*)ImageRvaToVa(pImageNtHeader,
lpBaseAddress,
pImportTable[i].Name,
NULL));
// 开始遍历target.exe从对应的DLL中用到了那些函数(IAT)
PIMAGE_THUNK_DATA32 pThunk = (PIMAGE_THUNK_DATA32)ImageRvaToVa(pImageNtHeader,
lpBaseAddress,
pImportTable[i].OriginalFirstThunk, // 无绑定情况下和pImportTable[i].FirstThunk一样的。
NULL);
for (int j = 0; memcmp(pThunk + j, &thunk, sizeof(IMAGE_THUNK_DATA)); j++)
{
// 通过RVA最高位判断函数的导入方式,
// 如果最高位为1,按序号导入,否则按照名称导入
if (pThunk[j].u1.AddressOfData & IMAGE_ORDINAL_FLAG32)
{
printf("[%d]\t%ld", j+1, pThunk[j].u1.AddressOfData & 0xffff);
}
else
{
// 按照名称导入
// 重新判断地址
PIMAGE_IMPORT_BY_NAME pFuncName = (PIMAGE_IMPORT_BY_NAME)ImageRvaToVa(pImageNtHeader,
lpBaseAddress,
pThunk[j].u1.AddressOfData,
NULL);
printf("[%d]\t%ld\t%s\n", j+1, pFuncName->Hint, pFuncName->Name);
}
}
}
cleanup:
CloseHandle(hMap);
clean:
CloseHandle(hFile);
return;
}
int main(void)
{
printf("\n\n#########################################\n\n");
PrintPEInfo();
printf("\n\n#########################################\n\n");
WritePE();
printf("\n\n#########################################\n\n");
PrintPEFunction();
printf("\n\n#########################################\n\n");
getchar();
return 0;
}