Skip to content

Instantly share code, notes, and snippets.

@ryancor
Last active June 24, 2020 17:42
Show Gist options
  • Save ryancor/302b1515b7d2c5e1244af90e1beb5bd5 to your computer and use it in GitHub Desktop.
Save ryancor/302b1515b7d2c5e1244af90e1beb5bd5 to your computer and use it in GitHub Desktop.
Decryption algorithms reversed engineered from this binary file: https://www.virustotal.com/gui/file/e8505b7c66d2cfecf23c36cf9c2ad14be21adb73e014cf41f30705258fa9900c
import random
import struct
from ctypes import cdll
vcrt = cdll.LoadLibrary("msvcrt.dll")
hash_table = [
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x1, 0x67, 0x2B,
0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x4, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x5, 0x9A, 0x7, 0x12, 0x80, 0xE2, 0xEB,
0x27, 0xB2, 0x75, 0x9, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B,
0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x0, 0xED, 0x20, 0xFC, 0xB1,
0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB,
0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x2, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51,
0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF,
0xF3, 0xD2, 0xCD, 0xC, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E,
0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0xB, 0xDB, 0xE0, 0x32, 0x3A, 0xA, 0x49,
0x6, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8,
0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE,
0x8, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x3, 0xF6, 0xE, 0x61,
0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9,
0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1,
0x89, 0xD, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0xF, 0xB0, 0x54, 0xBB,
0x16
]
decryption_table = [
0x52, 0x9, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81,
0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E,
0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23,
0x3D, 0xEE, 0x4C, 0x95, 0xB, 0x42, 0xFA, 0xC3, 0x4E, 0x8, 0x2E, 0xA1, 0x66,
0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72,
0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65,
0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46,
0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x0, 0x8C, 0xBC, 0xD3, 0xA,
0xF7, 0xE4, 0x58, 0x5, 0xB8, 0xB3, 0x45, 0x6, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA,
0x3F, 0xF, 0x2, 0xC1, 0xAF, 0xBD, 0x3, 0x1, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11,
0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C,
0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7,
0x62, 0xE, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79,
0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33,
0x88, 0x7, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60,
0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0xD, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9,
0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB,
0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x4, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0xC, 0x7D
]
def do_hash(buf):
new_hash = bytearray(96)
i = 32
for n in range(0x20*2):
new_hash[i] = buf[n%len(buf)]
i += 1
hash_pos = 1
for _ in range(7):
pos_1 = new_hash[93]
new_hash[64] ^= hash_pos ^ hash_table[pos_1]
pos_2 = new_hash[94]
pos_3 = new_hash[95]
new_hash[65] ^= hash_table[pos_2]
pos_4 = new_hash[92]
new_hash[66] ^= hash_table[pos_3]
new_hash[67] ^= hash_table[pos_4]
hash_pos = 27 * (hash_pos >> 7) ^ 2 * hash_pos
idx = 69
next_count = 3
for _ in range(next_count):
new_hash[idx-1] ^= new_hash[idx-5]
new_hash[idx] ^= new_hash[idx-4]
new_hash[idx+1] ^= new_hash[idx-3]
new_hash[idx+2] ^= new_hash[idx-2]
idx += 4
pos_5 = new_hash[77]
pos_6 = new_hash[78]
pos_7 = new_hash[79]
new_hash[80] ^= hash_table[new_hash[76]]
new_hash[81] ^= hash_table[pos_5]
new_hash[82] ^= hash_table[pos_6]
new_hash[83] ^= hash_table[pos_7]
next_idx = 85
final_count = 3
for _ in range(final_count):
new_hash[next_idx-1] ^= new_hash[next_idx-5]
new_hash[next_idx] ^= new_hash[next_idx-4]
new_hash[next_idx+1] ^= new_hash[next_idx-3]
new_hash[next_idx+2] ^= new_hash[next_idx-2]
next_idx += 4
return new_hash
def xor_byte_swap_1(new_hash, byte_key):
idx = 29
for i in range(3):
new_hash[idx-1] ^= new_hash[idx-5]
new_hash[idx] ^= new_hash[idx-4]
new_hash[idx+1] ^= new_hash[idx-3]
new_hash[idx+2] ^= new_hash[idx-2]
idx -= 4
new_hash[16] ^= hash_table[new_hash[12]]
new_hash[17] ^= hash_table[new_hash[13]]
new_hash[18] ^= hash_table[new_hash[14]]
new_hash[19] ^= hash_table[new_hash[15]]
i = 12
while(i != 0):
pos = i
new_hash[pos] ^= new_hash[i - 4]
new_hash[pos + 1] ^= new_hash[i - 3]
new_hash[pos + 2] ^= new_hash[i - 2]
new_hash[pos + 3] ^= new_hash[i - 1]
i -= 4
tmp_byte = (byte_key >> 1) ^ ((byte_key & 1) & 0x8D)
byte_key = tmp_byte
new_hash[0] ^= tmp_byte ^ hash_table[new_hash[29]]
new_hash[1] ^= hash_table[new_hash[30]]
new_hash[2] ^= hash_table[new_hash[31]]
val = new_hash[28]
new_hash[3] ^= hash_table[val]
return new_hash, byte_key
def xor_byte_swap_2(tmp_hash):
pos = 2
for _ in range(4):
xored_byte_1 = tmp_hash[pos:][0] ^ tmp_hash[pos:][1]
tmp_byte_1 = tmp_hash[pos - 2] ^ (tmp_hash[pos - 1] ^ xored_byte_1)
first_idx = tmp_hash[pos - 2]
third_idx = tmp_hash[pos:][0]
if (tmp_byte_1 & 0x80) == 0: # check Sign Flags on MSB
tmp_byte_2 = 2 * tmp_byte_1
else:
tmp_byte_2 = (2 * tmp_byte_1) ^ 0x1B
tmp_byte_3 = first_idx ^ third_idx ^ tmp_byte_2
if (tmp_byte_3 & 0x80) == 0:
tmp_byte_3 = 2 * tmp_byte_3
else:
tmp_byte_3 = (2 * tmp_byte_3) ^ 0x1B
if (tmp_byte_3 & 0x80) == 0:
tmp_byte_3 = 2 * tmp_byte_3
else:
tmp_byte_3 = (2 * tmp_byte_3) ^ 0x1B
tmp_byte_4 = tmp_hash[pos - 1]
xored_byte_2 = tmp_byte_1 ^ tmp_byte_3
tmp_byte_5 = tmp_hash[pos:][1]
xored_byte_3 = (tmp_byte_4 ^ tmp_byte_5 ^ tmp_byte_2) & 0xff
if (xored_byte_3 & 0x80) == 0:
tmp_byte_6 = 2 * xored_byte_3
else:
tmp_byte_6 = (2 * xored_byte_3) ^ 0x1B
if (tmp_byte_6 & 0x80) == 0:
tmp_byte_6 = 2 * tmp_byte_6
else:
tmp_byte_6 = (2 * tmp_byte_6) ^ 0x1B
xored_byte_4 = tmp_byte_1 ^ tmp_byte_6
tmp_byte_7 = first_idx ^ tmp_byte_4
if (tmp_byte_7 & 0x80) == 0:
tmp_byte_7 = 2 * tmp_byte_7
else:
tmp_byte_7 = (2 * tmp_byte_7) ^ 0x1B
tmp_hash[pos - 2] = (xored_byte_2 & 0xff) ^ ((tmp_byte_7 & 0xff) ^ first_idx)
tmp_byte_8 = tmp_byte_4 ^ tmp_hash[pos:][0]
if (tmp_byte_8 & 0x80) == 0:
tmp_byte_8 = 2 * tmp_byte_8
else:
tmp_byte_8 = (2 * tmp_byte_8) ^ 0x1B
tmp_hash[pos - 1] = (xored_byte_4 & 0xff) ^ ((tmp_byte_8 & 0xff) ^ tmp_byte_4)
if (xored_byte_1 & 0x80) == 0:
tmp_byte_9 = 2 * xored_byte_1
else:
tmp_byte_9 = (2 * xored_byte_1) ^ 0x1B
tmp_byte_10 = (xored_byte_2 ^ tmp_byte_9 ^ tmp_hash[pos:][0]) & 0xff
xored_byte_5 = first_idx ^ tmp_byte_5
tmp_hash[pos] = tmp_byte_10
if (xored_byte_5 & 0x80) == 0:
result = 2 * xored_byte_5
else:
result = (2 * xored_byte_5) ^ 0x1B
pos += 4
tmp_hash[pos - 3] = (xored_byte_4 & 0xff) ^ ((result & 0xff) ^ tmp_byte_5)
return tmp_hash, result
def do_decrypt(new_hash, key_remainder):
hash_pos_1 = new_hash[16:]
key = key_remainder
tmp_hash = bytearray(16)
for i in range(16):
tmp_byte = hash_pos_1[64-1-i]
new_hash[15-i] = tmp_byte
key[15-i] ^= tmp_byte
new_hash[31-i] = new_hash[31-i:][64]
tmp_hash[15-i] = key[15-i]
tmp_byte_1 = tmp_hash[9];
tmp_byte_2 = tmp_hash[1];
tmp_hash[1] = tmp_hash[13];
tmp_byte_3 = tmp_hash[5];
tmp_hash[13] = tmp_byte_1;
tmp_byte_4 = tmp_hash[10];
tmp_hash[5] = tmp_byte_2;
tmp_byte_5 = tmp_hash[2];
tmp_hash[9] = tmp_byte_3;
tmp_byte_6 = tmp_hash[7];
tmp_hash[2] = tmp_byte_4;
tmp_byte_7 = tmp_hash[11];
tmp_hash[10] = tmp_byte_5;
tmp_byte_8 = tmp_hash[3];
tmp_hash[3] = tmp_byte_6;
tmp_byte_9 = tmp_hash[15];
tmp_hash[7] = tmp_byte_7;
tmp_byte_10 = tmp_hash[14];
tmp_hash[15] = tmp_byte_8;
tmp_byte_11 = tmp_hash[6];
tmp_hash[11] = tmp_byte_9;
tmp_hash[14] = tmp_byte_11;
tmp_hash[6] = tmp_byte_10;
for i in range(16):
tmp_hash[15-i] = decryption_table[tmp_hash[15-i]]
byte_key = 0x80
for i in range(13):
if 13-i & 1:
new_hash, byte_key = xor_byte_swap_1(new_hash, byte_key)
for i in range(16):
tmp_hash[15-i] ^= new_hash[31-i]
else:
for n in range(16):
tmp_hash[15-n] ^= new_hash[15-n]
tmp_hash, result = xor_byte_swap_2(tmp_hash)
tmp_byte_12 = tmp_hash[9]
tmp_byte_13 = tmp_hash[1]
tmp_hash[1] = tmp_hash[13]
tmp_byte_14 = tmp_hash[5]
tmp_hash[13] = tmp_byte_12
tmp_byte_15 = tmp_hash[10]
tmp_hash[5] = tmp_byte_13
tmp_byte_16 = tmp_hash[2]
tmp_hash[9] = tmp_byte_14
tmp_byte_17 = tmp_hash[7]
tmp_hash[2] = tmp_byte_15
tmp_byte_18 = tmp_hash[11]
tmp_hash[10] = tmp_byte_16
tmp_byte_19 = tmp_hash[3]
tmp_hash[3] = tmp_byte_17
tmp_byte_20 = tmp_hash[15]
tmp_hash[7] = tmp_byte_18
tmp_byte_21 = tmp_hash[14]
tmp_hash[15] = tmp_byte_19
tmp_byte_22 = tmp_hash[6]
tmp_hash[11] = tmp_byte_20
tmp_hash[14] = tmp_byte_22
tmp_hash[6] = tmp_byte_21
for n in range(16):
tmp_byte_23 = tmp_hash[15-n]
tmp_hash[15-n] = decryption_table[tmp_byte_23]
for x in range(16):
tmp_hash[15-x] ^= new_hash[47-x]
return tmp_hash
def decrypt_string_remainder(r_string):
seed_val = struct.unpack("<H", r_string[:2])[0] # takes first two bytes and converts to little endian hex, ">H" does big
vcrt.srand(seed_val)
key_remainder = r_string[4:]
buf = b''
for i in range(0x20):
val = vcrt.rand() & 0xff
buf += bytes([val])
new_hash = do_hash(buf)
decrypted_string = do_decrypt(new_hash, key_remainder)
return decrypted_string
def decrypt_string(string_):
string_len = len(string_)
string_len_half = string_len >> 1
i = 1
buf = bytearray(string_len_half)
buf[0] = (ord(string_[1]) - ord(string_[0])) | (((ord(string_[0]) - 1) << 4) & 0xff)
for _ in range(string_len_half-1):
tmp = string_[2*i]
n = ord(tmp) - ord(string_[2*i-1])
if n < 0:
n = n + 0x5E
buf[i] = (n << 4) & 0xff
z = ord(string_[2*i+1]) - ord(tmp)
if z < 0:
z = z + 0x5E
string_len_half = string_len >> 1
buf[i] |= z & 0xf
i += 1
return buf
def main():
test_str_1 = "EMQVVVVVYZajp *4<IUU]jptz&'+-13BQSXcelu#"
print(decrypt_string_remainder(decrypt_string(test_str_1)))
test_str_2 = "LSWbbbbbelw$'2=CKLSXXcl{*79?IMQ\\hss!++177FQ^hhwz -5@AKYhhs -:AHTWWX^kvxy"
print(decrypt_string_remainder(decrypt_string(test_str_2)))
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment