Last active
August 19, 2020 16:39
-
-
Save ryancor/be83840d5e34016478b61edc34a21361 to your computer and use it in GitHub Desktop.
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
######################## | |
# PE image can be found at: https://www.virustotal.com/gui/file/8f87c2c3916bf71a3abbe9a371c8b6240548940754ac0e50e27a754ea9604bb5/detection | |
# VM Bin Dump can be found at: https://www.virustotal.com/gui/file/7ce18b7922cc1ecf46724bb04c877dd374c28b91887c01d8053a83aad1e2f11a/detection | |
######################## | |
SRAM = bytearray(48) # where everything gets calculated and compared | |
WRAM = bytearray(48) # contains plaintext input from user | |
DRAM = bytearray(120) # contains encrypted text | |
# Store data in SRAM | |
def handle_01_02_04(ip, arg): | |
if ip[0] == 0: | |
SRAM[12] = arg[0] | |
elif ip[0] == 1: | |
SRAM[16] = arg[0] | |
elif ip[0] == 2: | |
SRAM[20] = arg[0] | |
elif ip[0] == 3: | |
SRAM[24] = arg[0] | |
return ip | |
# Store input from WRAM to SRAM | |
def opcode_00_06(opcode): | |
byte = opcode[0] | |
if byte == 0x00: | |
current_ip = opcode[4:] | |
arg = opcode[8:] | |
res = handle_01_02_04(current_ip, arg) | |
elif byte == 0x04: | |
current_ip = opcode[4:] | |
arg = opcode[8:] | |
byte_1 = GetByteFromRAM(arg) #possibly make byte_1 a global counter | |
uByte = WRAM[byte_1] | |
res = handle_01_02_04(current_ip, [uByte]) | |
return res | |
# Collect encrypted bytes and store in DRAM | |
counter_7 = 0 | |
def handle_07(current_ip): | |
global counter_7 | |
DRAM[counter_7] = current_ip[0] | |
counter_7 += 1 | |
return counter_7 | |
# Increase the stack pointer | |
def handle_08_09(byte_from_ram): | |
SRAM[0] = byte_from_ram + 1 | |
# Store stack arg in DRAM | |
def opcode_07_09(opcode): | |
byte = opcode[0] | |
if byte == 0x07: | |
current_ip = opcode[4:] | |
res = handle_07(current_ip) | |
elif byte == 0x08: | |
current_ip = opcode[4:] | |
byte_1 = GetByteFromRAM(current_ip) | |
res = handle_08_09(byte_1) | |
return res | |
# Store data from DRAM into SRAM | |
hex_A_hit = 9 | |
hex_A_hit_again = 0 | |
hex_A_pass = 61 | |
def opcode_A_B_C(opcode): | |
byte = opcode[0] | |
global hex_A_hit | |
global hex_A_hit_again | |
global hex_A_pass | |
if byte == 0xA: | |
current_ip = opcode[4:] | |
if hex_A_hit != -1: | |
handle_01_02_04(current_ip, [DRAM[hex_A_hit]]) | |
hex_A_hit -= 1 | |
else: | |
if hex_A_hit_again == 1: | |
epass_byte = SRAM[20] + 1 | |
handle_01_02_04(current_ip, [epass_byte]) | |
elif hex_A_hit_again >= 2: | |
if hex_A_pass != 28: | |
handle_01_02_04(current_ip, [DRAM[hex_A_pass]]) | |
hex_A_pass -= 1 | |
hex_A_hit_again += 1 | |
# Store string length | |
def opcode_12_13_14_15_16(opcode): | |
byte = opcode[0] | |
sub_byte = byte - 18 | |
if sub_byte == 0: | |
arg = opcode[4:] | |
elif sub_byte == 1: | |
arg = opcode[4:] | |
byte_1 = GetByteFromRAM(arg) | |
ret_byte = byte_1 - opcode[8] | |
handle_01_02_04(arg, [ret_byte]) | |
def GetByteFromRAM(arg): | |
if arg[0] == 0: | |
val = SRAM[12] | |
elif arg[0] == 1: | |
val = SRAM[16] | |
elif arg[0] == 2: | |
val = SRAM[20] | |
elif arg[0] == 3: | |
val = SRAM[24] | |
return val | |
# Decrypt current byte sitting in SRAM | |
def opcode_1C_1D_1E_1F_20(opcode): | |
byte = opcode[0] | |
op_res = byte - 28 | |
if op_res == 0: | |
current_ip = opcode[4:] | |
stack_arg = opcode[8:] | |
byte_1 = GetByteFromRAM(current_ip) | |
byte_2 = GetByteFromRAM(stack_arg) | |
xor_res = byte_1 ^ byte_2 | |
handle_01_02_04(current_ip, [xor_res]) | |
elif op_res == 1: | |
current_ip = opcode[4:] | |
stack_arg = opcode[8:] | |
byte_1 = GetByteFromRAM(current_ip) | |
xor_res = byte_1 ^ stack_arg[0] | |
handle_01_02_04(current_ip, [xor_res]) | |
# process and compare current byte in SRAM | |
def opcode_2E_2F_30_31(opcode): | |
byte = opcode[0] | |
op_res = byte - 46 | |
byte_1 = 0 | |
res = 0 | |
if op_res == 0: | |
arg = opcode[4:] | |
byte_1 = GetByteFromRAM(arg) | |
stack = opcode[8:] | |
res = GetByteFromRAM(stack) | |
elif op_res == 1: | |
arg = opcode[4:] | |
byte_1 = GetByteFromRAM(arg) | |
res = opcode[8] | |
result = byte_1 - res | |
SRAM[44] = byte_1 == res | |
# store flag string length | |
def opcode_33_34_35(opcode): | |
byte = opcode[0] | |
if byte == 0x33: | |
SRAM[33] = byte | |
elif byte == 0x34: | |
arg = opcode[4] | |
res = (arg * 12) + byte | |
SRAM[34] = res | |
elif byte == 0x35: | |
SRAM[35] = 0 | |
# loop counter | |
def opcode_3A_3B(opcode): | |
byte = opcode[0] | |
if not SRAM[44]: | |
if byte == 0x3A: | |
SRAM[28] = byte | |
return 2 | |
elif byte == 0x3B: | |
SRAM[32] = byte | |
return 4 | |
return 0 | |
# print byte from SRAM | |
def opcode_3C(opcode): | |
byte = opcode[4:] | |
byte_from_stack = GetByteFromRAM(byte) | |
print(chr(byte_from_stack), end='') | |
# Get input from user | |
def opcode_3D(opcode): | |
password = input('') | |
for i in range(len(password)): | |
WRAM[i] = ord(password[i]) | |
SRAM[36] = len(password) | |
return 3 | |
def VM_Translate(opcode): | |
ip = opcode[0] | |
ret = 0 | |
if ip >= 0x00 and ip <= 0x06: | |
opcode_00_06(opcode) | |
elif ip >= 0x07 and ip <= 0x09: | |
opcode_07_09(opcode) | |
elif ip >= 0xA and ip <= 0xC: | |
opcode_A_B_C(opcode) | |
elif ip >= 0x12 and ip <= 0x16: | |
opcode_12_13_14_15_16(opcode) | |
elif ip >= 0x1C and ip <= 0x20: | |
opcode_1C_1D_1E_1F_20(opcode) | |
elif ip >= 0x2E and ip <= 0x31: | |
opcode_2E_2F_30_31(opcode) | |
elif ip >= 0x33 and ip <= 0x35: | |
opcode_33_34_35(opcode) | |
elif ip >= 0x3A and ip <= 0x3B: | |
ret = opcode_3A_3B(opcode) | |
elif ip == 0x3C: | |
opcode_3C(opcode) | |
elif ip == 0x3D: | |
ret = opcode_3D(opcode) | |
elif ip == 0x3F: | |
# Not part of VM, just the way the rest of DRAM uses up space to store the actual password to get the flag | |
counter = 27 | |
xkey = 0xAC | |
password = '' | |
for _ in range(17): | |
password += chr(DRAM[counter] ^ xkey) | |
counter -= 1 | |
print("\n" + "key->"+ password) | |
# end | |
ret = 1 | |
else: | |
ret = 0 | |
return ret | |
def VM_Start(machine_code): | |
opcode = machine_code[8:] | |
ip = 0 | |
pos = 0 | |
while True: | |
ret = VM_Translate(opcode[ip:]) | |
if ret == 0: | |
ip += 12 | |
elif ret == 1: | |
break | |
elif ret == 2 and hex_A_hit != -1: | |
ip -= 60 | |
elif ret == 2 and hex_A_hit_again >= 2 and hex_A_pass != 28: | |
ip -= 60 | |
elif ret == 3: | |
ip += 48 | |
elif ret == 4: | |
ip += 120 | |
else: | |
ip += 12 | |
def main(): | |
with open('vm_dump.vm', 'rb') as f: | |
data = bytearray(f.read(0x53C)) | |
VM_Start(data) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment