import os import ctypes from ctypes import wintypes import win32gui from PIL import Image
def hbitmap_to_pillow(hbitmap): """ 将 HBITMAP 转换为 Pillow Image(兼容新版 pywin32) """ hbitmap = int(hbitmap)
class BITMAP(ctypes.Structure): _fields_ = [ ("bmType", wintypes.LONG), ("bmWidth", wintypes.LONG), ("bmHeight", wintypes.LONG), ("bmWidthBytes", wintypes.LONG), ("bmPlanes", wintypes.WORD), ("bmBitsPixel", wintypes.WORD), ("bmBits", ctypes.c_void_p), ]
bmp = BITMAP() ctypes.windll.gdi32.GetObjectW(hbitmap, ctypes.sizeof(bmp), ctypes.byref(bmp))
width, height = bmp.bmWidth, bmp.bmHeight if width == 0 or height == 0: raise ValueError("位图尺寸无效")
total_bytes = width * height * 4 buffer = ctypes.create_string_buffer(total_bytes) res = ctypes.windll.gdi32.GetBitmapBits(hbitmap, total_bytes, buffer) if res == 0: raise ctypes.WinError()
img = Image.frombuffer("RGBA", (width, height), buffer, "raw", "BGRA", 0, 1) return img
def save_icon(hicon, filename): """ 将 HICON 保存为 .ico 文件 """ try: icon_info = win32gui.GetIconInfo(hicon) hbmColor = icon_info[4]
if not hbmColor: raise ValueError("未获取到有效的 HBITMAP 颜色句柄")
img = hbitmap_to_pillow(hbmColor) img.save(filename, format="ICO")
except Exception as e: print(f"[!] 保存图标失败: {filename} - {e}")
def extract_icons(dll_path, output_dir): """ 从 DLL 或 EXE 文件中提取所有图标 """ if not os.path.exists(output_dir): os.makedirs(output_dir)
total_icons = win32gui.ExtractIconEx(dll_path, -1) print(f"[+] 检测到 {total_icons} 个图标")
for i in range(total_icons): large, small = win32gui.ExtractIconEx(dll_path, i) if large: filename = os.path.join(output_dir, f"icon_{i}.ico") save_icon(large[0], filename) win32gui.DestroyIcon(large[0]) print(f"[+] 已保存: {filename}") if small: win32gui.DestroyIcon(small[0])
print("[✓] 图标提取完成!")
if __name__ == "__main__": dll_path = r"C:\Windows\System32\shell32.dll" output_dir = r".\extracted_icons"
extract_icons(dll_path, output_dir)
|