Sunday, December 22, 2019

WinDbg pykd 101 - Dumping Meterpreter Payload

WinDbg is a kernel-mode and user-mode debugger that is included in Debugging Tools for Windows. WinDbg has a very powerful scripting language but using it can sometimes be very annoying. Alternatively there's an extension "pykd" that can used to run python scripts to automate various repetitive tasks while debugging.

In this blog post we'll see how to use pykd to automate dumping of Metrepreter DLL injected into legitimate process memory. For purpose of demonstration I injected Merterpreter DLL into a "notepad" process. We can take a look at the notepad process memory using "Process Hacker".


The highlighted memory sections are suspicious since it doesn't belong to any of the loaded modules and it has a memory protection value of "RWX". As you can see the other loaded modules have a memory protection value of "RX".

Looking at one of the memory sections reveals the Meterpreter DLL payload (there's another section that has the shellcode for reflectively loading the DLL). We can dump the notepad process and load the same into WinDbg.



The headers of the DLL in WinDbg at that memory location from notepad process.



Now we can automate the payload dumping part using pykd. To load pykd first copy the "pykd.dll" (according to the architecture) under the "winext" directory in WinDbg folder. I'm using a 64 bit version of WinDbg so my extension folder is under "\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext".

Once done load the extension using "!load pykd" command. If everything worked well you should see no output :)

The python script will be used to dump the memory section that contains traces of Meterpreter related strings. The script does the following,

  1. Search for the pattern (using 's' command)
  2. Check the pattern's associated memory region  (using '!vprot' command)
  3. Gets the base address & region size of the memory section (output from vprot)
  4. Dump the memory section (using '.writemem' command)
You can get the python shell post loading of pykd extension using "!py" command.



To interact with WinDbg you can use the "pykd.dbgCommand". All WinDbg commands can be executed using this function and the output can be displayed or saved to a variable.

During analysis it was found that the Meterpreter payload has a unique pattern ('[REU') in the MZ header section. Lets use that term and search it throughout the process memory.



Using the above we can write our logic into a python file and run it inside WinDbg using pykd extension. To run the python file use the "!py " format. The complete script looks like below,

from pykd import *
import sys

def get_val(data, index):
 data = data.splitlines()
 for i in data:
  if index in i:
   val = i.split(':')[1].strip()
   return val
 return False

if len(sys.argv) < 3:
 print("Usage !py " + sys.argv[0] + "  ")
 exit(1)

pattern = sys.argv[2]
directory = sys.argv[1]

res = pykd.dbgCommand("s -a 0 L?80000000 " + pattern)

if res == None:
 print("[*] Pattern not found!")
 exit(1)

res = res.splitlines()

for i in res:
 addr = i.split("  ")[0]
 vprot_res = pykd.dbgCommand("!vprot %s" % addr)
 base_addr = get_val(vprot_res, "BaseAddress")
 region_size = get_val(vprot_res, "RegionSize")

 if base_addr and region_size:
  filename = directory + "\\" + base_addr + ".bin"
  cmd = ".writemem %s %s L?%s" % (filename, base_addr, region_size)
  pykd.dbgCommand(cmd)
  print("[*] Wrote memory dump to: %s of size %s from base address: %s" % (filename, region_size, base_addr))

The script takes the output directory and search string as input and dump the associated memory section. There's lot of scope for further improving the script :)



Looking at the dumped file inside PE studio confirms it is a DLL.



References:

https://rayanfam.com/topics/pykd-tutorial-part1/

No comments:

Post a Comment