首页
论坛
专栏
课程

[商业保护] [原创]围观tp驱动保护。详解debugport清0

2012-8-25 22:15 38914

[商业保护] [原创]围观tp驱动保护。详解debugport清0

2012-8-25 22:15
38914
刚毕业,找工作的时候郁闷中,还没找到理想的工作,刚好回到家又没什么事情,就研究下tp保护,闲闲散散的也搞了2个星期了。索性弄好了也就发篇文章了,求个精华阿,第一个精华不知道有木有的。对于tp网上已经有不少的文章了,但貌似的看了一些也有一些的不足,本文完全出于兴趣研究的目的,请勿用于商业用途。第一次写这样的文章,文中有不足的地方,还希望大家指正。
欢迎志同道合的朋友一起研究,一起讨论,只做研究为目的,不作于商业用途。附上本人QQ905050630请注明看雪,谢谢。
下面的是我求职的简历,真心求正规公司,求机会,顺带发下我的简历。
http://bbs.pediy.com/showthread.php?t=154765
好了, 进入正题。
  众所周知的几个函数有:
  双机调试
  Debugport清0 
  NtOpenProcess
  NtOpenThread
  KiAttachProcess
  NtReadVirtualMemory
  NtWriteVirtualMemory
  下面这两个函数是调试器接受发送信息用的,如果不处理这两个调试器无法发送接受到信息
  DbgkpSetProcessDebugObject
  DbgkpQueueMessage
  这些在网上已经有很多的文章中讲解了,这里只做简单的讲解,对于debugport清零我认为是tp中的一个难点,而对于这个网上的讲解很少,而且看了下并不完全。
  先来看下双机调试,tp不断的调用KdDisableDebugger禁用调试,对于这个函数,我们对它做了直接返回的处理,因为函数头并没有什么检测,而通过wrk源码中看,这个函数的处理中有



对于调试列程和一个值的赋值,这两处地方地方的赋值我们还需要处理一下。
  在KdDisableDebugger下断后跟踪发现,
  第一次TP加载
  TesSafe+0x56d5:     改成0x74   2字节90
  b13c76d5 75b0            jne     TesSafe+0x5687 (b13c7687)
  
  
  TesSafe+0x5803:   改成0xeb
  b13c7803 7402            je      TesSafe+0x5807 (b13c7807)
  
  
  第二次TP加载
  TesSafe+0x59dd:    改成0x9090
  b10419dd 75b0            jne     TesSafe+0x598f (b104198f)
  
  
  TesSafe+0x5b0b:     改成0xeb
  b1041b0b 7402            je      TesSafe+0x5b0f (b1041b0f)
  这是两次tp加载,分别要处理的位置。
  
  Tp会加载两次,第一次是假的。对于NtOpenProcess的中继函数处理。
  Tp对NtOpenProcess的hook
  // 805c2646 ff75c8          push    dword ptr [ebp-38h]
  // 805c2649 ff75dc          push    dword ptr [ebp-24h]
  // 805c264c e80d5e9f30      call    TesSafe+0xb45e (b0fb845e)
  我们要处理的是在push的位置处进行hook,过滤掉dnf游戏自身访问时候的判断,
  __declspec(naked) void FuckNtOpenProcess()
  {
    __asm
    {
      //判断如果是游戏自身调用的话,则执行被hook的call
      //如果是其他进程调用的话,就跳过被hook的call,执行g_uObOpenObjectByPointerAddr
      pushad
      pushfd
      call isGameAccess
      mov g_isGameAccess, al
      popfd
      popad
      cmp g_isGameAccess,1
      jnz NOISGAME
      push dword ptr [ebp-38h]
      push dword ptr [ebp-24h]
      mov eax, g_uNtOpenProcessHookAddr
      add eax, 6            //hook的代码字节数
      jmp eax
  NOISGAME:
      push dword ptr [ebp-38h]
      push dword ptr [ebp-24h]
      mov eax,g_uObOpenObjectByPointerAddr
      call eax
      push g_uHookNtOpenProcessRet
      ret
    }
  }
  
  下面是NtOpenThread函数的hook和NtOpenProcess同理 ,处理的方法相同,这里贴出中继函数的处理,
  //中继函数处理
  __declspec(naked) void FuckNtOpenThread()
  {
    __asm
    {
      //判断如果是游戏自身调用的话,则执行被hook的call
      //如果是其他进程调用的话,就跳过被hook的call,执行g_uObOpenObjectByPointerAddr
      pushad
      pushfd
      call isGameAccess
      mov g_isGameAccess, al
      popfd
      popad
      cmp g_isGameAccess,1
      jnz NOISGAME
      push dword ptr [ebp-34h]
      push dword ptr [ebp-20h]
      mov eax, g_uNtOpenThreadHookAddr
      add eax, 6            //hook的代码字节数
      jmp eax
  NOISGAME:
      push dword ptr [ebp-34h]
      push dword ptr [ebp-20h]
      mov eax,g_uObOpenObjectByPointerAddr
      call eax
      push g_uHookNtOpenThreadRet
      ret
    }
  }
  两个方法相同,这里不做过多的叙述。下面的是tp对KiAttachProcess的hook



