|
|
本帖最后由 红毛樱木 于 2025-11-5 23:46 编辑
更正后的代码。
C++源码你自己改吧....
- //LOGS * %&CurDir%\log.log
- ENVI^ ENVIMODE=1
- // PECMD2012 内部本身就是宽字符Unicode。路径\\可以直接写真实路径\,自动转义。
- ENVI &exePath=D:\软件\Photoshop\Photoshop.exe
- CALL GetFirstIconGroupID "%&exePath%" &iconId
- MESS. 第一个图标ID: %&iconId%@
- _SUB GetFirstIconGroupID
- ENVI-ret %~2=0
- ENVI &&exePath=%~1
- ENVI &&GENERIC_READ=0x80000000
- ENVI &&FILE_SHARE_READ=0x00000001
- ENVI &&OPEN_EXISTING=3
- ENVI &&INVALID_HANDLE_VALUE=-1
- CALL$--qd --ret:&&hFile Kernel32.dll,CreateFileW,$%&exePath%,#%&GENERIC_READ%,#%&FILE_SHARE_READ%,#0,#%&OPEN_EXISTING%,#0,#0 // C中的NULL就是0,在PECMD中用数值 #0
- IFEX #%&hFile%=%&INVALID_HANDLE_VALUE%,
- {*
- ENVI-ret %~2=0
- EXIT _SUB
- }
- CALL$--qd --ret:&&fileSize Kernel32.dll,GetFileSize,#%&hFile%,#0
- ENVI &&PAGE_READONLY=0x02
- CALL$--qd --ret:&&hMap Kernel32.dll,CreateFileMappingW,#%&hFile%,#0,#%&PAGE_READONLY%,#0,#%&fileSize%,0 //CreateFileMapping 要用实际的 CreateFileMappingW
- ENVI &&FILE_MAP_READ=0x0004
- CALL$--qd --16 --ret:&&pBase Kernel32.dll,MapViewOfFile,#%&hMap%,#%&FILE_MAP_READ%,#0,#0,#0
- //MESS. %&pBase%@&pBase
- IFEX #%&pBase%=0,
- {*
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
- ENVI-ret %~2=0
- EXIT _SUB
- }
- // PIMAGE_DOS_HEADER 的结构体 IMAGE_DOS_HEADER 64字节
- //SET$# &dos=*64 0
- SET-mkfixdummy &dos=%&pBase%@0;*64
- SET?longs dos=&&dos.e_lfanew:60
- //MESS. %&dos.e_lfanew%@&dos.e_lfanew
- // PIMAGE_NT_HEADERS 的结构体(64位为 IMAGE_NT_HEADERS64 大小 264字节)(32位为 IMAGE_NT_HEADERS32 大小 248字节)
- IFEX #0, //判断错误,应该直接判断PE文件头是32位还是64位。
- {*
- IFEX #%&bX64%=3,
- {*
- //SET$# &nt=*264 0
- SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
- }!
- {*
- //SET$# &nt=*248 0
- SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
- }
- }
- ENVI &&IMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b //32位
- ENVI &&IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b //64位
- SET?short (%&pBase%+%&dos.e_lfanew%)=&&nt.OptionalHeader.Magic:24
- //MESS. %&nt.OptionalHeader.Magic%@&nt.OptionalHeader.Magic
- IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
- {*
- SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*248
- }!
- {*
- IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
- {*
- SET-mkfixdummy &nt=(%&pBase%+%&dos.e_lfanew%)@0;*264
- }!
- {*
- CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
- ENVI-ret %~2=0
- EXIT _SUB
- }
- }
- //GETF &nt,0#*,&&nt_Hex
- //MESS. %&nt_Hex%@&nt_Hex
- SET?long nt=&&nt.Signature:0
- //MESS. %&nt.Signature%@&nt.Signature
- ENVI &&IMAGE_NT_SIGNATURE=0x00004550 // PE00
- IFEX #%&nt.Signature%<>%&IMAGE_NT_SIGNATURE%,
- {*
- CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
- ENVI-ret %~2=0
- EXIT _SUB
- }
-
- // 定位资源目录
- // auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
- ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=2 // Resource Directory
- //ENVI &&IMAGE_DIRECTORY_ENTRY_RESOURCE=0 // 测试
- IFEX #0,
- {*
- IFEX #%&bX64%=3,
- {*
- SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
- }!
- {*
- SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
- }
- }
- IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR32_MAGIC%,
- {*
- SET-mkfixdummy &resDir=&nt@(4+20+96+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
- }!
- {*
- IFEX #%&nt.OptionalHeader.Magic%=%&IMAGE_NT_OPTIONAL_HDR64_MAGIC%,
- {*
- SET-mkfixdummy &resDir=&nt@(4+20+112+(8*%&IMAGE_DIRECTORY_ENTRY_RESOURCE%));*8
- }!
- {*
- CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
- ENVI-ret %~2=0
- EXIT _SUB
- }
- }
- //GETF &resDir,0#*,&&resDir_Hex
- //MESS. %&resDir_Hex%@&resDir_Hex
- SET?long resDir=&&resDir.VirtualAddress:0
- //MESS. %&resDir.VirtualAddress%@&resDir.VirtualAddress
-
- // 定位资源节(.rsrc)
- ENVI &&i=0
- SET?shorts nt=&&nt.FileHeader.NumberOfSections:(4+2) //WORD 2 字节,用short和wchar都可以
- //MESS. %&nt.FileHeader.NumberOfSections%@&nt.FileHeader.NumberOfSections
- SET?shorts nt=&&nt.FileHeader.SizeOfOptionalHeader:(4+2+2+4+4+4)
- //MESS. %&nt.FileHeader.SizeOfOptionalHeader%@&nt.FileHeader.SizeOfOptionalHeader
- //SET-mkfixdummy §ion=&nt
-
- LOOP #%&i%<%&nt.FileHeader.NumberOfSections%,
- {*
- //#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))
- SET-mkfixdummy §ion=(%&pBase%+%&dos.e_lfanew%+(4+20+%&nt.FileHeader.SizeOfOptionalHeader%))@(40*%&i%);*40 // 相当于 section++
- //GETF §ion,0#40,&§ion_Hex
- //MESS. %§ion_Hex%@§ion_Hex
- SET?long section=&§ion.VirtualAddress:12
- //MESS. §ion.VirtualAddress:%§ion.VirtualAddress%@%&i%
- SET?long section=&§ion.Misc.VirtualSize:8
- //MESS. IFEX #[ ( %&resDir.VirtualAddress% >= %§ion.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %§ion.VirtualAddress% + %§ion.Misc.VirtualSize% ) ) ],@%&i%
- //IFEX #[ ( %&resDir.VirtualAddress% >= %§ion.VirtualAddress% ) & ( %&resDir.VirtualAddress% < ( %§ion.VirtualAddress% + %§ion.Misc.VirtualSize% ) ) ], // IFEX 存在BUG,不能这样嵌套使用,先算出来吧。
- IFEX #%&resDir.VirtualAddress% >= %§ion.VirtualAddress%,
- {*
- CALC &&Fix=%§ion.VirtualAddress% + %§ion.Misc.VirtualSize%
- IFEX #%&resDir.VirtualAddress% < %&Fix%,
- {*
- EXIT LOOP
- }
- }
- CALC #&i=%&i% + 1
- }
- // 计算资源目录在文件中的实际偏移
- SET?long section=&§ion.PointerToRawData:20
- CALC #&&resOffset=%&resDir.VirtualAddress% - %§ion.VirtualAddress% + %§ion.PointerToRawData%
- //MESS. %&resOffset%<&i:%&i%><CALC #&&resOffset=%&resDir.VirtualAddress% - %§ion.VirtualAddress% + %§ion.PointerToRawData%>@&resOffset
- SET-mkfixdummy &rootDir=(%&pBase%+%&resOffset%)@0;*16
- SET?short rootDir=&&rootDir.NumberOfIdEntries:(4+4+2+2+2)
- //MESS. %&rootDir.NumberOfIdEntries%@&rootDir.NumberOfIdEntries
-
- // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
- //SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@16;*8
- //GETF &typeEntry,0#8,&&typeEntry_Hex
- //MESS. %&typeEntry_Hex%@&typeEntry_Hex
-
- ENVI &&i=0
- LOOP #%&i%<%&rootDir.NumberOfIdEntries%,
- {*
- SET-mkfixdummy &typeEntry=(%&pBase%+%&resOffset%)@(16+(8*%&i%));*8
- SET?short typeEntry=&&typeEntry.Id:0
- //MESS. %&typeEntry.Id%@%&i%
- IFEX #%&typeEntry.Id%=14, // RT_GROUP_ICON = 14
- {*
- // 获取第一个图标ID(进入ID目录的第一个条目)
- SET?long typeEntry=&&typeEntry.OffsetToDirectory:4
- CALC #&typeEntry.OffsetToDirectory=%&typeEntry.OffsetToDirectory% & 0x7FFFFFFF
- SET-mkfixdummy &iconDir=(%&pBase%+%&resOffset%)@%&typeEntry.OffsetToDirectory%;*16
- SET-mkfixdummy &iconIdEntry=(%&pBase%+%&resOffset%)@(%&typeEntry.OffsetToDirectory%+16);*8
- SET?short iconIdEntry=&&iconIdEntry.Id:0
- CALC &&firstIconId=%&iconIdEntry.Id% // 不知道源码这里为什么用DWORD计算WORD
- //MESS. %&firstIconId%@
-
- CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
- ENVI-ret~ %~2=&firstIconId
- EXIT _SUB
- }
- CALC #&i=%&i% + 1
- }
- CALL$--qd --bool --ret:&&UnmapViewOfFileRet Kernel32.dll,UnmapViewOfFile,#%&pBase%;
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hMap%
- CALL$--qd --bool --ret:&&CloseHandleRet Kernel32.dll,CloseHandle,#%&hFile%
- ENVI-ret %~2=0
- _END
- EXIT FILE
- typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
- union {
- struct {
- DWORD NameOffset:31;
- DWORD NameIsString:1;
- } DUMMYSTRUCTNAME;
- DWORD Name;
- WORD Id;
- } DUMMYUNIONNAME;
- union {
- DWORD OffsetToData;
- struct {
- DWORD OffsetToDirectory:31;
- DWORD DataIsDirectory:1;
- } DUMMYSTRUCTNAME2;
- } DUMMYUNIONNAME2;
- } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; //8b
- typedef struct _IMAGE_RESOURCE_DIRECTORY {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- WORD NumberOfNamedEntries;
- WORD NumberOfIdEntries;
- // IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
- } IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; /16b
- typedef struct _IMAGE_SECTION_HEADER {
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- DWORD PhysicalAddress;
- DWORD VirtualSize;
- } Misc;
- DWORD VirtualAddress;
- DWORD SizeOfRawData;
- DWORD PointerToRawData;
- DWORD PointerToRelocations;
- DWORD PointerToLinenumbers;
- WORD NumberOfRelocations;
- WORD NumberOfLinenumbers;
- DWORD Characteristics;
- } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; //40b
- typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
- WORD e_magic; // Magic number
- WORD e_cblp; // Bytes on last page of file
- WORD e_cp; // Pages in file
- WORD e_crlc; // Relocations
- WORD e_cparhdr; // Size of header in paragraphs
- WORD e_minalloc; // Minimum extra paragraphs needed
- WORD e_maxalloc; // Maximum extra paragraphs needed
- WORD e_ss; // Initial (relative) SS value
- WORD e_sp; // Initial SP value
- WORD e_csum; // Checksum
- WORD e_ip; // Initial IP value
- WORD e_cs; // Initial (relative) CS value
- WORD e_lfarlc; // File address of relocation table
- WORD e_ovno; // Overlay number
- WORD e_res[4]; // Reserved words
- WORD e_oemid; // OEM identifier (for e_oeminfo)
- WORD e_oeminfo; // OEM information; e_oemid specific
- WORD e_res2[10]; // Reserved words
- LONG e_lfanew; // File address of new exe header
- } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; //64b
- typedef struct _IMAGE_FILE_HEADER {
- WORD Machine;
- WORD NumberOfSections;
- DWORD TimeDateStamp;
- DWORD PointerToSymbolTable;
- DWORD NumberOfSymbols;
- WORD SizeOfOptionalHeader;
- WORD Characteristics;
- } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; //20b
- typedef struct _IMAGE_DATA_DIRECTORY {
- DWORD VirtualAddress;
- DWORD Size;
- } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; //8b
- typedef struct _IMAGE_OPTIONAL_HEADER {
- //
- // Standard fields.
- //
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- DWORD BaseOfData;
- //
- // NT additional fields.
- //
- DWORD ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- DWORD SizeOfStackReserve;
- DWORD SizeOfStackCommit;
- DWORD SizeOfHeapReserve;
- DWORD SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //偏移地址 96b
- } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
- typedef struct _IMAGE_OPTIONAL_HEADER64 {
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
- ULONGLONG ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- ULONGLONG SizeOfStackReserve;
- ULONGLONG SizeOfStackCommit;
- ULONGLONG SizeOfHeapReserve;
- ULONGLONG SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; //偏移地址 112b
- } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;
- typedef struct _IMAGE_NT_HEADERS64 {
- DWORD Signature;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_OPTIONAL_HEADER64 OptionalHeader;
- } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;
- typedef struct _IMAGE_NT_HEADERS {
- DWORD Signature;
- IMAGE_FILE_HEADER FileHeader;
- IMAGE_OPTIONAL_HEADER32 OptionalHeader;
- } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
- #include <windows.h>
- #include <stdio.h>
- DWORD GetFirstIconGroupID(LPCWSTR exePath) {
- HANDLE hFile = CreateFileW(exePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if (hFile == INVALID_HANDLE_VALUE) return 0;
- DWORD fileSize = GetFileSize(hFile, NULL);
- HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, fileSize, NULL);
- LPVOID pBase = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
- if (!pBase) { CloseHandle(hMap); CloseHandle(hFile); return 0; }
- PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pBase;
- PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((BYTE*)pBase + dos->e_lfanew);
- if (nt->Signature != IMAGE_NT_SIGNATURE) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }
- // 定位资源目录
- auto& resDir = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
- if (resDir.VirtualAddress == 0) { UnmapViewOfFile(pBase); CloseHandle(hMap); CloseHandle(hFile); return 0; }
- // 定位资源节(.rsrc)
- PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(nt);
- for (int i = 0; i < nt->FileHeader.NumberOfSections; i++, section++) {
- if (resDir.VirtualAddress >= section->VirtualAddress &&
- resDir.VirtualAddress < section->VirtualAddress + section->Misc.VirtualSize) break;
- }
- // 计算资源目录在文件中的实际偏移
- DWORD resOffset = resDir.VirtualAddress - section->VirtualAddress + section->PointerToRawData;
- PIMAGE_RESOURCE_DIRECTORY rootDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)pBase + resOffset);
- // 遍历资源类型,找到 RT_GROUP_ICON(ID=14)
- PIMAGE_RESOURCE_DIRECTORY_ENTRY typeEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(rootDir + 1);
- for (DWORD i = 0; i < rootDir->NumberOfIdEntries; i++, typeEntry++) {
- if (typeEntry->Id == 14) { // RT_GROUP_ICON = 14
- // 获取第一个图标ID(进入ID目录的第一个条目)
- PIMAGE_RESOURCE_DIRECTORY iconDir = (PIMAGE_RESOURCE_DIRECTORY)((BYTE*)rootDir + typeEntry->OffsetToDirectory);
- PIMAGE_RESOURCE_DIRECTORY_ENTRY iconIdEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(iconDir + 1);
- DWORD firstIconId = iconIdEntry->Id;
- UnmapViewOfFile(pBase);
- CloseHandle(hMap);
- CloseHandle(hFile);
- return firstIconId;
- }
- }
- UnmapViewOfFile(pBase);
- CloseHandle(hMap);
- CloseHandle(hFile);
- return 0;
- }
- // 调用示例:获取 Photoshop.exe 的第一个图标ID
- int main() {
- LPCWSTR exePath = L"D:\\软件\\Photoshop\\Photoshop.exe";
- DWORD iconId = GetFirstIconGroupID(exePath);
- printf("第一个图标ID: %u\n", iconId); // 输出:1000 或 1 等
- return 0;
- }
复制代码
|
|