Windows内核情景分析学习笔记(二)

X86系统调用上

本文环境 WinXP SP2
在Windows操作系统中,应用层程序进行系统调用一般有两种途径,一种是通过int 0x2e的方式,一种是通过sysenter指令即快速调用进入系统调用。接下来将以ReadProcessMemory这个函数为例来介绍在X86下是如何进行系统调用通过的。主要讲解通过快速调用的方式进行系统调用

这是位于kernel32.dll中的ReadProcessMemory
			mov     edi, edi
			push    ebp
			mov     ebp, esp
			lea     eax, [ebp+nSize]
			push    eax             ; 以下几行功能为将提供的参数进行压栈以作为NtReadVirtualMemory这个函数的参数
			push    [ebp+nSize]     ; 
			push    [ebp+lpBuffer]  ; 
			push    [ebp+lpBaseAddress] ; 
			push    [ebp+hProcess]  ; 
			call    ds:__imp__NtReadVirtualMemory@20 ; 调用位于ntdll.dll中的NtReadVirtualMemory
			mov     ecx, [ebp+lpNumberOfBytesRead]
			test    ecx, ecx
			jnz     short loc_7C8021F9
loc_7C8021EE:
			test    eax, eax
			jl      short loc_7C802200
			xor     eax, eax
			inc     eax
loc_7C8021F5:
			pop     ebp
			retn    14h
loc_7C8021F9:                           
            mov     edx, [ebp+nSize]
            mov     [ecx], edx
            jmp     short loc_7C8021EE
loc_7C802200:                           
            push    eax             ; 
            call    _BaseSetLastNTError@4 ; 
            xor     eax, eax
            jmp     short loc_7C8021F5
这是位于ntdll.dll中的NtReadVirtualMemory也可以认为是ZwReadVirtualMemory,在应用层中Nt函数跟Zw函数是同一个函数
			mov     eax, 0BAh       ;用eax存储函数的调用号(这个需要了解SSDT表才知道用处)
			mov     edx, 7FFE0300h;
			call    dword ptr [edx];调用系统预先设置好的进入函数
			retn    14h

在内存中存在KUSER_SHARED_DATA这样结构的区域,位于虚拟地址的0x7FFE0000和0xffdf0000,这两个虚拟地址都指向同一个物理地址,但区别在于位于内核的虚拟地址页拥有可读可写的权限而应用层只有读权限。
回到正题,该结构如下所示

nt!_KUSER_SHARED_DATA
+0x000 TickCountLow : 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] Uint2B
+0x238 MaxStackTraceDepth : Uint4B
+0x23c CryptoExponent : Uint4B
+0x240 TimeZoneId : Uint4B
+0x244 Reserved2 : [8] 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
+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
+0x2f0 TraceLogging : Uint4B
+0x2f8 TestRetInstruction : Uint8B
+0x300 SystemCall : Uint4B
+0x304 SystemCallReturn : Uint4B
+0x308 SystemCallPad : [3] Uint8B
+0x320 TickCount : _KSYSTEM_TIME
+0x320 TickCountQuad : Uint8B
+0x330 Cookie : Uint4B

可以看出0x7FFE0300h这个地址上存储的为 SystemCall 该值在系统初始化时便会赋值,如果CPU支持快速调用这种方式则会被赋值KiFastSystemCall()这个函数地址,不支持则赋值为KiIntSystemCall()这个函数地址。

下面便是支持系统调用的KiFastSystemCall
			mov     edx,esp    ;使edx指向此时的栈顶
			sysenter		   ;

下面我们了解下sysenter这个指令做了什么
通过inter白皮书我们可以知道

这里是引用

该指令会做如下操作
1:IA32_SYSENTER_CS MSR寄存器中的值放入CS且加8后放入SS
2:IA32_SYSENTER_ESP MSR寄存器中的值放入ESP
3:IA32_SYSENTER_EIP MSR寄存器中的值放入EIP
4:将当前的权限设置为内核权限
5:清空ELAGS寄存器中的VM标志位
6:开始指向EIP所指向的代码

以上便为3环进入0环的全过程 如果存在错误,请务必私信或者留言,万分感谢

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值