This really is a match made in heaven. F-Response is really slick from a remote memory acquisition standpoint. Combine that with Volatility and you have an easy 30-minute meal recipe for memory forensics and incident response.
I set F-Response up to allow me to connect to a domain-joined machine on my network by deploying the F-Response agent from F-Response Enterprise. F-Response has a great mission guide on how to accomplish this with a Windows target.
Using my Kali machine on the same subnet, I was able to connect to the system using
iscsiadm (which is also what the F-Response examiner client uses on Windows, but on Linux all you have to do is apt-get iscsi, do a little configuration work, and you’re good to go).
Once the F-Response agent is deployed on the system you want to analyze, you can start working on configuring your analysis host (in my case, the Kali machine with Volatility installed on it) to handle the connection.
According to a blog post over at F-Response, you first need to set up an interface for a given connection. So make yourself an ifaces folder:
Within there, we’ll use the
iscsiadm command to generate an interface config file for each connection we want to make using iscsi.
iscsiadm -m iface -I iface0 --op=new
We then set the MAC address of the analysis machine in the newly created config:
iscsiadm -m iface -I iface0 --op=update -n iface.hwaddress -v AA:BB:CC:DD:EE:FF
The only remaining thing to do is to configure iscsi with the appropriate credentials to connect to the F-Response agent that you set up during the initial F-Response deployment process. The configuration is in
/etc/iscsi/iscsid.conf and you’ll want to update both of these sections:
# To enable CHAP authentication set node.session.auth.authmethod # to CHAP. The default is None. node.session.auth.authmethod = CHAP # To set a CHAP username and password for initiator # authentication by the target(s), uncomment the following lines: node.session.auth.username = grayhatninja node.session.auth.password = Sup3rS3cret! # To enable CHAP authentication for a discovery session to the target # set discovery.sendtargets.auth.authmethod to CHAP. The default is None. discovery.sendtargets.auth.authmethod = CHAP # To set a discovery session CHAP username and password for the initiator # authentication by the target(s), uncomment the following lines: discovery.sendtargets.auth.username = grayhatninja discovery.sendtargets.auth.password = Sup3rS3cret!
Good. Now we’re set up to discover available iscsi targets and connect to them:
iscsiadm -m discovery -t st -p 10.40.2.73 -P 1
That will yield results that look like this:
[email protected]:/etc/iscsi# iscsiadm -m discovery -t st -p 10.40.2.73 -P 1 Target: iqn.2008-02.com.f-response.dummyhostname:disk-0 Portal: 10.40.2.73:3260,1 Iface Name: iface0 Target: iqn.2008-02.com.f-response.dummyhostname:vol-c Portal: 10.40.2.73:3260,1 Iface Name: iface0 Target: iqn.2008-02.com.f-response.dummyhostname:pmem Portal: 10.40.2.73:3260,1 Iface Name: iface0
So, now that you know what iscsi targets are available on the system. We’re doing memory analysis so we’ll first try and map the pmem target since that’s the physical memory F-Response found.
iscsiadm -m node -T iqn.2008-02.com.f-response.dummyhostname:pmem -l
And we get this:
Logging in to [iface: iface0, target: iqn.2008-02.com.f-response.dummyhostname:pmem, portal: 10.40.2.73,3260] (multiple) Login to [iface: iface0, target: iqn.2008-02.com.f-response.dummyhostname:pmem, portal: 10.40.2.73,3260] successful.
So let’s take a look at our disks:
[email protected]:/etc/iscsi# fdisk -l Disk /dev/sda: 42.9 GB, 42949672960 bytes 255 heads, 63 sectors/track, 5221 cylinders, total 83886080 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00050374 Device Boot Start End Blocks Id System /dev/sda1 * 2048 499711 248832 83 Linux /dev/sda2 501758 83884031 41691137 5 Extended /dev/sda5 501760 83884031 41691136 8e Linux LVM Disk /dev/mapper/valvalis-root: 40.9 GB, 40907046912 bytes 255 heads, 63 sectors/track, 4973 cylinders, total 79896576 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000 Disk /dev/mapper/valvalis-root doesn't contain a valid partition table Disk /dev/mapper/valvalis-swap_1: 1782 MB, 1782579200 bytes 255 heads, 63 sectors/track, 216 cylinders, total 3481600 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x00000000 Disk /dev/mapper/valvalis-swap_1 doesn't contain a valid partition table Note: sector size is 4096 (not 512) Disk /dev/sdb: 5033 MB, 5033164800 bytes 155 heads, 62 sectors/track, 127 cylinders, total 1228800 sectors Units = sectors of 1 * 4096 = 4096 bytes Sector size (logical/physical): 4096 bytes / 4096 bytes I/O size (minimum/optimal): 4096 bytes / 4096 bytes Disk identifier: 0x00000000 Disk /dev/sdb doesn't contain a valid partition table
Our last entry
/dev/sdb is our memory. So the next step is to image that memory to a physical file located on our analysis machine using dc3dd. This command forensically copies the image to my machine (note the md5 hashes).
mkdir /cases dc3dd if=/dev/sdb of=/cases/dummyhostname.img hash=md5 hof=/cases/dummyhostname.md5 dc3dd 7.1.614 started at 2014-09-04 13:02:59 -0700 compiled options: command line: dc3dd if=/dev/sdb of=/cases/dummyhostname.img hash=md5 hof=/cases/dummyhostname.md5 device size: 1228800 sectors (probed) sector size: 4096 bytes (probed) 5033164800 bytes (4.7 G) copied (100%), 1277.95 s, 3.8 M/s output hashing (100%) input results for device
/dev/sdb: 1228800 sectors in 0 bad sectors replaced by zeros 69262c7c02b315a10fb80ad59a81d218 (md5) output results for file '/cases/dummyhostname.img': 1228800 sectors out output results for file '/cases/dummyhostname.md5': 1228800 sectors out [ok] 69262c7c02b315a10fb80ad59a81d218 (md5) dc3dd completed at 2014-09-04 13:24:17 -0700
Excellent! We successfully imaged the physical memory of our subject to our analysis machine. Now all we need to do is point Volatility at our image and we’re in business.
[email protected]:/usr/share/volatility_2.4/volatility# ./vol.py imageinfo -f /cases/dummyhostname.img Volatility Foundation Volatility Framework 2.4 Determining profile based on KDBG search... Suggested Profile(s) : Win7SP0x64, Win7SP1x64, Win2008R2SP0x64, Win2008R2SP1x64 AS Layer1 : AMD64PagedMemory (Kernel AS) AS Layer2 : FileAddressSpace (/cases/na00034l.img) PAE type : No PAE DTB : 0x187000L KDBG : 0xf80002c540a0 Number of Processors : 4 Image Type (Service Pack) : 1 KPCR for CPU 0 : 0xfffff80002c55d00L KPCR for CPU 1 : 0xfffff88003307000L KPCR for CPU 2 : 0xfffff88003377000L KPCR for CPU 3 : 0xfffff880033e7000L KUSER_SHARED_DATA : 0xfffff78000000000L Image date and time : 2014-09-04 20:03:00 UTC+0000 Image local date and time : 2014-09-04 13:03:00 -0700
You can see that Volatility suggests profiles for us to use. I happen to know this is a Win7SP1x64 machine so I’ll go ahead and run a Volatility plugin against our image using that profile:
[email protected]:/usr/share/volatility_2.4/volatility# ./vol.py psxview -f /cases/dummyhostname.img --profile=Win7SP1x64 Volatility Foundation Volatility Framework 2.4 Offset(P) Name PID pslist psscan thrdproc pspcid csrss session deskthrd ExitTime ------------------ -------------------- ------ ------ ------ -------- ------ 0x0000000127ac5060 svchost.exe 1188 True True False True True True False 0x0000000126842b30 unsecapp.exe 3036 True True False True True True False 0x0000000126f0b060 WmiPrvSE.exe 2096 True True False True True True False . . . 0x000000012bf64b30 f-response-ent 7760 False True False True True True False
You can see that the F-Response agent shows up in the list (psxview is a plugin that reveals hidden processes) but its value is “False” in the pslist column, indicating that it’s hidden in the Processes tab of Task Manager. A quick look on my target system reveals this is true.
Make sure you check out all of the plugins Volatility has to offer by running
Now that you’ve acquired the physical memory and you don’t need your iscsi target for anything else, simply disconnect. Since we’re only connected to one target, we can simply issue the following command which will disconnect us from all iscsi targets.
iscsiadm -m node -u
And you’re out.
One note that might save you some heartache. I first tried this exercise using a virtual machine as the subject under analysis. Despite joining the VM to the domain, successfully deploying the F-Response agent and successfully (I think) connecting with iscsi I could never get Volatility to work with the resulting image. I could successfully generate imageinfo with the correct profile suggestions and I could even run
strings against the image to find signatures I knew would be present in the image and yet Volatility plugins would never work quite right.
In this case, I’ve split my workflow. If our subject is a VM, just use the vmem or snapshot files with Volatility (or, use a program like Mandiant Memoryze to capture the memory). If our subject is bare metal, use F-Response.