Instantly share code, notes, and snippets.

Embed
What would you like to do?
CyberSecurityChallenge CSCBE2018 CCCPatHome Network Security

Introduction

This writeup covers my solution attempt for CSCBE2018's three Network Security challenges BLOCKSHARK (30), BLOCKSHARKNADO (90) and BLOCKSHARKNADO VS BLOCKSHARCOPUS (150). In essence each of these challenge revolve around the same concept but require you to incrementally understand more of how the setup works.

Writeup by Raven on the CCCPatHome team.

Links:

BLOCKSHARK

Challenge

One of your employees is believed to be leaking information to a competitor in return for Bitcoins. Fortunately, we were able to capture network traffic when he was exfiltrating data!

It is believed he was transferring a super secret nota which starts with the following string: Top Secret !!!

Attachment: data_exfil.pcap [7.09 MB]

Analyzing the challenge

The attached .pcap file only contains TCP and HTTP requests from ip's 192.168.0.2 and 6.6.6.6. It appears the employee is retrieving information on bitcoin blocks and addresses in json format by requesting the following from 6.6.6.6:

GET /block/312331?format=json HTTP/1.1
GET /block/312309?format=json HTTP/1.1
GET /block/312361?format=json HTTP/1.1
GET /block/312373?format=json HTTP/1.1
GET /block/312372?format=json HTTP/1.1
GET /block/312393?format=json HTTP/1.1
GET /address/1f620e09863c3d9321492c06096b3e492012489b3b5dc03d3d6d305d082d5d9e2148301109a211?format=json HTTP/1.1
GET /block/312388?format=json HTTP/1.1
GET /block/312304?format=json HTTP/1.1
GET /block/312322?format=json HTTP/1.1
GET /address/58d93309a22a1f5817580f13484d0a58e535097f0e091d1304e70609ba0e16031809ab1b589b0e?format=json HTTP/1.1
GET /address/4817395d782f040e124961231f8a3e49100958a11e58cc0904e6004933003d7a2a4881251fc30b?format=json HTTP/1.1
GET /block/312325?format=json HTTP/1.1
GET /address/191f325d7f3609e00f097400487e0b04350e1f96215dfe1d49342904b42909753358f93858c431?format=json HTTP/1.1
GET /block/312346?format=json HTTP/1.1
GET /address/58d401048520048e352e140e09dc0e5dd03158a0331f5437584208485c1458a02d3d742a5d9136?format=json HTTP/1.1
GET /address/3d8d1b3d660704a62f2e2f283d66025885351f603e4918092e083709d13209630d58c80158f730?format=json HTTP/1.1
GET /address/095c2749523e1f822a04db024915020938052e182f49310409630d09e4265dfa03489408044217?format=json HTTP/1.1
GET /address/099a174859163d530d58690758471e041027488b143dae151f841a1f1e3804350d5dd0015d6238?format=json HTTP/1.1
GET /address/58872c5d9e211f15235d5233042e3d588b125de7294813394858373d1125042c145d973b3d8918?format=json HTTP/1.1
GET /address/48252f1f88023dac0209e10a04f60958011f58f5312e18323d38391f791c5854035d2928582414?format=json HTTP/1.1
GET /address/09490a580f0104f13658e12904e73548733d5d56295d201404fd1f09882304321d2e1f3449762b?format=json HTTP/1.1
GET /address/09ae1848041e04d72604b3231f4f1e09452049741b58d00709be2c04b80f5db22e58b30e04c610?format=json HTTP/1.1
GET /address/040e125dc73b5dd91c58e1001f2e0858210b0455011f831904471d09a3243d2a0a04592b094811?format=json HTTP/1.1
GET /address/4965383d2b3358b32e48812558210b09ed1f097c04492c06496c20482c021fd7101fa119494f1a?format=json HTTP/1.1
GET /address/49220b48043158a432487333495c053d751c1fac205ded1004ca1509a32d584e225dc81b04653a?format=json HTTP/1.1
GET /address/5802353d8d1b5d03381f1f2c4820135d1d225d81123da3285d56195d3c04048b2e5dc3015d5d38?format=json HTTP/1.1
GET /address/4861385876071fc43004241704d3381f5a2b3d080904c31f099d2d04663758183e58f70a580b06?format=json HTTP/1.1
GET /address/58d92e58e6082e211c04e934193e1016040304012119061048552c09903158b31904142a48213d?format=json HTTP/1.1
GET /address/09701d3d0b075824143d3d3c1f3c2b5d0d2e3d581309cc131f5e1858692e1f29220454105daa16?format=json HTTP/1.1
GET /address/04cd2f493e1e040c3b04702a3d391e58ee1348281c04d30e58b82d48581f58592e193e0c046408?format=json HTTP/1.1
GET /address/160620584c305d8c1404f42f04c90509e23004d30e493a012e391704ce071f1e1f58c1375d6c1e?format=json HTTP/1.1
GET /address/09eb1e58293209ac3958f234096b0004d03358b52f094e222e182f1fac20493d3d5d5f3a5dfe1d?format=json HTTP/1.1
GET /address/047b1a1f0312585a0258992c3daa1849673e09d6003da30e58482e588e113d192b4952343da405?format=json HTTP/1.1
GET /address/09612958083719311e09a41a2e201c5831132e202909b8104873224846175d8c285d721f5dac26?format=json HTTP/1.1
GET /address/5de00909340a58223c58653e5891093d5733484422497811497b0904ac225db93809173b3da829?format=json HTTP/1.1
GET /address/5d9e051fa8132e2f32484f28048b2b042f120970355d4d0f3d9a040908161f1e30048102092e08?format=json HTTP/1.1
GET /address/5dc41704622404e42e1f2f015dee1c485506094d3d09b6074919151f742d0992342e1214580c06?format=json HTTP/1.1
GET /address/584a2004901209e52e2e202748570858b40c04ff061f2d0409be2c4857083da4152e082b192920?format=json HTTP/1.1
GET /address/09943b19092f3d1f151f6227098e1a496b00192f0809df145d991f3d1939096619095204192129?format=json HTTP/1.1
GET /address/1f061b1fcb2f48251004940309233a1f213858212948360a1fc23e160b083d9b2f584f19046c0b?format=json HTTP/1.1
GET /address/5d56193d391e1f312c482510097e173d8e02190615097309485e2d584e221fae3b49602c04453c?format=json HTTP/1.1
GET /address/09ca1258c62a48170404482758f6213d203858f622496e120943125d14243d7639094e035d4b24?format=json HTTP/1.1
GET /address/58c62c58690716012b1feb1b1fac305839351f5e185dc3015859171fb13958082909ea02094f21?format=json HTTP/1.1
GET /address/1f933409943b58cc091f753c04ec1a4964091f0b1549170a048c214869303d3f23093106097e17?format=json HTTP/1.1
GET /address/1f10335d53302e1e254825101f0a203da41c496809496f1c5d830f1fd42f58022f58680d5d0e24?format=json HTTP/1.1
GET /address/047b3209272258ab23097e1a04532b5d9b144939095d162609bf1e1fbf1204f30a04db0204ee2f?format=json HTTP/1.1
GET /address/4808354973345d9b3e485f2a58210409c514042030042a3e48201f48902c58b0285d570f5d9f04?format=json HTTP/1.1
GET /address/5d58091f4f093d660758982e1fb82209e72f585c3e1fe51d09371c5d593c2e200c040334192116?format=json HTTP/1.1
GET /address/5d5119494e31581e35585e3e04fe065d6d3504f404480e3b048c0a5d441309fb021fb00c588714042e3b58842d1f811019242f5d9e211fef3a486b2b09cd39044a255dee025d280304980c?format=json HTTP/1.1

