纯C代码解析PE.获取资源表中的文件版本信息.

代码如下. 代码属于转载. 并未使用 windows的结构体. PIMAGE_DOS_HEADER ....等解析.
适用于内核驱动. windows内核下可以使用此代码来获取文件资源版本.

/* Distributed under the CC-wiki license.
* user contributions licensed under cc by-sa 3.0 with attribution required:
* https://creativecommons.org/licenses/by-sa/3.0/ Originally taken from the
* answer by @rodrigo, found here: http://stackoverflow.com/a/12486703/850326
*/
#include <memory.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
//#include <windows.h>
typedef uint32_t DWORD;
typedef uint16_t WORD;
typedef uint8_t BYTE;
#define READ_BYTE(p) (((unsigned char *)(p))[0])
#define READ_WORD(p) \
((((unsigned char *)(p))[0]) | ((((unsigned char *)(p))[1]) << 8))
#define READ_DWORD(p) \
((((unsigned char *)(p))[0]) | ((((unsigned char *)(p))[1]) << 8) | \
((((unsigned char *)(p))[2]) << 16) | ((((unsigned char *)(p))[3]) << 24))
#define PAD(x) (((x) + 3) & 0xFFFFFFFC)
const char *FindVersion(const char *buf) {
// buf is a IMAGE_DOS_HEADER
if (READ_WORD(buf) != 0x5A4D) // MZ signature
return NULL;
// pe is a IMAGE_NT_HEADERS32
const char *pe = buf + READ_DWORD(buf + 0x3C);
if (READ_WORD(pe) != 0x4550) // PE signature
return NULL;
// coff is a IMAGE_FILE_HEADER
const char *coff = pe + 4;
WORD numSections = READ_WORD(coff + 2);
WORD optHeaderSize = READ_WORD(coff + 16);
if (numSections == 0 || optHeaderSize == 0) return NULL;
// optHeader is a IMAGE_OPTIONAL_HEADER32
const char *optHeader = coff + 20;
WORD magic = READ_WORD(optHeader);
if (magic != 0x10b && magic != 0x20b) return NULL;
// if (READ_WORD(optHeader) != 0x10b) //Optional header magic (32 bits)
// //这是判断32的代码.
// return NULL;
// dataDir is an array of IMAGE_DATA_DIRECTORY
// const char *dataDir = optHeader + 96; //这是判断32的代码
const char *dataDir = optHeader + (magic == 0x10b ? 96 : 112);
DWORD vaRes = READ_DWORD(dataDir + 8 * 2);
// secTable is an array of IMAGE_SECTION_HEADER
const char *secTable = optHeader + optHeaderSize;
int i;
for (i = 0; i < numSections; ++i) {
// sec is a IMAGE_SECTION_HEADER*
const char *sec = secTable + 40 * i;
char secName[9];
memcpy(secName, sec, 8);
secName[8] = 0;
if (strcmp(secName, ".rsrc") != 0) continue;
DWORD vaSec = READ_DWORD(sec + 12);
const char *raw = buf + READ_DWORD(sec + 20);
const char *resSec = raw + (vaRes - vaSec);
WORD numNamed = READ_WORD(resSec + 12);
WORD numId = READ_WORD(resSec + 14);
int j;
for (j = 0; j < numNamed + numId; ++j) {
// resSec is a IMAGE_RESOURCE_DIRECTORY followed by an array
// of IMAGE_RESOURCE_DIRECTORY_ENTRY
const char *res = resSec + 16 + 8 * j;
DWORD name = READ_DWORD(res);
if (name != 16) // RT_VERSION
continue;
DWORD offs = READ_DWORD(res + 4);
if ((offs & 0x80000000) == 0) // is a dir resource?
return NULL;
// verDir is another IMAGE_RESOURCE_DIRECTORY and
// IMAGE_RESOURCE_DIRECTORY_ENTRY array
const char *verDir = resSec + (offs & 0x7FFFFFFF);
numNamed = READ_WORD(verDir + 12);
numId = READ_WORD(verDir + 14);
if (numNamed == 0 && numId == 0) return NULL;
res = verDir + 16;
offs = READ_DWORD(res + 4);
if ((offs & 0x80000000) == 0) // is a dir resource?
return NULL;
// and yet another IMAGE_RESOURCE_DIRECTORY, etc.
verDir = resSec + (offs & 0x7FFFFFFF);
numNamed = READ_WORD(verDir + 12);
numId = READ_WORD(verDir + 14);
if (numNamed == 0 && numId == 0) return NULL;
res = verDir + 16;
offs = READ_DWORD(res + 4);
if ((offs & 0x80000000) != 0) // is a dir resource?
return NULL;
verDir = resSec + offs;
DWORD verVa = READ_DWORD(verDir);
const char *verPtr = raw + (verVa - vaSec);
return verPtr;
}
return NULL;
}
return NULL;
}
int PrintVersion(const char *version, int offs) {
offs = PAD(offs);
WORD len = READ_WORD(version + offs);
offs += 2;
WORD valLen = READ_WORD(version + offs);
offs += 2;
WORD type = READ_WORD(version + offs);
offs += 2;
char info[200];
int i;
for (i = 0; i < 200; ++i) {
WORD c = READ_WORD(version + offs);
offs += 2;
info[i] = c;
if (!c) break;
}
offs = PAD(offs);
if (type != 0) // TEXT
{
char value[200];
for (i = 0; i < valLen; ++i) {
WORD c = READ_WORD(version + offs);
offs += 2;
value[i] = c;
}
value[i] = 0;
printf("info <%s>: <%s>\n", info, value);
} else {
if (strcmp(info, "VS_VERSION_INFO") == 0) {
// fixed is a VS_FIXEDFILEINFO
const char *fixed = version + offs;
WORD fileA = READ_WORD(fixed + 10);
WORD fileB = READ_WORD(fixed + 8);
WORD fileC = READ_WORD(fixed + 14);
WORD fileD = READ_WORD(fixed + 12);
WORD prodA = READ_WORD(fixed + 18);
WORD prodB = READ_WORD(fixed + 16);
WORD prodC = READ_WORD(fixed + 22);
WORD prodD = READ_WORD(fixed + 20);
printf("\tFile: %d.%d.%d.%d\n", fileA, fileB, fileC, fileD);
printf("\tProd: %d.%d.%d.%d\n", prodA, prodB, prodC, prodD);
}
offs += valLen;
}
while (offs < len) offs = PrintVersion(version, offs);
return PAD(offs);
}
int main(int argc, char **argv) {
struct stat st;
if (stat(argv[1], &st) < 0) {
perror(argv[1]);
return 1;
}
char *buf = (char *)malloc(st.st_size);
FILE *f = fopen(argv[1], "rb");
if (!f) {
perror(argv[1]);
return 2;
}
fread(buf, 1, st.st_size, f);
fclose(f);
const char *version = FindVersion(buf);
if (!version)
printf("No version\n");
else
PrintVersion(version, 0);
return 0;
}

下图为解析 wirshark抓包工具. 64位版本.

posted @   iBinary  阅读(458)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
历史上的今天:
2018-10-16 Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字
点击右上角即可分享
微信分享提示