Sample Available here: [Sample fopen.exe]
Debug symbols Available here: [fopen.pdb]
fopen.exe - simply application in C utilazing fopen C function
ucrtbase.dll - C runtime library
ntoskrnl.exe (KERNEL Executive Subsystem part)
Execution flow:
fopen.exe calling fopen -> ucrtbase.dll;fopen -> ucrtbase.dll;_sopen_s -> ucrtbase.dll;_sopen_dispatch -> ucrtbase.dll;_sopen_nolock -> ucrtbase.dll;_wsopen_nolock -> kernel32.dll;CreateFileW -> kernelbase.dll;CreateFileW -> ntdll.dll;NtCreateFile -> ntdll.dll;KiFastSystemCall(0x52 - NtCreateFile) -> KERNEL Executive Subsystem (Part2)
Video: [Tracing C function fopen [Part1] - IDA Free User-Mode Walk-Through tracing to NTApi]
Tracing C function fopen [Part2] - Windbg Kernel Debugging - Walk-Through User-Mode to Kernel Executive Subsytem:
Performing Remote live Kernel debugging with Windbg Preview.
Attaching the Kernel debugger to process which has not started yet.
Staying in specified process context from User-Mode to Kernel-Mode.
Tracing Process.
Explaining what is System Service Number.
Investigating System Service Dispatch Table (SSDT).
Applying kernel function types in IDA.
Investigating interesting structures in Kernel.
Digging deeper.
Prepare VM for Kernel debugging (32bit win7 to avoid wow64)
Disable ASLR in fopen.exe (NT Headers -> Optional Header -> DLL Characteristics -> DLL can move (Disable)
If symbols needed for fopen.exe - change .pdb path in debug directory of fopen.exe to point to your HOST fopen.pdb path
Prepare windbg preview for kernel debugging
Prepare IDA - ntoskrnl.exe (KERNEL Executive Subsystem part)
Execution flow EXAMPLE:
fopen.exe calling fopen -> ucrtbase.dll;fopen -> ucrtbase.dll;_sopen_s -> ucrtbase.dll;_sopen_dispatch -> ucrtbase.dll;_sopen_nolock -> ucrtbase.dll;_wsopen_nolock -> kernel32.dll;CreateFileW -> kernelbase.dll;CreateFileW -> ntdll.dll;NtCreateFile -> ntdll.dll;KiFastSystemCall(0x42 - NtCreateFile) -> sysenter(x86) -> nt!IopCreateFile -> nt!ObOpenObjectByName -> ...........
-
Attach and break
!process -1 0 (Check the current process context)
.reload (load symbols - if you can not see resolved symbols)
!gflag +ksl (setting the gflags to allow sxe to report User-Mode module load events under kernel debugger)
sxe ld fopen.exe (cause kernel debugger break upon process load of fopen.exe)
g (continue) -
Run fopen.exe application and hit the breakpoint
!gflag -ksl (reset gflags)
.process (set process fopen.exe (currently on breakpoint in fopen.exe process) as implicit process to be in its context in windbg)
bp 00401000 (breakpoint on User-Mode address of fopen.exe main function - ASLR disabled (no code there yet))
g (continue to hit the set User-Mode breakpoint)
.reload /user or .reload (loading User-Mode modules symbols or all symbols)
x ntdll!NtCreateFile (Get the address of ntdll.dll;NtCreateFile function)
u address (u 77f050f0) (Show Diassembly of address)
bp address (ntdll!NtCreateFile) (bp 77f050f0) or bu ntdll!NtCreateFile (Breakpoint on ntdll.dll;NtCreateFile function entry in User-Mode)
!process 0 0 fopen.exe (Get the address of EPROCESS structure of fopen.exe process)
g (Continue to hit the breakpoint on ntdll.dll;NtCreateFile - User-Mode)
Check the value going to eax (0x42) in ntdll!NtCreateFile - System Service Number.
syscall(x64)/sysenter(x86) - Causes transition to the kernel into the System Service Dispatcher routine, which is responsible for dispatching to the real system call implementation within the Executive subsystem (ntoskrnl.exe).
EAX register must be used as a lookup index into the System Service Dispatch Table (SSDT), where each system service number (index) should point to the actual routine (NtCreateFile = 0x42 in this example).
SSDT is available in the kernel debugger in the nt!KiServiceTable.
- SSDT and System Service Number
dd nt!KiServiceTable (Show SSDT)
dd nt!KiServiceTable+42*4 L1 ("82a5b882" Find NtCreateFile routine in SSDT - we need to sign-extend the VALUE to 64 bit - ffffffff82a5b882)
u ffffffff82a5b882 (Show Diassembly of address -> we get the actual NtCreateFile implementation in ntoskrnl.exe)
bu nt!NtCreateFile (Set unresolved breakpoint on NtCreateFile in ntoskrnl.exe - Kernel Executive Subsytem)
g
bc * (Clear all Breakpoints)
pc (Step to next call)
TIP - Compare where you are in windbg to IDA statically - better overview
TIP - Apply some function types not recognized in IDA
Example:
pc - step to next call (nt!IopCreateFile) and step in
pc - step to next call (nt!ObOpenObjectByName) (can see filename and object type)
etc...
.reload (Load symbols - if you can not see resolved symbols, make sure to have properly set Default Symbol Path in WINDBG)
bp nt!PspInsertProcess (Breakpoint on newly created process)
dt nt!_EPROCESS @eax ImageFileName (on the nt!PspInsertProcess breakpoint - Check the name of created process)
!process 0 0 fopen.exe (Get the EPROCESS structure address of fopen.exe process)
.process /r /p 85584030 (Switch process context on specified process via EPROCESS structure address)
.reload /user (Reload user debug symbols)
lmu (Check User-Mode loaded modules and their debug symbols)
lm (Check all loaded modules (User-Mode and Kernel-Mode) and their debug symbols)
x nt!NT* (Find some NT* routine)
bu nt!NtCreateFile (Breakpoint on nt!NtCreateFile in kernel, all processes will break on it)
g (Continue)
!process -1 0 (Check current process context (-1 current process only) - whenever you are not sure)
k (Check call stack - whenever you are not sure)
dp nt!mmhighestuseraddress L1 (Get max User-Mode address range)
dd esp (List stack values dwords - good before funcion call to see arguments)
dt nt!*obj* (Get all available structures containing "obj" in name)
dt ntkrnlmp!_OBJECT_TYPE 852063f8 (Get object type structure)
dt nt!_UNICODE_STRING 852063f8+0x8
dt ntkrnlmp!_OBJECT_ATTRIBUTES 0012fcdc (Get object attributes structure)
Creating logfile for tracing:
.logopen C:\Users\DFIR_GUY\Desktop\xxx.log (Creating\Opening logfile)
.logfile (Check if logfile opened)
.logclose (Closing logfile)
Tracing and stepping:
wt startaddress endaddress (Watch and Trace)
pc (Step to next call)
tc (Trace to next call)
bp/bu/ba /p EProcess or /t EThread -Only in Kernel-Mode !!!
Get NTApi function types - good resource is processhacker src code - you can search there NTApi function type easily.
Get Kernel API - good resource is ReactOS - It is open-source contaning useful information about types.
ProcessHacker SRC code: https://github.com/processhacker/processhacker
ReactOS Documentation: https://doxygen.reactos.org/index.html
NTSTATUS __stdcall IopCreateFile(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG Disposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength, CREATE_FILE_TYPE CreateFileType, PVOID ExtraCreateParameters, ULONG Options, ULONG Flags, PDEVICE_OBJECT DeviceObject)
int __stdcall ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PACCESS_STATE PassedAccessState, ACCESS_MASK DesiredAccess, PVOID ParseContext, PHANDLE Handle)