返回顶部
扶摇直上九万里,展翅高飞岂可待。

系统调用

持续更新...

分析OpenProcess函数

我们在三环写一个OpenProcess来跟踪调试一下

#include <windows.h>

int main()
{
	__asm {
		mov eax, 0x100;
	}
	OpenProcess(NULL, NULL, NULL);
	return 0;
}

这里的mov eax, 0x100;是为了让我们快速定位,直接od附加搜索指令即可追踪到当前点。然后我们来看一下OpenProcess是怎么调用的。

这里首先走到了kernel32.OpenProcess,然后步入继续跟踪

接下来到了KernelBase.OpenProcess

继续走进去,发现到了ntdll.NtOpenProcess

然后call了一个0x7FFE0300

接着就是sysenter的快速调用指令,从这里执行后返回直接到了kernelbase

比如我们的ReadProcessMemory,他也是这么走下来的。

随着迭代式开发越来越迅速,在kernel32中实现的函数功能已经满足不了了。
我们老的Xp系统是没有KernelBase的,到了Win7就有了KernelBase了,在XP下走的是Kernel32,如果升级了Win7,那么之前xp下的程序还是需要可以正常使用的。
但是Win7做了很多的改造,所以还是调用Kernel32,但是他不去实现很多功能了,而是直接跳到KernelBase。
举个例子:
比如在XP下的OpenProcess有三个参数,升级了Win7之后有四个参数,如果修改了Kernel32,那么原来XP的在Win7上是不是就不兼容了
因为不能修改,所以就做个跳板,jmp kernelbase,增加一个默认参数。这样win7也能走,xp也不会有问题。

我们用IDA分析一下win7 32位的kernel32

可以看到这里只有一个jmp
我们去导入表看一下

这个东西只是一个跳板

本质上来说他什么事情都没有干

所以根据刚才的分析,我们是应该去看一下kernelbase的。

在KernelBase中依然可以看到是三个参数。
我们来看一下他在干什么


那么里面的ClientId是什么呢?我们去结构体窗口看一下

如果是进程就填到UniqueProcess,如果是线程就填到UniqueThread
下面还有一个ObjectAttributes,由于我们打开进程是通过进程ID打开的,不是通过名字,所以这个结构的初始化全都是0。
再接着往下就调用了NtOpenProcess就变成了四个参数,其实这个KernelBase.OpenProcess本质上就是把参数整理了一下,填充了一下额外参数去调用NtOpenProcess,然后判断一下返回值是不是0,经过判断,如果小于0就跳转到GetLastError

将内核错误码转换到三环错误码。

我们去ntdll中找NtOpenProcess

这里发现没有找到,我们去看导出表

发现导出的名字和真正的名字是不一样的,真正的名字叫ZwOpenProcess,也就是一个函数导出了两个名字
我们看到了一行这样的汇编指令:mov edx, 7FFE0300h,然后下面就call了这个地址,这是什么意思呢?这是个结构,所有的进程都有这个地址。这个结构所有进程共享。
windbg:dt _KUSER_SHARED_DATA

