Skip to content

Instantly share code, notes, and snippets.

Last active November 3, 2022 23:50
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Unpacking memfd malware with Qiling
#!/usr/bin/env python3
Alan <ex0dus-0x>
Using Qiling to unpack and decompress a sample being loaded
and executed in-memory.
import os
import sys
import shutil
from qiling import *
from qiling.const import QL_VERBOSE
# arbitrary file descriptor number to return when we emulate `memfd_create`
MEMFD = 123
# path to rootfs for storing dependencies and executables
ROOTFS = "rootfs"
def memfd_create_hook(ql, name, flags, *args, **kwargs):
""" Hooks memfd_create, parse name and return arbitrary file descriptor """
buf = ql.mem.string(name)"memfd_create called, anonymous file called {buf} created")
return MEMFD
def write_hook(ql, write_fd, write_buf, write_count, *args, **kwargs):
""" Instrument write only after in-memory fd is instantiated """
regreturn = 0
buf =, write_count)
# stop write to stdout or stderr and output
if (write_fd == 0x1) or (write_fd == 0x2):
ql.log.error(f"Program error: {str(bytes(buf))}")
# parse out executable if writing to our anonymous fd.
elif (write_fd == MEMFD):
# confirm ELF magic number
if bytes(buf[0:4]) != b'\x7fELF':
ql.log.error(f"Not a valid ELF executable being read!")
sys.exit(1)"Found valid ELF! Unpacking to disk at `unpacked.elf`.")
with open("unpacked.elf", "wb") as fd:
# write to buffer normally if not with our file descriptor
regreturn = write_count
return regreturn
def execve_hook(ql, fd, pathname, argv, envp, flags, *args, **kwargs):
""" Prevent execve from running and halt """
pathname = ql.mem.string(pathname)"Stopping execution of anonymous file")
# doesn't seem like ql.emu_stop() works at halting execution, so we'll call exit
def main():
if len(sys.argv) != 2:
print("Provide path to packed executable.")
path = sys.argv[1]
if not os.path.exists(path):
print("Binary does not exist forunpacking.")
# the path we provide needs to also reflect inside in rootfs, so make a copy
shutil.copyfile(path, os.path.join(ROOTFS, path))
# instantiate qiling and hook syscalls with callbacks
ql = Qiling([path], ROOTFS, stdout=sys.stdout, multithread=True)
ql.set_syscall(0x1, write_hook)
ql.set_syscall(0x13f, memfd_create_hook)
ql.set_syscall(0x142, execve_hook)
if __name__ == "__main__":
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment