How to extract 128x128 icon raster data from exe in python

I am trying to extract icons from .exe files in windows using win32gui. I found the ExtractIconEx () and ExtractIcon () functions.

I can get 32x32 or 16x16 icons only from the above functions. The following link only responds to 32x32 images. How to extract 32x32 icons from raster data from EXE and convert them to a PIL image object?

I need to extract icons 128x128 or larger. Any ideas on extracting larger icons from exe files?

+6
source share
2 answers

I did some research and also published them. If you want to just see the result code (I hope this is exactly what you are asking for), you can find it after the β€œhorizontal rule” below.

First, I tried to use the following code to determine what sizes of icons are stored in file resources:

# Using LoadLibrary (rather than CreateFile) is required otherwise # LoadResource, FindResource and others will fail PATH = ... # Valid file path hlib = win32api.LoadLibrary(PATH) # This loop should print sizes of resources icons icon_names = win32api.EnumResourceNames(hlib, win32con.RT_ICON) for icon_name in icon_names: rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name) hicon = win32gui.CreateIconFromResource(rec, True) info = win32gui.GetIconInfo(hicon) bminfo = win32gui.GetObject(info[3]) print("%2d: 0x%08X -> %d %d " % (icon_name, hicon, bminfo.bmWidth, bminfo.bmHeight)) 

While the file contains only 16x16 and 32x32 pixels icons, everything will be OK, here is the output for the Windows XP calculator:

  1: 0x0093051B -> 32 32 2: 0x005B0513 -> 32 32 3: 0x007004CB -> 32 32 4: 0x002E04C9 -> 32 32 5: 0x033A04C5 -> 32 32 6: 0x00780487 -> 32 32 7: 0x0052045D -> 32 32 8: 0x055D053D -> 32 32 

As soon as I tried a file with a large icon, I get an exception:

 Traceback (most recent call last): File "extract_icon.py", line 50, in <module> hicon = win32gui.CreateIconFromResource(rec, True) pywintypes.error: (0, 'CreateIconFromResource', 'No error message is available') 

After some research, I realized that the large icon is not stored in ico format , but in png (for my case).

Of course, I do not know what exactly your .exe (its internals) is, but after I analyzed several .exe files that I found on my computer, I found that the icons are larger than 32x32 or 16x16 pixels, most likely represented by medium .png files (you can check this using, for example, PE Explorer , a trial version exists).

So, to read the image from the resources, I used the C ++ manual . The main goal here is to get a pointer to the actual image resource data and copy it to the Python buffer. And the completion step is to save it in a file (I think you could translate it into PIL yourself).


FULL CODE TO READ A BIG RESOURCE :

 # Use wchar_t function version (FindResourceW rather than FindResourceA) from __future__ import unicode_literals # pywin32 imports import pywintypes import win32ui import win32gui import win32con import win32api import win32file # ctypes configuring. pywin32 has no a lot of required functions import ctypes import ctypes.util # memcpy used to copy data from resource storage to our buffer libc = ctypes.CDLL(ctypes.util.find_library('c')) libc.memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t] libc.memcpy.restype = ctypes.c_char_p # All Windows backslashes must be escaped to LoadLibrary worked correctly '\' -> '\\' PATH = ... # WARNING: Assumed that icon_name - VALID resource ID # It can be determined in loop when enumerating resources: # if exception at CreateIconFromResource raised than this code appropriate # otherwise resource is standard icon and first code snippet can be used. # If resources Id exactly known then it can be hardcoded as in this code icon_name = 1 try: hlib = win32api.LoadLibrary(PATH) # This part almost identical to C++ hResInfo = ctypes.windll.kernel32.FindResourceW(hlib, icon_name, win32con.RT_ICON) size = ctypes.windll.kernel32.SizeofResource(hlib, hResInfo) rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name) mem_pointer = ctypes.windll.kernel32.LockResource(rec) # And this is some differ (copy data to Python buffer) binary_data = (ctypes.c_ubyte * size)() libc.memcpy(binary_data, mem_pointer, size) # Save it with open("icon.png", "wb") as test_file: test_file.write(bytearray(binary_data)) except pywintypes.error as error: print "ERROR: %s" % error.strerror raise 

UPDATED

