Overview

Sample: f864922f947a6bb7d894245b53795b54b9378c0f7633c521240488e86f60c2c5

MalwareBazaar Database

Requirements:

  • pip install pyelftools

Examining our ELF file

from __future__ import print_function
import sys

sys.path[0:0] = ['.', '..']

from elftools.elf.elffile import ELFFile


def process_file(filename):
    print('Sections in ELF file:', filename)
    with open(filename, 'rb') as f:
        elffile = ELFFile(f)

        for section in elffile.iter_sections():
                print('  ' + section.name)



process_file("tmp/blackmatter_elf.inactive")
Sections in ELF file: tmp/blackmatter_elf.inactive
  
  .interp
  .note.ABI-tag
  .note.gnu.build-id
  .gnu.hash
  .dynsym
  .dynstr
  .gnu.version
  .gnu.version_r
  .rela.dyn
  .rela.plt
  .init
  .plt
  .text
  .fini
  .rodata
  .app.version
  .cfgETD
  .eh_frame_hdr
  .eh_frame
  .gcc_except_table
  .tbss
  .init_array
  .fini_array
  .jcr
  .data.rel.ro
  .dynamic
  .got
  .data
  nocommon
  .bss
  .comment
  .shstrtab

We can see that our ELF payload has a section named .cfgETD This is where the config data resides in current BlackMatter ELF payloads

def get_config_section_data(filename):
    with open(filename, 'rb') as f:
        elffile = ELFFile(f)

        for section in elffile.iter_sections():
            if section.name.startswith('.cfgETD'):
                return section.data()

config_data = get_config_section_data("tmp/blackmatter_elf.inactive")
config_string = config_data.decode("utf-8") #we do not add the 'validate=True' parameter
print(config_string) #if this does not print out a clear base64 string, something has gone wrong
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
JQwAAA==
 

Base64 Decoding