nt!_KUSER_SHARED_DATA
   +0x000 TickCountLowDeprecated : Uint4B
   +0x004 TickCountMultiplier : Uint4B
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   +0x020 TimeZoneBias     : _KSYSTEM_TIME
   +0x02c ImageNumberLow   : Uint2B
   +0x02e ImageNumberHigh  : Uint2B
   +0x030 NtSystemRoot     : [260] Wchar
   +0x238 MaxStackTraceDepth : Uint4B
   +0x23c CryptoExponent   : Uint4B
   +0x240 TimeZoneId       : Uint4B
   +0x244 LargePageMinimum : Uint4B
   +0x248 Reserved2        : [7] Uint4B
   +0x264 NtProductType    : _NT_PRODUCT_TYPE
   +0x268 ProductTypeIsValid : UChar
   +0x26c NtMajorVersion   : Uint4B
   +0x270 NtMinorVersion   : Uint4B
   +0x274 ProcessorFeatures : [64] UChar
   +0x2b4 Reserved1        : Uint4B
   +0x2b8 Reserved3        : Uint4B
   +0x2bc TimeSlip         : Uint4B
   +0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE
   +0x2c4 AltArchitecturePad : [1] Uint4B
   +0x2c8 SystemExpirationDate : _LARGE_INTEGER
   +0x2d0 SuiteMask        : Uint4B
   +0x2d4 KdDebuggerEnabled : UChar
   +0x2d5 NXSupportPolicy  : UChar
   +0x2d8 ActiveConsoleId  : Uint4B
   +0x2dc DismountCount    : Uint4B
   +0x2e0 ComPlusPackage   : Uint4B
   +0x2e4 LastSystemRITEventTickCount : Uint4B
   +0x2e8 NumberOfPhysicalPages : Uint4B
   +0x2ec SafeBootMode     : UChar
   +0x2ed TscQpcData       : UChar
   +0x2ed TscQpcEnabled    : Pos 0, 1 Bit
   +0x2ed TscQpcSpareFlag  : Pos 1, 1 Bit
   +0x2ed TscQpcShift      : Pos 2, 6 Bits
   +0x2ee TscQpcPad        : [2] UChar
   +0x2f0 SharedDataFlags  : Uint4B
   +0x2f0 DbgErrorPortPresent : Pos 0, 1 Bit
   +0x2f0 DbgElevationEnabled : Pos 1, 1 Bit
   +0x2f0 DbgVirtEnabled   : Pos 2, 1 Bit
   +0x2f0 DbgInstallerDetectEnabled : Pos 3, 1 Bit
   +0x2f0 DbgSystemDllRelocated : Pos 4, 1 Bit
   +0x2f0 DbgDynProcessorEnabled : Pos 5, 1 Bit
   +0x2f0 DbgSEHValidationEnabled : Pos 6, 1 Bit
   +0x2f0 SpareBits        : Pos 7, 25 Bits
   +0x2f4 DataFlagsPad     : [1] Uint4B
   +0x2f8 TestRetInstruction : Uint8B
   +0x300 SystemCall       : Uint4B
   +0x304 SystemCallReturn : Uint4B
   +0x308 SystemCallPad    : [3] Uint8B
   +0x320 TickCount        : _KSYSTEM_TIME
   +0x320 TickCountQuad    : Uint8B
   +0x320 ReservedTickCountOverlay : [3] Uint4B
   +0x32c TickCountPad     : [1] Uint4B
   +0x330 Cookie           : Uint4B
   +0x334 CookiePad        : [1] Uint4B
   +0x338 ConsoleSessionForegroundProcessId : Int8B
   +0x340 Wow64SharedInformation : [16] Uint4B
   +0x380 UserModeGlobalLogger : [16] Uint2B
   +0x3a0 ImageFileExecutionOptions : Uint4B
   +0x3a4 LangGenerationCount : Uint4B
   +0x3a8 Reserved5        : Uint8B
   +0x3b0 InterruptTimeBias : Uint8B
   +0x3b8 TscQpcBias       : Uint8B
   +0x3c0 ActiveProcessorCount : Uint4B
   +0x3c4 ActiveGroupCount : Uint2B
   +0x3c6 Reserved4        : Uint2B
   +0x3c8 AitSamplingValue : Uint4B
   +0x3cc AppCompatFlag    : Uint4B
   +0x3d0 SystemDllNativeRelocation : Uint8B
   +0x3d8 SystemDllWowRelocation : Uint4B
   +0x3dc XStatePad        : [1] Uint4B
   +0x3e0 XState           : _XSTATE_CONFIGURATION 

这个结构不是300这个值,而是:7FFE0000,所以我们来:dt _KUSER_SHARED_DATA 7FFE0000