对于KiAttachProcess 的处理, 这里我做了直接恢复。这里的KiAttachProcess并不是导出函数,所以这里我先获得了KeAttachProcess的地址,通过特征码搜索的方式找到了KiAttachProcess 的地址。直接贴代码。
VOID My_HookKiAttachProcess()
{
  BYTE bJmpAddr[7] = {0x8b, 0xff, 0x55, 0x8b, 0xec, 0x53, 0x8b};
  KIRQL klrql;

  // 获取KeAttachProcess地址
  BYTE *bKeAttachProcessAddr = (BYTE *)GetFunAddress(L"KeAttachProcess");

  if (bKeAttachProcessAddr == NULL)
    return;
  
  // 特征码搜索call nt!KiAttachProcess (804f87c8)
  while (TRUE)
  {
    if (*(bKeAttachProcessAddr) == 0xE8 &&
      *(bKeAttachProcessAddr + 5) == 0x5F &&
      *(bKeAttachProcessAddr + 6) == 0x5E &&
      *(bKeAttachProcessAddr + 7) == 0x5D &&
      *(bKeAttachProcessAddr + 8) == 0xC2 &&
      *(bKeAttachProcessAddr - 1) == 0x56 &&
      *(bKeAttachProcessAddr - 2) == 0x57 &&
      *(bKeAttachProcessAddr - 5) == 0xFF &&
      *(bKeAttachProcessAddr - 6) == 0x50)
    {
      g_uKiAttachProcessAddr = *(ULONG *)(bKeAttachProcessAddr + 1) + (ULONG)(bKeAttachProcessAddr + 5);
      break;
    }
    
    bKeAttachProcessAddr++;
  }

  CleanPageProtect(TRUE);
  klrql =  KeRaiseIrqlToDpcLevel();
  
  // Hook目标地址
  RtlCopyMemory((BYTE *)g_uKiAttachProcessAddr, bJmpAddr, 7);
  
  KeLowerIrql(klrql);
  CleanPageProtect(FALSE);
}
下面的是这4个函数的处理, 处理的方法差不多,按照hook前的汇编代码写回去即可。这里也没有什么好说的
  NtReadVirtualMemory
  NtWriteVirtualMemory
  DbgkpSetProcessDebugObject
  DbgkpQueueMessage
直接在下面贴段代码。
对读写内存的两处直接做了恢复。
VOID My_HookNtReadAndNtWriteVirtualMemory()
{
  BYTE bReadAndWritePush[2] = {0x6a, 0x1c};
  BYTE bReadPush[5] = {0x68, 0xe0, 0xa4, 0x4d, 0x80};
  BYTE bWritePush[5] = {0x68, 0xf8, 0xa4, 0x4d, 0x80};
  KIRQL klrql;
  BYTE *uNtReadVirtualMemoryAddr;
  BYTE *uNtWriteVirtualMemoryAddr;

  // 获取NtReadVirtualMemory在SSDT表中的地址
  uNtReadVirtualMemoryAddr = (BYTE *)GetSsdtFunAddress(0xBA);
  if (uNtReadVirtualMemoryAddr == NULL)
    return;
  
  // 获取NtWriteVirtualMemory在SSDT表中的地址
  uNtWriteVirtualMemoryAddr = (BYTE *)GetSsdtFunAddress(0x115);
  if (uNtWriteVirtualMemoryAddr == NULL)
    return;
  
  CleanPageProtect(TRUE);
  klrql =  KeRaiseIrqlToDpcLevel();
  
  // 恢复NtReadVirtualMemory
  RtlCopyMemory(uNtReadVirtualMemoryAddr, bReadAndWritePush, 2);
  RtlCopyMemory(uNtReadVirtualMemoryAddr + 2, bReadPush, 5);
  // 恢复NtWriteVirtualMemory  
  RtlCopyMemory(uNtWriteVirtualMemoryAddr, bReadAndWritePush, 2);
  RtlCopyMemory(uNtWriteVirtualMemoryAddr + 2, bWritePush, 5);
  
  KeLowerIrql(klrql);
  CleanPageProtect(FALSE);  
}
后面的两个函数  同理也是直接做了恢复,没什么好说的。
 接下来就是debugport清零和监控的处理了,我想大多数人关心的也就是这里了,这是我认为tp中的一个难点,EPROCESS结构中的DebugPort 它是调试端口,把这一处的位置下内存访问断点。会发现有4处的清0位置,和2处的检测代码。

