from
capstone
import
*
md
=
Cs(CS_ARCH_X86, CS_MODE_64)
with
open
(
'chal.exe'
,
'rb'
) as f:
vm_opcode
=
f.read()[
0x97200
:
0x97200
+
0x15b8c
]
print
(vm_opcode[:
16
])
pc_max
=
len
(vm_opcode)
pc
=
0
reg_index
=
-
1
def
get_reg():
reg_name
=
[
'rdi'
,
'rsi'
,
'rbp'
,
'r8'
,
'r9'
,
'r10'
,
'r11'
,
'r12'
,
'r13'
,
'r14'
,
'r15'
,
]
assert
reg_index >
=
0
,
"reg_index_error"
assert
reg_index <
len
(reg_name) ,
"reg_index_error"
return
reg_name[reg_index]
def
get_reg_size():
reg_name_size
=
[
[
'dil'
,
'di'
,
'edi'
,
'rdi'
],
[
'sil'
,
'si'
,
'esi'
,
'rsi'
],
[
'bpl'
,
'bp'
,
'ebp'
,
'rbp'
],
[
'r8b'
,
'r8w'
,
'r8d'
,
'r8'
],
[
'r9b'
,
'r9w'
,
'r9d'
,
'r9'
],
[
'r10b'
,
'r10w'
,
'r10d'
,
'r10'
],
[
'r11b'
,
'r11w'
,
'r11d'
,
'r11'
],
[
'r12b'
,
'r12w'
,
'r12d'
,
'r12'
],
[
'r13b'
,
'r13w'
,
'r13d'
,
'r13'
],
[
'r14b'
,
'r14w'
,
'r14d'
,
'r14'
],
[
'r15b'
,
'r15w'
,
'r15d'
,
'r15'
],
]
assert
reg_index >
=
0
,
"reg_index_error"
assert
reg_index <
len
(reg_name_size) ,
"reg_index_error"
return
reg_name_size[reg_index][opsize.bit_length()
-
1
]
opsize_arr
=
[
1
,
2
,
4
,
8
]
x64_asm
=
[]
need_label
=
set
()
pc_infor
=
[]
while
pc < pc_max:
opcode
=
vm_opcode[pc]
opsize
=
vm_opcode[pc
+
1
]
pc_infor.append(pc)
x64_asm.append(f
'lable_{hex(pc)}:'
)
assert
opsize
in
opsize_arr,
"opsize error"
if
opcode
=
=
0
:
imm
=
int
.from_bytes(vm_opcode[pc
+
2
:pc
+
2
+
opsize],
'little'
)
if
opsize
=
=
1
:
print
(f
"push16 {imm}"
)
if
opsize
=
=
2
:
print
(f
"push16 {imm}"
)
if
opsize
=
=
4
:
print
(f
"push32 {imm}"
)
if
opsize
=
=
8
:
print
(f
"push64 {imm}"
)
pc
+
=
2
+
opsize
reg_index
+
=
1
dst_reg
=
get_reg()
asm
=
f
'mov %s, {imm}'
%
(dst_reg)
x64_asm.append(asm)
elif
opcode
=
=
1
:
if
opsize
=
=
1
:
print
(f
"load16"
)
if
opsize
=
=
2
:
print
(f
"load16"
)
if
opsize
=
=
4
:
print
(f
"load32"
)
if
opsize
=
=
8
:
print
(f
"load64"
)
pc
+
=
2
src_reg
=
get_reg()
dst_reg
=
get_reg_size()
asm
=
'mov %s, [%s]'
%
(dst_reg, src_reg)
if
opsize <
4
:
asm
+
=
'\nmovzx %s, %s'
%
(src_reg, dst_reg)
x64_asm.append(asm)
elif
opcode
=
=
2
:
print
(f
"{opcode} not impl"
)
break
elif
opcode
=
=
3
:
if
opsize
=
=
1
:
print
(f
"store16"
)
if
opsize
=
=
2
:
print
(f
"store16"
)
if
opsize
=
=
4
:
print
(f
"store32"
)
if
opsize
=
=
8
:
print
(f
"store64"
)
pc
+
=
2
dst_reg
=
get_reg()
reg_index
-
=
1
src_reg
=
get_reg_size()
reg_index
-
=
1
asm
=
"mov [%s], %s"
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
4
:
print
(f
"{opcode} not impl"
)
break
elif
opcode
=
=
5
:
if
opsize
=
=
1
:
print
(f
"store8"
)
if
opsize
=
=
2
:
print
(f
"store16"
)
if
opsize
=
=
4
:
print
(f
"store32u"
)
if
opsize
=
=
8
:
print
(f
"store64"
)
pc
+
=
2
dst_reg
=
get_reg()
reg_index
-
=
1
src_reg
=
get_reg_size()
reg_index
-
=
1
asm
=
"mov [%s], %s"
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
6
:
if
opsize
=
=
1
:
print
(f
"store8"
)
if
opsize
=
=
2
:
print
(f
"store16"
)
pc
+
=
2
dst_reg
=
get_reg()
reg_index
-
=
1
src_reg
=
get_reg_size()
reg_index
-
=
1
asm
=
"mov [%s], %s"
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
7
:
if
opsize
=
=
1
:
print
(f
"add16"
)
if
opsize
=
=
2
:
print
(f
"add16"
)
if
opsize
=
=
4
:
print
(f
"add32"
)
if
opsize
=
=
8
:
print
(f
"add64"
)
pc
+
=
2
src_reg
=
get_reg_size()
reg_index
-
=
1
dst_reg
=
get_reg_size()
asm
=
'add %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
8
:
if
opsize
=
=
1
:
print
(f
"sub16"
)
if
opsize
=
=
2
:
print
(f
"sub16"
)
if
opsize
=
=
4
:
print
(f
"sub32"
)
if
opsize
=
=
8
:
print
(f
"sub64"
)
pc
+
=
2
src_reg
=
get_reg_size()
reg_index
-
=
1
dst_reg
=
get_reg_size()
asm
=
'sub %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
9
or
opcode
=
=
0xa
:
print
(f
"{opcode} not impl"
)
break
elif
opcode
=
=
0x0b
:
if
opsize
=
=
1
:
print
(f
"div16"
)
if
opsize
=
=
2
:
print
(f
"div16"
)
if
opsize
=
=
4
:
print
(f
"div32"
)
if
opsize
=
=
8
:
print
(f
"div64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'xor rdx, rdx'
asm
+
=
'\nmov rax, %s'
%
dst_reg
asm
+
=
'\nmov rcx, %s'
%
src_reg
asm
+
=
'\ndiv rcx'
asm
+
=
'\nmov %s, rax'
%
dst_reg
x64_asm.append(asm)
elif
opcode
=
=
0x0c
:
print
(f
"{opcode} not impl"
)
break
elif
opcode
=
=
0x0d
:
if
opsize
=
=
1
:
print
(f
"imul16"
)
if
opsize
=
=
2
:
print
(f
"imul16"
)
if
opsize
=
=
4
:
print
(f
"imul32"
)
if
opsize
=
=
8
:
print
(f
"imul64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'imul %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x0e
:
if
opsize
=
=
1
:
print
(f
"and16"
)
if
opsize
=
=
2
:
print
(f
"and16"
)
if
opsize
=
=
4
:
print
(f
"and32"
)
if
opsize
=
=
8
:
print
(f
"and64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'and %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x0f
:
if
opsize
=
=
1
:
print
(f
"or16"
)
if
opsize
=
=
2
:
print
(f
"or16"
)
if
opsize
=
=
4
:
print
(f
"or32"
)
if
opsize
=
=
8
:
print
(f
"or64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'or %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x10
:
if
opsize
=
=
1
:
print
(f
"xor16"
)
if
opsize
=
=
2
:
print
(f
"xor16"
)
if
opsize
=
=
4
:
print
(f
"xor32"
)
if
opsize
=
=
8
:
print
(f
"xor64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'xor %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x11
:
if
opsize
=
=
1
:
print
(f
"~16"
)
if
opsize
=
=
2
:
print
(f
"~16"
)
if
opsize
=
=
4
:
print
(f
"~32"
)
if
opsize
=
=
8
:
print
(f
"~64"
)
pc
+
=
2
src_reg
=
get_reg()
asm
=
'not %s'
%
(src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x12
:
if
opsize
=
=
1
:
print
(f
"CMP16"
)
if
opsize
=
=
2
:
print
(f
"CMP16"
)
if
opsize
=
=
4
:
print
(f
"CMP32"
)
if
opsize
=
=
8
:
print
(f
"CMP64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
reg_index
-
=
1
asm
=
'cmp %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x13
| opcode
=
=
0x14
:
print
(f
"{opcode} not impl"
)
break
elif
opcode
=
=
0x15
:
jmp_condition
=
vm_opcode[pc
+
2
]
offset
=
int
.from_bytes(vm_opcode[pc
+
3
:pc
+
3
+
8
],
'little'
)
jmp_pc
=
pc
-
offset &
2
*
*
64
-
1
target
=
hex
(jmp_pc)
lable
=
"lable_%s"
%
target
if
jmp_condition
=
=
0
:
print
(
"jmp"
)
asm
=
f
'jmp {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
1
:
print
(
"jz"
)
asm
=
f
'jz {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
2
:
print
(
"jnz"
)
asm
=
f
'jnz {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
3
:
print
(
"jbe"
)
asm
=
f
'jbe {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
4
:
print
(
"ja"
)
asm
=
f
'ja {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
5
:
print
(
"jae"
)
asm
=
f
'jae {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
6
:
print
(
"jle"
)
asm
=
f
'jle {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
7
:
print
(
"jg"
)
asm
=
f
'jg {lable}'
need_label.add(jmp_pc)
if
jmp_condition
=
=
8
:
print
(
"jg"
)
asm
=
f
'jg {lable}'
need_label.add(jmp_pc)
pc
+
=
11
x64_asm.append(asm)
elif
opcode
=
=
0x16
:
print
(
"pushVM"
)
reg_index
+
=
1
dst_reg
=
get_reg()
asm
=
"mov %s ,rbx"
%
dst_reg
pc
+
=
2
x64_asm.append(asm)
elif
opcode
=
=
0x17
:
print
(
"add64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'add %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x18
:
print
(
"imul64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'imul %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x19
:
print
(
"sub64"
)
pc
+
=
2
src_reg
=
get_reg()
reg_index
-
=
1
dst_reg
=
get_reg()
asm
=
'sub %s, %s'
%
(dst_reg, src_reg)
x64_asm.append(asm)
elif
opcode
=
=
0x1a
:
base
=
hex
(
int
.from_bytes(vm_opcode[pc
+
2
:pc
+
2
+
opsize],
'little'
))
print
(f
"rebase {base}"
)
pc
+
=
2
+
opsize
x64_asm.append(
'nop'
)
elif
opcode
=
=
0x1b
:
shellcode_len
=
vm_opcode[pc
+
2
]
print
(
"JIT"
)
print
(f
"shellcode {shellcode_len}"
)
shellcode_byte
=
vm_opcode[pc
+
3
:pc
+
3
+
shellcode_len]
asm
=
f
'JIT_{pc}:\n'
for
i
in
md.disasm(shellcode_byte,
0
):
asm
+
=
f
"{i.mnemonic} {i.op_str}\n"
print
(asm)
pc
+
=
3
+
shellcode_len
x64_asm.append(asm)
elif
opcode
=
=
0x1c
:
print
(
'return'
)
asm
=
'mov rax, rbx\nret'
x64_asm.append(asm)
break
with
open
(
"parse.s"
,
'w'
) as f:
f.write(
)
f.write(
'mov rbx, rcx\n'
)
f.write(
'\n'
.join(x64_asm))