阅读:5360回复:2
HackShield 版本5, 4, 7, 80驱动保护(跑跑拖拉机的)
只谈下hs的驱动层的保护,r3下的ehsvc.dll加了vmp,搞不定啊(针对跑跑拖拉机的)
EagleXNt.sys里面存在好几个名单,有进程的EPROCESS,2个进程ID,r3下面ehsvc.dll里面线程ID 的名单,还有2-3个不知道啥作用的进程ID名单 关于hs的hook其实根本可以不用管,游戏基本上都是有白名单保护的,找到白名单将od和ce之类的添加进去就可以自由打开进程和读写内存了。 hook了如下函数: NtOpenProcess NtReadVirtualMemory NtClose NtDeviceIoControlFile NtGetContextThread NtSetContextThread KiAttachProcess IopXxxControlFile PsSuspendThread NtUserSendInput IRP_MJ_READ kdb hook //过hook像tp之类的可以在游戏启动之前先将这些函数保存一分(要重定位的),然后游戏加载之后再hook sdt替换换来 然后再保存的一份系统函数中记得对于游戏进程来的请求要放过,直接调用被inline hook 的函数。当然如果游戏对 sdt hook有检测这种方法也不行的。 hs将常用的xuter od ce 加载驱动工具 windbg本地调试等之类的都会检测。 并且sys中很多的函数调用都是先得到函数地址保存于变量,然后直接用变量来调用,这样你就不能一眼看出这个调用是干什么的。要自己去windbg本地调试一个个打印出来看看到底是什么函数 sys是有vm的,但是只是vm掉了和r3通信的那一块。 r0下有2个线程 线程一: text:000208B0 CreateMinorSys proc near ; CODE XREF: sub_1FD50+5Dp .text:000208B0 .text:000208B0 var_10 = dword ptr -10h .text:000208B0 var_C = dword ptr -0Ch .text:000208B0 SStatus = dword ptr -8 .text:000208B0 handle = dword ptr -4 .text:000208B0 .text:000208B0 push ebp .text:000208B1 mov ebp, esp .text:000208B3 sub esp, 10h .text:000208B6 mov [ebp+var_10], 0 .text:000208BD xor eax, eax .text:000208BF mov [ebp+var_C], eax .text:000208C2 mov [ebp+SStatus], 0 .text:000208C9 cmp pThkeadBuyIng, 0 .text:000208D0 jnz loc_2095B .text:000208D6 push 0 ; _DWORD .text:000208D8 push 0 ; _DWORD .text:000208DA push offset unk_3B0A0 ; _DWORD .text:000208DF call dword_36AE8 .text:000208E5 push 0 ; _DWORD .text:000208E7 push offset MinorThreadProc ; _DWORD .text:000208EC push 0 ; _DWORD .text:000208EE push 0 ; _DWORD .text:000208F0 push 0 ; _DWORD .text:000208F2 push 1F03FFh ; _DWORD .text:000208F7 lea ecx, [ebp+handle] .text:000208FA push ecx ; _DWORD .text:000208FB call PsCreateSysThread .text:00020901 mov [ebp+SStatus], eax .text:00020904 xor edx, edx .text:00020906 cmp [ebp+SStatus], 0 .text:0002090A setnl dl .text:0002090D cmp edx, 1 .text:00020910 jz short loc_20917 .text:00020912 mov eax, [ebp+SStatus] .text:00020915 jmp short loc_2095D .text:00020917 ; --------------------------------------------------------------------------- .text:00020917 .text:00020917 loc_20917: ; CODE XREF: CreateMinorSys+60j .text:00020917 push 0 ; _DWORD .text:00020919 push offset pThkeadBuyIng ; _DWORD .text:0002091E push 0 ; _DWORD .text:00020920 push 0 ; _DWORD .text:00020922 push 1F03FFh ; _DWORD .text:00020927 mov eax, [ebp+handle] .text:0002092A push eax ; _DWORD .text:0002092B call ObReferObjectByHandle .text:00020931 mov [ebp+SStatus], eax .text:00020934 xor ecx, ecx .text:00020936 cmp [ebp+SStatus], 0 .text:0002093A setnl cl .text:0002093D cmp ecx, 1 .text:00020940 jz short loc_20951 .text:00020942 mov edx, [ebp+handle] .text:00020945 push edx ; _DWORD .text:00020946 call ZwCloseown .text:0002094C mov eax, [ebp+SStatus] .text:0002094F jmp short loc_2095D .text:00020951 ; --------------------------------------------------------------------------- .text:00020951 .text:00020951 loc_20951: ; CODE XREF: CreateMinorSys+90j .text:00020951 mov eax, [ebp+handle] .text:00020954 push eax ; _DWORD .text:00020955 call ZwCloseown .text:0002095B .text:0002095B loc_2095B: ; CODE XREF: CreateMinorSys+20j .text:0002095B xor eax, eax .text:0002095D .text:0002095D loc_2095D: ; CODE XREF: CreateMinorSys+65j .text:0002095D ; CreateMinorSys+9Fj .text:0002095D mov esp, ebp .text:0002095F pop ebp .text:00020960 retn 直接贴F5的代码 int __userpurge MinorThreadProc<eax>(int a1<ebx>, int a2<edi>, int a3<esi>, int a4) { int ebp0; // ebp@0 int v6; // ecx@5 int ProcessId; // eax@6 int v8; // eax@8 int v9; // eax@16 unsigned __int8 v10; // al@18 int v15; // [sp+0h] [bp-A4h]@18 int i; // [sp+4h] [bp-A0h]@18 int ProId; // [sp+8h] [bp-9Ch]@18 int bRet; // [sp+Ch] [bp-98h]@18 int eProcess1; // [sp+10h] [bp-94h]@12 int v20; // [sp+14h] [bp-90h]@5 int v21; // [sp+18h] [bp-8Ch]@18 char v22; // [sp+1Bh] [bp-89h]@5 int status; // [sp+1Ch] [bp-88h]@5 int eProcess; // [sp+20h] [bp-84h]@5 int v25; // [sp+24h] [bp-80h]@10 int v26; // [sp+28h] [bp-7Ch]@18 int v27; // [sp+2Ch] [bp-78h]@10 int v28; // [sp+30h] [bp-74h]@18 int v29; // [sp+34h] [bp-70h]@18 int v30; // [sp+38h] [bp-6Ch]@18 int v31; // [sp+3Ch] [bp-68h]@18 int v32; // [sp+40h] [bp-64h]@18 int v33; // [sp+44h] [bp-60h]@18 int StaRet; // [sp+54h] [bp-50h]@2 int v35; // [sp+58h] [bp-4Ch]@1 int v36; // [sp+5Ch] [bp-48h]@1 int v37; // [sp+60h] [bp-44h]@1 int v38; // [sp+68h] [bp-3Ch]@1 int v39; // [sp+6Ch] [bp-38h]@1 int *v40; // [sp+70h] [bp-34h]@1 int Timer; // [sp+74h] [bp-30h]@1 char v42; // [sp+9Fh] [bp-5h]@1 int v43; // [sp+A0h] [bp-4h]@1 v36 = 0; v37 = 0; v35 = 0; v43 = 0; v38 = 0; v42 = 0; v39 = (int)&unk_3B0A0; v40 = &Timer; dword_36AF8(&Timer, 1); dword_36AFC(&Timer, 0, 0, 3000, 0); while ( 1 ) // Pointer to an array of pointers to dispatcher objects { StaRet = KeWaitForMulObject(2, &v39, 1, 0, 0, 0, 0, 0);// KeWaitForMultipleObjects 等待2个对象 if ( !StaRet ) break; if ( ProcessIdTwo ) { status = 0; eProcess = 0; v22 = 0; v20 = InterlockedExchange(&ProcessIdTwo, 0); if ( (unsigned __int8)CheckWhiteProcessIdByList(v20, 0x84u) != 1 ) { ProcessId = PsGetCurrentProId(v6); if ( v20 != ProcessId ) { status = PLookupProcessByProcId(v20, &eProcess); if ( status >= 0 == 1 ) { v8 = KeAttachProcess(eProcess); v22 = CheckWhiteEprocessByList(v8, a1, a2, a3, eProcess, 4); KeDetachProcess(); ObDerefenceObject(eProcess); } } } if ( (unsigned __int8)v22 != 1 ) // 不在白名单中 { v25 = (int)byte_10601; v27 = v20; sub_134A0(0, 0x30u, &v25, 0i64, 0); } } if ( ProessIdOne ) { eProcess1 = 0; ProId = InterlockedExchange(&ProessIdOne, 0); bRet = PLookupProcessByProcId(ProId, &eProcess1); if ( bRet >= 0 == 1 ) { v25 = (int)byte_10B01; // 不在白名单中的话就进行一些操作 v27 = ProId; if ( (unsigned __int8)sub_134A0(0, 0x30u, &v25, 0i64, 0) == 1 ) TagsEprocessOutTime(eProcess1); ObDerefenceObject(eProcess1); } } v9 = v35++; if ( (unsigned int)v9 > 0xA ) // a次一次循环 { InterlockedExchange(&dword_3B134, 0); // 清零 v35 = 0; } while ( 1 ) //这个sub_1BB30不知道干啥的,貌似是操作IRP的 { sub_1BB30(v15, i, ProId, bRet, eProcess1, v20, v21, status, eProcess, v25, v26, v27, v28, v29, v30, v31, v32, v33); if ( v10 != 1 ) // 这个地方也patch break; v15 = 0; _DX = 0xCF9u; _AL = 6; __asm { out dx, al } for ( i = 0; (unsigned int)i < 0x2710; ++i )//重启代码 { __asm { in al, 64h ; AT Keyboard controller 8042. } v15 = _AL; if ( !(_AL & 2) && !(v15 & 1) ) { _AL = 0xFEu; __asm { out 64h, al ; AT Keyboard controller 8042. } break; } } sub_1BB00(a1, ebp0, a2, a3); } // 检测2和3这2个函数的hook? CheckHook(2, (int)&v42); CheckHook(3, (int)&v42); CheckThread(); // 里面检测是否r3下的EvsDll的线程是否被结束了,要是结束了 // 就结束进程并重启 if ( (unsigned __int8)FlagsToCheckThreadState == 1 )//这里面可以patch掉,将FlagsToCheckThreadState 置0 就可以去掉监视r3下dll里面线程的暂停。 MinorThreadState();//里面监视到线程暂停的话就会结束进程重启的 } // 大循环结束 KeCanTimer(&Timer); return PsTermiSystemThread(0); } //并未做详细注释,看下名字就知道干什么的吧 线程二:这个线程就是等待事件,并设置事件,估计是和r3通信用的吧,没什么用 .text:0002CE80 ; void __stdcall WaitForThreadProc(PVOID) .text:0002CE80 WaitForThreadProc proc near ; DATA XREF: sub_2C6E0+C9o .text:0002CE80 .text:0002CE80 var_4 = dword ptr -4 .text:0002CE80 arg_0 = dword ptr 8 .text:0002CE80 .text:0002CE80 push ebp .text:0002CE81 mov ebp, esp .text:0002CE83 push ecx .text:0002CE84 mov eax, [ebp+arg_0] .text:0002CE87 mov [ebp+var_4], eax .text:0002CE8A cmp [ebp+var_4], 0 .text:0002CE8E jnz short loc_2CE92 .text:0002CE90 jmp short loc_2CECD .text:0002CE92 ; --------------------------------------------------------------------------- .text:0002CE92 .text:0002CE92 loc_2CE92: ; CODE XREF: WaitForThreadProc+Ej .text:0002CE92 ; WaitForThreadProc+43j .text:0002CE92 mov ecx, [ebp+var_4] .text:0002CE95 movzx edx, byte ptr [ecx] .text:0002CE98 cmp edx, 1 .text:0002CE9B jz short loc_2CEC5 .text:0002CE9D push 1 ; Wait .text:0002CE9F push 0 ; Increment .text:0002CEA1 mov eax, [ebp+var_4] .text:0002CEA4 add eax, 4 .text:0002CEA7 push eax ; Event .text:0002CEA8 call ds:KeSetEvent .text:0002CEAE push 0 ; Timeout .text:0002CEB0 push 0 ; Alertable .text:0002CEB2 push 1 ; WaitMode .text:0002CEB4 push 0Dh ; WaitReason .text:0002CEB6 mov ecx, [ebp+var_4] .text:0002CEB9 add ecx, 14h .text:0002CEBC push ecx ; Object .text:0002CEBD call ds:KeWaitForSingleObject .text:0002CEC3 jmp short loc_2CE92 .text:0002CEC5 ; --------------------------------------------------------------------------- .text:0002CEC5 .text:0002CEC5 loc_2CEC5: ; CODE XREF: WaitForThreadProc+1Bj .text:0002CEC5 push 0 ; ExitStatus .text:0002CEC7 call ds:PsTerminateSystemThread .text:0002CECD .text:0002CECD loc_2CECD: ; CODE XREF: WaitForThreadProc+10j .text:0002CECD mov esp, ebp .text:0002CECF pop ebp .text:0002CED0 retn 4 .text:0002CED0 WaitForThreadProc endp 现在来看下白名单 下面我说下怎么找白名单,游戏都是hook相关函数,然后再hook 过程中判断相应的请求是否合法,因此必然就有一个 判断是否合法的规则,就是一个名单。 例如本sys中他有hook NtReadVirtualMemory。可以从这里面着手 说下方法吧:在xuter里面看到被hook过程的函数地址,然后转换下地址,在ida中找到相应位置(具体怎么转换不用问了吧) .text:00022D10 MyInlineReadVirtualMemory proc near ; DATA XREF: HookSwitchJmp+535o .text:00022D10 ; HookSwitchJmp+C21o .text:00022D10 mov eax, esp .text:00022D12 add eax, 8 .text:00022D15 pusha .text:00022D16 pushf .text:00022D17 push ebp .text:00022D18 mov ebp, esp .text:00022D1A sub esp, 40h .text:00022D1D mov ecx, [eax+8] .text:00022D20 mov [ebp-4], ecx .text:00022D23 mov ecx, offset qword_3B108 ; Addend .text:00022D28 call ds:InterlockedIncrement .text:00022D2E lea eax, [ebp-0Ch] .text:00022D31 push eax .text:00022D32 push 18h .text:00022D34 lea ecx, [ebp-28h] ; _DWORD .text:00022D37 push ecx .text:00022D38 push 0 ; _DWORD .text:00022D3A mov edx, [ebp-4] .text:00022D3D push edx ; _DWORD .text:00022D3E call ZwQueryInformationProcessOwn .text:00022D44 mov [ebp-10h], eax .text:00022D47 xor eax, eax .text:00022D49 cmp dword ptr [ebp-10h], 0 .text:00022D4D setnl al .text:00022D50 cmp eax, 1 .text:00022D53 jnz loc_22E2F .text:00022D59 call PsGetCurrentProId .text:00022D5F mov [ebp-8], eax .text:00022D62 push 4 .text:00022D64 mov ecx, [ebp-8] .text:00022D67 push ecx .text:00022D68 call CheckWhiteProcIdByList1 ; A2=4 .text:00022D6D movzx edx, al ; _DWORD .text:00022D70 cmp edx, 1 .text:00022D73 jnz short loc_22DB9 .text:00022D75 push 4 .text:00022D77 mov eax, [ebp-18h] .text:00022D7A push eax .text:00022D7B call CheckWhiteProcessIdByList ; 在白名单list中就返回1 .text:00022D80 movzx ecx, al ; _DWORD .text:00022D83 cmp ecx, 1 .text:00022D86 jnz short loc_22DB7 .text:00022D88 push 4 .text:00022D8A mov edx, [ebp-8] .text:00022D8D push edx .text:00022D8E call CheckWhiteProcessIdByList ; 在白名单list中就返回1 .text:00022D93 movzx eax, al .text:00022D96 cmp eax, 1 .text:00022D99 jz short loc_22DA0 .text:00022D9B jmp loc_22E46 .text:00022DA0 ; --------------------------------------------------------------------------- .text:00022DA0 .text:00022DA0 loc_22DA0: ; CODE XREF: MyInlineReadVirtualMemory+89j .text:00022DA0 push 1 .text:00022DA2 call dword_36ADC .text:00022DA8 push eax .text:00022DA9 call sub_207B0 .text:00022DAE mov edx, [ebp-8] .text:00022DB1 push edx .text:00022DB2 call DeleteWhiteProcessId1 .text:00022DB7 .text:00022DB7 loc_22DB7: ; CODE XREF: MyInlineReadVirtualMemory+76j .text:00022DB7 jmp short loc_22E2F .text:00022DB9 ; --------------------------------------------------------------------------- .text:00022DB9 .text:00022DB9 loc_22DB9: ; CODE XREF: MyInlineReadVirtualMemory+63j .text:00022DB9 push 4 .text:00022DBB mov eax, [ebp-18h] .text:00022DBE push eax .text:00022DBF call CheckWhiteProcessIdByList ; 在白名单list中就返回1 .text:00022DC4 movzx ecx, al .text:00022DC7 cmp ecx, 1 .text:00022DCA jnz short loc_22E2F .text:00022DCC push 4 .text:00022DCE mov edx, [ebp-8] .text:00022DD1 push edx .text:00022DD2 call CheckWhiteProcessIdByList ; 在白名单list中就返回1 .text:00022DD7 movzx eax, al .text:00022DDA cmp eax, 1 .text:00022DDD jz short loc_22E21 .text:00022DDF push 4 .text:00022DE1 call ds:IoGetCurrentProcess .text:00022DE7 push eax .text:00022DE8 call CheckWhiteEprocessByList .text:00022DED movzx ecx, al .text:00022DF0 cmp ecx, 1 .text:00022DF3 jz short loc_22E02 .text:00022DF5 push 4 .text:00022DF7 mov edx, [ebp-8] .text:00022DFA push edx .text:00022DFB call InsertWhiteProcessIdList1 .text:00022E00 jmp short loc_22E46 .text:00022E02 ; --------------------------------------------------------------------------- .text:00022E02 .text:00022E02 loc_22E02: ; CODE XREF: MyInlineReadVirtualMemory+E3j .text:00022E02 call ds:IoGetCurrentProcess .text:00022E08 push eax .text:00022E09 call AgainCheckWhitList ; 再次检查下白名单,确实+56处必须是0 .text:00022E0E movzx eax, al .text:00022E11 cmp eax, 1 .text:00022E14 jz short loc_22E1F .text:00022E16 mov ecx, [ebp-8] ; _DWORD .text:00022E19 push ecx ; Value .text:00022E1A call RecordProcessId .text:00022E1F .text:00022E1F loc_22E1F: ; CODE XREF: MyInlineReadVirtualMemory+104j .text:00022E1F jmp short loc_22E2F .text:00022E21 ; --------------------------------------------------------------------------- .text:00022E21 .text:00022E21 loc_22E21: ; CODE XREF: MyInlineReadVirtualMemory+CDj .text:00022E21 push 1 .text:00022E23 call dword_36ADC .text:00022E29 push eax .text:00022E2A call sub_207B0 .text:00022E2F .text:00022E2F loc_22E2F: ; CODE XREF: MyInlineReadVirtualMemory+43j .text:00022E2F ; MyInlineReadVirtualMemory:loc_22DB7j ... .text:00022E2F mov ecx, offset qword_3B108 ; Addend .text:00022E34 call ds:InterlockedDecrement .text:00022E3A add esp, 40h .text:00022E3D pop ebp .text:00022E3E popf .text:00022E3F popa .text:00022E40 jmp OldReadVirtualMemroy .text:00022E46 ; --------------------------------------------------------------------------- .text:00022E46 .text:00022E46 loc_22E46: ; CODE XREF: MyInlineReadVirtualMemory+8Bj .text:00022E46 ; MyInlineReadVirtualMemory+F0j .text:00022E46 mov ecx, offset qword_3B108 ; Addend .text:00022E4B call ds:InterlockedDecrement .text:00022E51 add esp, 40h .text:00022E54 pop ebp .text:00022E55 popf .text:00022E56 popa .text:00022E57 pop eax .text:00022E58 pop eax .text:00022E59 pop eax .text:00022E5A mov eax, 0C0000022h .text:00022E5F retn 14h .text:00022E5F MyInlineReadVirtualMemory endp 从上面可以看出,必须我们的进程要是CheckWhiteProcIdByList1 CheckWhiteProcessIdByList CheckWhiteProcessIdByList 这三个函数中都返回1的话就能直接过掉检测 //名单一般都是链表的形式,当然了,以前的tp是数组的形式,那样就更好过了,直接添加,要是链表的话还得分配内存节点然后加入 总结下 第一个进程ID白名单 dd EagleXNt+26A78 +0x38处事ProcessId +0x24要是4倍数 +0x20标志可以卸载驱动了? // 标志着可以卸载了?如果没有等于1的然后返回0然后就设置卸载历程 +8是DeviceObject? for ( i = WhiteProcessIdList; (int *)i != &WhiteProcessIdList; i = *(_DWORD *)i )// 链表 { // lkd> dd EagleXNt+26A78+24 if ( *(_DWORD *)(i + 0x38) == a1 && a2 & *(_DWORD *)(i + 0x24) )// a2=4 { v3 = 1; break; } } //自己遍历 for ( i = WhiteProcessIdList; (int *)i != &WhiteProcessIdList; i = *(_DWORD *)i ) { kdprint(("ProcessId:%.8X",*(i+0x38))); } 第二个进程ID白名单 0003B298 g_ListHeaderFirst dd 0 dd EagleXNt+2B298 +8处是ProcessId +0xc处要是4 的倍数 for ( i = WhitePrcessIDList1; (int *)i != &WhitePrcessIDList1; i = *(_DWORD *)i ) { if ( i && *(_DWORD *)(i + 8) == ProcessId ) { if ( a2 & *(_DWORD *)(i + 0xC) ) // 要返回1 v3 = 1; break; } } for ( i = WhitePrcessIDList1; (int *)i != &WhitePrcessIDList1; i = *(_DWORD *)i ) { kdprint(("ProcessId:%.8X",*(i+0x8))); } 进程EPROCESS 白名单列表 dd EagleXNt+2B200 这个地址里面存放着白名单列表头 在这个结构的+0x10处存放eprocess +0x56处必须为0字节 +4处必须要为4 的整数 +14h处事某个字符串?W.e.r.F.a.u.l.t...e.x.e应该是exe名字 +0xc=2; +0x8处为DeviceObject +170h为一个IRP dd EagleXNt+2B200 +4存放这下一个list for ( i = WhiteEprocessList; (int *)i != &WhiteEprocessList; i = *(_DWORD *)i ) { v28 = i; if ( i && *(_DWORD *)(v28 + 0x10) == eProcess && a6 & *(_DWORD *)(v28 + 8) ) { v27 = 1; break; } if ( v28 ) { if ( a6 & *(_DWORD *)(v28 + 8) ) v21 = 1; } } //自己遍历下 for( i =88af0ed8 ; (int *)i != &88af0ed8 ; i = *(_DWORD *)i) { kdprint(("%S,eprocess:%.8X,id:%.8X",(wchar_t *)(i+0x14),*(i+0x10),*(i+8))); } 到这里大家应该知道怎么做了吧,直接添加我们的id和进程eprocess进去就可以了 不过既然有名单,那么游戏肯定提供了插入名单和删除名单的操作函数,要是找到了,直接调用sys的函数,就帮我们 添加好了,多爽啊 例如这里面 .text:00026AA0 ; 这个应该插入白名单链表的操作,先检查是否在链表中存在 .text:00026AA0 ; Attributes: bp-based frame .text:00026AA0 .text:00026AA0 ; void __stdcall InsertWhiteEprocessList(const wchar_t *AppName, int a2) .text:00026AA0 InsertWhiteEprocessList proc near .text:00026AA0 .text:00026AA0 var_18 = dword ptr -18h .text:00026AA0 var_14 = dword ptr -14h .text:00026AA0 var_10 = dword ptr -10h .text:00026AA0 var_C = dword ptr -0Ch .text:00026AA0 var_8 = dword ptr -8 .text:00026AA0 var_1 = byte ptr -1 .text:00026AA0 AppName = dword ptr 8 .text:00026AA0 arg_4 = dword ptr 0Ch .text:00026AA0 .text:00026AA0 push ebp .text:00026AA1 mov ebp, esp .text:00026AA3 sub esp, 18h .text:00026AA6 mov [ebp+var_10], 0 .text:00026AAD cmp g_Flags, 0 .text:00026AB4 jnz short loc_26ABB .text:00026AB6 jmp loc_26BE8 。。。。。。。。 .text:00026BF0 ; void __stdcall InsertWhiteProcessIdList1(int ProcessId, int a2) .text:00026BF0 InsertWhiteProcessIdList1 proc near ; CODE XREF: MyInlineOpenProcess+DAp .text:00026BF0 ; sub_22BD0+D7p ... .text:00026BF0 .text:00026BF0 var_18 = dword ptr -18h .text:00026BF0 var_14 = dword ptr -14h .text:00026BF0 var_D = byte ptr -0Dh .text:00026BF0 Node = dword ptr -0Ch .text:00026BF0 var_8 = dword ptr -8 .text:00026BF0 var_1 = byte ptr -1 .text:00026BF0 ProcessId = dword ptr 8 .text:00026BF0 arg_4 = dword ptr 0Ch .text:00026BF0 .text:00026BF0 push ebp .text:00026BF1 mov ebp, esp .text:00026BF3 sub esp, 18h .text:00026BF6 mov [ebp+var_D], 0 .text:00026BFA cmp g_Flags, 0 .text:00026C01 jnz short loc_26C08 .text:00026C03 jmp loc_26D01 ........ //这个是检测r3下ehsvc.dll里面线程是否被结束的,里面有个线程IDm名单的 text:0002C110 ; __int64 __stdcall CheckThreadIsTerminter(int ParentId, int ThreadId) .text:0002C110 CheckThreadIsTerminter proc near ; CODE XREF: CheckThread+2Ap .text:0002C110 .text:0002C110 var_20 = dword ptr -20h .text:0002C110 var_19 = byte ptr -19h .text:0002C110 var_18 = dword ptr -18h .text:0002C110 var_14 = dword ptr -14h .text:0002C110 var_10 = dword ptr -10h .text:0002C110 var_C = dword ptr -0Ch .text:0002C110 Kthread = dword ptr -4 .text:0002C110 ParentId = dword ptr 8 .text:0002C110 ThreadId = dword ptr 0Ch .text:0002C110 .text:0002C110 push ebp .text:0002C111 mov ebp, esp .text:0002C113 sub esp, 20h .text:0002C116 mov [ebp+var_10], 0 .text:0002C11D mov [ebp+var_C], 0 .text:0002C124 mov [ebp+Kthread], 0 .text:0002C12B cmp dword_3B5A0, 0 .text:0002C132 jg short loc_2C13D .text:0002C134 xor eax, eax .text:0002C136 xor edx, edx .text:0002C138 jmp loc_2C2AE .text:0002C13D ; --------------------------------------------------------------------------- .text:0002C13D .text:0002C13D loc_2C13D: ; CODE XREF: CheckThreadIsTerminter+22j .text:0002C13D mov ecx, offset stru_3B580 ; FastMutex .text:0002C142 call ds:ExAcquireFastMutex .text:0002C148 mov eax, EvsDllThreadList .text:0002C14D mov [ebp+var_14], eax .text:0002C150 .text:0002C150 loc_2C150: ; CODE XREF: CheckThreadIsTerminter+188j .text:0002C150 cmp [ebp+var_14], offset EvsDllThreadList .text:0002C157 jz loc_2C29D .text:0002C15D mov ecx, [ebp+var_14] .text:0002C160 mov [ebp+var_18], ecx .text:0002C163 cmp [ebp+var_18], 0 .text:0002C167 jz loc_2C290 .text:0002C16D mov edx, [ebp+var_18] .text:0002C170 cmp dword ptr [edx+14h], 0 .text:0002C174 jz loc_2C290 .text:0002C17A lea eax, [ebp+Kthread] .text:0002C17D push eax .text:0002C17E mov ecx, [ebp+var_18] .text:0002C181 mov edx, [ecx+14h] .text:0002C184 push edx .text:0002C185 call PsLookupThreadByThreadId .text:0002C18A mov [ebp+var_20], eax .text:0002C18D xor eax, eax .text:0002C18F cmp [ebp+var_20], 0 .text:0002C193 setnl al .text:0002C196 cmp eax, 1 .text:0002C199 jz short loc_2C1D1 .text:0002C19B mov ecx, [ebp+var_18] .text:0002C19E mov edx, [ecx+8] .text:0002C1A1 mov [ebp+var_10], edx .text:0002C1A4 mov eax, [ecx+0Ch] .text:0002C1A7 mov [ebp+var_C], eax .text:0002C1AA cmp [ebp+ThreadId], 0 .text:0002C1AE jz short loc_2C1BB .text:0002C1B0 mov ecx, [ebp+ThreadId] .text:0002C1B3 mov edx, [ebp+var_18] .text:0002C1B6 mov eax, [edx+14h] .text:0002C1B9 mov [ecx], eax .text:0002C1BB .text:0002C1BB loc_2C1BB: ; CODE XREF: CheckThreadIsTerminter+9Ej .text:0002C1BB cmp [ebp+ParentId], 0 .text:0002C1BF jz short loc_2C1CC .text:0002C1C1 mov ecx, [ebp+ParentId] .text:0002C1C4 mov edx, [ebp+var_18] .text:0002C1C7 mov eax, [edx+10h] .text:0002C1CA mov [ecx], eax .text:0002C1CC .text:0002C1CC loc_2C1CC: ; CODE XREF: CheckThreadIsTerminter+AFj .text:0002C1CC jmp loc_2C29D .text:0002C1D1 ; --------------------------------------------------------------------------- .text:0002C1D1 .text:0002C1D1 loc_2C1D1: ; CODE XREF: CheckThreadIsTerminter+89j .text:0002C1D1 cmp [ebp+Kthread], 0 .text:0002C1D5 jz loc_2C286 .text:0002C1DB mov ecx, [ebp+Kthread] .text:0002C1DE push ecx .text:0002C1DF call PsIsThreadTerminating .text:0002C1E4 movzx edx, al .text:0002C1E7 cmp edx, 1 .text:0002C1EA jnz short loc_2C229 .text:0002C1EC mov eax, [ebp+Kthread] .text:0002C1EF push eax ; _DWORD .text:0002C1F0 call ObDerefenceObject .text:0002C1F6 mov ecx, [ebp+var_18] .text:0002C1F9 mov edx, [ecx+8] .text:0002C1FC mov [ebp+var_10], edx .text:0002C1FF mov eax, [ecx+0Ch] .text:0002C202 mov [ebp+var_C], eax .text:0002C205 cmp [ebp+ThreadId], 0 .text:0002C209 jz short loc_2C216 .text:0002C20B mov ecx, [ebp+ThreadId] .text:0002C20E mov edx, [ebp+var_18] .text:0002C211 mov eax, [edx+14h] .text:0002C214 mov [ecx], eax .text:0002C216 .text:0002C216 loc_2C216: ; CODE XREF: CheckThreadIsTerminter+F9j .text:0002C216 cmp [ebp+ParentId], 0 .text:0002C21A jz short loc_2C227 .text:0002C21C mov ecx, [ebp+ParentId] .text:0002C21F mov edx, [ebp+var_18] .text:0002C222 mov eax, [edx+10h] .text:0002C225 mov [ecx], eax .text:0002C227 .text:0002C227 loc_2C227: ; CODE XREF: CheckThreadIsTerminter+10Aj .text:0002C227 jmp short loc_2C29D .text:0002C229 ; --------------------------------------------------------------------------- .text:0002C229 .text:0002C229 loc_2C229: ; CODE XREF: CheckThreadIsTerminter+DAj .text:0002C229 cmp ThreadStateOffset, 0 .text:0002C230 jz short loc_2C286 .text:0002C232 mov ecx, [ebp+Kthread] .text:0002C235 add ecx, ThreadStateOffset .text:0002C23B mov dl, [ecx] .text:0002C23D mov [ebp+var_19], dl .text:0002C240 movzx eax, [ebp+var_19] .text:0002C244 cmp eax, 4 .text:0002C247 jnz short loc_2C286 .text:0002C249 mov ecx, [ebp+Kthread] .text:0002C24C push ecx ; _DWORD .text:0002C24D call ObDerefenceObject .text:0002C253 mov edx, [ebp+var_18] .text:0002C256 mov eax, [edx+8] .text:0002C259 mov [ebp+var_10], eax .text:0002C25C mov ecx, [edx+0Ch] .text:0002C25F mov [ebp+var_C], ecx .text:0002C262 cmp [ebp+ThreadId], 0 .text:0002C266 jz short loc_2C273 .text:0002C268 mov edx, [ebp+ThreadId] .text:0002C26B mov eax, [ebp+var_18] .text:0002C26E mov ecx, [eax+14h] .text:0002C271 mov [edx], ecx .text:0002C273 .text:0002C273 loc_2C273: ; CODE XREF: CheckThreadIsTerminter+156j .text:0002C273 cmp [ebp+ParentId], 0 .text:0002C277 jz short loc_2C284 .text:0002C279 mov edx, [ebp+ParentId] .text:0002C27C mov eax, [ebp+var_18] .text:0002C27F mov ecx, [eax+10h] .text:0002C282 mov [edx], ecx .text:0002C284 .text:0002C284 loc_2C284: ; CODE XREF: CheckThreadIsTerminter+167j .text:0002C284 jmp short loc_2C29D .text:0002C286 ; --------------------------------------------------------------------------- .text:0002C286 .text:0002C286 loc_2C286: ; CODE XREF: CheckThreadIsTerminter+C5j .text:0002C286 ; CheckThreadIsTerminter+120j ... .text:0002C286 mov edx, [ebp+Kthread] .text:0002C289 push edx ; _DWORD .text:0002C28A call ObDerefenceObject .text:0002C290 .text:0002C290 loc_2C290: ; CODE XREF: CheckThreadIsTerminter+57j .text:0002C290 ; CheckThreadIsTerminter+64j .text:0002C290 mov eax, [ebp+var_14] .text:0002C293 mov ecx, [eax] .text:0002C295 mov [ebp+var_14], ecx .text:0002C298 jmp loc_2C150 .text:0002C29D ; --------------------------------------------------------------------------- .text:0002C29D .text:0002C29D loc_2C29D: ; CODE XREF: CheckThreadIsTerminter+47j .text:0002C29D ; CheckThreadIsTerminter:loc_2C1CCj ... .text:0002C29D mov ecx, offset stru_3B580 ; FastMutex .text:0002C2A2 call ds:ExReleaseFastMutex .text:0002C2A8 mov eax, [ebp+var_10] .text:0002C2AB mov edx, [ebp+var_C] .text:0002C2AE .text:0002C2AE loc_2C2AE: ; CODE XREF: CheckThreadIsTerminter+28j .text:0002C2AE mov esp, ebp .text:0002C2B0 pop ebp .text:0002C2B1 retn 8 .text:0002C2B1 CheckThreadIsTerminter endp 到这里大家知道怎么加名单了吧,加入后在od里面就可以正常看见游戏进程了,也可以附加什么的 到这里我本以为hs已经被我干掉了,其实并不然 hs的最核心部分确实r3下的面的ehsvc.dll dll加了tmd壳,而且每个输出表函数都有vm,只能靠以前的一些 资料来猜测着作用。这个dll对游戏主程 dll相应模块都有校验,并和服务器通信。 这个年代搞不了vmp ,r3下的都是浮云啊。 呵呵,言语组织不行,在这祝贺驱网十年生日,祝越办越好 |
|
沙发#
发布于:2011-04-06 18:17
现在没有加vmp的代码真的太少了,分析的很给力,支持下
|
|
板凳#
发布于:2012-04-07 12:20
【说给自己听的话】1.放弃留不住的人。留住了个别人,也许会失去一群人。2.自己一定要在乎自尊,你的自尊在别人眼里一钱不值。 郑州牛皮癣专科医院 3.可以不把别人当朋友,也别把别人当敌人。4.一生会有很多诱惑,自己一定要有个底限。5.我们必须接受失望,因为它是有限的,但千万不可失去希望,因为它是无穷的。
|
|