Krakz
Malware hunting & Reverse engineering notes

Python 🐍

pbo

All notes related to Python goes here

Base64 custom alphabet python #

Here’s a brief Python code snippet for decoding base64 data that uses a non-standard alphabet. The Darkgate sample was observed to use this custom alphabet.

import base64

def custom_b64_decode(s):
     custom_base64 = "KHkFLg9RnhcZNSDl1TsOj2JveVUpfC4Bq67XyIbm5Q8EGi3A=Madwr0uYzt+oWPx"
     std_base64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/="
     o = str(s).translate(str(s).maketrans(custom_base64, std_base64chars))
     return base64.b64decode(o)

custom_b64_decode("jrIO2L2S")
b'SYSTEM'

PE with pefile #

Snippet of code to read each resource of a PE:

pe = pefile.PE("<path to PE>")

offset: int = 0
size: int = 0
resource_type: str = ""

for entry in pe.DIRECTORY_ENTRY_RESOURCE.entries:
    resource_type = str(entry.name)
    for directory in entry.directory.entries:
      for resource in directory.directory.entries:
	offset = resource.data.struct.OffsetToData
	size = resource.data.struct.Size
	content = pe.get_memory_mapped_image()[offset : offset + size]

	print(
	    f"read resource {resource_type} at offset 0x{offset:x} on 0x{size:x} bytes"
	)

CLSID identifier #

A Python helper to identify the object (class and interface) from the CLSID or the RIID.

The CoCreateInstance function can create various types of COM objects depending on the CLSID provided. Here are some examples of what these objects could be:

  1. Standard COM Objects: These are typical COM objects implementing various functionalities, such as document handling, media processing, or system components.
  2. Automation Objects: Objects that provide OLE Automation interfaces, making them accessible from scripting languages like VBScript, JavaScript, and PowerShell.
  3. ActiveX Controls: These are COM objects that can be embedded in applications or web pages to provide interactive features.
  4. Shell Extensions: COM objects that extend the functionality of the Windows Shell, such as custom context menu handlers, icon handlers, or property sheet handlers.
  5. Service Objects: Objects that provide specific services to other applications, like data access or messaging. https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance
  HRESULT CoCreateInstance(
  [in]  REFCLSID  rclsid,
  [in]  LPUNKNOWN pUnkOuter,
  [in]  DWORD     dwClsContext,
  [in]  REFIID    riid,
  [out] LPVOID    *ppv
);
Code Snippet 1: CoCreateInstance function prototype
Figure 1: example of Object creation using the class identifier

Figure 1: example of Object creation using the class identifier

Figure 2: CLSID export

Figure 2: CLSID export

import struct

