Friday, September 14, 2012

Week 1 of the Month of Volatility Plugins posted!

 I'm going to borrow from Andrew's blog here to let you know about our Month of Volatility Plugins:

I was writing to announce that week 1 of the month of Volatility plugins is finished, and we now have five in-depth blog posts covering Windows and Linux internals and rootkit detection. These have all been posted to the new Volatility Labs blog.

Post 1: Logon Sessions, Processes, and Images

This Windows focused post covers linking processes to their logon session, detecting hidden processes using session structures, and determining the loaded the drivers mapped into each session.

http://volatility-labs.blogspot.com/2012/09/movp-11-logon-sessions-processes-and.html

Post 2: Window Stations and Clipboard Malware

This Windows focused post covers enumerating and analyzing window stations and clipboard monitoring malware.

http://volatility-labs.blogspot.com/2012/09/movp-12-window-stations-and-clipboard.html

Post 3: Desktops, Heaps, and Ransomware

This Windows focused post covers finding rogue desktops used to hide applications and created by ransomware, linking threads to desktops, analyzing the desktop heap for memory corruptions, and profiling heap allocations to locate USER objects.

http://volatility-labs.blogspot.com/2012/09/movp-13-desktops-heaps-and-ransomware.html

Post 4: Average Coder Rootkit, Bash History, and Elevated Processes

This Linux focused post covers analyzing the Average Coder rootkit, recovering .bash_history from memory, even when faced with anti-forensics, and finding elevated processes.

http://volatility-labs.blogspot.com/2012/09/movp-14-average-coder-rootkit-bash.html

Post 5: KBeast Rootkit, Detecting Hidden Modules, and sysfs

This Linux focused post covers analyzing the KBeast rootkit, finding modules unlinked from the module list, and the forensic values of sysfs.

http://volatility-labs.blogspot.com/2012/09/movp-15-kbeast-rootkit-detecting-hidden.html


If you have any questions or comments on the posts, please leave a comment on the respective post on the Volatility Labs blog.

Future Volatility posts will appear on our official blog (http://volatility-labs.blogspot.com/).  Also you might want to follow our project on twitter: @Volatility for updates and news.  See you at OMFW!

Saturday, September 01, 2012

Job File Parser

While writing material for the Blackhat training course that Andrew Case and I gave this summer, I realized that there did not appear to be many tools that would parse job files. At that time, Harlan Carvey had written a blogpost on job files and had mentioned them in part of his timeline materials, but he had not yet released his Perl script (It has since been released here). This prompted me to write up a parser of my own in Python.

.job files consist of two sections: 1) Fixed Length and 2) Variable Length. The MSDN documentation is fairly good for letting us know how to parse out these sections.

So what does a .job file look like?

