无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
楼主: mdyblog
打印 上一主题 下一主题

[更新376#2825]PECMD2012.1.80.13_Win32_64.多窗口多线程.裸机系统2.3.3.1+18M酷M...

    [复制链接]
19471#
发表于 2025-9-18 15:32:06 | 只看该作者
本帖最后由 没想到 于 2025-9-18 21:21 编辑

PART -iv=1 list drv C:,分区
这个 分区 是物理号还是分区号

点评

-phy# 加上这个对比一下就知道啦  详情 回复 发表于 2025-9-20 19:25
回复

使用道具 举报

19472#
发表于 2025-9-20 10:01:22 | 只看该作者
唏嘘学习
回复

使用道具 举报

19473#
发表于 2025-9-20 19:25:31 来自手机 | 只看该作者
没想到 发表于 2025-9-18 15:32
PART -iv=1 list drv C:,分区
这个 分区 是物理号还是分区号

-phy#
加上这个对比一下就知道啦
回复

使用道具 举报

19474#
发表于 2025-9-20 20:23:08 来自手机 | 只看该作者
占楼
回复

使用道具 举报

19475#
发表于 2025-9-20 21:04:02 | 只看该作者
红毛樱木 发表于 2025-9-20 19:25
-phy#
加上这个对比一下就知道啦

测试到了,默认分区号
回复

使用道具 举报

19476#
发表于 2025-9-20 23:29:26 | 只看该作者
多看多学习,支持一下!
回复

使用道具 举报

19477#
发表于 2025-9-24 13:12:52 来自手机 | 只看该作者
占楼
回复

使用道具 举报

19478#
发表于 2025-9-25 23:18:55 | 只看该作者
感谢分享
回复

使用道具 举报

19479#
发表于 2025-9-27 11:44:17 来自手机 | 只看该作者
谢谢制作辛苦了
回复

使用道具 举报

19480#
发表于 2025-10-9 16:39:34 | 只看该作者
谢谢分享,学习一下,谢谢。
回复

使用道具 举报

19481#
发表于 2025-10-10 10:21:48 来自手机 | 只看该作者
看看
回复

使用道具 举报

19482#
发表于 2025-10-16 12:17:21 | 只看该作者
多窗口
回复

使用道具 举报

19483#
发表于 2025-10-16 12:17:54 | 只看该作者
多看多学习,支持一下!
回复

使用道具 举报

19484#
发表于 2025-10-16 13:30:38 | 只看该作者
好东西  
回复

使用道具 举报

19485#
发表于 2025-10-16 13:30:58 | 只看该作者
测试
回复

使用道具 举报

19486#
发表于 2025-10-16 16:30:38 | 只看该作者
干货满满!很给力~
回复

使用道具 举报

19487#
发表于 2025-10-16 16:31:20 | 只看该作者
支持大佬,收下备用!
回复

使用道具 举报

19488#
发表于 2025-10-16 16:31:33 | 只看该作者
正需要,很不错
回复

使用道具 举报

19489#
发表于 2025-10-16 16:31:44 | 只看该作者
经典资源,收藏备用
回复

使用道具 举报

19490#
发表于 2025-11-3 23:07:22 | 只看该作者
获取程序图标组中第一个图标的ID
    定位 RT_GROUP_ICON(类型ID=14)的资源目录,跳过无关资源类型。
    简化偏移计算,利用PE文件的 IMAGE_DATA_DIRECTORY 直接定位资源节。
求翻译PECMD怎样写

  1. #include <windows.h>
  2. #include <stdio.h>

  3. DWORD GetFirstIconGroupID(LPCWSTR exePath) {
  4.     HANDLE hFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  5.     if (hFile == INVALID_HANDLE_VALUE) return 0;

  6.     DWORD fileSize = GetFileSize(hFile, NULL);
  7.     HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, fileSize, NULL);
  8.     LPVOID pBase = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  9.     if (!pBase) { CloseHandle(hMap); CloseHandle(hFile); return 0; }

  10.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pBase;
  11.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)pBase + dos->e_lfanew);
  12.     if (nt->Signature != IMAGE_NT_SIGNATURE) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }

  13.     // 定位资源目录
  14.     auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  15.     if (resDir.VirtualAddress == 0) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }

  16.     // 定位资源节(.rsrc)
  17.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt);
  18.     for (int i = 0; i < nt->FileHeader.NumberOfSections; i++, section++) {
  19.         if (resDir.VirtualAddress >= section->VirtualAddress &&
  20.             resDir.VirtualAddress < section->VirtualAddress + section->Misc.VirtualSize) break;
  21.     }

  22.     // 计算资源目录在文件中的实际偏移
  23.     DWORD resOffset = resDir.VirtualAddress - section->VirtualAddress + section->PointerToRawData;
  24.     PIMAGE_RESOURCE_DIRECTORY rootDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pBase + resOffset);

  25.     // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
  26.     PIMAGE_RESOURCE_DIRECTORY_ENTRY typeEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(rootDir + 1);
  27.     for (DWORD i = 0; i < rootDir->NumberOfIdEntries; i++, typeEntry++) {
  28.         if (typeEntry->Id == 14) { // RT_GROUP_ICON = 14
  29.             // 获取第一个图标ID(进入ID目录的第一个条目)
  30.             PIMAGE_RESOURCE_DIRECTORY iconDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)rootDir + typeEntry->OffsetToDirectory);
  31.             PIMAGE_RESOURCE_DIRECTORY_ENTRY iconIdEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(iconDir + 1);
  32.             DWORD firstIconId = iconIdEntry->Id;

  33.             UnmapViewOfFile(pBase);
  34.             CloseHandle(hMap);
  35.             CloseHandle(hFile);
  36.             return firstIconId;
  37.         }
  38.     }

  39.     UnmapViewOfFile(pBase);
  40.     CloseHandle(hMap);
  41.     CloseHandle(hFile);
  42.     return 0;
  43. }

  44. // 调用示例:获取 Photoshop.exe 的第一个图标ID
  45. int main() {
  46.     LPCWSTR exePath = L"D:\\软件\\Photoshop\\Photoshop.exe";
  47.     DWORD iconId = GetFirstIconGroupID(exePath);
  48.     printf("第一个图标ID: %u\n", iconId); // 输出:1000 或 1 等
  49.     return 0;
  50. }
复制代码

点评

这玩意写的太累人了。坐了一天,快点给钱吧  详情 回复 发表于 2025-11-5 16:14
这里有几个结构体,要用PECMD搞,太烦了。  详情 回复 发表于 2025-11-5 10:33
回复

使用道具 举报

19491#
发表于 2025-11-4 11:31:02 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

19492#
发表于 2025-11-5 10:33:45 | 只看该作者
Zap 发表于 2025-11-3 23:07
获取程序图标组中第一个图标的ID
    定位 RT_GROUP_ICON(类型ID=14)的资源目录,跳过无关资源类型。
  ...

这里有几个结构体,要用PECMD搞,太烦了。
回复

使用道具 举报

