Kicking Off Post Exploitation On Unix-like Systems

Tom Bolen
5 min readJan 27, 2020

--

When people think of a typical hacker, they often picture a suspicious-looking fellow sporting a hooded black sweatshirt hunched over a laptop mashing a keyboard. A quick Google image search for the term “hacker” verifies this.

google this yourself — it is amusing

The highly-rated TV drama ‘Mr. Robot’ is the most realistic representation of a hacker that I have seen in media but they still do not stray from the idea that a hacker needs to be clad in a black sweatshirt. Attire aside, I must praise the show for illustrating the various details involved in a cyber attack. While I wish ethical hacking was as simple as depicted in the 1995 film ‘Hackers’ where the typing speed of the hacker directly correlates to the amount of pwnage performed, this is unfortunately not the case. The reality is that every hacker (ethical or malicious) or Red Teamer must follow a series of steps when performing an operation. This series of steps is known as the cyber killchain. These steps range from early reconnaissance of a target to the exfiltration of data. The cyber killchain framework was developed by Lockheed Martin in 2011 as a means to help defenders better understand the stages involved in a cyber attack. More info about the cyber killchain can be found here.

cyber killchain model

As a member of the Red Team at Code42, I perform monthly cyber killchain tests to give the Blue Team practice should a real adversary target our company. One of the killchain tests performed is a known command and control test. A known c2 test has the purpose of testing the Blue Team’s ability to detect malicious command and control traffic entering and/or leaving our network. Since the purpose of this test is specific to testing the c2 traffic, following the full cyber killchain process from the first step of reconnaissance is not necessary. To save time, I usually send a volunteer a piece of custom malware and ask them to run it for me. Having a volunteer directly aware of the engagement is helpful in case the agent dies or something happens where I need them to run the malware again. However, in a longer-term engagement where the volunteer (or victim, in this case) is not aware they are part of an exercise, a bit more stealth is needed. In this scenario, I may have Remote Code Execution (RCE) on the endpoint/server but depending on the context of the RCE I may only have one shot at deploying my post-exploitation agent. In a scenario like this, I need to not only be stealthy while deploying my agent but I also need to increase the odds that the agent does not die on the server because again this may be my only shot. There are a variety of reasons that could cause an agent to die — see my previous blog post for more information about this.

Assuming I already have a valid path to RCE, there are a couple of different strategies I like to employ to decrease the odds that my agent dies while maintaining a suitable level of stealthiness. These strategies will primarily apply to Unix based systems.

One way an agent process can die is if the parent process is terminated. As a successful RCE ideally leads to a shell, the parent process of a post-exploitation agent will usually be a shell process. A defensive security analyst may kill the unusual shell process initiated from the RCE resulting in a hangup signal (HUP) being sent from the parent process (the shell) to all child processes, which would include the agent process. The agent process will receive the HUP signal and exit. And Boom! All of that hard work gaining the RCE and deploying the post-exploitation agent was for nothing.

Fortunately, there is a simple way around this through the use of the nohup command. If you preface your command to start your post-exploitation agent with nohup it will instruct the child process to ignore the HUP signal! Even better is the fact that the detached agent process will have a much shorter process tree which looks less suspicious in the eyes of a defensive security analyst.

Another technique I like to employ is the use of bash loops. A simple bash loop can be used to restart the post-exploitation agent on an interval. This is useful if the agent unexpectedly dies or malfunctions. Now, this is a bit noisier than just calling the agent once so there is a tradeoff here between stealth and persistence. However, I have found that in most cases if the agent wasn’t detected on the first run, it likely won’t be detected on the second and third and so forth. A basic bash loop syntax utilizing nohup is as follows.

nohup /bin/bash -c 'while true; do "COMMAND TO START POST EXPLOITATION AGENT"; sleep 7200; done' &

Below is a proof of concept displaying both of these techniques using two separate terminal windows.

process tree of two open terminal windows
process tree of bash loop without nohup
process tree of bash loop with nohup before exiting parent terminal
process tree of bash loop with nohup after exiting parent terminal

Notice how nohup makes the bash loop look like it originated from launchd once the parent process is killed.

child process still running

Notice that the child process is still running after the parent process was killed.

The combination of these two techniques makes initial post-exploitation activities more sustainable and a bit more stealthy increasing the odds of success for persistence, privilege escalation, or lateral movement.

Stay posted for a follow-up blog detailing userland persistence techniques for MacOS.

For more articles like this checkout Code42’s Security Blog below!

--

--