nt!_KUSER_SHARED_DATA
   +0x000 TickCountLowDeprecated : 0
   +0x004 TickCountMultiplier : 0xf99a027
   +0x008 InterruptTime    : _KSYSTEM_TIME
   +0x014 SystemTime       : _KSYSTEM_TIME
   +0x020 TimeZoneBias     : _KSYSTEM_TIME
   +0x02c ImageNumberLow   : 0x14c
   +0x02e ImageNumberHigh  : 0x14c
   +0x030 NtSystemRoot     : [260]  "C:\Windows"
   +0x238 MaxStackTraceDepth : 0
   +0x23c CryptoExponent   : 0
   +0x240 TimeZoneId       : 0
   +0x244 LargePageMinimum : 0x200000
   +0x248 Reserved2        : [7] 0
   +0x264 NtProductType    : 1 ( NtProductWinNt )
   +0x268 ProductTypeIsValid : 0x1 ''
   +0x26c NtMajorVersion   : 6
   +0x270 NtMinorVersion   : 1
   +0x274 ProcessorFeatures : [64]  ""
   +0x2b4 Reserved1        : 0x7ffeffff
   +0x2b8 Reserved3        : 0x80000000
   +0x2bc TimeSlip         : 0
   +0x2c0 AlternativeArchitecture : 0 ( StandardDesign )
   +0x2c4 AltArchitecturePad : [1] 0
   +0x2c8 SystemExpirationDate : _LARGE_INTEGER 0x0
   +0x2d0 SuiteMask        : 0x110
   +0x2d4 KdDebuggerEnabled : 0x3 ''
   +0x2d5 NXSupportPolicy  : 0x2 ''
   +0x2d8 ActiveConsoleId  : 1
   +0x2dc DismountCount    : 0
   +0x2e0 ComPlusPackage   : 0xffffffff
   +0x2e4 LastSystemRITEventTickCount : 0x53db7e4
   +0x2e8 NumberOfPhysicalPages : 0x7ff7e
   +0x2ec SafeBootMode     : 0 ''
   +0x2ed TscQpcData       : 0 ''
   +0x2ed TscQpcEnabled    : 0y0
   +0x2ed TscQpcSpareFlag  : 0y0
   +0x2ed TscQpcShift      : 0y000000 (0)
   +0x2ee TscQpcPad        : [2]  ""
   +0x2f0 SharedDataFlags  : 0xe
   +0x2f0 DbgErrorPortPresent : 0y0
   +0x2f0 DbgElevationEnabled : 0y1
   +0x2f0 DbgVirtEnabled   : 0y1
   +0x2f0 DbgInstallerDetectEnabled : 0y1
   +0x2f0 DbgSystemDllRelocated : 0y0
   +0x2f0 DbgDynProcessorEnabled : 0y0
   +0x2f0 DbgSEHValidationEnabled : 0y0
   +0x2f0 SpareBits        : 0y0000000000000000000000000 (0)
   +0x2f4 DataFlagsPad     : [1] 0
   +0x2f8 TestRetInstruction : 0xc3
   +0x300 SystemCall       : 0x772570b0
   +0x304 SystemCallReturn : 0x772570b4
   +0x308 SystemCallPad    : [3] 0
   +0x320 TickCount        : _KSYSTEM_TIME
   +0x320 TickCountQuad    : 0x574d81
   +0x320 ReservedTickCountOverlay : [3] 0x574d81
   +0x32c TickCountPad     : [1] 0
   +0x330 Cookie           : 0x89ed980a
   +0x334 CookiePad        : [1] 0
   +0x338 ConsoleSessionForegroundProcessId : 0n3064
   +0x340 Wow64SharedInformation : [16] 0
   +0x380 UserModeGlobalLogger : [16] 0
   +0x3a0 ImageFileExecutionOptions : 0
   +0x3a4 LangGenerationCount : 1
   +0x3a8 Reserved5        : 0
   +0x3b0 InterruptTimeBias : 0
   +0x3b8 TscQpcBias       : 0
   +0x3c0 ActiveProcessorCount : 4
   +0x3c4 ActiveGroupCount : 1
   +0x3c6 Reserved4        : 0
   +0x3c8 AitSamplingValue : 0
   +0x3cc AppCompatFlag    : 1
   +0x3d0 SystemDllNativeRelocation : 0xff350000
   +0x3d8 SystemDllWowRelocation : 0
   +0x3dc XStatePad        : [1] 0
   +0x3e0 XState           : _XSTATE_CONFIGURATION

