Script to use SysWhispers2 direct system calls from Cobalt Strike BOFs.
This script was initially created to fix specific Cobalt Stike BOFs, such as @rookuu's MiniDumpWriteDump that did not work on Windows 21H1. The reason for the BOFs breaking was that they relied on direct system calls based on a syscalls.h file generated using @Outflank's InlineWhispers - which generates syscall wrappers based on the original SysWhispers project. The original version of SysWhispers relies on a table that maps system call names to system call numbers, which requires updating for each new Windows version to include the appropriate system call numbers for the updated Windows version. This means that a new syscalls.h file needs to be generated and BOFs using this syscalls.h file need to be recompiled each time a new Windows version is released.
A new version of SysWhispers called SysWhispers2 was released in March 2021 by Jackson T.. It uses a different technique and resolves the system call numbers on the target machine instead of relying on a pre-calculated list of system call numbers. This allows generating the syscalls.h and compiled BOF once and this single version should work on new Windows versions without updates.
Unfortunately, the output generated by SysWhispers2 cannot be directly used inside Cobalt Strike BOFs and requires some tweaks to convert it into a format that can be used by Cobalt Strike BOFs. The script provided in this repository performs those tweaks automatically for you and can also be used to convert an existing syscalls.h file from an existing BOF to a new syscalls.h file that uses SysWhispers2.
Start by cloning this repository. Once the repository is cloned, clone the SysWhispers2 repository inside, for example:
$ git clone https://github.com/FalconForceTeam/SysWhispers2BOF
$ cd SysWhispers2BOF
$ git clone https://github.com/jthuraisamy/SysWhispers2
The tool can be used to generate a syscalls.h file. To do this, the list of system calls to include in the .h file needs to be specified. This can be specified in 3 different ways:
- On the command-line using
--syscalls=comma,separated,list
, e.g.--syscalls=NtOpenProcess,NtQuerySystemInformation
- By reading the syscalls.h file from an existing BOF. This allows easy conversion of the BOF to use SysWhispers2 using
--syscalls_h=file_name.h
, e.g.--syscalls=bof/syscalls.h
- By reading the functions from a text file in the same method used by InlineWhispers, using
--syscalls_file=filename
, e.g.--syscalls_file=functions.txt
. Note: make sure to use the Nt prefix rather than the Zw prefix for the system call names.
It will produce a syscalls.h file in the current directory.
$ python3 syswhispers2bof.py --syscalls=NtOpenProcess,NtQuerySystemInformation
[*] Used syscalls: ['NtOpenProcess', 'NtQuerySystemInformation']
[*] Calling SysWhispers2 to generate stubs for these system calls
. ,--.
,-. . . ,-. . , , |-. o ,-. ,-. ,-. ,-. ,-. /
`-. | | `-. |/|/ | | | `-. | | |-' | `-. ,-'
`-' `-| `-' ' ' ' ' ' `-' |-' `-' ' `-' `---
/| | @Jackson_T
`-' ' @modexpblog, 2021
SysWhispers2: Why call the kernel when you can whisper?
Complete! Files written to:
syswhispers2bof.h
syswhispers2bof.c
syswhispers2bofstubs.asm
[*] Fixing up H file SysWhispers2/syswhispers2bof.h
[*] Fixing up C file SysWhispers2/syswhispers2bof.c
[*] Converting ASM stubs from SysWhispers2/syswhispers2bofstubs.asm
[*] Writing combined output to syscalls.h
[*] Note: asm.h is no longer needed
This will provide a single file: syscalls.h
that can be included in the BOF to make direct system calls.
Example of using it to update the syscalls.h file on an existing BOF to create a version of the BOF that works on Windows 21H1 and later.
# Clone a BOF that is not compatible with Windows 21H1 since it uses an older version of syscalls.h
$ git clone https://github.com/rookuu/BOFs
Cloning into 'BOFs'...
<snip>
$ python3 syswhispers2bof.py --syscalls_h=BOFs/MiniDumpWriteDump/syscalls.h
[*] Extracting syscalls from BOFs/MiniDumpWriteDump/syscalls.h
[*] Used syscalls: ['NtReadVirtualMemory', 'NtOpenProcessToken', 'NtAdjustPrivilegesToken', 'NtOpenProcess', 'NtClose', 'NtQuerySystemInformation']
<snip>
[*] Writing combined output to syscalls.h
[*] Note: asm.h is no longer needed
$ cp syscalls.h BOFs/MiniDumpWriteDump
$ cd BOFs/MiniDumpWriteDump
$ rm asm.h
$ make
x86_64-w64-mingw32-gcc -o minidumpwritedump.x64.o -c bof.c -masm=intel -Wno-multichar
# New .o file should be usable across newer Windows versions without the need to recompile it.
The tool was only tested on Mac and Linux - it might not work fully on Windows.
Note that this script is just a small wrapper around the excellent work done by @jthuraisamy and was heavily inspired by the output generated by @Outflank's InlineWhispers.