-
Notifications
You must be signed in to change notification settings - Fork 749
Malware Analysis
Qiling Framework is a powerful tool for malware analysis. Its sandboxed emulation environment allows you to safely execute and inspect malicious code, while its hooking capabilities provide deep visibility into the malware's behavior.
- Safety: Malware is executed within a secure sandbox, isolated from the host system. It cannot infect your machine.
- Environment Spoofing: You can easily modify the emulated environment to trick malware. For example, you can change the system time, fake registry keys, or alter API responses to trigger specific behaviors.
- Dynamic Analysis: Observe the malware as it runs. See what files it tries to access, what network connections it attempts, and what system changes it makes.
- Deobfuscation and Unpacking: Many malware samples are packed or obfuscated. You can use Qiling to run the malware until it unpacks itself in memory, and then dump the clean, deobfuscated code for further analysis.
- Cross-Platform Analysis: Analyze Windows malware on a Linux machine, or IoT malware on a Windows machine, without needing to set up multiple virtual machines.
The most common first step is to monitor the malware's interactions with the operating system.
Example: Logging all syscalls
from qiling import Qiling
from qiling.const import QL_VERBOSE
if __name__ == "__main__":
# Run a Windows malware sample
ql = Qiling(['malware.exe'], 'path/to/rootfs/x86_windows', verbose=QL_VERBOSE.DEFAULT)
ql.run()
This will print every syscall the malware makes, along with its parameters. This can reveal its intent, such as trying to delete files, create registry keys, or connect to a C2 server.
You can hook specific functions to gain more context or to control the malware's execution.
Example: Intercepting file creation
def on_createfile(ql, address, params):
filename = params['lpFileName']
print(f"Malware is attempting to create or open file: {filename}")
# You could even block the action
# ql.reg.eax = 0xFFFFFFFF # Return INVALID_HANDLE_VALUE
# ql.emu_stop()
# Hook CreateFileW in kernel32.dll
ql.os.set_api("CreateFileW", on_createfile, 'kernel32.dll')
If a sample is packed, you can use Qiling to let it unpack itself and then dump the unpacked code.
Technique:
- Identify a location in the code that is likely to be executed after the unpacking is complete. A good candidate is the first instruction of a newly allocated and executable memory region.
- Set a hook at that location.
- When the hook is hit, dump the entire process memory or specific regions of interest.
Example:
def dump_memory(ql):
print("Unpacking likely complete. Dumping memory...")
# Find the memory region containing the original entry point (OEP)
# This requires some heuristics or manual analysis
unpacked_region = ql.mem.get_map_containing(ql.reg.eip)
if unpacked_region:
start, end, perms, label = unpacked_region
unpacked_code = ql.mem.read(start, end - start)
with open("unpacked_binary.bin", "wb") as f:
f.write(unpacked_code)
print(f"Dumped {len(unpacked_code)} bytes to unpacked_binary.bin")
ql.emu_stop()
# Assume we found the OEP to be at 0x401500
ql.hook_address(dump_memory, 0x401500)
ql.run()
Qiling is ideal for analyzing shellcode, which often expects a very specific environment.
from qiling import Qiling
from qiling.const import QL_ARCH, QL_OS
with open("shellcode.bin", "rb") as f:
shellcode = f.read()
# Emulate the shellcode in a Windows environment
ql = Qiling(shellcode=shellcode, archtype=QL_ARCH.X86, ostype=QL_OS.WINDOWS)
# You can pre-populate memory or registers that the shellcode might need
# For example, set up a fake API address resolver
ql.run()
By combining these techniques, you can build a powerful and automated malware analysis pipeline with Qiling.
Many malware families try to launch other processes or inject code into existing ones. Hooking process creation APIs is a fundamental technique for detecting this behavior.
Here is a script that hooks CreateProcessA
to monitor for new processes.
Qiling Script:
from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.os.windows.api import hook_api
@hook_api("CreateProcessA", "kernel32.dll")
def hook_createprocessa(ql: Qiling, address: int, params: dict):
# Get the name of the application to be launched
app_name = params.get("lpApplicationName")
cmd_line = params.get("lpCommandLine")
print(f"\n[!] Hooked CreateProcessA! Malware is trying to launch:")
if app_name:
print(f" Application: {app_name}")
if cmd_line:
print(f" Command Line: {cmd_line}")
# We can block this action by returning 0 (failure)
ql.reg.eax = 0
ql.emu_stop()
return 0
if __name__ == "__main__":
# Assume 'malware.exe' is the sample we are analyzing
executable_path = 'C:\\malware.exe'
rootfs_path = 'path/to/your/rootfs/x86_windows'
ql = Qiling([executable_path], rootfs_path, verbose=QL_VERBOSE.OFF)
print("[*] Starting malware analysis...")
ql.run()
print("[*] Analysis finished.")
- This script will immediately detect if the malware attempts to call
CreateProcessA
. - The hook intercepts the call before the new process is created, giving the analyst full control.
- By printing the
lpApplicationName
andlpCommandLine
parameters, we can see exactly what the malware is trying to execute. - This technique can be extended to analyze process injection (using
CreateRemoteThread
) or other common persistence mechanisms.
- Home
- Getting Started
- Core Concepts
- Usage
- Features
- Tutorials
- Development
- Resources