能力值:
( LV2,RANK:10 )
|
-
-
2 楼
ntoskrnl.exe
|
能力值:
( LV2,RANK:10 )
|
-
-
3 楼
【转】关于PsSetCreateProcessNotifyRoutine函数的分析和简单利用
这是从别人那转来的,下面所看见的汇编代码跟我不同。
我的XP SP3,获取m_address_3的偏移是0x8A,而这里是0x8B。
分析PsSetCreateProcessNotifyRoutine函数:
nt!PsSetCreateProcessNotifyRoutine:
805c56d2 8bff mov edi,edi
805c56d4 55 push ebp
805c56d5 8bec mov ebp,esp
805c56d7 53 push ebx
805c56d8 33db xor ebx,ebx
805c56da 385d0c cmp byte ptr [ebp+0Ch],bl
805c56dd 56 push esi
805c56de 57 push edi
805c56df 7465 je nt!PsSetCreateProcessNotifyRoutine+0x74 (805c5746)
805c56e1 bfe0a35580 mov edi,offset nt!PspCreateProcessNotifyRoutine (8055a3e0)
//这儿的PspCreateProcessNotifyRoutine就是用来记录所有的监控函数的数组!
//这儿可以得到PspCreateProcessNotifyRoutine的地址-----Address_1
805c56e6 57 push edi
805c56e7 e848d50300 call nt!ExReferenceCallBackBlock (80602c34)
// ExReferenceCallBackBlock对PspCreateProcessNotifyRoutine进行处理,所以,我们还要定位到函数
// ExReferenceCallBackBlock
805c56ec 8bf0 mov esi,eax
805c56ee 85f6 test esi,esi
805c56f0 741f je nt!PsSetCreateProcessNotifyRoutine+0x3f (805c5711)
805c56f2 56 push esi
805c56f3 e82af9fcff call nt!IopGetRelationsTaggedCount (80595022)
//这儿是通过调用IopGetRelationsTaggedCount函数处理ExReferenceCallBackBlock(& PspCreateProcessNotifyRoutine[i])的返回值!
…….
805c572f 8d049de0a35580 lea eax,nt!PspCreateProcessNotifyRoutine (8055a3e0)[ebx*4]
//这儿可以得到PspCreateProcessNotifyRoutine的地址-----Address_2
………
805c575c bfe0a35580 mov edi,offset nt!PspCreateProcessNotifyRoutine (8055a3e0)
//这儿可以得到PspCreateProcessNotifyRoutine的地址-----Address_3
……
当然,仅通过一个就可以得到PspCreateProcessNotifyRoutine的地址,同时得到3个,比较是否相同,提高准确率!呵呵!看看代码是如何得到的:
如何得到PspCreateProcessNotifyRoutine数组的地址?
ULONG GetPspCreateProcessNotifyRoutineAddress()
{
ULONG m_PspCreateProcessNotifyRoutine=0;//记录PspCreateProcessNotifyRoutine地址
ULONG m_address_1=(ULONG)((ULONG)PsSetCreateProcessNotifyRoutine+0x10);
ULONG m_address_2=(LONG)((ULONG)PsSetCreateProcessNotifyRoutine+0x60);
ULONG m_address_3=(ULONG)((ULONG)PsSetCreateProcessNotifyRoutine+0x8B);
//这儿明显的看出程序的不兼容性
ULONG m_address=(ULONG)PsSetCreateProcessNotifyRoutine;
__asm
{
push eax;
mov eax,m_address_1;
mov eax,[eax];
mov m_address_1,eax;
mov eax,m_address_2;
mov eax,[eax];
mov m_address_2,eax;
mov eax,m_address_3;
mov eax,[eax];
mov m_address_3,eax;
pop eax;
}//将得到的地址转换为对应的值
DbgPrint("地址为:x%x\n",m_address);
DbgPrint("地址为:x%x\n",m_address_1);
DbgPrint("地址为:x%x\n",m_address_2);
DbgPrint("地址为:x%x\n",m_address_3);
if((m_address_1==m_address_2)&&(m_address_1==m_address_3))
{
DbgPrint("地址找到了!\n");
m_PspCreateProcessNotifyRoutine=m_address_1;
}
return m_PspCreateProcessNotifyRoutine;
}
如何定位到函数:ExReferenceCallBackBlock?
805c56e7 e848d50300 call nt!ExReferenceCallBackBlock (80602c34)
利用特征码得到ExReferenceCallBackBlock函数的地址!Call的偏移!
//偏移:(805c56e7-805c56d2 )=0x15!-----函数地址:A=PsSetCreateProcessNotifyRoutine+0x15!
B=[A+1];A=A+B+5;---------------A就是ExReferenceCallBackBlock 的地址!
看看具体实现的代码:
//声明ExReferenceCallBackBlock 函数原型:
typedef PVOID (*EXREFERENCECALLBACKBLOCK)(PULONG m_fun_address);
EXREFERENCECALLBACKBLOCK m_ExReferenceCallBackBlock;//声明ExReferenceCallBackBlock函数!
m_ExReference=(ULONG)PsSetCreateProcessNotifyRoutine+0x15;
__asm
{
push eax;
mov eax,m_ExReference;
inc eax;
mov eax,[eax];
add eax,5;
add eax,m_ExReference;
mov m_ExReference,eax;
pop eax;
}
//m_ExReference的值为ExReferenceCallBackBlock的地址!
m_ExReferenceCallBackBlock=(EXREFERENCECALLBACKBLOCK)m_ExReference;
在Windbg中看看IopGetRelationsTaggedCount是如何实现的:
nt!IopGetRelationsTaggedCount:
80595022 8bff mov edi,edi
80595024 55 push ebp
80595025 8bec mov ebp,esp
80595027 8b4508 mov eax,dword ptr [ebp+8]
8059502a 8b4004 mov eax,dword ptr [eax+4]
8059502d 5d pop ebp
8059502e c20400 ret 4
80595031 cc int 3
很简单,还是在程序中直接用吧,不用定位了!
如何定位回调函数所在的驱动?
1.ZwQuerySystemInformation调用11号功能,查询到所有的内核模块信息!
2.判断定位到的函数在哪个内核模块内!
3.输出定位到的模块信息!
这儿的前提是ZwQuerySystemInformation没有被Hook 下的情况!否则,就定位不到了啊!
看看代码:
PVOID m_start=NULL;
int m_length=1024;
ULONG m_real_size=0;
NTSTATUS m_status=STATUS_SUCCESS;
ULONG m_count=0;
m_start=ExAllocatePool (NonPagedPool,m_length);
//将得到的实际大小保存在m_real_size中!
m_status=ZwQuerySystemInformation (11,m_start,m_length,&m_real_size);
ExFreePool(m_start);
m_start=ExAllocatePool (NonPagedPool,m_real_size);
m_status=ZwQuerySystemInformation (11,m_start,m_real_size,NULL);
m_system_moudle_infomation=(PSYSTEM_MODULE_INFORMATION)((PULONG)m_start+1);
.....
定位到m_real_fun_address
.....
for(m_count=0;m_count<*(PULONG)m_start;m_count++)
{ if(((ULONG)m_real_fun_address>=(ULONG)m_system_moudle_infomation[m_count].Base)&&((ULONG)m_real_fun_address<=((ULONG)m_system_moudle_infomation[m_count].Base+m_system_moudle_infomation[m_count].Size)))
{
DbgPrint("函数的地址:0x%x在模块:%s中\n",m_real_fun_address,m_system_moudle_infomation[m_count].ImageName);
break;
}
}
这儿就查询到了回调函数的地址所在模块,根据列出的模块信息,就能知道到底是什么程序进行的监控!
如何清除对进程创建(卸载)的监控?
将PspCreateProcessNotifyRoutine[i]的值改为为0!
//清除所有数据的监控
VOID TryClearRoutineAddress(PULONG m_fun_address)
//m_fun_address就是得到的PspCreateProcessNotifyRoutine
{
int i=0;
__asm
{ //关闭保护
push eax;
mov eax,CR0;
and eax,0FFFEFFFFh;
mov CR0,eax;
pop eax;
}
for(i=0;i<8;i++)
{
m_fun_address[i]=0;//将所有的数据清为0;
}
__asm
{ //开启保护
push eax;
mov eax,CR0;
or eax, 0F0000h;
mov CR0,eax;
pop eax;
}
}
到这儿,就得到解决了查询进程监控模块,清除进程监控!对于线程,DLL的监控,只要采用同样的方法就能得到!
|