调用过程重点为 KernelBase->ntdll,kernelbase中做了数据的处理,函数名字为NtOpenProcess,ntdll中则选择服务号进入0环,我们可以逆向NtOpenProcess分析具体用了什么参数
在头文件<winternl.h>中包含了这两个结构体,当然CLIENT_ID这个结构体少了一个结构体指针
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
typedef struct _CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
第一步
把原本参数的PID写进CLIENT_ID结构体中
.text:0DCE9175 mov eax, [ebp+dwProcessId]
.text:0DCE9178 mov [ebp+ClientId.UniqueProcess], eax
第二步
如果bInheritHandle为0则最后计算后还是0,如果为其他数则置为1,并且填入ObjectAttributes中
text:0DCE917B mov eax, [ebp+bInheritHandle]
.text:0DCE917E push esi
.text:0DCE917F xor esi, esi
.text:0DCE9181 neg eax
.text:0DCE9183 sbb eax, eax
.text:0DCE9185 and eax, 2
.text:0DCE9188 mov [ebp+ObjectAttributes.Attributes], eax
最后一步
将两个结构体传入,再传入一个权限,最后还有一个OUT参数ProcessHandle,esi在上面已经置为在下面就当作参
数传入,mov [ebp+ObjectAttributes.Length], 18h则是把sizeof(ObjectAttributes)传入
.text:0DCE918B lea eax, [ebp+ClientId]
.text:0DCE918E push eax ; ClientId
.text:0DCE918F lea eax, [ebp+ObjectAttributes]
.text:0DCE9192 push eax ; ObjectAttributes
.text:0DCE9193 push [ebp+dwDesiredAccess] ; DesiredAccess
.text:0DCE9196 lea eax, [ebp+dwProcessId]
.text:0DCE9199 push eax ; ProcessHandle
.text:0DCE919A mov [ebp+ClientId.UniqueThread], esi
.text:0DCE919D mov [ebp+ObjectAttributes.Length], 18h
.text:0DCE91A4 mov [ebp+ObjectAttributes.RootDirectory], esi
.text:0DCE91A7 mov [ebp+ObjectAttributes.ObjectName], esi
.text:0DCE91AA mov [ebp+ObjectAttributes.SecurityDescriptor], esi
.text:0DCE91AD mov [ebp+ObjectAttributes.SecurityQualityOfService], esi
最后是测试的代码
#include <Windows.h>
#include <winternl.h>
#include <stdio.h>
int main() {
typedef NTSTATUS(__stdcall
* NtOpenProcess)(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, CLIENT_ID* ClientId);
HMODULE hNtdll = LoadLibraryA("ntdll.dll");
if (!hNtdll) {
printf("LoadLibraryA\n");
return 0;
}
NtOpenProcess ZwOpenProcess = (NtOpenProcess)GetProcAddress(hNtdll, "ZwOpenProcess");
if (!ZwOpenProcess) {
printf("open failed\n");
return 0;
}
OBJECT_ATTRIBUTES obj = { 0 };
obj.Length = sizeof(OBJECT_ATTRIBUTES);
CLIENT_ID client = { 0 };
client.UniqueProcess = 22036;
HANDLE OUT process = 0;
NTSTATUS status = ZwOpenProcess(&process, PROCESS_ALL_ACCESS,&obj,&client);
printf("%d\n", process);
}