The solution

Only the final request does not appear to contain any block or address information. It simply contains

{
    "hash160":"5cfb25c53220ec02913648a380e2b07fe0287ef2",
    "address":"19Ue2gkjFb7K3nodHSpz3DUqrVUNeNNkj2",
    "return_code":201
    "return_value":"RkxhZyAxOiBDU0NCRXtERkhKS0oqJigqVVlURyUjJDI0M30="
}

The return_value looks suspiciously as a base64 encoded string. We'll quickly decode it using the browser's built-in ascii-to-binary function:

atob('RkxhZyAxOiBDU0NCRXtERkhKS0oqJigqVVlURyUjJDI0M30=')

As a result first flag is presented to us: FLag 1: CSCBE{DFHJKJ*&(*UYTG%#$243}

BLOCKSHARKNADO

Challenge

This challenge is the follow up of Blockshark

The server the exfiltrator was communicating with has been seized and a copy of the software has been installed on: 52.214.111.33

To obtain the flag, only the same type of traffic as the exfiltrator is needed/allowed.

To prove your knowledge send the following message to the server: "gimme the second flag …" (minus the " quotes)

Analyzing the Challenge

Here we can start by replicating the requests found in the .pcap file on the live host (example).

We already know the return_value contains special information. Another giveaway for this is the incorrect formatting of the json: there is no comma delimiter after the return_code entry.

This return_value is also available in other /address/ requests. Let's translate with some more in-browser javascript.

Note: I loaded a small jQuery snippet in the devtools to allow for $.ajax() requests. These requests can also be perfomed using XMLHttpRequest().

urls = [
"1f620e09863c3d9321492c06096b3e492012489b3b5dc03d3d6d305d082d5d9e2148301109a211",
"58d93309a22a1f5817580f13484d0a58e535097f0e091d1304e70609ba0e16031809ab1b589b0e",
"4817395d782f040e124961231f8a3e49100958a11e58cc0904e6004933003d7a2a4881251fc30b",
"191f325d7f3609e00f097400487e0b04350e1f96215dfe1d49342904b42909753358f93858c431",
"58d401048520048e352e140e09dc0e5dd03158a0331f5437584208485c1458a02d3d742a5d9136",
"3d8d1b3d660704a62f2e2f283d66025885351f603e4918092e083709d13209630d58c80158f730",
"095c2749523e1f822a04db024915020938052e182f49310409630d09e4265dfa03489408044217",
"099a174859163d530d58690758471e041027488b143dae151f841a1f1e3804350d5dd0015d6238",
"58872c5d9e211f15235d5233042e3d588b125de7294813394858373d1125042c145d973b3d8918",
"48252f1f88023dac0209e10a04f60958011f58f5312e18323d38391f791c5854035d2928582414",
"09490a580f0104f13658e12904e73548733d5d56295d201404fd1f09882304321d2e1f3449762b",
"09ae1848041e04d72604b3231f4f1e09452049741b58d00709be2c04b80f5db22e58b30e04c610",
"040e125dc73b5dd91c58e1001f2e0858210b0455011f831904471d09a3243d2a0a04592b094811",
"4965383d2b3358b32e48812558210b09ed1f097c04492c06496c20482c021fd7101fa119494f1a",
"49220b48043158a432487333495c053d751c1fac205ded1004ca1509a32d584e225dc81b04653a",
"5802353d8d1b5d03381f1f2c4820135d1d225d81123da3285d56195d3c04048b2e5dc3015d5d38",
"4861385876071fc43004241704d3381f5a2b3d080904c31f099d2d04663758183e58f70a580b06",
"58d92e58e6082e211c04e934193e1016040304012119061048552c09903158b31904142a48213d",
"09701d3d0b075824143d3d3c1f3c2b5d0d2e3d581309cc131f5e1858692e1f29220454105daa16",
"04cd2f493e1e040c3b04702a3d391e58ee1348281c04d30e58b82d48581f58592e193e0c046408",
"160620584c305d8c1404f42f04c90509e23004d30e493a012e391704ce071f1e1f58c1375d6c1e",
"09eb1e58293209ac3958f234096b0004d03358b52f094e222e182f1fac20493d3d5d5f3a5dfe1d",
"047b1a1f0312585a0258992c3daa1849673e09d6003da30e58482e588e113d192b4952343da405",
"09612958083719311e09a41a2e201c5831132e202909b8104873224846175d8c285d721f5dac26",
"5de00909340a58223c58653e5891093d5733484422497811497b0904ac225db93809173b3da829",
"5d9e051fa8132e2f32484f28048b2b042f120970355d4d0f3d9a040908161f1e30048102092e08",
"5dc41704622404e42e1f2f015dee1c485506094d3d09b6074919151f742d0992342e1214580c06",
"584a2004901209e52e2e202748570858b40c04ff061f2d0409be2c4857083da4152e082b192920",
"09943b19092f3d1f151f6227098e1a496b00192f0809df145d991f3d1939096619095204192129",
"1f061b1fcb2f48251004940309233a1f213858212948360a1fc23e160b083d9b2f584f19046c0b",
"5d56193d391e1f312c482510097e173d8e02190615097309485e2d584e221fae3b49602c04453c",
"09ca1258c62a48170404482758f6213d203858f622496e120943125d14243d7639094e035d4b24",
"58c62c58690716012b1feb1b1fac305839351f5e185dc3015859171fb13958082909ea02094f21",
"1f933409943b58cc091f753c04ec1a4964091f0b1549170a048c214869303d3f23093106097e17",
"1f10335d53302e1e254825101f0a203da41c496809496f1c5d830f1fd42f58022f58680d5d0e24",
"047b3209272258ab23097e1a04532b5d9b144939095d162609bf1e1fbf1204f30a04db0204ee2f",
"4808354973345d9b3e485f2a58210409c514042030042a3e48201f48902c58b0285d570f5d9f04",
"5d58091f4f093d660758982e1fb82209e72f585c3e1fe51d09371c5d593c2e200c040334192116"
];

out = [];

function getMessage(url) {
    return $.ajax({
      type: 'GET',
      url: '/address/'+url+'?format=json'
    });
}

function translate(data) {
    return atob(/"return_value":"(.*)"/.exec(data)[1]);
}

function writeMessage() {
    console.log(out.reduce((a,b)=>a+b));
}

urls.forEach((url, uindex) => {
    getMessage(url).then(res => {
      msg = translate(res)
      out[uindex] = msg;
    });
});

$(document).ajaxStop(() => {
    writeMessage();
});

This will reveal the following message:

Top Secret !!!  A novel substance was sucessfully extracted from the leaves of the tea bush and also from kola nuts.  After complex and dangerous experimetnts a white solid was obtained with a melting point of 500K.  Chemical analysis revealed the followibg composition: 1,3,7-Trimethylpurine-2,6-dione. This new subtance will change the way in which people will be able to work,  hackers will write even more l33t c0d3 and provide hipsters with an essential ingredient for their gatherings. --

Each return_value contained 13 characters. Each requested 'address' also contained 78 characters. By manipulating the request we notice any address with n*6 characters will contain a base64 string of n characters in the return_value. Otherwise this key would return empty. Another finding is that the same 6 'address' characters (three bytes) always return the same character.

Building a dictionary

We can keep track of which three bytes form each character if we extend our script. This extension will look at each character in the return_value string and map it to the bytes from the request. This way we build up a dictionary.

// jQuery and the url array from previous snippet is required to run this code

out = [];
dict = {};

function getMessage(url) {
    return $.ajax({
      type: 'GET',
      url: '/address/'+url+'?format=json'
    });
}

function translate(data) {
    return atob(/"return_value":"(.*)"/.exec(data)[1]);
}

urls.forEach((url, uindex) => {
    getMessage(url).then(res => {
      msg = translate(res)
      out[uindex] = msg;
      // build up dictionary
      msg.split("").forEach((char, cid) => {
        dict[char] = url.substr(6*cid, 6);
      });
    });
});

After each request is parsed we have a partial dictoinary built up:

dict = {
" ":"2e200c","0":"58c62c","1":"58c137","2":"3da30e",
"3":"16012b","5":"1fc430","6":"588e11","7":"09ac39",
"!":"58d933",",":"1fcb2f","-":"192116",".":"5d593c",
":":"04ce07","A":"1f8802","C":"046637","K":"1f5a2b",
"S":"096b3e","T":"583113","a":"5d5809","b":"1f6227",
"c":"5d4b24","d":"1fbf12","e":"58982e","f":"5d9b3e",
"g":"1fe51d","h":"3d6607","i":"09e72f","k":"48360a",
"l":"58ab23","m":"481704","n":"585c3e","o":"485f2a",
"p":"496409","r":"1fb822","s":"09371c","t":"1f4f09",
"u":"58223c","v":"09ea02","w":"097e17","x":"1f4f1e",
"y":"04e42e","|":"312346"
}

The solution

To prove your knowledge send the following message to the server: "gimme the second flag …" (minus the " quotes)

function translateMessage(message) {
    urlBuilder = "";
    message.split("").forEach((char) => {
      urlBuilder += dict[char]
    });
    return urlBuilder;
}

function sendMessage(message) {
    getMessage(translateMessage(message)).then(res => {
      console.log(translate(res));
    });
}

sendMessage("gimme the second flag ...")

Upon which the second flag is returned: Flag 2: CSCBE{sdfIUerw893475#$&Y&#}

BLOCKSHARKNADO VS BLOCKSHARCOPUS

Challenge

This challenge is the follow up of Blockshark & BlocksharkNado

The server the exfiltrator was communicating with has been seized and a copy of the software has been installed on: 52.214.111.33

To obtain the flag, only the same type of traffic as the exfiltrator is needed/allowed.

To prove your knowledge send the following message to the server: "Dear 0r&cl# (what is Flag3)" (minus the " quotes)

Analyzing the Challenge

This time we also have to send an ecrypted message to the server but this time the message contains characters we don't have in our dictionary (yet!). After spending some time trying to make sense of the relation between the three bytes and their resulting character no direct relation could be established. As we've got a live server to test with an alternative and equally fast solution for finding the missing characters in our dictionary is using brute-force >:D

Breaking the dictionary

As each three bytes in an address maps to one character there are 256*256*256 = 16777216 combinations possible resolving only to a max of 128 ASCII characters. We can try sending requests for each three byte combination and see what comes out but this would take ages and put a lot of strain on the server to handle this many requests (sorry..). A better way is to build multiple combinations of three bytes and scan the whole address space partially. Using the same techniques as before a dictionary is built up of all relevant ASCII characters.

function getMessage(url) {
    return $.ajax({
      type: 'GET',
      url: '/address/'+url+'?format=json'
    });
}

function translate(data) {
    return atob(/"return_value":"(.*)"/.exec(data)[1]);
}

function cancelRequests() {
    requests.forEach(r => r.abort());
}

dict = {};
requests = [];

maxMaxHex = 256*256*256;
minHex = 256;
maxHex = 256*24;
stepHex = 1;
batchSize = 128;

for (i = minHex; i < maxHex; i += stepHex*batchSize) {
    let urlString = "";
    for(j = 0; j < batchSize; j++) {
        let hex = (i+j).toString(16);
        let hexPad = hex.padStart(6, "0");
		urlString += hexPad;
    }
    let req = getMessage(urlString);
    requests.push(req);
    req.then(res => {
        let str = translate(res);
        str.split("").forEach((chr, cid) => {
            if(!dict[chr]) {
                hexStr = urlString.substr(6*cid, 6);
                console.log("Found character", chr, hexStr);
                dict[chr] = hexStr;
            }
        });
    });
}

This way we've quickly built up a full dictionary containing all the characters we need to send the final message.

dict = {"0":"000528","1":"00072e","2":"000208","3":"00023a","4":"000123","5":"000212","6":"00023d","7":"000126","8":"000c34","9":"000526","|":"000100","=":"00010e","Q":"000110","q":"000114","x":"000116","U":"000119","[":"00011a","A":"000124","z":"000127","a":"00012c","L":"000134","t":"000136","N":"000137","k":"00013d","X":"000200","<":"000202","g":"000205","u":"000206","S":"000207","%":"000209","Z":"00020a","]":"00020e","c":"000211","`":"00021c","?":"00021e","J":"000226",">":"00022d","_":"00022f","~":"000238","l":"00023e","e":"000303","Y":"000304","!":"00030a","@":"00030c","T":"000313","K":"000314","^":"00031b","R":"00031e",".":"00031f","D":"000322","O":"000323","o":"00032f","'":"000403","y":"000406","j":"00040e","&":"000410","E":"000413","P":"000414","W":"00041f","-":"000426"," ":"00042a","i":"00042c","$":"000434","C":"00043a","H":"000508",";":"000512",",":"00052e",")":"00060a","\"":"00060c","}":"000633","v":"00063c","n":"00063d","G":"000702","w":"000709","s":"00072d","(":"000733","B":"000738","+":"000739","F":"000816","*":"00082b","#":"000834","/":"000900","f":"00090c","d":"00090d","\\":"000922","I":"000a01","r":"000a0d","p":"000a24","V":"000a31",":":"000a3b","{":"000c1a","M":"000e2a","m":"000e31","h":"000f21","b":"001411"}

The solution

To prove your knowledge send the following message to the server: "Dear 0r&cl# (what is Flag3)" (minus the " quotes)

function translateMessage(message) {
    urlBuilder = "";
    message.split("").forEach((char) => {
      urlBuilder += dict[char]
    });
    return urlBuilder;
}

function sendMessage(message) {
    getMessage(translateMessage(message)).then(res => {
      console.log(translate(res));
    });
}

sendMessage("Dear 0r&cl# (what is Flag3)")

And the final flag is revealed: Flag 3: CSCBE{jz2h478dfg^#%%$%jdfj}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment