F - Restoring Table(按位与,按位或)

本文深入探讨了一个利用位与操作还原原数序列的编程问题,通过实例演示如何通过位与操作符及位或操作符解决实际编程挑战。文章详细解释了位操作的基础知识,并提供了代码实现,帮助读者理解如何从给定的矩阵中恢复原始数值序列。
这题坑爹。。按位没学好。&是同为1,结果才是1,而|是同为0,结果才是0,这样num1&num2,num1&num3,num1&num4,得到的结果里的二进制含有1的位数,则在原数num1和num2.3.4里肯定是1,含有0的位数,要么在原数中是0,要么在num2.3.4中是0,或者都是0
 
所以用|运算,把有1的位数(原数中肯定此位是1)都先还原回去,然后多次操作叠加起来。就能还原出一组可能的数据了(注意:只是可能的一组数据,因为会有多组解,无法都找到)
 
F - Restoring Table
Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u

Description

Recently Polycarpus has learned the "bitwise AND" operation (which is also called "AND") of non-negative integers. Now he wants to demonstrate the school IT teacher his superb manipulation with the learned operation.

For that Polycarpus came to school a little earlier and wrote on the board a sequence of non-negative integers a1, a2, ..., an. He also wrote a square matrix b of size n × n. The element of matrix b that sits in the i-th row in the j-th column (we'll denote it as bij) equals:

  • the "bitwise AND" of numbers ai and aj (that is, bij = ai & aj), if i ≠ j;
  • -1, if i = j.

Having written out matrix b, Polycarpus got very happy and wiped a off the blackboard. But the thing is, the teacher will want this sequence to check whether Polycarpus' calculations were correct. Polycarus urgently needs to restore the removed sequence of integers, or else he won't prove that he can count correctly.

Help Polycarpus, given matrix b, restore the sequence of numbers a1, a2, ..., an, that he has removed from the board. Polycarpus doesn't like large numbers, so any number in the restored sequence mustn't exceed 109.

Input

The first line contains a single integer n(1 ≤ n ≤ 100) — the size of square matrix b. Next n lines contain matrix b. The i-th of these lines contains n space-separated integers: the j-th number represents the element of matrix bij. It is guaranteed, that for all i(1 ≤ i ≤ n) the following condition fulfills: bii = -1. It is guaranteed that for all i, j(1 ≤ i, j ≤ ni ≠ j) the following condition fulfills: 0 ≤ bij ≤ 109, bij = bji.

Output

Print n non-negative integers a1, a2, ..., an(0 ≤ ai ≤ 109) — the sequence that Polycarpus wiped off the board. Separate the numbers by whitespaces.

It is guaranteed that there is sequence a that satisfies the problem conditions. If there are multiple such sequences, you are allowed to print any of them.

Sample Input

Input
1
-1
Output
0 
Input
3
-1 18 0
18 -1 0
0 0 -1
Output
18 18 0 
Input
4
-1 128 128 128
128 -1 148 160
128 148 -1 128
128 160 128 -1
Output
128 180 148 160 

Hint

If you do not know what is the "bitwise AND" operation please read: http://en.wikipedia.org/wiki/Bitwise_operation.

 

下附代码

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<math.h>
 5 #include<queue>
 6 #include<algorithm>
 7 using namespace std;
 8 char s[5001];
 9 int a[500][500]={0};
10 int b[501]={0};
11 int main()
12 {
13     int n,i,j;
14     scanf("%d",&n);
15     for(i=0;i<n;i++)
16         for(j=0;j<n;j++)
17         {
18             scanf("%d",&a[i][j]);
19             if(i!=j)
20                 b[i]|=a[i][j];
21         }
22     for(i=0;i<n-1;i++)
23         printf("%d ",b[i]);
24     printf("%d\n",b[n-1]);
25     return 0;
26 }

 

转载于:https://www.cnblogs.com/linminxuan/p/4471655.html

#include <ntifs.h> #include <ntddk.h> #include <intrin.h> #include "ptehook.h" #define CR0_WP (1 << 16) #define DRIVER_TAG 'HKOB' #define MAX_G_BIT_RECORDS 128 #define MAX_HOOK_COUNT 64 #define PAGE_ALIGN(va) ((PVOID)((ULONG_PTR)(va) & ~0xFFF)) #define PTE_NX_BIT (1ULL << 63) // 调试打印宏 #define LOG_ERROR(fmt, ...) \ DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[PTE_HOOK] ERROR: " fmt "\n", ##__VA_ARGS__) #define LOG_INFO(fmt, ...) \ DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "[PTE_HOOK] INFO: " fmt "\n", ##__VA_ARGS__) #define LOG_TRACE(fmt, ...) \ DbgPrintEx(DPFLTR极IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "[PTE_HOOK] TRACE: " fmt "\n", ##__VA_ARGS__) // 修正的跳板指令结构 #pragma pack(push, 1) typedef struct _JMP_ABS { UINT8 opcode[6]; // FF 25 00 00 00 00 = jmp [rip+0] ULONG64 address; // 目标地址 (紧跟在指令后) } JMP_ABS, * PJMP_ABS; #pragma pack(pop) static_assert(sizeof(JMP_ABS) == 14, "JMP_ABS size must be 14 bytes"); // 声明PsGetProcessImageFileName extern "C" NTSYSAPI CHAR* NTAPI PsGetProcessImageFileName(PEPROCESS Process); // 页表结构定义 typedef struct _PAGE_TABLE { UINT64 LineAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 极; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 ignored_1 : 1; UINT64 page_size : 1; UINT64 ignored_2 : 4; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdpteAddress; UINT64* Pml4Address; BOOLEAN IsLargePage; BOOLEAN Is1GBPage; UINT64 OriginalPte; UINT64 OriginalPde; UINT64 OriginalPdpte; UINT64 OriginalPml4e; HANDLE ProcessId; } PAGE_TABLE, * PPAGE_TABLE; // G位信息记录结构体 typedef struct _G_BIT_INFO { void* AlignAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 large_page : 1; UINT64 global : 1; UINT64 ignored_2 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_3 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PdeAddress; union { struct { UINT64 present : 1; UINT64 write : 1; UINT64 user : 1; UINT64 write_through : 1; UINT64 cache_disable : 1; UINT64 accessed : 1; UINT64 dirty : 1; UINT64 pat : 1; UINT64 global : 1; UINT64 ignored_1 : 3; UINT64 page_frame_number : 36; UINT64 reserved_1 : 4; UINT64 ignored_2 : 7; UINT64 protection_key : 4; UINT64 execute_disable : 1; } flags; UINT64 value; }*PteAddress; BOOLEAN IsLargePage; } G_BIT_INFO, * PG_BIT_INFO; typedef struct _HOOK_INFO { void* OriginalAddress; void* HookAddress; UINT8 OriginalBytes[20]; UINT8 HookBytes[20]; UINT32 HookLength; BOOLEAN IsHooked; HANDLE ProcessId; UINT64 OriginalPteValue; UINT64 HookedPteValue; } HOOK_INFO; class PteHookManager { public: bool fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr); bool fn_remove_hook(HANDLE process_id, void* hook_addr); static PteHookManager* GetInstance(); HOOK_INFO* GetHookInfo() { return m_HookInfo; } char* GetTrampLinePool() { return m_TrampLinePool; } UINT32 GetHookCount() { return m_HookCount; } bool fn_resume_global_bits(void* align_addr); ~PteHookManager(); private: bool WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd); bool SetPageExecution(void* address, bool executable); void fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address); bool fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde); bool fn_isolation_pages(HANDLE process_id, void* ori_addr); bool fn_split_large_pages(void* in_pde, void* out_pde); NTSTATUS get_page_table(UINT64 cr3, PAGE_TABLE& table); void* fn_pa_to_va(UINT64 pa); UINT64 fn_va_to_pa(void* va); __forceinline KIRQL DisableWriteProtection(); __forceinline void EnableWriteProtection(KIRQL oldIrql); void FlushCacheAndTlb(void* address); G_BIT_INFO m_GbitRecords[MAX_G_BIT_RECORDS]; UINT32 m_GbitCount = 0; void* m_PteBase = 0; HOOK_INFO m_HookInfo[MAX_HOOK_COUNT] = { 0 }; UINT32 m_HookCount = 0; char* m_TrampLinePool = nullptr; UINT32 m_PoolUsed = 0; static PteHookManager* m_Instance; }; PteHookManager* PteHookManager::m_Instance = nullptr; // 实现部分 __forceinline KIRQL P极HookManager::DisableWriteProtection() { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); UINT64 cr0 = __readcr0(); __writecr0(cr0 & ~CR0_WP); // 清除CR0.WP位 _mm_mfence(); return oldIrql; } __forceinline void PteHookManager::EnableWriteProtection(KIRQL oldIrql) { _mm_mfence(); UINT64 cr0 = __readcr0(); __writecr0(cr0 | CR0_WP); // 设置CR0.WP位 KeLowerIrql(oldIrql); } void* PteHookManager::fn_pa_to_va(UINT64 pa) { PHYSICAL_ADDRESS physAddr; physAddr.QuadPart = pa; return MmGetVirtualForPhysical(physAddr); } UINT64 PteHookManager::fn_va_to_pa(void* va) { PHYSICAL_ADDRESS physAddr = MmGetPhysicalAddress(va); return physAddr.QuadPart; } NTSTATUS PteHookManager::get_page_table(UINT64 cr3_val, PAGE_TABLE& table) { UINT64 va = table.LineAddress; UINT64 pml4e_index = (va >> 39) & 0x1FF; UINT64 pdpte_index = (va >> 30) & 0x1FF; UINT64 pde_index = (va >> 21) & 0x1FF; UINT64 pte_index = (va >> 12) & 0x1FF; // PML4 UINT64 pml4_pa = cr3_val & ~0xFFF; UINT64* pml4_va = (UINT64*)fn_pa_to_va(pml4_pa); if (!pml4_va) return STATUS_INVALID_ADDRESS; table.Pml4Address = &pml4_va[pml4e_index]; table.OriginalPml4e = *table.Pml4Address; if (!(table.OriginalPml4e & 1)) return STATUS_ACCESS_VIOLATION; // PDPTE UINT64 pdpte_pa = table.OriginalPml4e & ~0xFFF; UINT64* pdpte_va = (UINT64*)fn_pa_to_va(pdpte_pa); if (!pdpte_va) return STATUS_INVALID_ADDRESS; table.PdpteAddress = (decltype(table.PdpteAddress))&pdpte_va[pdpte_index]; table.OriginalPdpte = table.PdpteAddress->value; table.Is1GBPage = (table.PdpteAddress->flags.page_size) ? TRUE : FALSE; if (!(table.OriginalPdpte & 1)) return STATUS_ACCESS_VIOLATION; if (table.Is1GBPage) return STATUS_SUCCESS; // PDE UINT64 pde_pa = table.OriginalPdpte & ~0xFFF; UINT64* pde_va = (UINT64*)fn_pa_to_va(pde_pa); if (!pde_va) return STATUS_INVALID_ADDRESS; table.PdeAddress = (decltype(table.PdeAddress))&pde_va[pde_index]; table.OriginalPde = table.PdeAddress->value; table.IsLargePage = (table.PdeAddress->flags.large_page) ? TRUE : FALSE; if (!(table.OriginalPde & 1)) return STATUS_ACCESS_VIOLATION; if (table.IsLargePage) return STATUS_SUCCESS; // PTE UINT64 pte_pa = table.OriginalPde & ~0xFFF; UINT64* pte_va = (UINT64*)fn_pa_to_va(pte_pa); if (!pte_va) return STATUS_INVALID_ADDRESS; table.PteAddress = (decltype(table.PteAddress))&pte_va[pte_index]; table.OriginalPte = table.PteAddress->value; if (!(table.OriginalPte & 1)) return STATUS_ACCESS_VIOLATION; LOG_TRACE("Page Table Info: VA=0x%p, PTE=0x%llX", (void*)table.LineAddress, table.OriginalPte); return STATUS_SUCCESS; } bool PteHookManager::fn_split_large_pages(void* in_pde_ptr, void* out_pde_ptr) { auto in_pde = (decltype(PAGE_TABLE::PdeAddress))in_pde_ptr; auto out_pde = (decltype(PAGE_TABLE::PdeAddress))out_pde_ptr; LOG_INFO("Splitting large page: Input PDE=0x%llx", in_pde->value); PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; auto pt = (decltype(PAGE_TABLE::PteAddress))MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!pt) { LOG_ERROR("Failed to allocate contiguous memory for page splitting"); return false; } UINT64 start_pfn = in_pde->flags.page_frame_number; for (int i = 0; i < 512; i++) { pt[i].value = 0; pt[i].flags.present = 1; pt[i].flags.write = in_pde->flags.write; pt[i].flags.user = in_pde->flags.user; pt[i].flags.write_through = in_pde->flags.write_through; pt[i].flags.cache_disable = in_pde->flags.cache_disable; pt[i].flags.accessed = in_pde->flags.accessed; pt[i].flags.dirty = in_pde->flags.dirty; pt[i].flags.global = 0; pt[i].flags.page_frame_number = start_pfn + i; } out_pde->value = in_pde->value; out_pde->flags.large_page = 0; out_pde->flags.page_frame_number = fn_va_to_pa(pt) >> 12; LOG_INFO("Large page split complete: New PTE table at PA=0x%llx", fn_va_to_pa(pt)); return true; } bool PteHookManager::SetPageExecution(void* address, bool executable) { // 使用页表遍历函数修改NX位 PAGE_TABLE table = { 0 }; table.LineAddress = (UINT64)address; NTSTATUS status = get_page_table(__readcr3(), table); if (!NT_SUCCESS(status)) { LOG_ERROR("Failed to get page table for address 0x%p", address); return false; } KIRQL oldIrql = DisableWriteProtection(); UINT64 oldPte = table.PteAddress->value; UINT64 newPte = oldPte; // 设置或清除NX位 if (executable) { newPte &= ~PTE_NX_BIT; } else { newPte |= PTE_NX_BIT; } table.PteAddress->value = newPte; // 刷新TLB __invlpg(address); _mm_mfence(); EnableWriteProtection(oldIrql); LOG_TRACE("PTE modified for 0x%p: Old=0x%llX, New=0x%llX", address, oldPte, newPte); return true; } bool PteHookManager::fn_isolation_pagetable(UINT64 cr3_val, void* replace_align_addr, void* split_pde_ptr) { PHYSICAL_ADDRESS LowAddr = { 0 }, HighAddr = { 0 }; HighAddr.QuadPart = MAXULONG64; LOG_INFO("Isolating page table: CR3=0x%llx, Address=0x%p", cr3_val, replace_align_addr); auto Va4kb = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, Low极, MmNonCached); auto VaPdt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); auto VaPdpt = (UINT64*)MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, LowAddr, HighAddr, LowAddr, MmNonCached); if (!VaPt || !Va4kb || !VaPdt || !VaPdpt) { if (VaPt) MmFreeContiguousMemory(VaPt); if (Va4kb) MmFreeContiguousMemory(Va4kb); if (VaPdt) MmFreeContiguousMemory(VaPdt); if (VaPdpt) MmFreeContiguousMemory(VaPd极); LOG_ERROR("Failed to allocate contiguous memory for isolation"); return false; } PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)replace_align_addr; NTSTATUS status = get_page_table(cr3_val, Table); if (!NT_SUCCESS(status)) { MmFreeContiguousMemory(VaPt); MmFreeContiguousMemory(Va4kb); MmFreeContiguousMemory(VaPdt); MmFreeContiguousMemory(VaPdpt); LOG_ERROR("get_page_table failed with status 0x%X", status); return false; } UINT64 pte_index = (Table.LineAddress >> 12) & 0x1FF; UINT64 pde_index = (Table.LineAddress >> 21) & 0x1FF; UINT64 pdpte_index = (Table.LineAddress >> 30) & 0x1FF; UINT64 pml4e_index = (Table.LineAddress >> 39) & 0x1FF; memcpy(Va4kb, replace_align_addr, PAGE_SIZE); if (Table.IsLargePage && split_pde_ptr) { auto split_pde = (decltype(PAGE_TABLE::PdeAddress))split_pde_ptr; memcpy(VaPt, (void*)(split_pde->flags.page_frame_number << 12), PAGE_SIZE); } else { memcpy(VaPt, (void*)(Table.PdeAddress->flags.page_frame_number << 12), PAGE_SIZE); } memcpy(VaPdt, (void*)(Table.PdpteAddress->flags.page_frame_number << 12), PAGE_SIZE); memcpy(VaPdpt, (void*)(Table.Pml4Address[pml4e_index] & ~0xFFF), PAGE_SIZE); auto new_pte = (decltype(PAGE_TABLE::PteAddress))VaPt; new_pte[pte_index].flags.page_frame_number = fn_va_to_pa(Va4kb) >> 12; auto new_pde = (decltype(PAGE_TABLE::PdeAddress))VaPdt; new_pde[pde_index].value = Table.OriginalPde; new_pde[pde_index].flags.large_page = 0; new_pde[pde_index].flags.page_frame_number = fn_va_to_pa(VaPt) >> 12; auto new_pdpte = (decltype(PAGE_TABLE::PdpteAddress))VaPdpt; new_pdpte[pdpte_index].flags.page_frame_number = fn_va_to_pa(VaPdt) >> 12; auto new_pml4 = (UINT64*)fn_pa_to_va(cr3_val & ~0xFFF); new_pml4[pml4e_index] = (new_pml4[pml4e_index] & 0xFFF) | (fn_va_to_pa(VaPdpt) & ~0xFFF); __invlpg(replace_align_addr); LOG_INFO("Page table isolation complete: New PFN=0x%llx", fn_va_to_pa(Va4kb) >> 12); return true; } bool PteHookManager::fn_isolation_pages(HANDLE process_id, void* ori_addr) { PEPROCESS Process; if (!NT_SUCCESS(PsLookupProcessByProcessId(process_id, &Process))) { LOG_ERROR("PsLookupProcessByProcessId failed"); return false; } LOG_INFO("Isolating pages: PID=%d, Address=0x%p", HandleToUlong(process_id), ori_addr); KAPC_STATE ApcState; KeStackAttachProcess(Process, &ApcState); void* AlignAddr = PAGE_ALIGN(ori_addr); PAGE_TABLE Table = { 0 }; Table.LineAddress = (UINT64)AlignAddr; UINT64 target_cr3 = *(UINT64*)((UCHAR*)Process + 0x28); if (!NT_SUCCESS(get_page_table(target_cr3, Table))) { KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); LOG_ERROR("get_page_table failed"); return false; } bool success = false; decltype(PAGE_TABLE::PdeAddress) split_pde = nullptr; if (Table.IsLargePage) { split_pde = (decltype(PAGE_TABLE::PdeAddress))ExAllocatePoolWithTag(NonPagedPool, sizeof(*split_pde), 'pdeS'); if (!split_pde || !fn_split_large_pages(Table.PdeAddress, split_pde)) { if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); LOG_ERROR("Splitting large page failed"); return false; } if (Table.PdeAddress->flags.global) { Table.PdeAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, Table.PdeAddress, nullptr); LOG_INFO("Cleared G-bit for large page PDE: 0x%llx", Table.PdeAddress->value); } } else if (Table.PteAddress && Table.PteAddress->flags.global) { Table.PteAddress->flags.global = 0; fn_add_g_bit_info(AlignAddr, nullptr, Table.PteAddress); LOG_INFO("Cleared G-bit for PTE: 0x%llx", Table.PteAddress->value); } success = fn_isolation_pagetable(__readcr3(), AlignAddr, split_pde); if (split_pde) ExFreePoolWithTag(split_pde, 'pdeS'); KeUnstackDetachProcess(&ApcState); ObDereferenceObject(Process); if (success) { LOG_INFO("Page isolation successful"); } else { LOG_ERROR("Page isolation failed"); } return success; } bool PteHookManager::WriteTrampolineInstruction(void* trampoline, const JMP_ABS& jmpCmd) { // 确保8字节对齐 if (reinterpret_cast<ULONG_PTR>(trampoline) & 0x7) { LOG_ERROR("Trampoline address not aligned: 0x%p", trampoline); return false; } // 禁用写保护 KIRQL oldIrql = DisableWriteProtection(); // 直接写入内存 RtlCopyMemory(trampoline, &jmpCmd, sizeof(JMP_ABS)); // 刷新缓存 __invlpg(trampoline); _mm_mfence(); // 恢复写保护 EnableWriteProtection(oldIrql); LOG_TRACE("Trampoline instruction written at 0x%p", trampoline); return true; } void PteHookManager::fn_add_g_bit_info(void* align_addr, void* pde_address, void* pte_address) { if (m_GbitCount >= MAX_G_BIT_RECORDS) { LOG_ERROR("Max G-bit records reached"); return; } PG_BIT_INFO record = &m_GbitRecords[m_GbitCount++]; record->AlignAddress = align_addr; record->PdeAddress = (decltype(G_BIT_INFO::PdeAddress))pde_address; record->PteAddress = (decltype(G_BIT_INFO::PteAddress))pte_address; record->IsLargePage = (pde_address != nullptr); LOG_TRACE("Added G-bit record: Address=0x%p, PDE=0x%p, PTE=0x%p", align_addr, pde_address, pte_address); } bool PteHookManager::fn_resume_global_bits(void* align_addr) { KIRQL oldIrql = DisableWriteProtection(); bool found = false; LOG_INFO("Restoring G-bits for address: 0x%p", align_addr); for (UINT32 i = 0; i < m_GbitCount; i++) { PG_BIT_INFO record = &m_GbitRecords[i]; if (align_addr && record->AlignAddress != align_addr) continue; if (record->PteAddress) { record->PteAddress->flags.global = 1; __invlpg(record->AlignAddress); LOG_TRACE("Restored G-bit for PTE: 0x%p", record->AlignAddress); } if (record->PdeAddress) { record->PdeAddress->flags.global = 1; if (record->IsLargePage) { __invlpg(record->AlignAddress); } LOG_TRACE("Restored G-bit for PDE: 0x%p", record->AlignAddress); } found = true; if (align_addr) break; } EnableWriteProtection(oldIrql); if (found) { LOG_INFO("G-bits restoration complete"); } else { LOG_ERROR("No matching G-bit record found"); } return found; } bool PteHookManager::fn_pte_inline_hook_bp_pg(HANDLE process_id, _Inout_ void** ori_addr, void* hk_addr) { if (!ori_addr || !hk_addr || !*ori_addr) { LOG_ERROR("Invalid parameters: ori_addr=%p, hk_addr=%p", ori_addr, hk_addr); return false; } // 分配跳板池(如果尚未分配) if (!m_TrampLinePool) { PHYSICAL_ADDRESS LowAddr; LowAddr.QuadPart = 0x100000; PHYSICAL_ADDRESS HighAddr; HighAddr.QuadPart = ~0ull; m_TrampLinePool = (char*)MmAllocateContiguousMemorySpecifyCache( PAGE_SIZE * 8, LowAddr, HighAddr, LowAddr, MmNonCached); if (!m_TrampLinePool) { LOG_ERROR("Failed to allocate trampoline pool"); return false; } // 设置跳板池可执行 if (!SetPageExecution(m_TrampLinePool, true)) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; LOG_ERROR("Failed to set trampoline pool executable"); return false; } LOG_INFO("Trampoline pool allocated: Address=0x%p, Size=%d bytes", m_TrampLinePool, PAGE_SIZE * 8); } // 计算跳板位置(16字节对齐确保RIP相对寻址) void* trampoline = (void*)((ULONG_PTR)(m_TrampLinePool + m_PoolUsed + 15) & ~15); SIZE_T requiredSize = ((char*)trampoline - m_TrampLinePool) + sizeof(JMP_ABS); // 检查跳板池空间 if (requiredSize > PAGE_SIZE * 8) { LOG_ERROR("Trampoline pool out of space: Used=%d, Required=%d", m_PoolUsed, requiredSize); return false; } // 构造跳转指令 JMP_ABS jmpCmd; memcpy(jmpCmd.opcode, "\xFF\x25\x00\x00\x00\x00", 6); // jmp [rip+0] jmpCmd.address = reinterpret_cast<ULONG64>(hk_addr); LOG_INFO("Constructing jump instruction: Target=0x%p, Trampoline=0x%p", hk_addr, trampoline); // 写入跳板指令 if (!WriteTrampolineInstruction(trampoline, jmpCmd)) { return false; } // 设置目标函数不可执行(触发页错误) if (!SetPageExecution(*ori_addr, false)) { LOG_ERROR("Failed to set target function non-executable"); return false; } // 记录Hook信息 bool hookRecorded = false; for (UINT32 i = 0; i < MAX_HOOK_COUNT; i++) { if (!m_HookInfo[i].IsHooked) { m_HookInfo[i].OriginalAddress = *ori_addr; m_HookInfo[i].HookAddress = trampoline; m_HookInfo[i].ProcessId = process_id; m_HookInfo极i].IsHooked = TRUE; m_HookInfo[i].HookLength = sizeof(JMP_ABS); RtlCopyMemory(m_HookInfo[i].HookBytes, &jmpCmd, sizeof(jmpCmd)); // 保存原始PTE值 PAGE_TABLE table = { 0 }; table.LineAddress = (UINT64)*ori_addr; if (NT_SUCCESS(get_page_table(__readcr3(), table))) { m_HookInfo[i].OriginalPteValue = table.OriginalPte; } m_HookCount++; hookRecorded = true; LOG_INFO("Hook recorded #%d: Original=0x%p, Trampoline=0x%p", i, *ori_addr, trampoline); break; } } if (!hookRecorded) { LOG_ERROR("Exceeded max hook count (%d)", MAX_HOOK_COUNT); return false; } // 更新原始地址为跳板地址 *ori_addr = trampoline; m_PoolUsed = (UINT32)requiredSize; LOG_INFO("Hook installed successfully: Trampoline=0x%p -> Hook=0x%p", trampoline, hk_addr); return true; } bool PteHookManager::fn_remove_hook(HANDLE process_id, void* hook_addr) { LOG_INFO("Removing hook: HookAddr=0x%p", hook_addr); for (UINT32 i = 0; i < m_HookCount; i++) { if (m_HookInfo[i].HookAddress == hook_addr && m_HookInfo[i].IsHooked) { LOG_INFO("Found matching hook: OriginalAddr=0x%p", m_HookInfo[i].OriginalAddress); // 恢复目标函数执行权限 SetPageExecution(m_HookInfo[i].OriginalAddress, true); // 恢复原始PTE值 if (m_HookInfo[i].OriginalPteValue) { PAGE_TABLE table = { 0 }; table.LineAddress = (UINT64)m_HookInfo[i].OriginalAddress; if (NT_SUCCESS(get_page_table(__readcr3(), table))) { KIRQL oldIrql = KeRaiseIrqlToDpcLevel(); table.PteAddress->value = m_HookInfo[i].OriginalPteValue; __invlpg(m_HookInfo[i].OriginalAddress); KeLowerIrql(oldIrql); LOG_TRACE("Restored PTE for 0x%p: 0x%llX", m_HookInfo[i].OriginalAddress, m_HookInfo[i].OriginalPteValue); } } m_HookInfo[i].IsHooked = FALSE; LOG_INFO("Hook removed successfully"); return true; } } LOG_ERROR("No matching hook found"); return false; } PteHookManager::~PteHookManager() { if (m_TrampLinePool) { MmFreeContiguousMemory(m_TrampLinePool); m_TrampLinePool = nullptr; LOG_INFO("Trampoline pool freed"); } } PteHookManager* PteHookManager::GetInstance() { if (!m_Instance) { m_Instance = static_cast<PteHookManager*>( ExAllocatePoolWithTag(NonPagedPool, sizeof(PteHookManager), 'tpHk')); if (m_Instance) { RtlZeroMemory(m_Instance, sizeof(PteHookManager)); LOG_INFO("PTE Hook Manager instance created: 0x%p", m_Instance); } else { LOG_ERROR("Failed to create PTE Hook Manager instance"); } } return m_Instance; } // 全局PTE Hook管理器实例 PteHookManager* g_PteHookManager = nullptr; // 目标进程名称 const char target_process_name[] = "oxygen.exe"; // 辅助函数:检查是否为目标进程 BOOLEAN IsTargetProcess(CHAR* imageName) { CHAR currentName[16]; RtlZeroMemory(currentName, sizeof(currentName)); strncpy(currentName, imageName, sizeof(currentName) - 1); return (_stricmp(currentName, target_process_name) == 0); } // 函数类型定义 typedef NTSTATUS(*fn_ObReferenceObjectByHandleWithTag)( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ); fn_ObReferenceObjectByHandleWithTag g_OriginalObReferenceObjectByHandleWithTag = nullptr; // Hook 函数 NTSTATUS MyObReferenceObjectByHandleWithTag( HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, ULONG Tag, PVOID* Object, POBJECT_HANDLE_INFORMATION HandleInformation ) { PEPROCESS currentProcess = PsGetCurrentProcess(); CHAR* imageName = PsGetProcessImageFileName(currentProcess); LOG_INFO("Hook function called by process: %s", imageName); if (IsTargetProcess(imageName)) { LOG_INFO("Access denied for target process: %s", imageName); return STATUS_ACCESS_DENIED; } return g_OriginalObReferenceObjectByHandleWithTag( Handle, DesiredAccess, ObjectType, AccessMode, Tag, Object, HandleInformation ); } NTSTATUS InstallHook(HANDLE targetProcessId) { UNICODE_STRING funcName; RtlInitUnicodeString(&funcName, L"ObReferenceObjectByHandleWithTag"); g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)MmGetSystemRoutineAddress(&funcName); if (!g_OriginalObReferenceObjectByHandleWithTag) { LOG_ERROR("ObReferenceObjectByHandleWithTag not found"); return STATUS_NOT_FOUND; } LOG_INFO("Target function found: 0x%p", g_OriginalObReferenceObjectByHandleWithTag); void* targetFunc = (void*)g_OriginalObReferenceObjectByHandleWithTag; void* hookFunc = (void*)MyObReferenceObjectByHandleWithTag; if (!g_PteHookManager->fn_pte_inline_hook_bp_pg(targetProcessId, &targetFunc, hookFunc)) { LOG_ERROR("PTE Hook installation failed"); return STATUS_UNSUCCESSFUL; } g_OriginalObReferenceObjectByHandleWithTag = (fn_ObReferenceObjectByHandleWithTag)targetFunc; LOG_INFO("Hook installed successfully. Trampoline: 0x%p", targetFunc); return STATUS_SUCCESS; } // 移除 Hook VOID RemoveHook() { if (g_OriginalObReferenceObjectByHandleWithTag && g_PteHookManager) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), (void*)MyObReferenceObjectByHandleWithTag); } } // 工作线程上下文 typedef struct _HOOK_THREAD_CONTEXT { HANDLE TargetProcessId; } HOOK_THREAD_CONTEXT, * PHOOK_THREAD_CONTEXT; // 工作线程函数 VOID InstallHookWorker(PVOID Context) { PHOOK_THREAD_CONTEXT ctx = (PHOOK_THREAD_CONTEXT)Context; if (ctx) { LOG_INFO("Installing hook for PID: %d", HandleToUlong(ctx->TargetProcessId)); InstallHook(ctx->TargetProcessId); ExFreePoolWithTag(ctx, 'CtxH'); } PsTerminateSystemThread(STATUS_SUCCESS); } // 进程创建回调 - 修正后的签名 VOID ProcessNotifyCallback( _In_ PEPROCESS Process, _In_ HANDLE ProcessId, _In_opt_ PPS_CREATE_NOTIFY_INFO CreateInfo ) { if (CreateInfo != NULL) { // 进程创建 CHAR* imageName = PsGetProcessImageFileName(Process); if (IsTargetProcess(imageName)) { LOG_INFO("Target process created: %s (PID: %d)", imageName, HandleToUlong(ProcessId)); // 创建工作线程上下文 PHOOK_THREAD_CONTEXT ctx = (PHOOK_THREAD_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOK_THREAD_CONTEXT), 'CtxH'); if (ctx) { ctx->TargetProcessId = ProcessId; HANDLE threadHandle; NTSTATUS status = PsCreateSystemThread( &threadHandle, THREAD_ALL_ACCESS, NULL, NULL, NULL, InstallHookWorker, ctx ); if (NT_SUCCESS(status)) { ZwClose(threadHandle); LOG_INFO("Worker thread created for hook installation"); } else { ExFreePoolWithTag(ctx, 'CtxH'); LOG_ERROR("Failed to create worker thread: 0x%X", status); } } else { LOG_ERROR("Failed to allocate thread context"); } } } } // 驱动卸载函数 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); LOG_INFO("Driver unloading..."); // 移除进程通知回调 PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, TRUE); // 移除Hook RemoveHook(); // 清理PTE Hook资源 if (g_PteHookManager) { LOG_INFO("Cleaning up PTE Hook Manager"); // 恢复所有被修改的G位 g_PteHookManager->fn_resume_global_bits(nullptr); // 移除所有活动的Hook HOOK_INFO* hookInfo = g_PteHookManager->GetHookInfo(); UINT32 hookCount = g_PteHookManager->GetHookCount(); for (UINT32 i = 0; i < hookCount; i++) { if (hookInfo[i].IsHooked) { g_PteHookManager->fn_remove_hook(PsGetCurrentProcessId(), hookInfo[i].HookAddress); } } // 释放管理器实例 ExFreePoolWithTag(g_PteHookManager, 'tpHk'); g_PteHookManager = nullptr; } LOG_INFO("Driver unloaded successfully"); } extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(RegistryPath); LOG_INFO("Driver loading..."); DriverObject->DriverUnload = DriverUnload; g_PteHookManager = PteHookManager::GetInstance(); if (!g_PteHookManager) { LOG_ERROR("Failed to initialize PteHookManager"); return STATUS_INSUFFICIENT_RESOURCES; } NTSTATUS status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, FALSE); if (!NT_SUCCESS(status)) { LOG_ERROR("Failed to register process callback: 0x%X", status); return status; } LOG_INFO("Driver loaded successfully"); return STATUS_SUCCESS; } 严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0020 未定义标识符 "极" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 51 错误(活动) E0276 后面有“::”的名称一定是类名或命名空间名 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 203 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 276 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 349 错误(活动) E0020 未定义标识符 "Low极" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 360 错误(活动) E0020 未定义标识符 "VaPd极" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 368 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 508 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 524 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 541 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 549 错误(活动) E0020 未定义标识符 "m_HookInfo极i" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误(活动) E0065 应输入“;” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误(活动) E0020 未定义标识符 "DPFLTR极IHVDRIVER_ID" obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 687 错误 C2065 “极”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 51 错误 C2653 “P极HookManager”: 不是类或命名空间名称 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 203 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 276 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 349 错误 C2065 “Low极”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 360 错误 C3536 “VaPt”: 初始化之前无法使用 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 364 错误 C2664 “void MmFreeContiguousMemory(PVOID)”: 无法将参数 1 从“int”转换为“PVOID” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 365 错误 C2065 “VaPd极”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 368 错误 C2664 “void MmFreeContiguousMemory(PVOID)”: 无法将参数 1 从“int”转换为“PVOID” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 377 错误 C2664 “void *memcpy(void *,const void *,size_t)”: 无法将参数 1 从“int”转换为“void *” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 394 错误 C2664 “void *memcpy(void *,const void *,size_t)”: 无法将参数 1 从“int”转换为“void *” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 397 错误 C2664 “UINT64 PteHookManager::fn_va_to_pa(void *)”: 无法将参数 1 从“int”转换为“void *” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 409 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 508 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 524 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 541 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 549 错误 C2065 “m_HookInfo极i”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误 C2143 语法错误: 缺少“;”(在“]”的前面) obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误 C2059 语法错误:“]” obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 636 错误 C2065 “DPFLTR极IHVDRIVER_ID”: 未声明的标识符 obpcallback C:\Users\17116\source\repos\obpcallback\obpcallback\源.cpp 687
06-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值