Last active
June 24, 2020 17:42
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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