CLSID = {
    "TaskScheduler": "0F87369F-A4E5-4CFC-BD3E-73E6154572DD",
    "ITaskFolderCollection": "79184A66-8664-423F-97F1-637356A5D812",
    "ITaskFolder": "8CFAC062-A080-4C15-9A88-AA7C2AF80DFC",
    "IRegisteredTask": "9C86F320-DEE3-4DD1-B972-A303F26B061E",
    "IRunningTask": "653758FB-7B9A-4F1E-A471-BEEB8E9B834E",
    "IRunningTaskCollection": "6A67614B-6828-4FEC-AA54-6D52E8F1F2DB",
    "ITaskDefinition": "F5BC8FC5-536D-4F77-B852-FBC1356FDEB6",
    "IRegistrationInfo": "416D8B73-CB41-4EA1-805C-9BE9A5AC4A74",
    "ITriggerCollection": "85DF5081-1B24-4F32-878A-D9D14DF4CB77",
    "ITrigger": "09941815-EA89-4B5B-89E0-2A773801FAC3",
    "IRepetitionPattern": "7FB9ACF1-26BE-400E-85B5-294B9C75DFD6",
    "ITaskSettings": "8FD4711D-2D02-4C8C-87E3-EFF699DE127E",
    "IIdleSettings": "84594461-0053-4342-A8FD-088FABF11F32",
    "INetworkSettings": "9F7DEA84-C30B-4245-80B6-00E9F646F1B4",
    "IPrincipal": "D98D51E5-C9B4-496A-A9C1-18980261CF0F",
    "IActionCollection": "02820E19-7B98-4ED2-B2E8-FDCCCEFF619B",
    "IAction": "BAE54997-48B1-4CBE-9965-D6BE263EBEA4",
    "IRegisteredTaskCollection": "86627EB4-42A7-41E4-A4D9-AC33A72F2D52",
    "ITaskService": "2FABA4C7-4DA9-4013-9697-20CC3FD40F85",
    "ITaskHandler": "839D7762-5121-4009-9234-4F0D19394F04",
    "ITaskHandlerStatus": "EAEC7A8F-27A0-4DDC-8675-14726A01A38A",
    "ITaskVariables": "3E4C9351-D966-4B8B-BB87-CEBA68BB0107",
    "ITaskNamedValuePair": "39038068-2B46-4AFD-8662-7BB6F868D221",
    "ITaskNamedValueCollection": "B4EF826B-63C3-46E4-A504-EF69E4F7EA4D",
    "IIdleTrigger": "D537D2B0-9FB3-4D34-9739-1FF5CE7B1EF3",
    "ILogonTrigger": "72DADE38-FAE4-4B3E-BAF4-5D009AF02B1C",
    "ISessionStateChangeTrigger": "754DA71B-4385-4475-9DD9-598294FA3641",
    "IEventTrigger": "D45B0167-9653-4EEF-B94F-0732CA7AF251",
    "ITimeTrigger": "B45747E0-EBA7-4276-9F29-85C5BB300006",
    "IDailyTrigger": "126C5CD8-B288-41D5-8DBF-E491446ADC5C",
    "IWeeklyTrigger": "5038FC98-82FF-436D-8728-A512A57C9DC1",
    "IMonthlyTrigger": "97C45EF1-6B02-4A1A-9C0E-1EBFBA1500AC",
    "IMonthlyDOWTrigger": "77D025A3-90FA-43AA-B52E-CDA5499B946A",
    "IBootTrigger": "2A9C35DA-D357-41F4-BBC1-207AC1B1F3CB",
    "IRegistrationTrigger": "4C8FEC3A-C218-4E0C-B23D-629024DB91A2",
    "IExecAction": "4C3D624D-FD6B-49A3-B9B7-09CB3CD3F047",
    "IExecAction2": "F2A82542-BDA5-4E6B-9143-E2BF4F8987B6",
    "IShowMessageAction": "505E9E68-AF89-46B8-A30F-56162A83D537",
    "IComHandlerAction": "6D2FD252-75C5-4F66-90BA-2A7D8CC3039F",
    "IEmailAction": "10F62C64-7E16-4314-A0C2-0C3683F99D40",
    "IPrincipal2": "248919AE-E345-4A6D-8AEB-E0D3165C904E",
    "ITaskSettings2": "2C05C3F0-6EED-4C05-A15F-ED7D7A98A369",
    "ITaskSettings3": "0AD9D0D7-0C7F-4EBB-9A5F-D1C648DCA528",
    "IMaintenanceSettings": "A6024FA8-9652-4ADB-A6BF-5CFCD877A7BA",
    "TaskHandlerPS": "F2A69DB7-DA2C-4352-9066-86FEE6DACAC9",
    "TaskHandlerStatusPS": "9F15266D-D7BA-48F0-93C1-E6895F6FE5AC",
}


def bytes_to_clsid(byte_data: bytes) -> str:
    if len(byte_data) != 16:
	raise ValueError("A CLSID must be 16 bytes long")

    # Unpack bytes according to CLSID structure
    part1, part2, part3, part4_and_part5 = struct.unpack("<IHH8s", byte_data[:16])

    # Split part4_and_part5 into two parts
    part4 = part4_and_part5[:2]
    part5 = part4_and_part5[2:8]
    part6 = byte_data[8:16]

    # Format the CLSID
    clsid = f"{part1:08X}-{part2:04X}-{part3:04X}-{part4.hex().upper()}-{part5.hex().upper()}{part6.hex().upper()}"
    return clsid


def identify_object(raw_id: str) -> str:
    byte_data = bytes.fromhex(raw_id)
    r_clsid = bytes_to_clsid(byte_data)

    for name, clsid in CLSID.items():
	if clsid.lower() in r_clsid.lower():
	    return f"{r_clsid} -> {name}"
    return ""


identify_object("9F36870FE5A4FC4CBD3E73E6154572DD")
0F87369F-A4E5-4CFC-BD3E-73E6154572DDBD3E73E6154572DD -> TaskScheduler

To no overstock the script all the CLSID are not included in it, however a script on this gist contains all the extracted CLSID and RIID from WINE repository is available. The snippet to extract the ID is the following one:

import os
clsids = {}

# make sure to put the script at the root of wine repo
for root_dir, _, filenames in os.walk("include/"):
    for filename in filenames:
      with open(os.path.join(root_dir,  filename), "r") as f:
	content = f.read().split("\n")
	for line_nb, line in enumerate(content):
	    if "uuid(" in line:
		if "interface" in content[line_nb+2] or "coclass" in content[line_nb+2]:
		    clsid = line.strip().replace('uuid(', '').replace(')','')
		    name = content[line_nb+2].split()[1].strip()
		    clsids[name] = clsid

print(clsids)
Code Snippet 2: snippet to extract the CLSID and RIID from wine/include