/DBGHider

An IDA plugin aims to hide debugger from processes

Primary LanguagePythonApache License 2.0Apache-2.0

DBGHider

DBGHider is an IDA Pro 7.x plugin written in Python. It aims to hide IDA Winddows debugger from processes.

DBGHider uses idaapi.DBG_Hooks to hook the debugger:

  1. Patch PEB (Process Environment Block) and WoW PEB in function dbg_process_start.
  2. Hook functions, such as NtClose, in function dbg_library_load.

Hooking

DBGHider uses two ways to hook functions: conditional breakpoint and inline hook.

Conditional Breakpoint

IDA Windows debugger supports conditional breakpoint. It allows you to attach a piece of python code to a breakpoint. If the code return True, the proccess suspends at the breakpoint. Otherwise, the process continues.

DBGHider adds a conditional breakpoint at each function you want to hook. And it attachs your code to each breakpoint.

Here is an example for NtClose.

import idautils
import idaapi
handle = idaapi.get_dword(idautils.cpu.esp + 4)
if handle >= 0x1000:
    ret_addr = idaapi.get_dword(idautils.cpu.esp)
    idautils.cpu.eax = 0
    idautils.cpu.esp = idautils.cpu.esp + 8
    idautils.cpu.eip = ret_addr
return False

However, this hooking method has an disadvantage. Some processes check 0xCC at API entry points before calling it.

Inline Hook

To implement inline hook, DBGHider moves one or more instructions at the function entry to somewhere else, then substitues the originals instruction with a jmp 0xhhhhhhhh instruction. And DBGHider writes your hooking code to 0xhhhhhhhh. Your code need to decide what to do, do something then return or execute the normal function. If you decide to execute the normal function, the saved instructions need to be executed first and then jump back.

Here is an example for NtClose.

The original NtClose:

.text:4B2E95D0 ; __stdcall NtClose(x)
.text:4B2E95D0                 public _NtClose@4
.text:4B2E95D0 _NtClose@4      proc near
.text:4B2E95D0                 mov     eax, 3000Fh
.text:4B2E95D5                 mov     edx, offset _Wow64SystemServiceCall@0
.text:4B2E95DA                 call    edx ; Wow64SystemServiceCall()
.text:4B2E95DC                 retn    4
.text:4B2E95DC _NtClose@4      endp

The NtClose being hooked:

.text:4B2E95D0 ; __stdcall NtClose(x)
.text:4B2E95D0                 public _NtClose@4
.text:4B2E95D0 _NtClose@4      proc near
.text:4B2E95D0                 jmp     ntclose_hook
.text:4B2E95D5                 mov     edx, offset _Wow64SystemServiceCall@0
.text:4B2E95DA                 call    edx
.text:4B2E95DC                 retn    4
.text:4B2E95DC _NtClose@4      endp

You hooking code.

ntclose_hook:
    mov     eax, [esp + 4]
    cmp     eax, 0x1000
    jl      jmp_back
    xor     eax, eax
    ret     4
jmp_back:
    mov     eax, 0x3000F
    jmp     0x4B2E95D5

Pleate note that you just need to write the code before jmp_back. The rest is generated by DBGHider automatically.

You can change the hooking method by changing the global variable bpt_hook to True or False.

Install

DBGHider uses keystone to assemble inline hook code. So you need to install keystone python module first, then just copy DBGHider.py to <IDADIR>/plugins/.

TODO

  • hooking more functions. DBGHder only hooks NtClose and NtQueryInformationProcess for now.
  • adding support for x64 process.
  • adding configuration
  • adding UI

If you can help, please do.