This project aims to facilitate debugging a kernel driver in windows by adding support for a code change on the fly without reboot/unload, and more!

Overview

BSOD Survivor

Tired of always telling yourself when you got a BSOD that what if I could just return to the caller function which caused the BSOD, and change its args? or just do any change? and instead of that you need to do the tiersome reboot/revert to the machine, attach Windbg again to the machine, and hope it isn't some statistically bug? Or want to add a conditional breakpoint easily to some function you have like if(g_counter == 8) {__debugbreak();} without any need to unload the driver? Or even just update almost any code of a function you want without driver unloading.

This project is for you!!

These are the major components off the project:

  1. Update source code / global variables in debugging without any need to unload the driver or reboot the computer, by compiling the wanted changed file and link the created obj file with the already loaded code in memory , and then replace the functions which were in the old obj by the new functions which are in the new obj, (for now even if the functions are the same).

    You will need to use Bsod Survivor Visual Studio Plugin (and not only Windbg Plugin as all the other components) in order to use this feature. This plugin is needed for instructing Windbg which code to change at run time.

    Please read the limitations.

  2. Change the program state to be in the state before the current function was called - useful for continue the program even from some BSODs or making the same function called again but with a changed code. (See Example)

    This is done by calling the needed destructors in the current function, and return to the registers state of the calling function

  3. Jump to a previous line in the function - include calling needed destructors.

    Useful in order to reexamine what some code do again and again.

  4. Run expression evaluation from a file including templates/default parameters and so on, which Windbg doesn't support.

This project is a fork of LLVM 10.

This project is in beta version 0.3.0

The project is composed from Visual Studio plugin, Windbg plugin, and changes to LLDB/Clang/LLD.

Example

First we load a driver

as you can see I accidently called a function(realEntry) which doesn't do anything, its run is infinite in fact, and I can't even unload this driver.

so lets fix this:

first I go to Visual Studio to change and activate the dynamic linking in runtime with our driver , by clicking Tools->Linking With Loaded Driver, which will compile the selected file (Main.cpp) and link it dynamically.

This is the result

as you can see I added DriverUnload to the code, and this is not an infinite loop anymore.

Then I return to Windbg and run !return_with (return_with is returning from the current function and calling needed destructors, without continue the function- so it should be safe to be used) in the Windbg command window , in order to return to the previous function and rerun the function which we were inside

we are now after the call to realEntry, but we wants to run realEntry again, so I am jumping to line 14 - using !jump 14

and now I can just step into the function(F11) and continue debugging my new code as a regular code.

but then I remembered that what I really wants is that uniName in line 17 to be \\DosDevices\C:\WINDOWS\example2.txt instead of \\DosDevices\C:\WINDOWS\example.txt, although I can just update line 17, and do the same procedure as I did previously of changing the function, I can also just do this in another way, by evaluating and running an expression which will affect the local variable uniName, only in this run, and not in all the runs, usefull for experiments / code you don't want to run in multiple threads and so on.

!expr c:\temp\a.txt , where I saved in c:\temp\a.txt the following content: RtlInitUnicodeString(&uniName, L" \\\DosDevices\\C:\\WINDOWS\\example2.txt");

UniName as you can see have the value of L" \\\DosDevices\\C:\\WINDOWS\\example2.txt".

and finally let's see how we can continue the program - even if we got BSOD:

First let's get a driver which do a BSOD:

as you can see we accessed variable a where variable a has a value of nullptr, and that caused a BSOD.

lets "survive" this, by using !return_to_frame_with, which returns from frame 0 to the selected frame.

and now we can continue the program as usual by changing the value of a (by windbg command), or we can just do what we did previously and change this function code, and rerun it with the changed code.

Please be noted that I added in advance a breakpoint in nt!KeBugCheck* in order for break the program before it will changed to DISPATCH_LEVEL because of the BSOD, my recommendation is for you to always configure Windbg to break in those functions by "bm nt!KeBugCheck* " command, please See it in the Configure Windbg

Installation

you need to download the msi executable from https://github.com/ykfre/BsodSurvivor

and follow the installation guide in here.

