Three Examples to Increase Sustainability in FatRat

Jason M. Pittman
6 min readJun 9, 2023

Introduction

The Python code we’re developing secretly guzzles more energy than necessary. Part of the high energy consumption is unavoidable. Python is an interpreted language after all. It runs on the CPU longer than compared to C++ for example given the same function. Further, there are code level efficiencies we tend to ignore. The result is unsustainable software. The negative impact is we wasting energy resources. Yet, our code doesn’t have to be a power hog.

Let’s dive deep into the intricate world of real-world Python code and its energy usage. We’ll shed light on its energy efficiency by peeling back the layers of how Python interacts a system. The CPU, RAM, and filesystem I/O.

The motivation is simple. We learn better through analyzing real code in the wild. Reading about coding or attending a lecture is fine but we want hands on keyboards.

Photo by Johen Redman on Unsplash

The Why

I do these open-source reviews not to embarrass or trifle with the developer’s feelings. Instead, these are valuable opportunities for us when it comes to two critical principles:

  • Learning to identify computer science theoretical concepts from source code…
  • Learning to be mindful of the sustainability of our coding decisions…

Why these two principles? Well, understanding theoretical concepts allows us to see why code behaves a certain way. The way we want the code to behave is in a sustainable manner. We want green operations.

Another way to express the same ideas is to say I want to generate awareness. Computation is the singular means to understand how to engineer effective information processing systems. Effective nowadays means sustainability.

Effective also means following a method. Without further ado…

The Review Method

The method for our code review consists of n steps.

  1. Pick a recommended project in my GitHub feed https://github.com/explore
  2. Select random Python file in the project
  3. Read through the code to find notable code operations related to:
  • String generation or manipulation
  • Large data structures
  • Filesystem Input/Output
  • Loops or recursion
  • Network Input/Output

I look for those five operations because those are the hot spots of energy consumption. And, rather than waffling on about theory in the absence of the practical, I review GitHub recommendations to find public open source code.

Today’s Recommended Project

Imagine my surprise when a cybersecurity related project appeared in my recommendations. I had to take the opportunity and thus today’s project is TheFatRat.

Per the repository description:

TheFatRat is an exploiting tool which compiles a malware with famous payload, and then the compiled maware can be executed on Linux , Windows , Mac and Android. TheFatRat Provides An Easy way to create Backdoors and Payload which can bypass most anti-virus.

The Python Source Code

I zeroed in on a single Python code file here: https://github.com/screetsec/TheFatRat/blob/master/tools/trusted_2_6.py

The source code has 18 functions and 635 total lines of code.

Look at the gen_cert_attack(filename) function beginning on line 323.

We have two interesting examples right off the bat. These are interesting because they both have innocuous energy profiles. They also operate against similar theoretical concepts. Check this out:

· Lines 14–15 of the function:

The code reads the contents of the specified file in binary mode using file(filename, “rb”).read(). Reading a file can consume energy, especially if the file is large. But, without knowing the size of the file or the frequency of execution, it’s challenging to determine the actual impact on energy usage.

· Line 16 of the function:

The code encodes the binary data using base64 encoding with base64.b64encode(data). Encoding data involves computational operations but is generally lightweight. The energy impact is likely minimal unless the input file is very large.

Both statements are linear in Time and Space complexity (e.g., O(n) ). Thus, the larger the input, the longer the statements will take to execute. The larger the space (i.e., RAM) each will consume. Now, there is no theoretical way to improve sustainability here. The best-case cost of reading N characters is reading those N characters. Nonetheless, this is a neat theoretical example.

Let’s shift to the gen_shellcode_attack(payload, ipaddr, port) function starting on line 424. Here we have an example which might hold room for sustainability improvement.

In lines 12–19 of the function, the loop iterates over the shellcode string and performs string concatenation operations. The time complexity of this loop can be analyzed as follows:

1. Iteration: The loop iterates over each character in the shellcode string exactly once. Thus, the number of iterations is proportional to the length of the shellcode string.

2. String concatenation: In each iteration, the floater variable is appended with a character from the shellcode string. Yet, concatenating strings in Python involves creating a new string object, which has a time complexity of O(n), where n is the length of the resulting string.

The time complexity of the loop is O(n^2), where n is the length of the shellcode string. This is because for each character appended to the floater variable, a new string object is created by concatenating all the previous characters, resulting in quadratic time complexity. Overall, If the number of elements n increases linearly, the time to perform the algorithm will increase quadratically.

The shellcode loop can be rewritten to improve its performance. We can do this by utilizing a more efficient string-building technique. In Python, the recommended approach for concatenating multiple strings efficiently is to use the join() method. Here’s an example of how you can refactor the loop using the join() method:

# Initialization
newdata_list = []

for line in shellcode:
floater += line
counter += 1

if counter == 4:
newdata_list.append(floater)
floater = ""
counter = 0

# Join the list of floater strings using a comma separator
newdata = ",".join(newdata_list)

We can achieve a significant improvement in sustainability through this refactor. The time complexity shrinks from O(n2) to O(n), where n is the length of the shellcode string.

If you thought that was neat, check out this last example. Let’s scan up in the source code to the scramble_stuff() function on line 236. We have a for loop similar to the prior example. Here, the code iterates over the characters in ps, wscript, and shell, and performs string manipulations and concatenations. While the approach is functional, it could be improved by utilizing list comprehensions or other concise methods for building strings.

There are three such loops which are identical except for the string operated on. We can analyze the first instance starting on line 4 in the function.

# Original code — Variable manipulation
list = ""

for letter in ps:
letter = '"' + letter.rstrip() + '" & '
list = list + letter

We get O(n) Time and Space complexity in this block. The string concatenation and character inserts increase the operation overhead, though. We can reduce the number of operations by using a list comprehension. This is without changing the complexity. For example:

# Improved code — Variable manipulation using list comprehension
list = ' & '.join(['"' + letter.rstrip() + '"' for letter in ps])

Conclusion

There are three points I want us to take away. First, O(n) is the best we can do theoretically but we still need to manage the input to optimize sustainability. Second, string concatenation can be optimized using manipulation methods such as .join() to reduce algorithmic complexity. Third, list comprehension is a powerful Python feature for reducing the number of operations required in a statement.

These points are not exhaustive, though. Nor are the code suggestions fully tested and validated. We would need to clone the project, measure the performance against various size inputs, patch in our changes, and rerun the performance tests. We also want to execute a regression test to ensure we didn’t break functionality with the changes. Those seem like good tasks for a quiet Saturday morning over coffee.

If you appreciate this story, here are three actions you can take right now to support my work:

  1. Give the story a CLAP 👏

2. FOLLOW me to get notified of new stories ⏰

3. SHARE and recommend this story on your social media 🐦

--

--

Jason M. Pittman
Jason M. Pittman

Written by Jason M. Pittman

I am a forward-leaning innovator committed to solving tomorrow’s grand challenges by developing cutting-edge research and technology today.