来说一下这几处地址是怎么找出来的,大家可以设想一下,把自己当做一个游戏开发者的角度去想,要检测debugport清0的位置处,那就必然游戏如果不对这个地址处进行访问,那又怎么来做这个检测呢,游戏既然要检测,必然就会对这个地址处进行访问,所以我们在debugport的位置处下内存访问断点(ba r4 地址),既然是检测,那同段检测代码到达的肯定就不止是一次而已了,也就是说会多次的不断的到达,反复的观察断下来的原因,结合反汇编代码分析。这一处的地方到底是因为什么而断下来的,这就需要有一点的汇编基础了。因为有几处的代码会被VM,所以如果是遇到被VM后的代码,就不能乱加修改了,以免破坏掉原先要执行的功能。我认为在做这些东西的时候,都可以把自己的方向定位成设计者的角度,反向的思考,别人会是怎么做的,去验证,那就有可能,这个猜想才能得到成立。

第一处位置
TesSafe+0x219e:
b0f8219e 8b09            mov     ecx,dword ptr [ecx]
函数首地址 b0f82124 8bff            mov     edi,edi
TesSafe+0x2124:
b0f82124 8bff            mov     edi,edi
第一处的位置,我们对函数的首地址下个内存访问断点看看, 函数头直接返回的时候是不是会有检测,发现这是一处常规的清零操作。函数头并没有检测。对于这一处我们直接返回即可。
第二处位置
TesSafe+0x58a7:
函数首地址 b0f8585e 8bff            mov     edi,edi
TesSafe+0x585e:
这里需要注意的是这处的函数清0代码不能直接返回,因为函数后还有重要的代码要执行,如果执行返回,即时干掉了两处检测函数,那样也是会有问题的。而我们的办法就是改掉清0的代码,改为nop
在第二处的位置处,我们下内存访问断点的时候发现有检测的代码。
TesSafe+0x3a02:
b0d1fa02 8bff            mov     edi,edi
对于这处的检测我们直接返回了即可。
持续运行多次的时候我们还会发现有一处地方的检测
TesSafe+0x22cc2:
b0edccc2 ff32            push    dword ptr [edx]

TesSafe+0x22cc4:
b0edccc4 e98bf4ffff      jmp     TesSafe+0x22154 (b0edc154)
对于这一处的代码,因为这处的代码有VM处理。所以我们不能对这处的地址乱改。
在push的位置处,我们对代码进行hook的处理,当判断edx是检测函数首地址的时候,我们对其做一下处理,而当不是函数首地址的时候,而执行原来的代码。下面的是这一处的处理代码
__asm
{
pushfd
pushad
mov eax, g_uTpZero1
cmp edx,eax      
je Detour
popad
popfd
push dword ptr [edx]
jmp g_uTPDetourPushAddr   //这是本身程序要jmp过去的位置,jmp到tp模块里的位置处。
Detour: 
popad
popfd
push 0
jmp g_uTPDetourPushAddr1
}
接下来是第三处的清0 位置
第三处位置
TesSafe+0x1ccd0
b0f9ccd0 ff32            push    dword ptr [edx]

TesSafe+0x1ccd2:
b0f9ccd2 e9dfddffff      jmp     TesSafe+0x1aab6 (b0f9aab6)
同理我们对push的位置处进行hook处理,下面是这一处的中继函数处理。
当判断edx是debugport的地址的时候,我们对其进行处理,而不是的时候则就不处理,执行hook前的代码。
__asm
{
pushfd
pushad
mov eax,g_uGetGameBaseAddr
add eax,0xbc      //debugport地址
cmp edx,eax
je Detour
popad
popfd
push dword ptr [edx]
jmp g_uTPDetourPushAddr  
Detour:
popad
popfd
push 0
jmp g_uTPDetourPushAddr
}
第四处位置
TesSafe+0x1e736:
b0f9e736 8f02            pop     dword ptr [edx]