Windbg Commands

  • !expr {expression} - Evaluates the expression in a file path and then evaluate it, Your breakpoints should be work as always so you can break in the functions which are called inside the expression.
  • !reload_config - Reload config.json again.
  • !return_with - Return from current frame with calling destructors, without continue the function flow.
  • !return_without - Return from current frame without calling destructors, without continue the function flow.
  • !return_to_frame_with - Return from current frame to the selected frame(you should press in Windbg on the selected frame) with calling destructors, without continue the function flow.
  • !return_to_frame_without - Return from current frame to the selected frame(you should press in Windbg on the selected frame) without calling destructors, without continue the function flow.
  • !jump {line_num} - Jump to a previous line in the same function, including calling needed destructors.
  • !reload_dynamic_modules - Make Windbg reload dynamic modules again, useful when you did .reload /f and Windbg removed the dynamic modules.
  • !reset_saved_files - Make Windbg stop showing some version of a cpp file, and make it use the most updated one in the disk, should only be used if a bug somehow appeared.
  • !discard_expr - Discard current expression if exists , this operation is not calling needed destructors.
  • !jump_to_most_updated - Change the current program counter to an equallivent function to the current function which is the most updated function, if it is safe to do so.

Build Your Driver

  • In order for the expression evaluator to work correctly even on templates/default arguments you need to add module.modulemap with sdafx.h as there is in the ClangDriverExample dir,(you can just take this file), and place it in the dir of the wanted include, see the structure of ClangDriverExample for better understanding.

    • stdafx.h should contain all the headers which we want their in information in debugging time Usually wdm and your STL types

    • In module.modulemap should be listed only one file.

    • There should be only one module.modulemap file in your entire project.

    • stdafx.h should be the first include in your files, and you shouldn't include any contained include after stdafx.h, for example let's say MyVector.h is inside stdafx.h - you shouldn't do:

      #include stdafx.h #include MyVector.h

  • In order for getting all the above functionality you need to use ${BSOD_SURVIVOR_DIR}\visual studio\BsodSurvivorDriverCommon.props for libs, and ${BSOD_SURVIVOR_DIR}\visual studio\BsodSurvivorDriver.props for drivers when you are compiling your driver. You must builld all your libs, which you want to change at run time and driver code using this compiler.

    BSOD_SURVIVOR_DIR - will be added to your environment variable after the Installation

Configure Windbg

In order for the plugin to work correctly you need to do the following:

  • In {windbg_folder}/amd64/winext/config.json please edit it as the comments there instructing.

  • In Windbg please make sure you are using the following command in order to use correctly the Windbg plugin:

    .load BsodSurvivor;.reload;ed nt!Kd_Default_Mask 8;bm nt!KeBugCheck*"

  • In your first ever plugin run - please let the plugin an access through Windows Defender firewall.

Supported Architectures

Currently it is supported on Windows 7 and Windows 10 without hvci.

For the Windbg plugin - Windbg Preview is required, and will not work correctly on the old one.

For the visual studio plugin - only Visual Studio 2019 is supported.

Limitations And Known Issues

  • There is for now only a support for one driver, that's means you can't use any feature of this project for debugging multiple drivers, only for one of them it will work (you will need to decide which one in the config.json file of the Windbg Plugin)
  • You won't be able to debug multiple vms nor using multiple instances of the Windbg plugin.
  • The vm must be stopped before you run any feature, and you must be sure the operation of the feature ended before you continue your run (There will be an informative log).
  • Some Antiviruses may for some reason block some operations of your local Windbg -please add Windbg and the plugin to the white list of those antiviruses if some blocking window appears.

Updating Driver Code In Runtime Limitations

  • Changes of functions are taking affect only on the next rerun of a function - meaning if you are already in a function when you debugged, before you linked, you must return from this function/call it again in order for the changes to take affect.

    for that reason I added a stub function like realEntry in ClangDriverExample, which gives me an ability to return from realEntry, and run it again like in the example above. Stubs are useful for every function which is a callback to external pes.

  • For now we support only changing one cpp/c file (and via that its headers).

  • Can't link with code which isn't reside in memory/ is in the source file which you change, meaning mostly that if you are using libs, your program should be linked with /wholearchive with them, please be note that this isn't necessary to libs of exported dlls like ntos, fltmgr and so on, because their functions are exported by drivers which are loaded in the memory.

  • Changes in a const static variable/static function (not static methods)/function in anonymous namespace/lambdas are taking affect only on the next run of this function from a changed regular function(not the mentioned functions), for example, let's say this is the code which is running:

    static void staticFunc()
    {
        // do_something
    }
    
    void r()
    {
        for(size_t i=0; i<10; i++)
        {
        	staticFunc();
        }
    }

    if we are in staticFunc we need not only to return from staticFunc, but we need also to return from r and rerun it, in order to changes to take affect, as staticFunc is static.

  • Functions/Globlals from old objs have different addresses from Functions/ Globals in the new the new obj.

  • Globals with ctor's/dtor's aren't supported and will not work as expected.

  • Pre build scripts which changes/adds c++ code aren't supported.

  • Inline static const int varialbes changes are taking affect only on an obj file change base, and all the cpp files which are using this variables should be recompiled.

  • Modifiable global variable won't be updated the value in the new obj if this variable was already exists in in the driver. For example let's say int g=0; was in the driver, and now we write int g=1;

    g will actually have a value of 0, and not 1. This is an intended behavior in order to reserve global variables values which may change in a runtime.

  • Old/new break points on an old source code, won't affect anymore the program, so you will need to place them on the newest source file, which is created in a temp directory, This file is opened when you step into one of the new functions, or you can open it manually by searching the last modified file using Everything and the file name which you changed. For example let's say you changed a file whose name is main.cpp, than search in Everything main.cpp, and you will find the file is "____2_____6264218882520860571____Main.cpp". You can of course just place __debugbreak() in the code instead of opening the file.

  • Code which uses try catch/sehs shouldn't be in a code which is being updated - as Windows will not run the catch/__except code.

    You should place them in different files from the file which you want to change.

