aboutsummaryrefslogtreecommitdiff
path: root/PastDSEDriver/BlackBoneLoaderReloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'PastDSEDriver/BlackBoneLoaderReloc.c')
1 files changed, 395 insertions, 0 deletions
diff --git a/PastDSEDriver/BlackBoneLoaderReloc.c b/PastDSEDriver/BlackBoneLoaderReloc.c
new file mode 100644
index 0000000..64ccf2f
--- /dev/null
+++ b/PastDSEDriver/BlackBoneLoaderReloc.c
@@ -0,0 +1,395 @@
+/******************************************************
+* FILENAME:
+* BlackBonedLoaderReloc.c
+*
+* DESCRIPTION:
+* Driver utility functions.
+*
+* Copyright Toni Uhlig 2019. All rights reserved.
+*
+* AUTHOR:
+* DarthTon
+* Toni Uhlig START DATE : 27 Mar 19
+*/
+
+#pragma once
+
+#include "Driver.h"
+#include "PE.h"
+#include "Imports.h"
+
+#include <ntddk.h>
+
+/*++
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
+If you do not agree to the terms, do not use the code.
+
+
+Module Name:
+
+ ldrreloc.c
+
+Abstract:
+
+ This module contains the code to relocate an image when
+ the preferred base isn't available. This is called by the
+ boot loader, device driver loader, and system loader.
+
+--*/
+
+
+//
+// Mark a HIGHADJ entry as needing an increment if reprocessing.
+//
+#define LDRP_RELOCATION_INCREMENT 0x1
+
+//
+// Mark a HIGHADJ entry as not suitable for reprocessing.
+//
+#define LDRP_RELOCATION_FINAL 0x2
+
+
+/*
+#pragma alloc_text(PAGE,LdrRelocateImage)
+#pragma alloc_text(PAGE,LdrProcessRelocationBlock)
+#pragma alloc_text(PAGE,LdrProcessRelocationBlockLongLong)*/
+
+NTSTATUS
+LdrRelocateImage(__in PVOID NewBase)
+{
+ LONGLONG Diff;
+ ULONG TotalCountBytes = 0;
+ ULONG_PTR VA;
+ ULONGLONG OldBase;
+ ULONG SizeOfBlock;
+ PUSHORT NextOffset = NULL;
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_BASE_RELOCATION NextBlock;
+ NTSTATUS Status;
+
+ NtHeaders = RtlImageNtHeader(NewBase);
+ if (NtHeaders == NULL) {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Exit;
+ }
+
+ switch (NtHeaders->OptionalHeader.Magic) {
+
+ case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
+
+ OldBase =
+ ((PIMAGE_NT_HEADERS64)NtHeaders)->OptionalHeader.ImageBase;
+ break;
+
+ default:
+
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Exit;
+ }
+
+ //
+ // Locate the relocation section.
+ //
+
+ NextBlock = (PIMAGE_BASE_RELOCATION)RtlImageDirectoryEntryToData(
+ NewBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &TotalCountBytes);
+
+ //
+ // It is possible for a file to have no relocations, but the relocations
+ // must not have been stripped.
+ //
+
+ if (!NextBlock || !TotalCountBytes)
+ {
+ Status = (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) ? STATUS_CONFLICTING_ADDRESSES : STATUS_SUCCESS;
+ goto Exit;
+ }
+
+ //
+ // If the image has a relocation table, then apply the specified fixup
+ // information to the image.
+ //
+ Diff = (ULONG_PTR)NewBase - OldBase;
+ while (TotalCountBytes)
+ {
+ SizeOfBlock = NextBlock->SizeOfBlock;
+
+ // Prevent crash
+ if (SizeOfBlock == 0)
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Exit;
+ }
+
+ TotalCountBytes -= SizeOfBlock;
+ SizeOfBlock -= sizeof(IMAGE_BASE_RELOCATION);
+ SizeOfBlock /= sizeof(USHORT);
+ NextOffset = (PUSHORT)((PCHAR)NextBlock + sizeof(IMAGE_BASE_RELOCATION));
+
+ VA = (ULONG_PTR)NewBase + NextBlock->VirtualAddress;
+ NextBlock = LdrProcessRelocationBlockLongLong(VA, SizeOfBlock, NextOffset, Diff);
+
+ if (!NextBlock)
+ {
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Exit;
+ }
+ }
+
+ Status = STATUS_SUCCESS;
+Exit:
+ return Status;
+}
+
+PIMAGE_BASE_RELOCATION
+LdrProcessRelocationBlock(
+ IN ULONG_PTR VA,
+ IN ULONG SizeOfBlock,
+ IN PUSHORT NextOffset,
+ IN LONG_PTR Diff
+)
+{
+ PIMAGE_BASE_RELOCATION baseRelocation;
+
+ baseRelocation = LdrProcessRelocationBlockLongLong(VA, SizeOfBlock, NextOffset, (LONGLONG)Diff);
+
+ return baseRelocation;
+}
+
+// begin_rebase
+PIMAGE_BASE_RELOCATION
+LdrProcessRelocationBlockLongLong(
+ IN ULONG_PTR VA,
+ IN ULONG SizeOfBlock,
+ IN PUSHORT NextOffset,
+ IN LONGLONG Diff
+)
+{
+ PUCHAR FixupVA;
+ USHORT Offset;
+ LONG Temp;
+ //ULONG Temp32;
+ ULONGLONG Value64;
+ //LONGLONG Temp64;
+
+ while (SizeOfBlock--) {
+
+ Offset = *NextOffset & (USHORT)0xfff;
+ FixupVA = (PUCHAR)(VA + Offset);
+
+ //
+ // Apply the fixups.
+ //
+
+ switch ((*NextOffset) >> 12) {
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ //
+ // HighLow - (32-bits) relocate the high and low half
+ // of an address.
+ //
+ *(LONG UNALIGNED *)FixupVA += (ULONG)Diff;
+ break;
+
+ case IMAGE_REL_BASED_HIGH:
+ //
+ // High - (16-bits) relocate the high half of an address.
+ //
+ Temp = *(PUSHORT)FixupVA << 16;
+ Temp += (ULONG)Diff;
+ *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
+ break;
+
+ case IMAGE_REL_BASED_HIGHADJ:
+ //
+ // Adjust high - (16-bits) relocate the high half of an
+ // address and adjust for sign extension of low half.
+ //
+
+ //
+ // If the address has already been relocated then don't
+ // process it again now or information will be lost.
+ //
+ if (Offset & LDRP_RELOCATION_FINAL) {
+ ++NextOffset;
+ --SizeOfBlock;
+ break;
+ }
+
+ Temp = *(PUSHORT)FixupVA << 16;
+ ++NextOffset;
+ --SizeOfBlock;
+ Temp += (LONG)(*(PSHORT)NextOffset);
+ Temp += (ULONG)Diff;
+ Temp += 0x8000;
+ *(PUSHORT)FixupVA = (USHORT)(Temp >> 16);
+
+ break;
+
+ case IMAGE_REL_BASED_LOW:
+ //
+ // Low - (16-bit) relocate the low half of an address.
+ //
+ Temp = *(PSHORT)FixupVA;
+ Temp += (ULONG)Diff;
+ *(PUSHORT)FixupVA = (USHORT)Temp;
+ break;
+
+ case IMAGE_REL_BASED_IA64_IMM64:
+
+ //
+ // Align it to bundle address before fixing up the
+ // 64-bit immediate value of the movl instruction.
+ //
+
+ FixupVA = (PUCHAR)((ULONG_PTR)FixupVA & ~(15));
+ Value64 = (ULONGLONG)0;
+
+ //
+ // Extract the lower 32 bits of IMM64 from bundle
+ //
+
+ /*
+ EXT_IMM64(Value64,
+ (PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X,
+ EMARCH_ENC_I17_IMM7B_SIZE_X,
+ EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM7B_VAL_POS_X);
+ EXT_IMM64(Value64,
+ (PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X,
+ EMARCH_ENC_I17_IMM9D_SIZE_X,
+ EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM9D_VAL_POS_X);
+ EXT_IMM64(Value64,
+ (PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X,
+ EMARCH_ENC_I17_IMM5C_SIZE_X,
+ EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM5C_VAL_POS_X);
+ EXT_IMM64(Value64,
+ (PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X,
+ EMARCH_ENC_I17_IC_SIZE_X,
+ EMARCH_ENC_I17_IC_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IC_VAL_POS_X);
+ EXT_IMM64(Value64,
+ (PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X,
+ EMARCH_ENC_I17_IMM41a_SIZE_X,
+ EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM41a_VAL_POS_X);
+
+ EXT_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
+ EMARCH_ENC_I17_IMM41b_SIZE_X,
+ EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM41b_VAL_POS_X);
+ EXT_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
+ EMARCH_ENC_I17_IMM41c_SIZE_X,
+ EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM41c_VAL_POS_X);
+ EXT_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
+ EMARCH_ENC_I17_SIGN_SIZE_X,
+ EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
+ EMARCH_ENC_I17_SIGN_VAL_POS_X);
+ //
+ // Update 64-bit address
+ //
+
+ Value64+=Diff;
+
+ //
+ // Insert IMM64 into bundle
+ //
+
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM7B_INST_WORD_X),
+ EMARCH_ENC_I17_IMM7B_SIZE_X,
+ EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM7B_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM9D_INST_WORD_X),
+ EMARCH_ENC_I17_IMM9D_SIZE_X,
+ EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM9D_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM5C_INST_WORD_X),
+ EMARCH_ENC_I17_IMM5C_SIZE_X,
+ EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM5C_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IC_INST_WORD_X),
+ EMARCH_ENC_I17_IC_SIZE_X,
+ EMARCH_ENC_I17_IC_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IC_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41a_INST_WORD_X),
+ EMARCH_ENC_I17_IMM41a_SIZE_X,
+ EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM41a_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41b_INST_WORD_X),
+ EMARCH_ENC_I17_IMM41b_SIZE_X,
+ EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM41b_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_IMM41c_INST_WORD_X),
+ EMARCH_ENC_I17_IMM41c_SIZE_X,
+ EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X,
+ EMARCH_ENC_I17_IMM41c_VAL_POS_X);
+ INS_IMM64(Value64,
+ ((PULONG)FixupVA + EMARCH_ENC_I17_SIGN_INST_WORD_X),
+ EMARCH_ENC_I17_SIGN_SIZE_X,
+ EMARCH_ENC_I17_SIGN_INST_WORD_POS_X,
+ EMARCH_ENC_I17_SIGN_VAL_POS_X);
+ */
+ break;
+
+ case IMAGE_REL_BASED_DIR64:
+
+ *(ULONGLONG UNALIGNED *)FixupVA += Diff;
+
+ break;
+
+ case IMAGE_REL_BASED_MIPS_JMPADDR:
+ //
+ // JumpAddress - (32-bits) relocate a MIPS jump address.
+ //
+ Temp = (*(PULONG)FixupVA & 0x3ffffff) << 2;
+ Temp += (ULONG)Diff;
+ *(PULONG)FixupVA = (*(PULONG)FixupVA & ~0x3ffffff) |
+ ((Temp >> 2) & 0x3ffffff);
+
+ break;
+
+ case IMAGE_REL_BASED_ABSOLUTE:
+ //
+ // Absolute - no fixup required.
+ //
+ break;
+
+ case IMAGE_REL_BASED_SECTION:
+ //
+ // Section Relative reloc. Ignore for now.
+ //
+ break;
+
+ case IMAGE_REL_BASED_REL32:
+ //
+ // Relative intrasection. Ignore for now.
+ //
+ break;
+
+ default:
+ //
+ // Illegal - illegal relocation type.
+ //
+
+ return (PIMAGE_BASE_RELOCATION)NULL;
+ }
+ ++NextOffset;
+ }
+ return (PIMAGE_BASE_RELOCATION)NextOffset;
+} \ No newline at end of file