看流星社区

 找回密码
 注册账号
查看: 2212|回复: 0

对抗debugport清零的另一种方法

[复制链接]

该用户从未签到

发表于 2017-6-1 17:20:53 | 显示全部楼层 |阅读模式
这篇文章大家还是别看了,有几处代码错误,因为是用notepad++写的,而且没有造成显式的错误,所以我起先也没发现,后来在看雪上贴了段时间,我又把代码几处错误改了,然后再次调试,到前几天为止,基本确认思路存在问题了……至于为什么,讲起来很麻烦的说

不过貌似因为这篇帖子,看雪给了我枚邀请码,很开心哈……因为这是我在看雪发的第一篇帖子嘛,而且,还是个半成品


前几天晚上看intel手册突然想到了一种另类的对抗debug port的方法,理论上蛮通用的,于是写了几百行代码实验了下
但是结果很悲催,IDT HOOK死活蓝屏,群里几个人帮我查那段代码错误,结果一致认为代码没错,说我RP不行
哎……好吧,我认了,我很久没扶老奶奶过马路了


我简单说下思路,如果你能搞定,请联系我,让我把这些代码close,谢了
前提:你必须知道目标驱动保护(简称213.sys)的哪个进程(简称213.exe),从而得到此进程的debugport地址
  你必须确认213.sys是否创建了一个线程来不断清零这个debugport


好了,不卖关子了,嘿嘿,进入正题
1:先hook 掉NtGetContextThread,NtSetContextThread,如果目标驱动没对这两个函数做手脚,此步略过
2:IDT HOOK 一号向量
3:枚举系统线程,对每个线程下硬件写入断点,地址就是213.sys要保护的进程的debugport
理论流程是这样的,保护线程对debugport进程,触发断点->1号向量接管->进入我们的函数->简单的处理是把debugport改回来,复杂的处理是自动寻找213.sys清零213.exe的debugport的函数体内可以modify的位置,改掉它,使清零操作无效,我用XDE(一个反汇编引擎)试过,后来把这块代码去了,太浪费生命了


现在思路有了,写代码就简单了。但是我很悲催的没有完成……主啊,饶恕我吧,我以后一定好好做人……


贴代码会不会太多了……而且我写代码不习惯写很多注释。呃……将就着看吧





#include <Ntddk.h>
#include <winDef.h>
#include <strsafe.h>




#define MAKELONG(a,b) ((ULONG)(((USHORT)(a))|((ULONG)((USHORT)(b))) << 16))


void Recover_NtGetContextThread();
void IDT_HOOK();
void Modify_Code();




ULONG NtGetContextThread_Addr;
ULONG NtSetContextThread_Addr;
ULONG Old_Addr;
ULONG DebugPort_Addr;


typedef struct _ServiceDescriptorTable
{
PVOID  ServiceTable; // array of entry points
PULONG   CounterTable; // array of usage counters
DWORD   ServiceLimit;  // number of table entries
PBYTE   ArgumentTable;  // array of byte counts
}
ServiceDescriptorTable,
*PServiceDescriptorTable,
**PPServiceDescriptorTable;

extern PServiceDescriptorTable KeServiceDescriptorTable;


#pragma pack(1)
typedef struct _IDTENTRY{
USHORT offsetLow;
USHORT selector;
UCHAR NoUseful;
UCHAR segType:4;
UCHAR segFlag:1;
UCHAR DPL:2;
UCHAR present:1;
USHORT offsetHigh;
}IDTENTRY,*PIDTENTRY;


typedef struct _IDT{
USHORT limit;
USHORT baseLow;
USHORT baseHigh;
}IDT,*PIDT;
#pragma pack()




void PPON(){
_asm{
cli
mov eax,cr0
or eax,10000h
mov cr0,eax
sti
}
}


void PPOFF(){
_asm{
cli
mov eax,cr0
and eax,not 10000h
mov cr0,eax
sti
}
}


ULONG GetFuncAddrFromSDT(ULONG index){
ULONG Addr;
_asm{
push eax
mov eax,KeServiceDescriptorTable
mov eax,[eax]
shr eax,2
add eax,index
shl eax,2
mov eax,[eax]
mov Addr,eax
pop eax
}
return Addr;
}


ULONG GetAddr(){  //Get the list link start address
#define DEBUG_PORT 0xBC
#define IMAGE_NAME 0x174
#define LIST_ADDR 0x88
ULONG cur=(ULONG)PsGetCurrentProcess(); //Current process must be SYSTEM
ULONG curAddr,startAddr;
curAddr=startAddr=(ULONG)(cur+LIST_ADDR); //save the start address
do{
if(strcmp((char*)(curAddr-LIST_ADDR+IMAGE_NAME),"DNF.EXE")) curAddr=*(ULONG*)curAddr;
else{
DebugPort_Addr=(ULONG)(curAddr-LIST_ADDR+DEBUG_PORT);
break;
}
}while(curAddr!=startAddr);
return *(ULONG*)(cur+0x114)+0x22C; //return the thread list head
}


