鱼C论坛

 找回密码
 立即注册
查看: 1624|回复: 5

[已解决]考验C语言编程能力的题

[复制链接]
发表于 2019-3-11 16:48:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
大家好,我又来了,今天遇到一个比较考验C语言编程的问题,大家听说过pe吧,这是可执行程序最重要的一个文件了,现在有一个要求就是,用C语言  编写一个程序用来显示任意exe程序的pe头,包括(dos头,NT头(标准pe头,可选pe头)),以及里面的内容打印出来
虽然网上有些编程例子,但是那些并不是很好,有一些错误,所以就考考大家了,(ps:本人菜鸟,自然不会做,丢人了 ),顺便也想试试小甲鱼,你会不会做呢??@小甲鱼
附上pe结构文件表
其实只要输出这些内容就可以了。
最佳答案
2019-3-11 20:37:18
PE头都是有结构的。用C写也很简单吧,先把所需要的结构声明出来,然后用二进制读文件,读入结构体中。
#include <stdio.h>
#include <stdlib.h>


typedef unsigned short WORD; // 声明 WORD 类型
typedef unsigned int DWORD; // 声明 DWORD 类型

// 声明 IMAGE_DOS_HEADER 结构体
typedef struct IDosHeader
{
        WORD e_magic;
        WORD e_cblp;
        WORD e_cp;
        WORD e_crlc;
        WORD e_cparhdr;
        WORD e_minalloc;
        WORD e_maxalloc;
        WORD e_ss;
        WORD e_sp;
        WORD e_csum;
        WORD e_ip;
        WORD e_cs;
        WORD e_lfarlc;
        WORD e_ovno;
        WORD e_res[4];
        WORD e_oemid;
        WORD e_oeminfo;
        WORD e_res2[10];
        DWORD e_lfanew;
} IDosHeader;

int main()
{
        IDosHeader DosHeader;
        FILE *fp = NULL;
        char szFileName[100];

        // 获取文件名(如:c:\2.exe)
        printf("请输入文件名:");
        gets(szFileName);

        // 打开文件
        if ( (fp=fopen(szFileName, "rb"))==NULL )
        {
                printf("文件打开失败!\n");
                exit(EXIT_FAILURE);
        }
        
        // 读取内容
        if (fread(&DosHeader, sizeof(IDosHeader),1 , fp) != 1)
        {
                printf("文件读取失败!\n");
                exit(EXIT_FAILURE);
        }

        printf("e_magic:%#x\n", DosHeader.e_magic); // 以16进制输出
        printf("e_cblp:%#x\n", DosHeader.e_cblp); // 以16进制输出

        return 0;
}
1.png

PE结构.rar

304.49 KB, 阅读权限: 10, 下载次数: 0

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-3-11 20:37:18 | 显示全部楼层    本楼为最佳答案   
PE头都是有结构的。用C写也很简单吧,先把所需要的结构声明出来,然后用二进制读文件,读入结构体中。
#include <stdio.h>
#include <stdlib.h>


typedef unsigned short WORD; // 声明 WORD 类型
typedef unsigned int DWORD; // 声明 DWORD 类型

// 声明 IMAGE_DOS_HEADER 结构体
typedef struct IDosHeader
{
        WORD e_magic;
        WORD e_cblp;
        WORD e_cp;
        WORD e_crlc;
        WORD e_cparhdr;
        WORD e_minalloc;
        WORD e_maxalloc;
        WORD e_ss;
        WORD e_sp;
        WORD e_csum;
        WORD e_ip;
        WORD e_cs;
        WORD e_lfarlc;
        WORD e_ovno;
        WORD e_res[4];
        WORD e_oemid;
        WORD e_oeminfo;
        WORD e_res2[10];
        DWORD e_lfanew;
} IDosHeader;

