├── Beacon_Task_return_AES_Decrypt.py ├── Beacon_metadata_RSA_Decrypt.py ├── CS_Task_AES_Decrypt.py ├── README.md └── get_RSA.java /Beacon_Task_return_AES_Decrypt.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Beacon任务执行结果解密 3 | ''' 4 | import hmac 5 | import binascii 6 | import base64 7 | import struct 8 | import hexdump 9 | from Crypto.Cipher import AES 10 | 11 | def compare_mac(mac, mac_verif): 12 | if mac == mac_verif: 13 | return True 14 | if len(mac) != len(mac_verif): 15 | print 16 | "invalid MAC size" 17 | return False 18 | 19 | result = 0 20 | 21 | for x, y in zip(mac, mac_verif): 22 | result |= x ^ y 23 | 24 | return result == 0 25 | 26 | def decrypt(encrypted_data, iv_bytes, signature, shared_key, hmac_key): 27 | if not compare_mac(hmac.new(hmac_key, encrypted_data, digestmod="sha256").digest()[0:16], signature): 28 | print("message authentication failed") 29 | return 30 | 31 | cypher = AES.new(shared_key, AES.MODE_CBC, iv_bytes) 32 | data = cypher.decrypt(encrypted_data) 33 | return data 34 | 35 | #key源自Beacon_metadata_RSA_Decrypt.py 36 | SHARED_KEY = binascii.unhexlify("") 37 | HMAC_KEY = binascii.unhexlify("") 38 | 39 | encrypt_data="AAAAQPmxmlOwWb3bsWCXfcZJL5HJqg3HfMKEVuoGvTGOGB1Imr8hvN3n01GWoneTc3pm0tLFrWZC7QGoGvp7JfZOa1o=" 40 | 41 | encrypt_data=base64.b64decode(encrypt_data) 42 | 43 | encrypt_data_length=encrypt_data[0:4] 44 | 45 | encrypt_data_length=int.from_bytes(encrypt_data_length, byteorder='big', signed=False) 46 | 47 | encrypt_data_l = encrypt_data[4:len(encrypt_data)] 48 | 49 | data1=encrypt_data_l[0:encrypt_data_length-16] 50 | signature=encrypt_data_l[encrypt_data_length-16:encrypt_data_length] 51 | iv_bytes = bytes("abcdefghijklmnop",'utf-8') 52 | 53 | dec=decrypt(data1,iv_bytes,signature,SHARED_KEY,HMAC_KEY) 54 | 55 | 56 | counter = dec[0:4] 57 | counter=int.from_bytes(counter, byteorder='big', signed=False) 58 | print("counter:{}".format(counter)) 59 | 60 | dec_length = dec[4:8] 61 | dec_length=int.from_bytes(dec_length, byteorder='big', signed=False) 62 | print("任务返回长度:{}".format(dec_length)) 63 | 64 | de_data= dec[8:len(dec)] 65 | Task_type=de_data[0:4] 66 | Task_type=int.from_bytes(Task_type, byteorder='big', signed=False) 67 | print("任务输出类型:{}".format(Task_type)) 68 | 69 | print(de_data[4:dec_length].decode('utf-8')) 70 | 71 | print(hexdump.hexdump(dec)) -------------------------------------------------------------------------------- /Beacon_metadata_RSA_Decrypt.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Beacon元数据 3 | ''' 4 | import hashlib 5 | import M2Crypto 6 | import base64 7 | import hexdump 8 | 9 | PRIVATE_KEY = """ 10 | -----BEGIN RSA PRIVATE KEY----- 11 | {} 12 | -----END RSA PRIVATE KEY----- 13 | """ 14 | 15 | encode_data = "" 16 | base64_key = "" 17 | 18 | pubkey = M2Crypto.RSA.load_key_string(PRIVATE_KEY.format(base64_key).encode()) 19 | ciphertext = pubkey.private_decrypt(base64.b64decode(encode_data), M2Crypto.RSA.pkcs1_padding) 20 | 21 | 22 | def isFlag(var, flag): 23 | return (var & flag) == flag 24 | 25 | 26 | def toIP(var): 27 | var2 = (var & -16777216) >> 24 28 | var4 = (var & 16711680) >> 16 29 | var6 = (var & 65280) >> 8 30 | var8 = var & 255 31 | return str(var2) + "." + str(var4) + "." + str(var6) + "." + str(var8) 32 | 33 | 34 | def getName(var0): 35 | if var0 == 37: 36 | return "IBM037" 37 | elif var0 == 437: 38 | return "IBM437" 39 | elif var0 == 500: 40 | return "IBM500" 41 | elif var0 == 708: 42 | return "ISO-8859-6" 43 | elif var0 == 709: 44 | return "" 45 | elif var0 == 710: 46 | return "" 47 | elif var0 == 720: 48 | return "IBM437" 49 | elif var0 == 737: 50 | return "x-IBM737" 51 | elif var0 == 775: 52 | return "IBM775" 53 | elif var0 == 850: 54 | return "IBM850" 55 | elif var0 == 852: 56 | return "IBM852" 57 | elif var0 == 855: 58 | return "IBM855" 59 | elif var0 == 857: 60 | return "IBM857" 61 | elif var0 == 858: 62 | return "IBM00858" 63 | elif var0 == 860: 64 | return "IBM860" 65 | elif var0 == 861: 66 | return "IBM861" 67 | elif var0 == 862: 68 | return "IBM862" 69 | elif var0 == 863: 70 | return "IBM863" 71 | elif var0 == 864: 72 | return "IBM864" 73 | elif var0 == 865: 74 | return "IBM865" 75 | elif var0 == 866: 76 | return "IBM866" 77 | elif var0 == 869: 78 | return "IBM869" 79 | elif var0 == 870: 80 | return "IBM870" 81 | elif var0 == 874: 82 | return "x-windows-874" 83 | elif var0 == 875: 84 | return "IBM875" 85 | elif var0 == 932: 86 | return "Shift_JIS" 87 | elif var0 == 936: 88 | return "x-mswin-936" 89 | elif var0 == 949: 90 | return "x-windows-949" 91 | elif var0 == 950: 92 | return "Big5" 93 | elif var0 == 1026: 94 | return "IBM1026" 95 | elif var0 == 1047: 96 | return "IBM1047" 97 | elif var0 == 1140: 98 | return "IBM01140" 99 | elif var0 == 1141: 100 | return "IBM01141" 101 | elif var0 == 1142: 102 | return "IBM01142" 103 | elif var0 == 1143: 104 | return "IBM01143" 105 | elif var0 == 1144: 106 | return "IBM01144" 107 | elif var0 == 1145: 108 | return "IBM01145" 109 | elif var0 == 1146: 110 | return "IBM01146" 111 | elif var0 == 1147: 112 | return "IBM01147" 113 | elif var0 == 1148: 114 | return "IBM01148" 115 | elif var0 == 1149: 116 | return "IBM01149" 117 | elif var0 == 1200: 118 | return "UTF-16LE" 119 | elif var0 == 1201: 120 | return "UTF-16BE" 121 | elif var0 == 1250: 122 | return "windows-1250" 123 | elif var0 == 1251: 124 | return "windows-1251" 125 | elif var0 == 1252: 126 | return "windows-1252" 127 | elif var0 == 1253: 128 | return "windows-1253" 129 | elif var0 == 1254: 130 | return "windows-1254" 131 | elif var0 == 1255: 132 | return "windows-1255" 133 | elif var0 == 1256: 134 | return "windows-1256" 135 | elif var0 == 1257: 136 | return "windows-1257" 137 | elif var0 == 1258: 138 | return "windows-1258" 139 | elif var0 == 1361: 140 | return "x-Johab" 141 | elif var0 == 10000: 142 | return "x-MacRoman" 143 | elif var0 == 10001: 144 | return "" 145 | elif var0 == 10002: 146 | return "" 147 | elif var0 == 10003: 148 | return "" 149 | elif var0 == 10004: 150 | return "x-MacArabic" 151 | elif var0 == 10005: 152 | return "x-MacHebrew" 153 | elif var0 == 10006: 154 | return "x-MacGreek" 155 | elif var0 == 10007: 156 | return "x-MacCyrillic" 157 | elif var0 == 10008: 158 | return "" 159 | elif var0 == 10010: 160 | return "x-MacRomania" 161 | elif var0 == 10017: 162 | return "x-MacUkraine" 163 | elif var0 == 10021: 164 | return "x-MacThai" 165 | elif var0 == 10029: 166 | return "x-MacCentralEurope" 167 | elif var0 == 10079: 168 | return "x-MacIceland" 169 | elif var0 == 10081: 170 | return "x-MacTurkish" 171 | elif var0 == 10082: 172 | return "x-MacCroatian" 173 | elif var0 == 12000: 174 | return "UTF-32LE" 175 | elif var0 == 12001: 176 | return "UTF-32BE" 177 | elif var0 == 20000: 178 | return "x-ISO-2022-CN-CNS" 179 | elif var0 == 20001: 180 | return "" 181 | elif var0 == 20002: 182 | return "" 183 | elif var0 == 20003: 184 | return "" 185 | elif var0 == 20004: 186 | return "" 187 | elif var0 == 20005: 188 | return "" 189 | elif var0 == 20105: 190 | return "" 191 | elif var0 == 20106: 192 | return "" 193 | elif var0 == 20107: 194 | return "" 195 | elif var0 == 20108: 196 | return "" 197 | elif var0 == 20127: 198 | return "US-ASCII" 199 | elif var0 == 20261: 200 | return "" 201 | elif var0 == 20269: 202 | return "" 203 | elif var0 == 20273: 204 | return "IBM273" 205 | elif var0 == 20277: 206 | return "IBM277" 207 | elif var0 == 20278: 208 | return "IBM278" 209 | elif var0 == 20280: 210 | return "IBM280" 211 | elif var0 == 20284: 212 | return "IBM284" 213 | elif var0 == 20285: 214 | return "IBM285" 215 | elif var0 == 20290: 216 | return "IBM290" 217 | elif var0 == 20297: 218 | return "IBM297" 219 | elif var0 == 20420: 220 | return "IBM420" 221 | elif var0 == 20423: 222 | return "" 223 | elif var0 == 20424: 224 | return "IBM424" 225 | elif var0 == 20833: 226 | return "" 227 | elif var0 == 20838: 228 | return "IBM-Thai" 229 | elif var0 == 20866: 230 | return "KOI8-R" 231 | elif var0 == 20871: 232 | return "IBM871" 233 | elif var0 == 20880: 234 | return "" 235 | elif var0 == 20905: 236 | return "" 237 | elif var0 == 20924: 238 | return "" 239 | elif var0 == 20932: 240 | return "EUC-JP" 241 | elif var0 == 20936: 242 | return "GB2312" 243 | elif var0 == 20949: 244 | return "" 245 | elif var0 == 21025: 246 | return "x-IBM1025" 247 | elif var0 == 21027: 248 | return "" 249 | elif var0 == 21866: 250 | return "KOI8-U" 251 | elif var0 == 28591: 252 | return "ISO-8859-1" 253 | elif var0 == 28592: 254 | return "ISO-8859-2" 255 | elif var0 == 28593: 256 | return "ISO-8859-3" 257 | elif var0 == 28594: 258 | return "ISO-8859-4" 259 | elif var0 == 28595: 260 | return "ISO-8859-5" 261 | elif var0 == 28596: 262 | return "ISO-8859-6" 263 | elif var0 == 28597: 264 | return "ISO-8859-7" 265 | elif var0 == 28598: 266 | return "ISO-8859-8" 267 | elif var0 == 28599: 268 | return "ISO-8859-9" 269 | elif var0 == 28603: 270 | return "ISO-8859-13" 271 | elif var0 == 28605: 272 | return "ISO-8859-15" 273 | elif var0 == 29001: 274 | return "" 275 | elif var0 == 38598: 276 | return "ISO-8859-8" 277 | elif var0 == 50220: 278 | return "ISO-2022-JP" 279 | elif var0 == 50221: 280 | return "ISO-2022-JP-2" 281 | elif var0 == 50222: 282 | return "ISO-2022-JP" 283 | elif var0 == 50225: 284 | return "ISO-2022-KR" 285 | elif var0 == 50227: 286 | return "ISO-2022-CN" 287 | elif var0 == 50229: 288 | return "ISO-2022-CN" 289 | elif var0 == 50930: 290 | return "x-IBM930" 291 | elif var0 == 50931: 292 | return "" 293 | elif var0 == 50933: 294 | return "x-IBM933" 295 | elif var0 == 50935: 296 | return "x-IBM935" 297 | elif var0 == 50936: 298 | return "" 299 | elif var0 == 50937: 300 | return "x-IBM937" 301 | elif var0 == 50939: 302 | return "x-IBM939" 303 | elif var0 == 51932: 304 | return "EUC-JP" 305 | elif var0 == 51936: 306 | return "GB2312" 307 | elif var0 == 51949: 308 | return "EUC-KR" 309 | elif var0 == 51950: 310 | return "" 311 | elif var0 == 52936: 312 | return "GB2312" 313 | elif var0 == 54936: 314 | return "GB18030" 315 | elif var0 == 57002: 316 | return "x-ISCII91" 317 | elif var0 == 57003: 318 | return "x-ISCII91" 319 | elif var0 == 57004: 320 | return "x-ISCII91" 321 | elif var0 == 57005: 322 | return "x-ISCII91" 323 | elif var0 == 57006: 324 | return "x-ISCII91" 325 | elif var0 == 57007: 326 | return "x-ISCII91" 327 | elif var0 == 57008: 328 | return "x-ISCII91" 329 | elif var0 == 57009: 330 | return "x-ISCII91" 331 | elif var0 == 57010: 332 | return "x-ISCII91" 333 | elif var0 == 57011: 334 | return "x-ISCII91" 335 | elif var0 == 65000: 336 | return "" 337 | elif var0 == 65001: 338 | return "UTF-8" 339 | 340 | 341 | if ciphertext[0:4] == b'\x00\x00\xBE\xEF': 342 | 343 | # 16 344 | raw_aes_keys = ciphertext[8:24] 345 | 346 | # 2 347 | var9 = ciphertext[24:26] 348 | var9 = int.from_bytes(var9, byteorder='little', signed=False) 349 | var9 = getName(var9) 350 | # 2 351 | var10 = ciphertext[26:28] 352 | var10 = int.from_bytes(var10, byteorder='little', signed=False) 353 | var10 = getName(var10) 354 | 355 | # 4 356 | id = ciphertext[28:32] 357 | id = int.from_bytes(id, byteorder='big', signed=False) 358 | print("Beacon id:{}".format(id)) 359 | 360 | # 4 361 | pid = ciphertext[32:36] 362 | pid = int.from_bytes(pid, byteorder='big', signed=False) 363 | print("pid:{}".format(pid)) 364 | 365 | # 2 366 | port = ciphertext[36:38] 367 | port = int.from_bytes(port, byteorder='big', signed=False) 368 | print("port:{}".format(port)) 369 | 370 | # 1 371 | flag = ciphertext[38:39] 372 | flag = int.from_bytes(flag, byteorder='big', signed=False) 373 | # print(flag) 374 | 375 | if isFlag(flag, 1): 376 | barch = "" 377 | pid = "" 378 | is64 = "" 379 | elif isFlag(flag, 2): 380 | barch = "x64" 381 | else: 382 | barch = "x86" 383 | 384 | if isFlag(flag, 4): 385 | is64 = "1" 386 | else: 387 | is64 = "0" 388 | 389 | if isFlag(flag, 8): 390 | bypassuac = "True" 391 | else: 392 | bypassuac = "False" 393 | 394 | print("barch:" + barch) 395 | print("is64:" + is64) 396 | print("bypass:" + bypassuac) 397 | 398 | # 2 399 | var_1 = ciphertext[39:40] 400 | var_2 = ciphertext[40:41] 401 | var_1 = int.from_bytes(var_1, byteorder='big', signed=False) 402 | var_2 = int.from_bytes(var_2, byteorder='big', signed=False) 403 | windows_var = str(var_1) + "." + str(var_2) 404 | print("windows var:" + windows_var) 405 | 406 | # 2 407 | windows_build = ciphertext[41:43] 408 | windows_build = int.from_bytes(windows_build, byteorder='big', signed=False) 409 | print("windows build:{}".format(windows_build)) 410 | 411 | # 4 412 | x64_P = ciphertext[43:47] 413 | 414 | # 4 415 | ptr_gmh = ciphertext[47:51] 416 | # 4 417 | ptr_gpa = ciphertext[51:55] 418 | 419 | # if ("x64".equals(this.barch)) { 420 | # this.ptr_gmh = CommonUtils.join(var10, this.ptr_gmh) 421 | # this.ptr_gpa = CommonUtils.join(var10, this.ptr_gpa) 422 | # } 423 | # 424 | # this.ptr_gmh = CommonUtils.bswap(this.ptr_gmh) 425 | # this.ptr_gpa = CommonUtils.bswap(this.ptr_gpa) 426 | 427 | # 4 428 | intz = ciphertext[55:59] 429 | intz = int.from_bytes(intz, byteorder='little', signed=False) 430 | intz = toIP(intz) 431 | 432 | if intz == "0.0.0.0": 433 | intz = "unknown" 434 | print("host:" + intz) 435 | 436 | if var9 == None: 437 | ddata = ciphertext[59:len(ciphertext)].decode("ISO8859-1") 438 | else: 439 | # ??x-mswin-936 440 | # ddata = ciphertext[59:len(ciphertext)].decode(var9) 441 | ddata = ciphertext[59:len(ciphertext)].decode("ISO8859-1") 442 | 443 | ddata = ddata.split("\t") 444 | if len(ddata) > 0: 445 | computer = ddata[0] 446 | if len(ddata) > 1: 447 | username = ddata[1] 448 | if len(ddata) > 2: 449 | process = ddata[2] 450 | 451 | print("PC name:" + computer) 452 | print("username:" + username) 453 | print("process name:" + process) 454 | 455 | raw_aes_hash256 = hashlib.sha256(raw_aes_keys) 456 | digest = raw_aes_hash256.digest() 457 | aes_key = digest[0:16] 458 | hmac_key = digest[16:] 459 | 460 | print("AES key:{}".format(aes_key.hex())) 461 | print("HMAC key:{}".format(hmac_key.hex())) 462 | 463 | 464 | 465 | print(hexdump.hexdump(ciphertext)) 466 | -------------------------------------------------------------------------------- /CS_Task_AES_Decrypt.py: -------------------------------------------------------------------------------- 1 | ''' 2 | cobaltstrike任务解密 3 | ''' 4 | import hmac 5 | import binascii 6 | import base64 7 | import struct 8 | 9 | import hexdump 10 | from Crypto.Cipher import AES 11 | 12 | def compare_mac(mac, mac_verif): 13 | if mac == mac_verif: 14 | return True 15 | if len(mac) != len(mac_verif): 16 | print 17 | "invalid MAC size" 18 | return False 19 | 20 | result = 0 21 | 22 | for x, y in zip(mac, mac_verif): 23 | result |= x ^ y 24 | 25 | return result == 0 26 | 27 | 28 | def decrypt(encrypted_data, iv_bytes, signature, shared_key, hmac_key): 29 | if not compare_mac(hmac.new(hmac_key, encrypted_data, digestmod="sha256").digest()[0:16], signature): 30 | print("message authentication failed") 31 | return 32 | 33 | cypher = AES.new(shared_key, AES.MODE_CBC, iv_bytes) 34 | data = cypher.decrypt(encrypted_data) 35 | return data 36 | 37 | 38 | def readInt(buf): 39 | return struct.unpack('>L', buf[0:4])[0] 40 | 41 | #接收到的任务数据 42 | shell_whoami="0k6lSpOcdzWFzgaXLVIG3KScxMndHJzDRt//TUIqQSgtJdnQHkbXaatrNiizJJrj+9e4q7iHpPnaxEFMfRFluw==" 43 | 44 | if __name__ == "__main__": 45 | #key源自Beacon_metadata_RSA_Decrypt.py 46 | SHARED_KEY = binascii.unhexlify("") 47 | HMAC_KEY = binascii.unhexlify("") 48 | 49 | enc_data = base64.b64decode(shell_whoami) 50 | print("数据总长度:{}".format(len(enc_data))) 51 | signature = enc_data[-16:] 52 | encrypted_data = enc_data[:-16] 53 | 54 | iv_bytes = bytes("abcdefghijklmnop",'utf-8') 55 | 56 | dec = decrypt(encrypted_data,iv_bytes,signature,SHARED_KEY,HMAC_KEY) 57 | 58 | counter = readInt(dec) 59 | print("时间戳:{}".format(counter)) 60 | 61 | decrypted_length = readInt(dec[4:]) 62 | print("任务数据包长度:{}".format(decrypted_length)) 63 | 64 | data = dec[8:len(dec)] 65 | print("任务Data") 66 | print(hexdump.hexdump(data)) 67 | 68 | # 任务标志 69 | Task_Sign=data[0:4] 70 | print("Task_Sign:{}".format(Task_Sign)) 71 | 72 | # 实际的任务数据长度 73 | Task_file_len = int.from_bytes(data[4:8], byteorder='big', signed=False) 74 | print("Task_file:{}".format(Task_file_len)) 75 | 76 | with open('data.bin', 'wb') as f: 77 | f.write(data[8:Task_file_len]) 78 | 79 | print(hexdump.hexdump(data[Task_file_len:])) 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | get_RSA.java 用来获取公私密钥 Get RSA key 3 | Beacon_metadata_RSA_Decrypt.py 解密元数据 Decrypt Beacon metadata 4 | CS_Task_AES_Decrypt.py 解密CS发送任务数据 Decrypt CS sending task data 5 | Beacon_Task_return_AES_Decrypt.py 解密Beacon任务执行结果 Decrypt the execution result of the Beacon task 6 | ``` 7 | 8 | 相关参考 9 | https://research.nccgroup.com/2020/06/15/striking-back-at-retired-cobalt-strike-a-look-at-a-legacy-vulnerability/ 10 | -------------------------------------------------------------------------------- /get_RSA.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.util.Base64; 3 | import common.CommonUtils; 4 | import java.security.KeyPair; 5 | 6 | class get_RSA 7 | { 8 | public static void main(String[] args) 9 | { 10 | try { 11 | File file = new File(".cobaltstrike.beacon_keys"); 12 | if (file.exists()) { 13 | KeyPair keyPair = (KeyPair)CommonUtils.readObject(file, null); 14 | System.out.printf("Private Key: %s\n\n", new String(Base64.getEncoder().encode(keyPair.getPrivate().getEncoded()))); 15 | System.out.printf("Public Key: %s\n\n", new String(Base64.getEncoder().encode(keyPair.getPublic().getEncoded()))); 16 | } 17 | else { 18 | System.out.println("Could not find .cobaltstrike.beacon_keys file"); 19 | } 20 | } 21 | catch (Exception exception) { 22 | System.out.println("Could not read asymmetric keys"); 23 | } 24 | } 25 | } --------------------------------------------------------------------------------