Evaluating Expressions - Limitations

  • For now there isn't a support for printing automatically a result of expression, you need to use instead DbgPrint in the expression, for example: DbgPrint("result is %d", f()).

  • Default function arguments /Macros won't be found if if the function isn't in a file which is in in a clang module

    • All the modules support is very much experimental!
  • Functions which didn't compiled to the binary - won't be able to be found and used, mainly important for templates/ static unused functions if their implementation isn't in a module .

  • Functions in an anonymous namespaces won't be found.

  • Expressions with classes/functions with const expressions SNIFAE, or forward declaration won't be evaluated correctly even with module, please use static const where possible. type_traits, std::unique_ptr,std::shared_ptr, std::optional, and std::expected were changed in order to be implemented without static constexpr where possible in here.

    This files are also installed as part of BSOD_SURVIVOR installation (will be used only if you include them).

  • Templates and Default function arguments won't work if you will compile the program using Incredibuild, as it won't find there module.modulemap in the remote computer ( the compilation will still succeed)

  • You won't be able to evaluate expression if there is an upper frame from your selected frame, which its program counter isn't in your main driver as configured in config.json

  • Consts values are evaluated using the original module content only.

Open Source Acknowledgements

Blink - https://github.com/crosire/blink for pdb parser and some ideas.

tenzen-llvm-project https://github.com/tentzen/llvm-project, for the implementation of sehs in llvm x64, which return of frame is based on.

cppcheck-plugin https://github.com/VioletGiraffe/cppcheck-vs-addin The code of the Visual Studio Extension is based on this code.

Microsoft stl - https://github.com/microsoft/STL

std::expected - https://github.com/TartanLlama/expected

Issues
  • make __finally work, and add UT.

    make __finally work, and add UT.

    make __finally work, and add UT. make drivers to be loaded, and seems to work on Windows 10 RS3.ReadDefinedMacros . remove debug info of nop for seh to make return_with work correctly even if nop is added in seh emitting.

    opened by ykfre 0
Releases(v0.3-bsod)
  • v0.3-bsod(Feb 8, 2021)

    Features:

    1. Add a support for expressions evaluation including templates/default parameters/run a function on the local variables without changing the current function code, which Windbg doesn't support. for example : v.push_back(5); v.at(0); Please read the README for more details about this feature and its limitations.
    2. When changing the code dynamically Windbg will move you to the changed function code if possible, and it should be possible if your changes are only calling functions/changing variables after the current line in the debugging.
    3. Add warnings/treat warnings as errors according to the visual studio project configuration.

    Bug Fixes:

    1. Fix bug where "." wasn't added for the include when compiled files for the new code change
    2. Fix bug of a handle to a CPP file wasn't close - prevent writing to the file.
    3. Make sure BsodSurvivor Visual Studio will be the active window after updating the binary.
    Source code(tar.gz)
    Source code(zip)
    BsodSurvivor.msi(412.56 MB)
  • v0.2-bsod(Jan 19, 2021)

  • v0.1-bsod(Jan 7, 2021)

    Add support for the following components:

    1. Editing driver code dynamically without any need to uninstall the driver/ reboot the computer
    2. Jump to a previous line-in function, and calling needed destructors.
    3. Stop execution of the current function and return to the caller function and call needed destructors.
    Source code(tar.gz)
    Source code(zip)
    BsodSurvivor.msi(411.90 MB)
Owner
Ido Westler
Ido Westler
An asynchronous directory file change watcher module for Windows, macOS and Linux wrapped for V

A V module for asynchronously watching for file changes in a directory. The module is essentially a wrapper for septag/dmon. It works for Windows, macOS and Linux.

null 16 Jul 29, 2022
This project aims to code a C library regrouping usual functions.

42-formation-lvl1-1.libft Project 1 - Libft - First project for the formation of software engineers at school 42 São Paulo This project aims to code a

