Pages

Friday, November 1, 2019

Retro shellcoding for current threats: rebinding sockets in Windows

In previous posts we saw two techniques to bypass firewalls through custom stagers to locate and reuse the connection socket; on the one hand, taking advantage of socket's lifetime and on the other, embedding OOB (Out Of Band) data in the stream of our exploit.

The truth is that this topic has always fascinated me despite I didn't find many public shellcodes that try to circumvent restrictive network environments (especially in Windows). What is evident is that having some skills in the development of shellcodes allows you to work wonders. Look for example at this remote exploit developed by HD Moore in Veritas Backup software. Due to the space restrictions to execute code (about 50 bytes), the payload gets the recv() address from the IAT and use it to stage the rest of the payload. This is pure art.


Let's see another example. In March 2013, researchers from Malware.lu CERT published a report about APT1 in which they describe how they designed a custom shellcode to maintain access to the bad guys' infrastructure who used Poison Ivy to infect their victims. Initially, they run a standard stager (reverse shell) to gain access to the Poison Ivy server; however the attackers detected connections from their C2 server without going through its proxy identifying this way the intrusion. In order to stay stealth the people of Malware.lu crafted a shellcode to reuse the Poison Ivy socket and thus be able to connect to it through their proxy imitating a legitimate malware infection. Cool!

Related to this last example, and continuing with the one-way shellcodes saga, I would like to share a shellcode to rebind sockets. Remember that these kind of techniques are useful when network conditions prevent running a reverse shell and when it is not possible to do socket-hunting (and of course when the socket is in the same exploited process). Unlike the two cases described in previous posts, with this approach we are not doing brute force of the process handles, but we are simply trying to execute a bind shell in the same port as the one used by the vulnerable service. Of course this idea is not new, you can take a look for example at Phrack 62 (Rebind socket shellcode implementation) to see in detail this kind of techniques. Or you can look at this 2002 presentation of "The Last Stage of Delirium" hacker group: "Win32 Assembly Components". Yes, almost 20 years ago old-school hackers already devised these kind of nifty techniques.

The interesting thing is that despite the age of these techniques, their use today can still be of great help in some scenarios; for example, I have found it useful when it comes to exploit some C2 servers used by certain malware (mainly because many of them are not very complex in terms of managing connections)

The proofs of concept that I have seen to do rebinding are mainly based on 2 approaches: using setsockopt along with the SO_REUSEADDR option which allows the socket to be bound to an address that is already in use, or ending the vulnerable service to reuse the same port. Since the first option is unstable and not useful in applications that use SO_EXCLUSIVEADDRUSE I will focus on the second option contributing with some nuances regarding the POCs I've seen.

Well, the goal of this approach is that once the corresponding service is exploited, the shellcode generates a new process in which it will inject the payload responsible for configuring the bind shell in the appropriate port. However, there are two problems here. The first and more important is that if you try to run a bind shell in the address space of a process, by default, Windows firewall will block it (most of the POCs I have seen migrate to a different process, for example cmd.exe, however, in practice this is not feasible precisely because of the Windows firewall). The second minor problem is that, even if the firewall allowed to open the socket, we would have to wait for the legitimate process (the one we just exploited) to finish its execution since we have to bind it in the same port (some shellcodes configure a kind of loop that tries to bind it until the main process "releases" it).


To address the first problem, one of the options we can try is to implement a kind of "fork", via CreateProcess. Since the process already has permission from the firewall to open the socket that we are trying to reuse, we will not have any filtering problems. To get the binary's own path you don't even need to call any API; from the PEB, through the structure PRTL_USER_PROCESS_PARAMETERS it is feasible to reach it with just few bytes. To develop the proof of concept I've used, as a boilerplate, the asm code that Matt Weeks used to implement the PrependMigrate functionality in Metasploit. Remember that through this option, the stager itself migrates to another process (the one specified by the user using the PrependMigrateProc var) to receive the corresponding stage; something that closely approximates what we are trying to achieve. The following image shows the changes to execute a new process from the same binary.


After creating a new suspended child process, we will only have to inject the payload into it (via VirtualAllocEx, WriteProcessMemory) and then use Thread Hijacking so that EIP of the main thread (which at this moment would point to the startup wrapper function RtlUserThreadStart in Ntdll.dll) points to the injected shellcode. Using Thread Hijacking (via GetThreadContext, SetThreadContext and ResumeThread) instead of CreateRemoteThread (as PrependMigrate does) is important in this case since we need the code of the "forked" process to never run since it could end its execution if it tries to check, for example, if an instance of the same process it is already running (through Mutex/Events objects, etc). In addition, we get more stability (just our thread is running) and collaterally we will make our injection less detectable.


Finally, after running ResumeThread, the main shellcode will finish the execution of the exploited process via ExitProcess. To prevent that the "forked" process from trying to reuse the port that is still in use, we can add a Sleep() to the payload so that it waits X seconds. In this way we give the main process time to close all its handles.


The following video shows an example of this payload with one of PlugX controllers vulnerable to a certain buffer overflow discovered by Waylon Grange a couple of years ago. In this case, the payload waits 3 seconds before binding on socket 13579 (the port used by the controller to receive its victims). Remember that to prevent a thief from stealing our bind shell we can use an IP-Knock-shellcode; this way the shell will only respond to its master.



No comments:

Post a Comment