Objective
See the Windows API layers on your own PC. You will find ntdll.dll, see which programs use it, call a real Win32 function yourself, translate error numbers, and (optionally) watch a program's file operations live in Process Monitor. You only look and call harmless functions. Nothing here changes a setting, injects code or hooks anything.
Time: 25–30 minutes
You need: A Windows PC. PowerShell and Command Prompt are enough. One free optional tool is named in Part 6.
What to Open
| Tool | How to open it |
|---|---|
| PowerShell | Press Win, type PowerShell, press Enter (normal, not admin) |
| Command Prompt | Press Win, type cmd, press Enter |
| Task Manager | Press Ctrl + Shift + Esc |
| Notepad | Press Win, type Notepad, press Enter (used in Part 6) |
Part 1: Find the Native API Layer
In Command Prompt:
dir C:\Windows\System32\ntdll.dll
dir C:\Windows\System32\kernel32.dll
dir C:\Windows\System32\kernelbase.dll
dir C:\Windows\System32\user32.dll
- Size of ntdll.dll: ________________
- Size of kernelbase.dll: ________________
- Date of ntdll.dll: ________________
Now ask PowerShell for the version:
(Get-Item C:\Windows\System32\ntdll.dll).VersionInfo.FileVersion- ntdll.dll version: ________________
Is
ntdll.dllbigger or smaller thankernelbase.dll? Section 3.5 said it is a thin layer.
Part 2: Who Uses These DLLs?
In Command Prompt:
tasklist /m ntdll.dll
- Roughly how many programs are listed? ________________
Now try the other layers:
tasklist /m kernel32.dll
tasklist /m user32.dll
tasklist /m gdi32.dll
- Are there programs that use
ntdll.dllbut notuser32.dll? (Hint: background services.) ________________
Also in PowerShell, look inside your own PowerShell process:
Get-Process -Id $PID | Select-Object -ExpandProperty Modules | Where-Object { $_.ModuleName -match "ntdll|kernel32|kernelbase|user32" } | Select-Object ModuleName, FileName- Which of the four modules did you find in PowerShell? ________________
(tasklist /m can be slow, and the exact output depends on your PC. Some protected programs may not list their modules.)
Part 3: Which Module Owns a Command?
PowerShell's Get-Command tells you where a command lives:
Get-Command Get-Process | Select-Object Name, Source
Get-Command notepad.exe | Select-Object Name, Source- What is the Source of
Get-Process? ________________ - What is the full path of
notepad.exe? ________________
Part 4: Call a Win32 Function Yourself (Safe)
This calls GetTickCount64 from kernel32.dll. It only reads the clock. Type both lines:
Add-Type -MemberDefinition '[DllImport("kernel32.dll")] public static extern ulong GetTickCount64();' -Name Native -Namespace Win32
[Win32.Native]::GetTickCount64()- Milliseconds since Windows started: ________________
- Convert to hours (divide by 3,600,000): ________________
Run the
Add-Typeline only once per PowerShell window. If you run it again you will see a "type already exists" message. That is harmless. Just run the second line again.
Compare with Windows' own idea of uptime:
(Get-Date) - (Get-CimInstance Win32_OperatingSystem).LastBootUpTime- Is that uptime close to your number from step 11? ________________
(If you use Fast Startup, "boot time" can look different from the tick count. That is normal.)
Optional: a harmless pop-up from user32.dll. This shows a message box through the Win32 window API:
Add-Type -MemberDefinition '[DllImport("user32.dll", CharSet=CharSet.Unicode)] public static extern int MessageBoxW(IntPtr h, string text, string caption, uint type);' -Name Msg -Namespace Win32
[Win32.Msg]::MessageBoxW([IntPtr]::Zero, "Hello from user32.dll", "API Lab", 0)Click OK. That one line travelled application → user32.dll → the window system in the kernel (Section 5.9).
Measure the cost of calls. Measure-Command times a piece of work:
Measure-Command { 1..100000 | ForEach-Object { [Win32.Native]::GetTickCount64() | Out-Null } }- TotalMilliseconds: ________________ (the exact figure depends on your PC)
Each loop passes through PowerShell, Win32 and sometimes the kernel. It shows that calls are cheap, but not free.
Part 5: Translate Error Numbers (Section 2.6)
In Command Prompt:
net helpmsg 2
net helpmsg 3
net helpmsg 5
net helpmsg 32
net helpmsg 87
- Write what each number means: ________________
Now trigger a real error safely, and read it. In PowerShell:
Get-Content C:\this-file-does-not-exist.txt- What message do you get? Which of the five numbers above does it match? ________________
Part 6 (Optional): Watch the Calls Live with Process Monitor
Process Monitor is a free tool from Microsoft Sysinternals. It is not part of Windows, so download it only from the official Microsoft Sysinternals site (search "Sysinternals Process Monitor"). It shows each file, registry and process operation a program asks the kernel to do. It only watches. It changes nothing.
- Start Process Monitor (it asks for administrator permission, because it needs to watch the kernel).
- Process Monitor starts capturing at once. Press
Ctrl + Eto stop capture, thenCtrl + Xto clear the list. - Choose Filter → Filter.... Add: Process Name is
notepad.exe, click Add, then OK. - Open Notepad and type a few words.
- Press
Ctrl + Eto start capture again. In Notepad choose File → Save As, name itapi-lab.txtand save it in Documents. Then pressCtrl + Eto stop capture. - Look for rows whose Operation is CreateFile, WriteFile and CloseFile, with Path ending
api-lab.txt.
What the columns mean:
| Column | Meaning |
|---|---|
| Operation | The file or registry action (CreateFile, ReadFile, RegOpenKey ...) |
| Path | What it acted on |
| Result | SUCCESS, NAME NOT FOUND, ACCESS DENIED ... (NTSTATUS-style names, Section 3.4) |
| Detail | Extra facts such as access type |
- Which Operation names did you see for
api-lab.txt? ________________ - Find a row with a Result other than
SUCCESS(such asNAME NOT FOUND). What was the path? ________________
See the layer stack. Double-click a CreateFile row and open the Stack tab. You should see frames from top to bottom such as ntdll.dll, KERNELBASE.dll and a Notepad or user32/comdlg32 frame. (Names may show as plain addresses if symbols are not set up. That is fine.)
- Name two DLLs in the stack: ________________
When you are done, press Ctrl + E to stop capturing and close Process Monitor.
Windows tip. The operation name
CreateFileis shown by Process Monitor for both creating and opening files. It is the I/O request at the kernel level, which your program started throughCreateFileWandNtCreateFile.
What Should Happen
- Part 1 shows
ntdll.dllas a modest-sized file inSystem32. - Part 2 shows
ntdll.dllin almost every process, and your PowerShell loads all four DLLs. - Part 4 gives a tick count that matches your uptime.
- Part 5 gives plain-English text for each error number.
- Part 6 shows the file operations and the stack of layers from Section 5.
Interpretation Guide
| What you see | What it means |
|---|---|
ntdll.dll in nearly every process | It is the lowest user-mode layer, used by all programs |
Some processes list ntdll but not user32 | Background programs with no windows do not need the window DLL |
Get-Process Source is Microsoft.PowerShell.Management | A PowerShell module, not a DLL in System32. PowerShell itself calls Win32 underneath |
GetTickCount64 matches uptime | You really called a Win32 function in kernel32.dll |
ACCESS DENIED in Process Monitor | The kernel's security check refused. A program would see error 5 |
NAME NOT FOUND in Process Monitor | The path did not exist. A program would see error 2 or 3 |
Stack shows ntdll.dll below KERNELBASE.dll | The chain from Section 5: Win32 calls Native |
Follow-Up Questions
- In Part 6, which DLL sits closest to the kernel in the stack,
KERNELBASE.dllorntdll.dll? - Why does
Get-Processhave a Source that is a PowerShell module, and not a plain Win32 name? - Why did Process Monitor show a NAME NOT FOUND result even though nothing was wrong?
- If a program can only see error number 5, how would you find out the kernel's own status code?
- Name three facts from this lab that you could not have learned from just using Notepad.