Journal: FlareOn7 (Part 2)

asuna amawaka
insomniacs
Published in
13 min readOct 25, 2020

Continuing on levels 7–9…

(edit: I’m sorry that some of the screencaptures for the solution python scripts are really low resolution. Go to my GitHub repo to download them! https://github.com/asuna-amawaka/Flareon7-2020)

(WebDav exploit, pcap) 7_-_re_crowd

This is a cool one that taught me about CVE-2017–7269. Before I started on solving this level, I spent some time reading up on the vulnerability and the exploit POC on: https://www.anquanke.com/post/id/85811. The English translation by Google works well for this page :) I’ll be relying very heavily on this post for solving this level.

You might be asking, in the first place, how did I know the pcap is about an exploit, and the exploit is for CVE-2017–7269?

There was a conversation from the employees in the IT department (from “The IT Crowd”) that tells us the flag is most probably in C:\accounts.txt or whatever is in this file will lead us to the flag. Then we see streams like this in the pcap:

Streams 33 to 48 looks like some unsuccessful attempts at doing something, with decreasing length of contents sent to the server and the server replying with a 500 error. Stream 49 looks like whatever is being done was finally successful (no 500 error) and is followed by Streams 50 and 51 that tell us some data is being exchanged. Looking up the keywords “PROPFIND”, “locktoken:write”, “webdav” will bring us to CVE-2017–7269 and articles on the exploit of this vulnerability.

We can concentrate on the contents sent in Stream 49, because that is the successful exploit.

The most direct way to tackle this level would be to do a dynamic analysis. First off, set up the environment: Windows Server 2003 r2 32bit (get the CD images here http://download.microsoft.com/download/5/1/C/51C53A00-7F8B-423C-A841-8B9C49B910BF/X13-04795.img and http://download.microsoft.com/download/5/1/C/51C53A00-7F8B-423C-A841-8B9C49B910BF/X13-04874.img), with IIS6.0 installed, webdav enabled and WebClient service running. Also install python 2.7 and process explorer of your liking. We will debug the exploit with windbg (I’ll run through how to set this up in abit).

Next I used the POC python script and edited it with the shellcode extracted from the pcap. I reused the “pay” variable contents from the POC, because it helped me to follow the steps from the abovementioned blog.

Now, we set up the tools within the WS2003r2 image. Download and install Windbg with this SDK: https://download.microsoft.com/download/F/1/0/F10113F5-B750-4969-A255-274341AC6BCE/GRMSDK_EN_DVD.iso. You might also need this .Net framework: https://download.microsoft.com/download/0/8/c/08c19fa4-4c4f-4ffb-9d6c-150906578c9e/NetFx20SP1_x86.exe

We are going to make use of gflags (Global flags) to help us with the debugging. This is a nifty trick that I usually use for debugging Windows Services, but looks like it is also helpful in this situation.

We know that the exploit will be executed under httpext.dll via w3wp.exe, hence we want to put our debugger into w3wp.exe so that we may step into the DLL. Fill in this page like this and click on Apply.

Ok, now we can execute our python script. Notice the processes that are created: svchost.exe > cdb.exe > w3wp.exe

Our target is “httpext.dll”, so let’s set a bp upon load of this dll with “sxe ld httpext.dll”.

The abovementioned blog post provided a lot of details on how the whole exploit worked, so I’m not going to go through the parts on the exploitation. What is interesting to us here is the shellcode that is executed that will lead to our flag.

The beginning of the shellcode execution is at address 0x68031460. However, we should not put a breakpoint here from the start, because this address will get overflowed as part of the exploit. Hence I put a breakpoint at 0x671335f3 and wait till the address 0x68016082 is called.

This address 0x68016082 is where the pre-ROP chains are found — the return at 0x6801608a marks the beginning of the ROP chain, all the way until the shellcode is called at 0x68031460.

The shellcode then starts to perform some decoding on itself, which means that breakpointing here has to be done carefully after the decoding is done, else you will end up crashing or the shellcode will not decode correctly. The decoding loop starts from 0x68031544 and will only be done when the code calls 0x68031553. It’s abit complex to describe the entire loop here in words, so I apologise for not going to try to confuse you. But you can try to step instruction by instruction to get a feel of what is happening here in the decoding loop. The ultimate outcome is that we get a properly decoded shellcode starting at 0x68031553.

It is safe to breakpoint at 0x68031553 after seeing that the memory at 0x68031550 looks like the one in the following screencapture.

At this point, I also dumped the shellcode out to look at it in IDA Pro.

I’ll continue to use dynamic analysis to help me make sense of what I see in IDA Pro. In the screenshot above, “call ebp” is calling 0x68031558, which performs hash-decoding and then call the function. So for example, at 0x6803165C, VirtualAlloc is being called and the allocated memory address is returned in eax.

What is happening in here is that the shellcode expects to receive something which starts with 4 bytes that is XORed with “ROXK” and then used as a size expected of subsequent data to be received.

Next, RC4 decryption is being applied onto the received data. The key used is also hardcoded within the shellcode — “killervulture123”.

From the pcap, we have this data! We can feed it into the shellcode via ncat. Opening the decrypted data in another IDA instance, we see something like this:

The interesting function is at 0x1CA048F. Whatever happened before the call to this function is just hash decoding of API calls. With a little bit more help from dynamic analysis, and a little bit of intuitive guessing, I was able to tell that the 2nd piece of data found in the pcap that is received from the server is RC4-encrypted with the key “intrepidmango” read from C:\accounts.txt.

Let’s confirm this guess.

Didn’t work for you? Have you tried turning it off and on again? :D

(WSL) 8_-_Aardvark

This challenge is pretty straightforward. I think the “hurdle” presented here is a psychological one. We were all looking for a flag that looked like.. well, a flag. But this one came up to be a gibberish flag.. But nonetheless, still an interesting binary, I had fun playing tic tac toe for a while before I got to solving it.

First we need a Win10 environment because Windows Subsystem for Linux (WSL) is required for this binary to run. Get one here: https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/.

While the Win10 is downloading and installing, I was poking around the binary and found the Linux component in the resources.

This ELF does not have many functions but the main function looked like this @.@

Statically analyzing the instructions slowly, we can kind of tell that it is preparing the game board, waiting for moves from the user and checking the moves. At one point, the winner is being checked and if the winner is “O”, the binary proceeds to do a series of value fetching e.g. opening /proc/modules, /proc/mounts, /proc/version_signatures etc.

Now, after all this static analysis is done, your Win10 environment should be ready. Let’s play tic tac toe for awhile..

You might notice you will never win :<

Ok back to breaking the game because YOU WANT TO WIN!

Now, notice that only when ‘O’ wins, we can get to hit line 220 in the decompiled view below. Which means that we need to patch the jumps so that even with “X” wins, we can get where we want to.

So we patched these two jumps here..

Also, we need to cheat the binary into acknowledging that the winner is ‘O’, else the XOR operation that we saw previously that acts on the encrypted flag will not give us the right output. Hence, patch the binary here to set EAX to 0x4F:

Now, play the game!

I don’t care who wins, just give me the flag :D

I’ll like to thank the kind soul who mentioned on Twitter about submitting the flag the moment you see readable ASCII. Else I think I would smash my computer if I only realised that this gibberish is the real flag 2 days later…

(Kernel debugging, COM) 9_-_crackinstaller

In summary, this level is just lots of hardwork debugging, and then a stroke of luck and a tinge of intuition and it’s done.

The hardwork begins with trying to set up kernel debugging. It’s not that hard actually. Follow these instructions and it’s a smooth ride: https://voidsec.com/windows-kernel-debugging-exploitation/

If you are planning on doing FlareOn8 next year, keep a snapshot of this environment after you get it up.. I’ve been using my snapshots from the previous years — there is always one kernel debugging level in FlareOn :P

With the help of a debugger (may not be windbg here, you can use anything you like because we still in user space), we can do a cursory analysis of the crackinstaller binary. Then we notice that it creates a file cfs.dll, followed by a call to DeviceIoControl (not immediately, but the code leads one way)

That IoControlCode looks kind of strange. Google it!

Ahah! Now we can find out what’s happening here. Again, Google’s translation to English works well for this post too. I’ll recommend reading this great post before continuing.

After reading, we understand that there is code execution via this cfs.dll driver , and we want to follow this code execution. Looking at cfs.dll with IDA Pro, we can see the function being executed when DeviceIoControl is called.

From this function sub_FFFFF88004BFE590, we can see that a shellcode subsequently gets loaded and called:

Looks like what we are looking for — Let’s get right into kernel space debugging then!

In order to hook onto cfs.dll, we have to do a “bu cfs!DriverEntry”, followed by a “lm” to find out where the driver was loaded in memory.

Put a breakpoint at where we expect the shellcode to be loaded.

The code execution goes into the shellcode. Dump this shellcode and look at it in IDA. Nothing fancy, just a way to jump to another address 0x13F002A10 in the exe (look at sub_2A10 in crackinstaller).

Personally I think my approach for analysing this binary is very rudimentary. Basically I copied output from windbg into my IDA Pro so that I can keep track of the values and then figure out what happened. So bear with my screen captures for the rest of this post, because you will see a lot of “bloated” comments in my IDA view :X

So when we enter this function, it starts to do a sort of dynamic loading of API functions. In windbg, I used the command “ln <addr>” to get the name of the API that is being retrieved. For example, in the following:

The result returned from the call at 0x140002A9C in RAX is 0xfffff80002e6df20. Executing the command “ln 0xfffff80002e6df20” in windbg gives us this:

And thus we know r12 is loaded with nt!IoCreateDriver.

With all these API calls properly labelled (hard work, yes), we get to this code that allocates some memory, and then get stuff moved into it. Finally a thread is created that starts execution at a function within this memory space.

Dump this 0x5800 bytes from memory so we can take a look at what kinda monster it is.

There we go, this 3rd binary that we have to analyse is named “driver.sys”.

The new thread starts its execution in the DriverBootstrap of driver.sys. Within this function, it creates a copy of itself and calls IoCreateDriver to start the execution of DriverEntry.

Within DriverEntry, there is a call to CmRegisterCallbackEx that executes the function at 0xFFFFFA8005015970 every time a thread performs an operation to the registry (this is the definition from MSDN, but I don’t really understand it). What interests me here is that this function will get called when a condition is met, so we should see what happens in here.

I’m going to omit all the boring analysis steps — I just stepped through the function within windbg and try to link up what the function is doing. Until we reach this part where a decryption algorithm is found. We would obviously love to know what is this mysterious string that is decrypted. Let’s make windbg do the job for us by putting a breakpoint on where the salsa_decryption function is called.

Nice! We found a string that looks like it’s a key to decrypt something…

The question is: what does it decrypt?

The answer is not that far off from where we found this password. In the same function, we see a registry key being created.

Let’s go find this regkey.

Now let’s take many steps back and go back to the original crackinstaller binary again. This time, I found another function that writes a file to “C:\users\<user>\AppData\Local\Microsoft\Credentials\credHelper.dll”. This is where this file came from.

OK, so now we shall analyze credHelper.dll. The clue to begin would probably be to find functions that read from/write to the regkey.

Now let’s find where the data comes from. Slightly above this code block is a XOR decryption loop…

In another function within the vftable, a regkey “Password” is being read and used in a loop that kinda looks like RC4’s KSA, which makes sense if the XOR decryption loop is probably part of RC4 too. I wasn’t sure at this point, my guess is just based on intuition.

Trying the decryption blindly…

And that’s it! Got the last part done based on intuition… If it had been any other decryption algorithm being used, I guess I would not have escaped from doing more COM-programming, which I saw other folks have coolly done :)

I ran out of energy writing just 7–9. Will have a part 3 for 10 and 11, stay tuned!

~~

Asuna
https://twitter.com/AsunaAmawaka

--

--