概述
将一个程序拖拽进OD中,这种方式是通过 CreateProcess() 建立联系的。
程序正在运行中通过OD附加程序,这种方式是通过 DebugActiveProcess() 建立联系的。
DebugActiveProcess执行流程
<1> kernel32! DbaUiConnectToDbg()
- ntdll! DbgUiConnectToDbg()
- ntdll! ZwCreateDebugObject()
- ntoskrnl! NtCreateDebugObject()
<2> kerel32! DbgUiDebugActiveProcess(被调试进程句柄)
- ntdll! DbgUiDebugActiveProcess(被调试进程句柄)
- ntdll! DebugActiveProcess(被调试进程句柄调试器进程TEB+0xF24)
- ntdll! DebugActiveProcess(HANDLE ProcessHandle, HANDLE DebugObjectHandle)
打开ntdll
这里开始提供操作码开始进入0环,ZwCreateDebugObject就是进入0环创建一个调试对象。
NTSTATUS
NTAPI
ZwCreateDebugObject(
_Out_ PHANDLE DebugHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ ULONG Flags
);
typedef struct _DEBUG_OBJECT
{
KEVENT EventsPresent;
FAST_MUTEX Mutex;
LIST_ENTRY EventList;
union
{
ULONG Flags;
struct
{
UCHAR DebuggerInactive:1;
UCHAR KillProcessOnExit:1;
};
};
} DEBUG_OBJECT, *PDEBUG_OBJECT;
ntdll是3环的只要是3环的一定不会存内核对象的地址而是一个句柄。
ZwCreateDebugObject 第一个参数是OUT类型返回一个句柄,返回到EAX了,这时EAX的位置是TEB+0xF24的位置。
遍历进程中所有线程的TEB+0xF24的位置,如果这个位置有值那你的程序一定是被调试了。
打开ntdll
开始进入0环了
打开ntoskrnl
ObReferenceObjectByHandle 执行完后标黄那Handle的值变成了 “被调试进程”的PEPROCESS结构的地址。
ObReferenceObjectByHandle执行完后Handle那个参数将变成 “调试对象地址”
DbgkpSetProcessDebugObject(
IN PEPROCESS Process, //被调试进程的PEPROCESS
IN PDEBUG_OBJECT DebugObject,//调试对象地址
IN NTSTATUS MsgStatus, //
IN PETHREAD LastThread //调试对象句柄
)
DebugActiveProcess就是像上图那样,将进程与调试器关链到一起。
防守方:
- DebugPort清0(创建完调试对象后要占用被调试的DebugPort,DebugPort被清0就不能与调试器建立联系了)
- 遍历当前进程所有线程_TEB+0xF24 有值就是被调试了
- HOOK NtCreateDebugObject() 不让它创建调试对象
攻击方:
- NtCreateDebugObject 函数就是分配一块内存给_DEBUG_OBJECT,然后给它的成员赋值。我们可以重写它代码对着IDA抄就完事了。
- 要跟被调试进程建立联系需要DebugPort,偏移是0xbc那我们将它改了EPROCESS的结构那么大选一个没用的地方,把用到0xbc的都改为你选的地方的偏移。
- 或者说来个更狠的,重写DebugActiveProcess,偏移什么的都是自己说的算。
最后
以上就是俊逸画笔为你收集整理的1.调试对象DebugActiveProcess执行流程的全部内容,希望文章能够帮你解决1.调试对象DebugActiveProcess执行流程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复