19493#
发表于 2025-11-5 16:14:08 | 只看该作者
本帖最后由 红毛樱木 于 2025-11-5 16:16 编辑
Zap 发表于 2025-11-3 23:07
获取程序图标组中第一个图标的ID
    定位 RT_GROUP_ICON(类型ID=14)的资源目录,跳过无关资源类型。
  ...


  1. //LOGS * %&CurDir%\log.log
  2. ENVI^ ENVIMODE=1
  3. // PECMD2012 内部本身就是宽字符Unicode。路径\\可以直接写真实路径\,自动转义。
  4. ENVI &exePath=D:\软件\Photoshop\Photoshop.exe
  5. CALL GetFirstIconGroupID "%&exePath%" &iconId
  6. MESS. 第一个图标ID: %&iconId%@

  7. _SUB GetFirstIconGroupID
  8.     ENVI &&exePath=%~1
  9.     ENVI &&GENERIC_READ=0x80000000
  10.     ENVI &&FILE_SHARE_READ=0x00000001
  11.     ENVI &&OPEN_EXISTING=3
  12.     ENVI &&INVALID_HANDLE_VALUE=-1
  13.     CALL$--qd --ret:&&hFile Kernel32.dll,CreateFileW,$%&exePath%,#%&GENERIC_READ%,#%&FILE_SHARE_READ%,#0,#%&OPEN_EXISTING%,#0,#0       // C中的NULL就是0,在PECMD中用数值 #0
  14.     IFEX #%&hFile%=%&INVALID_HANDLE_VALUE%,
  15.     {*
  16.         EXIT= 0
  17.         EXIT _SUB
  18.     }
  19.     CALL$--qd --ret:&&fileSize Kernel32.dll,GetFileSize,#%&hFile%,#0
  20.     ENVI &&PAGE_READONLY=0x02
  21.     CALL$--qd --ret:&&hMap Kernel32.dll,CreateFileMappingW,#%&hFile%,#0,#%&PAGE_READONLY%,#0,#%&fileSize%,0     //CreateFileMapping 要用实际的 CreateFileMappingW
  22.     ENVI &&FILE_MAP_READ=0x0004
  23.     CALL$--qd --16 --ret:&&pBase Kernel32.dll,MapViewOfFile,#%&hMap%,#%&FILE_MAP_READ%,#0,#0,#0
  24.     //MESS. %&pBase%@&pBase
  25.     IFEX #%&pBase%=0,
  26.     {*
  27.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  28.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  29.         ENVI-ret %~2=0
  30.         EXIT _SUB
  31.     }
  32.     // PIMAGE_DOS_HEADER 的结构体 IMAGE_DOS_HEADER  64字节
  33.     //SET$# &dos=*64 0
  34.     SET-mkfixdummy &dos=%&pBase%@0;*64
  35.     SET?longs dos=&&dos.e_lfanew:60
  36.     //MESS. %&dos.e_lfanew%@&dos.e_lfanew
  37.     // PIMAGE_NT_HEADERS 的结构体(64位为 IMAGE_NT_HEADERS64 大小 264字节)(32位为 IMAGE_NT_HEADERS32 大小 248字节)
  38.     IFEX #%&bX64%=3,
  39.     {*
  40.         //SET$# &nt=*264 0
  41.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
  42.     }!  
  43.     {*
  44.         //SET$# &nt=*248 0
  45.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
  46.     }
  47.     //GETF &nt,0#*,&&nt_Hex
  48.     //MESS. %&nt_Hex%@&nt_Hex
  49.     SET?long nt=&&nt.Signature:0
  50.     //MESS. %&nt.Signature%@&nt.Signature
  51.     ENVI &&IMAGE_NT_SIGNATURE=0x00004550  // PE00
  52.     IFEX #%&nt.Signature%<>%&IMAGE_NT_SIGNATURE%,
  53.     {*
  54.         CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  55.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  56.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  57.         ENVI-ret %~2=0
  58.         EXIT _SUB
  59.     }
  60.    
  61.     // 定位资源目录
  62.     // auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  63.     //ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2   // Resource Directory
  64.     ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0     // 测试
  65.     IFEX #%&bX64%=3,
  66.     {*
  67.         SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  68.     }!  
  69.     {*
  70.         SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  71.     }
  72.     //GETF &resDir,0#*,&&resDir_Hex
  73.     //MESS. %&resDir_Hex%@&resDir_Hex
  74.     SET?long resDir=&&resDir.VirtualAddress:0
  75.     //MESS. %&resDir.VirtualAddress%@&resDir.VirtualAddress
  76.    
  77.     // 定位资源节(.rsrc)
  78.     ENVI &&i=0
  79.     SET?shorts nt=&&nt.FileHeader.NumberOfSections:(4+2)    //WORD 2 字节,用short和wchar都可以
  80.     //MESS. %&nt.FileHeader.NumberOfSections%@&nt.FileHeader.NumberOfSections
  81.     SET?shorts nt=&&nt.FileHeader.SizeOfOptionalHeader:(4+2+2+4+4+4)
  82.     //MESS. %&nt.FileHeader.SizeOfOptionalHeader%@&nt.FileHeader.SizeOfOptionalHeader
  83.     //SET-mkfixdummy &section=&nt
  84.    
  85.     LOOP #%&i%<%&nt.FileHeader.NumberOfSections%,
  86.     {*
  87.         //#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))
  88.         SET-mkfixdummy &section=(%&pBase%+%&dos.e_lfanew%+(4+20+%&nt.FileHeader.SizeOfOptionalHeader%))@(40*%&i%);*40        // 相当于 section++
  89.         //GETF &section,0#40,&&section_Hex
  90.         //MESS. %&section_Hex%@&section_Hex
  91.         SET?long section=&&section.VirtualAddress:12
  92.         //MESS. &section.VirtualAddress:%&section.VirtualAddress%@%&i%
  93.         SET?long section=&&section.Misc.VirtualSize:8
  94.         //MESS. IFEX #[ ( %&resDir.VirtualAddress% >= %&section.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %&section.VirtualAddress% + %&section.Misc.VirtualSize% ) ) ],@%&i%
  95.         //IFEX #[ ( %&resDir.VirtualAddress% >= %&section.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %&section.VirtualAddress% + %&section.Misc.VirtualSize% ) ) ],     // IFEX 存在BUG,不能这样嵌套使用,先算出来吧。
  96.         IFEX #%&resDir.VirtualAddress% >= %&section.VirtualAddress%,
  97.         {*
  98.             CALC &&Fix=%&section.VirtualAddress% + %&section.Misc.VirtualSize%
  99.             IFEX #%&resDir.VirtualAddress% < %&Fix%,
  100.             {*
  101.                 EXIT LOOP
  102.             }
  103.         }
  104.         CALC #&i=%&i% + 1
  105.     }
  106.     // 计算资源目录在文件中的实际偏移
  107.     SET?long section=&&section.PointerToRawData:20
  108.     CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%
  109.     //MESS. %&resOffset%<&i:%&i%><CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%>@&resOffset
  110.     SET-mkfixdummy &rootDir=(%&pBase%+%&resOffset%)@0;*16
  111.     SET?short rootDir=&&rootDir.NumberOfIdEntries:(4+4+2+2+2)
  112.     //MESS. %&rootDir.NumberOfIdEntries%@&rootDir.NumberOfIdEntries
  113.    
  114.     // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
  115.     //SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@16;*8
  116.     //GETF &typeEntry,0#8,&&typeEntry_Hex
  117.     //MESS. %&typeEntry_Hex%@&typeEntry_Hex
  118.    
  119.     ENVI &&i=0
  120.     LOOP #%&i%<%&rootDir.NumberOfIdEntries%,
  121.     {*
  122.         SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@(16+(8*%&i%));*8
  123.         SET?short typeEntry=&&typeEntry.Id:0
  124.         //MESS. %&typeEntry.Id%@%&i%
  125.         IFEX #%&typeEntry.Id%=14,       // RT_GROUP_ICON = 14
  126.         {*
  127.             // 获取第一个图标ID(进入ID目录的第一个条目)
  128.             SET?long typeEntry=&&typeEntry.OffsetToDirectory:4
  129.             CALC #&typeEntry.OffsetToDirectory=%&typeEntry.OffsetToDirectory% & 0x7FFFFFFF
  130.             SET-mkfixdummy &iconDir=(%&pBase%+%&resOffset%)@%&typeEntry.OffsetToDirectory%;*16
  131.             SET-mkfixdummy &iconIdEntry=(%&pBase%+%&resOffset%)@(%&typeEntry.OffsetToDirectory%+16);*8
  132.             SET?short iconIdEntry=&&iconIdEntry.Id:0
  133.             CALC &&firstIconId=%&iconIdEntry.Id%        // 不知道源码这里为什么用DWORD计算WORD
  134.             //MESS. %&firstIconId%@
  135.             
  136.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  137.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  138.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  139.             ENVI-ret~ %~2=&firstIconId
  140.             EXIT _SUB
  141.         }
  142.         CALC #&i=%&i% + 1
  143.     }
  144.     CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  145.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  146.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  147.     ENVI-ret %~2=0
  148. _END


  149. EXIT FILE

  150. typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
  151.     union {
  152.         struct {
  153.             DWORD NameOffset:31;
  154.             DWORD NameIsString:1;
  155.         } DUMMYSTRUCTNAME;
  156.         DWORD   Name;
  157.         WORD    Id;
  158.     } DUMMYUNIONNAME;
  159.     union {
  160.         DWORD   OffsetToData;
  161.         struct {
  162.             DWORD   OffsetToDirectory:31;
  163.             DWORD   DataIsDirectory:1;
  164.         } DUMMYSTRUCTNAME2;
  165.     } DUMMYUNIONNAME2;
  166. } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;     //8b

  167. typedef struct _IMAGE_RESOURCE_DIRECTORY {
  168.     DWORD   Characteristics;
  169.     DWORD   TimeDateStamp;
  170.     WORD    MajorVersion;
  171.     WORD    MinorVersion;
  172.     WORD    NumberOfNamedEntries;
  173.     WORD    NumberOfIdEntries;
  174. //  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
  175. } IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;     /16b

  176. typedef struct _IMAGE_SECTION_HEADER {
  177.     BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
  178.     union {
  179.             DWORD   PhysicalAddress;
  180.             DWORD   VirtualSize;
  181.     } Misc;
  182.     DWORD   VirtualAddress;
  183.     DWORD   SizeOfRawData;
  184.     DWORD   PointerToRawData;
  185.     DWORD   PointerToRelocations;
  186.     DWORD   PointerToLinenumbers;
  187.     WORD    NumberOfRelocations;
  188.     WORD    NumberOfLinenumbers;
  189.     DWORD   Characteristics;
  190. } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;     //40b

  191. typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
  192.     WORD   e_magic;                     // Magic number
  193.     WORD   e_cblp;                      // Bytes on last page of file
  194.     WORD   e_cp;                        // Pages in file
  195.     WORD   e_crlc;                      // Relocations
  196.     WORD   e_cparhdr;                   // Size of header in paragraphs
  197.     WORD   e_minalloc;                  // Minimum extra paragraphs needed
  198.     WORD   e_maxalloc;                  // Maximum extra paragraphs needed
  199.     WORD   e_ss;                        // Initial (relative) SS value
  200.     WORD   e_sp;                        // Initial SP value
  201.     WORD   e_csum;                      // Checksum
  202.     WORD   e_ip;                        // Initial IP value
  203.     WORD   e_cs;                        // Initial (relative) CS value
  204.     WORD   e_lfarlc;                    // File address of relocation table
  205.     WORD   e_ovno;                      // Overlay number
  206.     WORD   e_res[4];                    // Reserved words
  207.     WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
  208.     WORD   e_oeminfo;                   // OEM information; e_oemid specific
  209.     WORD   e_res2[10];                  // Reserved words
  210.     LONG   e_lfanew;                    // File address of new exe header
  211.   } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;       //64b

  212. typedef struct _IMAGE_FILE_HEADER {
  213.     WORD    Machine;
  214.     WORD    NumberOfSections;
  215.     DWORD   TimeDateStamp;
  216.     DWORD   PointerToSymbolTable;
  217.     DWORD   NumberOfSymbols;
  218.     WORD    SizeOfOptionalHeader;
  219.     WORD    Characteristics;
  220. } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;       //20b

  221. typedef struct _IMAGE_DATA_DIRECTORY {
  222.     DWORD   VirtualAddress;
  223.     DWORD   Size;
  224. } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;     //8b

  225. typedef struct _IMAGE_OPTIONAL_HEADER {
  226.     //
  227.     // Standard fields.
  228.     //

  229.     WORD    Magic;
  230.     BYTE    MajorLinkerVersion;
  231.     BYTE    MinorLinkerVersion;
  232.     DWORD   SizeOfCode;
  233.     DWORD   SizeOfInitializedData;
  234.     DWORD   SizeOfUninitializedData;
  235.     DWORD   AddressOfEntryPoint;
  236.     DWORD   BaseOfCode;
  237.     DWORD   BaseOfData;

  238.     //
  239.     // NT additional fields.
  240.     //

  241.     DWORD   ImageBase;
  242.     DWORD   SectionAlignment;
  243.     DWORD   FileAlignment;
  244.     WORD    MajorOperatingSystemVersion;
  245.     WORD    MinorOperatingSystemVersion;
  246.     WORD    MajorImageVersion;
  247.     WORD    MinorImageVersion;
  248.     WORD    MajorSubsystemVersion;
  249.     WORD    MinorSubsystemVersion;
  250.     DWORD   Win32VersionValue;
  251.     DWORD   SizeOfImage;
  252.     DWORD   SizeOfHeaders;
  253.     DWORD   CheckSum;
  254.     WORD    Subsystem;
  255.     WORD    DllCharacteristics;
  256.     DWORD   SizeOfStackReserve;
  257.     DWORD   SizeOfStackCommit;
  258.     DWORD   SizeOfHeapReserve;
  259.     DWORD   SizeOfHeapCommit;
  260.     DWORD   LoaderFlags;
  261.     DWORD   NumberOfRvaAndSizes;
  262.     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];       //偏移地址  96b
  263. } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

  264. typedef struct _IMAGE_OPTIONAL_HEADER64 {
  265.     WORD        Magic;
  266.     BYTE        MajorLinkerVersion;
  267.     BYTE        MinorLinkerVersion;
  268.     DWORD       SizeOfCode;
  269.     DWORD       SizeOfInitializedData;
  270.     DWORD       SizeOfUninitializedData;
  271.     DWORD       AddressOfEntryPoint;
  272.     DWORD       BaseOfCode;
  273.     ULONGLONG   ImageBase;
  274.     DWORD       SectionAlignment;
  275.     DWORD       FileAlignment;
  276.     WORD        MajorOperatingSystemVersion;
  277.     WORD        MinorOperatingSystemVersion;
  278.     WORD        MajorImageVersion;
  279.     WORD        MinorImageVersion;
  280.     WORD        MajorSubsystemVersion;
  281.     WORD        MinorSubsystemVersion;
  282.     DWORD       Win32VersionValue;
  283.     DWORD       SizeOfImage;
  284.     DWORD       SizeOfHeaders;
  285.     DWORD       CheckSum;
  286.     WORD        Subsystem;
  287.     WORD        DllCharacteristics;
  288.     ULONGLONG   SizeOfStackReserve;
  289.     ULONGLONG   SizeOfStackCommit;
  290.     ULONGLONG   SizeOfHeapReserve;
  291.     ULONGLONG   SizeOfHeapCommit;
  292.     DWORD       LoaderFlags;
  293.     DWORD       NumberOfRvaAndSizes;
  294.     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];       //偏移地址  112b
  295. } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

  296. typedef struct _IMAGE_NT_HEADERS64 {
  297.     DWORD Signature;
  298.     IMAGE_FILE_HEADER FileHeader;
  299.     IMAGE_OPTIONAL_HEADER64 OptionalHeader;
  300. } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

  301. typedef struct _IMAGE_NT_HEADERS {
  302.     DWORD Signature;
  303.     IMAGE_FILE_HEADER FileHeader;
  304.     IMAGE_OPTIONAL_HEADER32 OptionalHeader;
  305. } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

  306. #include <windows.h>
  307. #include <stdio.h>

  308. DWORD GetFirstIconGroupID(LPCWSTR exePath) {
  309.     HANDLE hFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  310.     if (hFile == INVALID_HANDLE_VALUE) return 0;

  311.     DWORD fileSize = GetFileSize(hFile, NULL);
  312.     HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, fileSize, NULL);
  313.     LPVOID pBase = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  314.     if (!pBase) { CloseHandle(hMap); CloseHandle(hFile); return 0; }

  315.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pBase;
  316.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)pBase + dos->e_lfanew);
  317.     if (nt->Signature != IMAGE_NT_SIGNATURE) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }

  318.     // 定位资源目录
  319.     auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  320.     if (resDir.VirtualAddress == 0) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }

  321.     // 定位资源节(.rsrc)
  322.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt);
  323.     for (int i = 0; i < nt->FileHeader.NumberOfSections; i++, section++) {
  324.         if (resDir.VirtualAddress >= section->VirtualAddress &&
  325.             resDir.VirtualAddress < section->VirtualAddress + section->Misc.VirtualSize) break;
  326.     }

  327.     // 计算资源目录在文件中的实际偏移
  328.     DWORD resOffset = resDir.VirtualAddress - section->VirtualAddress + section->PointerToRawData;
  329.     PIMAGE_RESOURCE_DIRECTORY rootDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pBase + resOffset);

  330.     // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
  331.     PIMAGE_RESOURCE_DIRECTORY_ENTRY typeEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(rootDir + 1);
  332.     for (DWORD i = 0; i < rootDir->NumberOfIdEntries; i++, typeEntry++) {
  333.         if (typeEntry->Id == 14) { // RT_GROUP_ICON = 14
  334.             // 获取第一个图标ID(进入ID目录的第一个条目)
  335.             PIMAGE_RESOURCE_DIRECTORY iconDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)rootDir + typeEntry->OffsetToDirectory);
  336.             PIMAGE_RESOURCE_DIRECTORY_ENTRY iconIdEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(iconDir + 1);
  337.             DWORD firstIconId = iconIdEntry->Id;

  338.             UnmapViewOfFile(pBase);
  339.             CloseHandle(hMap);
  340.             CloseHandle(hFile);
  341.             return firstIconId;
  342.         }
  343.     }

  344.     UnmapViewOfFile(pBase);
  345.     CloseHandle(hMap);
  346.     CloseHandle(hFile);
  347.     return 0;
  348. }

  349. // 调用示例:获取 Photoshop.exe 的第一个图标ID
  350. int main() {
  351.     LPCWSTR exePath = L"D:\\软件\\Photoshop\\Photoshop.exe";
  352.     DWORD iconId = GetFirstIconGroupID(exePath);
  353.     printf("第一个图标ID: %u\n", iconId); // 输出:1000 或 1 等
  354.     return 0;
  355. }

