Malware Analysis | SikoMode
I’ve been working on the PMAT course from TCM Security for the last little bit and it’s been really interesting to learn more about these tools and actually participate in some hands-on malware analysis. For this specific writeup, everything has been done hands-on. The hash was submitted to VirusTotal post-analysis to verify (and to satisfy the questions that were laid out in the challenge). Other than that, everything was hands-on.
First Touch
First things first, getting hashes:
|=========================================================================|
| TYPE |HASH |
|=========================================================================|
|MD5 |b9497ffb7e9c6f49823b95851ec874e3 |
+------+----------------------------------------------------------------+
|SHA256|3aca2a08cf296f1845d6171958ef0ffd1c8bdfc3e48bdd34a605cb1f7468213e|
+------+----------------------------------------------------------------+
Checking through the strings of the sample, a few of them stood out to me. Firstly, multiple strings indicated that the program was written in nim. It also includes one URL, the nim httpclient module, and two file paths locally.
---
@invalid http version, `
@HTTP/
@Proxy-Authorization: basic
@Connection: Keep-Alive
@Connection
@Host:
@Host
@ HTTP/1.1
@User-Agent
@user-agent
@tables.nim(1144, 13) `len(t) == L` the length of the table changed while iterating over it
@Content-Length
@iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it
@field 'contentType' is not accessible for type 'MultipartEntry' using 'isFile =
@Content-Type:
@; filename="
@Content-Disposition: form-data; name="
@iterators.nim(249, 11) `len(a) == L` the length of the seq changed while iterating over it
@field 'fileSize' is not accessible for type 'MultipartEntry' using 'isFile =
@field 'isStream' is not accessible for type 'MultipartEntry' using 'isFile =
@multipart/form-data; boundary=
@Content-Type
@iterators.nim(173, 11) `len(a) == L` the length of the seq changed while iterating over it
@SSL support is not available. Cannot connect over SSL. Compile with -d:ssl to enable.
@https
@No uri scheme supplied.
PathFileExistsW
@shlwapi
@shlwapi
:state
DS_STREAM_RENAME1
@:houdini
@Authorization
@Host
@httpclient.nim(1144, 15) `false`
@Transfer-Encoding
@Content-Type
@Content-Length
@httpclient.nim(1082, 13) `not url.contains({'\r', '\n'})` url shouldn't contain any newline characters
@http://cdn.altimiter.local/feed?post=
@Nim httpclient/1.6.2
@Desktop\cosmo.jpeg
@SikoMode
@iterators.nim(240, 11) `len(a) == L` the length of the seq changed while iterating over it
@ccc
@Mozilla/5.0
@C:\Users\Public\passwrd.txt
Unknown error
---
Also, there’s the string toRC4__OOZOOZOOZOOZOOZOnimbleZpkgsZ8267524548O49O48Z826752_51
which looks like some sort of function inside the binary. We’ll check this out later. Other than that, there’s not much more to do before running it, so let’s run it.
Second Touch
At first run, it just deletes itself. :) So we have to look a bit deeper as to what’s happening. Wireshark captured this GET request heading out to a uri that wasn’t listed in the strings. I’ve tried this where it both gets a response and doesn’t get a response and it continues to delete itself, so maybe checking the paths that we found in strings might prove useful.
Those two file path strings show up in the procmon readout of running the binary, and what’s more interesting is it’s trying to read cosmo.jpeg
and failing. Let’s try re-running with a file in it.
It runs successfully, and then it deletes itself afterwards. I captured it running through procmon and wireshark. Looking at wireshark first, now it’s reaching out to the URL that we saw earlier in strings, with a ?post=<DATA>
over and over exporting something. Interesting that it’s doing exfil with GET requests instead of POST requests.
The export looks like BASE64, but I tried reconstructing stuff from the very beginning of the exfil and it didn’t work. But the string that I found about a binary above, the toRC4
function. I did some more digging with a decompiler, and a function called stealStuf_sikomode
is calling the to_RC4
function.
So that’s pretty much confirmed that the output is encrypted using RC4, but now we had to find the key. Well, the other file path from above, password.txt
seems like the best place to look. That file was still on the computer, so checking it out gives us the password used to encrypt the data being sent out.
Final Conclusion / TLDR
The malware sample here was a stealer, designed to take the file cosmo.jpeg
from the user’s Desktop and exfiltrate it to cdn.altimiter.local
through a GET request. The data was included in the GET request using the path /feed?post=<DATA>
, and the data was RC4 encrypted and Base64 encoded. The password for RC4 was written to the machine, in a file named password.txt
. The binary deletes itself if:
- The binary cannot initially reach
update.ec12-4-109-278-3-ubuntu20-04.local
- The binary completes data exfiltration
- The binary is interrupted during data exfiltration (ie. network connection is removed)
The binary was written in Nim, and was compiled into a 64-bit binary.