def test_trial_beacon_x86(self): path = os.path.join( os.path.dirname(__file__), "samples", "4d1d732125e4d1a3ba0571e0cd892cf8e0dce854387ee405f75df4dcfb0f616b.zip", ) f = decrypt_sample(path) parser = cobaltstrikeConfig(f) conf = parser.parse_config() self.assertIn('header "CGGGGG"', conf.get("HttpGet_Metadata").get("Metadata"))
def test_encrypted_x86(self): path = os.path.join( os.path.dirname(__file__), "samples", "7773169ca4ea81203a550dfebe53f091a8c57a3a5b12386e51c5a05194fef3ff.zip", ) f = decrypt_sample(path) parser = cobaltstrikeConfig(f) conf = parser.parse_encrypted_config() self.assertEqual(conf.get("PublicKey_MD5"), "8ac540617dddcdf575f6dc207abb7344")
def test_encrypted_x86_64(self): path = os.path.join( os.path.dirname(__file__), "samples", "10fd211ba97ddf12aecb1e7931d92c3ba37421c362cb1490e0203c1bd88ec141.zip", ) f = decrypt_sample(path) parser = cobaltstrikeConfig(f) conf = parser.parse_encrypted_config() self.assertEqual(conf.get("PublicKey_MD5"), "d2c8ec15d925e2514714d619022f7cdf")
def test_non_pe_x86(self): path = os.path.join( os.path.dirname(__file__), "samples", "13e954be0b0c022c392c956e9a800201a75dab7e288230b835bcdd4a9d68253d.zip", ) f = decrypt_sample(path) parser = cobaltstrikeConfig(f) conf = parser.parse_encrypted_config() self.assertEqual(conf.get("HttpPostUri"), "/submit.php")
def get_beacon_data(url, arch): full_url = urljoin(url, URL_PATHS[arch]) try: resp = requests.get(full_url, timeout=30, headers=EMPTY_UA_HEADERS, verify=False) except requests.exceptions.RequestException as e: print('[-] Connection error: ', e) return if resp.status_code != 200: print('[-] Failed with HTTP status code: ', resp.status_code) return buf = resp.content # Check if it's a Trial beacon, therefore not xor encoded (not tested) eicar_offset = buf.find(b'EICAR-STANDARD-ANTIVIRUS-TEST-FILE') if eicar_offset != -1: return cobaltstrikeConfig(BytesIO(buf)).parse_config() offset = buf.find(b'\xff\xff\xff') if offset == -1: print('[-] Unexpected buffer received') return offset += 3 key = struct.unpack_from('<I', buf, offset)[0] size = struct.unpack_from('<I', buf, offset + 4)[0] ^ key head_enc = struct.unpack_from('<I', buf, offset + 8)[0] ^ key head = head_enc & 0xffff # Taken directly from L8_get_beacon.py if head == 0x5a4d or head == 0x9090: decoded_data = b'' for i in range(2 + offset // 4, len(buf) // 4 - 4): a = struct.unpack_from('<I', buf, i * 4)[0] b = struct.unpack_from('<I', buf, i * 4 + 4)[0] с = a ^ b decoded_data += struct.pack('<I', с) return cobaltstrikeConfig(BytesIO(decoded_data)).parse_config()
def test_beacon_45_x86_64(self): path = os.path.join( os.path.dirname(__file__), "samples", "320a5f715aa5724c21013fc14bfe0a10893ce9723ebc25d9ae9f06f5517795d4.zip", ) f = decrypt_sample(path) parser = cobaltstrikeConfig(f) conf = parser.parse_config() self.assertEqual(conf.get("Watermark_Hash"), "xi1knfb/QiftN2EAhdtcyw==") self.assertEqual(conf.get("Retry_Max_Attempts"), 0) self.assertEqual(conf.get("Retry_Increase_Attempts"), 0) self.assertEqual(conf.get("Retry_Duration"), 0)