import base64
config_b64_decoded = base64.b64decode(config_string) #now we decode our base64 string into a bytearray
print(config_b64_decoded)
b'x\xda\x8dV\xe9_\xdaj\x13\xfd\x85\x90\x84\x18\x96\x04H\x08$\x04H\xd8\xf7\xcd\x00"(\xb2\x16AQ\x08\xa0\xa2"eqC\xad\xb8\xb5\xd6\xf6_\xbf\xa0\xa5\xaf\xf7~z?\x9f\xcc\x9c93\xcf\xcc\xc9t\xbcU*l=tF\xdb\x93\xf2\xd9\xe5]#v~\xf9\xf8\xb8\x1dy\x18\rg\xf9a\xfd:E]\x0f\xc6\xc3A\xdbAy\x8bo\xb9J\xc6\xf8\xc3\'D\xe2\xd0L\xa7&\x19\xb7jE\xda9\xb6\x83\x06@\xbeJy\x15N\xeb\x9eo\x81{\xe2Y\xc5\x9d\xce\xea\xc0\x9e\xd7\x91l}\xb5\x11\x9e\xea\xb8#{\xd3P\xf1\xc6\xd2\xe6\xd4\xdb\x81\xd6\x9cs\x94\x92\xe2\xd0\xe7See\xd2&8\xd6\xad|\x0b\xb8\x0c\xbc\xcf\xae\x0e+\xdd\x99a\xdb\x9br\x96\xa0}yj;ak:\xaf3m\xa8\xb3\xc6~\x9b\xd9&\xed\xd7\xda5\x7f\x0c\xd1\x17^8T\xf7?d\x82\xda\xbc?\x03\xba\xab\x87~\x81\x0f!\x84)8C\x05\xc5F\x99.\x03\xba\r\xee\xb5O\xec\xeb\x8d\xa2!\x8b\xb6\xf5!=\x19\x03\xf3\x9c\xedM\xa3\xeb\x9e\xac)Y\xcb~\x8e\xfa5I)\xfd\x19\xe3\xd0\x1dW\x7fq\x10\xeag1A9\x036\xc2*\x17O\x1b\xd9\xd7\x9e%\x9eyy%|\x91\\\x98w\xb4.S\xd1\x19\x07%\x94\xe3\xbdY0\xab7\xae$\x86Z\xab\x16\xd4Iy\x05\xb2i\xd7;\x8fgi\x84\xbbHh\xeb.\t\xd1\x90+\x18x\xd6ri\x88\rY\xa9\xa8\x14V_}\xac\xba7eD\xc1\x0bsGf\xc4\x13\xb9\x16\x9d"S\x05\xa1M\xf6\x87d\xe3\xfdI\xb5M\xa0\x7f\xa7\xed6=\x14\x04\xc6\x1d8\xf1\x8b\x8c\x16\x99\x11\xe8\xcan\x05\x7fg\x12jA\x9d\x95{\xef\x1c6"l\xd59o2Z9o\xed9Q\xe8\xdcw\xc4\x19\xdcO\xe6\xc6\xfe\xf6\xbd6DOO\xa4g\xed\x9bh\x0f\xb2?l\x01R{\xc4nE\xb4Q \r\x89;\xbdH\xc0l\xbc\x16\x8e\xe5\xcd-\xd1\x7fo\xdd\xc8\xee\xc9\x82\xde\xa0x\x9axeL\x91\x94\xb1\x992\xa0q\xd8\xf1\xc2\x9c0\x1d\x0f*\xd8\x04\xac\xea\xe7\x9f\xa8}\xbbM\xc2\xbbu\xc0\xc0Q\x01\xd8\xaeEl^\xedz\x94\x08\x80i\x060\x04\xd3\xe7\x92O\xa6dM\x98\xa8e:dk\x8f\x8e\xb9\x12>U\x92\xdb\xd2A\x14\xbe\xfe\xd3\xea5S\xad\x8c^\xd8[1\xa6\xe3\x1b\xbf\xb4amz\xcd\xfc\xa2h\x1a\xf9W\x8d\xe71\xe3\x8c\xbcPp\xbc\x1b1\x1d\xdb.\xa36\xe4\xa7\xdc,5\xb6f\xa1_d\xffT\xabdc\xee\x92\x10\xff\x8d\xab\xd2\xc7<u\x10\xd4\xb2H\xe8;\xb4\xd3\xf2PX\x08i\xfby\x83\xdf\t\xa4\xc3ab\x9f\xeb\xdaD\xc5\xa9\xc6\x98v\xf5\xf3krM\xc2\xca)\xa1\x87u\xc2\xc3\xfa\x83\x05S\xcb\xd8\xf0\x80\xd6\x8a0\xf1\xa5\xd6B\xfc\x891\xd2t\x92\xbb>\xe4\xeb\x86\xe8\xa6V|I\x15L\xc4\x00\xc8\xcd8&y\x0f\xbdy/7\xed\xac\xda1\xc4\xcd\x01\x0e!\xce>\x1b\x12T\x1c>\x1c\xd5\xfb\x8d;]\xa5\x82\xe0\xce\x13\xd9\xa8b\xa0B\xb2\xdb\xb6qW\x1b\x8e\xd9\xfa\xdd\xe3\xe2Uy\x927[\xf8\xae\x8a\xeeR\xf6S\x03N\x01\xce\x95 \xc9tJ\xfd\xa7\xf1\xcd\xaf\xe79>\x82@0M\xecW\xd5\xbf\xaf\x88V\xb1\xd0\xfcZ\xb8E;JyP\x18\xbf\xb4\x1e\x89\x94\x96\xcf\x97~\xcc\t\xaa\x92tE\xb4\t3\xe8,=\xd7\x18N\xe3\xb7\xb9]\xed\xd7\xdby\xfe\\u^@U\xadG\xac,\xa2\xe4\xa8\xb3\x93\xe9\x8e\xb2\xd7\xea_\xee\x0cZ\x8b\xfc\x93\\\x05I\x1e\xb2\x9a.\xcco\x13\xe5\x93\xe6Y\xe7\xed\x08;.\xdc\xd4\x86\x7f\xf0<b\xccr\x0c\xa8\xc1/\xb0V\xb9\xb5w{3\xad\x19\xeb\xa5\xf9.\xf7\x89\x10\x11D\xe3\n\x88{;\x05\x8c@\xe7\x1b\xd1\xd6\xa1\x06w%\r\xf4\xa69<\x12\x89\xdf\xd0I\xd9\xc5tQ@\xc02X\x14\xa8\xa3W\xc0\xbd\xef\x05q\xfc\x91`\xd0z\x1ca^\xc8\'\xafT\xef\x08\x96~\xc4;\x93\xf4\x87\xc4i\x8d\x01\xc0\xb8\xe0\xee\xef<\x973\xb2U\x10\x02W\x89B\x7f!q\x81\x9f\xe9\xfd\xf4\xdeno0\xa4\xa7\x0fFWj\xb8\xe2T\xc8O\xd6{\x9a\xca\xef\xc5\x07t\xe5\xfb{\x82\xa9\x82\x8c\xb8\x04W{Z\x0cO?\x9aP\xa9vpG\x83B\x81y\r\xb7\xf46\r~n\x02\x95:U\x95\x19\xbd\xb3\xd5>-\xec\x11\x80_\xf1\xa0\xa8\x88\xd9\xf0\x9f!-\xe2\t5h\xc4\xc7\xfb\x0c\x86S\x01|1\xc4\x0f\r\x9e\x9de\x93?\x86\xb0T\xb0\xd4\xf8\xbc\x8c\xbf\x85\xff\x83\xd7\xfe\xe0\xfd\xb4\xe7o\xfc\xf5;\x0e\xb8\x95\xa1\xfbe\xbc\xd1\x80\xbe\xc73\xb9E\xbc\xe5`\xbb\xb23\x94\x07\xb6\xe5\xf9\x05~\xdbJ\x16\xc7\x7f\xf9=\xcc\xa7\xfc\xd5#\xee\x82\xf9\xc3\x9f\x11\xdfq\xf4\x13\xff\x08\\\xd6w6\x8f\xa7\x1awz\xa9\xe0]\xe0\xc6\xff\xd6\xff\x87\x7f\xa9/\x95|\xc7\x0f\x1a\x15\xee\xc2~\xb3\xd4\xd7\xf9/\xbfa\x1e\x7f\xf6\xfd\xda\xa7\xd8~\xda\x9c\x00\x9d\xceG\xfc\xd9\xd4T\xdc\xfdW~\x93|C\xc7\xeb\x96\xf9\xfbs\xfc=^\xf8\xc0\xcf\xff\x95\x7f\xa1\xdf\x8d%\xcdo\x87\xb3\xda\r\x84\x88c\xbf w\x8d\xb0d\x97\xd1\xcc\x13\\"\x16DruM8\xdb\xf4aY\xbaZG\xc2\xc2\xd0e\x8a\x1b\xa2\x86\x98\\\xdd\xbb\xdb\x87\xd5\x12\x95\xcd\xc3#\x0c\xb7\xac\x15\x04\xb0^G\xa3\x82(<\x98\x93\x98\x17\xbb\xc8\x89\xdc\x9c"\x83K\x8e\x16\x01\x14\xd8\x80"^k\xc9\x14\xae\x8d\xf3\x01\x19!\x82\xe4\x84\xc0\xd0L\x1b\xe6$Y\x90\x00\x95\n\xcbW\xd0n\xea\xd5-\x81\xd8Ph\xc5Fp\x8aK\x90\x90\xecNBh\t\x10Z\xad9\x85)\x02Le=#\x11\x88\x87\x06d\n\xb8\xe2\xdc\xfa*\x92:\x95W\x11<Yd\x0c@\x93W\xd8ju\x08\x1c\xf0\x0e\x91\xfc\x9er\xccE\x8a\xdc\x8d\xaa]\xe5\xcd\xdebKFh#\x90@\xf7\x14\xe4\xdb\x98\xf6\xcf\x9b\xc0\xca&g:M#\xdbc\xabz)}B+q\x93\x15\xb2]\x93\xc6\xa9L\xeb\x0b;D"V\xf4\x93n\xbd\xa9\x119VVe\xf8\x95\xc4\x14W\xd8DA@{hIpgD6\x8b\xf9\xcbnRF\xf2:V\xa6g\xae*\x0cN5\x83\x98\x80n\xe6K\x9c{>\x07\x0e|/\xf1\x8e\xf0X*f\\Z\xef\xd2h\x01\x8c`i\xe8XQJ{"\x83\x076ZL\x93n\x98&2\x9b\x15\xa5\t\xb9\x92\x08\x98Z\x89\xe1v\xb0SG\xfc\xfcp\x95x\xd6\xf2\x98/\xa7&\xd7\xdb\xacFR\xda\x0bpq\x08!|u\x1a\xee\xccG\xa9\xe1\x07`\xb4\x18RL4\x90\xfc\xae\x05\xb0\xb8\x14=\x01\x8aC\x00\x8f\x983t\xcfB\x0e<\xe2\xa7\x0f:*\x18\x07\x82\x84j\x85\x00\xbe\x0e\xa1\x94\x8a\xac+\x02c\x9f\xff\x0f\x85\x89\xf0\xe8\xccF\x89u\x10\x0f\xec\xa8(\x83\x13\xc4\x06J\xd6\xb5\xdePb\x80\'G\xd4\x15\xea&\xab\xba\x8d\x13\x1aV\xcee<\xb0E\x0c\x8e\x14\xbc`\x17 \xaf\xff\xd7K\x95\x99\xf0lV\x00\x1cO\x13\x8bN\xc4(\x1ehp`\xe4\x9c\xf6\xbbSG\x8fe\x8d\xda\xdc\xb0\xf7*\xa8\x89\xd9h\x18\x88\x82\xdc\x8b;j5\xee``\xf2\xce7\xa25*\x83j3\xb7\xdeC\xd5\x92\xde!\xb5\x94+3d1\xcd)\x1f\x1f\xc8\xc5\x00h\x1f\x19\xaevC$w\x07^\xde\x96\xc5C\xd9z\xe9\x90\xc0\x809\x05\xdcSk\xaf=\xa2\xc3\xfdR\x1b\xbd/\xfd\xc0\\q@\xb8\x83`\t\x1c\xfc\x9e\x1c\x84)N\x17\x15\x9f\x9eT\xc1\xa6w\xef\x1bj\x06\xbd\xa5C\x13\xab\xf4w\r2\x1d\xea\xc2C\xcc\xa9Q\xfex\xe7\x17\xb5\x99\xfd\x0c\x1a$\x0e\x0c\xabe\r\xc3hb]|\x1b3{1!Ly\xf9-\x059{\x08[\xda\x9a\xa6\xda\x9b\x8e\x0f\x06\xaec\xd7\x91\xe1\xd4\x8d\x1d\xd6\xbf\xc6\xfc\\G\xaepL\x868\x11_\x99\xdfU\xba*[m \x08\x8d;$\x92P\xb1\x01\xc3\xd7\x9a1\xa2\x98o\x1d\xcc<cv\xdd\xc4\x11Z\'\'\x81\xea|\xd6?\xd3\xb6\xc0\xaa\xa9\xe0\x97m\xd6\xc7\x9a\xa0\x90\xb8ie\x89+\xb9SSeW\xf7\x95U\xc0t\x95\'`\x0crR\xf1\xda\x17\x0bj\xf5\xdaB\xc8S9\xb7X[\xd5\xcf\xd4bm/\x8eIl\xa82\xdb\xe7\xe6\xb45Y\xde\x95\x0b\x99\xe7\x0c\x84\xc9{\xb4R\x01\x90l\xab\xfd\xe5fy\x18\xfav\x9fx\x90\x05.\x8e\'y\x05\x11\x05\x0e4x\xee\xa7\x9cj\xb4\xf1\x19\xf2\x80\x1e\x1d\xec9\x1f\x9e]\x86\x1b\xc4\xdb\x16\x1a\x95\xde\xe1\xf20\x955\xd4\xda\xc2\xfd\xa4\xc63\x7fo/\x8d\xf7=\xc0\xa3\xfcX\'6\xb0C]\xc1\x13\x81\xf2\xbdf\xc9\xd6x\xeb2\xb9\xeb\xe5e.Fu08/ \xf2\xfb\xf3e\xdeU\x8b\xd1\xf8\x8b\xfb%548i\x84\xcc\x96\xcfQ\x94\x83G\xfb\x8c\xa2t\xfa\xe5\xf3i,\x0b\xba\x18\xd1\xf0\xff\xbe-#&\x8b\xbdi\x06\x00\xf3\x14\xe1\x01\xe6\xafD\xea_\xf6g\x99\xdf\x8d\x1b\xadu\x07\xac\x9b+Kk\x18\xc9\xe5D\xf4TU\xd9\x95.\x8a\xf37\xff\xd9_\xcda\xccN\xf25\xd8(\x94\xab\r)\x98\xfbl-}\x1c]%\x1d\xa3b\xc6\xcek8\x92\xff\xe4\x8e\xef\xe6\x97\xf6\xad\xbaD\xd7\x01\xa0L\xe9\xa2g\xaaT\x84\xe36@\x80\tn!\xe5\xbf=\xb6\xbc;<=y\xaf\xf0\xbe\x0b\xc0\xc6n:\xcf\xc0\xc0l\xf6\x7f[\xb4&\x12\x9d\xff\x85(o?\x1b\xe0E\xd9H\x99g\x16?\xe8\xd9\x89-\xdb\x94\xfcx\n\x87;\x83\x7f\x00k\xee\xb1B%\x0c\x00\x00'

