At SANS Hackfest Penetration Testing summit I had the pleasure of reminiscing with Jedi Master Ed Skoudis about assembly language on our old Commodore 64s. Then Ed made one of his typical profound statements. He said, "In the end, it is all peeks and pokes." On the Commodore 64 the PEEK command was use to read from memory. The POKE command was used to write a value to memory. Ultimately that is all we need to be able to control any process on any computer.
In yesterdays diary I showed you how you could read memory by calling two python functions. Writing to memory also only requires two functions. First you call win32file.SetFilePointer() to set the address you want to update. Then you call win32file.WriteFile() to write data. To make the process even simpler I'll add a writemem() function to the memsearch.py script I wrote yesterday. I add the following lines to yesterdays script: (Email me if you want a copy of the script or grab a copy from yesterday diary)
def writemem(fd,location, data):
Then I start the script and a Python interactive shell by running "python -i memsearch.py". Then I can use the memsrch() function to search for interesting data to update. In this case I am searching for the string "Command Prompt - python" in hopes of updating the titlebar for my command prompt. It finds the string at several addresses in memory. Then I can call writemem() and update the string. When you provide a string to write to memory keep in mind that strings in memory may be in ASCII, UTF-16LE OR UTF-16BE format. In this example I wrote "P0wned Shell" in UTF-16le format to the memory address 40345926. But it didn't update my command prompt title bar. Darn. Windows has several memory locations that contain that string. So I use readmem() to check the memory address to see if it changed. I can see that it did! The memory address contains the updated string.
One of those others addresses that I didn't change must contained our command prompts title bar. memsrch() returns a list of all the addresses that contain the search string. So I could do something like this to change all of the instances of that string between two given addresses.
for addr in memsrch(fd, "Command Prompt - python", 0x100000, 3fef0000, 1000):
But as I said, be careful. I've spent as much time rebooting my machine as I have actually writing code. A better approach is to import Volatility into your script so you can parse memory intelligently and update memory data structures rather than just guessing.
In their excelent paper titled Anti-Forensics resilient memory acquisition, Johannes Stuttgen and Michael Cohen discuss how making small changes to magic values in memory data structures can defeat tools like Volatility. If you have a chance give the paper a read. It is here.
If that sounds interesting to you and you want to know more about Python programming check out SEC573 Python for Penetration Testers. I am teaching it in Reston VA March 17th! Click HERE for more information.
Follow me on twitter? @MarkBaggett
Nov 21st 2013
6 years ago