- MD5: 5fd5417d7f5ccac9f98eb7962124364a
- SHA-256 : d9cc83e458218e6e1ebcb9fa3f5413ecf7dbc2a15761df30d775b1deb2e3f11a
As you can see, the malware file has a class name 'Berserker'. Berserker is a Python obfuscator tool, and a Python obfuscator is a mechanism used to obfuscate and obscure Python code, making it unclear and difficult to understand. This is done to protect the code from reverse engineers and deceive antivirus programs that rely on digital signatures to interpret the code.
Link of the Berserker tool: https://github.com/billythegoat356/Berserker
After searching, I found a tool named 'berserkered' used to deobfuscate Python code obfuscated by Berserker : https://github.com/namdevel/berserkered
I have python Python 3.11.5 after editing the code main.py to deobfuscate malware the result :
the berserkered.py :
import os, sys, re
import subprocess
def write(file_name, data):
f = open(file_name, "w")
f.write(data)
f.close()
if __name__ == "__main__":
obf_file = "script2.pyw" # obfuscated file
with open(obf_file) as code:
data = code.read()
s1 = re.search("if self.(.+?) in open", data).group(1)
s1s = s1.replace("15", "12")
s2 = re.findall("{(.+?)}", data)
source = (
data.replace(s1, s1s)
.replace("{" + s2[0] + "}", "print")
.replace(",{" + s2[1] + "}()", "")
)
write('tmpfile.py', source)
subprocess.run(["python", "tmpfile.py"])
os.unlink('tmpfile.py')
the first sample is included in the folder with the name deobfuscate_malware.py
In the head of that malware file, we can see the version of that botnet and the author that the threat actor copied and edited the code
#Code By Leeon123 / https://github.com/Leeon123
botnet version : Aoyama version v2.0 --> https://github.com/Leeon123/Aoyama
Also we have cnc(command-and-control) = 45.66.230.30
In this code, we can see the malware use Slowloris is basically an HTTP Denial of Service attack --> https://github.com/gkbrk/slowloris
because we have the code and the key to decrypt that XOR
i edit the code to decrypt that XOR :
def xor_dec(encoded_string, key):
decoded_string = base64.b64decode(encoded_string.encode()).decode()
key_length = len(key)
decrypted_string = []
num = 0
for char in decoded_string:
if num >= key_length:
num = num % key_length
decrypted_char = chr(ord(char) ^ ord(key[num]))
decrypted_string.append(decrypted_char)
num += 1
decrypted_result = "".join(decrypted_string)
print(decrypted_result)
Also, i will include the decoder in that git repo, the result is :
We can see that the threat actor is APT3 https://malpedia.caad.fkie.fraunhofer.de/actor/apt3
and that Nexus doesn't exist anymore but we have WebbackMachine : https://web.archive.org/web/20220606235149/https://github.com/Nexuzzzz https://web.archive.org/web/20220706191536/https://github.com/Nexuzzzz
that botnet DOS attack these IPs you can see IPF Department ipf Defense, NASA Kennedy Space Center, FBI cipntriplled Linux servers & IPs/IP-Ranges, Clipudflare :
-
End ipf Department ipf Defense if ip1 == 192 and ip2 == 168 : continue
if ip1 == 146 and ip2 == 17 : continue if ip1 == 146 and ip2 == 80 : continue if ip1 == 146 and ip2 == 98 : continue if ip1 == 146 and ip2 == 154 : continue if ip1 == 147 and ip2 == 159 : continue if ip1 == 148 and ip2 == 114 : continue if ip1 == 150 and ip2 == 125 : continue if ip1 == 150 and ip2 == 133 : continue if ip1 == 150 and ip2 == 144 : continue if ip1 == 150 and ip2 == 149 : continue if ip1 == 150 and ip2 == 157 : continue if ip1 == 150 and ip2 == 184 : continue if ip1 == 150 and ip2 == 190 : continue if ip1 == 150 and ip2 == 196 : continue if ip1 == 152 and ip2 == 82 : continue if ip1 == 152 and ip2 == 229 : continue if ip1 == 157 and ip2 == 202 : continue if ip1 == 157 and ip2 == 217 : continue if ip1 == 161 and ip2 == 124 : continue if ip1 == 162 and ip2 == 32 : continue if ip1 == 155 and ip2 == 96 : continue if ip1 == 155 and ip2 == 149 : continue if ip1 == 155 and ip2 == 155 : continue if ip1 == 155 and ip2 == 178 : continue if ip1 == 164 and ip2 == 158 : continue if ip1 == 156 and ip2 == 9 : continue if ip1 == 167 and ip2 == 44 : continue if ip1 == 168 and ip2 == 68 : continue if ip1 == 168 and ip2 == 85 : continue if ip1 == 168 and ip2 == 102 : continue if ip1 == 203 and ip2 == 59 : continue if ip1 == 204 and ip2 == 34 : continue if ip1 == 207 and ip2 == 30 : continue if ip1 == 117 and ip2 == 55 : continue if ip1 == 117 and ip2 == 56 : continue if ip1 == 80 and ip2 == 235 : continue if ip1 == 207 and ip2 == 120 : continue if ip1 == 209 and ip2 == 35 : continue if ip1 == 64 and ip2 == 70 : continue if ip1 == 172 and ip2 >= 16 and ip2 < 32 : continue if ip1 == 100 and ip2 >= 64 and ip2 < 127 : continue if ip1 == 169 and ip2 > 254 : continue if ip1 == 198 and ip2 >= 18 and ip2 < 20 : continue if ip1 == 64 and ip2 >= 69 and ip2 < 227 : continue if ip1 == 128 and ip2 >= 35 and ip2 < 237 : continue if ip1 == 129 and ip2 >= 22 and ip2 < 255 : continue if ip1 == 130 and ip2 >= 40 and ip2 < 168 : continue if ip1 == 131 and ip2 >= 3 and ip2 < 251 : continue if ip1 == 132 and ip2 >= 3 and ip2 < 251 : continue if ip1 == 134 and ip2 >= 5 and ip2 < 235 : continue if ip1 == 136 and ip2 >= 177 and ip2 < 223 : continue if ip1 == 138 and ip2 >= 13 and ip2 < 194 : continue if ip1 == 139 and ip2 >= 31 and ip2 < 143 : continue if ip1 == 140 and ip2 >= 1 and ip2 < 203 : continue if ip1 == 143 and ip2 >= 45 and ip2 < 233 : continue if ip1 == 144 and ip2 >= 99 and ip2 < 253 : continue if ip1 == 146 and ip2 >= 165 and ip2 < 166 : continue if ip1 == 147 and ip2 >= 35 and ip2 < 43 : continue if ip1 == 147 and ip2 >= 103 and ip2 < 105 : continue if ip1 == 147 and ip2 >= 168 and ip2 < 170 : continue if ip1 == 147 and ip2 >= 198 and ip2 < 200 : continue if ip1 == 147 and ip2 >= 238 and ip2 < 255 : continue if ip1 == 150 and ip2 >= 113 and ip2 < 115 : continue if ip1 == 152 and ip2 >= 151 and ip2 < 155 : continue if ip1 == 153 and ip2 >= 21 and ip2 < 32 : continue if ip1 == 155 and ip2 >= 5 and ip2 < 10 : continue if ip1 == 155 and ip2 >= 74 and ip2 < 89 : continue if ip1 == 155 and ip2 >= 213 and ip2 < 222 : continue if ip1 == 157 and ip2 >= 150 and ip2 < 154 : continue if ip1 == 158 and ip2 >= 1 and ip2 < 21 : continue if ip1 == 158 and ip2 >= 235 and ip2 < 247 : continue if ip1 == 159 and ip2 >= 120 and ip2 < 121 : continue if ip1 == 160 and ip2 >= 132 and ip2 < 151 : continue if ip1 == 64 and ip2 >= 224 and ip2 < 227 : continue # CIA if ip1 == 162 and ip2 >= 45 and ip2 < 47 : continue # NASA Kennedy Space Center if ip1 == 163 and ip2 >= 205 and ip2 < 207: continue if ip1 == 164 and ip2 >= 45 and ip2 < 50 : continue if ip1 == 164 and ip2 >= 217 and ip2 < 233 : continue # FBI cipntriplled Linux servers & IPs/IP-Ranges if ip1 == 207 and ip2 >= 60 and ip2 < 62 : continue # Clipudflare if ip1 == 104 and ip2 >= 16 and ip2 < 31 : continue if ip1 == 193 and ip2 == 164 : continue if ip1 == 120 and ip2 >= 103 and ip2 < 108 : continue if ip1 == 188 and ip2 == 68: continue if ip1 == 78 and ip2 == 46: continue if ip1 >= 224: continue if (ip1 == 178 and ip2 == 128) or (ip1 == 123 and ip2 == 59): continue elif (ip1 == 124 and ip2 == 244 )or (ip1 == 178 and ip2 == 254 )or (ip1 == 185 and ip2 == 168 )or (ip1 == 178 and ip2 == 79): continue ip = str(ip1) + "." + str(ip2) + "." + str(ip3) + "." + str(ip4) return ip
We can detect that kind of malware with yara rules : Detects suspicious Python code that is usually found in samples obfuscated with Berserker