Zlib decompression

Throwing our bytearray into cyberchef, any kind of 'magic' tool, will tell us that our data is compressed by zlib's 'deflate' algorithm.

We can gleem this from reverse engineering the payload in a dissasembler to spot a single call to the compress function

We need to decompress this data with the zlib 'inflate' algorithm before we continue

import zlib

#as functions in code, zlib's deflate and inflate algorithms are referenced as compress and decompress

decompressed = zlib.decompress(config_b64_decoded) #a simple decompress function will uncompress our data
print(decompressed)
b'mfBFDBtWeKgGajpP3hjuuK1tedsCdMl9\x16lbfdbV%\x16*E}AH=\x19z+#14\x05s\x13\x0e\x15\x1b(\r\nUN]$\x03\x17\x01\x045\x16*\x08& Q+=\x19z+)4>\x08p\x13 %\x0bw<\x07>M5P0m\x13\x1e[$S\x17H*3;\x1d9}Y\x12\x1dA%F86d++\r>\x02U@\x03f\x13\nq-\'\x17"+$\x0e0\x0c(=dV*9&F\x05R\x049K7!S&l=V\x05W:\x1cqs!gV{Ll"]\x05\x18i*\x06/M,t=.\x12C,=\x03(JZ,#"/\x07\x11\x1a.s\t#\x08?G\x18G\x01\x13?\x1e{`\x11R\x14\x196\x17>\tV\x14/\x14\x153\x03C\x1e!}\x0f\x13X^:\x0c\x1c\x1fRA\x16~g9\x0c,=\x19d(4\x0eI%\x11\x0ew67\x16&-!\x11 \x046_P>{\\\x1f4=x{\x11+1A0"%Tj92s\x1e\x057\x0cfQs.>\x14\x19\n7d\x12 \x12\x03\x13UC\x08\x07@$\x14&]s;\x07\x1ei7\x12M\'U\x07\x0f\x15\n\x0b\x03aT\'\x0f\x11?\x02FE\x0c#5{+\x1c\x0e\\m\x1b6#*\x06\x1e[\x1d\x07)1l6&6\x1bJ\x03\x05@\x1czU!",8\x0e!#\x18\x7f;$!\x14\x05.\x01fW\x067~\x152E\x1be\x03\'>B.\x7f=7\x0e#\x0e>\x04*p%!\x110 \x13&n=\x12\x04" \\&\t\x05h+[\x1e\x17(v\x1dPRKr\x12/\x18m^Uw\x12}6$.\x1cz!-\x15\x12[\x1cB1\x122\x01;\x056N\\1-\x1d\x19l#]\x04SB6,r ?>Q\x02.*.6_7{\x1b\x1a19\x19S9\x17\t4\x06%x\x1b^\x1bW)\t#!#\x0bJ,"v\x16R$!U\x10XM\x01\x17\x1e\x16-\x06$\x12\x07!*\x12<2\x11-\x03;\x1b\x01\x17.;hU+\x02\x0c\x1c\x1a\x0b6\x12\x1bW\x15TQ\x183\'7+\r8\x1eB\x13\x05\x16\x10<| *\x1d\x16T=\x14#Q\n\x19;4?~\x120\x12;:\x1dx\x08S\x19"{\x0f)u=&1x\x16\x064X1\x1a]!j2!\x07|\x04\x1dUPBs/~\x15`_\x12\x0c\x1c3(F#4\x7f\x10\r;]"\x16Y.\x12\x1c\x07/y\x05NT)\x16\x0b/\x07V,"\x17,&\x01;00\x11R\x1eX!6\x08_\x0f\x19;\'`C:\x04\x0f7 \x1e\x0c\x05t<\x11)\x1c,.D\x1aT\x19P)\x03 H#g+9:/"^\x191S&\x15O+\x07c?6(\x16\n+8\r\x06\x113\x01\x05(\x1b%gC)\x18@r\x04\x1aN5$\x0b\x07(\x1e\x01%#4\x1cw\x177\x164\x06ZeM`Pp\x13HH\x07\x10&^\x02eH\x17\x16/\x02oV\x19O\x1203!`X]EkGgC\x1d\x1f"X\r\x18X\x16$_\x17\x10\x16\x01&\n.\x15\x1bWF`vfn~wEkGe\x05\x03\x03;\x11RJ\x0e\x7fk\x11TEDScDo\tW\x0c\x04.#fxTu\x119\x12"CFzp\x13HJUUk\x11V\x11\x1d\x03&FwL\x1b\x1e\x0f,!(\'V{okGgAJPp\x13J\x0e\x14\x07 \x1c\x07\x0c\x1e\x16a^mN\x0c\\T`jNbTwEkGgAH\x078Z\x1c\x0fX\x06"K\x11G^SaW}[\x0b]DnLdbTwEkGgC\x07\x19>\x1e\x1b\x03\x0f\x10i\x0bTGTQonmL\x19MFbfd`\x11/\x11.\t4\x08\x05\x1e}_\x01\x19\x01Wq\x11V\x13\t\x17(H;\x01\\mA\x10114n\x188\x02imgAJP-\x1fbJUUk\x13\x18\n\x03QyD6f\x19MFbfdbTue\x0b*\x05+\x04HJp\x11\x1c\x18u\x10Wg;TEDScDmL\x1b\x01\x034#(`NwG=\x025\x03\x05\x035\x11D`UUk\x11TEDSa\x14,\x18QO\\bd\x18mt\x19\'9d\n&\x08\x04^<\\\x0fH\x7fUk\x11T\x18HycDmL\x1bm\x08\x151\'#\'VmE0mgAJPp\x13HJW\x10%P\x16\t\x01QyDo\x18K\x18\x03`jNbTwEkGgAH\x169_\rG\x1b\x14&TV_DQ\x11\x01,\x08t\x08H6>0`X]EkGgAJPp\x11\x0e\x03\x19\x10fR\x1b\x0b\x10\x16-\x10oV\x19OFbfdbT)NkGgAJPp\x13HJUUk\x11TEDScDmL\x19MFbfdbTwEkGgAJPpo\x06JUUk\x11TEDScDmL\x19MLbfdbTwE`;)AJPp\x13HJUUl\x11TEDS\x01(\x0c/rMFbfdbTw\x19\x17\tgAJPp\x1bAJUUk\x1fYKHNd\x04-K\x04CFbfdoT8EfGgAJPp\x13HJ)\x1bk\x11TEDScDmL\x19J[\x1ei\x1bbTwEkGg=6Pp\x13HJ\tUk\x11TEDScDmLe\x03FbfdbTwEaGgA\x16Pp\x14UD*Uk\x11T\x19DScDmL\x19MFbfdbTwE\x17\tgAJPp\x13HJUUk\x11T98ScDmLYPH\x1ei$nTwEkGgAJWp\x13HJ)\x1bk\x11TEDScDmL\x17MFbayl+\x08Kv@g\x01WWp\x13HJUUam\x1aEOScDmL\x19MFbfdbT\x1a\x04?\x13"\x13JPp\x13HJUU`m\x1aEDScDm#\x19MFbfdhTwEkGgAJWp\x13HJUUk\x1f(\x0b8\x1d}ZsLn\x05\x076f,#\x04\'e\x0b8X\x1b\x0fJPpj\x07\x1f\x07U\'X\x1a\x10\x1cS+\x0b>\x18JM\x070#d\'\x1a4\x172\x173\x04\x0e\\pR\x06\x0eU\x16>C\x06e\x0b\x10\x1f:D#\x03MM\t2#6#t\x1d8\x0b*\x0biA6\x1ep\x13H=\x10U%T\x11\x01D\x1c-\x084LT\x02\x08\'?hb\x151\x11.\x15g\x11\x0b\t=V\x06\x1eU\x02.\x11\x03\x0c\x08\x1fc\x03$\x1a\\M\x1f-3d#T3e\x069\x1e7\x15\x05\x02pU\x07\x18U\x01#TTe\x0b\x10\x1a1\x01m\x02\\\x19\x11-4/b\x159\x01k\x1e(\x14J\x079_\x04J\x07\x108E\x1b\x17\x01S"\x08!LM\x05\x03b"%6\x15y9%GgA6\x1en\rVJ"\x1d*ET\x02\x11\x121\x05#\x18\\\x08\x15}f\x18,TwE\x1c\x02ga\x13\x0fP>\\\x1cJ\x14U;^\x18\x0c\x10\x1a \x05!l\x15\x19m\x02\x12+0%6\x113E,\x15(\x14\x1aP1]\x0cJ\x02\x10kU\x1bE\n\x1c7D#\t\\\tF#(=6\x1c>\x0b,G(\x15\x02\x15"\x13\x1c\x02\x14\x1bkH\x1b\x10\x16S.\x0b#\t@CF\x1e(dbT\x1e\x03k\x1e(\x14Jp\x11)\x1fH\x1d\x10U<X\x18\tD\x031\x0b;\x05]\x08F;)1bt\x1c2E;\x15(\x06\x18\x11=@H\x0c\x1a\x07kU\x11\x06\x16\n3\x10$\x03WM\x07,"d5\x11w\x12"\x0b+A\x0e\x15<V\x1c\x0fU\x0c$D\x06Ed\x05\x07"Jm0WMFb\x0f"b\x032E/\x08g\x0f\x05\x04pT\x01\x1c\x10U2^\x01Ed\x01\x101\x1d=\x18\\\x1f\x15b)6b\x032E/\x08g\x0f\x05\x04pW\r\x06\x10\x01.\x11\r\n\x11\x01cd\x059\r\x15M\x08-f+,\x11w\x12"\x0b+A\x1a\x11)\x13\x1d\x19U\x1c%\x11t\x1ceE\x02\x067\x11?\t\x15M\x12*/7b\x108e\x16k\t(\x15J\x13?^\x18\x06\x0cU<Xt\x1cE\x0b\x061D*\x03X\x01\x15lf\x18,TwE\x1c\x02ga\r\x1d\x11)@H\x01\x10\x10;\x11\x1b\x10\x16S3\x16"\x01P\x1e\x031h\x18,(9[uG\x0f\x0e\x1dP$\\H\t\x1a\x1b?P\x17\x11D\x04*\x10%LL\x1eYb\x1a*bTwTeG\x03\x0e\x1d\x1e<\\\t\x0eU\x14%UT\x0c\ns\x07"\x08!Lm"4b\x046-\x03$e\x17kO/\x15\x1ep\x03joG6Z\x02<FZ\x11\x0b\x013\x16"\x06\\\x0e\x12l)6%(xLe;)AJPb\x1dH%\x05\x10%\x11\x1c\x11\x10\x03y8b0\x16\x1e\x1326vv\r.S*Qq\t\x1d\x03*FZ\x1a\x1c\x0c,X\x17\x02\x13\t\'\x10/\x1b_\x19\x04up,6\x12=R=\t.\x11Y\x175G\x0f\x1b\x1b\x0f3X\x10K\x0b\x1d*\x0b#0\x16*"B\x08\x15st0\x1fV\x0fS\x0e*;4bb\']\'[\x17_(\x0bZMc3,\x1eW\x04\x08%gd\x10\x114\n=\x025\x18J\x025P\x07\x07\x18\x10%U\x15\x11\r\x1c-\x17cL\x191\x08bfd\x06\x1bw\x0b$\x13g%/<\x15g-J\x1a\x07k|;!-5\x1aD,\x02@Mf\x0f.#7nT>\x11k\x04&\x0fJ\x1c5R\x0cJ\x01\x1akC\x11\x06\x0b\x05&\x164LI\x1f\t *!/\x07vGAGgAJ\r|9HJUUi]\x15\x0bd\r\x1d$FwLBgFbfdbTwEi\x02)a\x03\x06\x15r\tHH\x01\x07>TVInScDmL\x19MF`$+6Y>\x01i]gC\x08\x112\x01Y\x0f\x10A|\x04\x16PV\x10s\x07t\t[YQ&tw\'\x17n\x07*V#PH\\Z\x13HJUUk\x11TG\x0f\x16:FwL\x1bUPw"r$FfR)\x01u\x04]\x136P\x0bZ\x13D)1\x05C\\SF!P}X\x1bAlbfdbTwEkE2\x13\x06\x03r\tH1\x7fUk\x11TEDScDmL\x19O\x0e624x(x9d\x17&\x18\x07\x15>Gh\t\t\x1e\x06eR\x1b\x08F_IDmL\x19MFbfdbTwG#\x133\x11P,\x7foG\x07\x1a\x1f$S\x1d\x01\x01\x1dm\x07"\x01\x1bgFbfdbTwE\x16mgAJP-\x1fbJUUk\x13\x1f\x0c\x08\x1fn\x12 N\x03M\x1dHfdbTwEkGe\x04\x04\x112_\rHOUiE\x06\x10\x01QonmL\x19MFbfd`\x1d0\x0b$\x15"L\x06\x19#GJPU.A\x11TEDScDmL\x19MF`\x10\t5\x15%eE=$"\x0f\x1e\x15"\x11D`UUk\x11TEDScDmL\x1b;+5\'6\'Y\x01\x0c9\x132a\r91\x1e\x1e?\x03\x01\x1b.B\x07GnScDmL\x19MF\x1fLdbTw\x18gmgAJPrX\x01\x06\x19X;C\x1b\x06\x01ssQyD6f\x19MFbfdbTue\x0b*\x05+\x04HJp\x11\x1c\x18u\x10Wg;TEDScDmL\x1b\x01\x0f12fxT\x0cokGgAJPp\x13HJUUiG\x19\x16\x1ds\x1f,\x03)N3MFbfdbTw8AGgAJ\rZNb'

