Skip to content

Instantly share code, notes, and snippets.

@ryancor
Last active August 19, 2020 16:39
Show Gist options
  • Save ryancor/be83840d5e34016478b61edc34a21361 to your computer and use it in GitHub Desktop.
Save ryancor/be83840d5e34016478b61edc34a21361 to your computer and use it in GitHub Desktop.
########################
# 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