From 4211e24f449c8be4f657864d6b978eeef9c4ca70 Mon Sep 17 00:00:00 2001 From: n3k Date: Mon, 27 Feb 2023 20:10:10 -0300 Subject: [PATCH] major refactor - added features - fixed bugs --- CMakeLists.txt | 10 + PlatboxClient/CMakeLists.txt | 65 +- PlatboxClient/DeltaFuzz/DeltaFuzz.h | 63 -- PlatboxClient/Makefile | 8 - PlatboxClient/PlatboxClient.cpp | 383 ++++++++++++ PlatboxClient/PlatboxClient.h | 28 + PlatboxClient/README.md | 22 +- PlatboxClient/build.bat | 5 - PlatboxClient/src/PlatboxClient.cpp | 466 --------------- PlatboxClient/src/global.cpp | 82 --- {Platbox => PlatboxDrv}/linux/driver/Makefile | 0 .../linux/driver/install.sh | 0 .../linux/driver/kernetix.c | 14 +- .../linux/driver/low_level_functions.asm | 0 .../linux/include/kernetix.h | 1 + {Platbox => PlatboxDrv}/windows/Platbox.sln | 0 .../windows/Platbox/CbHooks.c | 0 .../windows/Platbox/CbHooks.h | 0 .../windows/Platbox/Platbox.c | 14 +- .../windows/Platbox/Platbox.h | 0 .../windows/Platbox/Platbox.inf | 0 .../windows/Platbox/Platbox.vcxproj | 3 +- .../windows/Platbox/Platbox.vcxproj.filters | 0 .../windows/Platbox/low_level_functions.asm | 0 PlatboxDrv/windows/Platbox/x86Bios.c | 16 + PlatboxDrv/windows/Platbox/x86Bios.h | 42 ++ PlatboxLib/CMakeLists.txt | 83 +++ .../DeltaFuzz/CMakeLists.txt | 2 - .../DeltaFuzz/DeltaFuzz.c | 105 ++-- PlatboxLib/DeltaFuzz/DeltaFuzz.h | 70 +++ .../DeltaFuzz/DeltaFuzzLib.lib | Bin .../DeltaFuzz/README.md | 0 PlatboxLib/README.md | 15 + {PlatboxClient => PlatboxLib}/inc/UEFIVars.h | 49 +- {PlatboxClient => PlatboxLib}/inc/Util.h | 6 +- .../inc/amd/amd_chipset.h | 104 ++-- PlatboxLib/inc/amd/amd_spi.h | 203 +++++++ .../inc/common_chipset.h | 0 {PlatboxClient => PlatboxLib}/inc/global.h | 24 +- .../inc/intel/intel_chipset.h | 32 +- .../inc/linux/__linux.h | 0 {PlatboxClient => PlatboxLib}/inc/msr.h | 0 {PlatboxClient => PlatboxLib}/inc/pci.h | 3 +- {PlatboxClient => PlatboxLib}/inc/physmem.h | 8 +- .../inc/smm/smi_fuzz.h | 0 .../inc/smm/smm_communicate.h | 1 + {PlatboxClient => PlatboxLib}/inc/types.h | 0 .../inc/windows/__win.h | 47 +- .../src/UEFIVars.cpp | 38 +- {PlatboxClient => PlatboxLib}/src/Util.cpp | 42 +- .../src/_run_attempt.asm | 0 .../src/amd/amd_chipset.cpp | 182 +++--- PlatboxLib/src/amd/amd_spi.cpp | 557 ++++++++++++++++++ .../src/common_chipset.cpp | 35 +- PlatboxLib/src/global.cpp | 349 +++++++++++ .../src/intel/intel_chipset.cpp | 208 +++---- .../src/linux/placeholder | 0 {PlatboxClient => PlatboxLib}/src/msr.cpp | 0 {PlatboxClient => PlatboxLib}/src/pci.cpp | 146 +---- {PlatboxClient => PlatboxLib}/src/physmem.cpp | 83 --- .../src/smm/smi_fuzz.cpp | 2 +- .../src/smm/smm_communicate.cpp | 4 +- .../src/windows/acpidump.cpp | 1 - .../src/windows/kernelHookCb.cpp | 0 .../src/windows/page_tables.cpp | 0 README.md | 99 ++-- build.bat | 8 + build.sh | 7 + compiled/Platbox.cer | Bin 0 -> 784 bytes compiled/Platbox.inf | 31 + compiled/Platbox.sys | Bin 0 -> 14496 bytes compiled/example | Bin 0 -> 72312 bytes compiled/example.exe | Bin 0 -> 134144 bytes compiled/platbox_cli | Bin 0 -> 115200 bytes compiled/platbox_cli.exe | Bin 0 -> 218112 bytes docs/smm_future.txt | 4 - pocs/CMakeLists.txt | 40 ++ pocs/README.md | 3 + pocs/poc.cpp | 63 ++ .../inc/PlatboxClient.h => pocs/poc.h | 23 +- 80 files changed, 2458 insertions(+), 1441 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 PlatboxClient/DeltaFuzz/DeltaFuzz.h delete mode 100644 PlatboxClient/Makefile create mode 100644 PlatboxClient/PlatboxClient.cpp create mode 100644 PlatboxClient/PlatboxClient.h delete mode 100644 PlatboxClient/build.bat delete mode 100644 PlatboxClient/src/PlatboxClient.cpp delete mode 100644 PlatboxClient/src/global.cpp rename {Platbox => PlatboxDrv}/linux/driver/Makefile (100%) rename {Platbox => PlatboxDrv}/linux/driver/install.sh (100%) rename {Platbox => PlatboxDrv}/linux/driver/kernetix.c (98%) rename {Platbox => PlatboxDrv}/linux/driver/low_level_functions.asm (100%) rename {Platbox => PlatboxDrv}/linux/include/kernetix.h (99%) rename {Platbox => PlatboxDrv}/windows/Platbox.sln (100%) rename {Platbox => PlatboxDrv}/windows/Platbox/CbHooks.c (100%) rename {Platbox => PlatboxDrv}/windows/Platbox/CbHooks.h (100%) rename {Platbox => PlatboxDrv}/windows/Platbox/Platbox.c (98%) rename {Platbox => PlatboxDrv}/windows/Platbox/Platbox.h (100%) rename {Platbox => PlatboxDrv}/windows/Platbox/Platbox.inf (100%) rename {Platbox => PlatboxDrv}/windows/Platbox/Platbox.vcxproj (98%) rename {Platbox => PlatboxDrv}/windows/Platbox/Platbox.vcxproj.filters (100%) rename {Platbox => PlatboxDrv}/windows/Platbox/low_level_functions.asm (100%) create mode 100644 PlatboxDrv/windows/Platbox/x86Bios.c create mode 100644 PlatboxDrv/windows/Platbox/x86Bios.h create mode 100644 PlatboxLib/CMakeLists.txt rename {PlatboxClient => PlatboxLib}/DeltaFuzz/CMakeLists.txt (82%) rename {PlatboxClient => PlatboxLib}/DeltaFuzz/DeltaFuzz.c (81%) create mode 100644 PlatboxLib/DeltaFuzz/DeltaFuzz.h rename {PlatboxClient => PlatboxLib}/DeltaFuzz/DeltaFuzzLib.lib (100%) rename {PlatboxClient => PlatboxLib}/DeltaFuzz/README.md (100%) create mode 100644 PlatboxLib/README.md rename {PlatboxClient => PlatboxLib}/inc/UEFIVars.h (61%) rename {PlatboxClient => PlatboxLib}/inc/Util.h (86%) rename {PlatboxClient => PlatboxLib}/inc/amd/amd_chipset.h (94%) create mode 100644 PlatboxLib/inc/amd/amd_spi.h rename {PlatboxClient => PlatboxLib}/inc/common_chipset.h (100%) rename {PlatboxClient => PlatboxLib}/inc/global.h (93%) rename {PlatboxClient => PlatboxLib}/inc/intel/intel_chipset.h (90%) rename {PlatboxClient => PlatboxLib}/inc/linux/__linux.h (100%) rename {PlatboxClient => PlatboxLib}/inc/msr.h (100%) rename {PlatboxClient => PlatboxLib}/inc/pci.h (83%) rename {PlatboxClient => PlatboxLib}/inc/physmem.h (87%) rename {PlatboxClient => PlatboxLib}/inc/smm/smi_fuzz.h (100%) rename {PlatboxClient => PlatboxLib}/inc/smm/smm_communicate.h (99%) rename {PlatboxClient => PlatboxLib}/inc/types.h (100%) rename {PlatboxClient => PlatboxLib}/inc/windows/__win.h (74%) rename {PlatboxClient => PlatboxLib}/src/UEFIVars.cpp (76%) rename {PlatboxClient => PlatboxLib}/src/Util.cpp (82%) rename {PlatboxClient => PlatboxLib}/src/_run_attempt.asm (100%) rename {PlatboxClient => PlatboxLib}/src/amd/amd_chipset.cpp (89%) create mode 100644 PlatboxLib/src/amd/amd_spi.cpp rename {PlatboxClient => PlatboxLib}/src/common_chipset.cpp (68%) create mode 100644 PlatboxLib/src/global.cpp rename {PlatboxClient => PlatboxLib}/src/intel/intel_chipset.cpp (85%) rename {PlatboxClient => PlatboxLib}/src/linux/placeholder (100%) rename {PlatboxClient => PlatboxLib}/src/msr.cpp (100%) rename {PlatboxClient => PlatboxLib}/src/pci.cpp (73%) rename {PlatboxClient => PlatboxLib}/src/physmem.cpp (88%) rename {PlatboxClient => PlatboxLib}/src/smm/smi_fuzz.cpp (98%) rename {PlatboxClient => PlatboxLib}/src/smm/smm_communicate.cpp (98%) rename {PlatboxClient => PlatboxLib}/src/windows/acpidump.cpp (98%) rename {PlatboxClient => PlatboxLib}/src/windows/kernelHookCb.cpp (100%) rename {PlatboxClient => PlatboxLib}/src/windows/page_tables.cpp (100%) create mode 100644 build.bat create mode 100755 build.sh create mode 100644 compiled/Platbox.cer create mode 100644 compiled/Platbox.inf create mode 100644 compiled/Platbox.sys create mode 100755 compiled/example create mode 100644 compiled/example.exe create mode 100755 compiled/platbox_cli create mode 100644 compiled/platbox_cli.exe delete mode 100644 docs/smm_future.txt create mode 100644 pocs/CMakeLists.txt create mode 100644 pocs/README.md create mode 100644 pocs/poc.cpp rename PlatboxClient/inc/PlatboxClient.h => pocs/poc.h (50%) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..03d1701 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.13) + +# Maps to Visual Studio solution file (Tutorial.sln) +# The solution will have all targets (exe, lib, dll) +# as Visual Studio projects (.vcproj) +project (PlatboxClient) + +add_subdirectory(PlatboxLib) +add_subdirectory(PlatboxClient) +add_subdirectory(pocs) \ No newline at end of file diff --git a/PlatboxClient/CMakeLists.txt b/PlatboxClient/CMakeLists.txt index 071b42c..f2b385a 100644 --- a/PlatboxClient/CMakeLists.txt +++ b/PlatboxClient/CMakeLists.txt @@ -5,57 +5,36 @@ cmake_minimum_required(VERSION 3.13) # as Visual Studio projects (.vcproj) project (PlatboxClient) +include_directories ( + "${PROJECT_SOURCE_DIR}/../PlatboxLib/inc" + "${PROJECT_SOURCE_DIR}/../PlatboxLib/inc/smm" + "${PROJECT_SOURCE_DIR}/../PlatboxLib/inc/intel" + "${PROJECT_SOURCE_DIR}/../PlatboxLib/inc/amd" + "${PROJECT_SOURCE_DIR}/../PlatboxLib/DeltaFuzz" +) + +if (WIN32) + include_directories ("${PROJECT_SOURCE_DIR}/../PlatboxLib/inc/windows") +endif (WIN32) -include_directories ("${PROJECT_SOURCE_DIR}/inc" "${PROJECT_SOURCE_DIR}/inc/smm" "${PROJECT_SOURCE_DIR}/inc/windows" "${PROJECT_SOURCE_DIR}/inc/linux" "${PROJECT_SOURCE_DIR}/inc/intel" "${PROJECT_SOURCE_DIR}/inc/amd" "${PROJECT_SOURCE_DIR}/DeltaFuzz") +if (UNIX) + include_directories ( + "${PROJECT_SOURCE_DIR}/../PlatboxLib/inc/linux" + "${PROJECT_SOURCE_DIR}/../PlatboxDrv/linux/include" + ) +endif (UNIX) SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + set (PROJECT_SOURCES - src/msr.cpp - src/pci.cpp - src/physmem.cpp - src/PlatboxClient.cpp - src/UEFIVars.cpp - src/global.cpp - src/Util.cpp - src/_run_attempt.asm - src/common_chipset.cpp - - src/windows/kernelHookCb.cpp - src/windows/page_tables.cpp - src/windows/acpidump.cpp - - src/intel/intel_chipset.cpp - - src/amd/amd_chipset.cpp - - src/smm/smm_communicate.cpp - src/smm/smi_fuzz.cpp - + PlatboxClient.cpp ) -add_subdirectory (DeltaFuzz) - - -set_target_properties(DeltaFuzzLib PROPERTIES LINKER_LANGUAGE C++) - # main executable add_executable(platbox_cli "${PROJECT_SOURCES}") - - # link lib -target_link_libraries (platbox_cli DeltaFuzzLib) - - -# Creates a folder "executables" and adds target -# project (app.vcproj) under it -#set_property(TARGET app PROPERTY FOLDER "executables") - -# Properties->General->Output Directory -#set_target_properties(app PROPERTIES - # RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) - -# Adds logic to INSTALL.vcproj to copy app.exe to destination directory -#install (TARGETS app - # RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/_install) \ No newline at end of file +target_link_libraries (platbox_cli platbox_lib) diff --git a/PlatboxClient/DeltaFuzz/DeltaFuzz.h b/PlatboxClient/DeltaFuzz/DeltaFuzz.h deleted file mode 100644 index 1ef4178..0000000 --- a/PlatboxClient/DeltaFuzz/DeltaFuzz.h +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once -#ifndef __DeltaFuzz_h__ -#define __DeltaFuzz_h__ - -#include -#include "types.h" - -#ifdef _WIN32 - #include -#endif - -/* Definitions */ - -#define DEFAULT_FUZZ_POSSIBILITY 100 -#define DEFAULT_UNMAP_POSSIBILITY 0 - -/* Structures and Variables */ - -typedef struct _FUZZER_OBJECT { - UINT32 Seed; - double FuzzPossibility; - double UnmapPossibility; - UINT64 Iterations; - BOOL FuzzGenerate; - BOOL FuzzMutate; - int(*get_random)(void *fuzzer); - void(*fuzz_blob)(void *fuzzer, UCHAR *blob, UINT32 size); - unsigned int(*get_fuzzy_len)(void *fuzzer, unsigned int max); - int (*gen_int)(void *fuzzer, unsigned long long *qp); -} FUZZER_OBJECT, *PFUZZER_OBJECT; - - -int wrapper_rand(FUZZER_OBJECT *fuzzer); -void _swapValues_UINT(UINT32 *a, UINT32 *b); -void _mutateNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); -void _mutateRangeSpecial(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); -void _mutateUnNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); -void _mutateRangeRandom(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); -void _mutateBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); -void _singleBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end); -UINT32 _getRandomRange(FUZZER_OBJECT *fuzzer, UINT32 min, UINT32 max); - -void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, UINT32 seed, BOOL FuzzGenerate, BOOL FuzzMutate); -void DestroyFuzzerObject(FUZZER_OBJECT *fuzzer); - -void FuzzBlob(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size); -unsigned int get_fuzzy_len(FUZZER_OBJECT *fuzzer, unsigned int max); -int genInt(FUZZER_OBJECT *fuzzer, unsigned long long *qp); -unsigned int getOffset(FUZZER_OBJECT *fuzzer, UINT size, UINT SpaceNeeded, BOOLEAN *error); -unsigned char getCharDelta(FUZZER_OBJECT *fuzzer); -unsigned short getWordDelta(FUZZER_OBJECT *fuzzer); -unsigned int getDwordDelta(FUZZER_OBJECT *fuzzer); -unsigned long long getQwordDelta(FUZZER_OBJECT *fuzzer); -unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b); -unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b); -unsigned short mutateWord(FUZZER_OBJECT *fuzzer, unsigned short w); -unsigned int mutateDword(FUZZER_OBJECT *fuzzer, unsigned int dw); -unsigned long long mutateQword(FUZZER_OBJECT *fuzzer, unsigned long long qw); - -#endif - - - diff --git a/PlatboxClient/Makefile b/PlatboxClient/Makefile deleted file mode 100644 index 9f0c851..0000000 --- a/PlatboxClient/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: - make clean - clang -c -static -IDeltaFuzz/*.h -o DeltaFuzz.o DeltaFuzz/*.c -Iinc - llvm-ar rc DeltaFuzz.a DeltaFuzz.o - clang++ -static -O2 -Iinc/ -Iinc/smm/ -Iinc/amd/ -Iinc/intel/ -Iinc/linux -I../Platbox/linux/include/ -IDeltaFuzz/ -o platbox src/*.cpp src/smm/*.cpp src/amd/*.cpp src/intel/*.cpp DeltaFuzz.a - -clean: - rm -f *.o platbox DeltaFuzz.a diff --git a/PlatboxClient/PlatboxClient.cpp b/PlatboxClient/PlatboxClient.cpp new file mode 100644 index 0000000..3a554cb --- /dev/null +++ b/PlatboxClient/PlatboxClient.cpp @@ -0,0 +1,383 @@ +// Written by Enrique Nissim (IOActive) 06/2018 + +#include "PlatboxClient.h" + +#pragma comment(lib, "platbox_lib.lib") + +/* +extern "C" { + void _run_attempt(); +}*/ + +void parse_handle_physmem_operation(int argc, char **argv) { + // physmem r 0x000000 0x100--> reads 0x100 bytes from physical address 0 + if (!strcmp(argv[1], "r")) { + if (argc == 4) { + UINT64 address = strtoull(argv[2], NULL, 16); + UINT32 size = strtoul(argv[3], NULL, 16); + read_physical_memory(address, size, NULL, TRUE); + } + if (argc == 5) { + // physmem r 0xFFAA0000 0x100 weird_region.bin + UINT64 address = strtoull(argv[2], NULL, 16); + UINT32 size = strtoul(argv[3], NULL, 16); + read_physical_memory_into_file(address, size, argv[4]); + } + } + if (!strcmp(argv[1], "wb")) { + if (argc == 4) { + UINT64 address = strtoull(argv[2], NULL, 16); + UINT32 value = strtoul(argv[3], NULL, 16); + write_byte_physical_memory(address, value); + } + } + if (!strcmp(argv[1], "efimap")) { + print_efi_memory_map(); + } +} + + +void parse_handle_map2user_operation(int argc, char **argv) { + // map2user 0x0000000 --> maps the physical page 0 to usermode + // argv[0] = map2user + // argv[1] = 0x000000 + if (argc == 2) { + UINT64 address = strtoull(argv[1], NULL, 16); + DEBUG_MODE = 1; + void *mapped_addr = map_physical_memory(address, PAGE_SIZE); + DEBUG_MODE = 0; + } +} + +void parse_handle_alloc_operation(int argc, char **argv) { + // alloc 0x0000000 --> allocs size + // argv[0] = alloc + // argv[1] = size + if (argc == 2) { + UINT32 size = strtoul(argv[1], NULL, 16); + DEBUG_MODE = 1; + alloc_user_mem(size, NULL); + DEBUG_MODE = 0; + } +} + +void parse_handle_free_memory_operation(int argc, char **argv) { + // alloc 0x0000000 --> allocs size + // argv[0] = alloc + // argv[1] = size + if (argc == 2) { + UINT64 address = strtoull(argv[1], NULL, 16); + DEBUG_MODE = 1; + unmap_physical_memory((void *) address, 0); + DEBUG_MODE = 0; + } +} + + +void parse_handle_mem_dump_operation(int argc, char **argv) { + // dd 0x0000000 0x100 -> dumps the first 0x100 bytes of the vA 0x000 + // argv[0] = dd + // argv[1] = addr + // argv[2] = size + if (argc == 3) { + UINT64 address = strtoull(argv[1], NULL, 16); + UINT64 size = strtoul(argv[2], NULL, 16); + print_memory(address, (char *) address, size); + + } +} + + +void parse_bus_device_function(char *line, UINT *bus, UINT *device, UINT *function) { + char **subargs = parse_arguments(line, ':'); + int subargc = (int)(size_t)subargs[0]; + subargc--; + if (subargc == 3) { + *bus = strtoul(subargs[1], NULL, 10); + *device = strtoul(subargs[2], NULL, 10); + *function = strtoul(subargs[3], NULL, 10); + } + free(subargs); +} + +void parse_handle_pci_operation(int argc, char **argv) { + // pci r 0:2:0 -> reads the configuration space + // pci rb 0:2:0 1 -> reads a byte from offset + // pci rw 0:2:0 1 -> reads a word from offset 1*4 + // pci rd 0:2:0 1 -> reads a dword from offset 1*4 + // pci wb 0:2:0 1 0x90 -> writes a byte to offset 1*4 + // pci ww 0:2:0 1 0x9090 -> writes a word to offset 1*4 + // pci wd 0:2:0 1 0x90909090 -> writes a dword to offset 1*4 + // pci r bar 0:2:0 0x10 -> read BAR info at offset 0x10 + UINT bus, device, function = 0; + UINT offset = 0; + UINT value = 0; + if (!strcmp(argv[1], "r")) { + if (argc == 3) { + parse_bus_device_function(argv[2], &bus, &device, &function); + read_pci_header(bus, device, function); + } + else if (argc == 5 && !strcmp(argv[2], "bar")) { + parse_bus_device_function(argv[3], &bus, &device, &function); + offset = strtoul(argv[4], NULL, 16); + read_pci_bar_info(bus, device, function, offset >> 2); + } + } + else if (!strcmp(argv[1], "rb")) { + if (argc == 4) { + parse_bus_device_function(argv[2], &bus, &device, &function); + offset = strtoul(argv[3], NULL, 16); + enable_debug_mode(); + read_pci_byte(bus, device, function, offset); + restore_debug_mode(); + } + } + else if (!strcmp(argv[1], "rw")) { + if (argc == 4) { + parse_bus_device_function(argv[2], &bus, &device, &function); + offset = strtoul(argv[3], NULL, 16); + enable_debug_mode(); + read_pci_word(bus, device, function, offset); + restore_debug_mode(); + } + } + else if (!strcmp(argv[1], "rd")) { + if (argc == 4) { + parse_bus_device_function(argv[2], &bus, &device, &function); + offset = strtoul(argv[3], NULL, 16); + enable_debug_mode(); + read_pci_dword(bus, device, function, offset); + restore_debug_mode(); + } + } + else if (!strcmp(argv[1], "wb")) { + if (argc == 5) { + parse_bus_device_function(argv[2], &bus, &device, &function); + offset = strtoul(argv[3], NULL, 16); + value = strtoul(argv[4], NULL, 16); + enable_debug_mode(); + write_pci_byte(bus, device, function, offset, value); + restore_debug_mode(); + } + } + else if (!strcmp(argv[1], "ww")) { + if (argc == 5) { + parse_bus_device_function(argv[2], &bus, &device, &function); + offset = strtoul(argv[3], NULL, 16); + value = strtoul(argv[4], NULL, 16); + enable_debug_mode(); + write_pci_word(bus, device, function, offset, value); + restore_debug_mode(); + } + } + else if (!strcmp(argv[1], "wd")) { + if (argc == 5) { + parse_bus_device_function(argv[2], &bus, &device, &function); + offset = strtoul(argv[3], NULL, 16); + value = strtoul(argv[4], NULL, 16); + enable_debug_mode(); + write_pci_dword(bus, device, function, offset, value); + restore_debug_mode(); + } + } +} + + +void show_cli_help() { + printf("CLI Commands:\n"); + printf("debug -> toogles DEBUG_MODE\n"); + printf("pci r 0:2:0 -> reads the configuration space\n"); + printf("pci r bar 0:2:0 0x10 -> read BAR info at offset 0x10\n"); + printf("pci rb 0:2:0 0 -> reads a byte from offset 0\n"); + printf("pci rw 0:2:0 4 -> reads a word from offset 4\n"); + printf("pci rd 0:2:0 4 -> reads a dword from offset 4\n"); + printf("pci wb 0:2:0 4 0x90 -> writes a byte to offset 4\n"); + printf("pci ww 0:2:0 4 0x9090 -> writes a word to offset 4\n"); + printf("pci wd 0:2:0 0xC 0x90909090 -> writes a dword to offset C\n"); + printf("physmem r 0x00000000 0x100 -> reads 0x100 bytes from physical address 0\n"); + printf("physmem r 0x00000000 0x100 file.bin -> reads 0x100 bytes from physical address 0 into file.bin\n"); + printf("physmem efimap -> prints the EFI memory map\n"); + printf("map2user 0x00000000 -> maps the physical address 0 and returns a virtual address to usermode\n"); + printf("alloc 0x100 -> allocates 0x100 bytes in kernel memory and maps it to usermode\n"); + printf("free 0xFEA000 -> frees that memory (if it was mapped by PlatboxDrv)\n"); + printf("dd 0xFEA0000 0x100 -> dumps the first 0x100 bytes of the memory address\n"); + printf("rdmsr 0x1F2 -> reads MSR 0x1F2\n"); + printf("wrmsr 0x1F2 0xA000 -> Writes 0xA0000 into MSR 0x1F2\n"); + printf("uefivars -> dump UEFI variables -> requires admin privileges\n"); + printf("fuzzsmi 0x44 -> fuzz SW SMI number 0x44\n"); + printf("fuzzsmi -> fuzz ALL SW SMI\n"); + printf("chipset -> throws information about several platform configuration registers\n"); + printf("dump_spi -> dumps the SPI Flash content into or 'spi_flash.bin'\n"); + printf("s3bootscript -> dumps the S3 bootscript into or 's3_bootscript.bin'\n"); + printf("s3bootscript \n"); + + #ifdef _WIN32 + printf("kernelhook patch ffff89868ba1ce30 -> creates a -breakpoint-hook into the ffff89868ba1ce30 callback\n"); + printf("kernelhook patch ffff89868ba1ce30 909090C3 -> creates a NOP NOP NOP RET hook into the ffff89868ba1ce30 callback\n"); + printf("kernelhook restores ffff89868ba1ce30 -> restores the original callback for ffff89868ba1ce30\n"); + printf("kernelhook remove -> deletes all hooks\n"); + #endif + printf("--\n"); +} + + + + +char command_line[512]; +void run_cli() { + + InitializeDeltaFuzz(); + open_platbox_device(); + + init_os_specifics(); + + char **args; + BOOL exit = FALSE; + while (exit != TRUE) { + printf(">>> "); + fflush(stdout); + get_user_input(command_line, sizeof(command_line)); + + if (strlen(command_line) == 0) { + continue; + } + args = parse_arguments(command_line, ' '); + int _argc = (int)(size_t)args[0]; + _argc--; + char **_argv = &args[1]; + + if (!strcmp(_argv[0], "debug")) { + DEBUG_MODE = DEBUG_MODE ^ 1; + if (DEBUG_MODE) { + printf("-> Debug: enabled\n"); + } else { + printf("-> Debug: disabled\n"); + } + } + else if (!strcmp(_argv[0], "pci")) { + parse_handle_pci_operation(_argc, _argv); + } + else if (!strcmp(_argv[0], "physmem")) { + parse_handle_physmem_operation(_argc, _argv); + } + else if (!strcmp(_argv[0], "map2user")) { + parse_handle_map2user_operation(_argc, _argv); + } + else if (!strcmp(_argv[0], "alloc")) { + parse_handle_alloc_operation(_argc, _argv); + } + else if (!strcmp(_argv[0], "free")) { + parse_handle_free_memory_operation(_argc, _argv); + } + else if (!strcmp(_argv[0], "dd")) { + parse_handle_mem_dump_operation(_argc, _argv); + } + else if (!strcmp(_argv[0], "rdmsr")) { + read_msr(_argc, _argv); + } + else if (!strcmp(_argv[0], "wrmsr")) { + write_msr(_argc, _argv); + } + else if (!strcmp(_argv[0], "fuzzsmi")) { + if (_argc > 1) { + fuzz_smi_number(strtoul(_argv[1], NULL, 16)); + } + else { // fuzzsmi + fuzz_all_smi(); + } + } + else if (!strcmp(_argv[0], "chipset")) { + get_chipset_information(); + } + else if (!strcmp(_argv[0], "dump_spi")) { + if (_argc > 1) { + dump_spi_flash(_argv[1]); + } else { + dump_spi_flash("spi_flash.bin"); + } + } + + else if (!strcmp(_argv[0], "s3bootscript")) { + if (_argc == 1) { + smm_dump_s3_bootscript("s3_bootscript.bin"); + } else if (_argc == 2) { + smm_dump_s3_bootscript(_argv[1]); + } else if (_argc > 2) { + UINT64 rt_start = strtoull(_argv[1], NULL, 16); + UINT64 rt_end = strtoull(_argv[2], NULL, 16); + if (_argc > 3) { + smm_dump_s3_bootscript_manual(rt_start, rt_end, _argv[1]); + } else { + smm_dump_s3_bootscript_manual(rt_start, rt_end, "s3_bootscript.bin"); + } + } + } + #ifdef _WIN32 + + else if (!strcmp(_argv[0], "uefivars")) { + list_uefi_variables(); + } + + + else if (!strcmp(_argv[0], "kernelhook")) { + if (_argc > 1) { + parse_kernel_hook_operation(_argc, _argv); + } + } + + #endif + + else if (!strcmp(_argv[0], "?") || !strcmp(_argv[0], "help")) { + show_cli_help(); + } + else if (!strcmp(_argv[0], "exit")) { + exit = TRUE; + } + free(args); + } + + close_platbox_device(); +} + + + +void show_usage(char *exename) { + printf("> %s install -> installs the platbox driver (requires privileges)\n", exename); + printf("> %s start -> starts the platbox driver (requires privileges)\n", exename); + printf("> %s cli -> runs the CLI\n", exename); + printf("> %s stop -> stops (unloads) the platbox driver\n", exename); + printf("> %s remove -> removes the platbox driver\n", exename); + printf("--\n"); +} + + +int main(int argc, char **argv) +{ + + if (argc < 2) { + show_usage(argv[0]); + exit(-1); + } + if (!strcmp(argv[1], "cli")) { + run_cli(); + } + if (!strcmp(argv[1], "install")) { + if (argc == 3) { + install_driver(argv[2]); + } else{ + install_driver(NULL); + } + } + if (!strcmp(argv[1], "start")) { + start_service(); + } + if (!strcmp(argv[1], "stop")) { + stop_service(); + } + if (!strcmp(argv[1], "remove")) { + remove_driver(); + } + + return 0; +} + diff --git a/PlatboxClient/PlatboxClient.h b/PlatboxClient/PlatboxClient.h new file mode 100644 index 0000000..eb65d4d --- /dev/null +++ b/PlatboxClient/PlatboxClient.h @@ -0,0 +1,28 @@ +// Written by Enrique Nissim (IOActive) 06/2018 + + +#pragma once +#include "global.h" +#include "pci.h" +#include "common_chipset.h" +#include "Util.h" +#include "physmem.h" +#include "msr.h" +#include "smm_communicate.h" +#include "smi_fuzz.h" +#include "UEFIVars.h" + + + +void parse_handle_physmem_operation(int argc, char **argv); +void parse_handle_map2user_operation(int argc, char **argv); +void parse_handle_alloc_operation(int argc, char **argv); +void parse_handle_free_memory_operation(int argc, char **argv); +void parse_handle_mem_dump_operation(int argc, char **argv); + + +void parse_bus_device_function(char *line, UINT *bus, UINT *device, UINT *function); +void parse_handle_pci_operation(int argc, char **argv); + + + diff --git a/PlatboxClient/README.md b/PlatboxClient/README.md index 09dbca3..3cf20d5 100644 --- a/PlatboxClient/README.md +++ b/PlatboxClient/README.md @@ -1,21 +1 @@ -## Compilation Steps - -### Linux - -Just use make - -### Windows - -``` -mkdir build -cd build -cmake -G "Visual Studio 17 2022" -A x64 -S .. -B "build64" -cmake --build build64/ --target platbox_cli -``` - -#### Release Build - -``` -cmake -G "Visual Studio 17 2022" -A x64 -S .. -B "build64" -cmake --build build64/ --target platbox_cli --config Release -``` \ No newline at end of file +- \ No newline at end of file diff --git a/PlatboxClient/build.bat b/PlatboxClient/build.bat deleted file mode 100644 index 476c965..0000000 --- a/PlatboxClient/build.bat +++ /dev/null @@ -1,5 +0,0 @@ -mkdir build -cd build -cmake -G "Visual Studio 16 2019" -A x64 -S .. -B "build64" -cmake --build build64/ --target platbox_cli --config Release -cd .. \ No newline at end of file diff --git a/PlatboxClient/src/PlatboxClient.cpp b/PlatboxClient/src/PlatboxClient.cpp deleted file mode 100644 index 4ce1ba7..0000000 --- a/PlatboxClient/src/PlatboxClient.cpp +++ /dev/null @@ -1,466 +0,0 @@ -// Written by Enrique Nissim (IOActive) 06/2018 - -#include "PlatboxClient.h" -#include "Util.h" - -/* -extern "C" { - void _run_attempt(); -}*/ - - -void InitializeDeltaFuzz() { - CreateFuzzerObject(&g_fuzzer, 0, TRUE, FALSE); -} - - -void open_platbox_device() { - #ifdef __linux__ - char device_name[256]; - memset(device_name, 0x00, sizeof(device_name)); - sprintf(device_name, "/dev/%s0", KERNETIX_DEVICE_NAME); - int fd = open(device_name, O_RDWR); - if (fd < 0) - { - printf("Can't open device file: %s\n", device_name); - exit(-1); - } - printf("%s opened successfully: %d\n", device_name, fd); - g_hDevice = fd; - - #else // _WIN32 - HANDLE h = CreateFileW( - L"\\\\.\\PlatboxDev", - FILE_READ_ACCESS | FILE_WRITE_ACCESS, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL - ); - - if (h == NULL || (int)h == -1) { - printf("Error: %08x\n", GetLastError()); - printf("Check Platbox driver is loaded!\n"); - exit(-1); - } - - g_hDevice = h; - - #endif - -} - -void close_platbox_device() { - #ifdef __linux__ - close(g_hDevice); - #else // _WIN32 - CloseHandle(g_hDevice); - #endif -} - - -char _ret_shellcode[] = { - //"\xc3" // ret - "\x53\x56\x57\xFA\x48\x31\xC9\x48\xC7\xC2\x0F\x00\x00\x00\x4D\x31" - "\xC0\x48\x31\xC0\xB0\x01\xC1\xE0\x1F\xC1\xE1\x10\xC1\xE2\x0B\x41" - "\xC1\xE0\x08\x09\xC8\x09\xD0\x44\x09\xC0\x48\x89\xC3\x48\x8B\x7C" - "\x24\x40\xCC\x48\x31\xC9\x48\xF7\xD1\x48\xFF\xC1\x48\x89\xC8\xC1" - "\xE0\x02\x09\xD8\x66\xBA\xF8\x0C\xEF\x48\x31\xC0\x66\xBA\xFC\x0C" - "\xED\x89\x04\x8F\x80\xF9\x40\x75\xE0\xFB\x5F\x5E\x5B\xC3" -}; - -void execute_shellcode() { - DWORD bytesReturned = 0; - - char *shellcode = &_ret_shellcode[0]; - int size = 0x200; - - #ifdef __linux__ - printf("execute_shellcode Unimplemented!"); - #elif _WIN32 - NTSTATUS status; - status = DeviceIoControl(g_hDevice, IOCTL_EXECUTE_SHELLCODE, shellcode, size, NULL, 0, &bytesReturned, NULL); - #else - #endif - -} - - - - -void show_cli_help() { - printf("CLI Commands:\n"); - printf("debug -> toogles DEBUG_MODE\n"); - printf("pci r 0:2:0 -> reads the configuration space\n"); - printf("pci r bar 0:2:0 0x10 -> read BAR info at offset 0x10\n"); - printf("pci rb 0:2:0 0 -> reads a byte from offset 0\n"); - printf("pci rw 0:2:0 4 -> reads a word from offset 4\n"); - printf("pci rd 0:2:0 4 -> reads a dword from offset 4\n"); - printf("pci wb 0:2:0 4 0x90 -> writes a byte to offset 4\n"); - printf("pci ww 0:2:0 4 0x9090 -> writes a word to offset 4\n"); - printf("pci wd 0:2:0 0xC 0x90909090 -> writes a dword to offset C\n"); - printf("physmem r 0x00000000 0x100 -> reads 0x100 bytes from physical address 0\n"); - printf("physmem r 0x00000000 0x100 file.bin -> reads 0x100 bytes from physical address 0 into file.bin\n"); - printf("physmem efimap -> prints the EFI memory map\n"); - printf("map2user 0x00000000 -> maps the physical address 0 and returns a virtual address to usermode\n"); - printf("alloc 0x100 -> allocates 0x100 bytes in kernel memory and maps it to usermode\n"); - printf("free 0xFEA000 -> frees that memory (if it was mapped by PlatboxDrv)\n"); - printf("dd 0xFEA0000 0x100 -> dumps the first 0x100 bytes of the memory address\n"); - printf("rdmsr 0x1F2 -> reads MSR 0x1F2\n"); - printf("wrmsr 0x1F2 0xA000 -> Writes 0xA0000 into MSR 0x1F2\n"); - printf("uefivars -> dump UEFI variables -> requires admin privileges\n"); - printf("fuzzsmi 0x44 -> fuzz SW SMI number 0x44\n"); - printf("fuzzsmi -> fuzz ALL SW SMI\n"); - printf("chipset -> throws information about several platform configuration registers\n"); - printf("dump_spi -> dumps the SPI Flash content into or 'spi_flash.bin'\n"); - printf("s3bootscript -> dumps the S3 bootscript into or 's3_bootscript.bin'\n"); - printf("s3bootscript \n"); - #ifdef _WIN32 - printf("kernelhook patch ffff89868ba1ce30 -> creates a -breakpoint-hook into the ffff89868ba1ce30 callback\n"); - printf("kernelhook patch ffff89868ba1ce30 909090C3 -> creates a NOP NOP NOP RET hook into the ffff89868ba1ce30 callback\n"); - printf("kernelhook restores ffff89868ba1ce30 -> restores the original callback for ffff89868ba1ce30\n"); - printf("kernelhook remove -> deletes all hooks\n"); - #endif - printf("--\n"); -} - - -void init_os_specifics() { - #ifdef _WIN32 - /* Set white foregorund*/ - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - - resolve_nt_functions(); - find_pml4_idx(); - #endif -} - -char command_line[512]; -void run_cli() { - - InitializeDeltaFuzz(); - open_platbox_device(); - - init_os_specifics(); - - char **args; - BOOL exit = FALSE; - while (exit != TRUE) { - printf(">>> "); - fflush(stdout); - get_user_input(command_line, sizeof(command_line)); - - if (strlen(command_line) == 0) { - continue; - } - args = parse_arguments(command_line, ' '); - int _argc = (int)(size_t)args[0]; - _argc--; - char **_argv = &args[1]; - - if (!strcmp(_argv[0], "debug")) { - DEBUG_MODE = DEBUG_MODE ^ 1; - if (DEBUG_MODE) { - printf("-> Debug: enabled\n"); - } else { - printf("-> Debug: disabled\n"); - } - } - else if (!strcmp(_argv[0], "pci")) { - parse_handle_pci_operation(_argc, _argv); - } - else if (!strcmp(_argv[0], "physmem")) { - parse_handle_physmem_operation(_argc, _argv); - } - else if (!strcmp(_argv[0], "map2user")) { - parse_handle_map2user_operation(_argc, _argv); - } - else if (!strcmp(_argv[0], "alloc")) { - parse_handle_alloc_operation(_argc, _argv); - } - else if (!strcmp(_argv[0], "free")) { - parse_handle_free_memory_operation(_argc, _argv); - } - else if (!strcmp(_argv[0], "dd")) { - parse_handle_mem_dump_operation(_argc, _argv); - } - else if (!strcmp(_argv[0], "rdmsr")) { - read_msr(_argc, _argv); - } - else if (!strcmp(_argv[0], "wrmsr")) { - write_msr(_argc, _argv); - } - else if (!strcmp(_argv[0], "fuzzsmi")) { - if (_argc > 1) { - fuzz_smi_number(strtoul(_argv[1], NULL, 16)); - } - else { // fuzzsmi - fuzz_all_smi(); - } - } - else if (!strcmp(_argv[0], "chipset")) { - get_chipset_information(); - } - else if (!strcmp(_argv[0], "dump_spi")) { - if (_argc > 1) { - dump_spi_flash(_argv[1]); - } else { - dump_spi_flash("spi_flash.bin"); - } - } - - else if (!strcmp(_argv[0], "s3bootscript")) { - if (_argc == 1) { - smm_dump_s3_bootscript("s3_bootscript.bin"); - } else if (_argc == 2) { - smm_dump_s3_bootscript(_argv[1]); - } else if (_argc > 2) { - UINT64 rt_start = strtoull(_argv[1], NULL, 16); - UINT64 rt_end = strtoull(_argv[2], NULL, 16); - if (_argc > 3) { - smm_dump_s3_bootscript_manual(rt_start, rt_end, _argv[1]); - } else { - smm_dump_s3_bootscript_manual(rt_start, rt_end, "s3_bootscript.bin"); - } - } - } - - else if (!strcmp(_argv[0], "uefivars")) { - list_uefi_variables(); - } - - #ifdef _WIN32 - else if (!strcmp(_argv[0], "kernelhook")) { - if (_argc > 1) { - parse_kernel_hook_operation(_argc, _argv); - } - } - #endif - - else if (!strcmp(_argv[0], "?") || !strcmp(_argv[0], "help")) { - show_cli_help(); - } - else if (!strcmp(_argv[0], "exit")) { - exit = TRUE; - } - free(args); - } - - close_platbox_device(); -} - - -void start_service() { - #ifdef __linux__ - printf("start_service Unimplemented!"); - exit(-1); - - #else // _WIN32 - SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); - - if (!hSCM) { - printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); - return; - } - - SC_HANDLE hSvc = OpenServiceA(hSCM, SVC_NAME, SERVICE_START | DELETE | SERVICE_STOP); - - if (hSvc == NULL) { - printf("-> could not open service %s - error: %08x\n", SVC_NAME, GetLastError()); - } - else { - if (StartService(hSvc, 0, NULL)) { - printf("-> service started successfully!\n"); - } - else { - DWORD error = GetLastError(); - if (error == ERROR_SERVICE_ALREADY_RUNNING) { - printf("-> service has already been started!\n"); - } - else { - printf("-> could not start service %s - error: %08x\n", SVC_NAME, error); - } - } - - CloseServiceHandle(hSCM); - } - - CloseServiceHandle(hSCM); - #endif -} - -char service_exe[512]; -void install_driver(char *driverNameArg) { - memset(service_exe, 0x00, sizeof(service_exe)); - - #ifdef __linux__ - printf("install_driver Unimplemented!"); - exit(-1); - - #else // _WIN32 - - char driverName[128] = "\\Platbox.sys"; - - char *pServiceExe = &service_exe[0]; - - if (driverNameArg != NULL) { - pServiceExe = driverNameArg; - } else { - GetCurrentDirectoryA(sizeof(service_exe), pServiceExe); - strcat(pServiceExe, driverName); - } - - printf("-> About to install the service: %s\n", pServiceExe); - - - SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); - - if (!hSCM) { - printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); - return; - } - - - SC_HANDLE hSvc = CreateServiceA( - hSCM, - SVC_NAME, - SVC_NAME, - SERVICE_START | DELETE | SERVICE_STOP, - SERVICE_KERNEL_DRIVER, - SERVICE_DEMAND_START, - SERVICE_ERROR_IGNORE, - pServiceExe, - NULL, - NULL, - NULL, - NULL, - NULL - ); - - - if (hSvc == NULL) { - DWORD error_code = GetLastError(); - if (error_code == ERROR_SERVICE_EXISTS) { - start_service(); - } - else { - printf("-> error creating the service - error: %08x\n", error_code); - } - } - else { - SERVICE_STATUS status; - if (QueryServiceStatus(hSvc, &status)) { - if (status.dwCurrentState == SERVICE_RUNNING) { - printf("-> %s service created and started successfully!\n", SVC_NAME); - } - } - CloseServiceHandle(hSvc); - } - - CloseServiceHandle(hSCM); - - - #endif -} - -void stop_service() { - #ifdef __linux__ - printf("stop_service Unimplemented!"); - exit(-1); - - #else // _WIN32 - SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); - - if (!hSCM) { - printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); - return; - } - - SC_HANDLE hSvc = OpenServiceA(hSCM, SVC_NAME, SERVICE_ALL_ACCESS); - SERVICE_STATUS status; - if (ControlService(hSvc, SERVICE_CONTROL_STOP, &status)) { - printf("-> service stopped successfully!\n"); - } - else { - printf("-> error stopping service: %08x\n", GetLastError()); - } - - CloseServiceHandle(hSvc); - CloseServiceHandle(hSCM); - - #endif -} - -void remove_driver() { - #ifdef __linux__ - printf("remove_driver Unimplemented!"); - exit(-1); - - #else // _WIN32 - SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); - - if (!hSCM) { - printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); - return; - } - - SC_HANDLE hSvc = OpenServiceA(hSCM, SVC_NAME, SERVICE_START | DELETE | SERVICE_STOP); - - if (hSvc == NULL) { - printf("-> service can't be opened - error: %08x\n", GetLastError()); - } - else { - if (DeleteService(hSvc)) { - printf("-> %s service was removed successfully\n", SVC_NAME); - } - else { - printf("-> service can't be removed - error: %08x\n", GetLastError()); - } - CloseServiceHandle(hSvc); - } - CloseServiceHandle(hSCM); - - #endif -} - -void show_usage(char *exename) { - printf("> %s install -> installs the platbox driver (requires privileges)\n", exename); - printf("> %s start -> starts the platbox driver (requires privileges)\n", exename); - printf("> %s cli -> runs the CLI\n", exename); - printf("> %s stop -> stops (unloads) the platbox driver\n", exename); - printf("> %s remove -> removes the platbox driver\n", exename); - printf("--\n"); -} - -int main(int argc, char **argv) -{ - - if (argc < 2) { - show_usage(argv[0]); - exit(-1); - } - if (!strcmp(argv[1], "cli")) { - run_cli(); - } - if (!strcmp(argv[1], "install")) { - if (argc == 3) { - install_driver(argv[2]); - } else{ - install_driver(NULL); - } - } - if (!strcmp(argv[1], "start")) { - start_service(); - } - if (!strcmp(argv[1], "stop")) { - stop_service(); - } - if (!strcmp(argv[1], "remove")) { - remove_driver(); - } - - return 0; -} - diff --git a/PlatboxClient/src/global.cpp b/PlatboxClient/src/global.cpp deleted file mode 100644 index d4cec77..0000000 --- a/PlatboxClient/src/global.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "global.h" - -HANDLE g_hDevice = 0; - -int DEBUG_MODE = 0; - -void debug_print(const char *fmt, ...) { - if (DEBUG_MODE) { - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - } -} - -int _prev_debug_mode = 0; -void enable_debug_mode() { - _prev_debug_mode = DEBUG_MODE; - DEBUG_MODE = 1; -} - -void restore_debug_mode() { - DEBUG_MODE = _prev_debug_mode; -} - -char _aux_print_buff[2048]; - -void print_green(const char *fmt, ...) { - #ifdef _WIN32 - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - #else - - memset(_aux_print_buff, 0x00, sizeof(_aux_print_buff)); - snprintf(_aux_print_buff, sizeof(_aux_print_buff), "\x1b[32m%s\x1b[0m", fmt); - - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, _aux_print_buff, ap); - va_end(ap); - - #endif -} - -void print_red(const char *fmt, ...) { - #ifdef _WIN32 - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - SetConsoleTextAttribute(hConsole, FOREGROUND_RED); - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - #else - - memset(_aux_print_buff, 0x00, sizeof(_aux_print_buff)); - snprintf(_aux_print_buff, sizeof(_aux_print_buff), "\x1b[31m%s\x1b[0m", fmt); - - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, _aux_print_buff, ap); - va_end(ap); - - #endif -} - - -#pragma comment(lib, "DeltaFuzzLib.lib") - -FUZZER_OBJECT *g_fuzzer; - - -PCI_ECAM g_pci_ecam; \ No newline at end of file diff --git a/Platbox/linux/driver/Makefile b/PlatboxDrv/linux/driver/Makefile similarity index 100% rename from Platbox/linux/driver/Makefile rename to PlatboxDrv/linux/driver/Makefile diff --git a/Platbox/linux/driver/install.sh b/PlatboxDrv/linux/driver/install.sh similarity index 100% rename from Platbox/linux/driver/install.sh rename to PlatboxDrv/linux/driver/install.sh diff --git a/Platbox/linux/driver/kernetix.c b/PlatboxDrv/linux/driver/kernetix.c similarity index 98% rename from Platbox/linux/driver/kernetix.c rename to PlatboxDrv/linux/driver/kernetix.c index 1876148..4f3e3bb 100644 --- a/Platbox/linux/driver/kernetix.c +++ b/PlatboxDrv/linux/driver/kernetix.c @@ -211,7 +211,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | offset); BYTE val = 0; _read_pci_byte(CF8, &val); @@ -235,7 +235,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); WORD val = 0; _read_pci_word(CF8, &val); @@ -259,7 +259,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); DWORD val = 0; _read_pci_dword(CF8, &val); @@ -283,7 +283,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); _write_pci_byte(CF8, pci_call->value); @@ -304,7 +304,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); _write_pci_word(CF8, pci_call->value); @@ -325,7 +325,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); _write_pci_dword(CF8, pci_call->value); @@ -371,7 +371,7 @@ static long int kernetix_ioctl(struct file *file, unsigned int cmd, unsigned lon UINT32 device = pci_call->device; UINT32 function = pci_call->function; UINT32 offset = pci_call->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); UINT64 bar_size = 0; _read_pci_bar_size(CF8, &bar_size); diff --git a/Platbox/linux/driver/low_level_functions.asm b/PlatboxDrv/linux/driver/low_level_functions.asm similarity index 100% rename from Platbox/linux/driver/low_level_functions.asm rename to PlatboxDrv/linux/driver/low_level_functions.asm diff --git a/Platbox/linux/include/kernetix.h b/PlatboxDrv/linux/include/kernetix.h similarity index 99% rename from Platbox/linux/include/kernetix.h rename to PlatboxDrv/linux/include/kernetix.h index 873261b..5b23805 100644 --- a/Platbox/linux/include/kernetix.h +++ b/PlatboxDrv/linux/include/kernetix.h @@ -66,6 +66,7 @@ typedef int NTSTATUS; void _swsmi(short smi_code_data, __u64 rax_value, __u64 rbx_value, __u64 rcx_value, __u64 rdx_value, __u64 rsi_value, __u64 rdi_value); + void _read_pci_compatible_configuration_space(UINT8 Bus, UINT8 Device, UINT8 Function, PVOID pOut); void _read_pci_byte( UINT32 CF8, PVOID pOut); diff --git a/Platbox/windows/Platbox.sln b/PlatboxDrv/windows/Platbox.sln similarity index 100% rename from Platbox/windows/Platbox.sln rename to PlatboxDrv/windows/Platbox.sln diff --git a/Platbox/windows/Platbox/CbHooks.c b/PlatboxDrv/windows/Platbox/CbHooks.c similarity index 100% rename from Platbox/windows/Platbox/CbHooks.c rename to PlatboxDrv/windows/Platbox/CbHooks.c diff --git a/Platbox/windows/Platbox/CbHooks.h b/PlatboxDrv/windows/Platbox/CbHooks.h similarity index 100% rename from Platbox/windows/Platbox/CbHooks.h rename to PlatboxDrv/windows/Platbox/CbHooks.h diff --git a/Platbox/windows/Platbox/Platbox.c b/PlatboxDrv/windows/Platbox/Platbox.c similarity index 98% rename from Platbox/windows/Platbox/Platbox.c rename to PlatboxDrv/windows/Platbox/Platbox.c index 1c90c9c..5b45e81 100644 --- a/Platbox/windows/Platbox/Platbox.c +++ b/PlatboxDrv/windows/Platbox/Platbox.c @@ -336,7 +336,7 @@ NTSTATUS ReadPCIByte(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); memset(Irp->AssociatedIrp.SystemBuffer, 0x00, IrpSp->Parameters.DeviceIoControl.OutputBufferLength); _read_pci_byte(CF8, Irp->AssociatedIrp.SystemBuffer); Irp->IoStatus.Information = 1; @@ -362,7 +362,7 @@ NTSTATUS ReadPCIWord(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); memset(Irp->AssociatedIrp.SystemBuffer, 0x00, IrpSp->Parameters.DeviceIoControl.OutputBufferLength); _read_pci_word(CF8, Irp->AssociatedIrp.SystemBuffer); Irp->IoStatus.Information = 2; @@ -388,7 +388,7 @@ NTSTATUS ReadPCIDword(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); memset(Irp->AssociatedIrp.SystemBuffer, 0x00, IrpSp->Parameters.DeviceIoControl.OutputBufferLength); _read_pci_dword(CF8, Irp->AssociatedIrp.SystemBuffer); Irp->IoStatus.Information = 4; @@ -413,7 +413,7 @@ NTSTATUS WritePCIByte(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); __try { _write_pci_byte(CF8, p->value); Status = STATUS_SUCCESS; @@ -440,7 +440,7 @@ NTSTATUS WritePCIWord(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); __try { _write_pci_word(CF8, p->value); Status = STATUS_SUCCESS; @@ -467,7 +467,7 @@ NTSTATUS WritePCIDword(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); __try { _write_pci_dword(CF8, p->value); Status = STATUS_SUCCESS; @@ -496,7 +496,7 @@ NTSTATUS ReadPCIBarSize(IN PIRP Irp, IN PIO_STACK_LOCATION IrpSp) { UINT32 device = p->device; UINT32 function = p->function; UINT32 offset = p->offset; - UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset << 2)); + UINT32 CF8 = ((1 << 0x1F) | (bus << 0x10) | (device << 0xB) | (function << 0x08) | (offset)); memset(Irp->AssociatedIrp.SystemBuffer, 0x00, IrpSp->Parameters.DeviceIoControl.OutputBufferLength); _read_pci_bar_size(CF8, Irp->AssociatedIrp.SystemBuffer); Irp->IoStatus.Information = sizeof(PVOID); diff --git a/Platbox/windows/Platbox/Platbox.h b/PlatboxDrv/windows/Platbox/Platbox.h similarity index 100% rename from Platbox/windows/Platbox/Platbox.h rename to PlatboxDrv/windows/Platbox/Platbox.h diff --git a/Platbox/windows/Platbox/Platbox.inf b/PlatboxDrv/windows/Platbox/Platbox.inf similarity index 100% rename from Platbox/windows/Platbox/Platbox.inf rename to PlatboxDrv/windows/Platbox/Platbox.inf diff --git a/Platbox/windows/Platbox/Platbox.vcxproj b/PlatboxDrv/windows/Platbox/Platbox.vcxproj similarity index 98% rename from Platbox/windows/Platbox/Platbox.vcxproj rename to PlatboxDrv/windows/Platbox/Platbox.vcxproj index 7da1f32..4550f06 100644 --- a/Platbox/windows/Platbox/Platbox.vcxproj +++ b/PlatboxDrv/windows/Platbox/Platbox.vcxproj @@ -42,7 +42,7 @@ Debug Win32 Platbox - 10.0.18362.0 + 10.0.19041.0 @@ -145,6 +145,7 @@ false false + MultiThreaded diff --git a/Platbox/windows/Platbox/Platbox.vcxproj.filters b/PlatboxDrv/windows/Platbox/Platbox.vcxproj.filters similarity index 100% rename from Platbox/windows/Platbox/Platbox.vcxproj.filters rename to PlatboxDrv/windows/Platbox/Platbox.vcxproj.filters diff --git a/Platbox/windows/Platbox/low_level_functions.asm b/PlatboxDrv/windows/Platbox/low_level_functions.asm similarity index 100% rename from Platbox/windows/Platbox/low_level_functions.asm rename to PlatboxDrv/windows/Platbox/low_level_functions.asm diff --git a/PlatboxDrv/windows/Platbox/x86Bios.c b/PlatboxDrv/windows/Platbox/x86Bios.c new file mode 100644 index 0000000..9c93eeb --- /dev/null +++ b/PlatboxDrv/windows/Platbox/x86Bios.c @@ -0,0 +1,16 @@ +#include "x86Bios.h" + +NTSTATUS Init(VOID) +{ + /* Get "real mode" memory for an E820_DESCRIPTOR. */ + + ULONG cb = sizeof(E820_DESCRIPTOR); + NTSTATUS status = x86BiosAllocateBuffer(&cb, &m_Segment, &m_Offset); + if (NOT NT_SUCCESS(status)) return status; + + /* Initialisation isn't necessary, but has the merit that we can + check that the buffer is usable. */ + + E820_DESCRIPTOR desc = { 0 }; + return x86BiosWriteMemory(m_Segment, m_Offset, &desc, sizeof(desc)); +}; \ No newline at end of file diff --git a/PlatboxDrv/windows/Platbox/x86Bios.h b/PlatboxDrv/windows/Platbox/x86Bios.h new file mode 100644 index 0000000..271fe7b --- /dev/null +++ b/PlatboxDrv/windows/Platbox/x86Bios.h @@ -0,0 +1,42 @@ +#pragma once +#include + +typedef struct _X86BIOS_REGISTERS // invented names +{ + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + USHORT SegDs; + USHORT SegEs; +} X86BIOS_REGISTERS, * PX86BIOS_REGISTERS; + +/* Undocumented imports from the HAL */ +NTHALAPI BOOLEAN x86BiosCall(ULONG, PX86BIOS_REGISTERS); +NTHALAPI NTSTATUS x86BiosAllocateBuffer(ULONG*, USHORT*, USHORT*); +NTHALAPI NTSTATUS x86BiosFreeBuffer(USHORT, USHORT); +NTHALAPI NTSTATUS x86BiosReadMemory(USHORT, USHORT, PVOID, ULONG); +NTHALAPI NTSTATUS x86BiosWriteMemory(USHORT, USHORT, PVOID, ULONG); + + +#pragma pack (push, 8) /* in case driver and application + get compiled differently */ +typedef struct _E820_DESCRIPTOR { + LARGE_INTEGER Base; + LARGE_INTEGER Size; + ULONG Type; + ULONG ExtAttr; // not actually used by WINLOAD +} E820_DESCRIPTOR, * PE820_DESCRIPTOR; + +typedef struct _E820_MAP { + ULONG Count; + E820_DESCRIPTOR Descriptors[1]; +} E820_MAP, * PE820_MAP; + +#pragma pack (pop) + +NTSTATUS GetMap(PE820_MAP*, ULONG*); +VOID ReleaseMap(PE820_MAP); diff --git a/PlatboxLib/CMakeLists.txt b/PlatboxLib/CMakeLists.txt new file mode 100644 index 0000000..53f3828 --- /dev/null +++ b/PlatboxLib/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.13) + +# Maps to Visual Studio solution file (Tutorial.sln) +# The solution will have all targets (exe, lib, dll) +# as Visual Studio projects (.vcproj) +project (PlatboxLib) + + +include_directories ( + "${PROJECT_SOURCE_DIR}/inc" + "${PROJECT_SOURCE_DIR}/inc/smm" + "${PROJECT_SOURCE_DIR}/inc/intel" + "${PROJECT_SOURCE_DIR}/inc/amd" + "${PROJECT_SOURCE_DIR}/DeltaFuzz" +) + +if (WIN32) + include_directories ("${PROJECT_SOURCE_DIR}/inc/windows") + set (PROJECT_SOURCES + src/msr.cpp + src/pci.cpp + src/physmem.cpp + src/UEFIVars.cpp + src/global.cpp + src/Util.cpp + src/_run_attempt.asm + src/common_chipset.cpp + + src/windows/kernelHookCb.cpp + src/windows/page_tables.cpp + src/windows/acpidump.cpp + + src/intel/intel_chipset.cpp + + src/amd/amd_chipset.cpp + src/amd/amd_spi.cpp + + src/smm/smm_communicate.cpp + src/smm/smi_fuzz.cpp + ) +endif (WIN32) + +if (UNIX) + include_directories ( + "${PROJECT_SOURCE_DIR}/inc/linux" + "${PROJECT_SOURCE_DIR}/../PlatboxDrv/linux/include" + ) + set (PROJECT_SOURCES + src/msr.cpp + src/pci.cpp + src/physmem.cpp + src/UEFIVars.cpp + src/global.cpp + src/Util.cpp + src/_run_attempt.asm + src/common_chipset.cpp + + src/intel/intel_chipset.cpp + + src/amd/amd_chipset.cpp + src/amd/amd_spi.cpp + + src/smm/smm_communicate.cpp + src/smm/smi_fuzz.cpp + ) +endif (UNIX) + +SET (PROJECT_ROOT "${PROJECT_SOURCE_DIR}") + +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") + + +add_subdirectory (DeltaFuzz) + + +set_target_properties(DeltaFuzzLib PROPERTIES LINKER_LANGUAGE CXX) + +# static lib +add_library(platbox_lib STATIC "${PROJECT_SOURCES}") + +# link lib +target_link_libraries (platbox_lib DeltaFuzzLib) diff --git a/PlatboxClient/DeltaFuzz/CMakeLists.txt b/PlatboxLib/DeltaFuzz/CMakeLists.txt similarity index 82% rename from PlatboxClient/DeltaFuzz/CMakeLists.txt rename to PlatboxLib/DeltaFuzz/CMakeLists.txt index 35985c3..2d40c62 100644 --- a/PlatboxClient/DeltaFuzz/CMakeLists.txt +++ b/PlatboxLib/DeltaFuzz/CMakeLists.txt @@ -6,8 +6,6 @@ cmake_minimum_required(VERSION 3.13) project (DeltaFuzzLib) -include_directories (. "${PROJECT_SOURCE_DIR}/../inc") - # static lib add_library(DeltaFuzzLib STATIC "DeltaFuzz.c") diff --git a/PlatboxClient/DeltaFuzz/DeltaFuzz.c b/PlatboxLib/DeltaFuzz/DeltaFuzz.c similarity index 81% rename from PlatboxClient/DeltaFuzz/DeltaFuzz.c rename to PlatboxLib/DeltaFuzz/DeltaFuzz.c index a951222..5162fc8 100644 --- a/PlatboxClient/DeltaFuzz/DeltaFuzz.c +++ b/PlatboxLib/DeltaFuzz/DeltaFuzz.c @@ -1,6 +1,5 @@ #include "DeltaFuzz.h" - uint64_t g_state = 0x8644d6eb17b7ab1a; uint64_t g_iter = 0; @@ -14,15 +13,15 @@ uint64_t xrand() { -UCHAR special_values[] = { '<','>', '?', '>', ')', '(', '*', '&', '^', '%', '$', '#', '@', '/', '-', '+', '?', '~', '`', '|', '\\' }; +unsigned char special_values[] = { '<','>', '?', '>', ')', '(', '*', '&', '^', '%', '$', '#', '@', '/', '-', '+', '?', '~', '`', '|', '\\' }; unsigned char chars[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0x3d, 0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xfe, 0xff }; unsigned short shorts[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xff, 0x100, 0x101, 0x3fff, 0x4000, 0x4001, 0x7fff, 0x8000, 0x8001, 0xffff }; unsigned int ints[] = { 0,1,2,3,4,5,6,7,8,9,10,11,0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xff, 0x100, 0x101, 0x3fff, 0x4000, 0x4001, 0x7fff, 0x8000, 0x8001, 0xffff, 0x10000, 0x10001, 0x3fffffff, 0x40000000, 0x40000001, 0x7fffffff, 0x80000000, 0x80000001, 0xffffffff }; unsigned long long qwords[] = { 0,1,2,3,4,5,6,7,8,9,10,11,0x3f, 0x40, 0x41, 0x7f, 0x80, 0x81, 0xff, 0x100, 0x101, 0x3fff, 0x4000, 0x4001, 0x7fff, 0x8000, 0x8001, 0xffff, 0x10000, 0x10001, 0x3fffffff, 0x40000000, 0x40000001, 0x7fffffff, 0x80000000, 0x80000001, 0xffffffff, 0x100000000, 0x100000001, 0x3fffffffffffffff, 0x4000000000000000, 0x4000000000000001, 0x7fffffffffffffff, 0x8000000000000000, 0x8000000000000001, 0xffffffffffffffff }; -UINT32 tsc_aux = 0; +unsigned int tsc_aux = 0; -void(*fpMutatorsArray[6])(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) = { +void(*fpMutatorsArray[6])(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) = { &_mutateNullRange, &_mutateUnNullRange, &_mutateRangeSpecial, @@ -38,7 +37,7 @@ int wrapper_rand(FUZZER_OBJECT *fuzzer) { return xrand(); } -void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, UINT32 seed, BOOL FuzzGenerate, BOOL FuzzMutate) { +void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, unsigned int seed, int FuzzGenerate, int FuzzMutate) { *fuzzer = (PFUZZER_OBJECT)calloc(1, sizeof(FUZZER_OBJECT)); #ifdef __linux__ @@ -62,10 +61,10 @@ void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, UINT32 seed, BOOL FuzzGenerate, (*fuzzer)->Iterations = 0; (*fuzzer)->FuzzGenerate = FuzzGenerate; (*fuzzer)->FuzzMutate = FuzzMutate; - (*fuzzer)->get_random = &wrapper_rand; - (*fuzzer)->fuzz_blob = &FuzzBlob; - (*fuzzer)->get_fuzzy_len = &get_fuzzy_len; - (*fuzzer)->gen_int = &genInt; + (*fuzzer)->get_random = (void *)&wrapper_rand; + (*fuzzer)->fuzz_blob = (void *)&FuzzBlob; + (*fuzzer)->get_fuzzy_len = (void *)&get_fuzzy_len; + (*fuzzer)->gen_int = (void *)&genInt; } void DestroyFuzzerObject(FUZZER_OBJECT *fuzzer) { @@ -102,7 +101,7 @@ int genInt(FUZZER_OBJECT *fuzzer, unsigned long long *qp) { return -1; } -unsigned int getOffset(FUZZER_OBJECT *fuzzer, UINT size, UINT SpaceNeeded, BOOLEAN *error) { +unsigned int getOffset(FUZZER_OBJECT *fuzzer, unsigned int size, unsigned int SpaceNeeded, int *error) { if (SpaceNeeded > size || SpaceNeeded == 0) { *error = TRUE; return 0; @@ -304,13 +303,13 @@ unsigned long long mutateQword(FUZZER_OBJECT *fuzzer, unsigned long long qw) { -void FuzzOnce(FUZZER_OBJECT *fuzzer, UCHAR *data, UINT32 size) { +void FuzzOnce(FUZZER_OBJECT *fuzzer, unsigned char *data, unsigned int size) { unsigned char c, *cp; unsigned short w, *wp; unsigned int dw, *dwp; unsigned long long qw, *qwp; unsigned int offset; - BOOLEAN error = FALSE; + int error = 0; /* - known ints (4/10) - random value (1/10) @@ -451,49 +450,49 @@ void FuzzOnce(FUZZER_OBJECT *fuzzer, UCHAR *data, UINT32 size) { return; } -void _mutateNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) +void _mutateNullRange(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) { memset(blob + start, 0, (end - start)); } -void _mutateUnNullRange(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { +void _mutateUnNullRange(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) { int i; for (i = start; i <= end; i++) { if (blob[i] == '\x00') { - blob[i] = (UCHAR)(fuzzer->get_random(fuzzer) % (UCHAR_MAX + 1)); + blob[i] = (unsigned char)(fuzzer->get_random(fuzzer) % (255 + 1)); } } } -void _mutateRangeSpecial(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { +void _mutateRangeSpecial(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) { int i; for (i = start; i <= end; i++) { blob[i] = special_values[fuzzer->get_random(fuzzer) % sizeof(special_values)]; } } -void _mutateRangeRandom(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { +void _mutateRangeRandom(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) { int i; for (i = start; i <= end; i++) { - blob[i] = (UCHAR)(fuzzer->get_random(fuzzer) % (UCHAR_MAX + 1)); + blob[i] = (unsigned char)(fuzzer->get_random(fuzzer) % (255 + 1)); } } -void _singleBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { - UINT32 bit_to_change = fuzzer->get_random(fuzzer) % 8; - UINT32 target_byte = fuzzer->get_random(fuzzer) % (end - start); +void _singleBitFlipping(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) { + unsigned int bit_to_change = fuzzer->get_random(fuzzer) % 8; + unsigned int target_byte = fuzzer->get_random(fuzzer) % (end - start); blob[target_byte] = blob[target_byte] ^ (1 << bit_to_change); } -void _mutateBitFlipping(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 start, UINT32 end) { - UINT32 bits_to_change = _getRandomRange(fuzzer, 0, (end - start) * 8); - UINT32 index; +void _mutateBitFlipping(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end) { + unsigned int bits_to_change = _getRandomRange(fuzzer, 0, (end - start) * 8); + unsigned int index; int i; - UCHAR bit; + unsigned char bit; for (i = 0; i < bits_to_change; i++) { index = fuzzer->get_random(fuzzer) % (end - start); // random index - bit = 1 << (fuzzer->get_random(fuzzer) % CHAR_BIT); // random bit + bit = 1 << (fuzzer->get_random(fuzzer) % 8); // random bit blob[start + index] ^= bit; } } @@ -519,10 +518,10 @@ unsigned int get_fuzzy_len(FUZZER_OBJECT *fuzzer, unsigned int max) { /** FUZZER PRIMITIVES **/ -void _performBlobFuzzing(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { - void(*fpMutator)(FUZZER_OBJECT *, UCHAR *, UINT32, UINT32); - UINT32 start = fuzzer->get_random(fuzzer) % size; - UINT32 end = fuzzer->get_random(fuzzer) % size; +void _performBlobFuzzing(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int size) { + void(*fpMutator)(FUZZER_OBJECT *, unsigned char *, unsigned int, unsigned int); + unsigned int start = fuzzer->get_random(fuzzer) % size; + unsigned int end = fuzzer->get_random(fuzzer) % size; // Cannot be equal while (start == end) { end = fuzzer->get_random(fuzzer) % size; @@ -531,7 +530,7 @@ void _performBlobFuzzing(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { _swapValues_UINT(&start, &end); } - fpMutator = fpMutatorsArray[fuzzer->get_random(fuzzer) % (sizeof(fpMutatorsArray) / sizeof(PVOID))]; + fpMutator = fpMutatorsArray[fuzzer->get_random(fuzzer) % (sizeof(fpMutatorsArray) / sizeof(void *))]; fpMutator(fuzzer, blob, start, end); } @@ -541,7 +540,7 @@ unsigned char fill_values[] = { 0x80, 0x0F, 0xCC, 0x90, 0xFF, 0xFE, 0x41 }; -void generate_content(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { +void generate_content(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int size) { if ((fuzzer->get_random(fuzzer) % 100) < 20) { memset(blob, fill_values[fuzzer->get_random(fuzzer) % sizeof(fill_values)], size); @@ -561,12 +560,12 @@ void generate_content(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { i++; break; case 2: - *(WORD *)(blob + i) = (unsigned short)qw; - i += sizeof(WORD); + *(short *)(blob + i) = (unsigned short)qw; + i += sizeof(short); break; case 4: - *(DWORD *)(blob + i) = (unsigned int)qw; - i += sizeof(DWORD); + *(int *)(blob + i) = (unsigned int)qw; + i += sizeof(int); break; case 8: *(unsigned long long *)(blob + i) = (unsigned long long)qw; @@ -578,7 +577,7 @@ void generate_content(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { } -void FuzzBlob(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { +void FuzzBlob(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int size) { if (size > 0 && blob != NULL) { //if (((int)size) < 0) { // __debugbreak(); @@ -606,26 +605,14 @@ void FuzzBlob(FUZZER_OBJECT *fuzzer, UCHAR *blob, UINT32 size) { } } -/* -BOOL FuzzDeallocateMemory(FUZZER_OBJECT *fuzzer, PVOID allocation, UINT size, BOOL virtualAllocated) { - //Returns TRUE if deallocation is performed, otherwise returns FALSE - if (_shouldUnmap(fuzzer)) - { - if (virtualAllocated) - VirtualFree(allocation, size, MEM_RELEASE); - else { - HeapFree(GetProcessHeap(), 0, allocation); - } - return TRUE; - } - return FALSE; -} -*/ + + + /** FUZZER_OBJECT Functions **/ -BOOL _shouldFuzz(FUZZER_OBJECT *fuzzer) { +int _shouldFuzz(FUZZER_OBJECT *fuzzer) { double chance = fuzzer->get_random(fuzzer) % 100; if (chance < fuzzer->FuzzPossibility) { return TRUE; @@ -633,7 +620,7 @@ BOOL _shouldFuzz(FUZZER_OBJECT *fuzzer) { return FALSE; } -BOOL _shouldUnmap(FUZZER_OBJECT *fuzzer) { +int _shouldUnmap(FUZZER_OBJECT *fuzzer) { double chance = fuzzer->get_random(fuzzer) % 100; if (chance < fuzzer->UnmapPossibility) { return TRUE; @@ -643,19 +630,19 @@ BOOL _shouldUnmap(FUZZER_OBJECT *fuzzer) { -UINT32 _getRandomRange(FUZZER_OBJECT *fuzzer, UINT32 min, UINT32 max) +unsigned int _getRandomRange(FUZZER_OBJECT *fuzzer, unsigned int min, unsigned int max) { - return (UINT32)((fuzzer->get_random(fuzzer) % ((max - min) + 1)) + min); + return (unsigned int)((fuzzer->get_random(fuzzer) % ((max - min) + 1)) + min); } -void _swapValues_UINT(UINT32 *a, UINT32 *b) { +void _swapValues_UINT(unsigned int *a, unsigned int *b) { *a ^= *b; *b ^= *a; *a ^= *b; } /* -int WINAPI DllMain(HINSTANCE hDllHandle, DWORD nReason, LPVOID Reserved) { +int WINAPI DllMain(HINSTANCE hDllHandle, int nReason, LPVOID Reserved) { switch (nReason) { case DLL_PROCESS_ATTACH: @@ -670,4 +657,4 @@ return TRUE; int main(void) { RunTests(); } -*/ \ No newline at end of file +*/ diff --git a/PlatboxLib/DeltaFuzz/DeltaFuzz.h b/PlatboxLib/DeltaFuzz/DeltaFuzz.h new file mode 100644 index 0000000..ed0f663 --- /dev/null +++ b/PlatboxLib/DeltaFuzz/DeltaFuzz.h @@ -0,0 +1,70 @@ +#pragma once +#ifndef __DeltaFuzz_h__ +#define __DeltaFuzz_h__ + +#include +#include +#include +#include + +#ifdef _WIN32 + #include +#endif + +/* Definitions */ + +#define DEFAULT_FUZZ_POSSIBILITY 100 +#define DEFAULT_UNMAP_POSSIBILITY 0 + +#define TRUE 1 +#define FALSE 0 + +/* Structures and Variables */ + +typedef struct _FUZZER_OBJECT { + unsigned int Seed; + double FuzzPossibility; + double UnmapPossibility; + uint64_t Iterations; + int FuzzGenerate; + int FuzzMutate; + int(*get_random)(void *fuzzer); + void(*fuzz_blob)(void *fuzzer, unsigned char *blob, unsigned int size); + unsigned int(*get_fuzzy_len)(void *fuzzer, unsigned int max); + int (*gen_int)(void *fuzzer, unsigned long long *qp); +} FUZZER_OBJECT, *PFUZZER_OBJECT; + + +int wrapper_rand(FUZZER_OBJECT *fuzzer); +void _swapValues_UINT(unsigned int *a, unsigned int *b); +void _mutateNullRange(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end); +void _mutateRangeSpecial(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end); +void _mutateUnNullRange(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end); +void _mutateRangeRandom(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end); +void _mutateBitFlipping(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end); +void _singleBitFlipping(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int start, unsigned int end); +unsigned int _getRandomRange(FUZZER_OBJECT *fuzzer, unsigned int min, unsigned int max); + +void CreateFuzzerObject(FUZZER_OBJECT **fuzzer, unsigned int seed, int FuzzGenerate, int FuzzMutate); +void DestroyFuzzerObject(FUZZER_OBJECT *fuzzer); + +void FuzzBlob(FUZZER_OBJECT *fuzzer, unsigned char *blob, unsigned int size); +unsigned int get_fuzzy_len(FUZZER_OBJECT *fuzzer, unsigned int max); +int genInt(FUZZER_OBJECT *fuzzer, unsigned long long *qp); +unsigned int getOffset(FUZZER_OBJECT *fuzzer, unsigned int size, unsigned int SpaceNeeded, int *error); +unsigned char getCharDelta(FUZZER_OBJECT *fuzzer); +unsigned short getWordDelta(FUZZER_OBJECT *fuzzer); +unsigned int getDwordDelta(FUZZER_OBJECT *fuzzer); +unsigned long long getQwordDelta(FUZZER_OBJECT *fuzzer); +unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b); +unsigned char mutateBit(FUZZER_OBJECT *fuzzer, unsigned char b); +unsigned short mutateWord(FUZZER_OBJECT *fuzzer, unsigned short w); +unsigned int mutateDword(FUZZER_OBJECT *fuzzer, unsigned int dw); +unsigned long long mutateQword(FUZZER_OBJECT *fuzzer, unsigned long long qw); + +int _shouldFuzz(FUZZER_OBJECT *fuzzer); + +#endif + + + diff --git a/PlatboxClient/DeltaFuzz/DeltaFuzzLib.lib b/PlatboxLib/DeltaFuzz/DeltaFuzzLib.lib similarity index 100% rename from PlatboxClient/DeltaFuzz/DeltaFuzzLib.lib rename to PlatboxLib/DeltaFuzz/DeltaFuzzLib.lib diff --git a/PlatboxClient/DeltaFuzz/README.md b/PlatboxLib/DeltaFuzz/README.md similarity index 100% rename from PlatboxClient/DeltaFuzz/README.md rename to PlatboxLib/DeltaFuzz/README.md diff --git a/PlatboxLib/README.md b/PlatboxLib/README.md new file mode 100644 index 0000000..536918b --- /dev/null +++ b/PlatboxLib/README.md @@ -0,0 +1,15 @@ +## PlatboxLib + +This is the usermode component that interacts with the driver and the system to retrieve information and modify settings. + +Exports several modules: + +- PCIe access +- MSRs +- Virtual memory +- Physical memory +- Silicon locks +- Processor capabilities +- SMM configuration +- SMI invocation +- SMI fuzzer \ No newline at end of file diff --git a/PlatboxClient/inc/UEFIVars.h b/PlatboxLib/inc/UEFIVars.h similarity index 61% rename from PlatboxClient/inc/UEFIVars.h rename to PlatboxLib/inc/UEFIVars.h index 09dc992..cbebd1e 100644 --- a/PlatboxClient/inc/UEFIVars.h +++ b/PlatboxLib/inc/UEFIVars.h @@ -5,42 +5,6 @@ #include "types.h" -#define SE_CREATE_TOKEN 2 -#define SE_ASSIGNPRIMARYTOKEN 3 -#define SE_LOCK_MEMORY 4 -#define SE_INCREASE_QUOTA 5 -#define SE_UNSOLICITED_INPUT 6 -#define SE_TCB 7 -#define SE_SECURITY 8 -#define SE_TAKE_OWNERSHIP 9 -#define SE_LOAD_DRIVER 10 -#define SE_SYSTEM_PROFILE 11 -#define SE_SYSTEMTIME 12 -#define SE_PROF_SINGLE_PROCESS 13 -#define SE_INC_BASE_PRIORITY 14 -#define SE_CREATE_PAGEFILE 15 -#define SE_CREATE_PERMANENT 16 -#define SE_BACKUP 17 -#define SE_RESTORE 18 -#define SE_SHUTDOWN 19 -#define SE_DEBUG 20 -#define SE_AUDIT 21 -#define SE_SYSTEM_ENVIRONMENT 22 -#define SE_CHANGE_NOTIFY 23 -#define SE_REMOTE_SHUTDOWN 24 -#define SE_UNDOCK 25 -#define SE_SYNC_AGENT 26 -#define SE_ENABLE_DELEGATION 27 -#define SE_MANAGE_VOLUME 28 -#define SE_IMPERSONATE 29 -#define SE_CREATE_GLOBAL 30 -#define SE_TRUSTED_CREDMAN_ACCESS 31 -#define SE_RELABEL 32 -#define SE_INC_WORKING_SET 33 -#define SE_TIME_ZONE 34 -#define SE_CREATE_SYMBOLIC_LINK 35 - - #ifdef _WIN32 @@ -76,10 +40,9 @@ typedef NTSTATUS(NTAPI * _NtQuerySystemEnvironmentValueEx)(__in PXUNICODE_STRING VariableName, __in LPGUID VendorGuid, __out_bcount_opt(*ValueLength) PVOID Value, __inout PULONG ValueLength, __out_opt PULONG Attributes); typedef NTSTATUS(NTAPI * _NtSetSystemEnvironmentValueEx)(__in PXUNICODE_STRING VariableName, __in LPGUID VendorGuid, __in_bcount_opt(ValueLength) PVOID Value, __in ULONG ValueLength, __in ULONG Attributes); typedef NTSTATUS(NTAPI * _NtEnumerateSystemEnvironmentValuesEx)(__in ULONG InformationClass, __out PVOID Buffer, __inout PULONG BufferLength); - typedef NTSTATUS(WINAPI * _RtlAdjustPrivilege)(IN ULONG Privilege, IN BOOL Enable, IN BOOL CurrentThread, OUT PULONG pPreviousState); - - _NtEnumerateSystemEnvironmentValuesEx NtEnumerateSystemEnvironmentValuesEx; - _RtlAdjustPrivilege RtlAdjustPrivilege; + + extern _NtEnumerateSystemEnvironmentValuesEx NtEnumerateSystemEnvironmentValuesEx; + #define EFI_VARIABLE_NON_VOLATILE 1 #define EFI_VARIABLE_BOOTSERVICE_ACCESS 2 @@ -89,4 +52,10 @@ #define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x20 #define EFI_VARIABLE_APPEND_WRITE 0x40 + + /* UEFI Vars */ + void list_uefi_variables(); + + + #endif \ No newline at end of file diff --git a/PlatboxClient/inc/Util.h b/PlatboxLib/inc/Util.h similarity index 86% rename from PlatboxClient/inc/Util.h rename to PlatboxLib/inc/Util.h index 6e26a72..f4f7cdb 100644 --- a/PlatboxClient/inc/Util.h +++ b/PlatboxLib/inc/Util.h @@ -6,6 +6,10 @@ #include "global.h" // switch for types.h? +#ifdef _WIN32 + #include "__win.h" +#endif + /* Utils */ void print_memory(unsigned long address, char *buffer, unsigned int bytes_to_print); void get_user_input(char *input, int size); @@ -19,5 +23,5 @@ void * memmem (const void *haystack, size_t haystack_len, const void *needle, si void display_guid(GUID *guid); -void to_guid(char *guid_str, GUID *guid_arg); +void to_guid(const char *guid_str, GUID *guid_arg); diff --git a/PlatboxClient/inc/amd/amd_chipset.h b/PlatboxLib/inc/amd/amd_chipset.h similarity index 94% rename from PlatboxClient/inc/amd/amd_chipset.h rename to PlatboxLib/inc/amd/amd_chipset.h index 29492f8..1ef6e48 100644 --- a/PlatboxClient/inc/amd/amd_chipset.h +++ b/PlatboxLib/inc/amd/amd_chipset.h @@ -1,22 +1,20 @@ #pragma once #include "types.h" +#include "amd_spi.h" -void amd_print_hwcr_smmlock(); -void amd_print_smm_base(); -void amd_print_apic_bar(); -void amd_print_smm_tseg_addr(); -void amd_print_smm_tseg_mask(); -void amd_print_mmio_ba(); -void amd_print_smi_on_io_trap_configuration(); -void amd_print_io_trap_control_status(); +void amd_retrieve_chipset_information(); +void amd_print_chipset_information(); +DWORD64 amd_retrieve_smm_base(); +void get_tseg_info(UINT64 *base, UINT32 *size); +void _read_mmio_cfg_base_addr(); +DWORD64 amd_retrieve_smm_tseg_mask(); +DWORD64 amd_retrieve_apic_bar(); +DWORD64 amd_retrieve_hwcr_smmlock(); +DWORD64 amd_retrieve_mmio_ba(); +DWORD amd_retrieve_root_complex_pci_control(); -void amd_get_chipset_information(); void amd_dump_spi_flash(const char *output_filename); - -void _read_mmio_cfg_base_addr(); - -void get_tseg_info(UINT64 *base, UINT32 *size); //////////////////// AMD //////////////// #define AMD_SMI_HANDLER_ENTRY_POINT 0x8000 @@ -105,7 +103,7 @@ enum AMD_MSRS { 39:17 TSegMask[39:17]: TSeg address range mask. IF MSRC001_0015[SmmLock] THEN Read-only ELSE Read-write ENDIF. See MSRC001_0112. 16:15 Reserved. - 14:12 TMTypeDram: TSeg address range memory type. IF MSRC001_0015[SmmLock] THEN Readonly. ELSE Read-write. ENDIF. Specifies the memory type for SMM accesses to the TSeg range that + 14:12 TMTypeDram: TSeg address range memory type. IF MSRC001_0015[SmmLock] THEN Read only. ELSE Read-write. ENDIF. Specifies the memory type for SMM accesses to the TSeg range that are directed to DRAM. See: Table 219 [Valid Values for Memory Type Definition]. 11 Reserved. 10:8 AMTypeDram: ASeg Range Memory Type. IF MSRC001_0015[SmmLock] THEN Read-only. @@ -494,7 +492,7 @@ typedef struct _LPC_ISA_Bridge { DWORD AlternativeWideIORangeEnable; // 0x78 - DWORD Reserved0; + DWORD MiscCtlBits; // MISC_CTL_BITS // 0x7C BYTE TPM; @@ -535,60 +533,20 @@ typedef struct _LPC_ISA_Bridge { } LPC_ISA_Bridge; - -typedef struct _ALT_SPI_CS { - BYTE AltSpiCsEn : 2; - BYTE WriteBufferEn : 1; - BYTE SpiProtectEn0 : 1; - BYTE SpiProtectEn1 : 1; - BYTE SpiProtectLock : 1; - BYTE Reserved : 1; - BYTE SpiCsDlySel : 1; -} ALT_SPI_CS; - -typedef struct _SPI { - // 0x00 - DWORD SPI_Cntrl0; - - // 0x04 - DWORD SPI_RestrictedCmd; - - // 0x08 - DWORD SPI_RestrictedCmd2; - - // 0x0C - DWORD SPI_Cntrl1; - - // 0x10 - DWORD SPI_CmdValue0; - - // 0x14 - DWORD SPI_CmdValue1; - - // 0x18 - DWORD SPI_CmdValue2; - - // 0x1C - BYTE Reserved0; - - // 0x1D - BYTE Alt_SPI_CS; - - // 0x1E - BYTE SpiExtRegIndx; - - // 0x1F; confusing definition in spec - BYTE SpiExtRegData; - - // 0x20 - BYTE SPI100Enable; - - // 0x22 - WORD SPI100SpeedConfig; - - // XXX To be extended if necessary - -} SPI; +typedef struct _MISC_CTL_BITS { + DWORD NoHog : 1; + DWORD Reserved1 : 1; + DWORD LDRQ0 : 1; + DWORD Reserved2 : 1; + DWORD SmmWriteRomEn : 1; + DWORD GateSpiAccessDis : 1; + DWORD GateWrongRx : 1; + DWORD AllowHostInDma : 1; + DWORD Reserved3 : 1; + DWORD LDRQ0_PU_EN : 1; + DWORD LDRQ0_PD_EN : 1; + DWORD Reserved4 : 21; +} MISC_CTL_BITS; #define ROOT_COMPLEX_PCI_CONTROL_OFFSET 0x4C @@ -628,3 +586,11 @@ typedef struct _SPI { #define D18F2_MEMORY_CONTROLLER_CONFIGURATION_LOW_OFFSET 0x118 + +/// Expose these to other modules + +extern LPC_ISA_Bridge g_lpc_isa_bridge_registers; +extern DWORD64 g_MmioCfgBaseAddr; + + +void write_rom_protect0(); \ No newline at end of file diff --git a/PlatboxLib/inc/amd/amd_spi.h b/PlatboxLib/inc/amd/amd_spi.h new file mode 100644 index 0000000..31d9699 --- /dev/null +++ b/PlatboxLib/inc/amd/amd_spi.h @@ -0,0 +1,203 @@ + +#pragma once +#include "types.h" + +typedef struct _ALT_SPI_CS { + BYTE AltSpiCsEn : 2; + BYTE WriteBufferEn : 1; + BYTE SpiProtectEn0 : 1; + BYTE SpiProtectEn1 : 1; + BYTE SpiProtectLock : 1; + BYTE lock_spi_cs : 1; // New 2022 + BYTE SpiCsDlySel : 1; +} ALT_SPI_CS; + +#define SPI_INDEX_MODE_READ_BLOCK_BITS 6 +#define SPI_INDEX_MODE_READ_BLOCK_SIZE 64 +#define SPI_INDEX_MODE_READ_BLOCK_MASK 0x3F +#define SPI_INDEX_MODE_WRITE_BLOCK_FIFO 8 + +#define SPI_INDEX_MODE_WRITE_BLOCK_4K 0x1000 +#define SPI_INDEX_MODE_WRITE_BLOCK_BITS 12 +#define SPI_INDEX_MODE_WRITE_BLOCK_MASK 0xFFF + +typedef struct _SPI { + // 0x00 + union { + DWORD SPI_Cntrl0Value; + struct { + BYTE SpiOpCode; + BYTE Rsvd0; + BYTE ExecuteOpcode: 1; + BYTE Rsvd1: 1; + BYTE SpiReadMode_0: 1; + BYTE SpiArbEnable: 1; + BYTE FifoPtrClr: 1; + BYTE IllegalAccess: 1; + BYTE SpiAccessMacRomEn: 1; + BYTE SpiHostAccessMacRomEn: 1; + BYTE ArbWaitCount: 3; + BYTE Rsvd2: 1; + BYTE SpiClkGate: 1; + BYTE SpiReadMode_1: 2; + BYTE SpiBusy: 1; + } SPI_Cntrl0 ; + }; + + // 0x04 + DWORD SPI_RestrictedCmd; + + // 0x08 + DWORD SPI_RestrictedCmd2; + + // 0x0C + union { + DWORD SPI_Cntrl1Value; + struct { + BYTE SpiParamters; + BYTE FifoPtr: 3; + BYTE TrackMacLockEn: 1; + BYTE Rsvd: 4; + BYTE WaitCount: 6; + BYTE Rsvd2: 2; + BYTE ByteCommand; + } SPI_Cntrl1; + }; + + + // 0x10 + DWORD SPI_CmdValue0; + + // 0x14 + DWORD SPI_CmdValue1; + + // 0x18 + DWORD SPI_CmdValue2; + + // 0x1C + BYTE Reserved0; + + // 0x1D + BYTE Alt_SPI_CS; + + // 0x1E + BYTE SpiExtRegIndx; + + // 0x1F; confusing definition in spec + BYTE SpiExtRegData; + + // 0x20 + BYTE SPI100Enable; + + // 0x22 + WORD SPI100SpeedConfig; + + // 0x24 + DWORD Reserved1; + // 0x28 + DWORD Reserved2; + + // 0x2C + WORD SPI100HostPrefetchCfg; + + // 0x2E + WORD Reserved3; + + // 0x30 + DWORD Reserved4[4]; + + // 0x40 + BYTE DDRCmdCode; + // 0x41 + BYTE QDRCmdCode; + // 0x42 + BYTE DPRCmdCode; + // 0x43 + BYTE QPRCmdCode; + // 0x44 + BYTE ModeByte; + // 0x45 + BYTE CmdCode; + // 0x46 + BYTE Reserved5; + // 0x47 + BYTE CmdTrig; + // 0x48 + BYTE TxByteCnt; + // 0x49 - 0x4A + BYTE Reserved6[2]; + // 0x4B + BYTE RxByteCnt; + // 0x4C + union { + DWORD SpiStatusValue; + struct { + BYTE DoneByCount; + BYTE FifoWrPtr: 7; + BYTE Rsvd0: 1; + BYTE FifoRdPtr: 7; + BYTE Rsvd1: 1; + BYTE Rsvd2: 7; + BYTE SpiBusy: 1; + } SpiStatus; + }; + + + // 0x50 + DWORD fla_addr; + BYTE Reserved7[0x2C]; + + // 0x80 + BYTE SPI_regx80; + BYTE SPI_regx81; + BYTE SPI_regx82; + + BYTE FIFO[SPI_INDEX_MODE_READ_BLOCK_SIZE]; // Actually is 67 + + // XXX To be extended if necessary + +} SPI; + +typedef struct _SPIRestrictedCmd { + DWORD RestrictedCmd0 : 8; + DWORD RestrictedCmd1 : 8; + DWORD RestrictedCmd2 : 8; + DWORD RestrictedCmd3 : 8; +} SPIRestrictedCmd; + +typedef struct _SPIRestrictedCmd2 { + DWORD RestrictedCmd4 : 8; + DWORD RestrictedCmdWoAddr0 : 8; + DWORD RestrictedCmdWoAddr1 : 8; + DWORD RestrictedCmdWoAddr2 : 8; +} SPIRestrictedCmd2; + +// todo: retrieve flash region size dynamically +#define FLASH_SIZE 16 * 1024 * 1024 + + +void load_spi_information(DWORD spi_addr); +void print_spi_info(); + +// SPI Controller operations +void amd_spi_clear_fifo_ptr(volatile SPI *spi_base); +void amd_spi_execute_command(volatile SPI *spi_base); +void amd_spi_write_enable(volatile SPI *spi_base); +void amd_spi_print_fifo_stats(volatile SPI *spi_base); +DWORD amd_spi_read_id(); + +void amd_spi_erase_4k_block(volatile SPI *spi_base_arg, UINT32 address); + +void read_from_flash_index_mode(volatile SPI *spi_base_arg, UINT32 start_offset, UINT32 length, BYTE *out_buff); +void amd_dump_spi_flash_index_mode(const char *output_filename); + +void write_4k_block(volatile SPI *spi_base, UINT32 addr, BYTE *block); +void amd_spi_write_buffer(volatile SPI *spi_base_arg, UINT32 flash_address, BYTE *in_buff, UINT32 length); + +// Exposed to other modules +extern DWORD g_spi_addr; +extern SPI g_spi_registers; + + +#define Winbond_25Q128JVS 0xEF6018 +#define Winbond_25Q128JVS_SECTOR_ERASE_OP 0x20 \ No newline at end of file diff --git a/PlatboxClient/inc/common_chipset.h b/PlatboxLib/inc/common_chipset.h similarity index 100% rename from PlatboxClient/inc/common_chipset.h rename to PlatboxLib/inc/common_chipset.h diff --git a/PlatboxClient/inc/global.h b/PlatboxLib/inc/global.h similarity index 93% rename from PlatboxClient/inc/global.h rename to PlatboxLib/inc/global.h index 8f99d08..4f140cf 100644 --- a/PlatboxClient/inc/global.h +++ b/PlatboxLib/inc/global.h @@ -2,6 +2,13 @@ #include #include "types.h" +#ifdef _WIN32 + #include "__win.h" +#elif __linux__ + #include "__linux.h" + #include +#endif + extern "C" { #include "DeltaFuzz.h" } @@ -19,6 +26,19 @@ extern HANDLE g_hDevice; extern FUZZER_OBJECT *g_fuzzer; +#define SVC_NAME "PlatboxSvc" + + +void InitializeDeltaFuzz(); +void open_platbox_device(); +void close_platbox_device(); +void start_service(); +void install_driver(char *driverNameArg); +void stop_service(); +void remove_driver(); +void init_os_specifics(); + + #ifdef __linux__ #include "kernetix.h" #elif _WIN32 @@ -203,4 +223,6 @@ typedef struct _PCI_ECAM { extern PCI_ECAM g_pci_ecam; #define PCI_COMPATIBLE_CONFIG_SPACE_SIZE 256 -//#define PCI_ECAM_SIZE 256 * 1024 * 1024 // 256MB \ No newline at end of file +//#define PCI_ECAM_SIZE 256 * 1024 * 1024 // 256MB + + diff --git a/PlatboxClient/inc/intel/intel_chipset.h b/PlatboxLib/inc/intel/intel_chipset.h similarity index 90% rename from PlatboxClient/inc/intel/intel_chipset.h rename to PlatboxLib/inc/intel/intel_chipset.h index db7c2b1..6c58d19 100644 --- a/PlatboxClient/inc/intel/intel_chipset.h +++ b/PlatboxLib/inc/intel/intel_chipset.h @@ -2,6 +2,22 @@ #include #include "types.h" +#define SPI_BIOS_MMIO_BIOS_BFPREG_OFFSET 0 +#define SPI_BIOS_MMIO_BIOS_HSFSTS_CTL 4 +#define SPI_BIOS_MMIO_BIOS_FADDR 8 +#define SPI_BIOS_MMIO_BIOS_DLOCK 0xC +#define SPI_BIOS_MMIO_BIOS_FREG0 0x54 +#define SPI_BIOS_MMIO_BIOS_FREG1 0x58 +#define SPI_BIOS_MMIO_BIOS_FREG2 0x5C +#define SPI_BIOS_MMIO_BIOS_FREG3 0x60 +#define SPI_BIOS_MMIO_BIOS_FREG4 0x64 +#define SPI_BIOS_MMIO_BIOS_FREG5 0x68 +#define SPI_BIOS_MMIO_BIOS_FPR0 0x84 +#define SPI_BIOS_MMIO_BIOS_FPR1 0x88 +#define SPI_BIOS_MMIO_BIOS_FPR2 0x8C +#define SPI_BIOS_MMIO_BIOS_FPR3 0x90 +#define SPI_BIOS_MMIO_BIOS_FPR4 0x94 + // Hostbridge operations void read_hostbridge_pxpepbar(DWORD64 *pPxpepbar); @@ -64,35 +80,21 @@ void print_spi_interface_bios_control(DWORD *p); // SPIBAR Operations void print_spi_bar_bios_bfpreg(DWORD *p); -void read_spi_bar_bios_bfpreg(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_hsfs_ctl(DWORD *p); -void read_spi_bar_hsfs_ctl(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_faddr(DWORD *p); -void read_spi_bar_faddr(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_dlock(DWORD *p); -void read_spi_bar_dlock(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_freg0(DWORD *p); -void read_spi_bar_freg0(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_freg1(DWORD *p); -void read_spi_bar_freg1(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_freg2(DWORD *p); -void read_spi_bar_freg2(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_freg3(DWORD *p); -void read_spi_bar_freg3(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_freg4(DWORD *p); -void read_spi_bar_freg4(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_freg5(DWORD *p); -void read_spi_bar_freg5(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_fpr0(DWORD *p); -void read_spi_bar_fpr0(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_fpr1(DWORD *p); -void read_spi_bar_fpr1(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_fpr2(DWORD *p); -void read_spi_bar_fpr2(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_fpr3(DWORD *p); -void read_spi_bar_fpr3(DWORD64 SPIBAR, DWORD *pOut); void print_spi_bar_fpr4(DWORD *p); -void read_spi_bar_fpr4(DWORD64 SPIBAR, DWORD *pOut); + void get_smrr(UINT64 *base, UINT32 *size); diff --git a/PlatboxClient/inc/linux/__linux.h b/PlatboxLib/inc/linux/__linux.h similarity index 100% rename from PlatboxClient/inc/linux/__linux.h rename to PlatboxLib/inc/linux/__linux.h diff --git a/PlatboxClient/inc/msr.h b/PlatboxLib/inc/msr.h similarity index 100% rename from PlatboxClient/inc/msr.h rename to PlatboxLib/inc/msr.h diff --git a/PlatboxClient/inc/pci.h b/PlatboxLib/inc/pci.h similarity index 83% rename from PlatboxClient/inc/pci.h rename to PlatboxLib/inc/pci.h index a3f03b3..afb9171 100644 --- a/PlatboxClient/inc/pci.h +++ b/PlatboxLib/inc/pci.h @@ -11,7 +11,6 @@ void write_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v void write_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT value); void read_pci_bar_info(UINT8 bus, UINT8 device, UINT8 function, UINT offset); -void parse_bus_device_function(char *line, UINT *bus, UINT *device, UINT *function); -void parse_handle_pci_operation(int argc, char **argv); + DWORD64 get_pci_ecam_va(); \ No newline at end of file diff --git a/PlatboxClient/inc/physmem.h b/PlatboxLib/inc/physmem.h similarity index 87% rename from PlatboxClient/inc/physmem.h rename to PlatboxLib/inc/physmem.h index 08cb504..e376c52 100644 --- a/PlatboxClient/inc/physmem.h +++ b/PlatboxLib/inc/physmem.h @@ -2,6 +2,9 @@ #include "global.h" #define PAGE_SIZE 0x1000 +#define PAGE_MASK 0xFFFFFFFFFFFFF000 +#define PAGE_OFFSET 0xFFF + #define PAGE_PRESENT 63 #define PAGE_SWAPPED 62 @@ -91,8 +94,3 @@ void _map_pci_ecam(); -void parse_handle_physmem_operation(int argc, char **argv); -void parse_handle_map2user_operation(int argc, char **argv); -void parse_handle_alloc_operation(int argc, char **argv); -void parse_handle_free_memory_operation(int argc, char **argv); -void parse_handle_mem_dump_operation(int argc, char **argv); \ No newline at end of file diff --git a/PlatboxClient/inc/smm/smi_fuzz.h b/PlatboxLib/inc/smm/smi_fuzz.h similarity index 100% rename from PlatboxClient/inc/smm/smi_fuzz.h rename to PlatboxLib/inc/smm/smi_fuzz.h diff --git a/PlatboxClient/inc/smm/smm_communicate.h b/PlatboxLib/inc/smm/smm_communicate.h similarity index 99% rename from PlatboxClient/inc/smm/smm_communicate.h rename to PlatboxLib/inc/smm/smm_communicate.h index 910035a..3ae0734 100644 --- a/PlatboxClient/inc/smm/smm_communicate.h +++ b/PlatboxLib/inc/smm/smm_communicate.h @@ -7,6 +7,7 @@ void smm_dump_s3_bootscript(const char *output_filename); void smm_dump_s3_bootscript_manual(UINT64 rtcode_start, UINT64 rtcode_end, const char *output_filename); + #define RETURN_SUCCESS 0 /// diff --git a/PlatboxClient/inc/types.h b/PlatboxLib/inc/types.h similarity index 100% rename from PlatboxClient/inc/types.h rename to PlatboxLib/inc/types.h diff --git a/PlatboxClient/inc/windows/__win.h b/PlatboxLib/inc/windows/__win.h similarity index 74% rename from PlatboxClient/inc/windows/__win.h rename to PlatboxLib/inc/windows/__win.h index 688b455..13007be 100644 --- a/PlatboxClient/inc/windows/__win.h +++ b/PlatboxLib/inc/windows/__win.h @@ -138,4 +138,49 @@ typedef struct { struct GenericAddressStructure X_GPE1_BLK; } RTACPI_FADT, RTACPI_FACP; -UINT32 GetFADT_Address(); \ No newline at end of file +UINT32 GetFADT_Address(); + + + +#define SE_CREATE_TOKEN 2 +#define SE_ASSIGNPRIMARYTOKEN 3 +#define SE_LOCK_MEMORY 4 +#define SE_INCREASE_QUOTA 5 +#define SE_UNSOLICITED_INPUT 6 +#define SE_TCB 7 +#define SE_SECURITY 8 +#define SE_TAKE_OWNERSHIP 9 +#define SE_LOAD_DRIVER 10 +#define SE_SYSTEM_PROFILE 11 +#define SE_SYSTEMTIME 12 +#define SE_PROF_SINGLE_PROCESS 13 +#define SE_INC_BASE_PRIORITY 14 +#define SE_CREATE_PAGEFILE 15 +#define SE_CREATE_PERMANENT 16 +#define SE_BACKUP 17 +#define SE_RESTORE 18 +#define SE_SHUTDOWN 19 +#define SE_DEBUG 20 +#define SE_AUDIT 21 +#define SE_SYSTEM_ENVIRONMENT 22 +#define SE_CHANGE_NOTIFY 23 +#define SE_REMOTE_SHUTDOWN 24 +#define SE_UNDOCK 25 +#define SE_SYNC_AGENT 26 +#define SE_ENABLE_DELEGATION 27 +#define SE_MANAGE_VOLUME 28 +#define SE_IMPERSONATE 29 +#define SE_CREATE_GLOBAL 30 +#define SE_TRUSTED_CREDMAN_ACCESS 31 +#define SE_RELABEL 32 +#define SE_INC_WORKING_SET 33 +#define SE_TIME_ZONE 34 +#define SE_CREATE_SYMBOLIC_LINK 35 + + +typedef NTSTATUS(WINAPI * _RtlAdjustPrivilege)(IN ULONG Privilege, IN BOOL Enable, IN BOOL CurrentThread, OUT PULONG pPreviousState); + +extern _RtlAdjustPrivilege RtlAdjustPrivilege; + +NTSTATUS enable_privilege(ULONG privId); +void get_more_privileges(void); \ No newline at end of file diff --git a/PlatboxClient/src/UEFIVars.cpp b/PlatboxLib/src/UEFIVars.cpp similarity index 76% rename from PlatboxClient/src/UEFIVars.cpp rename to PlatboxLib/src/UEFIVars.cpp index 9a8195d..0e79acb 100644 --- a/PlatboxClient/src/UEFIVars.cpp +++ b/PlatboxLib/src/UEFIVars.cpp @@ -3,6 +3,7 @@ #include "UEFIVars.h" #include "Util.h" + const char * UEFI_VARIABLE_ATTRIBUTES[] = { "NV", //"NON_VOLATILE", "BS", //"BOOTSERVICE_ACCESS", @@ -65,42 +66,15 @@ const char * UEFI_VARIABLE_ATTRIBUTES[] = { - NTSTATUS enable_privilege(ULONG privId) - { - ULONG previousState; - NTSTATUS status = RtlAdjustPrivilege(privId, TRUE, FALSE, &previousState); - if (NT_SUCCESS(status)) - printf("Privilege \'%u\' OK\n", privId); - else printf("RtlAdjustPrivilege (%u) %08x\n", privId, status); - return status; - } - - void get_more_privileges(void) { - enable_privilege(SE_SYSTEM_ENVIRONMENT); - //enable_privilege(SE_LOAD_DRIVER); - //enable_privilege(SE_SECURITY); - //enable_privilege(SE_TCB); - //enable_privilege(SE_BACKUP); - //enable_privilege(SE_RESTORE); - //enable_privilege(SE_DEBUG); - } -#endif +_NtEnumerateSystemEnvironmentValuesEx NtEnumerateSystemEnvironmentValuesEx; void list_uefi_variables() { - #ifdef __linux__ - printf("Unimplemented!\n"); - return; - #else // _WIN32 - HMODULE ntdll = LoadLibraryA("ntdll.dll"); + HMODULE ntdll = LoadLibraryA("ntdll.dll"); NtEnumerateSystemEnvironmentValuesEx = (_NtEnumerateSystemEnvironmentValuesEx) GetProcAddress(ntdll, "NtEnumerateSystemEnvironmentValuesEx"); printf("NtEnumerateSystemEnvironmentValuesEx: %p\n", NtEnumerateSystemEnvironmentValuesEx); - RtlAdjustPrivilege = (_RtlAdjustPrivilege) - GetProcAddress(ntdll, "RtlAdjustPrivilege"); - printf("RtlAdjustPrivilege: %p\n", RtlAdjustPrivilege); - PVARIABLE_NAME_AND_VALUE buffer = NULL; DWORD bufferLen = 0; NTSTATUS status; @@ -129,7 +103,7 @@ void list_uefi_variables() HeapFree(GetProcessHeap(), 0, buffer); } } - #endif - -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/PlatboxClient/src/Util.cpp b/PlatboxLib/src/Util.cpp similarity index 82% rename from PlatboxClient/src/Util.cpp rename to PlatboxLib/src/Util.cpp index b5605f9..2f29c04 100644 --- a/PlatboxClient/src/Util.cpp +++ b/PlatboxLib/src/Util.cpp @@ -2,9 +2,11 @@ #include "Util.h" + + char **parse_arguments(char *command_line, char arg_delim) { char delim[2] = { 0 }; - if (arg_delim == NULL) { + if (arg_delim == 0) { delim[0] = ' '; } else { @@ -150,7 +152,7 @@ memmem (const void *haystack, size_t haystack_len, const void *needle, } #endif -void to_guid(char *guid_str, GUID *guid_arg) { +void to_guid(const char *guid_str, GUID *guid_arg) { GUID guid; @@ -180,3 +182,39 @@ void display_guid(GUID *guid) { guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); } + + +#ifdef _WIN32 + +_RtlAdjustPrivilege RtlAdjustPrivilege; + +NTSTATUS enable_privilege(ULONG privId) +{ + HMODULE ntdll = LoadLibraryA("ntdll.dll"); + + RtlAdjustPrivilege = (_RtlAdjustPrivilege) + GetProcAddress(ntdll, "RtlAdjustPrivilege"); + + ULONG previousState; + + NTSTATUS status = RtlAdjustPrivilege(privId, TRUE, FALSE, &previousState); + if (NT_SUCCESS(status)) { + debug_print("Privilege \'%u\' OK\n", privId); + } else { + debug_print("RtlAdjustPrivilege (%u) %08x\n", privId, status); + } + + return status; +} + +void get_more_privileges(void) { + enable_privilege(SE_SYSTEM_ENVIRONMENT); + enable_privilege(SE_LOAD_DRIVER); + //enable_privilege(SE_SECURITY); + //enable_privilege(SE_TCB); + //enable_privilege(SE_BACKUP); + //enable_privilege(SE_RESTORE); + //enable_privilege(SE_DEBUG); +} + +#endif \ No newline at end of file diff --git a/PlatboxClient/src/_run_attempt.asm b/PlatboxLib/src/_run_attempt.asm similarity index 100% rename from PlatboxClient/src/_run_attempt.asm rename to PlatboxLib/src/_run_attempt.asm diff --git a/PlatboxClient/src/amd/amd_chipset.cpp b/PlatboxLib/src/amd/amd_chipset.cpp similarity index 89% rename from PlatboxClient/src/amd/amd_chipset.cpp rename to PlatboxLib/src/amd/amd_chipset.cpp index e02f5dd..cb7b663 100644 --- a/PlatboxClient/src/amd/amd_chipset.cpp +++ b/PlatboxLib/src/amd/amd_chipset.cpp @@ -7,14 +7,13 @@ #include "msr.h" LPC_ISA_Bridge g_lpc_isa_bridge_registers; -SPI g_spi_registers; DWORD64 g_MmioCfgBaseAddr; void _read_lpc_isa_bridge() { memset(&g_lpc_isa_bridge_registers, 0x00, sizeof(g_lpc_isa_bridge_registers)); DWORD *pw = (DWORD *) &g_lpc_isa_bridge_registers; - for (int i = 0; i < sizeof(g_lpc_isa_bridge_registers) / sizeof(DWORD); i++) { + for (int i = 0 ; i < sizeof(LPC_ISA_Bridge)/sizeof(DWORD); i++) { *pw = read_pci_dword(0, 0x14, 3, i); pw++; } @@ -61,12 +60,14 @@ void _read_mmio_cfg_base_addr() { } - - -void amd_print_smm_base() { +DWORD64 amd_retrieve_smm_base() { DWORD64 smm_base = 0; do_read_msr(AMD_MSR_SMM_BASE_ADDRESS, &smm_base); + return smm_base; +} +void amd_print_smm_base() { + DWORD64 smm_base = amd_retrieve_smm_base(); printf("MSR C001_0111 SMM Base Address (SMM_BASE)\n"); printf(" => Base: %lx\n", smm_base); printf(" -> SMI-Handler Entry Point: %lx\n", smm_base + AMD_SMI_HANDLER_ENTRY_POINT); @@ -74,6 +75,7 @@ void amd_print_smm_base() { printf("\n"); } + void amd_print_smm_tseg_addr() { DWORD64 smm_tseg_base = 0; UINT32 tseg_size = 0; @@ -86,9 +88,14 @@ void amd_print_smm_tseg_addr() { printf("\n"); } -void amd_print_smm_tseg_mask() { +DWORD64 amd_retrieve_smm_tseg_mask() { DWORD64 smm_tseg_mask = 0; do_read_msr(AMD_MSR_SMM_TSEG_MASK, &smm_tseg_mask); + return smm_tseg_mask; +} + +void amd_print_smm_tseg_mask() { + DWORD64 smm_tseg_mask = amd_retrieve_smm_tseg_mask(); printf("MSR C001_0113 SMM TSeg Mask (SMMMask)\n"); printf(" => Value: %016llx\n", smm_tseg_mask); @@ -117,9 +124,14 @@ void get_tseg_info(UINT64 *base, UINT32 *size) { } -void amd_print_apic_bar() { +DWORD64 amd_retrieve_apic_bar() { DWORD64 apic_bar = 0; do_read_msr(AMD_MSR_APIC_BAR, &apic_bar); + return apic_bar; +} + +void amd_print_apic_bar() { + DWORD64 apic_bar = amd_retrieve_apic_bar(); printf("MSR 0000_001B APIC Base Address (APIC_BAR)\n"); printf(" => Value: %lx\n", apic_bar); @@ -129,9 +141,14 @@ void amd_print_apic_bar() { printf("\n"); } -void amd_print_hwcr_smmlock() { +DWORD64 amd_retrieve_hwcr_smmlock() { DWORD64 hwcr = 0; do_read_msr(AMD_MSR_HARDWARE_CONFIGURATION, &hwcr); + return hwcr; +} + +void amd_print_hwcr_smmlock() { + DWORD64 hwcr = amd_retrieve_hwcr_smmlock(); int smm_lock = hwcr & BIT_MSR_HWCR_SMMLOCK; printf("MSR C001_0015 Hardware Configuration (HWCR)\n"); @@ -209,9 +226,14 @@ void amd_print_io_trap_control_status() { printf("\n"); } -void amd_print_mmio_ba() { +DWORD64 amd_retrieve_mmio_ba() { DWORD64 mmio_ba = 0; do_read_msr(AMD_MSR_MMIO_CONFIGURATION_BASE_ADDRRESS, &mmio_ba); + return mmio_ba; +} + +void amd_print_mmio_ba() { + DWORD64 mmio_ba = amd_retrieve_mmio_ba(); printf("MSR C001_0058 MMIO Configuration Base Address\n"); printf(" => Value: %016lx\n", mmio_ba); @@ -221,11 +243,14 @@ void amd_print_mmio_ba() { printf("\n"); } - +DWORD amd_retrieve_root_complex_pci_control() { + DWORD pci_control = read_pci_dword(0, 0, 0, ROOT_COMPLEX_PCI_CONTROL_OFFSET/sizeof(DWORD)); + return pci_control; +} void amd_print_root_complex_pci_control() { // D0F0x4C PCI Control - DWORD pci_control = read_pci_dword(0, 0, 0, ROOT_COMPLEX_PCI_CONTROL_OFFSET); + DWORD pci_control = amd_retrieve_root_complex_pci_control(); int mmio_enable = (pci_control >> 23) & 1; /* This range is used to @@ -246,8 +271,8 @@ void amd_print_root_complex_pci_control() { void amd_print_root_complex_nb_control() { // D0F0x64_x00 Northbridge Control - write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX, ROOT_COMPLEX_MISC_INDEX_OFFSET_NORTHBRIDGE_CONTROL); - DWORD nb_control = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA); + write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX/sizeof(DWORD), ROOT_COMPLEX_MISC_INDEX_OFFSET_NORTHBRIDGE_CONTROL); + DWORD nb_control = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA/sizeof(DWORD)); int HwInitWrLock = (nb_control >> 7) & 1; @@ -264,11 +289,11 @@ void amd_print_root_complex_nb_control() { void amd_print_root_complex_mmio_range() { // D0F0x64_x17 Memory Mapped IO Base Address // D0F0x64_x18 Memory Mapped IO Limit - write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX, ROOT_COMPLEX_MISC_INDEX_OFFSET_MMIO_BASE); - DWORD mmio_base = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA); + write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX/sizeof(DWORD), ROOT_COMPLEX_MISC_INDEX_OFFSET_MMIO_BASE); + DWORD mmio_base = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA/sizeof(DWORD)); - write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX, ROOT_COMPLEX_MISC_INDEX_OFFSET_MMIO_LIMIT); - DWORD mmio_limit = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA); + write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX/sizeof(DWORD), ROOT_COMPLEX_MISC_INDEX_OFFSET_MMIO_LIMIT); + DWORD mmio_limit = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA/sizeof(DWORD)); printf("D0F0x64_x17 Memory Mapped IO Base Address: %08x\n", mmio_base); printf("D0F0x64_x18 Memory Mapped IO Limit: %08x\n", mmio_limit); @@ -279,11 +304,11 @@ void amd_print_root_complex_mmio_range() { void amd_print_root_complex_tom2() { // D0F0x64_x19 Top of Memory 2 Low // D0F0x64_x1A Top of Memory 2 High - write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX, ROOT_COMPLEX_MISC_INDEX_OFFSET_TOM2_LOW); - DWORD tom2_low = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA); + write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX/sizeof(DWORD), ROOT_COMPLEX_MISC_INDEX_OFFSET_TOM2_LOW); + DWORD tom2_low = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA/sizeof(DWORD)); - write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX, ROOT_COMPLEX_MISC_INDEX_OFFSET_TOM2_HIGH); - DWORD tom2_high = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA); + write_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX/sizeof(DWORD), ROOT_COMPLEX_MISC_INDEX_OFFSET_TOM2_HIGH); + DWORD tom2_high = read_pci_dword(0, 0, 0, ROOT_COMPLEX_MISC_INDEX_DATA/sizeof(DWORD)); DWORD64 tom2 = ((DWORD64)tom2_high << 32) | ((DWORD64) tom2_low); int enabled = tom2 & 1; @@ -307,7 +332,7 @@ void amd_print_msr_tom2() { void amd_print_root_complex_tom() { // D0F0x90 Northbridge Top of Memory - DWORD tom = read_pci_dword(0, 0, 0, ROOT_COMPLEX_NORTHBRIDGE_TOP_OF_MEMORY_OFFSET); + DWORD tom = read_pci_dword(0, 0, 0, ROOT_COMPLEX_NORTHBRIDGE_TOP_OF_MEMORY_OFFSET/sizeof(DWORD)); /* TopOfDram. Read-write. BIOS: MSR C001_001A[TOM[31:23]]. Specifies the address that divides between MMIO and DRAM. From TopOfDram to 4G is MMIO; below TopOfDram is DR @@ -340,8 +365,8 @@ void amd_print_dram_range_base_limit() { printf(" => Range %d\n", i); - DWORD base_low = read_pci_dword(0, 0x18, 1, base_low_offset); - DWORD limit_low = read_pci_dword(0, 0x18, 1, limit_low_offset); + DWORD base_low = read_pci_dword(0, 0x18, 1, base_low_offset/sizeof(DWORD)); + DWORD limit_low = read_pci_dword(0, 0x18, 1, limit_low_offset/sizeof(DWORD)); //DWORD base_high = read_pci_dword(h, 0, 0x18, 1, base_high_offset); //DWORD limit_high = read_pci_dword(h, 0, 0x18, 1, limit_high_offset); @@ -379,8 +404,8 @@ void amd_print_mmio_base_limit_ranges() { printf(" => Range %d\n", i); - DWORD base_low = read_pci_dword(0, 0x18, 1, base_low_offset); - DWORD limit_low = read_pci_dword(0, 0x18, 1, limit_low_offset); + DWORD base_low = read_pci_dword(0, 0x18, 1, base_low_offset/sizeof(DWORD)); + DWORD limit_low = read_pci_dword(0, 0x18, 1, limit_low_offset/sizeof(DWORD)); printf(" => BaseLow : %08x\n", base_low & 0xFFFFFF00); printf(" => Lock: %d\n", (base_low >> 3) & 1); @@ -401,8 +426,8 @@ void amd_print_dram_system_address_range() { // D18F1x120 DRAM Base System Address // D18F1x124 DRAM Limit System Address - DWORD dram_base_system_address = read_pci_dword(0, 0x18, 1, D18F1_DRAM_BASE_SYSTEM_ADDRESS_OFFSET); - DWORD dram_limit_system_address = read_pci_dword(0, 0x18, 1, D18F1_DRAM_LIMIT_SYSTEM_ADDRESS_OFFSET); + DWORD dram_base_system_address = read_pci_dword(0, 0x18, 1, D18F1_DRAM_BASE_SYSTEM_ADDRESS_OFFSET/sizeof(DWORD)); + DWORD dram_limit_system_address = read_pci_dword(0, 0x18, 1, D18F1_DRAM_LIMIT_SYSTEM_ADDRESS_OFFSET/sizeof(DWORD)); printf("D18F1x120 DRAM System Address Range\n"); printf(" => Base: %08x\n", dram_base_system_address); @@ -425,8 +450,8 @@ void amd_print_dram_controller_range() { */ - DWORD dram_controller_base = read_pci_dword(0, 0x18, 1, D18F1_DRAM_CONTROLLER_BASE_RANGE_0_OFFSET); - DWORD dram_controller_limit = read_pci_dword(0, 0x18, 1, D18F1_DRAM_CONTROLLER_LIMIT_RANGE_0_OFFSET); + DWORD dram_controller_base = read_pci_dword(0, 0x18, 1, D18F1_DRAM_CONTROLLER_BASE_RANGE_0_OFFSET/sizeof(DWORD)); + DWORD dram_controller_limit = read_pci_dword(0, 0x18, 1, D18F1_DRAM_CONTROLLER_LIMIT_RANGE_0_OFFSET/sizeof(DWORD)); printf("D18F1x2[1C:00] DRAM Controller Base/Limit\n"); printf(" => Base: %08x\n", dram_controller_base & 0xFFFFF000); @@ -458,7 +483,7 @@ void amd_print_dram_hole() { */ - DWORD dram_hole_address = read_pci_dword(0, 0x18, 1, D18F1_DRAM_HOLE_ADDRESS_OFFSET); + DWORD dram_hole_address = read_pci_dword(0, 0x18, 1, D18F1_DRAM_HOLE_ADDRESS_OFFSET/sizeof(DWORD)); printf("D18F1xF0 DRAM Hole Address\n"); @@ -488,7 +513,7 @@ void amd_print_memory_controller_configuration_lock() { D18F2x118[CC6SaveEn] */ - DWORD mem_controller_config_low = read_pci_dword(0, 0x18, 2, D18F2_MEMORY_CONTROLLER_CONFIGURATION_LOW_OFFSET); + DWORD mem_controller_config_low = read_pci_dword(0, 0x18, 2, D18F2_MEMORY_CONTROLLER_CONFIGURATION_LOW_OFFSET/sizeof(DWORD)); int lockDramCfg = (mem_controller_config_low >> 19) & 1; @@ -502,43 +527,19 @@ void amd_print_memory_controller_configuration_lock() { printf("\n"); } -void print_SPI_Cntrl0() { - // AMD 15h Family - // SPIx00 SPI_Cntrl0 - /* - SpiHostAccessRomEn. Read; Write-0-only. Reset: 1. This is a clear-once protection bit; once it is - cleared to 0 it cannot be set back to 1. 0=MAC cannot access BIOS ROM space (upper 512KB). - 1=MAC can access BIOS ROM space. +void amd_retrieve_chipset_information() { + _read_lpc_isa_bridge(); + _read_mmio_cfg_base_addr(); + DWORD spi_addr = (*(DWORD *) &g_lpc_isa_bridge_registers.SPI_BASE) & 0xFFFFFFC0; + load_spi_information(spi_addr); +} - SpiAccessMacRomEn. IF (Mode == SMI) Read-write. ELSE Read; Write-0-only. ENDIF. Reset: 1. - This is a clear-once protection bit. 0=Software cannot access MAC’s portion of the ROM space - (lower 512KB). 1=Software can access MAC’s portion of the ROM space - */ - DWORD spiCntrl0 = g_spi_registers.SPI_Cntrl0; - int SpiAccessMacRomEn = (spiCntrl0 >> 22) & 1; - int SpiHostAccessRomEn = (spiCntrl0 >> 23) & 1; - printf("SPIx00 - SPI_Cntrl0: %08x\n", spiCntrl0); - printf(" - SpiAccessMacRomEn: %d - ", SpiAccessMacRomEn); - if (SpiAccessMacRomEn == 1) { - print_red("FAILED\n"); - } else { - print_green("OK\n"); - } - printf(" - SpiHostAccessRomEn: %d - ", SpiHostAccessRomEn); - if (SpiHostAccessRomEn == 1) { - print_red("FAILED\n"); - } else { - print_green("OK\n"); - } - printf("\n"); -} +void amd_print_chipset_information() { -void amd_get_chipset_information() { - _read_lpc_isa_bridge(); - _read_mmio_cfg_base_addr(); + amd_retrieve_chipset_information(); IO_MEM_PORT_DECODE *pIOMemPortDecodeEnable = (IO_MEM_PORT_DECODE *) &g_lpc_isa_bridge_registers.IOMemPortDecodeEnableRegister; printf("IO/Mem Port Decode\n"); @@ -569,7 +570,7 @@ void amd_get_chipset_information() { printf("\n=== SPI Range Protections ===\n"); ROM_PROTECT *pRomProtect; pRomProtect = (ROM_PROTECT *) & g_lpc_isa_bridge_registers.ROMProtect0; - printf("Rom Protect 0: \n"); + printf("Rom Protect 0: %08x\n", *(DWORD *)pRomProtect); printf(" - Base: %08x\n", pRomProtect->RomBase << 11); printf(" - RangeUnit: %d\n", pRomProtect->RangeUnit); printf(" - Range: %08x\n", pRomProtect->Range); @@ -584,7 +585,7 @@ void amd_get_chipset_information() { print_green("OK - Range in use\n"); } pRomProtect = (ROM_PROTECT *) & g_lpc_isa_bridge_registers.ROMProtect1; - printf("Rom Protect 1: \n"); + printf("Rom Protect 1: %08x\n", *(DWORD *)pRomProtect); printf(" - Base: %08x\n", pRomProtect->RomBase << 11); printf(" - RangeUnit: %d\n", pRomProtect->RangeUnit); printf(" - Range: %08x\n", pRomProtect->Range); @@ -600,7 +601,7 @@ void amd_get_chipset_information() { } pRomProtect = (ROM_PROTECT *) & g_lpc_isa_bridge_registers.ROMProtect2; - printf("Rom Protect 2: \n"); + printf("Rom Protect 2: %08x\n", *(DWORD *)pRomProtect); printf(" - Base: %08x\n", pRomProtect->RomBase << 11); printf(" - RangeUnit: %d\n", pRomProtect->RangeUnit); printf(" - Range: %08x\n", pRomProtect->Range); @@ -616,7 +617,7 @@ void amd_get_chipset_information() { } pRomProtect = (ROM_PROTECT *) & g_lpc_isa_bridge_registers.ROMProtect3; - printf("Rom Protect 3: \n"); + printf("Rom Protect 3: %08x\n", *(DWORD *)pRomProtect); printf(" - Base: %08x\n", pRomProtect->RomBase << 11); printf(" - RangeUnit: %d\n", pRomProtect->RangeUnit); printf(" - Range: %08x\n", pRomProtect->Range); @@ -633,39 +634,13 @@ void amd_get_chipset_information() { printf("\n"); - DWORD spi_addr = (*(DWORD *) &g_lpc_isa_bridge_registers.SPI_BASE) & 0xFFFFFFC0; - - printf("SPI BASE: %lx\n", spi_addr); - - read_physical_memory(spi_addr, sizeof(SPI), &g_spi_registers, false); - - // SPIx00 SPI_Cntrl0 - print_SPI_Cntrl0(); + MISC_CTL_BITS* pMiscCtlBits = (MISC_CTL_BITS *) &g_lpc_isa_bridge_registers.MiscCtlBits; + printf("SPI ROM SMM Write Enable: %d\n", pMiscCtlBits->SmmWriteRomEn); - ALT_SPI_CS *pAltSpiCs = (ALT_SPI_CS *) & g_spi_registers.Alt_SPI_CS; - printf("SPIx1D - SpiProtectEn0: %d - ", pAltSpiCs->SpiProtectEn0); - if (pAltSpiCs->SpiProtectEn0 == 0) { - print_red("FAILED\n"); - } else { - print_green("OK\n"); - } - printf("SPIx1D - SpiProtectEn1: %d - ", pAltSpiCs->SpiProtectEn1); - if (pAltSpiCs->SpiProtectEn1 == 0) { - print_red("FAILED\n"); - } else { - print_green("OK\n"); - } - printf("SPIx1D - SpiProtectLock: %d - ", pAltSpiCs->SpiProtectLock); - if (pAltSpiCs->SpiProtectLock == 0) { - print_red("FAILED\n"); - } else { - print_green("OK\n"); - } printf("\n"); - - - + print_spi_info(); + LPC_ROM_ADDRESS lpc_rom_addr_range1 = {0}; lpc_rom_addr_range1.StartAddr = (DWORD)g_lpc_isa_bridge_registers.LPC_ROM_Address_Range_1_StartAddress << 16; lpc_rom_addr_range1.EndAddr = ((DWORD)g_lpc_isa_bridge_registers.LPC_ROM_Address_Range_1_EndAddress << 16) | 0xffff; @@ -720,3 +695,14 @@ void amd_dump_spi_flash(const char *output_filename) { free(rom_data); } + + +void write_rom_protect0() { + DWORD val = read_pci_dword(0, 0x14, 3, 0x50>>2); + printf("RomProtect0 val: %08x\n", val); + ROM_PROTECT *pRomProtect = (ROM_PROTECT *) &val; + pRomProtect->Range = 1; + pRomProtect->WriteProtect = 1; + pRomProtect->RomBase = 0xFF000000 >> 12; + write_pci_dword(0, 0x14, 3, 0x50>>2, val); +} \ No newline at end of file diff --git a/PlatboxLib/src/amd/amd_spi.cpp b/PlatboxLib/src/amd/amd_spi.cpp new file mode 100644 index 0000000..48eea46 --- /dev/null +++ b/PlatboxLib/src/amd/amd_spi.cpp @@ -0,0 +1,557 @@ +#include "amd_spi.h" +#include "global.h" +#include "physmem.h" +#include "Util.h" + +DWORD g_spi_addr; +SPI g_spi_registers; +BOOL bSpiInformationInitialized; +DWORD g_flash_id; + + + +BYTE SPI_READ_OP; +BYTE SPI_WRITE_ENABLE_OP; +BYTE SPI_WRITE_DISABLE_OP; +BYTE SPI_WRITE_BYTE_OP; +BYTE SPI_RDID_OP; +BYTE SPI_SECTOR_ERASE_OP; // vendor specific - not shown in the SPI Controller region + + +void print_SPI_Cntrl0() { + // AMD 15h Family + // SPIx00 SPI_Cntrl0 + + /* + SpiHostAccessRomEn. Read; Write-0-only. Reset: 1. This is a clear-once protection bit; once it is + cleared to 0 it cannot be set back to 1. 0=MAC cannot access BIOS ROM space (upper 512KB). + 1=MAC can access BIOS ROM space. + + SpiAccessMacRomEn. IF (Mode == SMI) Read-write. ELSE Read; Write-0-only. ENDIF. Reset: 1. + This is a clear-once protection bit. 0=Software cannot access MAC’s portion of the ROM space + (lower 512KB). 1=Software can access MAC’s portion of the ROM space + */ + DWORD spiCntrl0 = g_spi_registers.SPI_Cntrl0Value; + int SpiAccessMacRomEn = (spiCntrl0 >> 22) & 1; + int SpiHostAccessRomEn = (spiCntrl0 >> 23) & 1; + printf("SPIx00 - SPI_Cntrl0: %08x\n", spiCntrl0); + printf(" - SpiAccessMacRomEn: %d - ", SpiAccessMacRomEn); + if (SpiAccessMacRomEn == 1) { + print_red("FAILED\n"); + } else { + print_green("OK\n"); + } + printf(" - SpiHostAccessRomEn: %d - ", SpiHostAccessRomEn); + if (SpiHostAccessRomEn == 1) { + print_red("FAILED\n"); + } else { + print_green("OK\n"); + } + + printf("\n"); +} + +void print_SPI_RestrictedCmds() { + + SPIRestrictedCmd* spiRestrictedCmd = (SPIRestrictedCmd *) &g_spi_registers.SPI_RestrictedCmd; + SPIRestrictedCmd2* spiRestrictedCmd2 = (SPIRestrictedCmd2 *) &g_spi_registers.SPI_RestrictedCmd2; + + printf(" RestrictedCmd: %02x %02x %02x %02x\n", + spiRestrictedCmd->RestrictedCmd0, + spiRestrictedCmd->RestrictedCmd1, + spiRestrictedCmd->RestrictedCmd2, + spiRestrictedCmd->RestrictedCmd3); + + printf("RestrictedCmd2: %02x %02x %02x %02x\n", + spiRestrictedCmd2->RestrictedCmd4, + spiRestrictedCmd2->RestrictedCmdWoAddr0, + spiRestrictedCmd2->RestrictedCmdWoAddr1, + spiRestrictedCmd2->RestrictedCmdWoAddr2); + + // TODO Implement check for 01 06 C7 bytes + + printf("\n"); +} + +void print_SPI_Cntrl1() { + BYTE ByteCommand = g_spi_registers.SPI_Cntrl1Value >> 24; + printf("SPIx0C [SPI_Cntrl1] - ByteCommand: %02x\n", ByteCommand); +} + +void print_SPI_CmdValue0() { + BYTE MacLockCmd0 = g_spi_registers.SPI_CmdValue0 & 0xFF; + BYTE MacLockCmd1 = (g_spi_registers.SPI_CmdValue0 >> 8 ) & 0xFF; + BYTE MacUnlockCmd0 = (g_spi_registers.SPI_CmdValue0 >> 16 ) & 0xFF; + BYTE MacUnlockCmd1 = (g_spi_registers.SPI_CmdValue0 >> 24 ) & 0xFF; + + printf("SPIx10 - CmdVal0\n"); + printf(" - MacLockCmd0: %02x\n", MacLockCmd0); + printf(" - MacLockCmd1: %02x\n", MacLockCmd1); + printf(" - MacUnlockCmd0: %02x\n", MacUnlockCmd0); + printf(" - MacUnlockCmd1: %02x\n", MacUnlockCmd1); +} + +void print_SPI_CmdValue1() { + BYTE WREN = g_spi_registers.SPI_CmdValue1 & 0xFF; + BYTE WRDI = (g_spi_registers.SPI_CmdValue1 >> 8 ) & 0xFF; + BYTE RDID = (g_spi_registers.SPI_CmdValue1 >> 16 ) & 0xFF; + BYTE RDSR = (g_spi_registers.SPI_CmdValue1 >> 24 ) & 0xFF; + + printf("SPIx14 - CmdVal1\n"); + printf(" - WREN: %02x\n", WREN); + printf(" - WRDI: %02x\n", WRDI); + printf(" - RDID: %02x\n", RDID); + printf(" - RDSR: %02x\n", RDSR); +} + +void print_SPI_CmdValue2() { + BYTE Read = g_spi_registers.SPI_CmdValue2 & 0xFF; + BYTE FRead = (g_spi_registers.SPI_CmdValue2 >> 8 ) & 0xFF; + BYTE PAGEWR = (g_spi_registers.SPI_CmdValue2 >> 16 ) & 0xFF; + BYTE BYTEWR = (g_spi_registers.SPI_CmdValue2 >> 24 ) & 0xFF; + + printf("SPIx18 - CmdVal2\n"); + printf(" - Read: %02x\n", Read); + printf(" - FRead: %02x\n", FRead); + printf(" - PAGEWR: %02x\n", PAGEWR); + printf(" - BYTEWR: %02x\n", BYTEWR); +} + +void print_SPI_x1D() { + ALT_SPI_CS *pAltSpiCs = (ALT_SPI_CS *) & g_spi_registers.Alt_SPI_CS; + printf("SPIx1D - Alt_SPI_CS\n"); + printf(" - lock_spi_cs: %d - ", pAltSpiCs->lock_spi_cs); + if (pAltSpiCs->lock_spi_cs == 0) { + print_red("FAILED\n"); + } else { + print_green("OK\n"); + } + printf(" - SpiProtectEn0: %d - ", pAltSpiCs->SpiProtectEn0); + if (pAltSpiCs->SpiProtectEn0 == 0) { + print_red("FAILED\n"); + } else { + print_green("OK\n"); + } + printf(" - SpiProtectEn1: %d - ", pAltSpiCs->SpiProtectEn1); + if (pAltSpiCs->SpiProtectEn1 == 0) { + print_red("FAILED\n"); + } else { + print_green("OK\n"); + } + printf(" - SpiProtectLock: %d - ", pAltSpiCs->SpiProtectLock); + if (pAltSpiCs->SpiProtectLock == 0) { + print_red("FAILED\n"); + } else { + print_green("OK\n"); + } + printf(" - AltSpiCsEn: %d\n", pAltSpiCs->AltSpiCsEn); +} + +void load_spi_information(DWORD spi_addr) { + g_spi_addr = spi_addr; + read_physical_memory(g_spi_addr, sizeof(SPI), &g_spi_registers, false); + + SPI_WRITE_ENABLE_OP = g_spi_registers.SPI_CmdValue1 & 0xFF; + SPI_WRITE_DISABLE_OP = (g_spi_registers.SPI_CmdValue1 >> 8 ) & 0xFF; + SPI_RDID_OP = (g_spi_registers.SPI_CmdValue1 >> 16 ) & 0xFF; + SPI_WRITE_BYTE_OP = (g_spi_registers.SPI_CmdValue2 >> 24 ) & 0xFF; + SPI_READ_OP = g_spi_registers.SPI_CmdValue2 & 0xFF; + + g_flash_id = amd_spi_read_id(); + + switch(g_flash_id) { + case Winbond_25Q128JVS: + SPI_SECTOR_ERASE_OP = Winbond_25Q128JVS_SECTOR_ERASE_OP; + break; + default: + break; + } + + if (SPI_SECTOR_ERASE_OP == 0) { + printf("warning: SPI_ERASE could not be found!\n"); + } + //printf("SPI_SECTOR_ERASE_OP: %02x\n", SPI_SECTOR_ERASE_OP); + bSpiInformationInitialized = 1; +} + + +void print_spi_info() { + + if (bSpiInformationInitialized == 0) { + printf("err: amd_spi - SPI_ADDR not set!\n"); + exit(-1); + } + + read_physical_memory(g_spi_addr, sizeof(SPI), &g_spi_registers, false); + + printf("SPI BASE: %lx\n", g_spi_addr); + + // SPIx00 SPI_Cntrl0 + print_SPI_Cntrl0(); + + // SPIx04, SPIx08 RestrictedCmd + print_SPI_RestrictedCmds(); + + print_SPI_Cntrl1(); + + print_SPI_CmdValue0(); + print_SPI_CmdValue1(); + print_SPI_CmdValue2(); + + // SPIx1D + print_SPI_x1D(); + +} + + +void amd_spi_clear_fifo_ptr(volatile SPI *spi_base) { + // DWORD SPI_Cntrl0 = spi_base->SPI_Cntrl0Value; + // SPI_Cntrl0 |= 1<<20; + // spi_base->SPI_Cntrl0Value = SPI_Cntrl0; + spi_base->SPI_Cntrl0.FifoPtrClr = 1; + while (spi_base->SPI_Cntrl1.FifoPtr != 0); +} + +void amd_spi_execute_command(volatile SPI *spi_base) { + spi_base->CmdTrig = 0xff; + while((spi_base->CmdTrig & 0x80) != 0); + while(spi_base->SpiStatus.SpiBusy); +} + +void amd_spi_write_enable(volatile SPI* spi_base) { + amd_spi_clear_fifo_ptr(spi_base); + spi_base->CmdCode = SPI_WRITE_ENABLE_OP; // WREN + // Set RX Byte Count + spi_base->RxByteCnt = 0; + spi_base->TxByteCnt = 0; + amd_spi_execute_command(spi_base); +} + +void amd_spi_print_fifo_stats(volatile SPI *spi_base) { + printf(" FifoRdPtr: %08x\n", spi_base->SpiStatus.FifoRdPtr); + printf(" FifoWrPtr: %08x\n", spi_base->SpiStatus.FifoWrPtr); + printf(" DoneByCount: %08x\n", spi_base->SpiStatus.DoneByCount); + printf("IllegalAccess: %02x\n", spi_base->SPI_Cntrl0.IllegalAccess); +} + +DWORD amd_spi_read_id() { + volatile SPI *spi_base = (volatile SPI *) map_physical_memory(g_spi_addr, PAGE_SIZE); + amd_spi_clear_fifo_ptr(spi_base); + spi_base->CmdCode = SPI_RDID_OP; + // Set RX Byte Count + spi_base->RxByteCnt = 3; + spi_base->TxByteCnt = 0; + amd_spi_execute_command(spi_base); + + DWORD flash_id = (DWORD)spi_base->SPI_regx80 << 16; + flash_id |= (DWORD)spi_base->SPI_regx81 << 8; + flash_id |= (DWORD) spi_base->SPI_regx82; + + + unmap_physical_memory((void *) spi_base, PAGE_SIZE); + + return flash_id; +} + +void amd_spi_erase_4k_block(volatile SPI *spi_base_arg, UINT32 address) { + if (address > FLASH_SIZE) + { + printf("invalid parameters for read_from_flash_index_mode\n"); + return; + } + + volatile SPI *spi_base; + + if (spi_base_arg) { + spi_base = spi_base_arg; + } else { + spi_base = (volatile SPI *) map_physical_memory(g_spi_addr, PAGE_SIZE); + } + + amd_spi_write_enable(spi_base); + + amd_spi_clear_fifo_ptr(spi_base); + + // Write address to read from into FIFO + spi_base->SPI_Cntrl1.SpiParamters = (address >> 16) & 0xFF; + spi_base->SPI_Cntrl1.SpiParamters = (address >> 8) & 0xFF; + spi_base->SPI_Cntrl1.SpiParamters = address & 0xFF; + + spi_base->CmdCode = SPI_SECTOR_ERASE_OP; + + // Set RX Byte Count + spi_base->RxByteCnt = 0; + + // Set Tx Byte Count + spi_base->TxByteCnt = 3; + + amd_spi_execute_command(spi_base); + + if (!spi_base_arg) { + unmap_physical_memory((void *) spi_base, PAGE_SIZE); + } +} + + +void read_block_index_mode(volatile SPI *spi_base, UINT32 addr, BYTE *block) { + /* + * Reads 64 byte block from flash + */ + + amd_spi_clear_fifo_ptr(spi_base); + + // Write address to read from into FIFO + spi_base->SPI_Cntrl1.SpiParamters = (addr >> 16) & 0xFF; + spi_base->SPI_Cntrl1.SpiParamters = (addr >> 8) & 0xFF; + spi_base->SPI_Cntrl1.SpiParamters = addr & 0xFF; + + // Set Read Opcode + spi_base->CmdCode = SPI_READ_OP; + + // Set TX Byte Count (address is 24 bits) + spi_base->TxByteCnt = 3; + + // Set RX for the block + spi_base->RxByteCnt = SPI_INDEX_MODE_READ_BLOCK_SIZE; + + amd_spi_execute_command(spi_base); + + memcpy(block, (void *) spi_base->FIFO, SPI_INDEX_MODE_READ_BLOCK_SIZE); + +} + +void read_from_flash_index_mode(volatile SPI *spi_base_arg, UINT32 start_offset, + UINT32 length, BYTE *out_buff) +{ + + if (bSpiInformationInitialized == 0) { + debug_print("SPI Information not retrieved: cannot read from SPI flash - index mode\n"); + return; + } + + if (start_offset > FLASH_SIZE + || (start_offset + length) > FLASH_SIZE + || (start_offset + length) < start_offset + || out_buff == NULL) + { + printf("invalid parameters for read_from_flash_index_mode\n"); + return; + } + + volatile SPI *spi_base; + if (spi_base_arg) { + spi_base = spi_base_arg; + } else { + spi_base = (volatile SPI *) map_physical_memory(g_spi_addr, PAGE_SIZE); + } + + int num_blocks = length >> SPI_INDEX_MODE_READ_BLOCK_BITS; + num_blocks += (length & SPI_INDEX_MODE_READ_BLOCK_MASK) ? 1 : 0; + + // align start address + UINT32 aligned_addr = start_offset & ~SPI_INDEX_MODE_READ_BLOCK_MASK; + UINT32 offset = start_offset & SPI_INDEX_MODE_READ_BLOCK_MASK; + + BYTE block[SPI_INDEX_MODE_READ_BLOCK_SIZE]; + + BYTE *pBuff = out_buff; + + // Remaining length + UINT32 rlength = length; + + //printf("Processing %d blocks\n", num_blocks); + for (int i = 0 ; i < num_blocks; i++) { + UINT32 addr = aligned_addr + i * SPI_INDEX_MODE_READ_BLOCK_SIZE; + //memset(block, 0x00, SPI_INDEX_MODE_READ_BLOCK_SIZE); + read_block_index_mode(spi_base, addr, block); + + printf("reading block:[%d] - addr: %08x\n", i, addr); + + // Handle first block + if (i == 0) { + memcpy(pBuff, &block[offset], SPI_INDEX_MODE_READ_BLOCK_SIZE - offset); + pBuff += SPI_INDEX_MODE_READ_BLOCK_SIZE - offset; + rlength -= SPI_INDEX_MODE_READ_BLOCK_SIZE - offset; + continue; + } + + // Handle last block + if (i == num_blocks - 1) { + memcpy(pBuff, block, rlength); + pBuff += rlength; + continue; + } + + // Handle middle blocks + memcpy(pBuff, block, SPI_INDEX_MODE_READ_BLOCK_SIZE); + pBuff += SPI_INDEX_MODE_READ_BLOCK_SIZE; + rlength -= SPI_INDEX_MODE_READ_BLOCK_SIZE; + } + + if ( (UINT32 )(pBuff - out_buff) != length) { + printf("Error during SPI block copy\n"); + } + + if (!spi_base_arg) { + unmap_physical_memory((void *) spi_base, PAGE_SIZE); + } +} + +void amd_dump_spi_flash_index_mode(const char *output_filename) { + + char *rom_data = (char *) calloc(1, FLASH_SIZE); + read_from_flash_index_mode(NULL, 0, FLASH_SIZE, (BYTE *) rom_data); + + FILE *f = fopen(output_filename, "wb"); + fwrite(rom_data, FLASH_SIZE, 1, f); + fclose(f); + + free(rom_data); +} + + +void write_block_index_mode(volatile SPI *spi_base, UINT32 addr, BYTE *block) { + /* + * Writes a 8 byte block into flash + */ + + #ifdef __linux__ + usleep(200); + #else + Sleep(200); + #endif + + amd_spi_write_enable(spi_base); + + amd_spi_clear_fifo_ptr(spi_base); + + // Write address to read from into FIFO + spi_base->SPI_Cntrl1.SpiParamters = (addr >> 16) & 0xFF; + spi_base->SPI_Cntrl1.SpiParamters = (addr >> 8) & 0xFF; + spi_base->SPI_Cntrl1.SpiParamters = addr & 0xFF; + + + for (int i = 0; i < SPI_INDEX_MODE_WRITE_BLOCK_FIFO; i++) { + spi_base->SPI_Cntrl1.SpiParamters = block[i]; + } + + // Set Write Opcode + spi_base->CmdCode = SPI_WRITE_BYTE_OP; + + // Set TX Byte Count (address is 24 bits) + spi_base->TxByteCnt = 3 + SPI_INDEX_MODE_WRITE_BLOCK_FIFO; + + // Set RX for the block + spi_base->RxByteCnt = 0; + + amd_spi_execute_command(spi_base); + + printf("Writing 8 bytes into address: %08x\n", addr); + +} + + +void write_4k_block(volatile SPI *spi_base, UINT32 addr, BYTE *block) { + // This function simply calls write_block_index_mode in blocks of 8 bytes + // 4K / 8 => 512 calls + UINT32 iterations = SPI_INDEX_MODE_WRITE_BLOCK_4K / SPI_INDEX_MODE_WRITE_BLOCK_FIFO; + for (int i = 0; i < iterations; i++) { + UINT32 cur_addr = addr + i * SPI_INDEX_MODE_WRITE_BLOCK_FIFO; + write_block_index_mode(spi_base, cur_addr, &block[i * SPI_INDEX_MODE_WRITE_BLOCK_FIFO]); + } +} + +void amd_spi_write_buffer(volatile SPI *spi_base_arg, UINT32 flash_address, BYTE *in_buff, UINT32 in_length) +{ + if (bSpiInformationInitialized == 0) { + debug_print("SPI Information not retrieved: cannot write to SPI flash - index mode\n"); + return; + } + + if (flash_address > FLASH_SIZE + || (flash_address + in_length) > FLASH_SIZE + || (flash_address + in_length) < flash_address + || in_buff == NULL) + { + printf("invalid parameters for amd_spi_write_buffer\n"); + return; + } + + volatile SPI *spi_base; + if (spi_base_arg) { + spi_base = spi_base_arg; + } else { + spi_base = (volatile SPI *) map_physical_memory(g_spi_addr, PAGE_SIZE); + } + + // Write happens in blocks of 4KB + int num_blocks = in_length >> SPI_INDEX_MODE_WRITE_BLOCK_BITS; + num_blocks += (in_length & SPI_INDEX_MODE_WRITE_BLOCK_MASK) ? 1 : 0; + + // align start address + UINT32 aligned_addr = flash_address & ~SPI_INDEX_MODE_WRITE_BLOCK_MASK; + UINT32 offset = flash_address & SPI_INDEX_MODE_WRITE_BLOCK_MASK; + + BYTE *block = (BYTE *) malloc(SPI_INDEX_MODE_WRITE_BLOCK_4K); + + BYTE *pBuff = in_buff; + + // Remaining length + UINT32 rlength = in_length; + + // Read the content of the block first + for (int i = 0; i < num_blocks; i++) { + UINT32 addr = aligned_addr + i * SPI_INDEX_MODE_WRITE_BLOCK_4K; + read_from_flash_index_mode(spi_base, addr, SPI_INDEX_MODE_WRITE_BLOCK_4K, block); + + // Apply changes in the block + + // Handle first block + if (i == 0) { + if (in_length < (SPI_INDEX_MODE_WRITE_BLOCK_4K - offset)) { + memcpy(&block[offset], pBuff, in_length); + pBuff += in_length; + rlength -= in_length; + } else { + memcpy(&block[offset], pBuff, SPI_INDEX_MODE_WRITE_BLOCK_4K - offset); + pBuff += SPI_INDEX_MODE_WRITE_BLOCK_4K - offset; + rlength -= SPI_INDEX_MODE_WRITE_BLOCK_4K - offset; + } + } + // Handle last block + else if (i == num_blocks - 1) { + memcpy(block, pBuff, rlength); + pBuff += rlength; + continue; + + } + // Handle middle blocks + else { + memcpy(block, pBuff, SPI_INDEX_MODE_WRITE_BLOCK_4K); + pBuff += SPI_INDEX_MODE_WRITE_BLOCK_4K; + rlength -= SPI_INDEX_MODE_WRITE_BLOCK_4K; + } + + // At this point, the block was modified, we now need to write it + + // Erase first + amd_spi_erase_4k_block(spi_base, addr); + + // Write + write_4k_block(spi_base, addr, block); + //print_memory(0, (char *) block, SPI_INDEX_MODE_WRITE_BLOCK_4K); + + } + + if ( (UINT32 )(pBuff - in_buff) != in_length) { + printf("Error during SPI block copy\n"); + } + + ////// + + free(block); + + if (!spi_base_arg) { + unmap_physical_memory((void *) spi_base, PAGE_SIZE); + } +} \ No newline at end of file diff --git a/PlatboxClient/src/common_chipset.cpp b/PlatboxLib/src/common_chipset.cpp similarity index 68% rename from PlatboxClient/src/common_chipset.cpp rename to PlatboxLib/src/common_chipset.cpp index 1c9209d..72ab0ba 100644 --- a/PlatboxClient/src/common_chipset.cpp +++ b/PlatboxLib/src/common_chipset.cpp @@ -2,7 +2,6 @@ int get_processor_type() { - #ifdef __linux__ UINT32 eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -34,6 +33,28 @@ int get_processor_type() { } +void get_processor_model(BYTE *family, BYTE *model) { + +#ifdef __linux__ + UINT32 eax = 0, ebx = 0, ecx = 0, edx = 0; + + __get_cpuid(1, &eax, &ebx, &ecx, &edx); + *family = ((eax >> 20) & 0x000000FF) + ((eax >> 8) & 0x0000000F); + *model = (((eax >> 16) & 0x0000000F) << 4) + ((eax >> 4) & 0x0000000F); + + +#else // _WIN32 + int regs[4] = { 0 }; + + __cpuidex(®s[0], 1, 0); + *family = ((regs[0] >> 20) & 0x000000FF) + ((regs[0] >> 8) & 0x0000000F); + *model = (((regs[0] >> 16) & 0x0000000F) << 4) + ((regs[0] >> 4) & 0x0000000F); + + +#endif +} + + void dump_spi_flash(const char *output_filename) { switch(get_processor_type()) { case _INTEL_PROCESSOR: @@ -51,7 +72,15 @@ void get_chipset_information() { intel_get_chipset_information(); break; case _AMD_PROCESSOR: - amd_get_chipset_information(); + + BYTE family, model = 0; + get_processor_model(&family, &model); + printf("Detected chipset:\n"); + printf("=> Family: %02x\n", family); + printf("=> Model: %02x\n", model); + printf("\n"); + + amd_print_chipset_information(); break; } } @@ -65,4 +94,4 @@ void get_tseg_region(UINT64 *base, UINT32 *size) { get_tseg_info(base, size); break; } -} \ No newline at end of file +} diff --git a/PlatboxLib/src/global.cpp b/PlatboxLib/src/global.cpp new file mode 100644 index 0000000..b2d2b37 --- /dev/null +++ b/PlatboxLib/src/global.cpp @@ -0,0 +1,349 @@ +#include "global.h" + +HANDLE g_hDevice = 0; + +int DEBUG_MODE = 0; + +void debug_print(const char *fmt, ...) { + if (DEBUG_MODE) { + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } +} + +int _prev_debug_mode = 0; +void enable_debug_mode() { + _prev_debug_mode = DEBUG_MODE; + DEBUG_MODE = 1; +} + +void restore_debug_mode() { + DEBUG_MODE = _prev_debug_mode; +} + +char _aux_print_buff[2048]; + +void print_green(const char *fmt, ...) { + #ifdef _WIN32 + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN); + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + #else + + memset(_aux_print_buff, 0x00, sizeof(_aux_print_buff)); + snprintf(_aux_print_buff, sizeof(_aux_print_buff), "\x1b[32m%s\x1b[0m", fmt); + + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, _aux_print_buff, ap); + va_end(ap); + + #endif +} + +void print_red(const char *fmt, ...) { + #ifdef _WIN32 + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + + SetConsoleTextAttribute(hConsole, FOREGROUND_RED); + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + #else + + memset(_aux_print_buff, 0x00, sizeof(_aux_print_buff)); + snprintf(_aux_print_buff, sizeof(_aux_print_buff), "\x1b[31m%s\x1b[0m", fmt); + + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, _aux_print_buff, ap); + va_end(ap); + + #endif +} + + +#pragma comment(lib, "DeltaFuzzLib.lib") + +FUZZER_OBJECT *g_fuzzer; +PCI_ECAM g_pci_ecam; + + + + +void InitializeDeltaFuzz() { + CreateFuzzerObject(&g_fuzzer, 0, TRUE, FALSE); +} + + +void open_platbox_device() { + #ifdef __linux__ + char device_name[256]; + memset(device_name, 0x00, sizeof(device_name)); + sprintf(device_name, "/dev/%s0", KERNETIX_DEVICE_NAME); + int fd = open(device_name, O_RDWR); + if (fd < 0) + { + printf("Can't open device file: %s\n", device_name); + exit(-1); + } + printf("%s opened successfully: %d\n", device_name, fd); + g_hDevice = fd; + + #else // _WIN32 + HANDLE h = CreateFileW( + L"\\\\.\\PlatboxDev", + FILE_READ_ACCESS | FILE_WRITE_ACCESS, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if (h == NULL || (int)h == -1) { + printf("Error: %08x\n", GetLastError()); + printf("Check Platbox driver is loaded!\n"); + exit(-1); + } + + g_hDevice = h; + + #endif + +} + +void close_platbox_device() { + #ifdef __linux__ + close(g_hDevice); + #else // _WIN32 + CloseHandle(g_hDevice); + #endif +} + + + +void start_service() { + #ifdef __linux__ + printf("start_service Unimplemented!"); + exit(-1); + + #else // _WIN32 + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + + if (!hSCM) { + printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); + return; + } + + SC_HANDLE hSvc = OpenServiceA(hSCM, SVC_NAME, SERVICE_START | DELETE | SERVICE_STOP); + + if (hSvc == NULL) { + printf("-> could not open service %s - error: %08x\n", SVC_NAME, GetLastError()); + } + else { + get_more_privileges(); + + if (StartServiceA(hSvc, 0, NULL)) { + printf("-> service started successfully!\n"); + } + else { + DWORD error = GetLastError(); + if (error == ERROR_SERVICE_ALREADY_RUNNING) { + printf("-> service has already been started!\n"); + } + else { + printf("-> could not start service %s - error: %08x\n", SVC_NAME, error); + } + } + + CloseServiceHandle(hSCM); + } + + CloseServiceHandle(hSCM); + #endif +} + +char service_exe[512]; +void install_driver(char *driverNameArg) { + memset(service_exe, 0x00, sizeof(service_exe)); + + #ifdef __linux__ + printf("install_driver Unimplemented!"); + exit(-1); + + #else // _WIN32 + + char driverName[128] = "\\Platbox.sys"; + + char *pServiceExe = &service_exe[0]; + + if (driverNameArg != NULL) { + pServiceExe = driverNameArg; + } else { + GetCurrentDirectoryA(sizeof(service_exe), pServiceExe); + strcat(pServiceExe, driverName); + } + + get_more_privileges(); + + printf("-> About to install the service: %s\n", pServiceExe); + + + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + + if (!hSCM) { + printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); + return; + } + + + SC_HANDLE hSvc = CreateServiceA( + hSCM, + SVC_NAME, + SVC_NAME, + SERVICE_START | DELETE | SERVICE_STOP, + SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, + SERVICE_ERROR_IGNORE, + pServiceExe, + NULL, + NULL, + NULL, + NULL, + NULL + ); + + + if (hSvc == NULL) { + DWORD error_code = GetLastError(); + if (error_code == ERROR_SERVICE_EXISTS) { + start_service(); + } + else { + printf("-> error creating the service - error: %08x\n", error_code); + } + } + else { + SERVICE_STATUS status; + if (QueryServiceStatus(hSvc, &status)) { + if (status.dwCurrentState == SERVICE_RUNNING) { + printf("-> %s service created and started successfully!\n", SVC_NAME); + } + } + CloseServiceHandle(hSvc); + } + + CloseServiceHandle(hSCM); + + + #endif +} + +void stop_service() { + #ifdef __linux__ + printf("stop_service Unimplemented!"); + exit(-1); + + #else // _WIN32 + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + + if (!hSCM) { + printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); + return; + } + + SC_HANDLE hSvc = OpenServiceA(hSCM, SVC_NAME, SERVICE_ALL_ACCESS); + SERVICE_STATUS status; + if (ControlService(hSvc, SERVICE_CONTROL_STOP, &status)) { + printf("-> service stopped successfully!\n"); + } + else { + printf("-> error stopping service: %08x\n", GetLastError()); + } + + CloseServiceHandle(hSvc); + CloseServiceHandle(hSCM); + + #endif +} + +void remove_driver() { + #ifdef __linux__ + printf("remove_driver Unimplemented!"); + exit(-1); + + #else // _WIN32 + SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); + + if (!hSCM) { + printf("-> OpenSCManager failed! error: %08x\n", GetLastError()); + return; + } + + SC_HANDLE hSvc = OpenServiceA(hSCM, SVC_NAME, SERVICE_START | DELETE | SERVICE_STOP); + + if (hSvc == NULL) { + printf("-> service can't be opened - error: %08x\n", GetLastError()); + } + else { + if (DeleteService(hSvc)) { + printf("-> %s service was removed successfully\n", SVC_NAME); + } + else { + printf("-> service can't be removed - error: %08x\n", GetLastError()); + } + CloseServiceHandle(hSvc); + } + CloseServiceHandle(hSCM); + + #endif +} + +// char _ret_shellcode[] = { +// //"\xc3" // ret +// "\x53\x56\x57\xFA\x48\x31\xC9\x48\xC7\xC2\x0F\x00\x00\x00\x4D\x31" +// "\xC0\x48\x31\xC0\xB0\x01\xC1\xE0\x1F\xC1\xE1\x10\xC1\xE2\x0B\x41" +// "\xC1\xE0\x08\x09\xC8\x09\xD0\x44\x09\xC0\x48\x89\xC3\x48\x8B\x7C" +// "\x24\x40\xCC\x48\x31\xC9\x48\xF7\xD1\x48\xFF\xC1\x48\x89\xC8\xC1" +// "\xE0\x02\x09\xD8\x66\xBA\xF8\x0C\xEF\x48\x31\xC0\x66\xBA\xFC\x0C" +// "\xED\x89\x04\x8F\x80\xF9\x40\x75\xE0\xFB\x5F\x5E\x5B\xC3" +// }; + +// void execute_shellcode() { +// DWORD bytesReturned = 0; + +// char *shellcode = &_ret_shellcode[0]; +// int size = 0x200; + +// #ifdef __linux__ +// printf("execute_shellcode Unimplemented!"); +// #elif _WIN32 +// NTSTATUS status; +// status = DeviceIoControl(g_hDevice, IOCTL_EXECUTE_SHELLCODE, shellcode, size, NULL, 0, &bytesReturned, NULL); +// #else +// #endif + +// } + +void init_os_specifics() { + #ifdef _WIN32 + /* Set white foregorund*/ + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + + resolve_nt_functions(); + find_pml4_idx(); + #endif +} \ No newline at end of file diff --git a/PlatboxClient/src/intel/intel_chipset.cpp b/PlatboxLib/src/intel/intel_chipset.cpp similarity index 85% rename from PlatboxClient/src/intel/intel_chipset.cpp rename to PlatboxLib/src/intel/intel_chipset.cpp index 9884329..5a9ed60 100644 --- a/PlatboxClient/src/intel/intel_chipset.cpp +++ b/PlatboxLib/src/intel/intel_chipset.cpp @@ -14,11 +14,6 @@ void print_spi_bar_bios_bfpreg(DWORD *p) { printf(" -> PRB (BIOS Flash Primary Region Base): %08x\n", ((_BIOS_BFPREG *)p)->PRB << 12); printf(" -> PRL (BIOS Flash Primary Region Limit): %08x\n", ((_BIOS_BFPREG *)p)->PRL << 12); } -void read_spi_bar_bios_bfpreg(DWORD64 SPIBAR, DWORD *pOut) { - // SPI BIOS MMIO PRI (BIOS_BFPREG) - Offset 0h - DWORD offset = 0; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} void print_spi_bar_hsfs_ctl(DWORD *p) { printf("SPIBAR::_BIOS_HSFSTS_CTL - Hardware Sequencing Flash Status and Control (BIOS_HSFSTS_CTL) - Offset 4h\n"); @@ -28,22 +23,12 @@ void print_spi_bar_hsfs_ctl(DWORD *p) { printf(" -> PRR34_LOCKDN (PRR3 PRR4 Lock-Down): %02x\n", ((_BIOS_HSFSTS_CTL *)p)->PRR34_LOCKDN); printf(" -> FLOCKDN (Flash Configuration Lock-Down): %02x\n", ((_BIOS_HSFSTS_CTL *)p)->FLOCKDN); } -void read_spi_bar_hsfs_ctl(DWORD64 SPIBAR, DWORD *pOut) { - // Hardware Sequencing Flash Status and Control (BIOS_HSFSTS_CTL) - Offset 4h - DWORD offset = 4; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} void print_spi_bar_faddr(DWORD *p) { printf("SPIBAR::_BIOS_FADDR - Flash Address (BIOS_FADDR) - Offset 8h\n"); printf(" => Value: %08x\n", *p); printf(" -> FLA (Flash Linear Address): %08x\n", ((_BIOS_FADDR *)p)->FLA); } -void read_spi_bar_faddr(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Address (BIOS_FADDR) - Offset 8h - DWORD offset = 8; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} void print_spi_bar_dlock(DWORD *p) { printf("SPIBAR::_BIOS_DLOCK - Discrete Lock Bits (BIOS_DLOCK) - Offset Ch\n"); @@ -59,11 +44,6 @@ void print_spi_bar_dlock(DWORD *p) { printf(" -> PR4LOCKDN (PR4 Lock-Down): %02x\n", ((_BIOS_DLOCK *)p)->PR4LOCKDN); printf(" -> SSEQLOCKDN (SSEQ Lock-Down): %02x\n", ((_BIOS_DLOCK *)p)->SSEQLOCKDN); } -void read_spi_bar_dlock(DWORD64 SPIBAR, DWORD *pOut) { - // Discrete Lock Bits (BIOS_DLOCK) - Offset Ch - DWORD offset = 0xC; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} void print_spi_bar_freg0(DWORD *p) { printf("SPIBAR::_BIOS_FREG0 - Flash Region 0 (BIOS_FREG0) - Offset 54h\n"); @@ -71,66 +51,41 @@ void print_spi_bar_freg0(DWORD *p) { printf(" -> RB (Region Base): %08x\n", ((_BIOS_FREG *)p)->RB<<12); printf(" -> RL (Region Limit): %08x\n", ((_BIOS_FREG *)p)->RL << 12); } -void read_spi_bar_freg0(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Region 0 (BIOS_FREG0) - Offset 54h - DWORD offset = 0x54; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_freg1(DWORD *p) { printf("SPIBAR::_BIOS_FREG1 - Flash Region 1 (BIOS_FREG1) - Offset 58h\n"); printf(" => Value: %08x\n", *p); printf(" -> RB (Region Base): %08x\n", ((_BIOS_FREG *)p)->RB << 12); printf(" -> RL (Region Limit): %08x\n", ((_BIOS_FREG *)p)->RL << 12); } -void read_spi_bar_freg1(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Region 1 (BIOS_FREG1) - Offset 58h - DWORD offset = 0x58; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_freg2(DWORD *p) { printf("SPIBAR::_BIOS_FREG2 - Flash Region 2 (BIOS_FREG2) - Offset 5Ch\n"); printf(" => Value: %08x\n", *p); printf(" -> RB (Region Base): %08x\n", ((_BIOS_FREG *)p)->RB << 12); printf(" -> RL (Region Limit): %08x\n", ((_BIOS_FREG *)p)->RL << 12); } -void read_spi_bar_freg2(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Region 2 (BIOS_FREG2) - Offset 5Ch - DWORD offset = 0x5C; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_freg3(DWORD *p) { printf("SPIBAR::_BIOS_FREG3 - Flash Region 3 (BIOS_FREG3) - Offset 60h\n"); printf(" => Value: %08x\n", *p); printf(" -> RB (Region Base): %08x\n", ((_BIOS_FREG *)p)->RB << 12); printf(" -> RL (Region Limit): %08x\n", ((_BIOS_FREG *)p)->RL << 12); } -void read_spi_bar_freg3(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Region 3 (BIOS_FREG3) - Offset 60h - DWORD offset = 0x60; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_freg4(DWORD *p) { printf("SPIBAR::_BIOS_FREG4 - Flash Region 4 (BIOS_FREG4) - Offset 64h\n"); printf(" => Value: %08x\n", *p); printf(" -> RB (Region Base): %08x\n", ((_BIOS_FREG *)p)->RB << 12); printf(" -> RL (Region Limit): %08x\n", ((_BIOS_FREG *)p)->RL << 12); } -void read_spi_bar_freg4(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Region 4 (BIOS_FREG4) - Offset 64h - DWORD offset = 0x64; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_freg5(DWORD *p) { printf("SPIBAR::_BIOS_FREG5 - Flash Region 5 (BIOS_FREG5) - Offset 68h\n"); printf(" => Value: %08x\n", *p); printf(" -> RB (Region Base): %08x\n", ((_BIOS_FREG *)p)->RB << 12); printf(" -> RL (Region Limit): %08x\n", ((_BIOS_FREG *)p)->RL << 12); } -void read_spi_bar_freg5(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Region 5 (BIOS_FREG5) - Offset 68h - DWORD offset = 0x68; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} void print_spi_bar_fpr0(DWORD *p) { printf("SPIBAR::_BIOS_FPR0 - Flash Protected Range 0 (BIOS_FPR0) - Offset 84h\n"); @@ -140,11 +95,7 @@ void print_spi_bar_fpr0(DWORD *p) { printf(" -> RPE (Read Protection Enable): %s\n", ((_BIOS_FPR *)p)->RPE ? "TRUE" : "FALSE"); printf(" -> WPE (Write Protection Enable): %s\n", ((_BIOS_FPR *)p)->WPE ? "TRUE" : "FALSE"); } -void read_spi_bar_fpr0(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Protected Range 0 (BIOS_FPR0) - Offset 84h - DWORD offset = 0x84; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_fpr1(DWORD *p) { printf("SPIBAR::_BIOS_FPR1 - Flash Protected Range 1 (BIOS_FPR1) - Offset 88h\n"); printf(" => Value: %08x\n", *p); @@ -153,11 +104,7 @@ void print_spi_bar_fpr1(DWORD *p) { printf(" -> RPE (Read Protection Enable): %s\n", ((_BIOS_FPR *)p)->RPE ? "TRUE" : "FALSE"); printf(" -> WPE (Write Protection Enable): %s\n", ((_BIOS_FPR *)p)->WPE ? "TRUE" : "FALSE"); } -void read_spi_bar_fpr1(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Protected Range 1 (BIOS_FPR1) - Offset 88h - DWORD offset = 0x88; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_fpr2(DWORD *p) { printf("SPIBAR::_BIOS_FPR2 - Flash Protected Range 2 (BIOS_FPR2) - Offset 8Ch\n"); printf(" => Value: %08x\n", *p); @@ -166,11 +113,7 @@ void print_spi_bar_fpr2(DWORD *p) { printf(" -> RPE (Read Protection Enable): %s\n", ((_BIOS_FPR *)p)->RPE ? "TRUE" : "FALSE"); printf(" -> WPE (Write Protection Enable): %s\n", ((_BIOS_FPR *)p)->WPE ? "TRUE" : "FALSE"); } -void read_spi_bar_fpr2(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Protected Range 2 (BIOS_FPR2) - Offset 8Ch - DWORD offset = 0x8C; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_fpr3(DWORD *p) { printf("SPIBAR::_BIOS_FPR3 - Flash Protected Range 3 (BIOS_FPR3) - Offset 90h\n"); printf(" => Value: %08x\n", *p); @@ -179,11 +122,7 @@ void print_spi_bar_fpr3(DWORD *p) { printf(" -> RPE (Read Protection Enable): %s\n", ((_BIOS_FPR *)p)->RPE ? "TRUE" : "FALSE"); printf(" -> WPE (Write Protection Enable): %s\n", ((_BIOS_FPR *)p)->WPE ? "TRUE" : "FALSE"); } -void read_spi_bar_fpr3(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Protected Range 3 (BIOS_FPR3) - Offset 90h - DWORD offset = 0x90; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + void print_spi_bar_fpr4(DWORD *p) { printf("SPIBAR::_BIOS_FPR4 - Flash Protected Range 4 (BIOS_FPR4) - Offset 94h\n"); printf(" => Value: %08x\n", *p); @@ -192,11 +131,7 @@ void print_spi_bar_fpr4(DWORD *p) { printf(" -> RPE (Read Protection Enable): %s\n", ((_BIOS_FPR *)p)->RPE ? "TRUE" : "FALSE"); printf(" -> WPE (Write Protection Enable): %s\n", ((_BIOS_FPR *)p)->WPE ? "TRUE" : "FALSE"); } -void read_spi_bar_fpr4(DWORD64 SPIBAR, DWORD *pOut) { - // Flash Protected Range 4 (BIOS_FPR4) - Offset 94h - DWORD offset = 0x94; - read_physical_memory(SPIBAR + offset, 4, pOut, FALSE); -} + ////////////////////////////////////////////////////// // SPI Interface B0:D31:F5 Registers @@ -210,7 +145,8 @@ void print_spi_interface_bar0_mmio(DWORD *p) { void read_spi_interface_bar0_mmio(DWORD *pBar0Mmio) { // SPI BAR0 MMIO (BIOS_SPI_BAR0) UINT32 offset1 = 0x10; - *pBar0Mmio = read_pci_dword(0, 31, 5, offset1); + *pBar0Mmio = read_pci_dword(0, 31, 5, offset1/sizeof(DWORD)); + debug_print("read_spi_interface_bar0_mmio -> %08x\n", *pBar0Mmio); } void print_spi_interface_bios_decode_enable(DWORD *p) { @@ -234,7 +170,7 @@ void print_spi_interface_bios_decode_enable(DWORD *p) { void read_spi_interface_bios_decode_enable(DWORD *pBiosSpiBDE) { // BIOS Decode Enable (BIOS_SPI_BDE) UINT32 offset1 = 0xD8; - *pBiosSpiBDE = read_pci_dword(0, 31, 5, offset1); + *pBiosSpiBDE = read_pci_dword(0, 31, 5, offset1/sizeof(DWORD)); } void print_spi_interface_bios_control(DWORD *p) { @@ -255,7 +191,7 @@ void print_spi_interface_bios_control(DWORD *p) { void read_spi_interface_bios_control(DWORD *pBiosCtl) { // UINT32 offset1 = 0xDC; - *pBiosCtl = read_pci_dword(0, 31, 5, offset1); + *pBiosCtl = read_pci_dword(0, 31, 5, offset1/sizeof(DWORD)); } ////////////////////////////////////////////////////// @@ -272,7 +208,7 @@ void print_pmc_acpi_base_address(DWORD *p) { void read_pmc_acpi_base_address(DWORD *pAcpiBase) { // ACPI Base Address (ABASE) UINT32 offset1 = 0x40; - *pAcpiBase = read_pci_dword(0, 31, 2, offset1); + *pAcpiBase = read_pci_dword(0, 31, 2, offset1/sizeof(DWORD)); } void print_pmc_acpi_control(DWORD *p) { @@ -284,7 +220,7 @@ void print_pmc_acpi_control(DWORD *p) { void read_pmc_acpi_control(DWORD *pAcpiControl) { // ACPI Control (ACTL) UINT32 offset1 = 0x44; - *pAcpiControl = read_pci_dword(0, 31, 2, offset1); + *pAcpiControl = read_pci_dword(0, 31, 2, offset1/sizeof(DWORD)); } void print_pmc_pm_base_address(DWORD *p) { @@ -296,7 +232,7 @@ void print_pmc_pm_base_address(DWORD *p) { void read_pmc_pm_base_address(DWORD *pPmBaseAddress) { // PM Base Address (PWRMBASE) UINT32 offset1 = 0x48; - *pPmBaseAddress = read_pci_dword(0, 31, 2, offset1); + *pPmBaseAddress = read_pci_dword(0, 31, 2, offset1/sizeof(DWORD)); } //////////////////////////////////////////////////////// @@ -313,8 +249,8 @@ void read_hostbridge_pxpepbar(DWORD64 *pPxpepbar) { // PCI Express* Egress Port Base Address (PXPEPBAR) UINT32 offset1 = 0x40; UINT32 offset2 = 0x44; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pPxpepbar = (high << 0x20) | low; } @@ -329,8 +265,8 @@ void read_hostbridge_mchbar(DWORD64 *pMchbar) { // Host Memory Mapped Register Range Base (MCHBAR) UINT32 offset1 = 0x48; UINT32 offset2 = 0x4C; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pMchbar = (high << 0x20) | low; } @@ -402,7 +338,7 @@ void print_gmch(WORD *p) { void read_hostbridge_gmch(WORD *pGmch) { // GMCH Graphics Control Register (GGC) UINT32 offset1 = 0x50; - *pGmch = read_pci_word(0, 0, 0, offset1); + *pGmch = read_pci_word(0, 0, 0, offset1/2); } void print_deven(DWORD *p) { @@ -422,7 +358,7 @@ void print_deven(DWORD *p) { void read_hostbridge_deven(DWORD *pDeven) { // Device Enable (DEVEN) UINT32 offset1 = 0x54; - *pDeven = read_pci_dword(0, 0, 0, offset1); + *pDeven = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } void print_pavpc(DWORD *p) { @@ -437,7 +373,7 @@ void print_pavpc(DWORD *p) { void read_hostbridge_pavpc(DWORD *pPavpc) { // Protected Audio Video Path Control (PAVPC) UINT32 offset1 = 0x58; - *pPavpc = read_pci_dword(0, 0, 0, offset1); + *pPavpc = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } void print_dpr(DWORD *p) { @@ -452,7 +388,7 @@ void print_dpr(DWORD *p) { void read_hostbridge_dpr(DWORD *pDpr) { // DMA Protected Range (DPR) UINT32 offset1 = 0x5C; - *pDpr = read_pci_dword(0, 0, 0, offset1); + *pDpr = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } void print_pciexbar(DWORD64 *p) { @@ -480,8 +416,8 @@ void read_hostbridge_pciexbar(DWORD64 *pPciexbar) { // PCI Express Register Range Base Address (PCIEXBAR) UINT32 offset1 = 0x60; UINT32 offset2 = 0x64; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pPciexbar = (high << 0x20) | low; } @@ -496,8 +432,8 @@ void read_hostbridge_dmibar(DWORD64 *pDmibar) { // Root Complex Register Range Base Address (DMIBAR) UINT32 offset1 = 0x68; UINT32 offset2 = 0x6C; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pDmibar = (high << 0x20) | low; } @@ -511,8 +447,8 @@ void read_hostbridge_meseg_base(DWORD64 *pMsegBase) { // Manageability Engine Base Address Register (MESEG) UINT32 offset1 = 0x70; UINT32 offset2 = 0x74; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pMsegBase = (high << 0x20) | low; } @@ -528,8 +464,8 @@ void read_hostbridge_meseg_limit(DWORD64 *pMsegLimit) { // Manageability Engine Limit Address Register (MESEG) UINT32 offset1 = 0x78; UINT32 offset2 = 0x7C; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pMsegLimit = (high << 0x20) | low; } @@ -551,7 +487,7 @@ void read_hostbridge_smramc(BYTE *pSmramc) { void print_remapbase(DWORD64 *p) { printf("0:0:0_REMAPBASE - Remap Base Address Register (REMAPBASE)\n"); - printf(" => Value: %px\n", *p); + printf(" => Value: %p\n", *p); printf(" -> REMAPBASE: %08x\n", ((_REMAPBASE *)p)->REMAPBASE<<20); printf(" -> LOCK: %s\n", ((_REMAPBASE *)p)->LOCK ? "TRUE" : "FALSE"); } @@ -560,8 +496,8 @@ void read_hostbridge_remap_base(DWORD64 *pRemapBase) { // Remap Base Address Register (REMAPBASE) UINT32 offset1 = 0x90; UINT32 offset2 = 0x94; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pRemapBase = (high << 0x20) | low; } @@ -576,8 +512,8 @@ void read_hostbridge_remap_limit(DWORD64 *pRemapLimit) { // Remap Limit Address Register (REMAPLIMIT) UINT32 offset1 = 0x98; UINT32 offset2 = 0x9C; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pRemapLimit = (high << 0x20) | low; } @@ -592,8 +528,8 @@ void read_hostbridge_tom(DWORD64 *pTom) { // Top of Memory (TOM) UINT32 offset1 = 0xA0; UINT32 offset2 = 0xA4; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pTom = (high << 0x20) | low; } @@ -608,8 +544,8 @@ void read_hostbridge_touud(DWORD64 *pTouud) { // Top of Upper Usable DRAM (TOUUD) UINT32 offset1 = 0xA8; UINT32 offset2 = 0xAC; - DWORD64 low = read_pci_dword(0, 0, 0, offset1); - DWORD64 high = read_pci_dword(0, 0, 0, offset2); + DWORD64 low = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); + DWORD64 high = read_pci_dword(0, 0, 0, offset2/sizeof(DWORD)); *pTouud = (high << 0x20) | low; } @@ -623,7 +559,7 @@ void print_bdsm(DWORD *p) { void read_hostbridge_bdsm(DWORD *pBdsm) { // Base Data of Stolen Memory (BDSM) UINT32 offset1 = 0xB0; - *pBdsm = read_pci_dword(0, 0, 0, offset1); + *pBdsm = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } void print_bgsm(DWORD *p) { @@ -635,7 +571,7 @@ void print_bgsm(DWORD *p) { void read_hostbridge_bgsm(DWORD *pBgsm) { // Base of GTT Stolen Memory (BGSM) UINT32 offset1 = 0xB4; - *pBgsm = read_pci_dword(0, 0, 0, offset1); + *pBgsm = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } void print_tsegmb(DWORD *p) { @@ -655,7 +591,7 @@ void print_tsegmb(DWORD *p) { void read_hostbridge_tseg(DWORD *pTseg) { // TSEG Memory Base (TSEGMB) UINT32 offset1 = 0xB8; - *pTseg = read_pci_dword(0, 0, 0, offset1); + *pTseg = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } void print_tolud(DWORD *p) { @@ -667,7 +603,7 @@ void print_tolud(DWORD *p) { void read_hostbridge_tolud(DWORD *pTolud) { // Top of Low Usable DRAM (TOLUD) UINT32 offset1 = 0xBC; - *pTolud = read_pci_dword(0, 0, 0, offset1); + *pTolud = read_pci_dword(0, 0, 0, offset1/sizeof(DWORD)); } ////////////////////////////////////////////////////////////// @@ -678,10 +614,10 @@ void get_chipset_id( WORD *PCHVID, WORD *PCHDID) { - DWORD platform = read_pci_dword(0, 0, 0, 0); + DWORD platform = read_pci_dword(0, 0, 0, 0/sizeof(DWORD)); *platformVID = platform & 0xFFFF; *platformDID = platform >> 0x10; - DWORD pch = read_pci_dword(0, 0x1f, 0, 0); + DWORD pch = read_pci_dword(0, 0x1f, 0, 0/sizeof(DWORD)); *PCHVID = pch & 0xFFFF; *PCHDID = pch >> 0x10; } @@ -841,21 +777,27 @@ void intel_get_chipset_information() { read_spi_interface_bios_decode_enable(&BiosSPIBDE); read_spi_interface_bios_control(&BiosCtl); - read_spi_bar_bios_bfpreg((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &BFPREG); - read_spi_bar_hsfs_ctl((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &HSFS_CTL); - read_spi_bar_faddr((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &BIOS_FADDR); - read_spi_bar_dlock((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &BIOS_DLOCK); - read_spi_bar_freg0((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FREG0); - read_spi_bar_freg1((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FREG1); - read_spi_bar_freg2((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FREG2); - read_spi_bar_freg3((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FREG3); - read_spi_bar_freg4((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FREG4); - read_spi_bar_freg5((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FREG5); - read_spi_bar_fpr0((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FPR0); - read_spi_bar_fpr1((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FPR1); - read_spi_bar_fpr2((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FPR2); - read_spi_bar_fpr3((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FPR3); - read_spi_bar_fpr4((DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4, &FPR4); + void *mapped_spi_bar = map_physical_memory(SPIBar0Mmio, PAGE_SIZE); + + BFPREG = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_BFPREG_OFFSET)); + HSFS_CTL = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_HSFSTS_CTL)); + BIOS_FADDR = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FADDR)); + BIOS_DLOCK = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_DLOCK)); + FREG0 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FREG0)); + FREG1 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FREG1)); + FREG2 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FREG2)); + FREG3 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FREG3)); + FREG4 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FREG4)); + FREG5 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FREG5)); + FPR0 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FPR0)); + FPR1 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FPR1)); + FPR2 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FPR2)); + FPR3 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FPR3)); + FPR4 = *((DWORD *) ((volatile char *)mapped_spi_bar + SPI_BIOS_MMIO_BIOS_FPR4)); + + unmap_physical_memory(mapped_spi_bar, PAGE_SIZE); + + printf("-----------------------------------------\n"); printf("ProcessorType: %02x\n", ProcessorType); @@ -971,7 +913,7 @@ int _wait_spi_cycle(volatile _BIOS_HSFSTS_CTL *hsfsts_ctl) { if (hsfsts_ctl->H_AEL == 1 || hsfsts_ctl-> FCERR == 1) { printf("error H_AEL or FCERR -> SPI not ready\n"); - return NULL; + return 0; } return 1; @@ -982,9 +924,12 @@ void intel_dump_spi_flash(const char *output_filename) { DWORD BFPREG = 0; read_spi_interface_bar0_mmio(&SPIBar0Mmio); - DWORD64 SPIBAR_ADDR = (DWORD64)((PCI_BAR *)&SPIBar0Mmio)->BaseAddress << 4; + DWORD64 SPIBAR_ADDR = SPIBar0Mmio; + + // Map the SPIBAR here + char *spi_bar = (char *) map_physical_memory(SPIBAR_ADDR, 0x1000); - read_spi_bar_bios_bfpreg(SPIBAR_ADDR, &BFPREG); + BFPREG = *((DWORD *) ((volatile char *)spi_bar + SPI_BIOS_MMIO_BIOS_BFPREG_OFFSET)); UINT flash_base = ((_BIOS_BFPREG *)&BFPREG)->PRB << 12; UINT flash_limit = ((_BIOS_BFPREG *)&BFPREG)->PRL << 12; @@ -999,8 +944,7 @@ void intel_dump_spi_flash(const char *output_filename) { return; } - // Map the SPIBAR here - char *spi_bar = (char *) map_physical_memory(SPIBAR_ADDR, 0x1000); + if (spi_bar == NULL) { printf(" -> error mapping SPIBAR\n"); } diff --git a/PlatboxClient/src/linux/placeholder b/PlatboxLib/src/linux/placeholder similarity index 100% rename from PlatboxClient/src/linux/placeholder rename to PlatboxLib/src/linux/placeholder diff --git a/PlatboxClient/src/msr.cpp b/PlatboxLib/src/msr.cpp similarity index 100% rename from PlatboxClient/src/msr.cpp rename to PlatboxLib/src/msr.cpp diff --git a/PlatboxClient/src/pci.cpp b/PlatboxLib/src/pci.cpp similarity index 73% rename from PlatboxClient/src/pci.cpp rename to PlatboxLib/src/pci.cpp index 5c07662..3259326 100644 --- a/PlatboxClient/src/pci.cpp +++ b/PlatboxLib/src/pci.cpp @@ -74,15 +74,16 @@ BYTE read_pci_byte(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { unmap_physical_memory(target_addr, 0x1000); } else { - offset = offset >> 2; + NTSTATUS status = 0; + #ifdef __linux__ status = -1; pci_call.result = (UINT64 *) &aux; status = ioctl(g_hDevice, IOCTL_READ_PCI_BYTE, &pci_call); if (status == 0) { debug_print("-> One byte read from %02x:%02x:%02x offset %08xh: %02xh\n", - bus, device, function, offset << 2, aux); + bus, device, function, offset, aux); } #elif _WIN32 DWORD bytesReturned = 0; @@ -93,7 +94,7 @@ BYTE read_pci_byte(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { if (NT_SUCCESS(status)) { debug_print("-> One byte read from %02x:%02x:%02x offset %08xh: %02xh\n", - bus, device, function, offset << 2, aux); + bus, device, function, offset, aux); } #endif } @@ -106,6 +107,8 @@ WORD read_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { pci_call.bus = bus; pci_call.device = device; pci_call.function = function; + + offset <<= 1; pci_call.offset = offset; WORD aux; @@ -127,8 +130,6 @@ WORD read_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { } else { - offset = offset >> 2; - NTSTATUS status; #ifdef __linux__ @@ -137,7 +138,7 @@ WORD read_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { status = ioctl(g_hDevice, IOCTL_READ_PCI_WORD, &pci_call); if (status == 0) { debug_print("-> One word read from %02x:%02x:%02x offset %08xh: %04xh\n", - bus, device, function, offset << 2, aux); + bus, device, function, offset, aux); } #elif _WIN32 DWORD bytesReturned = 0; @@ -147,7 +148,7 @@ WORD read_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { if (NT_SUCCESS(status)) { debug_print("-> One word read from %02x:%02x:%02x offset %08xh: %04xh\n", - bus, device, function, offset << 2, aux); + bus, device, function, offset, aux); } #endif @@ -161,8 +162,10 @@ DWORD read_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { pci_call.bus = bus; pci_call.device = device; pci_call.function = function; - pci_call.offset = offset; - + + offset <<= 2; + pci_call.offset = offset; + DWORD aux; if (offset >= PCI_COMPATIBLE_CONFIG_SPACE_SIZE) { @@ -181,8 +184,6 @@ DWORD read_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { unmap_physical_memory(target_addr, 0x1000); } else { - offset = offset >> 2; - NTSTATUS status; #ifdef __linux__ status = -1; @@ -190,7 +191,7 @@ DWORD read_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { status = ioctl(g_hDevice, IOCTL_READ_PCI_DWORD, &pci_call); if (status == 0) { debug_print("-> One dword read from %02x:%02x:%02x offset %08xh: %08xh\n", - bus, device, function, offset << 2, aux); + bus, device, function, offset, aux); } #elif _WIN32 DWORD bytesReturned = 0; @@ -200,7 +201,7 @@ DWORD read_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { if (NT_SUCCESS(status)) { debug_print("-> One dword read from %02x:%02x:%02x offset %08xh: %08xh\n", - bus, device, function, offset << 2, aux); + bus, device, function, offset, aux); } #endif } @@ -231,8 +232,6 @@ void write_pci_byte(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v } else { - offset = offset >> 2; - NTSTATUS status; #ifdef __linux__ @@ -240,7 +239,7 @@ void write_pci_byte(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v status = ioctl(g_hDevice, IOCTL_WRITE_PCI_BYTE, &pci_call); if (status == 0) { debug_print("-> One byte written into %02x:%02x:%02x offset %08xh: %02xh\n", - bus, device, function, offset << 2, value); + bus, device, function, offset, value); } #elif _WIN32 DWORD bytesReturned = 0; @@ -250,7 +249,7 @@ void write_pci_byte(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v if (NT_SUCCESS(status)) { debug_print("-> One byte written into %02x:%02x:%02x offset %08xh: %02xh\n", - bus, device, function, offset << 2, value); + bus, device, function, offset, value); } #endif } @@ -262,10 +261,12 @@ void write_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v pci_call.bus = bus; pci_call.device = device; pci_call.function = function; + + offset <<= 1; pci_call.offset = offset; pci_call.value = value; - - + + if (offset >= PCI_COMPATIBLE_CONFIG_SPACE_SIZE) { DWORD64 ecam_pa = g_pci_ecam.physaddr; @@ -281,8 +282,6 @@ void write_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v } else { - offset = offset >> 2; - NTSTATUS status; #ifdef __linux__ @@ -290,7 +289,7 @@ void write_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v status = ioctl(g_hDevice, IOCTL_WRITE_PCI_WORD, &pci_call); if (status == 0) { debug_print("-> One byte written into %02x:%02x:%02x offset %08xh: %02xh\n", - bus, device, function, offset << 2, value); + bus, device, function, offset, value); } #elif _WIN32 DWORD bytesReturned = 0; @@ -300,7 +299,7 @@ void write_pci_word(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT v if (NT_SUCCESS(status)) { debug_print("-> One word written into %02x:%02x:%02x offset %08xh: %04xh\n", - bus, device, function, offset << 2, value); + bus, device, function, offset, value); } #endif } @@ -312,6 +311,8 @@ void write_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT pci_call.bus = bus; pci_call.device = device; pci_call.function = function; + + offset <<= 2; pci_call.offset = offset; pci_call.value = value; @@ -331,8 +332,6 @@ void write_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT } else { - offset = offset >> 2; - NTSTATUS status; #ifdef __linux__ @@ -340,7 +339,7 @@ void write_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT status = ioctl(g_hDevice, IOCTL_WRITE_PCI_DWORD, &pci_call); if (status == 0) { debug_print("-> One byte written into %02x:%02x:%02x offset %08xh: %02xh\n", - bus, device, function, offset << 2, value); + bus, device, function, offset, value); } #elif _WIN32 DWORD bytesReturned = 0; @@ -350,7 +349,7 @@ void write_pci_dword(UINT8 bus, UINT8 device, UINT8 function, UINT offset, UINT if (NT_SUCCESS(status)) { debug_print("-> One dword written into %02x:%02x:%02x offset %08xh: %08xh\n", - bus, device, function, offset << 2, value); + bus, device, function, offset, value); } #endif @@ -398,96 +397,3 @@ void read_pci_bar_info(UINT8 bus, UINT8 device, UINT8 function, UINT offset) { } -void parse_bus_device_function(char *line, UINT *bus, UINT *device, UINT *function) { - char **subargs = parse_arguments(line, ':'); - int subargc = (int)(size_t)subargs[0]; - subargc--; - if (subargc == 3) { - *bus = strtoul(subargs[1], NULL, 10); - *device = strtoul(subargs[2], NULL, 10); - *function = strtoul(subargs[3], NULL, 10); - } - free(subargs); -} - -void parse_handle_pci_operation(int argc, char **argv) { - // pci r 0:2:0 -> reads the configuration space - // pci rb 0:2:0 1 -> reads a byte from offset - // pci rw 0:2:0 1 -> reads a word from offset 1*4 - // pci rd 0:2:0 1 -> reads a dword from offset 1*4 - // pci wb 0:2:0 1 0x90 -> writes a byte to offset 1*4 - // pci ww 0:2:0 1 0x9090 -> writes a word to offset 1*4 - // pci wd 0:2:0 1 0x90909090 -> writes a dword to offset 1*4 - // pci r bar 0:2:0 0x10 -> read BAR info at offset 0x10 - UINT bus, device, function = 0; - UINT offset = 0; - UINT value = 0; - if (!strcmp(argv[1], "r")) { - if (argc == 3) { - parse_bus_device_function(argv[2], &bus, &device, &function); - read_pci_header(bus, device, function); - } - else if (argc == 5 && !strcmp(argv[2], "bar")) { - parse_bus_device_function(argv[3], &bus, &device, &function); - offset = strtoul(argv[4], NULL, 16); - read_pci_bar_info(bus, device, function, offset >> 2); - } - } - else if (!strcmp(argv[1], "rb")) { - if (argc == 4) { - parse_bus_device_function(argv[2], &bus, &device, &function); - offset = strtoul(argv[3], NULL, 16); - enable_debug_mode(); - read_pci_byte(bus, device, function, offset); - restore_debug_mode(); - } - } - else if (!strcmp(argv[1], "rw")) { - if (argc == 4) { - parse_bus_device_function(argv[2], &bus, &device, &function); - offset = strtoul(argv[3], NULL, 16); - enable_debug_mode(); - read_pci_word(bus, device, function, offset); - restore_debug_mode(); - } - } - else if (!strcmp(argv[1], "rd")) { - if (argc == 4) { - parse_bus_device_function(argv[2], &bus, &device, &function); - offset = strtoul(argv[3], NULL, 16); - enable_debug_mode(); - read_pci_dword(bus, device, function, offset); - restore_debug_mode(); - } - } - else if (!strcmp(argv[1], "wb")) { - if (argc == 5) { - parse_bus_device_function(argv[2], &bus, &device, &function); - offset = strtoul(argv[3], NULL, 16); - value = strtoul(argv[4], NULL, 16); - enable_debug_mode(); - write_pci_byte(bus, device, function, offset, value); - restore_debug_mode(); - } - } - else if (!strcmp(argv[1], "ww")) { - if (argc == 5) { - parse_bus_device_function(argv[2], &bus, &device, &function); - offset = strtoul(argv[3], NULL, 16); - value = strtoul(argv[4], NULL, 16); - enable_debug_mode(); - write_pci_word(bus, device, function, offset, value); - restore_debug_mode(); - } - } - else if (!strcmp(argv[1], "wd")) { - if (argc == 5) { - parse_bus_device_function(argv[2], &bus, &device, &function); - offset = strtoul(argv[3], NULL, 16); - value = strtoul(argv[4], NULL, 16); - enable_debug_mode(); - write_pci_dword(bus, device, function, offset, value); - restore_debug_mode(); - } - } -} \ No newline at end of file diff --git a/PlatboxClient/src/physmem.cpp b/PlatboxLib/src/physmem.cpp similarity index 88% rename from PlatboxClient/src/physmem.cpp rename to PlatboxLib/src/physmem.cpp index 2834ecf..ac9b1a7 100644 --- a/PlatboxClient/src/physmem.cpp +++ b/PlatboxLib/src/physmem.cpp @@ -7,9 +7,6 @@ using namespace std; struct wrap_efi_memmap g_EFI_memmap; - - - void * map_physical_memory(UINT64 address, UINT32 size) { #ifdef __linux__ @@ -249,10 +246,6 @@ void read_physical_memory(UINT64 address, UINT32 size, PVOID buffer, BOOL bPrint void read_physical_memory_into_file(UINT64 address, UINT32 size, const char *filename) { - char filepath[2048] = { 0 }; - //GetCurrentDirectoryA(sizeof(filepath), filepath); - strcat(filepath, "\\"); - strcat(filepath, filename); FILE *f = fopen(filename, "wb"); #ifdef __linux__ @@ -364,83 +357,7 @@ void write_byte_physical_memory(UINT64 address, UINT32 value) { } } -void parse_handle_physmem_operation(int argc, char **argv) { - // physmem r 0x000000 0x100--> reads 0x100 bytes from physical address 0 - if (!strcmp(argv[1], "r")) { - if (argc == 4) { - UINT64 address = strtoull(argv[2], NULL, 16); - UINT32 size = strtoul(argv[3], NULL, 16); - read_physical_memory(address, size, NULL, TRUE); - } - if (argc == 5) { - // physmem r 0xFFAA0000 0x100 weird_region.bin - UINT64 address = strtoull(argv[2], NULL, 16); - UINT32 size = strtoul(argv[3], NULL, 16); - read_physical_memory_into_file(address, size, argv[4]); - } - } - if (!strcmp(argv[1], "wb")) { - if (argc == 4) { - UINT64 address = strtoull(argv[2], NULL, 16); - UINT32 value = strtoul(argv[3], NULL, 16); - write_byte_physical_memory(address, value); - } - } - if (!strcmp(argv[1], "efimap")) { - print_efi_memory_map(); - } -} - - -void parse_handle_map2user_operation(int argc, char **argv) { - // map2user 0x0000000 --> maps the physical page 0 to usermode - // argv[0] = map2user - // argv[1] = 0x000000 - if (argc == 2) { - UINT64 address = strtoull(argv[1], NULL, 16); - DEBUG_MODE = 1; - void *mapped_addr = map_physical_memory(address, PAGE_SIZE); - DEBUG_MODE = 0; - } -} - -void parse_handle_alloc_operation(int argc, char **argv) { - // alloc 0x0000000 --> allocs size - // argv[0] = alloc - // argv[1] = size - if (argc == 2) { - UINT32 size = strtoul(argv[1], NULL, 16); - DEBUG_MODE = 1; - alloc_user_mem(size, NULL); - DEBUG_MODE = 0; - } -} - -void parse_handle_free_memory_operation(int argc, char **argv) { - // alloc 0x0000000 --> allocs size - // argv[0] = alloc - // argv[1] = size - if (argc == 2) { - UINT64 address = strtoull(argv[1], NULL, 16); - DEBUG_MODE = 1; - unmap_physical_memory((void *) address, 0); - DEBUG_MODE = 0; - } -} - -void parse_handle_mem_dump_operation(int argc, char **argv) { - // dd 0x0000000 0x100 -> dumps the first 0x100 bytes of the vA 0x000 - // argv[0] = dd - // argv[1] = addr - // argv[2] = size - if (argc == 3) { - UINT64 address = strtoull(argv[1], NULL, 16); - UINT64 size = strtoul(argv[2], NULL, 16); - print_memory(address, (char *) address, size); - - } -} diff --git a/PlatboxClient/src/smm/smi_fuzz.cpp b/PlatboxLib/src/smm/smi_fuzz.cpp similarity index 98% rename from PlatboxClient/src/smm/smi_fuzz.cpp rename to PlatboxLib/src/smm/smi_fuzz.cpp index a745516..7d3136a 100644 --- a/PlatboxClient/src/smm/smi_fuzz.cpp +++ b/PlatboxLib/src/smm/smi_fuzz.cpp @@ -90,7 +90,7 @@ void fuzz_all_smi() { printf("-> SEED: %08x", g_fuzzer->Seed); - for (int i = 0x30; i < 0x100; i++) { + for (int i = 0x00; i < 0x100; i++) { printf("\n--> SwSmiNumber: %02x\n", i); for (int j = 0; j < 10000; j++) { diff --git a/PlatboxClient/src/smm/smm_communicate.cpp b/PlatboxLib/src/smm/smm_communicate.cpp similarity index 98% rename from PlatboxClient/src/smm/smm_communicate.cpp rename to PlatboxLib/src/smm/smm_communicate.cpp index ac2daa1..b97f039 100644 --- a/PlatboxClient/src/smm/smm_communicate.cpp +++ b/PlatboxLib/src/smm/smm_communicate.cpp @@ -49,7 +49,7 @@ UINT64 _get_smm_core_private() { if (!ptr) { printf("SMM_CORE_PRIVATE_DATA was not found in the provided range\n"); - return NULL; + return 0; } g_SMMCorePrivateAddr = (UINT64) ptr; @@ -92,7 +92,7 @@ void __smm_dump_s3_bootscript(void *ptr_smm_core_private, const char *output_fil to_guid("AEA6B965-DCF5-4311-B4B8-0F12464494D2", &mBootScriptDataGuid); - const UINT alloc_size = PAGE_SIZE * 20; + const UINT alloc_size = PAGE_SIZE * 64; struct alloc_user_physmem user_page = {0}; BOOL res = alloc_user_mem(alloc_size, &user_page); diff --git a/PlatboxClient/src/windows/acpidump.cpp b/PlatboxLib/src/windows/acpidump.cpp similarity index 98% rename from PlatboxClient/src/windows/acpidump.cpp rename to PlatboxLib/src/windows/acpidump.cpp index f5500a3..713ceec 100644 --- a/PlatboxClient/src/windows/acpidump.cpp +++ b/PlatboxLib/src/windows/acpidump.cpp @@ -1,4 +1,3 @@ -#include "PlatboxClient.h" #include "Util.h" diff --git a/PlatboxClient/src/windows/kernelHookCb.cpp b/PlatboxLib/src/windows/kernelHookCb.cpp similarity index 100% rename from PlatboxClient/src/windows/kernelHookCb.cpp rename to PlatboxLib/src/windows/kernelHookCb.cpp diff --git a/PlatboxClient/src/windows/page_tables.cpp b/PlatboxLib/src/windows/page_tables.cpp similarity index 100% rename from PlatboxClient/src/windows/page_tables.cpp rename to PlatboxLib/src/windows/page_tables.cpp diff --git a/README.md b/README.md index 64a9140..affdcd8 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,56 @@ -# Platbox -UEFI and SMM Assessment Tool - -## Features - -Platbox is a tool that helps assessing the security of the platform: - -- Dumps the platform registers that are interesting security-wise - - Flash Locks - - MMIO and Remapping Locks - - SMM Base and Locks - - MSRs -- RW access to the PCI configuration space of devices. -- RW to physical memory and virtual memory. -- Allows allocating physical memory and map memory to usermode. -- Read and Write MSRs. -- Dump SPI Flash content (BIOS) into a file. -- Basic dumb SMI Fuzzer. -- Dump S3 Bootscript (from SMM-Lockbox) into a file. -- Dump EFI Memory Map (Linux only for now). -- List UEFI variables. -- Supports Linux and Windows. -- Supports Intel and AMD. - -### Example of 'chipset' command output for an AMD platform - -![Kiku](example_chipset_output_amd.png) -![Kiku](example_chipset_output_amd2.png) - -## Project Structure - -The project is divided as follows: - -- Platbox: kernel drivers used for Linux and Windows. -- PlatboxClient: the usermode component that loads the kernel driver and access to al the previously listed features. - - -## TODOs - -- Implement DSE Bypass -- Retrieve the EFI memory map and SMM_CORE_PRIVATE struct from Windows (in progress) -- Give the option to perform register changes in all the cores -- Grab SMI port automatically and remove hardcoded 0xb2 \ No newline at end of file +# Platbox +UEFI and SMM Assessment Tool + +## Features + +Platbox is a tool that helps assessing the security of the platform: + +- Dumps the platform registers that are interesting security-wise + - Flash Locks + - MMIO and Remapping Locks + - SMM Base and Locks + - MSRs +- RW access to the PCI configuration space of devices. +- RW to physical memory and virtual memory. +- Allows allocating physical memory and map memory to usermode. +- Read and Write MSRs. +- Dump SPI Flash content (BIOS) into a file. +- Basic dumb SMI Fuzzer. +- Dump S3 Bootscript (from SMM-Lockbox) into a file. +- Dump EFI Memory Map (Linux only for now). +- List UEFI variables. +- Supports Linux and Windows. +- Supports Intel and AMD. + +### Example of 'chipset' command output for an AMD platform + +![Kiku](example_chipset_output_amd.png) +![Kiku](example_chipset_output_amd2.png) + +## Project Structure + +The project is divided as follows: + +- PlatboxDrv: kernel drivers used for Linux and Windows. +- PlatboxLib: the usermode component that loads the kernel driver and provides access to all the previously listed features. +- PlatboxCli: a console client that uses the library. +- Pocs: an example of a program using features from the libary. + + +## Compilation Steps + +### Windows + +``` +mkdir build +cd build +cmake -G "Visual Studio 17 2022" -A x64 -S .. -B "build64" +cmake --build build64/ --target platbox_cli +``` + +#### Release Build + +``` +cmake -G "Visual Studio 17 2022" -A x64 -S .. -B "build64" +cmake --build build64/ --target platbox_cli --config Release +``` \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..8207dfc --- /dev/null +++ b/build.bat @@ -0,0 +1,8 @@ +mkdir build +cd build +cmake -G "Visual Studio 16 2019" -A x64 -S .. -B "build64" +cmake --build build64/ --target platbox_cli --config Release +cmake --build build64/ --target example --config Release +copy build64\PlatboxClient\Release\platbox_cli.exe ..\compiled\ +copy build64\pocs\Release\example.exe ..\compiled\ +cd .. \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..5f2efe6 --- /dev/null +++ b/build.sh @@ -0,0 +1,7 @@ +mkdir build +cd build +cmake .. +make +cp PlatboxClient/platbox_cli ../compiled/ +cp pocs/example ../compiled/ +cd .. diff --git a/compiled/Platbox.cer b/compiled/Platbox.cer new file mode 100644 index 0000000000000000000000000000000000000000..4d13ee452e6ff6b252d893d9d3b7eed94b84e84a GIT binary patch literal 784 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 literal 0 HcmV?d00001 diff --git a/compiled/example b/compiled/example new file mode 100755 index 0000000000000000000000000000000000000000..b9299d0c6296782514dc676bf456378c8ae7155c GIT binary patch literal 72312 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�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 Y_uA;ccC81y&l=;T7=POSI6UzG0A+_gH2?qr literal 0 HcmV?d00001 diff --git a/compiled/platbox_cli b/compiled/platbox_cli new file mode 100755 index 0000000000000000000000000000000000000000..6fb0524a6a1017868ba738d30589b51e5033ff24 GIT binary patch literal 115200 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 literal 0 HcmV?d00001 diff --git a/compiled/platbox_cli.exe b/compiled/platbox_cli.exe new file mode 100644 index 0000000000000000000000000000000000000000..acd044431dfca56bfd4cfbeb109ec9e0484da2aa GIT binary patch literal 218112 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

}$!}2gC)&_EJg=eA^dwR9{w%ik&#Y~7cdp+dR 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≠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