复制代码
这玩意写的太累人了。坐了一天,快点给钱吧

点评

牛逼!目测这代码值一千块钱  详情 回复 发表于 2025-11-5 17:50
这代码应该还有地方有偏移地址计算错的。 ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0 才可以,实际看源码是 ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2。 你看看自己能不能解决吧,解决不了 回头我再看看。  详情 回复 发表于 2025-11-5 16:19
回复

使用道具 举报

19494#
发表于 2025-11-5 16:19:50 | 只看该作者
红毛樱木 发表于 2025-11-5 16:14
这玩意写的太累人了。坐了一天,快点给钱吧

这代码应该还有地方有偏移地址计算错的。   ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0  才可以,实际看源码是 ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2。  你看看自己能不能解决吧,解决不了  回头我再看看。

点评

更正后的代码。 C++源码你自己改吧....  详情 回复 发表于 2025-11-5 23:36
回复

使用道具 举报

19495#
发表于 2025-11-5 17:50:50 | 只看该作者
红毛樱木 发表于 2025-11-5 16:14
这玩意写的太累人了。坐了一天,快点给钱吧

牛逼!目测这代码值一千块钱
回复

使用道具 举报

19496#
发表于 2025-11-5 23:36:11 | 只看该作者
本帖最后由 红毛樱木 于 2025-11-5 23:46 编辑
红毛樱木 发表于 2025-11-5 16:19
这代码应该还有地方有偏移地址计算错的。   ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0  才可以,实际看源 ...