int main()
{
        IDosHeader DosHeader;
        FILE *fp = NULL;
        char szFileName[100];

        // 获取文件名(如:c:\2.exe)
        printf("请输入文件名:");
        gets(szFileName);

        // 打开文件
        if ( (fp=fopen(szFileName, "rb"))==NULL )
        {
                printf("文件打开失败!\n");
                exit(EXIT_FAILURE);
        }
        
        // 读取内容
        if (fread(&DosHeader, sizeof(IDosHeader),1 , fp) != 1)
        {
                printf("文件读取失败!\n");
                exit(EXIT_FAILURE);
        }

        printf("e_magic:%#x\n", DosHeader.e_magic); // 以16进制输出
        printf("e_cblp:%#x\n", DosHeader.e_cblp); // 以16进制输出

        return 0;
}

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
A小小鸟 + 5 + 5 + 3 大哥,膜拜

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-11 23:16:36 | 显示全部楼层
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <windows.h>

size_t get_file_size(const char *filename)
{
        FILE *file = fopen(filename, "r");
        if(!file)
                return -1;

        fseek(file, 0, SEEK_END);
        size_t size = ftell(file);
        fclose(file);
        return size;
}

bool read_file(const char *filename, uint8_t *buff, size_t size)
{
        FILE *file = fopen(filename, "rb");
        if(!file)
                return false;

        fread(buff, 1, size, file);
        fclose(file);
        return true;
}

void print_image_dos_header(IMAGE_DOS_HEADER *idh)
{
        printf("IMAGE_DOS_HEADER\n");
        printf("e_magic: %.4x\n", idh->e_magic);
        printf("e_cblp: %.4x\n", idh->e_cblp);
        printf("e_cp: %.4x\n", idh->e_cp);
        printf("e_crlc: %.4x\n", idh->e_crlc);
        printf("e_cparhdr: %.4x\n", idh->e_cparhdr);
        printf("e_minalloc: %.4x\n", idh->e_minalloc);
        printf("e_maxalloc: %.4x\n", idh->e_maxalloc);
        printf("e_ss: %.4x\n", idh->e_ss);
        printf("e_sp: %.4x\n", idh->e_sp);
        printf("e_csum: %.4x\n", idh->e_csum);
        printf("e_ip: %.4x\n", idh->e_ip);
        printf("e_cs: %.4x\n", idh->e_cs);
        printf("e_lfarlc: %.4x\n", idh->e_lfarlc);
        printf("e_ovno: %.4x\n", idh->e_ovno);
        printf("e_res[0]: %.2x\n", idh->e_res[0]);
        printf("e_res[1]: %.2x\n", idh->e_res[1]);
        printf("e_res[2]: %.2x\n", idh->e_res[2]);
        printf("e_res[3]: %.2x\n", idh->e_res[3]);
        printf("e_oemid: %.4x\n", idh->e_oemid);
        printf("e_oeminfo: %.4x\n", idh->e_oeminfo);
        printf("e_res2[0]: %.2x\n", idh->e_res2[0]);
        printf("e_res2[1]: %.2x\n", idh->e_res2[1]);
        printf("e_res2[2]: %.2x\n", idh->e_res2[2]);
        printf("e_res2[3]: %.2x\n", idh->e_res2[3]);
        printf("e_res2[4]: %.2x\n", idh->e_res2[4]);
        printf("e_res2[5]: %.2x\n", idh->e_res2[5]);
        printf("e_res2[6]: %.2x\n", idh->e_res2[6]);
        printf("e_res2[7]: %.2x\n", idh->e_res2[7]);
        printf("e_res2[8]: %.2x\n", idh->e_res2[8]);
        printf("e_res2[9]: %.2x\n", idh->e_res2[9]);
        printf("e_lfanew: %.8x\n", idh->e_lfanew);
}

void print_image_nt_headers(IMAGE_NT_HEADERS *inh, uint8_t *base)
{
        printf("IMAGE_NT_HEADERS\n");
        printf("Signature: %.8x\n", inh->Signature);
        
        // 下面这两个结构,这里只打印出在文件中的偏移
        printf("FileHeader: %.8x\n", (uint8_t *)&inh->FileHeader - base);
        printf("OptionalHeader: %.8x\n", (uint8_t *)&inh->OptionalHeader - base);
}

