In a Red Team assessment, obtaining our payload undetectable can sometimes be very time-consuming. Today I will show how you can develop a custom undetectable backdoor in Python and how to protect yourself against one.
Python Backdoor in 15 Lines
I have compiled the client for the macOS executable and uploaded to virus total. The result will amaze you because none of the antivirus agents detected the backdoor just because we are using the HTTP protocol and there is nothing that looks suspicious to the anti-virus program. You can have a look at the executable file.
I will use macOS as a client and kali machine as a server and we will test for the backdoor to see if it works or not. We will execute the client code on macOS and the server will be our Kali machine.
This is very dangerous. We should always use licensed tools and software for our organizations or as an individual and only download content from legit and official sources. Downloading it from other sources could be the modified version and a backdoor could be attached to it.
There are numerous backdoor delivery methods. Sometimes it can be bound to some other valid software or sometimes they will be serving as a web page. An example is HTA, so we should always be aware of what is being installed on the system and their sources.
produces a .pyo file that contains byte-code, and where docstrings are removed, etc. You can rename the .pyo file with a .py extension, and python runs like your program but does not contain your source code.
I recently stumbled across this blogpost: Python Source Obfuscation using ASTs where the author talks about python source file obfuscation using the builtin AST module. The compiled binary was to be used for the HitB CTF and as such had strict obfuscation requirements.
The official version runs as a standalone utility, with the original intended design being that you drop a script into the root of the directory you want to obfuscate, along with a config file to define the details/options you want to employ. I wasn't in love with that plan, so I added a fork from project, allowing you to import and utilize the tool from a library instead. That way, you can roll this directly into a more encompassing packaging script. (You could of course wrap multiple py scripts in bash/batch, but I think a pure python solution is ideal). I requested my fork be merged into the original work, but in case that never happens, here's the url to my revised version:
Additionally, the third stage writes the Base64-decoded backdoor to %AppDaTa%\microsoft\\ where and are four and 52 random characters, respectively. This Base64-decoded backdoor has the following SHA256 hash:
This shortcut then points to the fourth stage itself. Once persistence has been established, the fourth stage then Base64-decodes a path to the Base64-decoded backdoor. Recall that the Base64-decoded backdoor had been written to %AppDaTa%\microsoft\\ by the third stage. In the presented fourth stage sample, this Base64-encoded path is:
This Run function is the entry point of the SolarMarker backdoor (alias C2 Jupyter client). Initially, the backdoor generates a 32-byte random string as a victim ID and saves it under %AppData%\AppData\Roaming\solarmarker.dat. Additionally, the malware collects information about the computer and sends an initial request to its C2 server at http[:]//45.135.232[.]131. Communication between the backdoor and its C2 servers is facilitated via a JSON-like protocol where each message is encrypted using the following hardcoded XOR key:
The C2 then answers with a payload that is saved under %Temp%\. with the respective extension, where are 24 random characters. Next the payload is executed. After 30 seconds, the backdoor sends the following message to the C2:
Mininet is written almost completely in Python so eventually you may want to access moreof its capabilities. This means that you can run Mininet from the interactive Python shell oreven an enhanced Python shell like IPythontarget="_blank". The oneimportantcaveat is you must sudo intothe python shell, i.e., use the Linux command sudo python to start yourpython session.
If you've used Mininet a bit one thing you might not like about Code Example 1 is that you don't get the nice Mininet CLI that eases poking and probing your network. In Code Example 2 on line 18 we bring back the nice Mininet CLI. While you can enter Code Example 2 line by line into a python shell you can more easily just run it in your Mininet VM with the command sudo python ExMNtcSimple.pyin a terminal window.
On line 10 we use iperf to determine the bandwidth available between h1 and h2. The link from h1 to s1 has a bandwidth of 20Mbps and from h2 to s1 has a bandwidth of 25Mbps. Hence the first link is the bottleneck and we expect roughly 20Mbps of throughput which is confirmed on line 12. On line 13 we test the throughput between hosts h1 and h3 in this case the link between s1 and s2 with a bandwidth of 11Mbps is the bottleneckas confirmed on lines 14 and 15.
Now lets look a bit into the network that Mininet setup for us. Here we are using the Mininet CLI to execute some Python commands for us using its py command. On lines 1-6 we look at the IP addresses that Mininet has given the hosts and (not given) the switches. Hosts are given IP addresses in increasing order starting from an initial base. However, Mininet also allows you to set these yourself. Mininet does not give the switches IP addresses. We see on lines 7-10 that Mininet has assigned port numbers to all the ports on the switches. When we program switches with OpenFlow we need to use port numbers in our "matches" and "actions". Mininet also allows us to explicitly set port numbers on links. Finally lines 11-14 show the MAC (Ethernet) addresses that Mininet has assigned to the hosts. Mininet will use either random addresses, simple incremental number, or (as we'll use later) allow you to assign the MAC addresses.
Now when you run this code with the command sudo python ExMNtcSimpleLoop.py Mininetwill build the network and bring up the CLI. You won't get any indication there is a problem unless you try to ping between the hosts (go ahead try it!) and for me this failed. The other indications are that my task manager shows that VirtualBox is starting to use a lot more processing power for the Mininet VM, or if you've gotten WireShark working with your Mininet VM you'll see a huge flood of packets.
In Code Example 6, we show simple graph creation on lines 12-14, and some calls to some nice NetworkX graph member functions on lines 15-18. On lines 3-9 we give an example of a function to check for the validity of a given path against a given graph. We then test this function on lines 19-20.
What makes a graph into a good model for a network is the addition of attributes tothe links (edges) and nodes (vertices) of the graph. This is easily done in NetworkX asshown on lines 7-9 of Code Example 7. Furthermore a network (graph with attributes) can be easily exported in a web friendly JSON format as shown on line 16.
In Code Example 9 we show how to read the previous JSON file into a NetworkX graph object (line 6). We then print a list of the ids of the nodes in the graph (line 7), the links in the graph along with their attributes (line 8), the hosts in the graph and their IP and MAC addresses (lines 9-11). Finally on line 14 we use NetworkX to compute the shortest paths from node "H8" to all other nodes. Lines 15-17 are use to print this information in a nice format.
Two complementary sources of documentation on Ryu are Ryu.ReadTheDocs and the Ryu Book. Note that the Ryu book is also available in Japanese, Chinese and Korean. Ryu is available a package from the Python Package Index and can be simply installed into your python installation with the command pip install ryu.
We are going to use the same network description file we gave to Mininet for network creation to compute forwarding tables. In particular we will not be using the controller/framework to perform network discovery or host tracking. To do this we Ryu's option system on lines 31-38 to specify additional command line options. One for the network file and one for whether to use shortest or widest paths.
The next thing we do is get the command line parameters, the netfile and widest_paths indicator, on lines 51-52. The first being our JSON network description file and the second a boolean to indicate whether we will use shortest or widest paths. You can see the precomputation of the forwarding tables around lines 55-59. Note that since Ryu is currently based on a multi-threaded cooperative multitasking infrastructure, i.e., eventlet you should use the Ryu application's logging facilities rather than print statements for debuging as I did on lines 53-54.
Before we can program the switches we need to wait to hear that the switches are up and connected to the controller. Per the OpenFlow protocol, a good time to do this is after controller receives a "switch features" OpenFlow message from a switch. This is the purpose of the code on lines 61-69. The odd syntax of @set_ev_cls(ofp_event.EventOFPSwitchFeatures) before the definition of the handle_SwitchUp() function is known as a Python decorator. The decorator, in this case, basically tells the Ryu framework to call our function when a particular class of event occurs. To see what OpenFlow events are supported and their names is a little tricky since the Ryu module ryu.controller.ofp_event dynamically generates the event classes from other python files that implement particular OpenFlow versions. The easiest way to see a list of Ryu supported OpenFlow events and their names is to type the following into an interactive python shell:
When the "switch features" message comes in we get the information on the switch that finished its handshake with the controller on line 67 (the "datapath" part of the message). We then call our function load_fwd_table() which sends all the forwarding table entries down to the switch. This function shown on lines 71-89, takes the datapath (switch) id and turns it into a switch name (line 77). The datapath id in our case is the Ethernet address we assigned to the switches in our JSON network description file (Mininet did this for us when we created the switch). We then get the forwarding table appropriate to this switch on line 79. 2ff7e9595c
Comments