Vinicius Naziozeno Santoro do Rio 1 Jun 20, 2022
Windows kernel hacking framework, driver template, hypervisor and API written on C++

Windows kernel hacking framework, driver template, hypervisor and API written on C++

Александр 1.2k Aug 1, 2022
A c++ file just to show how can we change color of Background and Text in C++...

A c++ file just to show how can we change color of Background and Text in C++...

null 1 Nov 2, 2021
A LKM rootkit targeting 4.x and 5.x kernel versions which opens a backdoor that can be used to spawn a reverse shell to a remote host and more.

Umbra Umbra (/ˈʌmbrə/) is an experimental LKM rootkit for kernels 4.x and 5.x (up to 5.7) which opens a network backdoor that spawns reverse shells to

Marcos S. Bajo 83 Jul 26, 2022
cavi is an open-source library that aims to provide performant utilities for closed hierarchies (i.e. all class types of the hierarchy are known at compile time).

cavi cavi is an open-source library that aims to provide performant utilities for closed hierarchies (i.e. all class types of the hierarchy are known

Baber Nawaz 5 Mar 9, 2022
CppDyn is a library which aims to simplify use of polymorphism in C++20

Cpp Dyn Cpp-Dyn tries to improve C++ runtime polymorphism. Indeed, C++ runtime polymorphism, originally, uses inheritance and virtual methods. Sean Pa

Antoine MORRIER 14 Jun 7, 2022
A simple Windows kernel rootkit.

Venom RootKit A simple windows rootkit that I have wrote, In order to explore a bit about the world of rootkits and windows kernel in general. The Ven

Amit Schendel 58 Jul 22, 2022
GNU project's implementation of the standard C library(with Xuantie RISC-V CPU support).

GNU project's implementation of the standard C library(with Xuantie RISC-V CPU support).

T-Head Semiconductor Co., Ltd. 5 Mar 17, 2022
Tool based in nodes to build GLSL shaders without any programming knowledge written in C using OpenGL and GLFW.

FNode Tool based in nodes to build GLSL shaders without any programming knowledge written in C using OpenGL and GLFW (raylib library). It contains a c

Víctor Fisac 72 Jul 17, 2022
Handling C++ & __try exceptions without the need of built-in handlers.

manual_exception_handling this handles exceptions inside the module its specified to manage without needing previous handlers for the exception a good

null 36 Aug 8, 2022
Do u wanna create more than one trial account on exitlag? This 'spoofer' is for you!

ExitLag HWID Bypass Do you wanna create more than one trial account on exitlag? So this 'spoofer' is for you! Why? Exitlag limit the trial account cre

Benjamin 10 Mar 6, 2021
x64 Windows PatchGuard bypass, register process-creation callbacks from unsigned code

NoPatchGuardCallback x64 Windows PatchGuard bypass, register process-creation callbacks from unsigned code Read: https://www.godeye.club/2021/05/22/00

Kento Oki 119 Jul 31, 2022
ARCHIVED - libbson has moved to https://github.com/mongodb/mongo-c-driver/tree/master/src/libbson

libbson ARCHIVED - libbson is now maintained in a subdirectory of the libmongoc project: https://github.com/mongodb/mongo-c-driver/tree/master/src/lib

mongodb 340 Aug 1, 2022
runsc loads 32/64 bit shellcode (depending on how runsc is compiled) in a way that makes it easy to load in a debugger. This code is based on the code from https://github.com/Kdr0x/Kd_Shellcode_Loader by Gary "kd" Contreras.

runsc This code is based on the code from https://github.com/Kdr0x/Kd_Shellcode_Loader by Gary "kd" Contreras and contains additional functionality. T

null 25 Jul 27, 2022
A shebang-friendly script for "interpreting" single C99, C11, and C++ files, including rcfile support.

c99sh Basic Idea Control Files Shebang Tricks C++ C11 Credits Basic Idea A shebang-friendly script for "interpreting" single C99, C11, and C++ files,

Rhys Ulerich 101 Jul 29, 2022
A small and portable INI file library with read/write support

minIni minIni is a portable and configurable library for reading and writing ".INI" files. At just below 900 lines of commented source code, minIni tr

Thiadmer Riemersma 270 Aug 8, 2022
The goal of arrowvctrs is to wrap the Arrow Data C API and Arrow Stream C API to provide lightweight Arrow support for R packages

The goal of arrowvctrs is to wrap the Arrow Data C API and Arrow Stream C API to provide lightweight Arrow support for R packages to consume and produce streams of data in Arrow format. Right now it’s just a fun way for me to learn about Arrow!

Dewey Dunnington 29 Jul 9, 2022