leechcorepyc 2.17.4__tar.gz → 2.18.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/MANIFEST.in +2 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/Makefile +3 -0
- {leechcorepyc-2.17.4/leechcorepyc.egg-info → leechcorepyc-2.18.4}/PKG-INFO +1 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/includes/leechcore.h +21 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/Makefile +1 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_file.c +21 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_fpga.c +1 -1
- leechcorepyc-2.18.4/leechcore/device_hibr.c +533 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_vmm.c +18 -40
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechcore.c +7 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechcore.h +21 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechcore_internal.h +8 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/oscompatibility.c +0 -3
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/version.h +2 -2
- leechcorepyc-2.18.4/leechcore_device_qemu/Makefile +21 -0
- leechcorepyc-2.18.4/leechcore_device_qemu/leechcore_device_qemu.c +395 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4/leechcorepyc.egg-info}/PKG-INFO +1 -1
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc.egg-info/SOURCES.txt +28 -1
- leechcorepyc-2.18.4/ms-compress/Makefile +18 -0
- leechcorepyc-2.18.4/ms-compress/include/lznt1.h +67 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/Array.h +60 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/Bitstream.h +152 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/CircularBuffer.h +113 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/HuffmanDecoder.h +117 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/HuffmanEncoder.h +234 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/LZNT1Dictionary.h +148 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/LZNT1Dictionary_SA.h +489 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/XpressDictionary.h +188 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/config.h +88 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/general.h +122 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/internal.h +632 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp/sorting.h +68 -0
- leechcorepyc-2.18.4/ms-compress/include/mscomp.h +217 -0
- leechcorepyc-2.18.4/ms-compress/include/xpress.h +64 -0
- leechcorepyc-2.18.4/ms-compress/include/xpress_huff.h +63 -0
- leechcorepyc-2.18.4/ms-compress/src/lznt1_compress.cpp +278 -0
- leechcorepyc-2.18.4/ms-compress/src/lznt1_decompress.cpp +340 -0
- leechcorepyc-2.18.4/ms-compress/src/mscomp.cpp +223 -0
- leechcorepyc-2.18.4/ms-compress/src/xpress_compress.cpp +352 -0
- leechcorepyc-2.18.4/ms-compress/src/xpress_decompress.cpp +467 -0
- leechcorepyc-2.18.4/ms-compress/src/xpress_huff_compress.cpp +333 -0
- leechcorepyc-2.18.4/ms-compress/src/xpress_huff_decompress.cpp +164 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/setup.py +2 -2
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/README +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/files/dummy +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/includes/leechcore_device.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/includes/libpdbcrust.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/includes/vmmdll.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/includes/vmmyara.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_pmem.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_tmd.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_usb3380.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/device_vmware.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechcore.rc +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechcore_device.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechrpc.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechrpc.idl +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechrpc_c.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechrpc_h.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechrpcclient.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/leechrpcshared.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/memmap.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/ob/ob.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/ob/ob_bytequeue.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/ob/ob_core.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/ob/ob_map.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/ob/ob_set.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/oscompatibility.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/util.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore/util.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/Makefile +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/leechcore_device_rawtcp.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/oscompatibility.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/oscompatibility.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/plugin.rc +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/resource.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_device_rawtcp/version.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_ft601_driver_linux/Makefile +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_ft601_driver_linux/fpga_libusb.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_ft601_driver_linux/fpga_libusb.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_ft601_driver_linux/leechcore_ft601_driver_linux.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcore_ft601_driver_linux/leechcore_ft601_driver_linux.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc/__init__.py +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc.egg-info/dependency_links.txt +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc.egg-info/top_level.txt +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/leechcorepyc_barrequest.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/oscompatibility.c +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/oscompatibility.h +0 -0
- {leechcorepyc-2.17.4 → leechcorepyc-2.18.4}/setup.cfg +0 -0
|
@@ -6,8 +6,9 @@ include includes/*.h
|
|
|
6
6
|
graft files
|
|
7
7
|
graft leechcore
|
|
8
8
|
graft leechcore_device_rawtcp
|
|
9
|
-
graft
|
|
9
|
+
graft leechcore_device_qemu
|
|
10
10
|
graft leechcore_ft601_driver_linux
|
|
11
|
+
graft ms-compress
|
|
11
12
|
global-exclude *vcxproj*
|
|
12
13
|
global-exclude *.so
|
|
13
14
|
|
|
@@ -4,6 +4,8 @@ all:
|
|
|
4
4
|
$(MAKE) -C leechcore_ft601_driver_linux || true
|
|
5
5
|
$(MAKE) -C leechcore_device_qemu || true
|
|
6
6
|
$(MAKE) -C leechcore_device_rawtcp || true
|
|
7
|
+
$(MAKE) -C ms-compress || true
|
|
8
|
+
cp ms-compress/libMSCompression.so files/ || true
|
|
7
9
|
cp files/leechcore.so .
|
|
8
10
|
cp files/*.so leechcorepyc/
|
|
9
11
|
|
|
@@ -12,6 +14,7 @@ clean:
|
|
|
12
14
|
$(MAKE) clean -C leechcore_ft601_driver_linux || true
|
|
13
15
|
$(MAKE) clean -C leechcore_device_qemu || true
|
|
14
16
|
$(MAKE) clean -C leechcore_device_rawtcp || true
|
|
17
|
+
$(MAKE) clean -C ms-compress || true
|
|
15
18
|
rm files/*.so || true
|
|
16
19
|
rm leechcore.so || true
|
|
17
20
|
rm leechcorepyc/*.so || true
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// (c) Ulf Frisk, 2020-2024
|
|
15
15
|
// Author: Ulf Frisk, pcileech@frizk.net
|
|
16
16
|
//
|
|
17
|
-
// Header Version: 2.
|
|
17
|
+
// Header Version: 2.18.4
|
|
18
18
|
//
|
|
19
19
|
|
|
20
20
|
#ifndef __LEECHCORE_H__
|
|
@@ -568,6 +568,26 @@ typedef VOID(*PLC_TLP_FUNCTION_CALLBACK)(
|
|
|
568
568
|
|
|
569
569
|
|
|
570
570
|
|
|
571
|
+
//-----------------------------------------------------------------------------
|
|
572
|
+
// VMM (VM) LOOPBACK SUPPORT:
|
|
573
|
+
// Functionality is used to create a VMM loopback device which is used by VMM
|
|
574
|
+
// to read and write memory to/from a virtual machine. See VMM for an example.
|
|
575
|
+
// Struct is passed in the 'hlcvmm' parameter to LcCreate() and will be copied.
|
|
576
|
+
//-----------------------------------------------------------------------------
|
|
577
|
+
|
|
578
|
+
#define LC_VMM_VERSION 0x1eef0001
|
|
579
|
+
|
|
580
|
+
typedef struct tdLC_VMM {
|
|
581
|
+
DWORD dwVersion;
|
|
582
|
+
HANDLE hVMM;
|
|
583
|
+
HANDLE hVMMVM;
|
|
584
|
+
PVOID pfnVMMDLL_ConfigGet;
|
|
585
|
+
PVOID pfnVMMDLL_VmMemReadScatter;
|
|
586
|
+
PVOID pfnVMMDLL_VmMemWriteScatter;
|
|
587
|
+
} LC_VMM, *PLC_VMM;
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
|
|
571
591
|
//-----------------------------------------------------------------------------
|
|
572
592
|
// PCIE BAR SUPPORT:
|
|
573
593
|
//-----------------------------------------------------------------------------
|
|
@@ -10,7 +10,7 @@ CFLAGS += -fPIE -fPIC -pie -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O1 -Wl
|
|
|
10
10
|
CFLAGS += -Wall -Wno-multichar -Wno-unused-result -Wno-unused-variable -Wno-unused-value -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast
|
|
11
11
|
LDFLAGS += -g -ldl -shared
|
|
12
12
|
DEPS = leechcore.h
|
|
13
|
-
OBJ = oscompatibility.o leechcore.o util.o memmap.o device_file.o device_fpga.o device_pmem.o device_tmd.o device_usb3380.o device_vmm.o device_vmware.o leechrpcclient.o ob/ob_core.o ob/ob_map.o ob/ob_set.o ob/ob_bytequeue.o
|
|
13
|
+
OBJ = oscompatibility.o leechcore.o util.o memmap.o device_file.o device_fpga.o device_hibr.o device_pmem.o device_tmd.o device_usb3380.o device_vmm.o device_vmware.o leechrpcclient.o ob/ob_core.o ob/ob_map.o ob/ob_set.o ob/ob_bytequeue.o
|
|
14
14
|
|
|
15
15
|
%.o: %.c $(DEPS)
|
|
16
16
|
$(CC) -c -o $@ $< $(CFLAGS)
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
#include "leechcore_internal.h"
|
|
9
9
|
#include "util.h"
|
|
10
10
|
|
|
11
|
+
//-----------------------------------------------------------------------------
|
|
12
|
+
// DEFINES: HIBERNATION 'HIBR' FILE DEVICE
|
|
13
|
+
//-----------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
_Success_(return)
|
|
16
|
+
BOOL DeviceHIBR_Open(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcCreateErrorInfo);
|
|
17
|
+
|
|
11
18
|
//-----------------------------------------------------------------------------
|
|
12
19
|
// DEFINES: MICROSOFT CRASH DUMP DEFINES
|
|
13
20
|
//-----------------------------------------------------------------------------
|
|
@@ -844,7 +851,7 @@ VOID DeviceFile_Close(_Inout_ PLC_CONTEXT ctxLC)
|
|
|
844
851
|
_Success_(return)
|
|
845
852
|
BOOL DeviceFile_Open(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcCreateErrorInfo)
|
|
846
853
|
{
|
|
847
|
-
DWORD i;
|
|
854
|
+
DWORD i, dwFileMagic = 0;
|
|
848
855
|
LPSTR szType;
|
|
849
856
|
PDEVICE_CONTEXT_FILE ctx;
|
|
850
857
|
PLC_DEVICE_PARAMETER_ENTRY pParam;
|
|
@@ -872,6 +879,19 @@ BOOL DeviceFile_Open(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO
|
|
|
872
879
|
}
|
|
873
880
|
// open backing file:
|
|
874
881
|
if(fopen_s(&ctx->File[0].h, ctx->szFileName, (ctxLC->Config.fWritable ? "r+b" : "rb")) || !ctx->File[0].h) { goto fail; }
|
|
882
|
+
{
|
|
883
|
+
// check if file is hibernation file, in which case delegate open to hibr device:
|
|
884
|
+
_fseeki64(ctx->File[0].h, 0, SEEK_SET);
|
|
885
|
+
fread(&dwFileMagic, 1, sizeof(DWORD), ctx->File[0].h);
|
|
886
|
+
if((dwFileMagic == 0x52424948) || (dwFileMagic == 0x454b4157)) { // 'HIBR' or 'WAKE'
|
|
887
|
+
strncpy_s(ctxLC->Config.szDevice, _countof(ctxLC->Config.szDevice), "hibr://file=", _TRUNCATE);
|
|
888
|
+
strncpy_s(ctxLC->Config.szDevice + 12, _countof(ctxLC->Config.szDevice) - 12, ctx->szFileName, _TRUNCATE);
|
|
889
|
+
strncpy_s(ctxLC->Config.szDeviceName, _countof(ctxLC->Config.szDeviceName), "hibr", _TRUNCATE);
|
|
890
|
+
LocalFree(ctx);
|
|
891
|
+
LcCreate_FetchDeviceParameter(ctxLC);
|
|
892
|
+
return DeviceHIBR_Open(ctxLC, ppLcCreateErrorInfo);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
875
895
|
InitializeCriticalSection(&ctx->File[0].Lock);
|
|
876
896
|
if(_fseeki64(ctx->File[0].h, 0, SEEK_END)) { goto fail; } // seek to end of file
|
|
877
897
|
ctx->cbFile = _ftelli64(ctx->File[0].h); // get current file pointer
|
|
@@ -2273,7 +2273,7 @@ VOID DeviceFPGA_Synch_ReadScatter_Impl(_In_ PLC_CONTEXT ctxLC, _In_ DWORD cMEMs,
|
|
|
2273
2273
|
continue;
|
|
2274
2274
|
}
|
|
2275
2275
|
if(cbTotalInCycle >= ctx->perf.MAX_SIZE_RX) { break; } // over max size -> break loop and read result
|
|
2276
|
-
cbTotalInCycle += pDMA->cb;
|
|
2276
|
+
cbTotalInCycle += (pDMA->cb == 0x1000) ? 0x1000 : (pDMA->cb + 48);
|
|
2277
2277
|
o = 0;
|
|
2278
2278
|
while(o < pDMA->cb) {
|
|
2279
2279
|
cb = fTiny ? min(0x80, pDMA->cb - o) : pDMA->cb;
|
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
// leechcore_device_hibr.c : implementation of hibernation file support for
|
|
2
|
+
// Windows 8+.
|
|
3
|
+
//
|
|
4
|
+
// The hibernation file format of Windows 8+ is documented in the excellent
|
|
5
|
+
// blog post by ForensicXlab at: https://www.forensicxlab.com/posts/hibernation/
|
|
6
|
+
// Also the original paper at: https://www.cct.lsu.edu/~golden/Papers/sylvehiber.pdf
|
|
7
|
+
//
|
|
8
|
+
// (c) Ulf Frisk, 2024
|
|
9
|
+
// Author: Ulf Frisk, pcileech@frizk.net
|
|
10
|
+
//
|
|
11
|
+
#include "leechcore.h"
|
|
12
|
+
#include "leechcore_device.h"
|
|
13
|
+
#include "oscompatibility.h"
|
|
14
|
+
#include "util.h"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
//-----------------------------------------------------------------------------
|
|
19
|
+
// HARD CODED HIBERNATION OFFSETS FOR WINDOWS 8+
|
|
20
|
+
//-----------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
typedef struct tdHIBR_OFFSET {
|
|
23
|
+
DWORD LengthSelf;
|
|
24
|
+
BOOL f32;
|
|
25
|
+
DWORD PageSize;
|
|
26
|
+
DWORD SystemTime;
|
|
27
|
+
DWORD NumPagesForLoader;
|
|
28
|
+
DWORD FirstBootRestorePage;
|
|
29
|
+
DWORD FirstKernelRestorePage;
|
|
30
|
+
DWORD KernelPagesProcessed;
|
|
31
|
+
DWORD HighestPhysicalPage;
|
|
32
|
+
} HIBR_OFFSET, *PHIBR_OFFSET;
|
|
33
|
+
|
|
34
|
+
const HIBR_OFFSET HIBR_OFFSET_PROFILES[] = {
|
|
35
|
+
{.LengthSelf = 0x448, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x400}, // 64-bit build 22621
|
|
36
|
+
{.LengthSelf = 0x448, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x400}, // 64-bit build 22000
|
|
37
|
+
{.LengthSelf = 0x448, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x400}, // 64-bit build 20348
|
|
38
|
+
{.LengthSelf = 0x3e0, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 19041
|
|
39
|
+
{.LengthSelf = 0x3e0, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 18363
|
|
40
|
+
{.LengthSelf = 0x3e0, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 18362
|
|
41
|
+
{.LengthSelf = 0x3e0, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 17763
|
|
42
|
+
{.LengthSelf = 0x3d8, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 17134
|
|
43
|
+
{.LengthSelf = 0x3d8, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 16299
|
|
44
|
+
{.LengthSelf = 0x3d8, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x230, .HighestPhysicalPage = 0x398}, // 64-bit build 15063
|
|
45
|
+
{.LengthSelf = 0x3c8, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x220, .HighestPhysicalPage = 0x388}, // 64-bit build 14393
|
|
46
|
+
{.LengthSelf = 0x3b0, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x218, .HighestPhysicalPage = 0x380}, // 64-bit build 10586
|
|
47
|
+
{.LengthSelf = 0x3b0, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x68, .FirstKernelRestorePage = 0x70, .KernelPagesProcessed = 0x218, .HighestPhysicalPage = 0x380}, // 64-bit build 10240
|
|
48
|
+
{.LengthSelf = 0x360, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x60, .FirstKernelRestorePage = 0x68, .KernelPagesProcessed = 0x1c8, .HighestPhysicalPage = 0x330}, // 64-bit build 9600
|
|
49
|
+
{.LengthSelf = 0x360, .f32 = FALSE, .PageSize = 0x18, .SystemTime = 0x20, .NumPagesForLoader = 0x58, .FirstBootRestorePage = 0x60, .FirstKernelRestorePage = 0x68, .KernelPagesProcessed = 0x1c8, .HighestPhysicalPage = 0x330}, // 64-bit build 9200
|
|
50
|
+
{.LengthSelf = 0x340, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 19041
|
|
51
|
+
{.LengthSelf = 0x340, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 18363
|
|
52
|
+
{.LengthSelf = 0x340, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 18362
|
|
53
|
+
{.LengthSelf = 0x340, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 17763
|
|
54
|
+
{.LengthSelf = 0x338, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 17134
|
|
55
|
+
{.LengthSelf = 0x338, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 16299
|
|
56
|
+
{.LengthSelf = 0x338, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x210, .HighestPhysicalPage = 0x310}, // 32-bit build 15063
|
|
57
|
+
{.LengthSelf = 0x328, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x200, .HighestPhysicalPage = 0x300}, // 32-bit build 14393
|
|
58
|
+
{.LengthSelf = 0x310, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x1f8, .HighestPhysicalPage = 0x2f8}, // 32-bit build 10586
|
|
59
|
+
{.LengthSelf = 0x310, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x1f8, .HighestPhysicalPage = 0x2f8}, // 32-bit build 10240
|
|
60
|
+
{.LengthSelf = 0x2c8, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x1b0, .HighestPhysicalPage = 0x2b0}, // 32-bit build 9600
|
|
61
|
+
{.LengthSelf = 0x2c8, .f32 = TRUE, .PageSize = 0x14, .SystemTime = 0x18, .NumPagesForLoader = 0x48, .FirstBootRestorePage = 0x50, .FirstKernelRestorePage = 0x54, .KernelPagesProcessed = 0x1b0, .HighestPhysicalPage = 0x2b0}, // 32-bit build 9200
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
//-----------------------------------------------------------------------------
|
|
67
|
+
// DEFINES:
|
|
68
|
+
//-----------------------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
#define VMM_PTR_OFFSET(f32, pb, o) ((f32) ? *(PDWORD)((o) + (PBYTE)(pb)) : *(PQWORD)((o) + (PBYTE)(pb)))
|
|
71
|
+
|
|
72
|
+
#define HIBR_MAGIC 0x52424948
|
|
73
|
+
#define WAKE_MAGIC 0x454b4157
|
|
74
|
+
|
|
75
|
+
#define COMPRESS_ALGORITHM_NONE 0
|
|
76
|
+
#define COMPRESS_ALGORITHM_XPRESS 3
|
|
77
|
+
#define COMPRESS_ALGORITHM_XPRESS_HUFF 4
|
|
78
|
+
|
|
79
|
+
#define HIBR_STATUS_SUCCESS ((NTSTATUS)0x00000000L)
|
|
80
|
+
#define HIBR_STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
|
|
81
|
+
|
|
82
|
+
#define HIBR_COMPRESSION_TABLE_SIZE 0x1000
|
|
83
|
+
#define HIBR_COMPRESSION_DIRECTORY_SIZE 0x1000
|
|
84
|
+
#define HIBR_COMPRESSION_INDEX_DIRECTORY(i) ((i >> 12) & (HIBR_COMPRESSION_DIRECTORY_SIZE - 1))
|
|
85
|
+
#define HIBR_COMPRESSION_INDEX_TABLE(i) (i & (HIBR_COMPRESSION_TABLE_SIZE - 1))
|
|
86
|
+
|
|
87
|
+
#define HIBR_NUM_CACHE_ENTRIES 4
|
|
88
|
+
|
|
89
|
+
// decompression function pointer compatible with ntdll!RtlDecompressBuffer.
|
|
90
|
+
typedef NTSTATUS WINAPI HIBR_RtlDecompressBufferEx(
|
|
91
|
+
USHORT CompressionFormat,
|
|
92
|
+
PUCHAR UncompressedBuffer,
|
|
93
|
+
ULONG UncompressedBufferSize,
|
|
94
|
+
PUCHAR CompressedBuffer,
|
|
95
|
+
ULONG CompressedBufferSize,
|
|
96
|
+
PULONG FinalUncompressedSize,
|
|
97
|
+
PVOID WorkSpace
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
typedef struct tdHIBR_COMPRESSION_SET {
|
|
101
|
+
QWORD o; // byte offset of compressed data inside hiberfil.sys
|
|
102
|
+
DWORD cb; // compressed size in bytes
|
|
103
|
+
WORD cpg; // number of pages in this compression set
|
|
104
|
+
BYTE tp; // compression type
|
|
105
|
+
} HIBR_COMPRESSION_SET, *PHIBR_COMPRESSION_SET;
|
|
106
|
+
|
|
107
|
+
typedef struct tdHIBR_COMPRESSION_SET_TABLE {
|
|
108
|
+
HIBR_COMPRESSION_SET v[HIBR_COMPRESSION_TABLE_SIZE];
|
|
109
|
+
} HIBR_COMPRESSION_SET_TABLE, *PHIBR_COMPRESSION_SET_TABLE;
|
|
110
|
+
|
|
111
|
+
typedef struct tdDEVICE_CONTEXT_FILE {
|
|
112
|
+
FILE *hFile;
|
|
113
|
+
QWORD cbFile;
|
|
114
|
+
CHAR szFileName[MAX_PATH];
|
|
115
|
+
BOOL f32;
|
|
116
|
+
BOOL fWarningFirst;
|
|
117
|
+
PHIBR_OFFSET po;
|
|
118
|
+
HIBR_RtlDecompressBufferEx *pfnRtlDecompressBufferExOpt;
|
|
119
|
+
DWORD cCS; // compression set count
|
|
120
|
+
PHIBR_COMPRESSION_SET_TABLE CS_Directory[HIBR_COMPRESSION_DIRECTORY_SIZE];
|
|
121
|
+
QWORD cPfns;
|
|
122
|
+
PDWORD pdwPfn2CS;
|
|
123
|
+
DWORD iCsCacheNext;
|
|
124
|
+
struct {
|
|
125
|
+
DWORD iCS; // current compression set index
|
|
126
|
+
BYTE pb[0x10000]; // buffer for decompression
|
|
127
|
+
} CS_Cache[HIBR_NUM_CACHE_ENTRIES];
|
|
128
|
+
BYTE pbBufferCompressedData[0x10000];
|
|
129
|
+
BYTE pbWorkSpace[0x00100000];
|
|
130
|
+
} DEVICE_CONTEXT_FILE, *PDEVICE_CONTEXT_FILE;
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
//-----------------------------------------------------------------------------
|
|
134
|
+
// DECOMPRESSION FUNCTION FUNCTIONALITY BELOW:
|
|
135
|
+
//-----------------------------------------------------------------------------
|
|
136
|
+
|
|
137
|
+
#ifdef _WIN32
|
|
138
|
+
/*
|
|
139
|
+
* Try to initialize the decompression function pointer.
|
|
140
|
+
* Decompression is handled by ntdll.dll on Windows and by libMSCompression.so on Linux.
|
|
141
|
+
* -- ctx
|
|
142
|
+
* -- return = TRUE on success, FALSE on failure.
|
|
143
|
+
*/
|
|
144
|
+
_Success_(return)
|
|
145
|
+
BOOL DeviceHibr_InitializeFunctions(_In_ PDEVICE_CONTEXT_FILE ctx)
|
|
146
|
+
{
|
|
147
|
+
HMODULE hNtDll = NULL;
|
|
148
|
+
if((hNtDll = LoadLibraryA("ntdll.dll"))) {
|
|
149
|
+
ctx->pfnRtlDecompressBufferExOpt = (HIBR_RtlDecompressBufferEx*)GetProcAddress(hNtDll, "RtlDecompressBufferEx");
|
|
150
|
+
FreeLibrary(hNtDll);
|
|
151
|
+
}
|
|
152
|
+
return ctx->pfnRtlDecompressBufferExOpt ? TRUE : FALSE;
|
|
153
|
+
}
|
|
154
|
+
#endif /* _WIN32 */
|
|
155
|
+
|
|
156
|
+
#ifdef LINUX
|
|
157
|
+
|
|
158
|
+
/*
|
|
159
|
+
* Linux implementation of ntdll!RtlDecompressBuffer for COMPRESS_ALGORITHM_XPRESS:
|
|
160
|
+
* Dynamically load libMSCompression.so (if it exists) and use it. If library does
|
|
161
|
+
* not exist then fail gracefully (i.e. don't support XPRESS decompress).
|
|
162
|
+
* https://github.com/coderforlife/ms-compress (License: GPLv3)
|
|
163
|
+
*/
|
|
164
|
+
NTSTATUS OSCOMPAT_RtlDecompressBufferEx(USHORT CompressionFormat, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, PULONG FinalUncompressedSize, PVOID pv)
|
|
165
|
+
{
|
|
166
|
+
int rc;
|
|
167
|
+
void *lib_mscompress;
|
|
168
|
+
SIZE_T cbOut;
|
|
169
|
+
static BOOL fFirst = TRUE;
|
|
170
|
+
static SRWLOCK LockSRW = SRWLOCK_INIT;
|
|
171
|
+
static int(*pfn_xpress_decompress)(PBYTE pbIn, SIZE_T cbIn, PBYTE pbOut, SIZE_T *pcbOut) = NULL;
|
|
172
|
+
static int(*pfn_xpress_decompress_huff)(PBYTE pbIn, SIZE_T cbIn, PBYTE pbOut, SIZE_T * pcbOut) = NULL;
|
|
173
|
+
CHAR szPathLib[MAX_PATH] = { 0 };
|
|
174
|
+
Util_GetPathLib(szPathLib);
|
|
175
|
+
strncat_s(szPathLib, sizeof(szPathLib), "libMSCompression.so", _TRUNCATE);
|
|
176
|
+
if((CompressionFormat != 3) && (CompressionFormat != 4)) { return HIBR_STATUS_UNSUCCESSFUL; } // 3 == COMPRESS_ALGORITHM_XPRESS, 4 == COMPRESS_ALGORITHM_XPRESS_HUFF
|
|
177
|
+
if(fFirst) {
|
|
178
|
+
AcquireSRWLockExclusive(&LockSRW);
|
|
179
|
+
if(fFirst) {
|
|
180
|
+
fFirst = FALSE;
|
|
181
|
+
lib_mscompress = dlopen(szPathLib, RTLD_NOW);
|
|
182
|
+
if(lib_mscompress) {
|
|
183
|
+
pfn_xpress_decompress = (int(*)(PBYTE, SIZE_T, PBYTE, SIZE_T *))dlsym(lib_mscompress, "xpress_decompress");
|
|
184
|
+
pfn_xpress_decompress_huff = (int(*)(PBYTE, SIZE_T, PBYTE, SIZE_T *))dlsym(lib_mscompress, "xpress_huff_decompress");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
ReleaseSRWLockExclusive(&LockSRW);
|
|
188
|
+
}
|
|
189
|
+
*FinalUncompressedSize = 0;
|
|
190
|
+
if(pfn_xpress_decompress && pfn_xpress_decompress_huff) {
|
|
191
|
+
cbOut = UncompressedBufferSize;
|
|
192
|
+
rc = (CompressionFormat == 4) ?
|
|
193
|
+
pfn_xpress_decompress_huff(CompressedBuffer, CompressedBufferSize, UncompressedBuffer, &cbOut) :
|
|
194
|
+
pfn_xpress_decompress(CompressedBuffer, CompressedBufferSize, UncompressedBuffer, &cbOut);
|
|
195
|
+
if(rc == 0) {
|
|
196
|
+
*FinalUncompressedSize = cbOut;
|
|
197
|
+
return HIBR_STATUS_SUCCESS;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return HIBR_STATUS_UNSUCCESSFUL;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
/*
|
|
205
|
+
* Verify that the compression library is available.
|
|
206
|
+
* -- ctx
|
|
207
|
+
* -- return = TRUE on success, FALSE on failure.
|
|
208
|
+
*/
|
|
209
|
+
_Success_(return)
|
|
210
|
+
BOOL DeviceHibr_InitializeFunctions(_In_ PDEVICE_CONTEXT_FILE ctx)
|
|
211
|
+
{
|
|
212
|
+
void *lib_mscompress;
|
|
213
|
+
CHAR szPathLib[MAX_PATH] = { 0 };
|
|
214
|
+
Util_GetPathLib(szPathLib);
|
|
215
|
+
strncat_s(szPathLib, sizeof(szPathLib), "libMSCompression.so", _TRUNCATE);
|
|
216
|
+
lib_mscompress = dlopen(szPathLib, RTLD_NOW);
|
|
217
|
+
if(lib_mscompress) {
|
|
218
|
+
dlclose(lib_mscompress);
|
|
219
|
+
ctx->pfnRtlDecompressBufferExOpt = OSCOMPAT_RtlDecompressBufferEx;
|
|
220
|
+
return TRUE;
|
|
221
|
+
}
|
|
222
|
+
return FALSE;
|
|
223
|
+
}
|
|
224
|
+
#endif /* LINUX */
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
//-----------------------------------------------------------------------------
|
|
229
|
+
// GENERAL 'DEVICE' FUNCTIONALITY BELOW:
|
|
230
|
+
//-----------------------------------------------------------------------------
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
* Read a decompressed page. Either from the cache or from the hibernation file (and decompress it).
|
|
234
|
+
* -- ctxLC
|
|
235
|
+
* -- pCS
|
|
236
|
+
* -- iCS
|
|
237
|
+
* -- iPB
|
|
238
|
+
* -- return = pointer to decompressed page, or NULL on error.
|
|
239
|
+
*/
|
|
240
|
+
_Success_(return != NULL)
|
|
241
|
+
PBYTE DeviceHibr_ReadPage(_In_ PLC_CONTEXT ctxLC, _In_ PHIBR_COMPRESSION_SET pCS, _In_ DWORD iCS, _In_ DWORD iPG)
|
|
242
|
+
{
|
|
243
|
+
PDEVICE_CONTEXT_FILE ctx = (PDEVICE_CONTEXT_FILE)ctxLC->hDevice;
|
|
244
|
+
NTSTATUS nt;
|
|
245
|
+
PBYTE pbBufferUncompressed;
|
|
246
|
+
DWORD i, cbUncompressed, cbUncompressedResult = 0;
|
|
247
|
+
if(!iCS || (iPG > pCS->cpg) || (iPG >= 0x10)) { return NULL; }
|
|
248
|
+
// 1: try to find page in cache:
|
|
249
|
+
for(i = 0; i < HIBR_NUM_CACHE_ENTRIES; i++) {
|
|
250
|
+
if(ctx->CS_Cache[i].iCS == iCS) {
|
|
251
|
+
return ctx->CS_Cache[i].pb + (iPG * 0x1000);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// 2: not found in cache, try fetch from hiberfil.sys:
|
|
255
|
+
if(_fseeki64(ctx->hFile, pCS->o, SEEK_SET)) { return NULL; }
|
|
256
|
+
if(fread(ctx->pbBufferCompressedData, 1, pCS->cb, ctx->hFile) != pCS->cb) { return NULL; }
|
|
257
|
+
// 3: decompress buffer and store in cache:
|
|
258
|
+
ctx->CS_Cache[ctx->iCsCacheNext].iCS = 0;
|
|
259
|
+
cbUncompressed = 0x1000 * pCS->cpg;
|
|
260
|
+
pbBufferUncompressed = ctx->CS_Cache[ctx->iCsCacheNext].pb;
|
|
261
|
+
if(pCS->tp == COMPRESS_ALGORITHM_NONE) {
|
|
262
|
+
memcpy(pbBufferUncompressed, ctx->pbBufferCompressedData, cbUncompressed);
|
|
263
|
+
cbUncompressedResult = cbUncompressed;
|
|
264
|
+
nt = HIBR_STATUS_SUCCESS;
|
|
265
|
+
} else {
|
|
266
|
+
nt = ctx->pfnRtlDecompressBufferExOpt(pCS->tp, pbBufferUncompressed, cbUncompressed, ctx->pbBufferCompressedData, pCS->cb, &cbUncompressedResult, ctx->pbWorkSpace);
|
|
267
|
+
}
|
|
268
|
+
if((nt == HIBR_STATUS_SUCCESS) && (cbUncompressed == cbUncompressedResult)) {
|
|
269
|
+
ctx->CS_Cache[ctx->iCsCacheNext].iCS = iCS;
|
|
270
|
+
ctx->iCsCacheNext = (ctx->iCsCacheNext + 1) % HIBR_NUM_CACHE_ENTRIES;
|
|
271
|
+
return pbBufferUncompressed + (iPG * 0x1000);
|
|
272
|
+
}
|
|
273
|
+
if(!ctx->fWarningFirst) {
|
|
274
|
+
ctx->fWarningFirst = TRUE;
|
|
275
|
+
lcprintf(ctxLC, "DEVICE: HIBR: WARNING: Decompression failed. Should not happen [only shown once].\n");
|
|
276
|
+
}
|
|
277
|
+
return NULL;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/*
|
|
281
|
+
* Default scatter read function - to be called by LeechCore. This function is
|
|
282
|
+
* currently not supported to be called in a multi-threaded way.
|
|
283
|
+
* -- ctxLC
|
|
284
|
+
* -- cpMEMs
|
|
285
|
+
* -- ppMEMs
|
|
286
|
+
*/
|
|
287
|
+
VOID DeviceHibr_ReadScatter(_In_ PLC_CONTEXT ctxLC, _In_ DWORD cpMEMs, _Inout_ PPMEM_SCATTER ppMEMs)
|
|
288
|
+
{
|
|
289
|
+
PDEVICE_CONTEXT_FILE ctx = (PDEVICE_CONTEXT_FILE)ctxLC->hDevice;
|
|
290
|
+
DWORD iMEM, iCS, iPG;
|
|
291
|
+
QWORD qwPfn;
|
|
292
|
+
PBYTE pbPage;
|
|
293
|
+
PMEM_SCATTER pMEM;
|
|
294
|
+
PHIBR_COMPRESSION_SET pCS;
|
|
295
|
+
for(iMEM = 0; iMEM < cpMEMs; iMEM++) {
|
|
296
|
+
pMEM = ppMEMs[iMEM];
|
|
297
|
+
if(pMEM->f || (pMEM->qwA == (QWORD)-1)) { continue; }
|
|
298
|
+
qwPfn = pMEM->qwA >> 12;
|
|
299
|
+
if(qwPfn >= ctx->cPfns) { continue; }
|
|
300
|
+
iCS = ctx->pdwPfn2CS[qwPfn] & 0x00ffffff;
|
|
301
|
+
iPG = ctx->pdwPfn2CS[qwPfn] >> 24;
|
|
302
|
+
pCS = &ctx->CS_Directory[HIBR_COMPRESSION_INDEX_DIRECTORY(iCS)]->v[HIBR_COMPRESSION_INDEX_TABLE(iCS)];
|
|
303
|
+
if(!pCS || !pCS->cb) {
|
|
304
|
+
// failed to find compression set, probably a zero page, mark as successful read.
|
|
305
|
+
ZeroMemory(pMEM->pb, pMEM->cb);
|
|
306
|
+
pMEM->f = TRUE;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
pbPage = DeviceHibr_ReadPage(ctxLC, pCS, iCS, iPG);
|
|
310
|
+
if(pbPage) {
|
|
311
|
+
memcpy(pMEM->pb, pbPage + (pMEM->qwA & 0xfff), pMEM->cb);
|
|
312
|
+
pMEM->f = TRUE;
|
|
313
|
+
}
|
|
314
|
+
if(pMEM->f) {
|
|
315
|
+
if(ctxLC->fPrintf[LC_PRINTF_VVV]) {
|
|
316
|
+
lcprintf_fn(
|
|
317
|
+
ctxLC,
|
|
318
|
+
"READ:\n offset=%016llx req_len=%08x\n",
|
|
319
|
+
pMEM->qwA,
|
|
320
|
+
pMEM->cb
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
lcprintfvvv_fn(ctxLC, "READ FAILED:\n offset=%016llx req_len=%08x\n", pMEM->qwA, pMEM->cb);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/*
|
|
330
|
+
* Parse a hibernation file restoration set consisting of multiple compression sets.
|
|
331
|
+
* -- ctx
|
|
332
|
+
* -- cbo
|
|
333
|
+
* -- cPageTotal
|
|
334
|
+
*/
|
|
335
|
+
VOID DeviceHibr_HibrInitialize_RestoreSet(_In_ PLC_CONTEXT ctxLC, _In_ QWORD cbo, _In_ QWORD cPageTotal)
|
|
336
|
+
{
|
|
337
|
+
PDEVICE_CONTEXT_FILE ctx = (PDEVICE_CONTEXT_FILE)ctxLC->hDevice;
|
|
338
|
+
BOOL fWarning = FALSE;
|
|
339
|
+
BYTE i, j, cDescCS;
|
|
340
|
+
BYTE pb[0x1000];
|
|
341
|
+
QWORD iDescPfn, qwStatusPGD;
|
|
342
|
+
DWORD cDescPages, dwStatusCS, pbo, dwPfnOffsetPGD;
|
|
343
|
+
PHIBR_COMPRESSION_SET pCS;
|
|
344
|
+
if(!cPageTotal) { return; }
|
|
345
|
+
restart:
|
|
346
|
+
// 1: fetch next compression set from context (allocate new empty if needed):
|
|
347
|
+
if(0 == (ctx->cCS % HIBR_COMPRESSION_TABLE_SIZE)) {
|
|
348
|
+
if((ctx->cCS + HIBR_COMPRESSION_DIRECTORY_SIZE) > 0x00ffffff) { return; }
|
|
349
|
+
if(ctx->cCS == HIBR_COMPRESSION_TABLE_SIZE * HIBR_COMPRESSION_DIRECTORY_SIZE) { return; }
|
|
350
|
+
if(!(ctx->CS_Directory[HIBR_COMPRESSION_INDEX_DIRECTORY(ctx->cCS)] = (PHIBR_COMPRESSION_SET_TABLE)LocalAlloc(LMEM_ZEROINIT, sizeof(HIBR_COMPRESSION_SET_TABLE)))) { return; }
|
|
351
|
+
}
|
|
352
|
+
pCS = &ctx->CS_Directory[HIBR_COMPRESSION_INDEX_DIRECTORY(ctx->cCS)]->v[HIBR_COMPRESSION_INDEX_TABLE(ctx->cCS)];
|
|
353
|
+
// 2: fetch, from hibernation file, compression set header & parse compression set status dword:
|
|
354
|
+
if(_fseeki64(ctx->hFile, cbo, SEEK_SET)) { return; }
|
|
355
|
+
if(fread(pb, 1, sizeof(pb), ctx->hFile) != sizeof(pb)) { return; }
|
|
356
|
+
dwStatusCS = *(PDWORD)(pb + 0x000);
|
|
357
|
+
cDescCS = dwStatusCS & 0xff;
|
|
358
|
+
pCS->cb = (dwStatusCS >> 8) & 0x3fffff;
|
|
359
|
+
pCS->tp = (dwStatusCS & 0x80000000) ? COMPRESS_ALGORITHM_XPRESS_HUFF : COMPRESS_ALGORITHM_XPRESS;
|
|
360
|
+
if(!cDescCS || !pCS->cb) { return; }
|
|
361
|
+
// 2: iterate over page descriptors in the compression set.
|
|
362
|
+
pbo = 4;
|
|
363
|
+
for(i = 0; i < cDescCS; i++) {
|
|
364
|
+
if(ctx->f32) {
|
|
365
|
+
qwStatusPGD = *(PDWORD)(pb + pbo);
|
|
366
|
+
pbo += 4;
|
|
367
|
+
} else {
|
|
368
|
+
qwStatusPGD = *(PQWORD)(pb + pbo);
|
|
369
|
+
pbo += 8;
|
|
370
|
+
}
|
|
371
|
+
cDescPages = 1 + (qwStatusPGD & 0xf);
|
|
372
|
+
iDescPfn = qwStatusPGD >> 4;
|
|
373
|
+
// 2.1: store pfn -> cs mapping:
|
|
374
|
+
if(iDescPfn + cDescPages < ctx->cPfns) {
|
|
375
|
+
for(j = 0; j < cDescPages; j++) {
|
|
376
|
+
dwPfnOffsetPGD = pCS->cpg + j;
|
|
377
|
+
ctx->pdwPfn2CS[iDescPfn + j] = (dwPfnOffsetPGD << 24) | ctx->cCS;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
pCS->cpg += (WORD)cDescPages;
|
|
381
|
+
}
|
|
382
|
+
if((pCS->cpg > 0x10) && !fWarning) {
|
|
383
|
+
lcprintf(ctxLC, "DEVICE: HIBR: WARNING: COMPRESSION SET #PAGES > 10 (only showed once).\n");
|
|
384
|
+
fWarning = TRUE;
|
|
385
|
+
}
|
|
386
|
+
if(pCS->cb == ((DWORD)pCS->cpg << 12)) {
|
|
387
|
+
pCS->tp = COMPRESS_ALGORITHM_NONE;
|
|
388
|
+
}
|
|
389
|
+
pCS->o = cbo + pbo;
|
|
390
|
+
ctx->cCS++;
|
|
391
|
+
cbo += pbo + pCS->cb;
|
|
392
|
+
if(cPageTotal > pCS->cpg) {
|
|
393
|
+
cPageTotal -= pCS->cpg;
|
|
394
|
+
goto restart;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/*
|
|
399
|
+
* Parse and initialize the hibernation file:
|
|
400
|
+
* -- ctxLC
|
|
401
|
+
* -- return = FALSE on fatal non-recoverable error, otherwise TRUE.
|
|
402
|
+
*/
|
|
403
|
+
_Success_(return)
|
|
404
|
+
BOOL DeviceHibr_HibrInitialize(_In_ PLC_CONTEXT ctxLC)
|
|
405
|
+
{
|
|
406
|
+
PDEVICE_CONTEXT_FILE ctx = (PDEVICE_CONTEXT_FILE)ctxLC->hDevice;
|
|
407
|
+
BYTE pb[0x1000];
|
|
408
|
+
DWORD i, cbPO_MEMORY_IMAGE;
|
|
409
|
+
QWORD cboRestoreBoot = 0, cboRestoreKernel = 0, cPagesLoader = 0, cPagesKernel = 0;
|
|
410
|
+
// 1: fetch header:
|
|
411
|
+
if(_fseeki64(ctx->hFile, 0, SEEK_SET)) { goto fail; }
|
|
412
|
+
if(fread(pb, 1, sizeof(pb), ctx->hFile) != sizeof(pb)) { goto fail; }
|
|
413
|
+
if((*(PDWORD)(pb + 0x000) != HIBR_MAGIC) && (*(PDWORD)(pb + 0x000) != WAKE_MAGIC)) { goto fail; }
|
|
414
|
+
// 2: fetch offsets to use by looking at struct length:
|
|
415
|
+
cbPO_MEMORY_IMAGE = *(PDWORD)(pb + 0x00c);
|
|
416
|
+
for(i = 0; i < _countof(HIBR_OFFSET_PROFILES); i++) {
|
|
417
|
+
if(HIBR_OFFSET_PROFILES[i].LengthSelf == cbPO_MEMORY_IMAGE) {
|
|
418
|
+
ctx->po = (PHIBR_OFFSET)&HIBR_OFFSET_PROFILES[i];
|
|
419
|
+
ctx->f32 = ctx->po->f32;
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
if(!ctx->po) {
|
|
424
|
+
lcprintf(ctxLC, "DEVICE: HIBR: FAIL: Unable to determine hibernation profile (size=%i).\n", cbPO_MEMORY_IMAGE);
|
|
425
|
+
goto fail;
|
|
426
|
+
}
|
|
427
|
+
if(0x1000 != *(PDWORD)(pb + ctx->po->PageSize)) {
|
|
428
|
+
lcprintf(ctxLC, "DEVICE: HIBR: FAIL: Unsupported page size: %llu.\n", *(PQWORD)(pb + ctx->po->PageSize));
|
|
429
|
+
goto fail;
|
|
430
|
+
}
|
|
431
|
+
// 3: fetch offsets and pages for boot and kernel restoration sets:
|
|
432
|
+
cPagesLoader = *(PQWORD)(pb + ctx->po->NumPagesForLoader);
|
|
433
|
+
cPagesKernel = *(PQWORD)(pb + ctx->po->KernelPagesProcessed);
|
|
434
|
+
cboRestoreBoot = 0x1000 * (QWORD)VMM_PTR_OFFSET(ctx->f32, pb, ctx->po->FirstBootRestorePage);
|
|
435
|
+
cboRestoreKernel = 0x1000 * (QWORD)VMM_PTR_OFFSET(ctx->f32, pb, ctx->po->FirstKernelRestorePage);
|
|
436
|
+
// 4: fetch highest physical page and calculate max memory:
|
|
437
|
+
ctx->cPfns = VMM_PTR_OFFSET(ctx->f32, pb, ctx->po->HighestPhysicalPage) + 1;
|
|
438
|
+
if((ctx->cPfns < 0x1000) || (ctx->cPfns > 0x14000000)) {
|
|
439
|
+
lcprintf(ctxLC, "DEVICE: HIBR: FAIL: Hibernation set shows incorrect memory dump size: %llu pages.\n", ctx->cPfns);
|
|
440
|
+
goto fail;
|
|
441
|
+
}
|
|
442
|
+
if(!(ctx->pdwPfn2CS = LocalAlloc(LMEM_ZEROINIT, (SIZE_T)ctx->cPfns * sizeof(DWORD)))) {
|
|
443
|
+
lcprintf(ctxLC, "DEVICE: HIBR: FAIL: Out of memory, #PFNs: %llu.\n", ctx->cPfns);
|
|
444
|
+
goto fail;
|
|
445
|
+
}
|
|
446
|
+
// 5: process restoration sets:
|
|
447
|
+
DeviceHibr_HibrInitialize_RestoreSet(ctxLC, cboRestoreBoot, cPagesLoader);
|
|
448
|
+
DeviceHibr_HibrInitialize_RestoreSet(ctxLC, cboRestoreKernel, cPagesKernel);
|
|
449
|
+
if(ctx->cCS < 0x10) {
|
|
450
|
+
lcprintf(ctxLC, "DEVICE: HIBR: FAIL: Too few compression sets found: %i.\n", ctx->cCS);
|
|
451
|
+
goto fail;
|
|
452
|
+
}
|
|
453
|
+
return TRUE;
|
|
454
|
+
fail:
|
|
455
|
+
return FALSE;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
//-----------------------------------------------------------------------------
|
|
461
|
+
// OPEN/CLOSE FUNCTIONALITY BELOW:
|
|
462
|
+
//-----------------------------------------------------------------------------
|
|
463
|
+
|
|
464
|
+
VOID DeviceHibr_CloseInternal(_Frees_ptr_opt_ PDEVICE_CONTEXT_FILE ctx)
|
|
465
|
+
{
|
|
466
|
+
DWORD i;
|
|
467
|
+
if(ctx) {
|
|
468
|
+
if(ctx->hFile) { fclose(ctx->hFile); }
|
|
469
|
+
for(i = 0; (i < HIBR_COMPRESSION_DIRECTORY_SIZE) && ctx->CS_Directory[i]; i++) {
|
|
470
|
+
LocalFree(ctx->CS_Directory[i]);
|
|
471
|
+
}
|
|
472
|
+
LocalFree(ctx->pdwPfn2CS);
|
|
473
|
+
LocalFree(ctx);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
VOID DeviceHibr_Close(_Inout_ PLC_CONTEXT ctxLC)
|
|
478
|
+
{
|
|
479
|
+
PDEVICE_CONTEXT_FILE ctx = (PDEVICE_CONTEXT_FILE)ctxLC->hDevice;
|
|
480
|
+
DeviceHibr_CloseInternal(ctx);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
#define DEVICE_FILE_PARAMETER_FILE "file"
|
|
484
|
+
|
|
485
|
+
/*
|
|
486
|
+
* Open a Windows hibernation file. Syntax: -device hibr://file=<filename>
|
|
487
|
+
* -- ctxLC
|
|
488
|
+
* -- ppLcCreateErrorInfo
|
|
489
|
+
* -- return = TRUE on success, FALSE on failure.
|
|
490
|
+
*/
|
|
491
|
+
_Success_(return)
|
|
492
|
+
BOOL DeviceHIBR_Open(_Inout_ PLC_CONTEXT ctxLC, _Out_opt_ PPLC_CONFIG_ERRORINFO ppLcCreateErrorInfo)
|
|
493
|
+
{
|
|
494
|
+
PDEVICE_CONTEXT_FILE ctx;
|
|
495
|
+
PLC_DEVICE_PARAMETER_ENTRY pParam;
|
|
496
|
+
QWORD tmEnd = 0, tmStart = GetTickCount64();
|
|
497
|
+
if(ppLcCreateErrorInfo) { *ppLcCreateErrorInfo = NULL; }
|
|
498
|
+
if(!(ctx = (PDEVICE_CONTEXT_FILE)LocalAlloc(LMEM_ZEROINIT, sizeof(DEVICE_CONTEXT_FILE)))) { return FALSE; }
|
|
499
|
+
if(!(ctx->CS_Directory[0] = (PHIBR_COMPRESSION_SET_TABLE)LocalAlloc(LMEM_ZEROINIT, sizeof(HIBR_COMPRESSION_SET_TABLE)))) { goto fail; }
|
|
500
|
+
ctx->cCS = 1; // 0 = reserved for invalid/not set compression set.
|
|
501
|
+
if(0 == _strnicmp("hibr://", ctxLC->Config.szDevice, 7)) {
|
|
502
|
+
if((pParam = LcDeviceParameterGet(ctxLC, DEVICE_FILE_PARAMETER_FILE)) && pParam->szValue) {
|
|
503
|
+
strncpy_s(ctx->szFileName, _countof(ctx->szFileName), pParam->szValue, _TRUNCATE);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
if(!ctx->szFileName[0]) { goto fail; }
|
|
507
|
+
lcprintfv(ctxLC, "DEVICE: HIBR: OPEN: '%s'\n", ctx->szFileName);
|
|
508
|
+
// initialize decompression:
|
|
509
|
+
if(!DeviceHibr_InitializeFunctions(ctx)) {
|
|
510
|
+
lcprintf(ctxLC, "DEVICE: HIBR: Failed to load compression function [libMSCompression.so missing?].\n");
|
|
511
|
+
goto fail;
|
|
512
|
+
}
|
|
513
|
+
// open backing file:
|
|
514
|
+
if(fopen_s(&ctx->hFile, ctx->szFileName, "rb") || !ctx->hFile) { goto fail; }
|
|
515
|
+
if(_fseeki64(ctx->hFile, 0, SEEK_END)) { goto fail; } // seek to end of file
|
|
516
|
+
ctx->cbFile = _ftelli64(ctx->hFile); // get current file pointer
|
|
517
|
+
if(ctx->cbFile < 0x01000000) { goto fail; } // minimum allowed file size = 16MB
|
|
518
|
+
if(ctx->cbFile > 0xffff000000000000) { goto fail; } // file too large
|
|
519
|
+
// set callback functions and fix up config:
|
|
520
|
+
ctxLC->hDevice = (HANDLE)ctx;
|
|
521
|
+
ctxLC->pfnClose = DeviceHibr_Close;
|
|
522
|
+
ctxLC->pfnReadScatter = DeviceHibr_ReadScatter;
|
|
523
|
+
if(!DeviceHibr_HibrInitialize(ctxLC)) { ctxLC->hDevice = NULL; goto fail; }
|
|
524
|
+
ctxLC->Config.paMax = ctx->cPfns * 0x1000;
|
|
525
|
+
// print result and return:
|
|
526
|
+
tmEnd = GetTickCount64();
|
|
527
|
+
lcprintfv(ctxLC, "DEVICE: HIBR: Successfully hibernation file in %llus.\n", (tmEnd - tmStart) / 1000);
|
|
528
|
+
return TRUE;
|
|
529
|
+
fail:
|
|
530
|
+
DeviceHibr_CloseInternal(ctx);
|
|
531
|
+
lcprintf(ctxLC, "DEVICE: HIBR: ERROR: Failed opening file: '%s'.\n", ctxLC->Config.szDevice);
|
|
532
|
+
return FALSE;
|
|
533
|
+
}
|