纯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位版本.
作者:IBinary
坚持两字,简单,轻便,但是真正的执行起来确实需要很长很长时间.当你把坚持两字当做你要走的路,那么你总会成功. 想学习,有问题请加群.群号:725864912(收费)群名称: 逆向学习小分队 群里有大量学习资源. 以及定期直播答疑.有一个良好的学习氛围. 涉及到外挂反外挂病毒 司法取证加解密 驱动过保护 VT 等技术,期待你的进入。
详情请点击链接查看置顶博客 https://www.cnblogs.com/iBinary/p/7572603.html
本文来自博客园,作者:iBinary,未经允许禁止转载 转载前可联系本人.对于爬虫人员来说如果发现保留起诉权力.https://www.cnblogs.com/iBinary/p/17766999.html
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能. QQ群: