PG2 BYPASS源码阅读 学习x64解密定时器、特征码定位
以前没有接触过x64内核编程,借这份代码来学习一下,源码 http://www.codeproject.com/Articles/28318/Bypassing-PatchGuard-3
之前说到过PG3的一些机制,下面根据源码回顾一下
PG可能会queue一些dpc来触发syscheck,其中dpc context传入的是非传统地址,从而触发异常,转到异常处理去执行PG。
所以要判断dpc context
BOOLEAN CheckSubValue(ULONGLONG InValue)
{ULONG i;ULONG Result;UCHAR* Chars = (UCHAR*)&InValue;// random values will have a result around 120...Result = 0;for(i = 0; i < 8; i++){Result += ((Chars[i] & 0xF0) >> 4) + (Chars[i] & 0x0F);}// the maximum value is 240, so this should be safe...if(Result < 70)return TRUE;return FALSE;
}BOOLEAN PgIsPatchGuardContext(void* Ptr)
{ULONGLONG Value = (ULONGLONG)Ptr;UCHAR* Chars = (UCHAR*)&Value;LONG i;// this is a requirement for a canonical pointer...//合法地址if((Value & 0xFFFF000000000000) == 0xFFFF000000000000)return FALSE;//0 也不是非法的if((Value & 0xFFFF000000000000) == 0)return FALSE;// sieve out other common values...//检测随机数?if(CheckSubValue(Value) || CheckSubValue(~Value))return FALSE;if(Ptr == NULL)return FALSE;//This must be the last check and filters latin-char UTF16 strings...//检测字符串for(i = 7; i >= 0; i -= 2){if(Chars[i] != 0)return TRUE;}// this should only return true if the pointer is a unicode string!!!return FALSE;
}
这个检测还是考虑了不少情况,接下来是获得dpc加密key的方法
NTSTATUS PgInitialize()
{void* SymbolArray[MAX_SYMBOL_COUNT];void* ValidationArray[MAX_SYMBOL_COUNT];void* IntersectionArray[MAX_SYMBOL_COUNT];ULONG iSymbol;ULONG Index;ULONG MatchCount;KTIMER TestTimer;KDPC TestTimerDpc;LARGE_INTEGER TimerDueTime = {0};ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);/*Extract and validate methods...搜索同步用的未导出api,还是很谨慎的,用KeCancelTimer和KeSetTimerEx对比进行定位*/if(!ExtractSymbolAddresses((void*)KeCancelTimer, FALSE, 0xE8, OUT SymbolArray) ||!ExtractSymbolAddresses((void*)KeSetTimerEx, FALSE, 0xE8, OUT ValidationArray))return STATUS_NOT_SUPPORTED;if(IntersectSymbolAddresses(SymbolArray, ValidationArray, OUT IntersectionArray) != 5)return STATUS_NOT_SUPPORTED;KiAcquireDispatcherLockRaiseToSynch = IntersectionArray[0];KeAcquireQueuedSpinLockAtDpcLevel = IntersectionArray[1];KeReleaseQueuedSpinLockFromDpcLevel = IntersectionArray[2];KiReleaseDispatcherLockFromSynchLevel = IntersectionArray[3];KiExitDispatcher = IntersectionArray[4];/*Extract KiTimerTableListHead...*/if(!ExtractSymbolAddresses((void*)KeCancelTimer, TRUE, 0x8D48, OUT SymbolArray))return STATUS_NOT_SUPPORTED;if(!ExtractSymbolAddresses((void*)KeSetTimerEx, TRUE, 0x8D48, OUT ValidationArray))return STATUS_NOT_SUPPORTED;MatchCount = IntersectSymbolAddresses(SymbolArray, ValidationArray, OUT IntersectionArray);for(iSymbol = 0; iSymbol < MatchCount; iSymbol++){if(ValidateTimerTable(IntersectionArray[iSymbol])){// check if we found ambiguous symbol referencesKiTimerTableListHead = IntersectionArray[iSymbol];break;}}if(KiTimerTableListHead == NULL)return STATUS_NOT_SUPPORTED;/*Create test timer...We use a well known, probably unique DeferredContext for later identification...*/KeInitializeTimer(&TestTimer);KeInitializeDpc(&TestTimerDpc, OnTestTimerInvokation, (void*)PgInitialize);__try{KeSetTimerEx(&TestTimer, TimerDueTime, 10000, &TestTimerDpc);/*Extract KiWaitAlways and KiWaitNever一个特征码找到这两个值,然后验证*/if(!ExtractSymbolAddresses((void*)KeSetTimerEx, TRUE, 0x8B48, OUT SymbolArray))return STATUS_NOT_SUPPORTED;for(iSymbol = 0; iSymbol < MAX_SYMBOL_COUNT; iSymbol++){if(SymbolArray[iSymbol] == NULL)break;for(Index = 0; Index < MAX_SYMBOL_COUNT; Index++){if(SymbolArray[Index] == NULL)break;if(iSymbol == Index)continue;if(!ProbeAndSetKeys(&TestTimer,(ULONGLONG*)SymbolArray[iSymbol],(ULONGLONG*)SymbolArray[Index]))continue;return STATUS_SUCCESS;}}return STATUS_NOT_SUPPORTED;}__finally{// cleanup resourcesKeCancelTimer(&TestTimer);}
}
PG2非常简单,直接摘掉dpc了事
BOOLEAN PgDisablePatchGuard(PDEVICE_OBJECT InDevice)
{KIRQL OldIrql;ULONG Index;PKSPIN_LOCK_QUEUE LockQueue;PKTIMER_TABLE_ENTRY TimerListHead;PLIST_ENTRY TimerList;PKTIMER Timer;PKDPC TimerDpc;/*Lock the dispatcher database and loop through the timer list...We will cancel all timers that have a non-canonical DeferredContext.*/OldIrql = KiAcquireDispatcherLockRaiseToSynch();for(Index = 0; Index < TIMER_TABLE_SIZE; Index++){LockQueue = KeTimerIndexToLockQueue((UCHAR)(Index & 0xFF));KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);// now we can work with the timer list...TimerListHead = &KiTimerTableListHead[Index];TimerList = TimerListHead->Entry.Flink;while(TimerList != (PLIST_ENTRY)TimerListHead){// is DPC patched?Timer = CONTAINING_RECORD(TimerList, KTIMER, TimerListEntry);TimerList = TimerList->Flink;TimerDpc = PgDeobfuscateTimerDpc(Timer);if(TimerDpc == NULL)continue;if(PgIsPatchGuardContext(TimerDpc->DeferredContext) && KeContainsSymbol(TimerDpc->DeferredRoutine)){// this will cancel the timer...Timer->Header.Inserted = FALSE;if(RemoveEntryList(&Timer->TimerListEntry))TimerListHead->Time.HighPart = 0xFFFFFFFF;}}KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);}KiReleaseDispatcherLockFromSynchLevel();KiExitDispatcher(OldIrql);return TRUE;
}
PG2 BYPASS源码阅读 学习x64解密定时器、特征码定位相关推荐
- Java源码阅读学习后的浅析和感悟(JDK篇)(持续更新)
目录 Java源码阅读学习后的浅析和感悟(JKD篇) - 为什么阅读源码 集合框架类 - 为什么会要引入集合 - 集合结构图(部分) ArrayList集合源码分析 - 扩容机制 - 关键方法解释(D ...
- Vue 源码阅读学习(三)
第三节:函数柯里化与渲染模型 嘿,朋友们,本节是 Vue 源码阅读的第三讲.Vue 源码阅读系列得到了赞赏,我很高兴,同时希望大家可以给予反馈!我虚心接纳您的意见! 如果没有看之前的第一讲和第二讲的内 ...
- openfire服务器源码阅读学习之启动流程(一)
openfire启动流程(ServerStarter类.XMPPServer类) 首先从org.jivesoftware.openfire.starter包下的ServerStarter.java文件 ...
- rust墙壁升级点什么_分享:如何在阅读Rust项目源码中学习
今天做了一个Substrate相关的小分享,公开出来. 因为我平时也比较忙,昨天才选定了本次分享的主题,准备比较仓促,细节可能不是很充足,但分享的目的也是给大家提供一个学习的思路,更多的细节大家可以在 ...
- java经典源码 阅读_公开!阿里甩出“源码阅读指南”,原来源码才是最经典的学习范例...
我们为啥要阅读源码? 为什么面试要问源码?为什么我们Java程序员要去看源码?相信大多数程序员看到源码第一感觉都是:枯燥无味,费力不讨好!要不是为了"涨薪"我才不去看这个鬼东西!但 ...
- 阅读 redis 源码,学习缓存淘汰算法 W-TinyLFU
所有 IT 从业者都接触过缓存,一定了解基本工作原理,业界流行一句话: 缓存就是万金油,哪里有问题哪里抹一下 .那他的本质是什么呢? 上图代表从 cpu 到底层硬盘不同层次,不同模块的运行速度,上层多 ...
- MAE学习 论文阅读与学习 源码阅读
这里回顾了BERT的重要自监督任务:masked input:randomly mask some tokes and predict them 作者提到了3点看法(以后随着技术发展,背景 ...
- 【vn.py学习笔记(八)】vn.py utility、BarGenerator、ArrayManager源码阅读
[vn.py学习笔记(八)]vn.py utility.BarGenerator.ArrayManager源码阅读 写在前面 1 工具函数 2 BarGenerator 2.1 update_tick ...
- 【vn.py学习笔记(五)】vn.py Base、Log、Oms、Email Engine源码阅读
[vn.py学习笔记(五)]vn.py Base.Log.Oms.Email Engine源码阅读 写在前面 1 BaseEngine 2 LogEngine 3 OmsEngine 3.1 构造函数 ...
最新文章
- varnish---反向代理web加速缓存服务器和CDN的推送
- c语言结构体输入身高体重,c++:输入n名学生的身高体重,按身高排序输出并计算平均体重和身高...
- 进程线程002 等待链表 调度链表
- android模拟器启动没有拨号功能
- 法流程图_【对反应过程的笔记整理方法——时间轴法】
- request中getParameter和getAttribute的区别
- 算法第四版_第二章_练习题_2.1.1~2.1.12
- linux基于i2c-tools快速搭建设备读写环境
- C# 调用mschart控件
- Android和iPhone浏览器大战,第1部分,WebKit抢救
- 计算机硬盘能改成移动硬盘,旧硬盘怎么改装成移动硬盘
- SD卡启动第二篇 (手动导入系统到SD卡分区)
- neon浮点运算_ARM 浮点计算测试与分析
- Android距离传感器unregisterListener无用解决
- bmp格式如何转换成png格式
- ES6 新特性之 let, const : JavaScript在变量方面的改进。
- 海天蚝油《挑战不可能》清华博士远程驾驶无人车迎战高难度车道
- 360 || 2021校园招聘的一道笔试题思路分享
- 电路课组(一)电路原理 Part 0 电路仿真(1)Multisim基本功能
- Magix 促销:让你的音视频制作更加专业