更正后的代码。
C++源码你自己改吧....



  1. //LOGS * %&CurDir%\log.log
  2. ENVI^ ENVIMODE=1
  3. // PECMD2012 内部本身就是宽字符Unicode。路径\\可以直接写真实路径\,自动转义。
  4. ENVI &exePath=D:\软件\Photoshop\Photoshop.exe
  5. CALL GetFirstIconGroupID "%&exePath%" &iconId
  6. MESS. 第一个图标ID: %&iconId%@

  7. _SUB GetFirstIconGroupID
  8.     ENVI-ret %~2=0
  9.     ENVI &&exePath=%~1
  10.     ENVI &&GENERIC_READ=0x80000000
  11.     ENVI &&FILE_SHARE_READ=0x00000001
  12.     ENVI &&OPEN_EXISTING=3
  13.     ENVI &&INVALID_HANDLE_VALUE=-1
  14.     CALL$--qd --ret:&&hFile Kernel32.dll,CreateFileW,$%&exePath%,#%&GENERIC_READ%,#%&FILE_SHARE_READ%,#0,#%&OPEN_EXISTING%,#0,#0       // C中的NULL就是0,在PECMD中用数值 #0
  15.     IFEX #%&hFile%=%&INVALID_HANDLE_VALUE%,
  16.     {*
  17.         ENVI-ret %~2=0
  18.         EXIT _SUB
  19.     }
  20.     CALL$--qd --ret:&&fileSize Kernel32.dll,GetFileSize,#%&hFile%,#0
  21.     ENVI &&PAGE_READONLY=0x02
  22.     CALL$--qd --ret:&&hMap Kernel32.dll,CreateFileMappingW,#%&hFile%,#0,#%&PAGE_READONLY%,#0,#%&fileSize%,0     //CreateFileMapping 要用实际的 CreateFileMappingW
  23.     ENVI &&FILE_MAP_READ=0x0004
  24.     CALL$--qd --16 --ret:&&pBase Kernel32.dll,MapViewOfFile,#%&hMap%,#%&FILE_MAP_READ%,#0,#0,#0
  25.     //MESS. %&pBase%@&pBase
  26.     IFEX #%&pBase%=0,
  27.     {*
  28.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  29.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  30.         ENVI-ret %~2=0
  31.         EXIT _SUB
  32.     }
  33.     // PIMAGE_DOS_HEADER 的结构体 IMAGE_DOS_HEADER  64字节
  34.     //SET$# &dos=*64 0
  35.     SET-mkfixdummy &dos=%&pBase%@0;*64
  36.     SET?longs dos=&&dos.e_lfanew:60
  37.     //MESS. %&dos.e_lfanew%@&dos.e_lfanew
  38.     // PIMAGE_NT_HEADERS 的结构体(64位为 IMAGE_NT_HEADERS64 大小 264字节)(32位为 IMAGE_NT_HEADERS32 大小 248字节)
  39.     IFEX #0,    //判断错误,应该直接判断PE文件头是32位还是64位。
  40.     {*
  41.     IFEX #%&bX64%=3,
  42.     {*
  43.         //SET$# &nt=*264 0
  44.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
  45.     }!  
  46.     {*
  47.         //SET$# &nt=*248 0
  48.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
  49.     }
  50.     }
  51.     ENVI &&IMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b      //32位
  52.     ENVI &&IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b      //64位
  53.     SET?short (%&pBase%+%&dos.e_lfanew%)=&&nt.OptionalHeader.Magic:24
  54.     //MESS. %&nt.OptionalHeader.Magic%@&nt.OptionalHeader.Magic
  55.     IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
  56.     {*
  57.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
  58.     }!  
  59.     {*
  60.         IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
  61.         {*
  62.             SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
  63.         }!  
  64.         {*
  65.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  66.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  67.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  68.             ENVI-ret %~2=0
  69.             EXIT _SUB
  70.         }
  71.     }
  72.     //GETF &nt,0#*,&&nt_Hex
  73.     //MESS. %&nt_Hex%@&nt_Hex
  74.     SET?long nt=&&nt.Signature:0
  75.     //MESS. %&nt.Signature%@&nt.Signature
  76.     ENVI &&IMAGE_NT_SIGNATURE=0x00004550  // PE00
  77.     IFEX #%&nt.Signature%<>%&IMAGE_NT_SIGNATURE%,
  78.     {*
  79.         CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  80.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  81.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  82.         ENVI-ret %~2=0
  83.         EXIT _SUB
  84.     }
  85.    
  86.     // 定位资源目录
  87.     // auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  88.     ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2   // Resource Directory
  89.     //ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0     // 测试
  90.     IFEX #0,
  91.     {*
  92.     IFEX #%&bX64%=3,
  93.     {*
  94.         SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  95.     }!  
  96.     {*
  97.         SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  98.     }
  99.     }
  100.     IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
  101.     {*
  102.         SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  103.     }!  
  104.     {*
  105.         IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
  106.         {*
  107.             SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  108.         }!  
  109.         {*
  110.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  111.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  112.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  113.             ENVI-ret %~2=0
  114.             EXIT _SUB
  115.         }
  116.     }
  117.     //GETF &resDir,0#*,&&resDir_Hex
  118.     //MESS. %&resDir_Hex%@&resDir_Hex
  119.     SET?long resDir=&&resDir.VirtualAddress:0
  120.     //MESS. %&resDir.VirtualAddress%@&resDir.VirtualAddress
  121.    
  122.     // 定位资源节(.rsrc)
  123.     ENVI &&i=0
  124.     SET?shorts nt=&&nt.FileHeader.NumberOfSections:(4+2)    //WORD 2 字节,用short和wchar都可以
  125.     //MESS. %&nt.FileHeader.NumberOfSections%@&nt.FileHeader.NumberOfSections
  126.     SET?shorts nt=&&nt.FileHeader.SizeOfOptionalHeader:(4+2+2+4+4+4)
  127.     //MESS. %&nt.FileHeader.SizeOfOptionalHeader%@&nt.FileHeader.SizeOfOptionalHeader
  128.     //SET-mkfixdummy &section=&nt
  129.    
  130.     LOOP #%&i%<%&nt.FileHeader.NumberOfSections%,
  131.     {*
  132.         //#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))
  133.         SET-mkfixdummy &section=(%&pBase%+%&dos.e_lfanew%+(4+20+%&nt.FileHeader.SizeOfOptionalHeader%))@(40*%&i%);*40        // 相当于 section++
  134.         //GETF &section,0#40,&&section_Hex
  135.         //MESS. %&section_Hex%@&section_Hex
  136.         SET?long section=&&section.VirtualAddress:12
  137.         //MESS. &section.VirtualAddress:%&section.VirtualAddress%@%&i%
  138.         SET?long section=&&section.Misc.VirtualSize:8
  139.         //MESS. IFEX #[ ( %&resDir.VirtualAddress% >= %&section.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %&section.VirtualAddress% + %&section.Misc.VirtualSize% ) ) ],@%&i%
  140.         //IFEX #[ ( %&resDir.VirtualAddress% >= %&section.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %&section.VirtualAddress% + %&section.Misc.VirtualSize% ) ) ],     // IFEX 存在BUG,不能这样嵌套使用,先算出来吧。
  141.         IFEX #%&resDir.VirtualAddress% >= %&section.VirtualAddress%,
  142.         {*
  143.             CALC &&Fix=%&section.VirtualAddress% + %&section.Misc.VirtualSize%
  144.             IFEX #%&resDir.VirtualAddress% < %&Fix%,
  145.             {*
  146.                 EXIT LOOP
  147.             }
  148.         }
  149.         CALC #&i=%&i% + 1
  150.     }
  151.     // 计算资源目录在文件中的实际偏移
  152.     SET?long section=&&section.PointerToRawData:20
  153.     CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%
  154.     //MESS. %&resOffset%<&i:%&i%><CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%>@&resOffset
  155.     SET-mkfixdummy &rootDir=(%&pBase%+%&resOffset%)@0;*16
  156.     SET?short rootDir=&&rootDir.NumberOfIdEntries:(4+4+2+2+2)
  157.     //MESS. %&rootDir.NumberOfIdEntries%@&rootDir.NumberOfIdEntries
  158.    
  159.     // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
  160.     //SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@16;*8
  161.     //GETF &typeEntry,0#8,&&typeEntry_Hex
  162.     //MESS. %&typeEntry_Hex%@&typeEntry_Hex
  163.    
  164.     ENVI &&i=0
  165.     LOOP #%&i%<%&rootDir.NumberOfIdEntries%,
  166.     {*
  167.         SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@(16+(8*%&i%));*8
  168.         SET?short typeEntry=&&typeEntry.Id:0
  169.         //MESS. %&typeEntry.Id%@%&i%
  170.         IFEX #%&typeEntry.Id%=14,       // RT_GROUP_ICON = 14
  171.         {*
  172.             // 获取第一个图标ID(进入ID目录的第一个条目)
  173.             SET?long typeEntry=&&typeEntry.OffsetToDirectory:4
  174.             CALC #&typeEntry.OffsetToDirectory=%&typeEntry.OffsetToDirectory% & 0x7FFFFFFF
  175.             SET-mkfixdummy &iconDir=(%&pBase%+%&resOffset%)@%&typeEntry.OffsetToDirectory%;*16
  176.             SET-mkfixdummy &iconIdEntry=(%&pBase%+%&resOffset%)@(%&typeEntry.OffsetToDirectory%+16);*8
  177.             SET?short iconIdEntry=&&iconIdEntry.Id:0
  178.             CALC &&firstIconId=%&iconIdEntry.Id%        // 不知道源码这里为什么用DWORD计算WORD
  179.             //MESS. %&firstIconId%@
  180.             
  181.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  182.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  183.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  184.             ENVI-ret~ %~2=&firstIconId
  185.             EXIT _SUB
  186.         }
  187.         CALC #&i=%&i% + 1
  188.     }
  189.     CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  190.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  191.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  192.     ENVI-ret %~2=0
  193. _END


  194. EXIT FILE

  195. typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
  196.     union {
  197.         struct {
  198.             DWORD NameOffset:31;
  199.             DWORD NameIsString:1;
  200.         } DUMMYSTRUCTNAME;
  201.         DWORD   Name;
  202.         WORD    Id;
  203.     } DUMMYUNIONNAME;
  204.     union {
  205.         DWORD   OffsetToData;
  206.         struct {
  207.             DWORD   OffsetToDirectory:31;
  208.             DWORD   DataIsDirectory:1;
  209.         } DUMMYSTRUCTNAME2;
  210.     } DUMMYUNIONNAME2;
  211. } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;     //8b

  212. typedef struct _IMAGE_RESOURCE_DIRECTORY {
  213.     DWORD   Characteristics;
  214.     DWORD   TimeDateStamp;
  215.     WORD    MajorVersion;
  216.     WORD    MinorVersion;
  217.     WORD    NumberOfNamedEntries;
  218.     WORD    NumberOfIdEntries;
  219. //  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
  220. } IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;     /16b

  221. typedef struct _IMAGE_SECTION_HEADER {
  222.     BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
  223.     union {
  224.             DWORD   PhysicalAddress;
  225.             DWORD   VirtualSize;
  226.     } Misc;
  227.     DWORD   VirtualAddress;
  228.     DWORD   SizeOfRawData;
  229.     DWORD   PointerToRawData;
  230.     DWORD   PointerToRelocations;
  231.     DWORD   PointerToLinenumbers;
  232.     WORD    NumberOfRelocations;
  233.     WORD    NumberOfLinenumbers;
  234.     DWORD   Characteristics;
  235. } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;     //40b

  236. typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
  237.     WORD   e_magic;                     // Magic number
  238.     WORD   e_cblp;                      // Bytes on last page of file
  239.     WORD   e_cp;                        // Pages in file
  240.     WORD   e_crlc;                      // Relocations
  241.     WORD   e_cparhdr;                   // Size of header in paragraphs
  242.     WORD   e_minalloc;                  // Minimum extra paragraphs needed
  243.     WORD   e_maxalloc;                  // Maximum extra paragraphs needed
  244.     WORD   e_ss;                        // Initial (relative) SS value
  245.     WORD   e_sp;                        // Initial SP value
  246.     WORD   e_csum;                      // Checksum
  247.     WORD   e_ip;                        // Initial IP value
  248.     WORD   e_cs;                        // Initial (relative) CS value
  249.     WORD   e_lfarlc;                    // File address of relocation table
  250.     WORD   e_ovno;                      // Overlay number
  251.     WORD   e_res[4];                    // Reserved words
  252.     WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
  253.     WORD   e_oeminfo;                   // OEM information; e_oemid specific
  254.     WORD   e_res2[10];                  // Reserved words
  255.     LONG   e_lfanew;                    // File address of new exe header
  256.   } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;       //64b

  257. typedef struct _IMAGE_FILE_HEADER {
  258.     WORD    Machine;
  259.     WORD    NumberOfSections;
  260.     DWORD   TimeDateStamp;
  261.     DWORD   PointerToSymbolTable;
  262.     DWORD   NumberOfSymbols;
  263.     WORD    SizeOfOptionalHeader;
  264.     WORD    Characteristics;
  265. } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;       //20b

  266. typedef struct _IMAGE_DATA_DIRECTORY {
  267.     DWORD   VirtualAddress;
  268.     DWORD   Size;
  269. } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;     //8b

  270. typedef struct _IMAGE_OPTIONAL_HEADER {
  271.     //
  272.     // Standard fields.
  273.     //

  274.     WORD    Magic;
  275.     BYTE    MajorLinkerVersion;
  276.     BYTE    MinorLinkerVersion;
  277.     DWORD   SizeOfCode;
  278.     DWORD   SizeOfInitializedData;
  279.     DWORD   SizeOfUninitializedData;
  280.     DWORD   AddressOfEntryPoint;
  281.     DWORD   BaseOfCode;
  282.     DWORD   BaseOfData;

  283.     //
  284.     // NT additional fields.
  285.     //

  286.     DWORD   ImageBase;
  287.     DWORD   SectionAlignment;
  288.     DWORD   FileAlignment;
  289.     WORD    MajorOperatingSystemVersion;
  290.     WORD    MinorOperatingSystemVersion;
  291.     WORD    MajorImageVersion;
  292.     WORD    MinorImageVersion;
  293.     WORD    MajorSubsystemVersion;
  294.     WORD    MinorSubsystemVersion;
  295.     DWORD   Win32VersionValue;
  296.     DWORD   SizeOfImage;
  297.     DWORD   SizeOfHeaders;
  298.     DWORD   CheckSum;
  299.     WORD    Subsystem;
  300.     WORD    DllCharacteristics;
  301.     DWORD   SizeOfStackReserve;
  302.     DWORD   SizeOfStackCommit;
  303.     DWORD   SizeOfHeapReserve;
  304.     DWORD   SizeOfHeapCommit;
  305.     DWORD   LoaderFlags;
  306.     DWORD   NumberOfRvaAndSizes;
  307.     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];       //偏移地址  96b
  308. } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

  309. typedef struct _IMAGE_OPTIONAL_HEADER64 {
  310.     WORD        Magic;
  311.     BYTE        MajorLinkerVersion;
  312.     BYTE        MinorLinkerVersion;
  313.     DWORD       SizeOfCode;
  314.     DWORD       SizeOfInitializedData;
  315.     DWORD       SizeOfUninitializedData;
  316.     DWORD       AddressOfEntryPoint;
  317.     DWORD       BaseOfCode;
  318.     ULONGLONG   ImageBase;
  319.     DWORD       SectionAlignment;
  320.     DWORD       FileAlignment;
  321.     WORD        MajorOperatingSystemVersion;
  322.     WORD        MinorOperatingSystemVersion;
  323.     WORD        MajorImageVersion;
  324.     WORD        MinorImageVersion;
  325.     WORD        MajorSubsystemVersion;
  326.     WORD        MinorSubsystemVersion;
  327.     DWORD       Win32VersionValue;
  328.     DWORD       SizeOfImage;
  329.     DWORD       SizeOfHeaders;
  330.     DWORD       CheckSum;
  331.     WORD        Subsystem;
  332.     WORD        DllCharacteristics;
  333.     ULONGLONG   SizeOfStackReserve;
  334.     ULONGLONG   SizeOfStackCommit;
  335.     ULONGLONG   SizeOfHeapReserve;
  336.     ULONGLONG   SizeOfHeapCommit;
  337.     DWORD       LoaderFlags;
  338.     DWORD       NumberOfRvaAndSizes;
  339.     IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];       //偏移地址  112b
  340. } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

  341. typedef struct _IMAGE_NT_HEADERS64 {
  342.     DWORD Signature;
  343.     IMAGE_FILE_HEADER FileHeader;
  344.     IMAGE_OPTIONAL_HEADER64 OptionalHeader;
  345. } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

  346. typedef struct _IMAGE_NT_HEADERS {
  347.     DWORD Signature;
  348.     IMAGE_FILE_HEADER FileHeader;
  349.     IMAGE_OPTIONAL_HEADER32 OptionalHeader;
  350. } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

  351. #include <windows.h>
  352. #include <stdio.h>

  353. DWORD GetFirstIconGroupID(LPCWSTR exePath) {
  354.     HANDLE hFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  355.     if (hFile == INVALID_HANDLE_VALUE) return 0;

  356.     DWORD fileSize = GetFileSize(hFile, NULL);
  357.     HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, fileSize, NULL);
  358.     LPVOID pBase = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  359.     if (!pBase) { CloseHandle(hMap); CloseHandle(hFile); return 0; }

  360.     PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pBase;
  361.     PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)pBase + dos->e_lfanew);
  362.     if (nt->Signature != IMAGE_NT_SIGNATURE) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }

  363.     // 定位资源目录
  364.     auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  365.     if (resDir.VirtualAddress == 0) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }

  366.     // 定位资源节(.rsrc)
  367.     PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt);
  368.     for (int i = 0; i < nt->FileHeader.NumberOfSections; i++, section++) {
  369.         if (resDir.VirtualAddress >= section->VirtualAddress &&
  370.             resDir.VirtualAddress < section->VirtualAddress + section->Misc.VirtualSize) break;
  371.     }

  372.     // 计算资源目录在文件中的实际偏移
  373.     DWORD resOffset = resDir.VirtualAddress - section->VirtualAddress + section->PointerToRawData;
  374.     PIMAGE_RESOURCE_DIRECTORY rootDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pBase + resOffset);

  375.     // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
  376.     PIMAGE_RESOURCE_DIRECTORY_ENTRY typeEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(rootDir + 1);
  377.     for (DWORD i = 0; i < rootDir->NumberOfIdEntries; i++, typeEntry++) {
  378.         if (typeEntry->Id == 14) { // RT_GROUP_ICON = 14
  379.             // 获取第一个图标ID(进入ID目录的第一个条目)
  380.             PIMAGE_RESOURCE_DIRECTORY iconDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)rootDir + typeEntry->OffsetToDirectory);
  381.             PIMAGE_RESOURCE_DIRECTORY_ENTRY iconIdEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(iconDir + 1);
  382.             DWORD firstIconId = iconIdEntry->Id;

  383.             UnmapViewOfFile(pBase);
  384.             CloseHandle(hMap);
  385.             CloseHandle(hFile);
  386.             return firstIconId;
  387.         }
  388.     }

  389.     UnmapViewOfFile(pBase);
  390.     CloseHandle(hMap);
  391.     CloseHandle(hFile);
  392.     return 0;
  393. }

  394. // 调用示例:获取 Photoshop.exe 的第一个图标ID
  395. int main() {
  396.     LPCWSTR exePath = L"D:\\软件\\Photoshop\\Photoshop.exe";
  397.     DWORD iconId = GetFirstIconGroupID(exePath);
  398.     printf("第一个图标ID: %u\n", iconId); // 输出:1000 或 1 等
  399.     return 0;
  400. }