Custom 32 Byte Rolling XOR Algorithm

Reverse engineering our algorithm

We can see from our uncompressed data, that the beginning stands out as something 'key' like. However, if we try and use this as an xor key, we see that it only decodes the first 32 bytes succesfully, and is garbled after. From this, we know something more complicated is going on, but we know it must involve xor, and our key is definitely a key.

In a decompiled pseudocode view of our ELF payload, we can track the output from the base64 decoding, to the uncompress() call, and then onwards through some checks, before arriving at a 'do' statement as displayed below:

This loop conveniently leads into a string constructor, which is a pretty big hint that this is the final stage of decoding before our config string is constructed.

We can follow the outputs of our uncompress() function and mark up our variables to get to something like the following:

Recreating our algorithm

We can see that the algorithm functions similar to something called a rolling xor key encoding, or "multibyte XOR key" encoding, which is where byte 1 is XORd with the first byte of the key, byte 2 with the 2nd, byte 3 with the 3rd, and so on. This repeats until we get to the end of our key (_see if keyposition == 32) and then we loop back to the first byte of our key again (so the 33rd byte of the data is XORd with the 1st byte of the key)

However, two if statements throw in some additional complexities:

  • If the encoded config byte is zero, do not encode it and move on
  • If the encoded config byte is the same as whichever byte of the key we are on, do not encode it and move on

