A、定位特征码函数FindCode_Address构建
B、定位NtOpenThread
C、定位NtOpenProcess
D、定位NtReadVirtualMemory
E、定位NtWriteVirtualMemory
F、CALL与JMP指令的区别
G、构建相应的替换函数
课时:39分
OpenProcess //NtOpenProcess+0x21E //SSDT 122
OpenThread //NtOpenThread+0x214 //SSDT 128
ReadProcessMemory //NtReadVirtualMemory+0 //SSDT 186
WriteProcessMemory //NtWriteVirtualMemory+0 //SSDT 277
ReadProcessMemory
mov eax,Proc
jmp eax
WriteProcessMemory
mov eax,Proc2
jmp eax
WriteProcessMemory +7
#pragma PAGECODE
__declspec(naked)VOID My_ReadProcessMemory()
{
//恢复前2条指令
__asm
{
push 1Ch
}
}
#pragma PAGECODE
__declspec(naked)VOID yjxsoft_com_OpenProcess()
{
__asm
{
push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
mov eax,ntopenprcaddr
add eax,0bh
push eax //CALL后返回的地址 非压栈参数
//
jmp ObOpenObjectByPointeraddr
}
}
========================================================
笔记:
上节课有个函数写错了,应该是NtDebugActiveProcess.将46课的源代码复制过来,新建一个49.H头文件.首先通过NtReadVirtualMemory函数,建立函数先恢复前面几个字节,然后再跳回到原函数.同理WriteProcessMemory 也写上恢复代码.再写nt!NtOpenProcess函数的恢复,但是这个不能在头部直接恢复,是要在后面偏移0X21E处修改. nt!NtOpenThread的方法也类似.怕有人不明白汇编又讲解call = push + jmp 的原理.
最终代码如下:
//nt!NtReadVirtualMemory:
//805b528a 6a1c push 1Ch
//805b528c 68e8ae4d80 push offset nt!MmClaimParameterAdjustDownTime+0x90 (804daee8)
DWORD Real_NtReadVirtualMemory_7 =0x805b5291;
DWORD Real_NtWriteVirtualMemory_7=0x805b5394;
DWORD NtOpenProcess_21E=0x805cc61a; //myNtOpenProcess
DWORD NtOpenThread_214=805cc89ch; //myNtOpenThread
DWORD NtOpenThread_214_B=805cc8a7h;
DWORD NtOpenProcess_21E_B=805cc625h;
#pragma PAGECODE
__declspec(naked)VOID My_NtReadVirtualMemory()
{
//恢复前2条指令
__asm
{
push 1Ch
puhs 804daee8h
jmp Real_NtReadVirtualMemory_7
}
}
#pragma PAGECODE
__declspec(naked)VOID My_NtWriteVirtualMemory()
{
//恢复前2条指令
// nt!NtWriteVirtualMemory:
// 805b5394 6a1c push 1Ch
// 805b5396 6800af4d80 push offset nt!MmClaimParameterAdjustDownTime+0xa8 (804daf00)
__asm
{
push 1Ch
puhs 804daf00h
jmp Real_NtWriteVirtualMemory_7
}
}
// OpenProcess //NtOpenProcess+0x21E //SSDT 122
// nt!NtOpenProcess+0x21e:
// 805cc61a ff75c8 push dword ptr [ebp-38h] //jmp My_NtOpenPrcoess
// 805cc61d ff75dc push dword ptr [ebp-24h]
// 805cc620 e84706ffff call nt!ObOpenObjectByPointer (805bcc6c)
// 805cc625 8bf8 mov edi,eax
#pragma PAGECODE
__declspec(naked)VOID My_NtOpenPrcoess()
{
//恢复前2条指令
// nt!NtWriteVirtualMemory:
// 805b5394 6a1c push 1Ch
// 805b5396 6800af4d80 push offset nt!MmClaimParameterAdjustDownTime+0xa8 (804daf00)
__asm
{
push dword ptr [ebp-38h]
push dword ptr [ebp-24h]
push NtOpenProcess_21E_B //DWORD NtOpenProcess_21E_B=805cc625h
jmp ObOpenObjectByPointer /*(805bcc6c)*/ ret c3 eip
//jmp NtOpenProcess_21E_B
}
}
// OpenThread //NtOpenThread+0x214 //SSDT 128
// 805cc89c ff75cc push dword ptr [ebp-34h] //jmp DWORD NtOpenThread_214=805cc89ch;
// 805cc89f ff75e0 push dword ptr [ebp-20h]
// 805cc8a2 e8c503ffff call nt!ObOpenObjectByPointer (805bcc6c)
// 805cc8a7 8bf8 mov edi,eax
#pragma PAGECODE
__declspec(naked)VOID My_NtOpenThread()
{
//恢复前2条指令
// nt!NtWriteVirtualMemory:
// 805b5394 6a1c push 1Ch
// 805b5396 6800af4d80 push offset nt!MmClaimParameterAdjustDownTime+0xa8 (804daf00)
__asm
{
push dword ptr [ebp-34h]
push dword ptr [ebp-20h]
push NtOpenProcess_214_B // DWORD NtOpenProcess_214_B=805cc8a7h
jmp ObOpenObjectByPointer /*(805bcc6c)*/
//jmp NtOpenProcess_214_B
}
}
#pragma PAGECODE
VOID HOOK()
{
// SSDT 186 =My_NtReadVirtualMemory
// SSDT 277 =My_NtWriteVirtualMemory
//DWORD NtOpenProcess_21E=0x805cc61a; //myNtOpenProcess
//DWORD NtOpenThread_214=805cc89ch; //myNtOpenThread
__asm
{ // NtOpenProcess 还原
lea ebx,NtOpenProcess_21E
mov [ebx+0],E9h
lea eax,myNtOpenProcess
mov [ebx+1],eax
// NtOpenThread 还原
lea ebx,NtOpenThread_214
mov [ebx+0],E9h
lea eax,myNtOpenThread //通过公式计算
mov [ebx+1],eax
}
}
另外老师给出了另一个passtp.h源代码里面有更详细的过保护.- DWORD ssdtaddr,
- oldreadaddr,readpush ,readjmpaddr,
- oldwriteaddr,writepush ,writejmpaddr ,
- ntopenprcaddr ,
- ntopentrdaddr ,
- KiAttachProcessaddr,KeStackAttachProcess_jmpaddr,
- ObOpenObjectByPointeraddr/*,
- h1,h2,hr,hw*/;
- #pragma PAGECODE
- __declspec(naked) VOID yjxsoft_com_KeStackAttachProcess()
- {
- KdPrint(("yjxsoft_com_KeStackAttachProcess\n"));
- //KeStackAttachProcess_jmpaddr+0xD
- __asm
- {
-
- //还原jmp占用处指令字节指令
- push dword ptr [ebp+0ch]
- push dword ptr [ebp+8]
- push edi
- push esi
- //压入返回地址
- mov eax,KeStackAttachProcess_jmpaddr
- add eax,0xd //push dword ptr [ebp+8] 至CALL KiAttachProcess后的距离
- push eax //返回地址
- //KiAttachProcess 前7字节
- mov edi,edi
- push ebp
- mov ebp,esp
- push ebx
- push esi
- //jmp 至KiAttachProcess+7位置执行,执行完返回至 KeStackAttachProcess_jmpaddr+D处继续执行
- mov eax, KiAttachProcessaddr
- add eax,7
- jmp eax
- }
- }
- #pragma PAGECODE
- __declspec(naked) VOID yjxsoft_com_KiAttachProcess()
- {
- //KdPrint(("yjxsoft_com_KiAttachProcess\n"));
- __asm
- {
- /* 804f9b5e ff7508 push dword ptr [ebp+8]
- 804f9b61 57 push edi
- 804f9b62 56 push esi
- 804f9b63 e890feffff call nt!KiAttachProcess (804f99f8)
- 804f9b68 5f pop edi
- 804f9b69 5e pop esi
- 804f9b6a 5d pop ebp
- 804f9b6b c20400 ret 4
- */
- push dword ptr [ebp+8]
- push edi
- push esi
- //恢复 前7字节指令
- /* nt!KiAttachProcess:
- 804f99f8 8bff mov edi,edi
- 804f99fa 55 push ebp
- 804f99fb 8bec mov ebp,esp
- 804f99fd 53 push ebx
- 804f99fe 56 push esi
- */
- push endCall //压栈返回地址
- mov edi,edi
- push ebp
- mov ebp,esp
- push ebx
- push esi
- //
- mov eax, KiAttachProcessaddr
- add eax,7
- jmp eax
- endCall:
- pop edi
- pop esi
- pop ebp
- ret 4
- }
- }
- #pragma PAGECODE
- __declspec(naked) VOID yjxsoft_com_NtReadVirtualMemory()
- {
- //KdPrint(("yjxsoft_com_NtReadVirtualMemory\n"));
-
- __asm
- {
- //
- push 0x1c
- push readpush ////压栈参数
- //
- jmp readjmpaddr
- }
- }
- //
- //;///////////////////////////////////////////////////////////////////
- //
- #pragma PAGECODE
- __declspec(naked)VOID yjxsoft_com_NtWriteVirtualMemory()
- {
- // KdPrint(("yjxsoft_com_NtWriteVirtualMemory\n"));
- __asm
- {
- push 0x1c
- push writepush //压栈参数
- //
- jmp writejmpaddr
- }
- }
- //
- //;/////////////////////////////////////////////////////////////////
- //805cc613 8d8548ffffff lea eax,[ebp-0B8h]
- //805cc619 50 push eax
- //805cc61a ff75c8 push dword ptr [ebp-38h]
- //805cc61d ff75dc push dword ptr [ebp-24h]
- //805cc620 e84706ffff call nt!ObOpenObjectByPointer (805bcc6c)
- //805cc625 8bf8 mov edi,eax
- //805cc625-805cc61a= 0bh
- #pragma PAGECODE
- __declspec(naked)VOID yjxsoft_com_OpenProcess()
- {
-
- __asm
- {
-
- push dword ptr [ebp-38h]
- push dword ptr [ebp-24h]
- mov eax,ntopenprcaddr
- add eax,0bh
- push eax //CALL后返回的地址 非压栈参数
- //
- jmp ObOpenObjectByPointeraddr
- }
- }
- //
- //;//////////////////////////////////////////////////////////////////
- //
- #pragma PAGECODE
- __declspec(naked)VOID yjxsoft_com_OpenTread()
- {
- //KdPrint(("yjxsoft_com_OpenTread \n"));
- __asm
- {
- push dword ptr [ebp-34h]
- push dword ptr [ebp-20h]
- mov eax,ntopentrdaddr
- add eax,0bh
- push eax
- //
- jmp ObOpenObjectByPointeraddr
- }
- }
-
- //
- //;//////////////////////////////////////////////////////////////////
- //
- #pragma PAGECODE
- __declspec(naked) DWORD __stdcall Findcodeaddr(DWORD code1,WORD code2,DWORD prcaddr)
- {
-
- __asm
- {
- mov edx,[esp+0x0c] //prcaddr
- mov ecx,1000h
- //while( ecx>0)
- ////
- start:
- sub ecx,1h
- add edx,1h
- mov ebx,dword ptr [edx]
- xor eax,eax
- mov ax,word ptr [edx+4h]
- test ecx,ecx
- jz end
- cmp ebx,[esp+4] //code1
- jnz start
- cmp ax,[esp+8] //code2
- jnz start
- /*if (ebx==code1 && ax==code2) break */
- end:
- mov eax,edx
- ret 0x0c
- }
- }
- //;////////////////////////////////////////////////////////////////
- //
- #pragma PAGECODE
- VOID PassTPhook ()
- {
- UNICODE_STRING g_ProcessAddr,g_ThreadAddr,g_KeAttachAddr,g_PointerAddr,g_KeStackAttachProcess;
- RtlInitUnicodeString(&g_ProcessAddr,L"NtOpenProcess");
- RtlInitUnicodeString(&g_ThreadAddr,L"NtOpenThread");
- RtlInitUnicodeString(&g_KeAttachAddr,L"KeAttachProcess");
- RtlInitUnicodeString(&g_PointerAddr,L"ObOpenObjectByPointer");
- RtlInitUnicodeString(&g_KeStackAttachProcess,L"KeStackAttachProcess");
- // __asm //
- // __asm mov eax,eax
- // ntopenprcaddr=(DWORD)MmGetSystemRoutineAddress(&g_ProcessAddr);
- //
- // Findcodeaddr(0xffc875ff,0xdc75,ntopenprcaddr);
- __asm
- {
-
- // pushad
- lea eax,g_KeStackAttachProcess
- push eax
- call DWORD ptr DS:[ MmGetSystemRoutineAddress]
- push eax //传入 KeStackAttachProcess地址
- //push 0E856h
- //push 570875FFh
- push 0875h
- push 0FF0C75FFh
- call Findcodeaddr
- mov KeStackAttachProcess_jmpaddr,eax //// KeStackAttachProcess里 CALL KiAttachProcess的地址 定位push dword ptr[ebp+8]
- // hook KeStackAttachProcess+7d
- lea ebx,yjxsoft_com_KeStackAttachProcess
- sub ebx,eax
- sub ebx,5
- mov BYTE ptr [eax],0E9h
- mov dword ptr [eax+1],ebx
- //hook end
- /////////////
- lea eax,g_ProcessAddr
- push eax
- call DWORD ptr DS:[ MmGetSystemRoutineAddress]
- push eax //传入 NtOpenProcess地址
- push 0dc75h
- push 0ffc875ffh
- call Findcodeaddr
- mov ntopenprcaddr,eax ///NtOpenProcess里 CALL ObOpenObjectByPointer的地址
- lea eax, g_ThreadAddr
- push eax
- call DWORD ptr DS:[ MmGetSystemRoutineAddress]
- push eax ////传入 NtOpenThread地址
- push 0e075h
- push 0ffcc75ffh
- call Findcodeaddr
- mov ntopentrdaddr,eax //////存放 NtOpenThread 里 CALL ObOpenObjectByPointer的地址
- lea eax,g_PointerAddr
- push eax
- call DWORD ptr DS:[ MmGetSystemRoutineAddress]
- mov ObOpenObjectByPointeraddr,eax //存放 ObOpenObjectByPointer地址
- //hook KiAttachProcess begin
- lea eax,g_KeAttachAddr
- push eax
- call DWORD ptr DS:[ MmGetSystemRoutineAddress]
- push eax // 传入KeAttachProcess
- push 0e856h
- push 570875ffh
- call Findcodeaddr //查找KiAttachProcess地址
- add eax,6h //指向 804f9b64// 804f9b63 e890feffff call nt!KiAttachProcess (804f99f8)
- mov ebx,dword ptr [eax] //取CALL 地址
- add ebx,eax //当前地址+取出地址+4
- add ebx,4h
- mov KiAttachProcessaddr,ebx //计算出 KiAttachProcess 这个未导出函数地址
-
- sub eax,6h //mov KiAttachProcess -6
-
- // HOOK KeAttachProcessPush->KiAttachProcessPush-5
- mov dword ptr[eax],0xE9 //jmp
- lea ebx,yjxsoft_com_KiAttachProcess
- sub ebx,eax
- sub ebx,5
- mov dword ptr[eax+1],ebx
- //hook KiAttachProcess end
- mov eax, KeServiceDescriptorTable
- mov eax,[eax] //address of KeServiceDescriptorTable
- mov ssdtaddr,eax
- mov eax,ssdtaddr
- add eax,2e8h //0xBA * 4 ntreadvirtualmemoryaddr ssdt186
- mov eax,DWORD PTR [eax]
- mov oldreadaddr,eax
- mov ebx,DWORD PTR [eax+3h]
- mov readpush,ebx
- add eax,7h
- mov readjmpaddr,eax
- mov eax,ssdtaddr
- add eax,454h //0x115*4 ntwritevirtualmemoryaddr ssdt227
- mov eax,DWORD PTR [eax]
- mov oldwriteaddr,eax
- mov ebx,DWORD PTR [eax+3h]
- mov writepush,ebx
- add eax,7h
- mov writejmpaddr,eax
- cli
- mov eax,cr0
- and eax,not 10000h
- mov cr0,eax
-
- mov ebx,ssdtaddr
- mov eax,yjxsoft_com_NtReadVirtualMemory
- mov DWORD ptr [ebx+2e8h],eax
- // lea ebx,DWORD ptr [ebx+2e8h]
- // mov hr,ebx
- mov eax,yjxsoft_com_NtWriteVirtualMemory
- mov DWORD ptr [ebx+454h],eax
- // lea ebx,DWORD ptr [ebx+454h]
- // mov hw,ebx
-
- mov ebx,ntopenprcaddr
- mov BYTE ptr [ebx],0e9h
- /* int 3*/
- mov eax,offset yjxsoft_com_OpenProcess
- lea eax,yjxsoft_com_OpenProcess
- sub eax,ebx
- sub eax,5h
- mov DWORD ptr [ebx+1h],eax
- /*lea ebx,DWORD ptr[ebx+1h]
- mov h1,ebx*/
-
- mov ebx,ntopentrdaddr
- mov BYTE ptr [ebx],0e9h
- mov eax,offset yjxsoft_com_OpenTread
- sub eax,ebx
- sub eax,5h //计算跳转地址
- mov DWORD ptr [ebx+1h],eax //紧接着 E9后边写 跳转地址
- lea ebx,DWORD ptr[ebx+1h]
- // mov h2,ebx
- // mov eax,90h
- // mov BYTE ptr [ebx+4],al
-
- mov eax,cr0
- or eax,10000h
- mov cr0,eax
- sti
-
-
- }
- //
- //;/////////////////////////////////////////////////////////////////
- //
- void jxcom_UnHook()
- {
- __asm
- {
- pushad
- cli
- mov eax,cr0
- and eax,not 10000h
- mov cr0,eax
- mov eax,ssdtaddr
- mov ebx,DWORD ptr [oldreadaddr]
- mov DWORD ptr [eax+2e8h],ebx
- mov ebx,DWORD ptr [oldwriteaddr]
- mov DWORD ptr [eax+454h],ebx
- mov eax,ntopenprcaddr
- mov dword PTR [eax],0ffc875ffh
- mov WORD ptr [eax+4h],0dc75h
- mov eax,ntopentrdaddr
- mov dword PTR [eax],0ffcc75ffh
- mov WORD ptr [eax+4h],0e075h
- mov eax,cr0
- or eax,10000h
- mov cr0,eax
- sti
- popad
- }
- }
- //yjxsoft_com_UnHook end
- //;////////////////////////////////////////////////////////////////////
复制代码 |