Code for automatically searching for resources without icons and extracting it into a file named "Resource_XX":

 # Same IMPORT as previously should be used # All Windows backslashes must be escaped to LoadLibrary worked correctly '\' -> '\\' PATH = ... def extract(rec): try: hicon = win32gui.CreateIconFromResource(rec, True) except pywintypes.error as error: # Check on appropriate error if error.winerror != 6: raise print("Resource %2d isn't .ico, extract" % icon_name) # This part almost identical to C++ hResInfo = ctypes.windll.kernel32.FindResourceW(hlib, icon_name, win32con.RT_ICON) size = ctypes.windll.kernel32.SizeofResource(hlib, hResInfo) mem_pointer = ctypes.windll.kernel32.LockResource(rec) # And this is some differ (copy data to Python buffer) binary_data = (ctypes.c_ubyte * size)() libc.memcpy(binary_data, mem_pointer, size) # Save it with open("Resource_%s.png" % icon_name, "wb") as extract_file: extract_file.write(bytearray(binary_data)) else: info = win32gui.GetIconInfo(hicon) bminfo = win32gui.GetObject(info[3]) print("Resource %2d is .ico: 0x%08X -> %d %d " % (icon_name, hicon, bminfo.bmWidth, bminfo.bmHeight)) try: hlib = win32api.LoadLibrary(PATH) icon_names = win32api.EnumResourceNames(hlib, win32con.RT_ICON) for icon_name in icon_names: rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name) extract(rec) except pywintypes.error as error: print "ERROR: %s" % error.strerror raise 
+8
source

I want to extract the default icon and various options. Based on Alexey's answer and Audionautics answer in a 32x32 stream, here is the code.

 # Use wchar_t function version (FindResourceW rather than FindResourceA) from __future__ import unicode_literals # pywin32 imports import win32con import win32api import win32file import win32gui import win32ui import pywintypes # ctypes configuring. pywin32 has no a lot of required functions import ctypes import ctypes.util # memcpy used to copy data from resource storage to our buffer libc = ctypes.CDLL(ctypes.util.find_library('c')) libc.memcpy.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t] libc.memcpy.restype = ctypes.c_char_p # patch FindResourceW, ctypes.windll.kernel32.SizeofResource FindResourceW = ctypes.windll.kernel32.FindResourceW FindResourceW.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] FindResourceW.restype = ctypes.c_void_p SizeofResource = ctypes.windll.kernel32.SizeofResource SizeofResource.argtypes = [ctypes.c_void_p, ctypes.c_void_p] SizeofResource.restype = ctypes.c_size_t # Using LoadLibrary (rather than CreateFile) is required otherwise # LoadResource, FindResource and others will fail PATH = "C:\\Program Files\\Internet Explorer\\iexplore.exe" hlib = win32api.LoadLibraryEx(PATH, 0, 2) # get icon groups, default is the first group icon_groups = win32api.EnumResourceNames(hlib, win32con.RT_GROUP_ICON) group_name = icon_groups[0] print group_name hRes = win32api.LoadResource(hlib, win32con.RT_GROUP_ICON, group_name) mem_icon_dir = ctypes.windll.kernel32.LockResource(hRes) # 32 bits color; 16 and 256 colors are too old # iterate through the common sizes icon_sizes = (16, 24, 32, 48, 96, 256) for icon_size in icon_sizes: icon_name = ctypes.windll.user32.LookupIconIdFromDirectoryEx(mem_icon_dir, True, icon_size, icon_size, 0x00000000); hResInfo = FindResourceW(hlib, icon_name, win32con.RT_ICON) size = ctypes.windll.kernel32.SizeofResource(hlib, hResInfo) rec = win32api.LoadResource(hlib, win32con.RT_ICON, icon_name) mem_icon = ctypes.windll.kernel32.LockResource(rec) # And this is some differ (copy data to Python buffer) binary_data = (ctypes.c_ubyte * size)() libc.memcpy(binary_data, mem_icon, size) hIconRet = ctypes.windll.user32.CreateIconFromResourceEx(binary_data, size, True, 0x00030000, 0, 0, 0x00000000); info = win32gui.GetIconInfo(hIconRet) bminfo = win32gui.GetObject(info[4]) # generate bitmap by drawing the icon hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0)) hbmp = win32ui.CreateBitmap() hbmp.CreateCompatibleBitmap(hdc, bminfo.bmWidth, bminfo.bmHeight) hcdc = hdc.CreateCompatibleDC() hcdc.SelectObject(hbmp) win32gui.DrawIconEx(hcdc.GetHandleOutput(), 0, 0, hIconRet, bminfo.bmWidth, bminfo.bmHeight, 0, 0, 0x0003) hbmp.SaveBitmapFile(hcdc, "icon-%03dx%03d-%05d-%03d.bmp" % (bminfo.bmWidth, bminfo.bmHeight, group_name, icon_name)) win32gui.DestroyIcon(hIconRet) 
+1
source

All Articles