我们在这个结构偏移300的位置找到了这个成员: +0x300 SystemCall : 0x772570b0,这是个函数叫SystemCall。

这个结构是所有进程共享的,也就是共享同一份物理地址,我们去看看内核的这个结构体,地址是:FFDF0000

可以看到和三环是同一个地址

但是我们在直接用u 0x772570b0看不到这个内存,因为system进程没有模块,看不到,所以我们去附加一个进程去看

我们去reload一下符号再看

也就是说这里调用的是KiFastSystemCall,
我们再看一下这个地方:mov eax, 0BEh

这个BE是服务号

我们去ntdll看一下这个函数

这里把esp给了edx,这个esp是什么?
从上一个函数call过来的时候,esp就是上个函数的返回地址,然后进行sysenter,他带参数进内核了吗?这里看起来好像是没带参数。
这里就会有疑问:

  1. 怎么带参数进内核?
  2. 参数有多少个?
  3. 他需要如何返回?
  4. sysenter如何进内核?

自己实现OpenProcess

#include "stdafx.h"
#include <iostream>
#include <windows.h>

typedef struct _CLIENT_ID
{
	DWORD UniqueProcess;
	DWORD UniqueThread;
}CLIENT_ID, *PCLIENT_ID;

typedef struct _UNICODE_STRING {
	USHORT Length;
	USHORT MaximumLength;
	PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES {
	ULONG           Length;
	HANDLE          RootDirectory;
	PUNICODE_STRING ObjectName;
	ULONG           Attributes;
	PVOID           SecurityDescriptor;
	PVOID           SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

NTSTATUS __stdcall MyZwOpenProcess(
	PHANDLE            ProcessHandle,
	ACCESS_MASK        DesiredAccess,
	POBJECT_ATTRIBUTES ObjectAttributes,
	PCLIENT_ID         ClientId
);

HANDLE MyOpenProcess(
	DWORD dwDesiredAccess,
	BOOL  bInheritHandle,
	DWORD dwProcessId
)
{
	CLIENT_ID ClientID;
	OBJECT_ATTRIBUTES ObjectAttributes;
	ClientID.UniqueProcess = dwProcessId;

	if (bInheritHandle == TRUE)
	{
		ObjectAttributes.Attributes = 2;
	}
	else
	{
		ObjectAttributes.Attributes = 0;
	}
	ClientID.UniqueThread = 0;
	ObjectAttributes.Length = 0x18;
	ObjectAttributes.RootDirectory = 0;
	ObjectAttributes.ObjectName = 0;
	ObjectAttributes.SecurityDescriptor = 0;
	ObjectAttributes.SecurityQualityOfService = 0;

	DWORD dwRet = MyZwOpenProcess((PHANDLE)&dwProcessId, dwDesiredAccess,
		&ObjectAttributes, &ClientID);

	if (dwRet < 0)
	{
		//BaseSetLastNTError(dwRet);//设置错误码
		return 0;
	}
	return (HANDLE)dwProcessId;//这里是返回句柄
}

__declspec(naked) NTSTATUS __stdcall MyZwOpenProcess(
	PHANDLE            ProcessHandle,
	ACCESS_MASK        DesiredAccess,
	POBJECT_ATTRIBUTES ObjectAttributes,
	PCLIENT_ID         ClientId
)
{
	__asm
	{
		mov     eax, 0BEh
		mov     edx, 7FFE0300h
		call    dword ptr[edx]
		ret 10h
	}
}

int main()
{
	HANDLE hProcess = MyOpenProcess(PROCESS_ALL_ACCESS, FALSE, 3740);
	if (!hProcess)
	{
		return 0;
	}
	printf("ProcessHandle is:%x\r\n ", hProcess);
	getchar();
}
posted @ 2021-07-18 17:01  唯君画馨  阅读(129)  评论(0编辑  收藏  举报