Friday, September 27, 2013

Intel Assembly Addressing Mode

Global variable is defined in a .DATA section. DB, DW and DD declare variables of 1, 2 and 4 bytes in length.

.DATA
var1 DB 64 ; initialize variable with value 64
var2 DB ? ; uninintialized variable
var3 DD 1, 2, 3 ; declare 3 doubleword variables and initialized to value 1, 2 and 3

arr1 DD 100 DUP (0) ; declare and array of 100 entries. Initialized to 0
str1 DB 'hello',0 ; declare a null terminating string of 6-bytes long

mov eax, [ebx] ; move the eax content to 4 byte pointed to by address in ebx
mov [eax], ebx ; move the ebx content to the address stored in eax

Somtimes, the size of data during manipulation is ambiguous e.g. when immediate value is used

mov BYTE PTR [ebx], 2 ; move 2 into a single byte at address stored in ebx
mov WORD PTR [ebx], 2
mov DWORD PTR [ebx], 2

Windows System Call Flow

(1) user mode program call BOOL WINAPI WriteFile()
(2) control transfer to Writefile() routine implemented by kernel32.dll
(3) kernal32.dll calls ZwWriteFile() in ntdll.dll (user mode)
(4) ZwWriteFile() calls KiFastSystemCall() in ntdll.dll which execute the SYSENTER instruction to transit to kernel mode
(5) SYSENTER transfers control to KiFastCallEntry() in ntoskrnl.exe (Executive) via the MSR_CS and MSR_EIP settings
(6) KiFastCallEntry() calls KiSystemService() in ntoskrnl.exe
(7) KiSystemService() dispatch 0x163 which is NtWriteFile() in ntoskrnl.exe

Windows API

With the exception of NtGetTickCount() and NtCurrentTeb(), each Nt* function has a matching Zw* function. To the user mode program, calling Nt* function eventually ends up calling Zw* function. In kernel mode, calling Zw* module will follow a formal transition path via KiSystemService() routine. Calling Nt* will not.

Windows user mode components

Environmental subsystem provide API for specific applications to run. NT4 supports 5 environmental subsystems:

Win32 or later Windows subsystem
Windows on Windows (WOW) for 16-bit Windows applications e.g. Win 3.1
NT Virtual DOS machine (NTVDM) for DOS applications
OS/2
POSIX and later Services for UNIX (SFU) or Subsystem for UNIX based application (SUA)

Windows subsystem consists of 3 basic components:
(1) csrss.exe - Client Server Runtime Subsystem (user mode) It plays a role in managing processes and threads. It supports command line interface.
(2) win32k.sys - Kernel mode device driver
(3) User mode DLL that implement the subsystem's API, e.g. kernel32.dll, gdi.dll, shell32.dll, rpcrt4.dll, advapi32.dll, user32.dll etc.

When a Windows API need to access services in executives, it goes through ntdll.dll which reroutes code to ntoskrnl.exe

Service Control Manager (SCM) is implemented by service.exe in system32 directory. SCM launches and manages user mode service which is just a user-mode application runs in background.

Windows kernel mode components

The core is implemented in ntoskrnl.exe. This executable implements its functionalist in 2 layers - executive and kernel.

The executive implements the system call interface and major OS components such as I/O manager, memory manager, process and thread manager). Kernel mode device drives is in layer between the executive's I/O manager and HAL. The kernel implements low level routines (e.g. synchronization, thread scheduling, interrupt handling) that executive uses to provide high level services.

There are several version of kernel executives

  • ntoskrnl.exe - uniprocessor without PAE 
  • ntkrnlpa.exe - uniprocessor with PAE 
  • ntkrnlmp.exe - multiprocessor without PAE 
  • ntkrpamp.exe - multiprocessor with PAE 


win32k.sys is a kernel mode driver tat implement both user and graphic device interface (GDI) services. GDI is pushed to run in kernel mode for speed.

User to Kernel Model Switching

