纯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
欢迎大家关注我的微信公众号.不定期的更新文章.更新技术. 关注公众号后请大家养成 不白嫖的习惯.欢迎大家赞赏. 也希望在看完公众号文章之后 不忘 点击 收藏 转发 以及点击在看功能.

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2018-10-16 Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字