This is what was causing our problems when trying to perform a simple XOR, and is the reason why our key only worked up until a certain point.

We recreated the algorithm in python with some slight reordering and modification

When recreating the exact steps of the algorithm from our decompiler, we see that the output is a clean json file, with all of our blackmatter config values

data = bytearray(decompressed)
key = data[0:32]

data_position = 32
key_position = 0

#print(data[0:32].decode("utf-8","ignore"))

output = bytearray()

while data_position != len(data):
    #print("Data position at " + str(data_position) + " and key position at " + str(key_position))
    #print(str(data[data_position]) + str(key[key_position]))
    if data[data_position] != 0:
        if data[data_position] != key[key_position]:
            data[data_position] = data[data_position] ^ key[key_position]
            key_position += 1
            if key_position == 32:
                key_position = 0
            
    data_position += 1 

print(data.decode("utf-8"))
            
mfBFDBtWeKgGajpP3hjuuK1tedsCdMl9{
    "rsa": "MIICIDANBgkqhkiG9w0BAQEFAAOCAg0AMIICCAKCAgEAx4XJRtX6r+W\/s6\/mRQmiN1xh4nwLSdOXNZO9ynfuH7iecuNoiwmBM4eBSS3Ncp\/Db7klQoh1xZ51U030++C7uHZBlZ8gEIKv0oYNDs7JadkEeMK8ndiU7HtiyJk0Qe7pjusseoyIVSwA7ID6hT94J\/w84c5VMiHNZdLybpHwL1rubqHjvge\/PnH4uAH3JeNU2sFh8STT1XAux148IyuszgWzJgvXd7mc3gpk1JVa\/sP9p0LhRkas1gOedJIw1iGF8OQbemvPalB\/JbbV+WLFKyko5i1dUGHKMEntFVBcRAlu12MP9tX5KVkMK7eNIRjPMZIFIHGSvdQR9XYceA6VY6hC1kbcGi5681vbtT335T9tPyy1Fjtx+LqYxGtp4B+8BnyTlOdi5Btj6bKi4IImO\/gHspDLRbMrmGEA5wgv1kOgcW\/gE1w8Tqfx28t\/bHbWQclF+QTSkGyoVre\/4Ar\/raCgPfa15kpCzG4UxBQCRRH+EazQ5WdsbbsNAtOfUvHyy5djtD9Im7IqT3qAU2AJnIjXTr75i0410K3yY2tNZwj2tQ4wJZ7RFjFxirdHq+0ZUobkoADUjbCOgUZ5Y9KFXlgsNR+rNakDczAiMQwkZhl0M1R7nbJ8sTCSOZiomT7UV+fkZRPjPNiLZcZTFdBkuT+Cm595n+QWHcer8HEvZ3UCAQM=",
    "remove-self": "true",
    "worker-concurrency": "0",
    "disk": {
        "enable": "true",
        "type": "single",
        "dark-size": "512",
        "white-size": "30720",
        "min-size": "0",
        "extension-list": "vmdk,vmem,vswp,log"
    },
    "log": {
        "enable": "true",
        "level": "verbose",
        "path": "\/tmp\/main.log"
    },
    "message": {
        "enable": "true",
        "file-name": "ReadMe.txt",
        "file-content": "      ~+                                       \n               *       +\n         '     BLACK        |\n     ()    .-.,='``'=.    - o -         \n           '=\/_       \\     |           \n        *   |  '=._    |                \n             \\     `=.\/`,        '    \n          .   '=.__.=' `='      *\n +             Matter        +\n      O      *        '       .\n\n>>> What happens?\n   Your linux hosts are encrypted, and currently not operational. \n   We need only money, after payment we will give you a decryptor for the entire network and you will restore all the data.\n   \n>>> What guarantees? \n   We are not a politically motivated group and we do not need anything other than your money. \n   If you pay, we will provide you the programs for decryption and we will delete your data. \n   If we do not give you decrypters or we do not delete your data, no one will pay us in the future, this does not comply with our goals. \n   We always keep our promises.\n\n>> How to contact with us? \n   1. Download and install TOR Browser (https:\/\/www.torproject.org\/).\n   2. Open http:\/\/supp24yy6a66hwszu2piygicgwzdtbwftb76htfj7vnip3getgqnzxid.onion\/GDBJS76DH3D4IKQD2QO7R.\n\n>> Warning! Recovery recommendations.  \n   Do not DELETE or MODIFY any files, it can lead to recovery problems!"
    },
    "landing": {
        "enable": "true",
        "bot-id": "bab21ee475b52c0c9eb47d23ec9ba1d1",
        "key": "865d6f217bf2e7cfcc0f1b147975b404",
        "urls": [
            "http:\/\/paymenthacks.com",
            "http:\/\/mojobiden.com"
        ]
    },
    "kill-vm": {
        "enable": "true",
        "ignore-list": [
            "VMware vCenter",
            "VMware-VirtualSAN-Witness"
        ]
    },
    "kill-process": {
        "enable": "true",
        "list": [
            "vmsyslogd"
        ]
    }
}