"Deadly nailed to the core" graphics subsystem



    What is commonly called "graphics in the kernel" usually refers to win32k. Win32k.sys is the core of the graphics subsystem. Loaded by the user process smss.exe during the initialization process of all other subsystems. The path to the executable image for the "kmode" subsystem is registered here:


    How does this happen?



    Here (on the stack trace at the bottom of the screenshot), it is clearly visible that the win32k boot process of the smss user mode (which, among other things, initializes paging files, registry, environment variables, saves a memory dump, if there was a bugcheck before, starts service with wininit control manager and local security authority subsystem, creates logon sessions, etc.), and one of the first things win32k does is to "establish connections" with the kernel. And here's why: win32k is at a higher level than the core, so the kernel cannot have a dependency (“dependency” in this case means the classic “reason to change”) on (specific implementation) win32k, but both the kernel and win32k can It is safe to depend on the interface.

    In addition, win32k registers several types of objects (in particular, Desktop and WindowStation) through the general-purpose interfaces provided by Object Manager.

    Thus, the kernel does not have any dependencies on win32k. Moreover, before NT4, all user / gdi APIs were processed in csrss and, of course, slowed down. Starting with NT4, the PART of user / gdi primitives has been ported to the kernel to improve performance.

    In general, win32k can be completely removed, you can replace it with your own kernel part, or you can implement everything completely in user mode (using, for example, ioctls to communicate with the kernel), but this will slow down. The only reason this is not done is because it is not needed. You can write in another way - yes, it is much better to write - hardly. Well, rewriting for the sake of rewriting is not a good idea.

    Practice is the criterion of truth or “MinWin on the knee”


    To eliminate misunderstandings, I want to say right away: what I will do is not MinWin. It’s not at least because the real MinWin contains a minimal set of user (user mode) binaries, but I'm going to demonstrate a fully loaded kernel (another difference is that MinWin contains a minimal set of drivers, but my set of drivers does not change compared to regular loading ) without any user mode at all (ok, one process and one dll there is still there, but you need to at least somehow show the user that something is happening). An additional reason for reflection may be that the real MinWin appeared in connection with the work of “bundling” the Windows 7 code, the same thing that I will do in principle is possible on XP and even on NT3.51

    So, if you carefully read what is written in the previous section, you can guess that we need to replace smss with one that does not initialize the subsystem, but still remains more or less interactive. smss.exe is an ordinary native process (approximately, a native application is an application that only links to ntdll.dll and accordingly uses only the Native API to work). Luckily for me, Alex Ionescu, a former ReactOS chief developer, has already written a similar application as part of the (long-closed) tinykrnl project. This application is not built under amd64, is not built on the latest WDK, it has several bugs, but generally works. The following picture can be opened by the archiver - it contains the sources and the compiled amd64 binary of the small application native.exe:


    Please forgive me, but I can’t lay out the finished image because it is illegal, so I post the code that can collect the vhd-image from the installation image.
    The following code can be executed ONLY on Win7. Save it somewhere to a temporary directory under the name, for example minwin.ps1, put install.wim next to it (located in the \ sources directory) from the en-us installation disk of Windows 7 (this is important - only the NLS files necessary for this localization are copied), save the native.exe file from the picture attached above to this directory, go to this same directory in the elevated console and do the following:
    powershell -executionpolicy bypass .\minwin.ps1

    For brevity:
    1. Next in one directory should be the following files: minwin.ps1, install.wim and native.exe
    2. You need to run minwin.ps1 only after changing the current directory to the directory containing the above files

    Disclaimer: you do the following on own fear and risk. The teams are quite obvious and should not do any harm, but this is “knee-high” creativity, therefore it is not required to work in any conditions. Do not execute this script if you do not understand the meaning of EVERY command (moreover, the execution must be performed from under an elevated user).If not, below is a picture of how it finally looks. In a simplified version, you can simply rename native.exe to smss.exe, copy it over the existing smss.exe in the already loaded virtual machine (any x64 Windows will work - from XP to 7) and reboot.
    The script itself:
    $vhdName = "disk.vhd"
    $wimName = "install.wim"
    $vhdDisk = "V"
    $wimMountName = "MountedWim"
    md $wimMountName
    dism /mount-wim /wimfile:$wimName /index:1 /mountdir:$wimMountName
    #del $vhdName
    @"
    create vdisk file=$pwd\$vhdName type=expandable maximum=128
    select vdisk file=$pwd\$vhdName
    attach vdisk
    create partition primary
    format fs=ntfs quick
    assign letter=$vhdDisk
    active
    "@ | diskpart
    bcdboot "$pwd\$wimMountName\Windows" /s "${vhdDisk}:"
    #cmd /c "$wimMountName\Windows\System32\bootsect /nt60 ${vhdDisk}: /mbr /force"
    $disk = gwmi win32_diskdrive -filter "Model = 'Msft Virtual Disk SCSI Disk Device'"
    $part = $disk.GetRelated("win32_diskpartition") | select -first 1
    $bootmgr = [wmi]"root\wmi:BcdObject.Id=`"{9dea862c-5cdd-4e70-acc1-f32b344d4795}`",StoreFilePath=`"${vhdDisk}:\\boot\\bcd`""
    $osloader = [wmi]"root\wmi:BcdObject.Id=`"$($bootmgr.GetElement(0x23000003).Element.Id)`",StoreFilePath=`"${vhdDisk}:\\boot\\bcd`""
    $bootmgr.SetQualifiedPartitionDeviceElement(0x11000001, 0, $disk.Signature, $part.StartingOffset)
    $osloader.SetQualifiedPartitionDeviceElement(0x11000001, 0, $disk.Signature, $part.StartingOffset)
    $osloader.SetQualifiedPartitionDeviceElement(0x21000001, 0, $disk.Signature, $part.StartingOffset)
    $osloader.SetStringElement(0x12000002, "\Windows\system32\winload.exe")
    $osloader.SetStringElement(0x22000002, "\Windows")
    $osloader.SetBooleanElement(0x26000022, $true)
    md "${vhdDisk}:\Windows\System32\config\", "${vhdDisk}:\Windows\Fonts", "${vhdDisk}:\Windows\inf", "${vhdDisk}:\Windows\SysWOW64"
    copy -r "$wimMountName\Windows\System32\drivers" "${vhdDisk}:\Windows\System32\drivers"
    del "${vhdDisk}:\Windows\System32\drivers\termdd.sys"
    copy "$wimMountName\Windows\Fonts\vgaoem.fon" "${vhdDisk}:\Windows\Fonts"
    copy "$wimMountName\Windows\inf\errata.inf" "${vhdDisk}:\Windows\inf"
    copy "$wimMountName\Windows\System32\config\SYSTEM" "${vhdDisk}:\Windows\System32\config"
    copy "$wimMountName\Windows\SysWOW64\ntdll.dll" "${vhdDisk}:\Windows\SysWOW64"
    copy native.exe "${vhdDisk}:\Windows\System32\smss.exe"
    "ntoskrnl.exe", "hal.dll", "ci.dll", "pshed.dll", "clfs.sys", "kdcom.dll", "ntdll.dll", "apisetschema.dll",
    "winload.exe", "bootvid.dll", "bootres.dll", "l_intl.nls", "c_1252.nls", "c_437.nls" |% {
        copy (Join-Path "$wimMountName\Windows\System32" $_) "${vhdDisk}:\Windows\System32"
    }
    @"
    select vdisk file=$pwd\$vhdName
    detach vdisk
    "@ | diskpart
    dism /unmount-wim /mountdir:$wimMountName /discard
    

    It looks something like this:


    If everything is done correctly (and with some luck :-)), then after some time the disk.vhd file will appear in the same directory - it can be run in a virtual machine (tested in VirtualBox, but I see no reason for which it should not work in Virtual PC, Hyper-V or anywhere else):


    Well, a few comments in the end.

    1. Almost 300 drivers are copied, downloaded - about 100, really needed on a specific system - 10-20 pieces.
    2. The eight-megabyte SYSTEM high from install.wim can be replaced quite normally with the two-megabyte from boot.wim, or you can manually blind something up to a hundred kilobytes.
    3. bcdboot copies all bootmgr localizations and several megabytes of fonts (mainly for CJK) - you can cut
    4. You may notice that when creating the image termdd.sys is deleted - this is not done because it does not work. It just creates another keyboard device (which in normal mode is used to “press buttons” on a remote machine in a terminal session), and I was too lazy to modify native.exe to read keystrokes from all keyboards.
    5. You can suppress the graphics at boot and refuse bootvid.dll and bootres.dll

    Well and most importantly, win32k.sys is not copied to the created image, which does not prevent this image from working relatively well without graphics at all. With a great desire, as I said, you can screw the fully console shell, you can cut out the Windows subsystem and leave only Posix (this would be a very strange desire, as for me, but people often want a strange one). Or (an even stranger desire) to implement native X11 on top of the NT kernel. You can replace smss and “completely control” everything that works above the kernel, or you can leave smss and change the set of loaded subsystems with a couple of edits in the registry. In short, there is simply no graphics “tightly nailed to the core”.

    Thanks for attention

    Also popular now: