HOOK NtCreateThread 怎么获得 创建进程的命令行参数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HOOK NtCreateThread 怎么获得 创建进程的命令行参数相关的知识,希望对你有一定的参考价值。

不在驱动级用不了ObReferenceObjectByHandle吧
用NtQueryInformationProcess(ProcessHandle,……
得不到理想中的结果

线程注入,说到底还是创建线程,只不过创建的线程在别的进程中运行而已,那么,我们需要下手的地方跟监控普通线程创建需要下手的地方应当是一样的——NtCreateThread(不过这不是一个太好的选择,因为NtCreateThread的定位稍显麻烦。这儿只是一个为了说明如何监控而做一个例子而已,所以尽可能选择简单的方法来挂钩,修改ssdt可以挂这个函数,所以就选择了它。^-^更好的选择见后文)。

我认为我有必要先列出NtCreateThread的原型:

NTSTATUS
NtCreateThread(
__out PHANDLE ThreadHandle,
__in ACCESS_MASK DesiredAccess,
__in_opt POBJECT_ATTRIBUTES ObjectAttributes,
__in HANDLE ProcessHandle,
__out PCLIENT_ID ClientId,
__in PCONTEXT ThreadContext,
__in PINITIAL_TEB InitialTeb,
__in BOOLEAN CreateSuspended
)

__out的那些就都不解释了,主要解释需要用到的。
access_mask是访问权限,不解释;ObjectAttr是对象属性,_opt的,不解释;ProcessHandle就是将要被创建线程的进程(新线程在这个进程中运行)的句柄了;剩下几个也跟本文无关,也不解释,需要了解详细信息可以查MSDN。

需要关注的参数我想我已经说的很明确了——ProcessHandle。我们可以使用ObReferenceObjectByHandle来获取这个Handle所指向的进程的EPROCESS的地址(PEPROCESS)。

剩下的就是判断这个线程是正常创建还是远程创建的问题了,这个判断将会变得很容易,因为我们可以用获得到PEPROCESS和IoGetCurrentProcess的结果相比较——NtCreateThread总是应当在创建者的进程上下文中被执行。

不过当我们编译运行之后就会发现,还有一个问题是我们不得不关注的——运行程序的时候父进程会“帮助”子进程创建子进程的主要线程(因为这个时候子进程还没有线程,所以不可能自己创建),所以这就引出了另外一个问题——如何判断这个远程线程创建是注入还是正常的程序运行呢?

简单分析下我们不难发现,二者的区别在于将被创建线程的进程是否还存在其他线程——因为我们的代码是在NtCreateThread之前执行的,所以如果是正常运行的程序的话,这个时候它不应当有任何的线程,而线程注入则不同,线程注入的话目标进程应当已经有了至少一个线程(一个主线程和若干个附属线程(或者没有附属线程))。

那么如何判断目标进程是否已经存在线程呢?在EPROCESS结构中:

...
+0x190 ThreadListHead : _LIST_ENTRY
...

我想这个ThreadListHead这是很容易理解的。。。。

实现方法(因为只是为了演示,所以所有的地址、偏移等都是硬编码):

ThreadListHead = 0x190;
//==========================================
BOOLEAN
ProcessNoThread( PEPROCESS Process)

PLIST_ENTRY Entry;
PLIST_ENTRY ThreadListEntry;
PLIST_ENTRY ListHead;

ThreadListEntry = (PLIST_ENTRY)((ULONG)Process + ThreadListHead);
Entry = ThreadListEntry->Flink;
return (Entry==ThreadListEntry);


//==========================================
NTSTATUS new_NtCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PVOID InitialTeb,
IN BOOLEAN CreateSuspended )

NTSTATUS st;
PVOID pepCurrentProcess=0;
st=ObReferenceObjectByHandle(ProcessHandle,(ACCESS_MASK)PROCESS_ALL_ACCESS,NULL,KernelMode,&pepCurrentProcess,NULL);
if (NT_SUCCESS(st))

if (IoGetCurrentProcess()!=pepCurrentProcess)

if (!ProcessNoThread((PEPROCESS)pepCurrentProcess)) DbgPrint("PROCESS 0x%X have created a thread into PROCESS 0x%X, NtCreateThread return value = 0x%x",IoGetCurrentProcess(),pepCurrentProcess,st);

ObDereferenceObject((PVOID)pepCurrentProcess);

st=old_NtCreateThread(ThreadHandle,DesiredAccess,ObjectAttributes,ProcessHandle,ClientId,ThreadContext,InitialTeb,CreateSuspended);
return st;

//==========================================

我想这段代码也不至于太难理解。。

是时候说说其他的一些问题了:

1、其实hook PspCreateThread要比hook NtCreateThread相对容易一些(两个函数同样都没有被导出,而PspCreateThread可以很容易的在PsCreateSystemThread中被定位,但NtCreateThread的定位就需要分析PE文件了(改SSDT另当别论,不过改SSDT的强度太差))。

2、遍历进程的线程是使用硬编码的,这使得通用性变得很差,而通过遍历PspCidTable枚举系统中的线程则成为一种不错的方法(从PspCreateThread中的代码来看,是由PspCreateThread在PspCidTable中ExCreateHandle的,但是我没有做测试)

就这样把,我自负的认为我的语言表达能力还算是不错的。

---EOF---
参考技术A PROCESS_BASIC_INFORMATION pbi;
PEB2 peb;
PROCESS_PARAMETERS ppa;
wchar_t pa[255];

NtQueryInformationProcess(ProcessHandle,ProcessBasicInformation,(void *) &pbi,sizeof(PROCESS_BASIC_INFORMATION),0);
ReadProcessMemory(ProcessHandle,pbi.PebBaseAddress,(void *) &peb,sizeof(PEB2),0);
ReadProcessMemory(ProcessHandle,peb.ProcessParameters,(void *) &ppa,sizeof(PROCESS_PARAMETERS),0);
ReadProcessMemory(ProcessHandle,ppa.CommandLine.Buffer,pa,ppa.CommandLine.Length,0);本回答被提问者采纳

app检测到hook打不开

参考技术A app检测到hook打不开,有hook风险可以下载手机管家或者360管家清理相关垃圾,并且删除一些乱七八糟的软件,可能会好一点。 参考技术B 有hook风险可以下载手机管家或者360管家清理相关垃圾,并且删除一些乱七八糟的软件,可能会好一点。

以上是关于HOOK NtCreateThread 怎么获得 创建进程的命令行参数的主要内容,如果未能解决你的问题,请参考以下文章

通用hook拦截所有API的实现

Xposed hook函数内有匿名内部类该怎么写

tp5 的hook钩子 怎么用

app检测到hook打不开

app被加固了,该怎么用xposed模块hook

windows Hook 消息分类