void print_image_file_header(IMAGE_FILE_HEADER *ifh)
{
        printf("IMAGE_FILE_HEADER\n");
        printf("Machine: %.4x\n", ifh->Machine);
        printf("NumberOfSections: %.4x\n", ifh->NumberOfSections);
        printf("TimeDateStamp: %.8x\n", ifh->TimeDateStamp);
        printf("PointerToSymbolTable: %.8x\n", ifh->PointerToSymbolTable);
        printf("NumberOfSymbols: %.8x\n", ifh->NumberOfSymbols);
        printf("SizeOfOptionalHeader: %.4x\n", ifh->SizeOfOptionalHeader);
        printf("Characteristics: %.4x\n", ifh->Characteristics);
}

void print_image_optional_header(IMAGE_OPTIONAL_HEADER *ioh, uint8_t *base)
{
        printf("IMAGE_OPTIONAL_HEADER\n");
        printf("Magic: %.4x\n", ioh->Magic);
        printf("MajorLinkerVersion: %.2x\n", ioh->MajorLinkerVersion);
        printf("MinorLinkerVersion: %.2x\n", ioh->MinorLinkerVersion);
        printf("SizeOfCode: %.8x\n", ioh->SizeOfCode);
        printf("SizeOfInitializedData: %.8x\n", ioh->SizeOfInitializedData);
        printf("SizeOfUninitializedData: %.8x\n", ioh->SizeOfUninitializedData);
        printf("AddressOfEntryPoint: %.8x\n", ioh->AddressOfEntryPoint);
        printf("BaseOfCode: %.8x\n", ioh->BaseOfCode);
        printf("BaseOfData: %.8x\n", ioh->BaseOfData);
        printf("ImageBase: %.8x\n", ioh->ImageBase);
        printf("SectionAlignment: %.8x\n", ioh->SectionAlignment);
        printf("FileAlignment: %.8x\n", ioh->FileAlignment);
        printf("MajorOperatingSystemVersion: %.4x\n", ioh->MajorOperatingSystemVersion);
        printf("MinorOperatingSystemVersion: %.4x\n", ioh->MinorOperatingSystemVersion);
        printf("MajorImageVersion: %.4x\n", ioh->MajorImageVersion);
        printf("MinorImageVersion: %.4x\n", ioh->MinorImageVersion);
        printf("MajorSubsystemVersion: %.4x\n", ioh->MajorSubsystemVersion);
        printf("MinorSubsystemVersion: %.4x\n", ioh->MinorSubsystemVersion);
        printf("Win32VersionValue: %.8x\n", ioh->Win32VersionValue);
        printf("SizeOfImage: %.8x\n", ioh->SizeOfImage);
        printf("SizeOfHeaders: %.8x\n", ioh->SizeOfHeaders);
        printf("CheckSum: %.8x\n", ioh->CheckSum);
        printf("Subsystem: %.4x\n", ioh->Subsystem);
        printf("DllCharacteristics: %.4x\n", ioh->DllCharacteristics);
        printf("SizeOfStackReserve: %.8x\n", ioh->SizeOfStackReserve);
        printf("SizeOfStackCommit: %.8x\n", ioh->SizeOfStackCommit);
        printf("SizeOfHeapReserve: %.8x\n", ioh->SizeOfHeapReserve);
        printf("SizeOfHeapCommit: %.8x\n", ioh->SizeOfHeapCommit);
        printf("LoaderFlags: %.8x\n", ioh->LoaderFlags);
        printf("NumberOfRvaAndSizes: %.8x\n", ioh->NumberOfRvaAndSizes);

        // 下面这个数组,我还没有想好要以什么样的形式展开,如何展开,现在只是打印文件偏移
        printf("DataDirectory: %.8x\n", (uint8_t *)&ioh->DataDirectory - base);
}

