-
Notifications
You must be signed in to change notification settings - Fork 10
Architecture
Brovan is a multi-guest emulator, with a large set of components shared between the guests. It runs Windows and Linux programs, and it runs on Windows, Linux and Android hosts.
Brovan is not tied to one CPU backend anymore. Three backends are available today, and you select one with --backend=<name>.
- Unicorn is the default. It translates the guest code, so the emulator sees every instruction and can hook it. This is the backend to use for analysis.
- KVM runs the guest on the real CPU through the Linux hypervisor.
- WHP runs the guest on the real CPU through the Windows Hypervisor Platform.
The hypervisor backends are much faster, but they don't have the analysis capabilities unicorn has. so some analysis features stay Unicorn-only.
-
Core/BinaryFile.cswhich parses binary file formats. Many parts of the emulator use it, either from a guest or from the core, to do the operations related to that guest, or to do analysis. For example, the Windows guest uses it to parse other modules and to fill their information intoWinModule. -
Core/Emulation/BinaryEmulator.cswhich is the main binary emulation interface. It accepts a guest directly, or aBinaryFilethat tells it which guest to build. It owns the guest memory map, the handle and object state, the MLFQ scheduler, and the callbacks that guests plug into, such asExecuteThreadSliceandOnThreadContextLoaded. It also receives the runtime events like CPUID, syscalls, interrupts and memory faults, and it sends them to the active guest. -
Core/Emulation/BinaryEmulatorHelper.cswhich holds the contracts and the small types the core needs.IGuestEnvironmentis the interface every guest implements.IWinSyscallandILinuxSyscallare the two syscall handler interfaces, and each one documents its argument convention for x86 and for x64.SyscallDispatchTable<TEntry>is the packed table used to find a handler from a syscall number without a dictionary lookup.MemoryRegion, the allocation and protection flags, andBrovanSocket, which applies the network policy, also live here. -
Core/Emulation/RuntimeTypes.cswhich holds the runtime thread types.EmulatedThreadandCpuContextdescribe a guest thread and its saved registers, including the vector registers.WakeSignalis the counter that tells the scheduler that something can unblock a thread. -
Core/Emulation/SyscallManager.cswhich holds the user-facing syscall rules, the syscall trace, and the call history that the interactive menu shows. It is separate from the handlers themselves. -
Core/Emulation/Backends/which containsIEmulationBackend, the interface that hides the CPU backend from the rest of the emulator,BackendFactory, which builds the one you asked for, and one folder for each backend. The interface also reports what the backend can and cannot do, for example the highest address it can map and whether RDTSC reaches the emulator. -
Core/Emulation/UnicornBinding/,Core/Emulation/KvmBinding/andCore/Emulation/WhpBinding/which contain the native bindings, constants and imports for each backend.UnicornCodeCache.cssaves and reloads the translated code, so a program does not translate itself again on every launch. -
Core/Emulation/Guests/which containsGuestFactoryand the guests. A PE file goes toWindowsGuest, an ELF file goes toLinuxGuest, andGenericGuestruns a raw blob or a memory dump that has no recognized format, including ARM code. -
Core/Helpers/which contains the shared helpers.BinaryHelpers.csholds the PE, .NET and ELF parsing types and the common enums.Utils.csandSimdStringHelpers.cshold general utilities.RegistryManager.csreads the real registry hives that the guest sees.WindowsImage/holds the importer used by--install-windows, with the ISO, WIM, LZX, XPRESS and LZMS readers, plus the Visual C++ runtime and DXVK importers. -
GeneralHelper.cswhich is the general-purpose helper. It contains the native imports for some Windows and Linux functions, theIOhelper that gives sandboxed and cross-platform file access, and other utility functions. -
Core/Emulation/OS/SharedHelpers/StructSerializer.cswhich is the general struct helper. It reads a struct from guest memory, writes one back, and reports its size.StructSerializerGeneratorgenerates the fast path for it, so a call site does not change. -
Core/Emulation/OS/SharedHelpers/WindowManager/which is the host window layer that both guests use.WindowManager.csholds the shared state and the host event queue,GuiThreadManager.csruns the event-driven GUI thread, andWindowsWinManager.csandLinuxWinManager.csimplement the host side. The Android host adds its own manager underBrovan/Android/. -
Core/Emulation/OS/SharedHelpers/AudioManager/which is the host audio layer, with a sink for each host. The Windows guest audio path runs on top of it. -
Analysis/which containsBinaryAnalyzer.cs, the disassembly and analysis code built on Iced, andNetworkTrafficPcapCapture.cs, which writes the emulated network traffic to a pcap file. -
EmulationMenu/which contains the interactive command menu and the built-in debugger, including the call trace, the function monitor and the string scanner. -
Brovan.Generators/which contains the Roslyn source generators.StructSerializerGeneratoremits the struct read and write code.VulkanForwardGeneratorreadsvk.xmland emits the Vulkan forwarding layer.WinRegistryGeneratoremits registry-related code. Generators cannot rewrite call sites, so each one dispatches from a registry instead. -
Brovan.Graphics/which contains the graphics side.brovvulk-icd/is the small Vulkan ICD that the guest loads,vulkan-headers/holds the headers it builds against, anddemo/is a sample. -
Brovan/Android/andBrovan.Android/which contain the Android host code and the launcher application.Brovan/Android/holds the host implementations, such as the window manager, the audio sink, input, text and the Vulkan WSI.Brovan.Android/is the app project that packages them.
The MLFQ scheduler lives in BinaryEmulator. It gives each runnable thread a slice, drops a thread that uses its whole slice to a lower queue, and ages a thread that waited too long back up.
The scheduler skips its wakeup scan when nothing changed, and it decides that from WakeSignal, a counter that every event able to unblock a thread must increase. The eight waitable handle types increase it from their setters. Everything else increases it at the point where the event happens, such as window messages, host input, APCs, thread termination and resume, futex wake, signals and eventfd.
A missing increase drops a wakeup. That reads as a hang, and no test fails, so be careful when you add a new way to unblock a thread. EmulatedThread.State has no setter that increases the counter for you, and that is on purpose.
All of these are under Core/Emulation/OS/Windows/.
-
Guests/WindowsGuest.cswhich contains the Windows guest itself. It handles the process setup, module loading, PEB and TEB creation, thread start, APC dispatch, and the Windows-specific flow used at runtime. It also builds the WOW64 view for 32-bit guests, which needs a second TEB and PEB pair and the System32 to SysWOW64 path redirection. -
BinaryEmulator.WindowsBridge.cswhich connectsBinaryEmulatorto the Windows state and helpers, and exposes the Windows accessors that the core uses. This part is legacy and will be removed later. It only exists because the guest-style implementation came after many syscalls already expected everything to live inBinaryEmulator.cs. -
WinSyscallsHelper.cswhich contains the shared Windows syscall support code, such as handle and object management, the shared buffers, the device control helpers, and the logic reused across the handlers. Use the shared buffer it already exposes instead of allocating a new one. -
WinInternalHelper.csandWinHelperConstants.cswhich hold the internal Windows helper types and the constants and device data types that the handlers share. -
WinStructs.cswhich contains many Windows structure definitions and their helpers. Some structures are written straight into guest memory by hand, so you will not find every structure the emulator uses in this file. -
WinThreading.cswhich contains the Windows thread state, such as APC tracking, exception state, worker factory state, and the other per-thread Windows data. -
WindowsFileStream.cswhich is the Windows file stream used by the guest. It prefers the Windows VFS and falls back to the allowed host files when that is correct. -
WindowsVersionInfo.cswhich contains the version and build information written into guest memory and reported to Windows programs. -
Devices/which contains the emulated Windows devices. It includesConDrvfor the console, the AFD socket device, the mount point manager, the physical disk and volume devices, WMI, the KsecDD device that serves CNG, andBrovVulk, which forwards Vulkan from the guest to the host driver. -
Session/which contains the guest session table, the mailbox, and the remote process support. Each guest process runs in its own Brovan process, and these files let the members of one session find and talk to each other. -
RPC/which contains the ALPC and LRPC support, the NDR reader, and the ports underRPC/Ports/, such as the API port and the audio service port. -
Files/,Misc/,Process/,Registry/andWin32k/which contain the Windows syscall handlers grouped by subsystem. They cover file operations, synchronization and object handling, process, thread and memory control, registry access, and the win32k and user-mode GUI behaviour, which includes GDI drawing, window management, input and DPI.
All of these are under Core/Emulation/OS/Linux/, except the guest itself.
-
Guests/LinuxGuest.cswhich contains the Linux guest. It handles ELF loading, module mapping, thread and signal state, syscall dispatch, and the Linux-specific flow. -
LinuxSyscallsHelper.cswhich contains the shared Linux syscall support code, such as the errno values, the stat helpers, the socket and file helpers, and the memory and process utilities. It also exposes a shared buffer, the same as the Windows side. -
LinuxFileStream.cswhich is the Linux file stream used by the guest. It prefers the Linux VFS paths and falls back to host files when that is correct. -
LinuxStructs.cswhich contains the Linux structure definitions and their helpers. -
SpecialPathsHandlers.cswhich handles the special paths such as/dev,/procand/sys, and gives the emulated content for the virtual files and the device-like paths that Linux programs read. -
Events/which contains the event syscalls such asepoll,eventfdandtimerfd. -
Files/which contains the file syscalls such asopen,read,write,stat,fcntl,lseek,mountand directory enumeration. -
Misc/which contains the remaining syscalls such asclock_gettime,poll,pselect6,getrandom,unameandclose. -
network/which contains the networking syscalls such assocket,bind,connect,accept,sendto,recvfrom,setsockoptandsocketcall. -
Process/which contains the process and memory syscalls such asclone,mmap,mprotect,mremap,munmap,prctl,futex,brkandarch_prctl. -
Signals/which contains the signal syscalls such askill,tgkill,tkill,rt_sigaction,rt_sigprocmask,rt_sigsuspendandsigaltstack.
The flow keeps the core generic and lets each guest control its own behaviour.
-
A
BinaryFileis created from the input file.- It parses the file format and extracts the information needed for analysis and loading.
- This can include the headers, sections, imports, exports, symbols and other format-specific data.
-
A backend is created from
BackendFactory.- The
--backendoption selects Unicorn, KVM or WHP. Unicorn is the default. - The rest of the emulator only sees
IEmulationBackend, so the choice does not change the code above it.
- The
-
BinaryEmulatorreceives either theBinaryFileor a guest directly.- If a
BinaryFileis given,GuestFactorypicks the guest from the file format. - A file with no recognized format can still run through
GenericGuest.
- If a
-
The selected guest does its own setup.
- The Windows guest loads the modules, builds the module list, creates the PEB and TEB, and prepares the memory layout. For a 32-bit program it also builds the WOW64 view.
- The Linux guest maps the ELF image and does its own process and memory setup.
-
BinaryEmulatorconfigures the execution state.- Memory mappings, registers, hooks and backend-specific settings are applied here.
- The shared helpers such as
StructSerializerandGeneralHelperare used when needed.
-
Execution starts through the backend.
- The backend executes the instructions.
- During execution, the callbacks go back to the guest when guest-specific handling is needed.
-
The guest and the scheduler work together at runtime.
- The MLFQ scheduler manages the threads and their slices.
-
ExecuteThreadSliceandOnThreadContextLoadedlet the guest join the scheduling without repeating the logic. - Anything that makes a blocked thread runnable must increase
WakeSignal, or the scheduler does not look.
-
Runtime events go through the shared callbacks.
- CPUID, syscalls, interrupts, exceptions and memory faults arrive at
BinaryEmulator. - The emulator sends them to the active guest, or handles them with the common logic when it can.
- CPUID, syscalls, interrupts, exceptions and memory faults arrive at