复制代码


点评

Zap
换个程序就不行了  详情 回复 发表于 2025-11-6 11:00
Zap
搞不定  详情 回复 发表于 2025-11-6 09:45
Zap
是哦 以C:\Windows\explorer.exe为例 第一个是名称ICO_MYCOMPUTER 应该转换为字符  详情 回复 发表于 2025-11-6 00:40
回复

使用道具 举报

19497#
发表于 2025-11-6 00:40:11 | 只看该作者
红毛樱木 发表于 2025-11-5 23:36
更正后的代码。
C++源码你自己改吧....

是哦 以C:\Windows\explorer.exe为例 第一个是名称ICO_MYCOMPUTER 应该转换为字符
回复

使用道具 举报

19498#
发表于 2025-11-6 09:45:02 | 只看该作者
红毛樱木 发表于 2025-11-5 23:36
更正后的代码。
C++源码你自己改吧....

搞不定
  1. //LOGS * %&CurDir%\log.log
  2. ENVI^ ENVIMODE=1
  3. ENVI &exePath=C:\Windows\explorer.exe

  4. CALL GetFirstIconGroupID "%&exePath%" &iconId
  5. MESS. 第一个图标ID: %&iconId%@
  6. exit

  7. _SUB GetFirstIconGroupID
  8.     ENVI-ret %~2=0
  9.     ENVI &&exePath=%~1
  10.     ENVI &&GENERIC_READ=0x80000000
  11.     ENVI &&FILE_SHARE_READ=0x00000001
  12.     ENVI &&OPEN_EXISTING=3
  13.     ENVI &&INVALID_HANDLE_VALUE=-1
  14.     CALL$--qd --ret:&&hFile Kernel32.dll,CreateFileW,$%&exePath%,#%&GENERIC_READ%,#%&FILE_SHARE_READ%,#0,#%&OPEN_EXISTING%,#0,#0
  15.     IFEX #%&hFile%=%&INVALID_HANDLE_VALUE%,
  16.     {*
  17.         ENVI-ret %~2=0
  18.         EXIT _SUB
  19.     }
  20.     CALL$--qd --ret:&&fileSize Kernel32.dll,GetFileSize,#%&hFile%,#0
  21.     ENVI &&PAGE_READONLY=0x02
  22.     CALL$--qd --ret:&&hMap Kernel32.dll,CreateFileMappingW,#%&hFile%,#0,#%&PAGE_READONLY%,#0,#%&fileSize%,0
  23.     ENVI &&FILE_MAP_READ=0x0004
  24.     CALL$--qd --16 --ret:&&pBase Kernel32.dll,MapViewOfFile,#%&hMap%,#%&FILE_MAP_READ%,#0,#0,#0
  25.     IFEX #%&pBase%=0,
  26.     {*
  27.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  28.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  29.         ENVI-ret %~2=0
  30.         EXIT _SUB
  31.     }
  32.    
  33.     SET-mkfixdummy &dos=%&pBase%@0;*64
  34.     SET?longs dos=&&dos.e_lfanew:60
  35.    
  36.     ENVI &&IMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b
  37.     ENVI &&IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b
  38.     SET?short (%&pBase%+%&dos.e_lfanew%)=&&nt.OptionalHeader.Magic:24
  39.    
  40.     IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
  41.     {*
  42.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
  43.     }!
  44.     {*
  45.         IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
  46.         {*
  47.             SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
  48.         }!
  49.         {*
  50.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  51.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  52.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  53.             ENVI-ret %~2=0
  54.             EXIT _SUB
  55.         }
  56.     }
  57.    
  58.     SET?long nt=&&nt.Signature:0
  59.     ENVI &&IMAGE_NT_SIGNATURE=0x00004550
  60.     IFEX #%&nt.Signature%<>%&IMAGE_NT_SIGNATURE%,
  61.     {*
  62.         CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  63.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  64.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  65.         ENVI-ret %~2=0
  66.         EXIT _SUB
  67.     }

  68.     ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2
  69.     IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
  70.     {*
  71.         SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  72.     }!
  73.     {*
  74.         SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  75.     }
  76.    
  77.     SET?long resDir=&&resDir.VirtualAddress:0
  78.    
  79.     ENVI &&i=0
  80.     SET?shorts nt=&&nt.FileHeader.NumberOfSections:(4+2)
  81.     SET?shorts nt=&&nt.FileHeader.SizeOfOptionalHeader:(4+2+2+4+4+4)
  82.    
  83.     LOOP #%&i%<%&nt.FileHeader.NumberOfSections%,
  84.     {*
  85.         SET-mkfixdummy &section=(%&pBase%+%&dos.e_lfanew%+(4+20+%&nt.FileHeader.SizeOfOptionalHeader%))@(40*%&i%);*40
  86.         SET?long section=&&section.VirtualAddress:12
  87.         SET?long section=&&section.Misc.VirtualSize:8
  88.         IFEX #%&resDir.VirtualAddress% >= %&section.VirtualAddress%,
  89.         {*
  90.             CALC &&Fix=%&section.VirtualAddress% + %&section.Misc.VirtualSize%
  91.             IFEX #%&resDir.VirtualAddress% < %&Fix%,
  92.             {*
  93.                 EXIT LOOP
  94.             }
  95.         }
  96.         CALC #&i=%&i% + 1
  97.     }
  98.    
  99.     SET?long section=&&section.PointerToRawData:20
  100.     CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%
  101.     SET-mkfixdummy &rootDir=(%&pBase%+%&resOffset%)@0;*16
  102.     SET?short rootDir=&&rootDir.NumberOfIdEntries:(4+4+2+2+2)
  103.    
  104.     ENVI &&i=0
  105.     LOOP #%&i%<%&rootDir.NumberOfIdEntries%,
  106.     {*
  107.         SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@(16+(8*%&i%));*8
  108.         SET?short typeEntry=&&typeEntry.Id:0
  109.         
  110.         IFEX #%&typeEntry.Id%=14,  // RT_GROUP_ICON
  111.         {*
  112.             SET?long typeEntry=&&typeEntry.OffsetToDirectory:4
  113.             CALC #&typeEntry.OffsetToDirectory=%&typeEntry.OffsetToDirectory% & 0x7FFFFFFF
  114.             SET-mkfixdummy &iconDir=(%&pBase%+%&resOffset%)@%&typeEntry.OffsetToDirectory%;*16
  115.             
  116.             // 获取第一个条目(可能是命名或ID条目)
  117.             SET-mkfixdummy &iconIdEntry=(%&pBase%+%&resOffset%+%&typeEntry.OffsetToDirectory%+16)@0;*8
  118.             SET?short iconIdEntry=&&iconIdEntry.Id:0
  119.             
  120.             // 判断条目类型 (高位为1表示命名条目)
  121.             IFEX #%&iconIdEntry.Id% >= 0x8000,
  122.             {*
  123.                 // 命名条目处理
  124.                 CALC #&&nameOffset=%&iconIdEntry.Id% & 0x7FFF
  125.                 SET-mkfixdummy &nameHeader=(%&pBase%+%&resOffset%+%&nameOffset%)@0;*2
  126.                 SET?short nameHeader=&&nameHeader.Length:0
  127.                
  128.                 // 读取Unicode字符串
  129.                 SET $ &buffer=0
  130.                 CALC #&strAddr=%&pBase% + %&resOffset% + %&nameOffset% + 2
  131.                 CALL $--ret:&buffer --wid %&strAddr%, %&nameHeader.Length%
  132.                
  133.                 ENVI-ret~ %~2=%&buffer%
  134.             }!
  135.             {*
  136.                 // ID条目处理
  137.                 ENVI-ret~ %~2=%&iconIdEntry.Id%
  138.             }
  139.             
  140.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  141.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  142.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  143.             EXIT _SUB
  144.         }
  145.         CALC #&i=%&i% + 1
  146.     }
  147.     CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  148.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  149.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  150.     ENVI-ret %~2=0
  151. _END
