Skip to content
/ ZVM Public

Disassembler for Zeus VM custom instruction set

Notifications You must be signed in to change notification settings

OALabs/ZVM

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 

Repository files navigation

ZVM

Disassembler for Zeus VM custom instruction set with a Binary Ninja plugin.

What

This is just a demo to learn more about reverse engineering virtual machines and Binary Ninja architecture plugin development. Our goal is to build a disassembler for the custom Zeus VM instruction set and disassemble the VM code then lift it in Binary Ninja to reveal the custom algorithm used to protect their configuration file.

The Zeus VM uses a custom set of XOR keys in the instruction set that is updated with each build. Because of this our disassembler will only work with a single version of the malware f792997cb36a477fa55102ad6b680c97e3517b2e63c83c802bf8d57ae9ed525e [Download].

Development Notes

The full analysis and development process is being streamed on Twitch and the VODs are available on the OALABS Patreon.

Notes from our streams are also available here.

Documentation

For the Binary Ninja Plugin we loosely followed the binja Architecture Plugin guides and had a lot of help from @xusheng6.

Reference

The following references were also helpful.

Intrinsics

For our architecture we had two unique instructions, rc4 and shuffle both of which don't have a good representation in the binja IL. To represent these we used intrinsics

from binaryninja.architecture import IntrinsicInfo
from binaryninja.types import Type

intrinsics = {'rc4': IntrinsicInfo(inputs=[], outputs=[], index=1),
              'shuffle': IntrinsicInfo(inputs=[Type.int(4, False), Type.int(1, False)], outputs=[], index=2)

Loops

Loops are also interesting as they require an expression that branches. The code is straight forward but one thing to keep in mind is that each expression in the IL has a label an labels are used for branching (instead of addresses).

il.append(il.set_reg(4,
                     'loop_counter',
                     il.sub(4, il.reg(4, 'loop_counter'), il.const(4, 1))))
condition = il.compare_not_equal(4, il.reg(4, 'loop_counter'), il.const(4, 0))
t = il.get_label_for_address(Architecture['ZVM'], addr + instr.size - op2.value)
f = il.get_label_for_address(Architecture['ZVM'], addr + instr.size)
# here we just think t and f are both valid, and take the easy route
il.append(il.if_expr(condition, t, f))

No PRs

Because this project is meant to be a community effort on stream we won’t be accepting PRs. Aside from some maintenance/cleanup all coding will be done on-stream. If you have feature requests or suggestions leave your feedback as an Issue or come chat with us on Discord.

Join Us!

💖 Check out our schedule we stream Sundays at 1300 EST

Chat Support

About

Disassembler for Zeus VM custom instruction set

Resources

Stars

Watchers

Forks

Languages