ULONG SetAllSystemThreads(ULONG ListAddr){
#define THREADLIST_ADDR 0x22C
#define CID_OFFSET 0x1EC
ULONG curAddr,startAddr;
OBJECT_ATTRIBUTES ObjAttr;
PCLIENT_ID cid;
HANDLE h;
CONTEXT con;
NTSTATUS status;
InitializeObjectAttributes(&amp;ObjAttr,0,OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,0,0);
curAddr=startAddr=ListAddr;
do{
cid=(PCLIENT_ID)(ULONG)(curAddr-THREADLIST_ADDR+CID_OFFSET);
//h=NtOpenThread(h,THREAD_ADLL_ACCESS,&amp;ObjAttr,cid);
_asm{
push eax
push edx
push 80h
call GetFuncAddrFromSDT
mov edx,eax
push cid
lea eax,ObjAttr
push eax
push THREAD_ALL_ACCESS
push h
call edx
pop edx
pop eax
}
if(h){
_asm{
push eax
lea eax,con
push eax
push h
call NtGetContextThread_Addr
mov status,eax
pop eax
}
if(NT_SUCCESS(status)){
con.Dr3=DebugPort_Addr;
con.Dr7=0xD0002080;
//NtSetContextThread(h,&amp;con);
_asm{
push eax
lea eax,con
push eax
push h
call NtGetContextThread_Addr
pop eax
}
}
ZwClose(h);
}
}while(curAddr!=startAddr);
}


NTSTATUS Jmp_NtGetContextThread(
IN HANDLE ThreadHandle,
OUT PCONTEXT Context
){
if(strcmp((char*)((ULONG)PsGetCurrentProcess()+0x174),"DNF.EXE")){
_asm jmp Jmp_NtGetContextThread
}
else return STATUS_UNSUCCESSFUL;
}


NTSTATUS Jmp_NtSetContextThread(
IN HANDLE ThreadHandle,
IN PCONTEXT Context
){
if(strcmp((char*)((ULONG)PsGetCurrentProcess()+0x174),"DNF.EXE")){
_asm jmp Jmp_NtSetContextThread
}
else return STATUS_UNSUCCESSFUL;
}

void Rcover_NtGetAndSetContextThread(){
//SSDT HOOK
KIRQL irq;
irq=KeRaiseIrqlToDpcLevel();
PPOFF();
_asm{
sti
push eax
push ebx
mov eax,KeServiceDescriptorTable
mov eax,[eax]
shr eax,2
add eax,0x55
shl eax,2
mov ebx,[eax]
mov NtGetContextThread_Addr,ebx
mov ebx,Jmp_NtGetContextThread
mov [eax],ebx
shr eax,2
add eax,0x90
shl eax,2
mov ebx,[eax]
mov NtSetContextThread_Addr,ebx
mov ebx,Jmp_NtSetContextThread
mov [eax],ebx
pop ebx
pop eax
sti
}
PPON();
KeLowerIrql(irq);
}


void Unhook_NtGetAndSetContextThread(){
KIRQL irq=KeRaiseIrqlToDpcLevel();
PPOFF();
_asm{
push eax
push ebx
mov eax,KeServiceDescriptorTable
mov eax,[eax]
shr eax,2
add eax,55h
shl eax,2
mov ebx,NtGetContextThread_Addr
mov [eax],ebx
shr eax,2
add eax,90h
shl eax,2
mov ebx,NtSetContextThread_Addr
mov [eax],ebx
pop ebx
pop eax
}
PPON();
KeLowerIrql(irq);
}


void _stdcall Modify_Code(){
_asm mov dword ptr[DebugPort_Addr],0x44 //set the value of debugport to nozero
}


_declspec(naked) IDT_ProxyFunc(){
_asm{
pushad
pushfd
call Modify_Code
popfd
popad
jmp Old_Addr
}
}


void IDT_HOOK(){
IDT idt;
PIDTENTRY entry;
_asm sidt idt
entry=(PIDTENTRY)MAKELONG(idt.baseLow,idt.baseHigh);
KdPrint(("the base address of IDT is %X",(ULONG)entry));
Old_Addr=(ULONG)MAKELONG(entry[1].offsetLow,entry[1].offsetHigh);
KdPrint(("the NO.1 ISR address is %X",Old_Addr));
PPOFF();
_asm{
//entry[1].offsetLow=(USHORT)(ULONG)&amp;IDT_ProxyFunc;
//entry[1].offsetHigh=(USHORT)((ULONG)&amp;IDT_ProxyFunc>>16);
cli
push eax
push edx
mov eax,entry
add eax,8 //move to next ISR
mov edx,IDT_ProxyFunc
mov word ptr[eax],dx
add eax,6 //move to offsetHigh
shr edx,16
mov word ptr[eax],dx
pop edx
pop eax
sti
}
PPON(); //上面的就是导致蓝屏的代码,我实在郁闷~咋就蓝了呢,我用汇编改写了上面注释的两句C代码,虽然ASM写的很累赘,但是我只是为了找出哪里导致了蓝屏,大家不要鄙视,我用notepad++写了几小时代码通宵也不容易诶,一个字一个字母敲,呜呜
}


void IDT_UNHOOK(){
IDT idt;
PIDTENTRY entry;
_asm sidt idt
entry=(PIDTENTRY)(ULONG)MAKELONG(idt.baseLow,idt.baseHigh);
_asm cli
entry[1].offsetLow=(USHORT)Old_Addr;
entry[1].offsetHigh=(USHORT)((ULONG)Old_Addr>>16);
_asm sti
}


NTSTATUS DriverUnload(PDRIVER_OBJECT driver){
Unhook_NtGetAndSetContextThread();
IDT_UNHOOK();
}


NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING reg){
ULONG ListAddr;
#if DBG
_asm int 3
#endif
driver->DriverUnload=DriverUnload;
Rcover_NtGetAndSetContextThread();
IDT_HOOK();
ListAddr=GetAddr();
if(DebugPort_Addr) SetAllSystemThreads(ListAddr);
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-4-23 20:00

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表