Analyzing shellcode with Qiling Framework

Dec. 23, 2020 // echel0n

Analyzing shellcode with Qiling Framework

Hello guys!

In this blog, i will show you how to analyze malicious shellcode with qiling framework.
Actually, If you really need quick check if some shellcode is trying to connect any IP, you can use this example.

  1. #!/usr/bin/env python
  2. """
  3. This code will hook connect() function and will print out the address which
  4. shellcode is trying to.
  5. The sample shellcode is from BATTLEWARE CTF
  6. sample shellcode base64 encoded:
  7. kJCQkJCQkJCQkJCQkJCQkJCQkJDb3rpanC/h2XQk9F4zybFSMVYXg+78AwyPzRRMR5PXrJj0XkmpNAQamoROThduAnqsAouNBajtoJaBzqMU2AIDJBNXQmFOmhY6BAmGT1CSLQN0ktLUd7NFbi4TZKNaGn6gZ9T1EhPn32rcRB5DL5RnZNDjkZZt9GbkqXF8TjkhWG7utCt8W7JzYVoXCJ3Xlt4Xo7z6fHfcW9nW4buCh0ewL9P1mycQNCO4Pk9QiuH7/qZqIvnJQJKVN2vjvPM/s9bSP1gm2pXPdnRGsCY0Nlgsu2l4TxECE6ry7UyxCIaOuQxjBl9mm07IHwLLgr7Lwe+BQOYQT6GDAjhB3njvXvQUc8yT5PrtC7OrwEVRRnr8R5sax8NA38bKBVvt3NNkqYiLMmdmau3J0CRCgLSxqBPCveTlKg9RsFWgNTQu3KW75WTV8afNflwyTONf6ZMa3Bts2fxuaaW6gwO2LqOwtwc=
  8. """
  9. from qiling import *
  10. from qiling.const import *
  11. from binascii import hexlify
  12. # IP format for humans
  13. def ip_builder(IP: bytes) -> str:
  14. """TODO: Docstring for ip_builder.
  15. :IP: bytes
  16. :returns: str
  17. """
  18. first = int(IP[0:2], 16)
  19. second = int(IP[2:4], 16)
  20. third = int(IP[4:6], 16)
  21. fourth = int(IP[6:8], 16)
  22. return f"{first}.{second}.{third}.{fourth}"
  23. def human_readable_ip_str(name):
  24. ipp_addr_version = hexlify(name[0:2])
  25. ip_addr_port = int(hexlify(name[2:4]), 16)
  26. ip_addr = hexlify(name[4:8])
  27. ip = ip_builder(ip_addr)
  28. print(f"Trying to connect ~> {ip}:{ip_addr_port}")
  29. def _connect(ql, address, params):
  30. value = ql.mem.read(params["name"], params["namelen"])
  31. human_readable_ip_str(value)
  32. def prepare() -> Qiling:
  33. shellcode = open("./bin.sc", "rb").read()
  34. rootfs = "/tools/qiling/examples/rootfs/x86_windows"
  35. ostype = "windows"
  36. archtype = "x86"
  37. output = "default"
  38. ql = Qiling(
  39. shellcoder=shellcode,
  40. rootfs=rootfs,
  41. ostype=ostype,
  42. archtype=archtype,
  43. output=output,
  44. console=True,
  45. )
  46. ql.filter = ["connect"]
  47. ql.set_api("connect", _connect, QL_INTERCEPT.ENTER)
  48. return ql
  49. def main():
  50. ql = prepare()
  51. try:
  52. ql.run()
  53. except:
  54. pass
  55. if __name__ == "__main__":
  56. main()

Example output below;