[C] 纯文本查看 复制代码
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <conio.h>
#include <Windows.h>
// 计算数组长度
#define GET_ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
/*
打印 IMAGE_DOS_HEADER 信息
PIMAGE_DOS_HEADER pDosHeader: IMAGE_DOS_HEADER 结构体指针
*/
void printImageDosHeader (IN PIMAGE_DOS_HEADER pDosHeader) {
printf ("IMAGE_DOS_HEADER:\n");
char *DOS_HEADER_Name[] = {"e_magic", "e_cblp", "e_cp", "e_crlc", "e_cparhdr",
"e_minalloc", "e_maxalloc", "e_ss", "e_sp",
"e_csum", "e_ip", "e_cs", "e_lfarlc", "e_ovno",
"e_res[4]", "e_oemid", "e_oeminfo",
"e_res2[10]",
"e_lfanew", //指向IMAGE_NT_HEADERS的所在
};
int temp = 0;
for (int i = 0; i < 31; i++) {
if (i == 14) { // 打印 e_res[4] 的内容
for (int j = 0; j < 4; j++) {
printf ("\t%-20s:%04X\n", DOS_HEADER_Name[temp],
*(&(pDosHeader->e_magic) + i++));
}
temp++;
}
else if (i == 20) { // 打印 e_res2[10] 的内容
for (int j = 0; j < 10; j++) {
printf ("\t%-20s:%04X\n", DOS_HEADER_Name[temp],
*(&(pDosHeader->e_magic) + i++));
}
temp++;
}
printf ("\t%-20s:%04X\n", DOS_HEADER_Name[temp++], *(&(pDosHeader->e_magic) + i));
}
}
/*
打印 IMAGE_OPTIONAL_HEADER32 结构体信息
IMAGE_NT_HEADERS* pPeHeader: IMAGE_NT_HEADERS 结构体指针
*/
void printOptionalHead32 (IN IMAGE_NT_HEADERS* pPeHeader) {
char *OptionalHeadName[] = {
// Standard fields.
"Magic", "MajorLinkerVersion", "MinorLinkerVersion", "SizeOfCode",
"SizeOfInitializedData", "SizeOfUninitializedData", "AddressOfEntryPoint", "BaseOfCode", "BaseOfData",
// NT additional fields.
"ImageBase", "SectionAlignment", "FileAlignment", "MajorOperatingSystemVersion",
"MinorOperatingSystemVersion", "MajorImageVersion", "MinorImageVersion", "MajorSubsystemVersion",
"MinorSubsystemVersion", "Win32VersionValue", "SizeOfImage", "SizeOfHeaders", "CheckSum",
"Subsystem", "DllCharacteristics", "SizeOfStackReserve", "SizeOfStackCommit", "SizeOfHeapReserve",
"SizeOfHeapCommit", "LoaderFlags", "NumberOfRvaAndSizes", "IMAGE_DATA_DIRECTORY"};
char *DataDirectory[] = {"VirtualAddress", "Size"};
char *VirtualAddressp[] = {"IMAGE_DIRECTORY_ENTRY_EXPORT", "IMAGE_DIRECTORY_ENTRY_IMPORT",
"IMAGE_DIRECTORY_ENTRY_RESOURCE", "IMAGE_DIRECTORY_ENTRY_EXCEPTION", "IMAGE_DIRECTORY_ENTRY_SECURITY",
"IMAGE_DIRECTORY_ENTRY_DEBUG", "IMAGE_DIRECTORY_ENTRY_COPYRIGHT", "IMAGE_DIRECTORY_ENTRY_GLOBALPTR",
"IMAGE_DIRECTORY_ENTRY_TLS", "IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG", "IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT",
"IMAGE_DIRECTORY_ENTRY_IAT", "IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT", "IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR",
"IMAGE_NUMBEROF_DIRECTORY_ENTRIES"
};
size_t structOffset = 0;
DWORD* addr;
printf ("IMAGE_OPTIONAL_HEADER32\n");
for (size_t i = 0; i < GET_ARRAY_LEN (OptionalHeadName); i++) {
if (i == 1) {
structOffset++;;
printf ("\t%-40s:%02X\n", OptionalHeadName[i++], pPeHeader->OptionalHeader.MajorLinkerVersion);
printf ("\t%-40s:%02X\n", OptionalHeadName[i++], pPeHeader->OptionalHeader.MinorLinkerVersion);
}
if (i == 3) {
for (size_t j = 0; j < 9; j++) {
addr = &(pPeHeader->OptionalHeader.Magic) + structOffset;
structOffset += 2;
printf ("\t%-40s:%08X\n", OptionalHeadName[i++], *addr);
}
}
if (i == 18) {
for (size_t j = 0; j < 4; j++) {
addr = &(pPeHeader->OptionalHeader.Magic) + structOffset;
structOffset += 2;
printf ("\t%-40s:%08X\n", OptionalHeadName[i++], *addr);
}
}
if (i == 24) {
for (size_t j = 0; j < 6; j++) {
addr = &(pPeHeader->OptionalHeader.Magic) + structOffset;
structOffset += 2;
printf ("\t%-40s:%08X\n", OptionalHeadName[i++], *addr);
}
}
printf ("\t%-40s:%04X\n", OptionalHeadName[i], *(&(pPeHeader->OptionalHeader.Magic) + structOffset));
structOffset++;
}
}
/*
打印 IMAGE_NT_HEADERS 结构体信息
IMAGE_NT_HEADERS *pPeHeader: IMAGE_NT_HEADERS 结构体指针
*/
void printImageNtHeaders (IN IMAGE_NT_HEADERS* pPeHeader) {
char *PeHeaderName[] = {"Signature", "IMAGE_FILE_HEADER", "IMAGE_OPTIONAL_HEADER32"};
char *FileHeaderName[] = {"Machine", "NumberOfSections", "TimeDateStamp", "PointerToSymbolTable",
"NumberOfSymbols", "SizeOfOptionalHeader", "Characteristics"};
printf ("IMAGE_NT_HEADERS:\n");
printf ("\t%-20s:%08X\n", PeHeaderName[0], pPeHeader->Signature);
printf ("IMAGE_FILE_HEADER:\n");
int temp = 0;
size_t structOffset = 0;
DWORD *addr;
for (int i = 0; i < 7; i++) {
if (i == 2) {
for (int j = 0; j < 3; j++) {
/*
printf ("\t%-20s:%04X%04X\n", FileHeaderName[temp++],
// 这里实在是想不到什么好方法来处理了 求指导下
*(&(pPeHeader->FileHeader.Machine) + structOffset++),
*(&(pPeHeader->FileHeader.Machine) + structOffset++));
这里完全被自己带沟里去了......
果然对指针还是不了解啊
addr = (DOWRD *)&(pPeHeader->FileHeader.Machine) + structOffset; // 这个就偏移飞了.
*/
addr = &(pPeHeader->FileHeader.Machine) + structOffset;
structOffset += 2;
printf ("\t%-40s:%08X\n", FileHeaderName[temp++], *addr);
i++;
}
}
printf ("\t%-40s:%04X\n", FileHeaderName[temp++], *(&(pPeHeader->FileHeader.Machine) + structOffset++));
}
}
int main (int argc, char *argv[])
{
if (argc < 2) {
printf ("Help: %s FileName\n", argv[0]);
exit (EXIT_FAILURE);
}
IMAGE_DOS_HEADER DosHeader; // Dos 头 结构体
IMAGE_NT_HEADERS PeHeader; // PE 头 结构体
FILE *fpPeFile = fopen (argv[1], "rb"); // 以二进制方式打开文件
if (!fpPeFile) {
fprintf (stderr, "打开文件失败\n");
exit (EXIT_FAILURE);
}
fread (&DosHeader.e_magic, 1, sizeof(DosHeader), fpPeFile);
if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) { // e_magic --> DOS可执行文件标记
fprintf (stderr, "请确定该文件是PE文件\n");
exit (EXIT_FAILURE);
}
/*
这里我想多了 其实可以一次性读取出来的
fseek (fpPeFile, 0, SEEK_SET);
for (int i = 0; i < 30; i++) {
// 取 DosHeader.e_magic 首地址
// 根据这个地址来计算 结构体偏移
fread (&DosHeader.e_magic + i, 1, sizeof(WORD), fpPeFile);
}
fread (&DosHeader.e_lfanew, 1, sizeof(LONG), fpPeFile); // 获取 指向PE文件头的文件偏移
*/
printImageDosHeader (&DosHeader);
// 直接跳过了 Dos Stub
fseek (fpPeFile, DosHeader.e_lfanew, 0); // 移动文件偏移到PE头
// 获取PeHeader 信息
fread (&PeHeader, 1, sizeof(PeHeader), fpPeFile);
printImageNtHeaders (&PeHeader);
printOptionalHead32 (&PeHeader);
return 0;
}