Windows Command Line Persistence?
A few weeks ago, I wrote a diary about forensics and the bash UNIX shell and last week, I attended the training FOR408 ("Windows Forensics Analysis") in Amsterdam. The training was great and covered many ways to collect artifact in a Microsoft Windows environment but there was nothing about the Windows command line ("cmd.exe" or "powershell.exe") which are common tools used by attackers or insiders. In fact, the memory analysis is covered in the training FOR508. To make thinks clear, the good old cmd.exe does not provide any logging facilities at all. When the process is running, it is possible to use the in-memory history to scroll across the previously executed commands but this is not persistent. The command doskey (this will maybe remind the good old times of MS-DOS to some of you) is still available and can be used to display the current history in the current cmd.exe:
C:\> doskey /h
But how to get the history? My first idea was to check into the process memory:
C:\> procdump.exe -accepteula -ma cmd.exe cmd.dump
And then search for interesting strings. Nothing! After some Google searches, I found a paper written in 2010 which explains how command history is managed into the computer memory. Hopefully, volatility has a module which helps to extract this kind of information from a memory image:
# ./vol.py -f laptop.dump consoles ************************************************** ConsoleProcess: conhost.exe Pid: 7336 Console: 0xff1c6200 CommandHistorySize: 50 HistoryBufferCount: 1 HistoryBufferMax: 4 OriginalTitle: %SystemRoot%\system32\cmd.exe Title: C:\WINDOWS\system32\cmd.exe AttachedProcess: cmd.exe Pid: 7308 Handle: 0x6c ---- CommandHistory: 0x39eab0 Application: cmd.exe Flags: Allocated, Reset CommandCount: 42 LastAdded: 41 LastDisplayed: 41 FirstCommand: 0 CommandCountMax: 50 ProcessHandle: 0x6c Cmd #0 at 0x3774b0: cd / Cmd #1 at 0x399e90: cd users/xmertens Cmd #2 at 0x399ec0: type secret.txt Cmd #3 at 0x3774d0: history Cmd #4 at 0x39e2a0: h Cmd #5 at 0x39e2b0: dir Cmd #6 at 0x399ef0: type secret.txt Cmd #7 at 0x39e2c0: f: Cmd #8 at 0x39e2d0: dir Cmd #9 at 0x3774f0: md cases Cmd #10 at 0x39e2e0: e: Cmd #11 at 0x39e2f0: dir Cmd #12 at 0x377510: cd tools Cmd #13 at 0x39e300: ls Cmd #14 at 0x39e310: dir Cmd #15 at 0x377530: cd PSTools Cmd #16 at 0x39e320: dir Cmd #17 at 0x377550: cd .. Cmd #18 at 0x39e330: dir Cmd #19 at 0x377570: cd .. Cmd #20 at 0x39e340: dir ... ...
This plugin scans for CONSOLE_INFORMATION and prints the entire screen buffer (including input and output - the type commands and results). But to use volatility, we need to make a copy of the target system image, this can be slow, difficult to perform. How to get an "real time" history of the commands?
The first idea is to re-use the doskey command and create macro that will dump the commands when the user exits cmd.exe. To achieve this, cmd.exe can be executed from a shortcut like this:
The .bat file will contain this line:
@echo off doskey exit=doskey /h $g$g "%USERPROFILE%\cmd.log"$t exit $*
This will dump the cmd.exe history to the file cmd.log every time the user closes the session with "exit" (but not by closing the windows!)
C:\> cmd /k c:\scripts\cmdhist.bat C:\> whoami win10vm\xavier C:\> exit C:\> type %USERPROFILE%/cmd.log whoami C:\>
This technique has many limitations but, at least, data is written on disk (and data deleted from the disk can easily be recovered if the user erases the file!).
Another approach is to extend the existing cmd.exe features with a more powerful tool like Clink which describes itself as "a powerful bash-style command line editing for cmd.exe". Besides many interesting features to improve the command line, it saves the commands history by default. Once installed, it can be executed automatically when a cmd.exe is launched and the user's history is saved to "%USERPROFILE%\AppData\Local\clink\.history". Like in a UNIX bash shell, the behavior of the history can be configured with environment variables:
- history_dupe_mode
- history_expand_mode
- history_file_lines
- history_ignore_space
- history_io
And what about PowerShell? Like cmd.exe, it does not have a persistent mechanism to store the commands history. Clink is reported to be compatible with PowerShell (since the latest release) but it does not work for me. An alternative is to use the PSReadLine module. I found a blog post which explains how to implement history persistence in PowerShell.
Xavier Mertens
ISC Handler - Freelance Security Consultant
PGP Key
Reverse-Engineering Malware: Advanced Code Analysis | Online | Greenwich Mean Time | Oct 28th - Nov 1st 2024 |
Comments
@echo off
setlocal EnableDelayedExpansion
:getCommand
set command=
set /P command=%cd%^>
echo(!command!>> D:\test\1.txt
call %command%
goto getCommand
The CMD will look the same, but it will record all commands to a file.
You can put this script in the CMD.exe autorun regkey (HKCU\Software\Microsoft\Command Processor:AutoRun).
Anonymous
Apr 17th 2016
8 years ago
This can be combined with command-line Windows event creation:
http://stackoverflow.com/questions/446691/how-to-create-windows-eventlog-source-from-command-line
and Windows event collection/forwarding:
https://msdn.microsoft.com/en-us/library/cc748890.aspx
in order to get logs out of the machine, safe even if it gets compromised... :)
Anonymous
Apr 17th 2016
8 years ago
Computer Policy: Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell > Turn on PowerShell Transcription
User Policy: User Configuration > Administrative Templates > Windows Components > Windows PowerShell > Turn on PowerShell Transcription
If you plan to use a network share to centralize the transcripts, ensure the user has the correct rights to write data but not read it or delete it.
Anonymous
Apr 18th 2016
8 years ago
In Adv Audit policy - enable 'new process creation' which kicks off a very noisy event ID 4688. With this I am able to capture the cmd.exe process within the event.
Now, within the win admin templates we enable ‘Include command line in process creation events’ which provides us with the process plus the cmd input like so:
cmd.exe
ping 1.1.1.1 (or any other command)
This capability is also available in powershell since the introduction of enhanced auditing features in ps-v5.
This event can now be captured within splunk as part of your behavioural and suspicious activity analytics. A watch-list can be created by utilising splunk lookups for suspicious ps cmdlets or other shell commands of interest that go towards your library of IOCs.
And thanks to Xaviers previous post on Bash forensics – I now have a plan to implement this technique across my nix boxes – thanks Xavier.
Anonymous
Apr 19th 2016
8 years ago