$ xxd At5.job 0000000: 0006 0100 e378 73f7 4d8b 2a45 a589 1cc5 .....xs.M.*E.... 0000010: fa64 cfd2 4600 cc00 0000 0000 3c00 0a00 .d..F.......<... 0000020: 2000 0000 0014 730f 0000 0000 0513 0400 .....s......... 0000030: 0200 e421 dc07 0700 0100 1000 0b00 1a00 ...!............ 0000040: 0000 0f00 0000 0400 6300 6d00 6400 0000 ........c.m.d... 0000050: 0f00 2f00 6300 2000 6e00 6f00 7400 6500 ../.c. .n.o.t.e. 0000060: 7000 6100 6400 2e00 6500 7800 6500 0000 p.a.d...e.x.e... 0000070: 0000 0700 5300 5900 5300 5400 4500 4d00 ....S.Y.S.T.E.M. 0000080: 0000 1e00 4300 7200 6500 6100 7400 6500 ....C.r.e.a.t.e. 0000090: 6400 2000 6200 7900 2000 4e00 6500 7400 d. .b.y. .N.e.t. 00000a0: 5300 6300 6800 6500 6400 7500 6c00 6500 S.c.h.e.d.u.l.e. 00000b0: 4a00 6f00 6200 4100 6400 6400 2e00 0000 J.o.b.A.d.d..... 00000c0: 0000 0800 0000 0000 0000 0000 0100 3000 ..............0. 00000d0: 0000 dc07 0700 1000 0000 0000 0000 0b00 ................ 00000e0: 1a00 0000 0000 0000 0000 0000 0000 0000 ................ 00000f0: 0000 feff ffff fd68 7377 0000 0000 0100 .......hsw...... 0000100: 0100 0416 10dd 78d9 b300 f7f0 9b20 9bd8 ......x...... .. 0000110: a0c4 5108 c943 d5c9 c64f 47ea 6052 0349 ..Q..C...OG.`R.I 0000120: 23e1 e1ab 6815 e8ef 219e 6d3b aa88 1360 #...h...!.m;...` 0000130: 706b c27b 2e44 9db1 4e89 81ca dd0a 869e pk.{.D..N....... 0000140: 2b61 .6..

We can see the first section of the job file below:

0000000: 0006 0100 e378 73f7 4d8b 2a45 a589 1cc5 .....xs.M.*E.... 0000010: fa64 cfd2 4600 cc00 0000 0000 3c00 0a00 .d..F.......<... 0000020: 2000 0000 0014 730f 0000 0000 0513 0400 .....s......... 0000030: 0200 e421 dc07 0700 0100 1000 0b00 1a00 ...!............ 0000040: 0000 0f00 ....

The fixed length section is pretty straightforward (I will only fill in a few):
0-2 : Product Info (0x600 - Vista)
2-4 : File Version (0x1)
4-20 : UUID ({F77378E3-8B4D-452A-A589-1CC5FA64CFD2})
20-22: Application Name Offset (0x46)
22-24: Trigger Offset (0xcc)
24-26: Error Retry Count (0x00)
26-28: Error Retry Interval (0x00)
28-30: Idle Deadline (0x3c)
30-32: Idle Wait (0xa)
32-36: Priority
36-40: Maximum Runtime
40-44: Exit Code (0x0)
44-48: Status (0x41305)
48-52: Flags
52-68: Run Date (Monday Jul 16 11:26:00.15 2012)

The variable length section actually contains sizes (denoted in red below) before some of the data members mentioned in the MSDN documentation:

0000 0400 6300 6d00 6400 0000 ...c.m.d... 0000050: 0f00 2f00 6300 2000 6e00 6f00 7400 6500 ../.c. .n.o.t.e. 0000060: 7000 6100 6400 2e00 6500 7800 6500 0000 p.a.d...e.x.e... 0000070: 0000 0700 5300 5900 5300 5400 4500 4d00 ....S.Y.S.T.E.M. 0000080: 0000 1e00 4300 7200 6500 6100 7400 6500 ....C.r.e.a.t.e. 0000090: 6400 2000 6200 7900 2000 4e00 6500 7400 d. .b.y. .N.e.t. 00000a0: 5300 6300 6800 6500 6400 7500 6c00 6500 S.c.h.e.d.u.l.e. 00000b0: 4a00 6f00 6200 4100 6400 6400 2e00 0000 J.o.b.A.d.d..... 00000c0: 0000 0800 0000 0000 0000 0000 0100 3000 ..............0. 00000d0: 0000 dc07 0700 1000 0000 0000 0000 0b00 ................ 00000e0: 1a00 0000 0000 0000 0000 0000 0000 0000 ................ 00000f0: 0000 feff ffff fd68 7377 0000 0000 0100 .......hsw...... 0000100: 0100 0416 10dd 78d9 b300 f7f0 9b20 9bd8 ......x...... .. 0000110: a0c4 5108 c943 d5c9 c64f 47ea 6052 0349 ..Q..C...OG.`R.I 0000120: 23e1 e1ab 6815 e8ef 219e 6d3b aa88 1360 #...h...!.m;...` 0000130: 706b c27b 2e44 9db1 4e89 81ca dd0a 869e pk.{.D..N....... 0000140: 2b61 .6..

Going over some of the data above we have:
Running instance count
Command Name Length (0x4 - includes ending '\x00')
Command Name (cmd )
Parameter length (0xf)
Parameter (/c notepad.exe )
Working Directory Length (0x0)
Working Directory (if Working Directory Length > 0)
User Name Length (0x7)
User Name (SYSTEM)
Comment Length (0x1e)
Comment (if Comment length > 0 - Created by NetScheduleJobAdd. )
User Data / Reserved data
Trigger count
Triggers
- Scheduled date (Jul 16 11:26:00.0 2012)
Job Signature

So I am releasing a job file parser script that can parse out almost all of these items mentioned above. You can find it here. The only things left off are the user/reserved data, some of the trigger data and the job signature sections. I have only tested this on 32 bit *nix systems, so let me know if you hit issues on another platforms. You can see an example output of the above job file below:

$ python jobparser.py -f At5.job Product Info: Windows Vista File Version: 1 UUID: {F77378E3-8B4D-452A-A589-1CC5FA64CFD2} Maximum Run Time: 72:00:00.0 (HH:MM:SS.MS) Exit Code: 0 Status: Properties not set Flags: TASK_FLAG_DONT_START_IF_ON_BATTERIES Date Run: Monday Jul 16 11:26:00.15 2012 Running Instances: 0 Application: cmd Parameters: /c notepad.exe Working Directory: Working Directory not set User: SYSTEM Comment: Created by NetScheduleJobAdd. Scheduled Date: Jul 16 11:26:00.0 2012

Here is some output of job files taken from a Windows 2008 machine:

$ python jobparser.py -d Tasks/ ************************************************************************ File: Tasks/At1.job Product Info: Windows Vista File Version: 1 UUID: {CE14B659-4115-4263-BFAD-A8318428AB68} Maximum Run Time: 72:00:00.0 (HH:MM:SS.MS) Exit Code: 0 Status: Properties not set Flags: TASK_FLAG_DONT_START_IF_ON_BATTERIES Date Run: Task not yet run Running Instances: 0 Application: notepad.exe Working Directory: Working Directory not set User: SYSTEM Comment: Created by NetScheduleJobAdd. Scheduled Date: Jul 17 02:20:00.0 2012 ************************************************************************ ************************************************************************ File: Tasks/At2.job Product Info: Windows Vista File Version: 1 UUID: {46F61E52-4581-49A9-9AD0-2244C206AEEB} Maximum Run Time: 72:00:00.0 (HH:MM:SS.MS) Exit Code: 0 Status: Properties not set Flags: TASK_FLAG_DONT_START_IF_ON_BATTERIES Date Run: Task not yet run Running Instances: 0 Application: notepad.exe Working Directory: Working Directory not set User: SYSTEM Comment: Created by NetScheduleJobAdd. Scheduled Date: Jul 16 14:20:00.0 2012 ************************************************************************

And here are a couple of XP Tasks, notice that one has "Running Instances" value of "1", this was copied when the command was currently running:

************************************************************************ File: Solitaire.job Product Info: Windows XP File Version: 1 UUID: {3824DDBB-A037-4016-B99A-28BD95D429AF} Maximum Run Time: 72:00:00.0 (HH:MM:SS.MS) Exit Code: 0 Status: Task has not run Flags: TASK_FLAG_INTERACTIVE, TASK_FLAG_DELETE_WHEN_DONE Date Run: Monday Aug 13 12:37:00.10 2012 Running Instances: 1 Application: C:\WINDOWS\system32\sol.exe Working Directory: C:\WINDOWS\system32 User: user Comment: Comment not set Scheduled Date: Aug 13 12:37:00.0 2012 ************************************************************************ ************************************************************************ File: Solitaire2.job Product Info: Windows XP File Version: 1 UUID: {3824DDBB-A037-4016-B99A-28BD95D429AF} Maximum Run Time: 72:00:00.0 (HH:MM:SS.MS) Exit Code: 0 Status: Task is ready to run Flags: TASK_FLAG_INTERACTIVE, TASK_FLAG_DELETE_WHEN_DONE Date Run: Monday Aug 13 12:37:00.10 2012 Running Instances: 0 Application: C:\WINDOWS\system32\sol.exe Working Directory: C:\WINDOWS\system32 User: user Comment: Comment not set Scheduled Date: Aug 13 12:37:00.0 2012 ************************************************************************

References:

[1] Windows Forensic Analysis 2nd Ed., Harlan Carvey
[2] .JOB File Format, http://msdn.microsoft.com/en-us/library/cc248285%28v=prot.13%29.aspx
[3] Windows Scheduler (at job) Forensics, http://computer-forensics.sans.org/blog/2009/09/16/windows-scheduler-at-job-forensics

Saturday, April 21, 2012

MBR Parser

With the increase in MBR infectors, I've decided to release a script I wrote that parses the MBR as well as hashes and disassembles the bootcode. I've found that MBR bootcode is pretty stable across systems of the same OS, so this script should allow you to quickly check for any discrepancies on a system.

You of course need Python and Distorm to use this script.

A shortened example output can be seen below:

$ python mbr_parser.py -f mbr.bin Disk signature: 96-80-96-80 Bootcode md5: 4ad444d4e7efce9485a94186c3f4b157 Bootcode Disassembly: 00000000: 33c0 XOR AX, AX 00000002: 8ed0 MOV SS, AX 00000004: bc007c MOV SP, 0x7c00 00000007: fb STI 00000008: 50 PUSH AX 00000009: 07 POP ES 0000000a: 50 PUSH AX 0000000b: 1f POP DS 0000000c: fc CLD 0000000d: 50 PUSH AX 0000000e: be007c MOV SI, 0x7c00 00000011: bf0006 MOV DI, 0x600 00000014: b90002 MOV CX, 0x200 00000017: f3a4 REP MOVSB 00000019: bf1e06 MOV DI, 0x61e 0000001c: 57 PUSH DI 0000001d: cb RETF 0000001e: b441 MOV AH, 0x41 00000020: b280 MOV DL, 0x80 00000022: bbaa55 MOV BX, 0x55aa 00000025: cd13 INT 0x13 00000027: 81fb55aa CMP BX, 0xaa55 0000002b: 7530 JNZ 0x5d 0000002d: f6c101 TEST CL, 0x1 00000030: 742b JZ 0x5d 00000032: be0008 MOV SI, 0x800 00000035: c7041000 MOV WORD [SI], 0x10 00000039: c744020600 MOV WORD [SI+0x2], 0x6 [snip] 000001b2: 0000 ADD [BX+SI], AL 000001b4: 002c ADD [SI], CH 000001b6: 44 INC SP 000001b7: 63 DB 0x63 ===== Partition Table #1 ===== Boot flag: 0x80 (Bootable) Partition type: 0x7 (NTFS) Starting Sector (LBA): 0x3f (63) Starting CHS: Cylinder: 0 Head: 1 Sector: 1 Ending CHS: Cylinder: 520 Head: 254 Sector: 63 Size in sectors: 0x7fb68a (8369802) ===== Partition Table #2 ===== Boot flag: 0x0 Partition type: 0x0 (Empty) Starting Sector (LBA): 0x0 (0) Starting CHS: Cylinder: 0 Head: 0 Sector: 0 Ending CHS: Cylinder: 0 Head: 0 Sector: 0 Size in sectors: 0x0 (0) ===== Partition Table #3 ===== Boot flag: 0x0 Partition type: 0x0 (Empty) Starting Sector (LBA): 0x0 (0) Starting CHS: Cylinder: 0 Head: 0 Sector: 0 Ending CHS: Cylinder: 0 Head: 0 Sector: 0 Size in sectors: 0x0 (0) ===== Partition Table #4 ===== Boot flag: 0x0 Partition type: 0x0 (Empty) Starting Sector (LBA): 0x0 (0) Starting CHS: Cylinder: 0 Head: 0 Sector: 0 Ending CHS: Cylinder: 0 Head: 0 Sector: 0 Size in sectors: 0x0 (0)

Update: Fixed output to 16bit assembly. Thanks for the feedback!

The script can be found here.

Friday, March 23, 2012

Upcoming Cybercrime Studies talk: For a Free Digital Society by Dr. Richard Stallman

Yet another interesting upcoming talk at John Jay College on Tuesday March 27, 2012:


Center for Cybercrime Studies

John Jay College of Criminal Justice

presents

For a Free Digital Society

Dr. Richard Stallman

President

Free Software Foundation

Abstract

Activities directed at ``including'' more people in the use of digital technology are predicated on the assumption that such inclusion is invariably a good thing. It appears so, when judged solely by immediate practical convenience. However, if we also judge in terms of human rights, whether digital inclusion is good or bad depends on what kind of digital world we are to be included in. If we wish to work towards digital inclusion as a goal, it behooves us to make sure it is the good kind.

Richard Stallman launched the free software movement in 1983 and started the development of the GNU operating system (see www.gnu.org) in 1984. GNU is free software: everyone has the freedom to copy it and redistribute it, with or without changes. The GNU/Linux system, basically the GNU operating system with Linux added, is used on tens of millions of computers today. Stallman has received the ACM Grace Hopper Award, a MacArthur Foundation Fellowship, the Electronic Frontier Foundation's Pioneer Award, and the Takeda Award for Social/Economic Betterment, as well as several honorary doctorates.

Date: Tuesday, March 27, 2012
Time: 1:30 PM

Location: L.61 Conference Center (New Building)

John Jay College of Criminal Justice

899 Tenth Avenue

New York, NY

RSVP: Nicole Daniels at 212-237-8920 or email ndaniels@jjay.cuny.edu. For additional information please contact Professor Doug Salane, Director of the Center for Cybercrime Studies, 212-237-8836 or email dsalane@jjay.cuny.edu.

For additional Center for Cybercrime Studies events visit our web site. Go to WWW.JJAY.CUNY.EDU , ACADEMICS, RESEARCH CENTERS and INSTITUTES.


Thursday, March 22, 2012

Differential EnScript

I know I haven't written much in the last few months; I've been busy. Even though I'm writing a blogpost today it's still going to be pretty short... this is because most of what I have to say has already been written up in documentation ahead of time. Today I'm releasing an EnScript that allows you to compare two disk images using various options. The purpose of this EnScript is to find differences on a machine after some event, such as infection, software installation etc. has taken place.

I'm also releasing the source in hopes that others will be able to troubleshoot or expand it themselves as needed. I offer no warranties for this script nor promises that it is beautiful code (in all reality this was written hastily out of necessity), this is "as-is" and has worked well enough for me for my purposes. Unlike most of my stuff, I actually took time to create a GUI for it, however, to make it easier to use. Information on how it works can be found in the documentation (pdf) so I will not cover it here. Hopefully someone out there will find it useful.

Please feel free to leave comments and suggestions here or by email. Here is the Differential.EnScript.

Friday, March 16, 2012

Upcoming Cybercrime Studies talk: Digital Forensic Crime Labs

I just wanted to take the time to announce the following upcoming talk at John Jay College next week:


The Center for Cybercrime Studies

John Jay College of Criminal Justice

Presents


Digital Forensic Crime Labs

Monique Mattei Ferraro

M.S., J.D., CISSP

Technology Forensics, LLC



Digital forensics labs throughout the country were set up and subsidized by United States Department of Justice. Most labs are administered by police or law enforcement agencies. In 2009, the National Academy of Science released “Strengthening Forensic Science in the United States: A Path Forward,” which made several recommendations. Among the recommendations were that criminal labs should be independent of police/law enforcement in order to retain an appearance of objectivity. This talk delves into the tensions between the recommendations and the practice, the ethical implications and current issues affecting digital forensics labs today.



Date: Wednesday, March 21, 2012
Time: 1:30 PM

Location: Haaren Hall, RM 630
899 Tenth Avenue
(10th Avenue and 59th Street)


RSVP: Nicole Daniels at 212-237-8920 or email ndaniels@jjay.cuny.edu. For additional information please contact Professor Doug Salane, Director of the Center for Cybercrime Studies, 212-237-8836 or email dsalane@jjay.cuny.edu.

For additional Center for Cybercrime Studies events visit our Web site (http://www.jjay.cuny.edu/centers/cybercrime_studies/index.php) or go to WWW.JJAY.CUNY.EDU, ACADEMICS, RESEARCH CENTERS and INSTITUTES.

Tuesday, September 13, 2011

Volatility 2.0: Timeliner, RegistryAPI, evtlogs and more

Back in July I gave a talk at OMFW about extracting timeline data from a memory sample using the Volatility framework. Now has come the time to release the plugins that came along with that talk.

In addition to the plugins I have included a whitepaper on how these plugins were created and used. It is released more in hopes that people will see how to use the framework and be able to write their own plugins or extend existing ones.

I have included all these plugins in a zip file:


$ unzip -l timeliner_9-2011.zip
Archive: timeliner_9-2011.zip
Length Date Time Name
-------- ---- ---- ----
14455 09-28-11 14:40 volatility/plugins/timeliner.py
10789 09-27-11 09:24 volatility/plugins/evtlogs.py
147458 09-09-11 11:03 volatility/plugins/malware.py
13559 09-22-11 19:09 volatility/plugins/registryapi.py
8554 09-18-11 21:33 volatility/plugins/getsids.py
40993 09-22-11 16:29 volatility/plugins/getservicesids.py
-------- -------
235808 6 files



  • evtlogs.py: plugin to parse Evt logs from XP/2K3
  • registryapi.py: plugin for routine registry actions
  • getservicesids.py: plugin to collect and calculate service SIDs (used with the new getsids and evtlogs
  • timeliner.py: the timeline creating script that pulls everything together


MHL's malware malware plugins (malware.py) are included only for convenience. You can also download them from his repository and check there for updates.

I would like to thank MHL and AW for their valuable feedback and Bertha M for extensive testing of the timeliner plugins. The links to the paper and plugins are below:

Timeliner Release Documentation (PDF)

timeliner plugins (ZIP)

Note: Any updates to these plugins will appear in my github repository first.

Monday, August 08, 2011

Volatility 2.0 and OMFW

In case you missed it, Volatility 2.0 has been released! Please download it and test it out and let us know if you have any problems via the "issues area" of the Google Code project. We have lots of documentation and for those on Windows who don't like to install Python, there is a standalone executable available in the downloads section. Make sure to check out the FAQ wiki which contains information on what is supported and how to use MHL's malware plugins.

Some OMFW materials have been released:

Moyix's slides (pdf).
MHL's Stuxnet blogpost and slides.
My slides (google docs)

You can help with the development of Volatility by giving us suggestions for plugins, writing documentation or donating malware samples. Check out the FAQ for how to do all of the above.

Saturday, April 30, 2011

Volatility 1.4 UserAssist plugin

From a computer forensics standpoint, userassist keys can provide a lot of information about user activity (see the Harlan's posts for more information).

After looking at Didier Steven's article on userassist keys for Windows 7 from Into the Boxes issue 0x0 and RegRipper, I decided to write up a plugin that would pull out UserAssist keys from all versions of windows for Volatility.

One thing I decided to add was an enumeration of GUIDs to human friendly folder names, which were obtained from here.

The plugin is available in my git repository. Simply download and place into your volatility/plugins directory and you're set.

Update: This plugin is now part of the core Volatility code

Example Output

Below you can see some snippets of output for Windows 7. The fields are pretty self explanatory, though you can read Didier Steven's article for more details. The hex dump is the actual data from which this information was parsed, just so you can verify it yourself.


$ ./vol.py -f win7.vmem --profile=Win7SP0x86 userassist --no-cache
Volatile Systems Volatility Framework 1.4_rc1
----------------------------
Registry: \??\C:\Users\admin\ntuser.dat
Key name: Count
Last updated: 2010-07-06 22:40:25

Subkeys:

Values:
REG_BINARY Microsoft.Windows.GettingStarted :
Count: 14
Focus Count: 21
Time Focused: 0:07:00.500000
Last updated: 2010-03-09 19:49:20

0000 00 00 00 00 0E 00 00 00 15 00 00 00 A0 68 06 00 .............h..
0010 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0020 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0030 00 00 80 BF 00 00 80 BF FF FF FF FF EC FE 7B 9C ..............{.
0040 C1 BF CA 01 00 00 00 00 ........

REG_BINARY UEME_CTLSESSION :
Count: 187
Focus Count: 1205
Time Focused: 6:25:06.216000
Last updated: 1970-01-01 00:00:00

0000 00 00 00 00 BB 00 00 00 B5 04 00 00 B4 90 60 01 ..............`.
0010 10 00 00 00 39 00 00 00 E9 67 28 00 7B 00 44 00 ....9....g(.{.D.
0020 36 00 35 00 32 00 33 00 31 00 42 00 30 00 2D 00 6.5.2.3.1.B.0.-.
0030 42 00 32 00 46 00 31 00 2D 00 34 00 38 00 35 00 B.2.F.1.-.4.8.5.

[snip]

REG_BINARY %windir%\system32\displayswitch.exe :
Count: 13
Focus Count: 19
Time Focused: 0:06:20.500000
Last updated: 2010-03-09 19:49:20

0000 00 00 00 00 0D 00 00 00 13 00 00 00 60 CC 05 00 ............`...
0010 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0020 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0030 00 00 80 BF 00 00 80 BF FF FF FF FF EC FE 7B 9C ..............{.
0040 C1 BF CA 01 00 00 00 00 ........

REG_BINARY %windir%\system32\calc.exe :
Count: 12
Focus Count: 17
Time Focused: 0:05:40.500000
Last updated: 2010-03-09 19:49:20

0000 00 00 00 00 0C 00 00 00 11 00 00 00 20 30 05 00 ............ 0..
0010 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0020 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0030 00 00 80 BF 00 00 80 BF FF FF FF FF EC FE 7B 9C ..............{.
0040 C1 BF CA 01 00 00 00 00 ........
........

REG_BINARY Z:\vmware-share\apps\odbg110\OLLYDBG.EXE :
Count: 11
Focus Count: 266
Time Focused: 1:19:58.045000
Last updated: 2010-03-18 01:56:31

0000 00 00 00 00 0B 00 00 00 0A 01 00 00 69 34 49 00 ............i4I.
0010 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0020 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0030 00 00 80 BF 00 00 80 BF FF FF FF FF 70 3B CB 3A ............p;.:
0040 3E C6 CA 01 00 00 00 00 >.......

REG_BINARY %ProgramFiles%\Microsoft SDKs\Windows\v7.0\Bin\vsstools\vshadow.exe :
Count: 0
Focus Count: 67
Time Focused: 0:06:12.811000
Last updated: 1970-01-01 00:00:00

0000 00 00 00 00 00 00 00 00 43 00 00 00 57 AE 05 00 ........C...W...
0010 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0020 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0030 00 00 80 BF 00 00 80 BF FF FF FF FF 00 00 00 00 ................
0040 00 00 00 00 00 00 00 00 ........

REG_BINARY %windir%\regedit.exe :
Count: 2
Focus Count: 8
Time Focused: 0:03:22.626000
Last updated: 2010-03-17 23:40:36

0000 00 00 00 00 02 00 00 00 08 00 00 00 8E 15 03 00 ................
0010 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0020 00 00 80 BF 00 00 80 BF 00 00 80 BF 00 00 80 BF ................
0030 00 00 80 BF 00 00 80 BF FF FF FF FF 90 3A 93 3E .............:.>
0040 2B C6 CA 01 00 00 00 00 +.......



Here you can see an example of output from Windows XP:


$ ./vol.py -f XPSP3.vmem --profile=WinXPSP3x86 userassist --no-cache
Volatile Systems Volatility Framework 1.4_rc1
----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\Administrator\NTUSER.DAT
Key name: Count
Last updated: 2010-11-24 16:35:34

Subkeys:

Values:
REG_BINARY UEME_CTLSESSION :
0000 91 52 5B 0E 1F 00 00 00 .R[.....

REG_BINARY UEME_CTLCUACount:ctor :
ID: 1
Count: 2
Last updated: 1970-01-01 00:00:00

0000 01 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 ................

REG_BINARY UEME_RUNPATH :
ID: 31
Count: 589
Last updated: 2010-11-24 16:30:49

0000 1F 00 00 00 52 02 00 00 A0 91 09 F4 F4 8B CB 01 ....R...........

REG_BINARY UEME_RUNPATH:D:\SETUP.EXE :
ID: 30
Count: 6
Last updated: 2010-09-20 15:02:47

0000 1E 00 00 00 0B 00 00 00 E0 85 39 E3 D4 58 CB 01 ..........9..X..

REG_BINARY UEME_RUNPIDL :
ID: 31
Count: 124
Last updated: 2010-11-24 14:19:29

0000 1F 00 00 00 81 00 00 00 50 78 79 9B E2 8B CB 01 ........Pxy.....

REG_BINARY UEME_RUNPIDL:%csidl2%\Microsoft Visual Basic 6.0 :
ID: 1
Count: 2
Last updated: 2009-05-12 02:28:10

0000 01 00 00 00 02 00 00 00 B0 1E DB 4A A9 D2 C9 01 ...........J....

REG_BINARY UEME_RUNPATH:C:\Program Files\Microsoft Visual Studio\VB98\VB6.EXE :
ID: 1
Count: 1
Last updated: 2009-05-12 02:28:10

0000 01 00 00 00 06 00 00 00 50 62 FC 4A A9 D2 C9 01 ........Pb.J....

REG_BINARY UEME_RUNPIDL:C:\Documents and Settings\All Users\Start Menu\Windows Update.lnk :
ID: 1
Count: 1
Last updated: 2009-05-12 02:28:36

0000 01 00 00 00 06 00 00 00 F0 D0 A1 5A A9 D2 C9 01 ...........Z....

REG_BINARY UEME_RUNPATH:C:\WINDOWS\system32\wupdmgr.exe :
ID: 31
Count: 2
Last updated: 2010-11-24 14:50:05




Shoutz to ikelos for helping me optimize this :-)


References:

Into the Boxes issue 0x0 http://intotheboxes.wordpress.com/2010/01/01/into-the-boxes-issue-0x0/

RegRipper http://regripper.wordpress.com/

Tuesday, April 05, 2011

What's the Difference? [A Brief Volatility 1.4 Plugin Tutorial]

So if you come to this blog, you've most likely heard of Volatility. You're probably also a user... maybe you've written some plugins, maybe not. Most people tend to fall into the latter category, though they may be be power users. Today I thought I'd go over a few things that might make it easier for people to start writing their own plugins for simple useful things, because even though the Volatility 1.4 isn't officially released doesn't mean that you can't enjoy it in the meantime :-)

A common way that people start their analysis is to look at differences in output of plugins that represent what the OS knows about (pslist/modules/connections/sockets etc) vs scanning for possible hidden/unlinked items. Examples of this can be seen in Jesse Kornblum's pstotal, Command Line Kung Fu's Making a Difference and MHL's psxview (which actually is very useful).

If you look at some of these examples, you might think to yourself that it's difficult to write a plugin to get a process difference, but it's really not! You can use inheritance to make your life easier.

PSList vs. PSScan2

Below is a complete plugin for printing out the difference between pslist and psscan2, which we will go over in detail.


1 import volatility.plugins.taskmods as taskmods
2 import volatility.plugins.filescan as filescan
3
4 class PSDiff(filescan.PSScan2):
5 """Print processes found in psscan2, but not in pslist"""
6
7 def __init__(self, config, *args):
8 filescan.PSScan2.__init__(self, config, *args)
9
10 def calculate(self):
11 pslist = taskmods.PSList(self._config).calculate()
12 pids = []
13 for task in pslist:
14 pids.append(task.UniqueProcessId.v())
15
16 psscan = filescan.PSScan2.calculate(self)
17 for task in psscan:
18 if task.UniqueProcessId.v() not in pids:
19 yield task



First you need to import the plugin files that contain the classes you want to inherit into your plugin file. In this case PSList is defined in volatility/plugins/taskmods.py and PSScan2 is defined in volatility/plugins/filescan.py. You can see the import in lines (1-2). Now you have to define the class for your plugin (line 4). Try to give it a meaningful name for what it does, here we will name it PSDiff. Classes should be named in CamelCase. In the parentheses after the class name we will specify which classes we want to inherit. Since we want processes that are only found in psscan2 output, we will use the render_text output function of psscan2 without having to redefine it. Therefore, since we want for our new class to be more like psscan2, we choose this class to inherit. We specify it as filescan.PSScan2 because we had imported the plugin file as "filescan" and the class for pssscan2 is named "PSScan2".

Next on line 5, we add a description of what this plugin does as a multiline comment. Whatever you type here will appear in the help function when you run python vol.py [plugin] -h, or just python vol.py -h.

Lines 7-8 are the initialization and options section of the plugin. We are not adding any command line options to this plugin and are just initializing the PSScan2 class that we inherited.

Lines 10-19 define the calculate part of our plugin, or what we want the plugin to do. In this case we only want to print out processes that are found by psscan2 and not pslist, so should decide how to do that... Since processes should have unique process IDs (PIDs) to specify unique processes. So PIDs that are found in psscan2, but not in pslist will be printed.

Let's walk through the calculate function. First we gather all processes that pslist knows about (line 11). We call the taskmods.PSList class, give it our configuration (self._config) so that it can know what profile to use and call its calculate function, which returns eprocess objects (and really is just DllList's calculate function, but we'll ignore that for now). In line 12, we define an empty list to store PIDs from pslist in order to compare to psscan2's PIDs. Lines 13-14 collect all the PIDs pslist knows about.

Now lines 16-19 repeat the process for psscan2 except that instead of collecting PIDs into a list, we check to see if the PID we've encountered is already in the list of PIDs from pslist. If it isn't, then we yield the task that contains that PID so that it will be caught by psscan2's render_text function and output onto the screen.

The output? Here you can see what it looks like on a Windows 7 image:


$ python vol.py -f win7.dd --profile=Win7SP0x86 psdiff
Volatile Systems Volatility Framework 1.4_rc1
Offset Name PID PPID PDB Time created Time exited
---------- ---------------- ------ ------ ---------- ------------------------ ------------------------
0x3eac6030 SearchProtocol 2448 1168 0x3ecf15c0 2010-06-16 23:30:52 2010-06-16 23:33:14
0x3eb10030 SearchFilterHo 1812 1168 0x3ecf1480 2010-06-16 23:31:02 2010-06-16 23:33:14
0x3f0576a0 svchost.exe 2836 508 0x3ecf15c0 2010-06-16 17:02:34 2010-06-16 17:08:43
0x3faa66e8 dllhost.exe 948 628 0x3ecf1540 2010-06-16 23:32:15 2010-06-16 23:32:21
0x3fbcf920 dllhost.exe 3776 628 0x3ecf11e0 2010-06-16 23:32:09 2010-06-16 23:32:15



The only difference in this case seems to be exited processes.

Here you can see a run on Moyix's ds_fuzz image:


$ python vol.py -f ds_fuzz_hidden_proc.img psdiff
Volatile Systems Volatility Framework 1.4_rc1
Offset Name PID PPID PDB Time created Time exited
---------- ---------------- ------ ------ ---------- ------------------------ ------------------------
0x0181b748 alg.exe 992 660 0x08140260 2008-11-15 23:43:25
0x0185dda0 cmd.exe 940 1516 0x081401a0 2008-11-26 07:43:39 2008-11-26 07:45:49
0x018af020 taskmgr.exe 808 620 0x08140280 2008-11-26 07:45:22 2008-11-26 07:45:40
0x019456e8 csrss.exe 592 360 0x08140040 2008-11-15 23:42:56
0x01946020 svchost.exe 828 660 0x081400c0 2008-11-15 23:42:57
0x019467e0 services.exe 660 616 0x08140080 2008-11-15 23:42:56
0x0194f658 svchost.exe 1016 660 0x08140100 2008-11-15 23:42:57
0x019533c8 svchost.exe 924 660 0x081400e0 2008-11-15 23:42:57



Suppose you are concerned that a PID could have been overwritten somehow (DKOM). You could rewrite the plugin to use _EPROCESS offsets instead of PIDs for a check:


1 import volatility.plugins.taskmods as taskmods
2 import volatility.plugins.filescan as filescan
3
4 class PSDiff(filescan.PSScan2):
5 """Print processes found in psscan2, but not in pslist"""
6
7 def __init__(self, config, *args):
8 filescan.PSScan2.__init__(self, config, *args)
9
10 def calculate(self):
11 pslist = taskmods.PSList(self._config).calculate()
12 offsets = []
13 for task in pslist:
14 offsets.append(task.obj_vm.vtop(task.obj_offset))
15
16 psscan = filescan.PSScan2.calculate(self)
17 for task in psscan:
18 if task.obj_offset not in offsets:
19 yield task



The changes are in lines 12, 14 and 18. The idea is the same as our PID plugin above, only with offsets. So we rename our list to offsets to make it clearer (line 12). We append the physical address of where our _EPROCESS object is found (line 14), this is because scanners like psscan2 only output physical addresses so we want to make sure that the addresses from pslist are the same. In line 18 we check to see if our _EPROCESS object offset found by psscan2 is already found by pslist and if not we yield it so that its information will be printed. Output is the same as what we saw above for our two test images.

Conclusion

So there you have it. You can use the same idea for comparing output from modules and modscan, connections and connscan2, sockets and sockscan or files and filescan etc... (I'm leaving this as an exercise for the reader ;-)).

You can check also out the references below for further reading on Python and Volatility. Make sure to read the Volatility Plugin Writers Guide that Mike Auty and Scudette put together.

Update: I just noticed that MHL also gave the Command Line Kung Fu crew a psdiff example. You can check out another way of doing things over there.

Update 2: I just updated the code to work with the current changes in the svn (we moved psscan2 to filescan).

References

Google Python Class http://code.google.com/edu/languages/google-python-class/

Python 2.7 Tutorial http://docs.python.org/tutorial/

Volatility Plugin Writers Guide http://code.google.com/p/volatility/wiki/PluginWritersGuide

Monday, April 04, 2011

OT: Maze Generator Update

Since my QC (venus) website is no longer active, I thought I'd put the files for a maze generator some place where they can be accessed, especially since I have received emails about it... Here is the original information that was on venus before it disappeared:

Maze Generator Using Disjoint Sets

I recently went through several files of mine that had been stored away from my undergrad days. So I thought I might share them. Someone might like them. I have not changed any of the code since it was first written. I have only changed the formatting of a couple of files to make them easier to read and modified the comment header slightly (also for readability). Everything is well commented, which was my style at the time :-) Hopefully I have not erased anything important as I was doing these modifications, but I have no patience to test it at the moment. Oh, and I added a GPL for my code only, just in case (though no one will really want this... :-P )

This particular project is from Prof Stewart Weiss' CS 335 class, and consisted of writing a program that would generate mazes. It was compiled under Visual Studio 6.0 C++. We had studied Disjoint Sets in our class and were allowed to use code from Mark Allen Weiss' book from which we were studying. In addition to printing out to a text file, for extra credit we could output a graphical representation of the maze. For this I used code from Owen L. Astrachan's book which I think is from CMU Graphics. Two example outputs can be seen below:







The idea is fairly simple. The maze is broken up into cells. We will use the idea of disjoint sets: in the beginning each cell is in its own set. Cells are randomly chosen to remove a wall (and one of the four walls is also randomly chosen) and as the wall is removed, the cell and its new neighbor are then placed in the same set. You keep doing this until all cells are within the first (entry) cell's set. At this point you have a maze.

You should make sure that once a cell is in the main (entry cell's) set, it should
never be picked again to remove wall. You also have to be careful not
to remove the outer border walls, thus creating alternate exits :-)

The disjoint sets class was modified from the original given in the book. There was a problem with the find() function so it was changed. Also, I added extra functions to make it fit with the maze class. I also created a vector of cells for the maze (see Cell class and Maze class below). I would have done things differently if I were doing writing this now, but this was in the beginning of my programming experience.



I created a Cell class to represent each cell of the maze. This way I could control the walls of the cells and keep track of which walls were still up or down when I printed out the maze.



Next I wrote a Maze class to keep track of all of the cells. At first I thought to implement this using a 2-dimensional array, but ultimately decided to use a linear vector (defined in DisjSets) folded onto itself. There is also a list used to contain all cells of the maze. This is not the maze itself, but rather the cells that have not yet been placed into the main set in order to create a maze. I did this to cut down on run time because you do not want to remove walls from cells that have already become part of the main set and randomly picking cells most likely leads to picking cells that have already been chosen (especially towards the end). So keeping a pool of possible choices was the only logical thing to do to cut down on run time.



Now for the main part of the program. At the time I was obsessed
with making the main() function as small as possible:


int main(){
string resp;

while(true){

getMazeInfo();

cout<<"To quit press 'q', otherwise press a key"<<endl;
cin>>resp;

if(resp=="q")
break;

}//end while

return 0;


Granted it could have been smaller... :-) It basically loops forever creating mazes of whatever size (I think 50x60 is the max) is requested and stops when the user wants to leave. The code is NOT perfect. Just glancing over ASSN3Main.cpp, I see a buffer overflow error could occur in the getMazeInfo() function. Plus there were better ways now of dealing with the graphics. (Yes I COULD fix it, but then I would find other things and before you know it this would explode into a full time project...Ok. Maybe I'm exaggerating). Perhaps some day when I have more time I will rewrite this little application. It's kinda fun to create mazes...



I am releasing all of the code in gzip files as well as a precompiled executable. You can use 7zip to open the files. If you use the executable, you will see a message box saying something about how this was compiled with the student version and can't be used as commercial software or some such. Just push Ok and you're set. After you input the dimensions and the name of the output file to which you would like the maze saved, a graphical window will pop up. Click it with the mouse and the maze should display. You have to push ESC to get out of the graphical maze window.


Hopefully I have managed to include all of the code that is needed. Let me know if something is missing.

Sunday, April 03, 2011

Windows Registry Paths (_CMHIVE)

A little while ago I helped get the registry stuff working on images other than XP for Volatility 1.4. There are some differences in how the paths/names of the hives are stored, that I thought I might go over here.

In XP we have the following structure for a registry hive:


'_CMHIVE' : [ 0x49c, {
'Hive' : [ 0x0, ['_HHIVE']],
'FileHandles' : [ 0x210, ['array', 3, ['pointer', ['void']]]],
'NotifyList' : [ 0x21c, ['_LIST_ENTRY']],
'HiveList' : [ 0x224, ['_LIST_ENTRY']],
'HiveLock' : [ 0x22c, ['pointer', ['_FAST_MUTEX']]],
'ViewLock' : [ 0x230, ['pointer', ['_FAST_MUTEX']]],
'LRUViewListHead' : [ 0x234, ['_LIST_ENTRY']],
'PinViewListHead' : [ 0x23c, ['_LIST_ENTRY']],
'FileObject' : [ 0x244, ['pointer', ['_FILE_OBJECT']]],
'FileFullPath' : [ 0x248, ['_UNICODE_STRING']],
'FileUserName' : [ 0x250, ['_UNICODE_STRING']],
'MappedViews' : [ 0x258, ['unsigned short']],
'PinnedViews' : [ 0x25a, ['unsigned short']],
'UseCount' : [ 0x25c, ['unsigned long']],
'SecurityCount' : [ 0x260, ['unsigned long']],
'SecurityCacheSize' : [ 0x264, ['unsigned long']],
'SecurityHitHint' : [ 0x268, ['long']],
'SecurityCache' : [ 0x26c, ['pointer', ['_CM_KEY_SECURITY_CACHE_ENTRY']]],
'SecurityHash' : [ 0x270, ['array', 64, ['_LIST_ENTRY']]],
'UnloadEvent' : [ 0x470, ['pointer', ['_KEVENT']]],
'RootKcb' : [ 0x474, ['pointer', ['_CM_KEY_CONTROL_BLOCK']]],
'Frozen' : [ 0x478, ['unsigned char']],
'UnloadWorkItem' : [ 0x47c, ['pointer', ['_WORK_QUEUE_ITEM']]],
'GrowOnlyMode' : [ 0x480, ['unsigned char']],
'GrowOffset' : [ 0x484, ['unsigned long']],
'KcbConvertListHead' : [ 0x488, ['_LIST_ENTRY']],
'KnodeConvertListHead' : [ 0x490, ['_LIST_ENTRY']],
'CellRemapArray' : [ 0x498, ['pointer', ['_CM_CELL_REMAP_BLOCK']]],
} ],


When running the hivelist command from Volatility on an XP or Windows 2003 image, the name of the hive is obtained from the FileFullPath entry above. This is more of a generic name prefixed with "\Device\HarddiskVolume1". There is also a FileUserName entry in _CMHIVE, which may contain the actual path to the hive on disk. Here are a few examples:


************************************************************************
FileFullPath: \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY
FileUserName: \SystemRoot\System32\Config\SECURITY
************************************************************************
FileFullPath: \Device\HarddiskVolume1\WINDOWS\system32\config\software
FileUserName: \SystemRoot\System32\Config\SOFTWARE
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
FileUserName: \??\C:\Documents and Settings\NetworkService\ntuser.dat
************************************************************************


As I said, we get the same results for Windows 2003.

Starting with Windows Vista, we have an extra member in _CMHIVE, named HiveRootPath which contains another registry name starting either with (\REGISTRY\MACHINE or \REGISTRY\USER). Here we can see output from a modified hivelist plugin, each hive is separated by asterisks:


FileFullPath:
FileUserName:
HiveRootPath: \REGISTRY\MACHINE\HARDWARE
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\System32\SMI\Store\Machine\SCHEMA.DAT
FileUserName: \??\C:\Windows\System32\SMI\Store\Machine\SCHEMA.DAT
HiveRootPath: \registry\machine\Schema
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\System32\config\SOFTWARE
FileUserName: \SystemRoot\System32\Config\SOFTWARE
HiveRootPath: \REGISTRY\MACHINE\SOFTWARE
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\System32\config\DEFAULT
FileUserName: \SystemRoot\System32\Config\DEFAULT
HiveRootPath: \REGISTRY\USER\.DEFAULT
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\System32\config\SAM
FileUserName: \SystemRoot\System32\Config\SAM
HiveRootPath: \REGISTRY\MACHINE\SAM
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\System32\config\SECURITY
FileUserName: \SystemRoot\System32\Config\SECURITY
HiveRootPath: \REGISTRY\MACHINE\SECURITY
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\System32\config\COMPONENTS
FileUserName: \SystemRoot\System32\Config\COMPONENTS
HiveRootPath: \REGISTRY\MACHINE\COMPONENTS
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Boot\BCD
FileUserName: \Device\HarddiskVolume1\Boot\BCD
HiveRootPath: \REGISTRY\MACHINE\BCD00000000
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\ServiceProfiles\NetworkService\NTUSER.DAT
FileUserName:
HiveRootPath: \REGISTRY\USER\S-1-5-20
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Windows\ServiceProfiles\LocalService\NTUSER.DAT
FileUserName: \??\C:\Windows\ServiceProfiles\LocalService\ntuser.dat
HiveRootPath: \REGISTRY\USER\S-1-5-19
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Users\user\NTUSER.DAT
FileUserName: \??\C:\Users\user\ntuser.dat
HiveRootPath: \Registry\User\S-1-5-21-3861645159-1226237480-2911178601-1000
************************************************************************
FileFullPath: \Device\HarddiskVolume1\Users\user\AppData\Local\Microsoft\Windows\UsrClass.dat
FileUserName: \??\C:\Users\user\AppData\Local\Microsoft\Windows\UsrClass.dat
HiveRootPath: \Registry\User\S-1-5-21-3861645159-1226237480-2911178601-1000_Classes
************************************************************************
FileFullPath:
FileUserName:
HiveRootPath: \REGISTRY\MACHINE\SYSTEM
************************************************************************



You can see that there are a couple of registries that only have HiveRootPath populated (\REGISTRY\MACHINE\SYSTEM and \REGISTRY\MACHINE\HARDWARE). \REGISTRY\MACHINE\HARDWARE is a volatile hive that contains hardware information populated during bootup[1], we will explore this key a bit later... We get the same output for all service packs of Vista as well as Windows 2008 (which is closely related to Vista SP1/2).

For Windows 7 we get slightly different results. Even though FileFullPath is defined in _CMHIVE for Windows 7, it does not appear to be used at all:


FileFullPath:
FileUserName: \SystemRoot\System32\Config\SECURITY
HiveRootPath: \REGISTRY\MACHINE\SECURITY
************************************************************************
FileFullPath:
FileUserName: \??\C:\System Volume Information\Syscache.hve
HiveRootPath: \REGISTRY\A\{43bcec53-795b-11df-9d3d-000c29bf81c3}
************************************************************************
FileFullPath:
FileUserName:
HiveRootPath: \REGISTRY\MACHINE\SYSTEM
************************************************************************
FileFullPath:
FileUserName:
HiveRootPath: \REGISTRY\MACHINE\HARDWARE
************************************************************************
FileFullPath:
FileUserName: \SystemRoot\System32\Config\DEFAULT
HiveRootPath: \REGISTRY\USER\.DEFAULT
************************************************************************
FileFullPath:
FileUserName:
HiveRootPath: \REGISTRY\USER\S-1-5-20
************************************************************************
FileFullPath:
FileUserName: \??\C:\Windows\ServiceProfiles\LocalService\NTUSER.DAT
HiveRootPath: \REGISTRY\USER\S-1-5-19
************************************************************************
FileFullPath:
FileUserName: \Device\HarddiskVolume1\Boot\BCD
HiveRootPath: \REGISTRY\MACHINE\BCD00000000
************************************************************************
FileFullPath:
FileUserName: \SystemRoot\System32\Config\SOFTWARE
HiveRootPath: \REGISTRY\MACHINE\SOFTWARE
************************************************************************
FileFullPath:
FileUserName: \??\C:\Users\user\ntuser.dat
HiveRootPath: \Registry\User\S-1-5-21-1665533257-296859758-874228692-1000
************************************************************************
FileFullPath:
FileUserName: \??\C:\Users\user\AppData\Local\Microsoft\Windows\UsrClass.dat
HiveRootPath: \Registry\User\S-1-5-21-1665533257-296859758-874228692-1000_Classes
************************************************************************
FileFullPath:
FileUserName: \SystemRoot\System32\Config\SAM
HiveRootPath: \REGISTRY\MACHINE\SAM
************************************************************************



Therefore in Windows 7 output of hivelist, you will see FileUserName paths when they are defined or HiveRootPath paths if they are not:


Virtual Physical Name
0x963e39d0 0x1d41a9d0 \SystemRoot\System32\Config\SECURITY
0xa057a7a8 0x3518e7a8 \??\C:\System Volume Information\Syscache.hve
0x82ba6140 0x02ba6140 [no name]
0x87a0c008 0x28027008 [no name]
0x87a1c008 0x27fb5008 \REGISTRY\MACHINE\SYSTEM
0x87a429d0 0x27f9d9d0 \REGISTRY\MACHINE\HARDWARE
0x87abc898 0x1fd97898 \SystemRoot\System32\Config\DEFAULT
0x8849e008 0x27dc0008 \REGISTRY\USER\S-1-5-20
0x88521008 0x1be07008 \??\C:\Windows\ServiceProfiles\LocalService\NTUSER.DAT
0x8bb309d0 0x25bac9d0 \Device\HarddiskVolume1\Boot\BCD
0x8bb328d8 0x25bb58d8 \SystemRoot\System32\Config\SOFTWARE
0x91a9a9d0 0x1787c9d0 \??\C:\Users\user\ntuser.dat
0x91f2d9d0 0x13b949d0 \??\C:\Users\user\AppData\Local\Microsoft\Windows\UsrClass.dat
0x963bf008 0x1fa36008 \SystemRoot\System32\Config\SAM



Getting Registry Paths from the SYSTEM Registry

You can also obtain a list of registry files were loaded by the system by checking the "SYSTEM\CurrentControlSet\Control\Hivelist" key[1]:


$ python vol.py -f VistaSP2x86.dmp --profile=VistaSP2x86 printkey -K 'controlset001\control\hivelist'
Volatile Systems Volatility Framework 1.4_rc1
Legend: (S) = Stable (V) = Volatile

----------------------------
Registry: \REGISTRY\MACHINE\SYSTEM
Key name: hivelist (V)
Last updated: 2010-11-30 18:05:20

Subkeys:

Values:
REG_SZ \REGISTRY\MACHINE\HARDWARE : (V)
REG_SZ \REGISTRY\MACHINE\SECURITY : (V) \Device\HarddiskVolume1\Windows\System32\config\SECURITY
REG_SZ \REGISTRY\MACHINE\SOFTWARE : (V) \Device\HarddiskVolume1\Windows\System32\config\SOFTWARE
REG_SZ \REGISTRY\MACHINE\SYSTEM : (V) \Device\HarddiskVolume1\Windows\System32\config\SYSTEM
REG_SZ \REGISTRY\USER\.DEFAULT : (V) \Device\HarddiskVolume1\Windows\System32\config\DEFAULT
REG_SZ \REGISTRY\MACHINE\SAM : (V) \Device\HarddiskVolume1\Windows\System32\config\SAM
REG_SZ \REGISTRY\MACHINE\COMPONENTS : (V) \Device\HarddiskVolume1\Windows\System32\config\COMPONENTS
REG_SZ \REGISTRY\MACHINE\BCD00000000 : (V) \Device\HarddiskVolume1\Boot\BCD
REG_SZ \REGISTRY\USER\S-1-5-20 : (V) \Device\HarddiskVolume1\Windows\ServiceProfiles\NetworkService\NTUSER.DAT
REG_SZ \REGISTRY\USER\S-1-5-19 : (V) \Device\HarddiskVolume1\Windows\ServiceProfiles\LocalService\NTUSER.DAT
REG_SZ \registry\machine\Schema : (V) \Device\HarddiskVolume1\Windows\System32\SMI\Store\Machine\SCHEMA.DAT
REG_SZ \Registry\User\S-1-5-21-3861645159-1226237480-2911178601-1000 : (V) \Device\HarddiskVolume1\Users\user\NTUSER.DAT
REG_SZ \Registry\User\S-1-5-21-3861645159-1226237480-2911178601-1000_Classes : (V) \Device\HarddiskVolume1\Users\user\AppData\Local\Microsoft\Windows\UsrClass.dat



References

[1] Mark Russinovich, David Solomon and Alex Ionescu Windows Internals 5th Edition

[2] Moyix, Enumerating Registry Hives

Wednesday, March 30, 2011

Update: Volatility printkey Plugin

You don't have to use the printkey plugin I released to get bruteforce action. It has been incorporated into the Volatility SVN (thanks to Mike Auty :-)).

So by default you don't have to issue an offset anymore:


$ python vol.py -f ds_fuzz_hidden_proc.img printkey -K 'ControlSet001\Control\ComputerName\ComputerName'
Volatile Systems Volatility Framework 1.4_rc1
Legend: (S) = Stable (V) = Volatile

----------------------------
Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\system
Key name: ComputerName (S)
Last updated: 2008-10-21 17:48:29

Subkeys:

Values:
REG_SZ ComputerName : (S) GINEVRA



And keys from multiple hives will also appear with a separator:


$ python vol.py -f ds_fuzz_hidden_proc.img printkey -K 'Software\Microsoft\Windows NT\CurrentVersion\Winlogon'
Volatile Systems Volatility Framework 1.4_rc1
Legend: (S) = Stable (V) = Volatile

----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
Key name: Winlogon (S)
Last updated: 2008-11-26 07:38:23

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600
----------------------------
Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\default
Key name: Winlogon (S)
Last updated: 2008-11-26 07:39:40

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600
----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
Key name: Winlogon (S)
Last updated: 2008-11-26 07:38:53

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600
----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\moyix\NTUSER.DAT
Key name: Winlogon (S)
Last updated: 2008-09-19 20:29:52

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600

Friday, March 25, 2011

Modified Volatility printkey Plugin

As a lot of you already know, Volatility has some pretty cool registry plugins. You can use hivescan to look for registry hives (CMHIVE), hivelist to locate virtual and physical addresses of registry hives and printkey to print out keys for a specified hive, whose virtual address is found from hivelist.

In Volatility 1.3, you had to specify CMHIVE offset (obtained from hivescan) for hivelist in order to get the virtual address for a hive to use with printkey. In Volatility 1.4, hivelist inherits hivescan and obtains the CMHIVE offsets removing one extra step and making it easier for the user.

We still have to provide a virtual address (obtained by hivelist) to printkey in order to print a key from a particular registry. Suppose you don't know which registry contains the key, or you are a little clumsy about which offset you gave printkey, or maybe you want the same key from multiple hives (like all users for example). Well, I know I've personally had some of these issues and I'm sure others have as well ;-)

Recently I modified printkey to include a "brute-force" option to try to obtain a particular key from all hives and thought I'd share this in case anyone else might find it useful. The idea works similar to how hivelist was written to inherit from hivescan; printkey inherits hivelist and can obtain the offsets for all hives if run in brute-force mode. It also retains the previous usage so you can specify an offset.

Let's see some examples. So suppose we want to get the computer name from this image. How do we get that? So normally you have to get a list of registry hives:


$ python vol.py -f ds_fuzz_hidden_proc.img hivelist
Volatile Systems Volatility Framework 1.4_rc1
Virtual Physical Name
0xe1ada008 0x0b46c008 \Device\HarddiskVolume1\Documents and Settings\moyix\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1ad0880 0x0b339880 \Device\HarddiskVolume1\Documents and Settings\moyix\NTUSER.DAT
0xe1ac09e8 0x0b21b9e8 \Device\HarddiskVolume1\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1a9f008 0x0b28b008 \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
0xe1797a60 0x0951da60 \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1790820 0x0960f820 \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
0xe1534820 0x032a9820 \Device\HarddiskVolume1\WINDOWS\system32\config\software
0xe1536820 0x032ab820 \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY
0xe14771f8 0x07fc91f8 \Device\HarddiskVolume1\WINDOWS\system32\config\default
0xe1482008 0x07f93008 \Device\HarddiskVolume1\WINDOWS\system32\config\SAM
0xe13725b8 0x0241d5b8 [no name]
0xe1018388 0x02200388 \Device\HarddiskVolume1\WINDOWS\system32\config\system
0xe1008b60 0x020c4b60 [no name]
0x80670a8c 0x00670a8c [no name]


From the SYSTEM registry we need this key: ControlSet001\Control\ComputerName\ComputerName We find the virtual offset and specify that in the commandline along with the key:


$ python vol.py -f ds_fuzz_hidden_proc.img printkey -o 0xe1018388 -K 'ControlSet001\Control\ComputerName\ComputerName'
Volatile Systems Volatility Framework 1.4_rc1
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\system
Key name: ComputerName (S)
Last updated: 2008-10-21 17:48:29

Subkeys:

Values:
REG_SZ ComputerName : (S) GINEVRA



Nice. Ok, suppose you didn't know you needed to get this information from the SYSTEM registry. You can use the brute-force option (-b):

$ python vol.py -f ds_fuzz_hidden_proc.img printkey -b -K 'ControlSet001\Control\ComputerName\ComputerName'
Volatile Systems Volatility Framework 1.4_rc1
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of S-1-5-21-725345543-1292428093-2147272213-1003_Classes
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of $$$PROTO.HIV
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of S-1-5-19_Classes
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of $$$PROTO.HIV
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of S-1-5-20_Classes
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of $$$PROTO.HIV
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of $$$PROTO.HIV
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of SECURITY
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of $$$PROTO.HIV
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of SAM
WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of HARDWARE
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\system
Key name: ComputerName (S)
Last updated: 2008-10-21 17:48:29

Subkeys:

Values:
REG_SZ ComputerName : (S) GINEVRA

WARNING : volatility.win32.rawreg: Couldn't find subkey ControlSet001 of REGISTRY



Hrmmmm.... notice that you get a lot of debug warnings in addition to the correct output for this key. This is because normally you would want to know if the key is not found and as each hive is queried for the key, failed attempts appear in output. However in this case, we know it's not going to be found in all of the registries, so we don't care about these warnings. You could comment out the piece of code in volatility/win32/rawreg.py that gives this warning, or you could use another plugin supplied by Mike Auty called disablewarnings.py This plugin (disablewarnings.py) is located in the "contrib/plugins" folder when you first download Volatility from the Google SVN. In order to use it, you must first move it to your plugins directory. So from the Volatility root folder do the following:


$ mv contrib/plugins/disablewarnings.py volatility/plugins


Now we can run the printkey plugin with brute-force option and disable debug statements with two extra switches: -d -W:


$ python vol.py -f ds_fuzz_hidden_proc.img printkey -b -d -W -K 'ControlSet001\Control\ComputerName\ComputerName'
Volatile Systems Volatility Framework 1.4_rc1
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\system
Key name: ComputerName (S)
Last updated: 2008-10-21 17:48:29

Subkeys:

Values:
REG_SZ ComputerName : (S) GINEVRA



Want to see output from multiple hives? Let's look at the Software\Microsoft\Windows NT\CurrentVersion\WinLogon key from user hives:


$ python vol.py -f ds_fuzz_hidden_proc.img printkey -K 'Software\Microsoft\Windows NT\CurrentVersion\WinLogon' -b -d -W
Volatile Systems Volatility Framework 1.4_rc1
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\Documents and Settings\moyix\NTUSER.DAT
Key name: Winlogon (S)
Last updated: 2008-09-19 20:29:52

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
Key name: Winlogon (S)
Last updated: 2008-11-26 07:38:53

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
Key name: Winlogon (S)
Last updated: 2008-11-26 07:38:23

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600
Legend: (S) = Stable (V) = Volatile

Registry: \Device\HarddiskVolume1\WINDOWS\system32\config\default
Key name: Winlogon (S)
Last updated: 2008-11-26 07:39:40

Subkeys:

Values:
REG_SZ ParseAutoexec : (S) 1
REG_SZ ExcludeProfileDirs : (S) Local Settings;Temporary Internet Files;History;Temp
REG_DWORD BuildNumber : (S) 2600



Notice that the output is also slightly different, since printkey specifies which hive it got the information from (Registry: [Path])

Update: this modification is now in the SVN see here.

Tuesday, March 22, 2011

John Jay Center for Cybercrime Studies Talk: 3/29/11 2PM

There's an upcoming talk at The Center for Cybercrime Studies, John Jay College of Criminal Justice next week (Tuesday March 29th, 2011 2:00 PM) that may interest some of you in the NYC area:


Cyber Criminals: Who are they? Why are they successful? How do we respond?

Kim Peretti

Director, Forensic Services Practices
PricewaterhouseCoopers LLP

Formerly Senior Counsel
US Dept. of Justice, Criminal Division
Computer Crime and Intellectual Property Section

This session will walk through recent prosecutions of sophisticated hacking rings in order to provide insight into the individuals behind these types of crimes and why they are successful. This presentation will also discuss the emerging area of cyber forensics and methods by which entities can better prevent, detect, and respond to cyber attacks on their systems.


Events will take place at
John Jay College of Criminal Justice
899 Tenth Avenue
Room 630T, Haaren Hall

(between 58th and 59th Streets.)
RSVP to Nicole Daniels (ndaniels@jjay.cuny.edu: 212.237.8920).

Volatility 1.4 get_plugins Script

For those who can't wait for the official release of 1.4: I've updated the Volatility Full Dev Installation Wiki to include installation on Linux.

In case you want to automate installation you can use the new get_plugins script. I've only tested it on Mac OSX and Ubuntu, but it should still install dependencies and Volatility 1.4 on other Linux distributions (provided that you have your supporting libraries like libpcre installed already). Feel free to look at the code before running however :-)

Caveat: There is still an issue with the Distorm3 library on Mac OSX and you'll have to compile and install that one manually.

Wednesday, January 05, 2011

NYC4SEC Meeting 1/19/2011

There is an NYC4SEC meeting this month on 1/19/2011. This month our speaker is Jon Stewart who will be giving a talk about his new tool: Lightgrep. Details are below:

Lightgrep - Fast Keyword Searching for Forensics

Dislike waiting 5 days for your keyword search to complete? Been brought to tears by thousands of keywords? Lost faith in your forensics tools when they didn't find all the hits they should have? Come to this talk to see the first public demonstration of Lightgrep, a new regular expressions search tool designed specifically for forensics.

Search is a fundamental part of forensics, useful not only for discovering relevant documents and snippets of text, but also artifacts, files in unallocated space, and file signature analysis. We will discuss the basic principles behind how a grep search works, why it's important to consider how multiple keywords are handled, and how to validate a search tool's results. Finally, we'll show Lightgrep, a tool that allows for fast searching for thousands of keywords, with full EnCase integration.

Please join us on Wednesday, January 19th, 7:00pm at John Jay College - Forensic Computing Program and the Center for Cybercrime Studies
899 Tenth Avenue - btwn 58th & 59th
Room 610T - 6th Floor


Don't forget to RSVP!!!

Thanks to Douglas Brush, Prof Bilal Khan, Prof Douglas Salane and Prof Richard Lovely for helping to make this possible.

Sunday, December 12, 2010

Identifying Memory Images

Have you ever been given a memory image to examine and not known what OS it was? Or maybe you were told it was X when it was really Y? Or perhaps you have a collection of images that may not be labeled correctly?

So how do you figure out the OS of an unknown Windows image?

Strings

You could use strings to look for clues of the OS type. For example looking for the version numbers [1]. You can often find this in close proximity to a DLL name. Two examples (XP and Windows 7) are below:

Windows XP: 5.1.2600


2546060:5.1.2600.0 (xpclient.010817-1148)
2546134:InternalName
2546160:HCAppRes.dll
2546194:LegalCopyright
2546226: Microsoft Corporation. All rights reserved.
2546322:OriginalFilename
2546356:HCAppRes.dll


Windows 7: 6.1.7600.16385 (win7_rtm.090713-1255)


1335896:6.1.7600.16385 (win7_rtm.090713-1255)
1335978:InternalName
1336004:BlbEvents.dll
1336038:LegalCopyright
1336070: Microsoft Corporation. All rights reserved.


How do you determine if the memory image is from a x86 or x64 machine? Well, here you can look for environmental variables like PROCESSOR_ARCHITECTURE and PROCESSOR_ARCHITEW6432 (used for WOW64) [2]. An example from x86 and x64 machines:


PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 37 Stepping 5, GenuineIntel

PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64

PROCESSOR_ARCHITECTURE=x86
PROCESSOR_ARCHITEW6432=AMD64



More details about these variables can be found here.

Still, this is more labor intensive than it need be.

Using _DBGKD_DEBUG_DATA_HEADER64

Remembering a blogpost Moyix wrote about finding kernel global variables in Windows I figured each OS would have a different size after the OwnerTag defined in wdbgext.h:


typedef struct _DBGKD_DEBUG_DATA_HEADER64 {
LIST_ENTRY64 List;
ULONG OwnerTag; //"KDBG"
ULONG Size; //Different for each OS
} DBGKD_DEBUG_DATA_HEADER64, *PDBGKD_DEBUG_DATA_HEADER64;


Moyix gives us the pattern to search for regarding x86 OSes since the end of LIST_ENTRY64 will be 0 for x86 machines [3]:


\x00\x00\x00\x00\x00\x00\x00\x00KDBG


First let's try to find the sizes for each OS:


$ xxd xpsp3x86.dd |less
[skip]
0000b70: 6780 0000 0000 0000 0000 4b44 4247 9002 g.........KDBG..
[skip]

$ xxd win7x86.dd |less
[skip]
0000bf0: ffff ffec 6fbb 83ec 6fbb 8300 0000 0000 ....o...o.......
0000c00: 0000 004b 4442 4740 0300 0000 8084 8300 ...KDBG@........
[skip]


After examining XP, W2K3, Vista, W2K8 and Windows 7 machines (and different service packs), this is what we get (Windows 2000 value not done personally, but taken from Moyix's blog [3]):


OS Size
Windows 2000 \x08\x02
XP \x90\x02
W2K3 \x18\x03
Vista \x28\x03
W2K8 \x30\x03
Windows 7 \x40\x03


Now we need to find the pattern for x64 systems as well. We could do this with a hexdump of memory images to find the KDBG pattern:


$ xxd win7x64.dd |less
[skip]
0000080: f8ff ff10 44a1 0200 f8ff ff4b 4442 4740 ....D......KDBG@
0000090: 0300 0000 f080 0200 f8ff ff60 8f87 0200 ...........`....
[skip]

$ xxd w2k8x64.dd |less
[skip]
0000f10: f8ff ff40 f878 0100 f8ff ff4b 4442 4730 ...@.x.....KDBG0
0000f20: 0300 0000 c060 0100 f8ff ff60 b865 0100 .....`.....`.e..
[skip]


After examining several x64 dumps, the pattern that seemed universal to them was:


'\x00\xf8\xff\xffKDBG'


The header sizes also appear to remain the same for x64 and x86 machines. So there it is. You can search for a unique pattern in the memory image in order to figure out what OS it is. Some examples:

Windows 7x86: '\x00\x00\x00\x00\x00\x00\x00\x00KDBG\x40\x03'
W2K3 x86: '\x00\x00\x00\x00\x00\x00\x00\x00KDBG\x18\x03'
W2K8 x64: '\x00\xf8\xff\xffKDBG\x30\x03'

You could very easily write a Python script to identify Windows memory images using this technique, but you don't have to: This has already been incorporated into the Volatility 1.4 framework in the imageinfo.py plugin. Thanks to Mike Auty (ikelos) for doing the honors :-)

References

[1] List of Windows Versions
http://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions

[2] HOWTO: Detect Process Bitness
http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx

[3] Finding Kernel Global Variables in Windows
http://moyix.blogspot.com/2008/04/finding-kernel-global-variables-in.html

Monday, December 06, 2010

Volatility 1.3 get_plugins Script Update

I've finally gotten around to updating the get_plugins script I wrote a while back for Volatility 1.3 (and finally gotten around to blogging about it). This is due to a few changes in plugins, dependencies and to address difficulties mentioned in lorgor's blog.

MHL has also updated malfind2 to work with Yara 1.4a, so this script is compatible with those changes.

I have only tested this on Ubuntu and Mac OSX (with MacPorts installed).

  1. You must run this script as root

  2. This script also installs Volatility using SVN. If you are running Ubuntu or Mac it will check that SVN is installed, and if not, will install it and pull down Volatility in the current directory.

  3. If you are running Ubuntu or Mac OSX, this script will install other dependencies you will need like pcregrep libpcre++-dev python-dev for Ubuntu or pcre pcre++ for Mac.

  4. This script installs dependencies: pefile, libdasm, pycrypto, yara-python 1.4a, as well as all known Volatility plugins, including the newer VAP ones from MHL


You still have to install Inline::Python on your own.

You can find the script in my GitHub repository or as raw text here