复制代码
回复

使用道具 举报

19499#
发表于 2025-11-6 10:53:54 | 只看该作者
又不行了
  1. //LOGS * %&CurDir%\log.log
  2. ENVI^ ENVIMODE=1

  3. ENVI &exePath=D:\软件\BCompare\BCompare.exe   //C:\Windows\explorer.exe //C:\Windows\System32\calc.exe
  4. CALL GetFirstIconGroupID "%&exePath%" &iconId
  5. MESS. 第一个图标ID:%&iconId%@
  6. exit

  7. _SUB GetFirstIconGroupID
  8.     ENVI-ret %~2=0
  9.     ENVI &&exePath=%~1
  10.     ENVI &&GENERIC_READ=0x80000000
  11.     ENVI &&FILE_SHARE_READ=0x00000001
  12.     ENVI &&OPEN_EXISTING=3
  13.     ENVI &&INVALID_HANDLE_VALUE=-1
  14.     CALL$--qd --ret:&&hFile Kernel32.dll,CreateFileW,$%&exePath%,#%&GENERIC_READ%,#%&FILE_SHARE_READ%,#0,#%&OPEN_EXISTING%,#0,#0       // C中的NULL就是0,在PECMD中用数值 #0
  15.     IFEX #%&hFile%=%&INVALID_HANDLE_VALUE%,
  16.     {*
  17.         ENVI-ret %~2=0
  18.         EXIT _SUB
  19.     }
  20.     CALL$--qd --ret:&&fileSize Kernel32.dll,GetFileSize,#%&hFile%,#0
  21.     ENVI &&PAGE_READONLY=0x02
  22.     CALL$--qd --ret:&&hMap Kernel32.dll,CreateFileMappingW,#%&hFile%,#0,#%&PAGE_READONLY%,#0,#%&fileSize%,0     //CreateFileMapping 要用实际的 CreateFileMappingW
  23.     ENVI &&FILE_MAP_READ=0x0004
  24.     CALL$--qd --16 --ret:&&pBase Kernel32.dll,MapViewOfFile,#%&hMap%,#%&FILE_MAP_READ%,#0,#0,#0
  25.     IFEX #%&pBase%=0,
  26.     {*
  27.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  28.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  29.         ENVI-ret %~2=0
  30.         EXIT _SUB
  31.     }
  32.     // PIMAGE_DOS_HEADER 的结构体 IMAGE_DOS_HEADER  64字节
  33.     //SET$# &dos=*64 0
  34.     SET-mkfixdummy &dos=%&pBase%@0;*64
  35.     SET?longs dos=&&dos.e_lfanew:60
  36.     //MESS. %&dos.e_lfanew%@&dos.e_lfanew
  37.     // PIMAGE_NT_HEADERS 的结构体(64位为 IMAGE_NT_HEADERS64 大小 264字节)(32位为 IMAGE_NT_HEADERS32 大小 248字节)
  38.     IFEX #0,    //判断错误,应该直接判断PE文件头是32位还是64位。
  39.     {*
  40.     IFEX #%&bX64%=3,
  41.     {*
  42.         //SET$# &nt=*264 0
  43.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
  44.     }!
  45.     {*
  46.         //SET$# &nt=*248 0
  47.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
  48.     }
  49.     }
  50.     ENVI &&IMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b      //32位
  51.     ENVI &&IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b      //64位
  52.     SET?short (%&pBase%+%&dos.e_lfanew%)=&&nt.OptionalHeader.Magic:24
  53.     //MESS. %&nt.OptionalHeader.Magic%@&nt.OptionalHeader.Magic
  54.     IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
  55.     {*
  56.         SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
  57.     }!
  58.     {*
  59.         IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
  60.         {*
  61.             SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
  62.         }!
  63.         {*
  64.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  65.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  66.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  67.             ENVI-ret %~2=0
  68.             EXIT _SUB
  69.         }
  70.     }
  71.     //GETF &nt,0#*,&&nt_Hex
  72.     //MESS. %&nt_Hex%@&nt_Hex
  73.     SET?long nt=&&nt.Signature:0
  74.     //MESS. %&nt.Signature%@&nt.Signature
  75.     ENVI &&IMAGE_NT_SIGNATURE=0x00004550  // PE00
  76.     IFEX #%&nt.Signature%<>%&IMAGE_NT_SIGNATURE%,
  77.     {*
  78.         CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  79.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  80.         CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  81.         ENVI-ret %~2=0
  82.         EXIT _SUB
  83.     }

  84.     // 定位资源目录
  85.     // auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
  86.     ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2   // Resource Directory
  87.     //ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0     // 测试
  88.     IFEX #0,
  89.     {*
  90.     IFEX #%&bX64%=3,
  91.     {*
  92.         SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  93.     }!
  94.     {*
  95.         SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  96.     }
  97.     }
  98.     IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
  99.     {*
  100.         SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  101.     }!
  102.     {*
  103.         IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
  104.         {*
  105.             SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
  106.         }!
  107.         {*
  108.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  109.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  110.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  111.             ENVI-ret %~2=0
  112.             EXIT _SUB
  113.         }
  114.    
  115.     //GETF &resDir,0#*,&&resDir_Hex
  116.     //MESS. %&resDir_Hex%@&resDir_Hex
  117.     SET?long resDir=&&resDir.VirtualAddress:0
  118.     //MESS. %&resDir.VirtualAddress%@&resDir.VirtualAddress

  119.     // 定位资源节(.rsrc)
  120.     ENVI &&i=0
  121.     SET?shorts nt=&&nt.FileHeader.NumberOfSections:(4+2)    //WORD 2 字节,用short和wchar都可以
  122.     //MESS. %&nt.FileHeader.NumberOfSections%@&nt.FileHeader.NumberOfSections
  123.     SET?shorts nt=&&nt.FileHeader.SizeOfOptionalHeader:(4+2+2+4+4+4)
  124.     //MESS. %&nt.FileHeader.SizeOfOptionalHeader%@&nt.FileHeader.SizeOfOptionalHeader
  125.     //SET-mkfixdummy &section=&nt

  126.     LOOP #%&i%<%&nt.FileHeader.NumberOfSections%,
  127.     {*
  128.         //#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))
  129.         SET-mkfixdummy &section=(%&pBase%+%&dos.e_lfanew%+(4+20+%&nt.FileHeader.SizeOfOptionalHeader%))@(40*%&i%);*40        // 相当于 section++
  130.         //GETF &section,0#40,&&section_Hex
  131.         //MESS. %&section_Hex%@&section_Hex
  132.         SET?long section=&&section.VirtualAddress:12
  133.         //MESS. &section.VirtualAddress:%&section.VirtualAddress%@%&i%
  134.         SET?long section=&&section.Misc.VirtualSize:8
  135.         //MESS. IFEX #[ ( %&resDir.VirtualAddress% >= %&section.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %&section.VirtualAddress% + %&section.Misc.VirtualSize% ) ) ],@%&i%
  136.         //IFEX #[ ( %&resDir.VirtualAddress% >= %&section.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %&section.VirtualAddress% + %&section.Misc.VirtualSize% ) ) ],     // IFEX 存在BUG,不能这样嵌套使用,先算出来吧。
  137.         IFEX #%&resDir.VirtualAddress% >= %&section.VirtualAddress%,
  138.         {*
  139.             CALC &&Fix=%&section.VirtualAddress% + %&section.Misc.VirtualSize%
  140.             IFEX #%&resDir.VirtualAddress% < %&Fix%,
  141.             {*
  142.                 EXIT LOOP
  143.             }
  144.         }
  145.         CALC #&i=%&i% + 1
  146.     }
  147.     // 计算资源目录在文件中的实际偏移
  148.     SET?long section=&&section.PointerToRawData:20
  149.     CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%
  150.     //MESS. %&resOffset%<&i:%&i%><CALC #&&resOffset=%&resDir.VirtualAddress% - %&section.VirtualAddress% + %&section.PointerToRawData%>@&resOffset
  151.     SET-mkfixdummy &rootDir=(%&pBase%+%&resOffset%)@0;*16
  152.     SET?short rootDir=&&rootDir.NumberOfIdEntries:(4+4+2+2+2)
  153.     //MESS. %&rootDir.NumberOfIdEntries%@&rootDir.NumberOfIdEntries

  154.     // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
  155.     //SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@16;*8
  156.     //GETF &typeEntry,0#8,&&typeEntry_Hex
  157.     //MESS. %&typeEntry_Hex%@&typeEntry_Hex

  158.     ENVI &&i=0
  159.     LOOP #%&i%<%&rootDir.NumberOfIdEntries%,
  160.     {*
  161.         SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@(16+(8*%&i%));*8
  162.         SET?short typeEntry=&&typeEntry.Id:0
  163.         //MESS. %&typeEntry.Id%@%&i%
  164.         IFEX #%&typeEntry.Id%=14,       // RT_GROUP_ICON = 14
  165.         {*
  166.             // 获取第一个图标ID(进入ID目录的第一个条目)
  167.             SET?long typeEntry=&&typeEntry.OffsetToDirectory:4
  168.             CALC #&typeEntry.OffsetToDirectory=%&typeEntry.OffsetToDirectory% & 0x7FFFFFFF
  169.             SET-mkfixdummy &iconDir=(%&pBase%+%&resOffset%)@%&typeEntry.OffsetToDirectory%;*16
  170.             SET-mkfixdummy &iconIdEntry=(%&pBase%+%&resOffset%)@(%&typeEntry.OffsetToDirectory%+16);*8
  171.             SET?short iconIdEntry=&&iconIdEntry.Id:0

  172.             // 判断条目类型 (高位为1表示命名条目)
  173.             IFEX #%&iconIdEntry.Id% >= 0x0,
  174.             {*
  175.                 // 命名条目处理
  176.                 CALC #&&nameOffset=%&iconIdEntry.Id% & 0x7FFF
  177.                 SET-mkfixdummy &nameHeader=(%&pBase%+%&resOffset%+%&nameOffset%)@0;*2
  178.                 SET?short nameHeader=&&nameHeader.Length:0

  179.                 // 读取Unicode字符串
  180.                 CALC #&strAddr=%&resOffset% + %&nameOffset% + 2
  181.                 GETF "%&exePath%",%&strAddr%#(%&nameHeader.Length%+14),&buffer
  182.                           
  183.                 SET#% a=%&buffer%
  184.                 CODE *,%a%,**-UNICODE,UNI
  185.                
  186.                 mess %&pBase% + %&resOffset% + %&nameOffset% + 2\n%&strAddr% %&nameHeader.Length%\n%UNI%
  187.                 ENVI-ret~ %~2=UNI
  188.             }!
  189.             {*
  190.                 // ID条目处理
  191.                 ENVI-ret~ %~2=%&iconIdEntry.Id%
  192.             }

  193.             CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  194.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  195.             CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  196.             EXIT _SUB
  197.         }
  198.         CALC #&i=%&i% + 1
  199.     }
  200.     CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
  201.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
  202.     CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
  203.     ENVI-ret %~2=0
  204. _END
复制代码
回复

使用道具 举报

19500#
发表于 2025-11-6 11:00:52 | 只看该作者
红毛樱木 发表于 2025-11-5 23:36
更正后的代码。
C++源码你自己改吧....

换个程序就不行了
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-11-29 20:15

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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