int main(void)
{
        const char *filename = "print_pe.exe";
        size_t size = get_file_size(filename);
        uint8_t *buff = malloc(size);
        read_file(filename, buff, size);
        
        IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)buff;
        IMAGE_NT_HEADERS *inh = (IMAGE_NT_HEADERS *)(buff + idh->e_lfanew);

        print_image_dos_header(idh); printf("\n");
        print_image_nt_headers(inh, buff); printf("\n");
        print_image_file_header(&inh->FileHeader); printf("\n");
        print_image_optional_header(&inh->OptionalHeader, buff); printf("\n");

        free(buff);
        return 0;
}
IMAGE_DOS_HEADER
e_magic: 5a4d
e_cblp: 0090
e_cp: 0003
e_crlc: 0000
e_cparhdr: 0004
e_minalloc: 0000
e_maxalloc: ffff
e_ss: 0000
e_sp: 00b8
e_csum: 0000
e_ip: 0000
e_cs: 0000
e_lfarlc: 0040
e_ovno: 0000
e_res[0]: 00
e_res[1]: 00
e_res[2]: 00
e_res[3]: 00
e_oemid: 0000
e_oeminfo: 0000
e_res2[0]: 00
e_res2[1]: 00
e_res2[2]: 00
e_res2[3]: 00
e_res2[4]: 00
e_res2[5]: 00
e_res2[6]: 00
e_res2[7]: 00
e_res2[8]: 00
e_res2[9]: 00
e_lfanew: 000000f0

IMAGE_NT_HEADERS
Signature: 00004550
FileHeader: 000000f4
OptionalHeader: 00000108

IMAGE_FILE_HEADER
Machine: 014c
NumberOfSections: 0009
TimeDateStamp: 5c86674e
PointerToSymbolTable: 00000000
NumberOfSymbols: 00000000
SizeOfOptionalHeader: 00e0
Characteristics: 0102

IMAGE_OPTIONAL_HEADER
Magic: 010b
MajorLinkerVersion: 0e
MinorLinkerVersion: 10
SizeOfCode: 00005200
SizeOfInitializedData: 00004400
SizeOfUninitializedData: 00000000
AddressOfEntryPoint: 00011343
BaseOfCode: 00001000
BaseOfData: 00001000
ImageBase: 00400000
SectionAlignment: 00001000
FileAlignment: 00000200
MajorOperatingSystemVersion: 0006
MinorOperatingSystemVersion: 0000
MajorImageVersion: 0000
MinorImageVersion: 0000
MajorSubsystemVersion: 0006
MinorSubsystemVersion: 0000
Win32VersionValue: 00000000
SizeOfImage: 00020000
SizeOfHeaders: 00000400
CheckSum: 00000000
Subsystem: 0003
DllCharacteristics: 8140
SizeOfStackReserve: 00100000
SizeOfStackCommit: 00001000
SizeOfHeapReserve: 00100000
SizeOfHeapCommit: 00001000
LoaderFlags: 00000000
NumberOfRvaAndSizes: 00000010
DataDirectory: 00000168

请按任意键继续. . .

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
A小小鸟 + 5 + 5 + 3 大哥好厉害,还是我太菜了

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-11 23:24:57 | 显示全部楼层
仅仅解析出值是不够的,如果这个程序还要继续写下去,那就要去解析值所对应的含义
例如
e_magic: 5a4d
应该解析为
e_magic: IMAGE_DOS_SIGNATURE

IMAGE_DOS_SIGNATURE这个宏定义的值就是 0x5a4d
#include "pshpack4.h"                   // 4 byte packing is the default

#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ
#define IMAGE_OS2_SIGNATURE                 0x454E      // NE
#define IMAGE_OS2_SIGNATURE_LE              0x454C      // LE
#define IMAGE_VXD_SIGNATURE                 0x454C      // LE
#define IMAGE_NT_SIGNATURE                  0x00004550  // PE00
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-12 14:31:19 | 显示全部楼层
ba21 发表于 2019-3-11 20:37
PE头都是有结构的。用C写也很简单吧,先把所需要的结构声明出来,然后用二进制读文件,读入结构体中。

哇,大哥好厉害,我只能膜拜了,我还以为是很高大上的呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-12 14:34:11 | 显示全部楼层

我什么时候,能达到你的一半啊,感觉你的编程能力好厉害啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-10-3 10:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表