"In the end it is all PEEKS and POKES."
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.
Doing a PEEK in live memory is easy with winpmem. I've already shown you how you can use Python and winpmem to read live memory. If you missed the article click here to take a peek. (Pun intended) Today I'm going to show you how to poke. Not a Facebook poke; a Commodore 64 poke. Which is, of course, much much cooler. You see, winpmem can also write to anywhere in memory that you choose.
Winpmem has two different device drivers. One is used for read only access to memory. The read only device driver is installed by default when you use the "-L" option. This is the device driver of choice for capturing forensics images. The other driver is used for read and write access to memory. To install the write driver you run "winpmem_write_1.4.exe" and specify the "-L" and the "-W" option.
Winpmem will indicate that write mode is enabled and gives you a friendly warning by saying, "Hope you know what your doing." Well, ignorance has never stopped me. But, it is wise to note that are should save what you are doing before experimenting with this. You are using a device driver (that is running in Kernel memory) and you can write to anywhere you want to in memory. That includes KERNEL memory space. You can very easily render your machine unusable, blue screen your box or worse.
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):
win32file.SetFilePointer(fd, location, 0 )
win32file.WriteFile(fd, data)
return
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):
writemem(fd, addr, "p0wned shell".encode("utf-16le"))
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
Comments