TesSafe+0x1e738:
b0f9e738 e979c3ffff      jmp     TesSafe+0x1aab6 (b0f9aab6)
这一处的处理方法和第三处的处理相同,只需要同样的进行判断下就好了,直接贴上代码。
__asm
{
pushfd
pushad
mov eax,g_uGetGameBaseAddr
add eax,0xbc        //debugport地址
cmp edx,eax
je Detour
popad
popfd
pop dword ptr [edx]
jmp g_uTPDetourPushAddr
Detour: 
popad
popfd
add esp,4
jmp g_uTPDetourPushAddr
}
再说一下tp对deport清0 做的一个手脚,在游戏跑起来后的时候,用windebug看的时候会有两个进程,而如果我们得到的是第一个游戏进程的EPROCESS位置的话,那是错的,要进行下判断,得到第二个进程的EPROCESS才是正确的。
好了,写到这里的话已经差不多了,当然还有硬件断点,枚举系统回调等的没处理,网上资料也很多,这里就不讲了。
以后如果有研究出好的东西也会放出来的。如果有好东西也记得与我分享哈。

[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

上传的附件:
  • 1.png (15.58kb,3573次下载)
  • 2.png (25.72kb,3518次下载)
最新回复 (36)
Reversal 2012-8-25 22:17
2
0
沙发是我的
Reversal 2012-8-25 22:17
3
0
板凳也是我的

个人见解:看雪不太适合发表新人学习和共享学习资料的地方了

一个刚满18岁小伙研究2星期,把自己研究的心得发出来,招来各位传说中的大牛各种喷

又是讲的不好,又是满大街烂货  试想,你18岁时算个啥?

如果一个爱好者学习了的成果,发出来没得到鼓励,反而是各种BS,何来讨论和学习进步,不要觉得你懂了,就满世界的人都懂了,人得思路是不同的

不要拿你得理解去理解全世界的人,BS会了的不共享的却说风凉话的人,鼓励新人进步
尘埃kr 2012-8-25 22:24
4
0
顶一下,继续加油
Nekoxiaoji 2012-8-25 22:32
5
0
很好啊,楼主最好做一个视频教程啊
z许 2012-8-26 03:25
8
0
假如能找到防的方法的话,那么工作就有着落了。
  能够过CRC的话比清零要受关注很多。
本小菜学习了。
神秘力量 2012-8-27 07:11
9
0
顶一下,占个位置
cdty 2012-8-27 09:16
10
0
楼主的详解debugport清0看来不够详解啊,并没用说明debugport在应用层与驱动层之间怎么交互,为什么把debugport改了调试器就收不到调试信号了,调试器怎么与debugport交互的,如果把这些理清楚了,求个精华应该不是什么问题吧,至于楼主的通过对debugport下访问断点的方式,已经烂大街了,也没什么必要发出来
心如止境 2 2012-8-27 21:46
11
0
还是没有说清楚啊,你是怎么发现debugport清零的位置的,这才是重点,如何进行内核调试的.
wangweilll 2 2012-8-27 22:13
12
0
写的的不错应该看过萝卜老兄的教程
不过清0   方法很多
我更喜欢找全局变量,这样只要修改四个字节就OK了
windowsa 2012-8-28 00:52
13
0
为什么只看到了结果,没看到过程呢...比如说 如何找到debugport清零的地址的 神马的..
诶一 2012-8-28 02:21
14
0
怎么找到的我有提到过一点,下内存访问断点,持续多次,看下值,反汇编代码。不过让楼上的这位仁兄cdty 说成是已经烂大街了,也没什么必要发出来。
心如止境 2 2012-8-28 09:23
15
0
呵呵,你应该写篇能让我们这些新人学到东西的文章;你应该告诉我们为什么这么做,而不是告诉我们如何做;注重自己的做法,不要在意人家的说法,才能走的远.加油!
comewisdom 2012-8-28 10:16
16
0
强烈围观,围观中....
wangweilll 2 2012-8-28 13:02
17
0
我来说说这东西吧~~~~

1.首先找到该进程的EPROCESS结构的址
在WinDbg 命令行输入!process 0 0得到EPROCESS结构的址
lkd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****

PROCESS 84648268  SessionId: 0  Cid: 0344    Peb: 7ffd7000  ParentCid: 02f4
    DirBase: 18ca7000  ObjectTable: e14cca28  HandleCount: 272.
    Image: winlogon.exe

2. 再在命令行输入dt _EPROCESS  84648268  

lkd> dt _EPROCESS 84648268  
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER 0x1cd84d5`34f2da66
   +0x078 ExitTime         : _LARGE_INTEGER 0x0
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : 0x00000344 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x84652d90 - 0x846c6e28 ]
   +0x090 QuotaUsage       : [3] 0x1c90
   +0x09c QuotaPeak        : [3] 0x23c0
   +0x0a8 CommitCharge     : 0x49a
   +0x0ac PeakVirtualSize  : 0x368f000
   +0x0b0 VirtualSize      : 0x3342000
   +0x0b4 SessionProcessLinks : _LIST_ENTRY [ 0x84652dbc - 0x846c6e54 ]
   +0x0bc DebugPort        : (null)
   +0x0c0 ExceptionPort    : 0xe1631df0 Void
   +0x0c4 ObjectTable      : 0xe14cca28 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : 0x18caa
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   +0x110 HyperSpaceLock   : 0
   +0x114 ForkInProgress   : (null)
   +0x118 HardwareTrigger  : 0
   +0x11c VadRoot          : 0x8464f008 Void
   +0x120 VadHint          : 0x8464f008 Void
   +0x124 CloneRoot        : (null)
   +0x128 NumberOfPrivatePages : 0x25b
   +0x12c NumberOfLockedPages : 0
   +0x130 Win32Process     : 0xe1803610 Void
   +0x134 Job              : (null)
   +0x138 SectionObject    : 0xe14e5680 Void
   +0x13c SectionBaseAddress : 0x01000000 Void
   +0x140 QuotaBlock       : 0x8056a700 _EPROCESS_QUOTA_BLOCK
   +0x144 WorkingSetWatch  : (null)
   +0x148 Win32WindowStation : 0x000000a8 Void
   +0x14c InheritedFromUniqueProcessId : 0x000002f4 Void
   +0x150 LdtInformation   : (null)
   +0x154 VadFreeHint      : (null)
   +0x158 VdmObjects       : (null)
   +0x15c DeviceMap        : 0xe1008780 Void
   +0x160 PhysicalVadList  : _LIST_ENTRY [ 0x846483c8 - 0x846483c8 ]
   +0x168 PageDirectoryPte : _HARDWARE_PTE
   +0x168 Filler           : 0
   +0x170 Session          : 0xf7bc7000 Void
   +0x174 ImageFileName    : [16]  "winlogon.exe"
   +0x184 JobLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x18c LockedPagesList  : (null)
   +0x190 ThreadListHead   : _LIST_ENTRY [ 0x8471cb7c - 0x8450f24c ]
   +0x198 SecurityPort     : (null)
   +0x19c PaeTop           : (null)
   +0x1a0 ActiveThreads    : 0x10
   +0x1a4 GrantedAccess    : 0x1f0fff
   +0x1a8 DefaultHardErrorProcessing : 0x8000
   +0x1ac LastThreadExitStatus : 0n0
   +0x1b0 Peb              : 0x7ffd7000 _PEB
   +0x1b4 PrefetchTrace    : _EX_FAST_REF
   +0x1b8 ReadOperationCount : _LARGE_INTEGER 0x11b
   +0x1c0 WriteOperationCount : _LARGE_INTEGER 0x68
   +0x1c8 OtherOperationCount : _LARGE_INTEGER 0xcf7
   +0x1d0 ReadTransferCount : _LARGE_INTEGER 0x3e76d4
   +0x1d8 WriteTransferCount : _LARGE_INTEGER 0x1f97
   +0x1e0 OtherTransferCount : _LARGE_INTEGER 0x1bbe4
   +0x1e8 CommitChargeLimit : 0
   +0x1ec CommitChargePeak : 0x646
   +0x1f0 AweInfo          : (null)
   +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x1f8 Vm               : _MMSUPPORT
   +0x238 LastFaultCount   : 0
   +0x23c ModifiedPageCount : 0x51a
   +0x240 NumberOfVads     : 0xa1
   +0x244 JobStatus        : 0
   +0x248 Flags            : 0x50800
   +0x248 CreateReported   : 0y0
   +0x248 NoDebugInherit   : 0y0
   +0x248 ProcessExiting   : 0y0
   +0x248 ProcessDelete    : 0y0
   +0x248 Wow64SplitPages  : 0y0
   +0x248 VmDeleted        : 0y0
   +0x248 OutswapEnabled   : 0y0
   +0x248 Outswapped       : 0y0
   +0x248 ForkFailed       : 0y0
   +0x248 HasPhysicalVad   : 0y0
   +0x248 AddressSpaceInitialized : 0y10
   +0x248 SetTimerResolution : 0y0
   +0x248 BreakOnTermination : 0y0
   +0x248 SessionCreationUnderway : 0y0
   +0x248 WriteWatch       : 0y0
   +0x248 ProcessInSession : 0y1
   +0x248 OverrideAddressSpace : 0y0
   +0x248 HasAddressSpace  : 0y1
   +0x248 LaunchPrefetched : 0y0
   +0x248 InjectInpageErrors : 0y0
   +0x248 VmTopDown        : 0y0
   +0x248 Unused3          : 0y0
   +0x248 Unused4          : 0y0
   +0x248 VdmAllowed       : 0y0
   +0x248 Unused           : 0y00000 (0)
   +0x248 Unused1          : 0y0
   +0x248 Unused2          : 0y0
   +0x24c ExitStatus       : 0n259
   +0x250 NextPageColor    : 0xd6e1
   +0x252 SubSystemMinorVersion : 0 ''
   +0x253 SubSystemMajorVersion : 0x4 ''
   +0x252 SubSystemVersion : 0x400
   +0x254 PriorityClass    : 0x3 ''
   +0x255 WorkingSetAcquiredUnsafe : 0 ''
   +0x258 Cookie           : 0x353f16cb
3.  找到DebugPort  看看    DebugPort  的偏移是多少我的是0xbc
4.EPROCESS的的地址及DebugPort  偏移都找到了就可以开工了
  在命令行输入ba w1 EPROCESS + 0xbc
这条命令:谁对这个地址进行了写的操作,g一下就可以看到清0的地方......
心如止境 2 2012-8-28 13:15
18
0
可以结贴了,还是楼上简单明了,学习一下.
zgyknight 2012-8-28 14:28
19
0
mark~~~~~~~~~~~~
mumaren 2012-8-28 14:45
20
0
那个幸福说的不错

3q
moasm 2012-8-30 00:12
21
0
  如果我是一个想进步的新人, 我就从来不惧怕 高手骂我喷我 -- 只要他们喷我的时候有只言片语的指点, 而不是仅仅喷完走人那种就行.

怕喷 就别TMD来发帖. 想进步就别TMD怕喷.

欢迎大家喷我, (只要不是单纯的人身攻击) 喷 -- 是直白的思维碰撞.
exediy 1 2012-8-30 10:57
22
0
Tp会加载两次,第一次是假的。对于NtOpenProcess的中继函数处理。

。第一次启动做的事情是XXPELOAD。。。并不是所谓假的。。。。
诶一 2012-8-30 21:46
23
0
嗯,是我表达错误。
xed 2012-8-30 23:05
24
0
tp有VM???
诶一 2012-8-31 00:48
25
0
有的。
evilor 2012-8-31 17:53
26
0
楼主加油 年轻淫别浮躁
zhidd 2012-9-10 23:55
27
0
suowei所谓的喷 不就是你在浏览器 打开自己心爱的url(我的领地),看到了一些让你难受的文字, 这有什么害怕??
hackbyll 2012-9-17 11:21
28
0
mark+1
pooiy 2012-11-10 00:42
29
0
请问如何知道代码是VM过的?
lylxd 2012-11-12 00:24
30
0
好帖子~~~~
omni 2013-7-1 18:18
31
0
成功的人,没被喷的很少,所以楼主心态要放好,对你工作或是生活都是有好处的
Jameszhou 2013-7-13 11:53
32
0
Mark一下,慢慢看,谢谢!
jsubject 2013-7-13 12:06
33
0
不错 学习了啊
cqzj70 2014-4-13 18:46
34
0
mark
jkydhe 2014-5-11 09:17
35
0
百度搜到此贴,第一项,众所周知的几个函数我就不知道,那么我应该先学点什么呢?望指点!
天涯何处 2014-6-1 17:19
36
0
楼主是不是成大神了回来给小菜们讲解讲解最新的TP心得呀
南门听雨 2014-6-2 17:13
37
0
我倒是想喷 可惜没水 喷个毛啊
诶一 2014-6-5 18:57
38
0
喷子太多,技术太水,还是留着就不献丑了
wanziying 2014-8-8 00:56
39
0
快点快点快点快点快点看
游客
登录 | 注册 方可回帖
返回