Windows7 x64系统调用分析

目录

  • 0x01 Syscall & Sysret
    •  与32位sysenter & int 2e的区别   
  • 0x02 KiSystemCall64
    •  构造TrapFrame
    •  _kthread->header->DebugActive.ActiveDR7|Instrumented
    •  user-mode scheduling(???这部分暂时还不明白)
    •  SSDT & ShadowSSDT API地址计算
    •  KiInitiateUserApc Apc分发
    •  InstrumentationCallback用户层回调

 


0x01 Syscall & Sysret

  • Syscall

Windows7 x64系统调用分析

Windows7 x64系统调用分析

Windows7 x64系统调用分析

Windows7 x64系统调用分析

Windows7 x64系统调用分析

 

Syscall

IF (CS.L ≠ 1 ) or (IA32_EFER.LMA ≠ 1) or (IA32_EFER.SCE ≠ 1) (* Not in 64-Bit Mode or SYSCALL/SYSRET not enabled in IA32_EFER *) THEN #UD; FI; RCX ← RIP; (* Will contain address of next instruction *) RIP ← IA32_LSTAR; R11 ← RFLAGS; RFLAGS ← RFLAGS AND NOT(IA32_FMASK); CS.Selector ← IA32_STAR[47:32] AND FFFCH (* Operating system provides CS; RPL forced to 0 *) (* Set rest of CS to a fixed value *) CS.Base ← 0; (* Flat segment *) CS.Limit ← FFFFFH; (* With 4-KByte granularity, implies a 4-GByte limit *) CS.Type ← 11; (* Execute/read code, accessed *) CS.S ← 1; CS.DPL ← 0; CS.P ← 1; CS.L ← 1; (* Entry is to 64-bit mode *) CS.D ← 0; (* Required if CS.L = 1 *) CS.G ← 1; (* 4-KByte granularity *) CPL ← 0;

  从上面的Syscall的伪代码可以看到,rcx储存的是下一条指令的地址,所以windows在Syscall之前会将rcx储存到r10中。r11中储存的是rflags。rip是从IA32_LSTAR中获取的,cs的选择子是从IA32_STAR[47:32] 读取的,但是cs的其他段属性并没有根据选择子在内存中进行读取,而是设置的固定值,因此OS有义务让段选择对应的段描述符与设置的固定值相对应。可以发现上面伪代码并没有进行堆栈切换,因此需要OS在系统调用例程中自己进行堆栈切换。

 

  • Sysret

IF (CS.L ≠ 1 ) or (IA32_EFER.LMA ≠ 1) or (IA32_EFER.SCE ≠ 1)
(* Not in 64-Bit Mode or SYSCALL/SYSRET not enabled in IA32_EFER *)
THEN #UD; FI;
IF (CPL ≠ 0) THEN #GP(0); FI;
IF (operand size is 64-bit)
THEN (* Return to 64-Bit Mode *)
IF (RCX is not canonical) THEN #GP(0);
RIP ← RCX;
ELSE (* Return to Compatibility Mode *)
RIP ← ECX;
FI;
RFLAGS ← (R11 & 3C7FD7H) | 2; (* Clear RF, VM, reserved bits; set bit 2 *)
IF (operand size is 64-bit)
THEN CS.Selector ← IA32_STAR[63:48]+16;
ELSE CS.Selector ← IA32_STAR[63:48];
FI;
CS.Selector ← CS.Selector OR 3; (* RPL forced to 3 *)
(* Set rest of CS to a fixed value *)
CS.Base ← 0; (* Flat segment *)
CS.Limit ← FFFFFH; (* With 4-KByte granularity, implies a 4-GByte limit *)
CS.Type ← 11; (* Execute/read code, accessed *)
CS.S ← 1;
CS.DPL ← 3;
CS.P ← 1;
IF (operand size is 64-bit)
THEN (* Return to 64-Bit Mode *)
CS.L ← 1; (* 64-bit code segment *)
CS.D ← 0; (* Required if CS.L = 1 *)
ELSE (* Return to Compatibility Mode *)
CS.L ← 0; (* Compatibility mode *)
CS.D ← 1; (* 32-bit code segment *)
FI;
CS.G ← 1; (* 4-KByte granularity *)
CPL ← 3;
SS.Selector ← (IA32_STAR[63:48]+8) OR 3; (* RPL forced to 3 *)
(* Set rest of SS to a fixed value *)
SS.Base ← 0; (* Flat segment *)
SS.Limit ← FFFFFH; (* With 4-KByte granularity, implies a 4-GByte limit *)
SS.Type ← 3; (* Read/write data, accessed *)
SS.S ← 1;
SS.DPL ← 3;
SS.P ← 1;
SS.B ← 1; (* 32-bit stack segment*)
SS.G ← 1; (* 4-KByte granularity *)

  SYSRET loads the CS and SS selectors with values derived from bits 63:48 of the IA32_STAR MSR. However, the CS and SS descriptor caches are not loaded from the descriptors (in GDT or LDT) referenced by those selectors. Instead, the descriptor caches are loaded with fixed values.

  • rip<-rcx
  • rflags<-(R11 & 3C7FD7H) | 2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Windows7 x64系统调用分析

上一篇:Windows包管理器


下一篇:centos7 修改引导顺序,默认引导windows,引导等待时间