In real mode, MSDOS uses the Interrupt Vector Table (IVT) to expose system services runs in supervisor mode. Applications call INT 0x21 with a function code placed in AH.

Windows use IDT (Interrupt Descriptor Table). In a multiprocessor environment, each processor has its own IDTR register. Windows check the processor it's running on during start up to determine its system call invocation mechanism.

For Pentium II, INT 0x2E instruction and IDT are used to implement system call mechanism. For later IA32 processors, Windows uses SYSENTER instruction to jump to kernel space. IDT is only used to handle hardware exceptions IDT contain up to 256 8-byte descriptors. To dump the descriptor registers content, use rM 0x100 command in debugger. idtr shows the base address and idtl shows the limit (length). To format idt content, use debugger command !idt -a

In Windows, most of the entries point to KiUnexpectedInterrupt routines, which in turn jump to nt!KiEndUnexpectedRange routine. Even those later processor uses SYSENTER, the IDT entry at 0x2E also implement the functionality by pointing to nt!KiSystemService (System Service Dispatcher). It uses information passed on from application to invoke the native API routine. Nowadays, switching from user to kernel mode is done via the SYSENTER instruction. 3 64-bit machine specific registers (MSR) is used to identify the target to jump to, the location of kernel-level stack (in case the user mode stack needs to copy over).

  • IA32_SYSENTER_CS (0x174 register address) - kernel mode code code and stack segment 
  • IA32_SYSENTER_ESP (0x175) - stack pointer in the stack segment 
  • IA32_SYSENTER_ISP (0x176) - first instruction to execute These registers are manipulated using the RDMSR and WRMSR instructions. 

SYSENTER_CS usually points to a Ring 0 code segment that spans the entire address range. Thus SYSENTER_EIP is a full 32-bit linear address in a kernel module called KiFastCallEntry. The module will eventually jump to KiSystemService.

Like INT 0x2E,the service number needs to stow in EAX before calling SYSENTER. KiFastCallEntry involve KiSystemService to dispatch the target Nt funciton. The dispatch is achieved via a service number to index a lookup table. The system service number is 32-bit. Bit 0 to 11 represents the service number to be invoked. Bit 12-13 specify 1 of 4 possible service descriptor tables. In fact, only 2 of the service tables are used. If the table number is 0x00, the KeServiceDescriptorTable is used. If the table number is 0x01, the KeSErviceDescriptorTableShadow is to be used. The KeServiceDescriptorTable is exported by ntoskrnl.exe and KeServiceDescriptorTableShadow is not exposed and used internally in the executive.

The 2 descriptor tables contain a structure called System Service Table (SST):

  • serviceTable points to an array of linear addresses which are entry points of routines. The array is called SSDT System Service Dispatch Table and contains 391 elements. SSDT is similar to IVT. 
  • nEntries specifies the number of elements in the SSDT 
  • argumentTable is a pointer to an array of bytes called SSPT (System Service Parameter Table). Each byte represent the number of bytes allocated for function arguments for the corresponding SSDT routine. 

KeServiceDescriptorTable contain one SST. KeServiceDescriptorTableShadow contains 2 SST. The first one is same as the one contains in KeServiceDescriptorTable. The second one points to the SSDT for the GDI routines implemented by win32k.sys and contain 772 entries.

HAL and bootvid

Hardware Abstraction Layer (HAL) insulates the OS from hardware by wrapping machine-specific details with an API that is implemented by HAL.DLL. Kernel mode device drivers invoke HAL routines rather than interface to hardware directly.

HAL implementation depends on hardware on which Windows runs on. HAL is located in system32 directory:

  • hal.dll - standard PC 
  • halacpi.dll - hardware with advanced configuration and power interface (ACPI) 
  • halmacpi.dll - hardware uses multiple processors Sitting with HAL, 


bootvid.dll offers primitive VGA graphic support during boot phase. It can be controlled via the /noguiboot option in boot.ini.