
Visualiza el espacio de direcciones virtuales de un proceso de Windows en una curva de Hilbert.
Clairvoyance (/klɛərˈvɔɪəns/; del francés clair que significa claro y voyance que significa visión) de Wikipedia.
clairvoyance crea una visualización colorida de la protección de páginas de todo el espacio de direcciones de un proceso de 64 bits (usuario y kernel) que se ejecuta en un kernel de Windows de 64 bits.
Para transformar el espacio de 1 dimensión, es decir, el espacio de direcciones, en una visualización de 2 dimensiones, se utiliza la curva de Hilbert que llena el espacio. Cada píxel de color en la imagen anterior representa la protección de página (UserRead, UserReadWrite, etc.) de una página de 4 KB en memoria virtual.
El espacio de direcciones se calcula directamente analizando manualmente la jerarquía de tablas de páginas de cuatro niveles asociada con un proceso a partir de un volcado de memoria del kernel que se ha generado utilizando WindDbg.
Finalmente, el programa genera un archivo con los metadatos necesarios para mostrarlo en un lienzo bidimensional, así como para poder calcular la dirección virtual correspondiente a un píxel resaltado específico.
Los binarios compilados están disponibles en la sección de lanzamientos. También hay un visor en línea alojado en 0vercl0k.github.io/clairvoyance.
Agradecimientos a:
Para generar el volcado de memoria del kernel, se recomienda utilizar WinDbg, KDNet con el comando .dump /f.
Una vez que haya obtenido el volcado, puede pasar su ruta a clairvoyance junto con la dirección física del directorio de páginas que le interese:
./clairvoyance <dump path> [<page dir pa>]
Esto genera un archivo con la extensión clairvoyance que luego puede visualizar en su navegador en 0vercl0k.github.io/clairvoyance o consultando la rama gh-pages, que es donde está alojado el visor.
La CI compila clairvoyance en Linux usando clang++-11 y en Windows usando Visual Studio 2019 de Microsoft.
Para compilarlo usted mismo, puede usar los scripts en build/:
(base) clairvoyance\build>build-msvc.bat
(base) clairvoyance\build>cmake ..
-- Selecting Windows SDK version 10.0.19041.0 to target Windows 10.0.19042.
-- Configuring done
-- Generating done
-- Build files have been written to: clairvoyance/build
(base) clairvoyance\build>cmake --build . --config RelWithDebInfo
Microsoft (R) Build Engine version 16.8.2+25e4d540b for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
clairvoyance.vcxproj -> clairvoyance\build\RelWithDebInfo\clairvoyance.exe
Building Custom Rule clairvoyance/CMakeLists.txt
Lo siguiente son cosas que he notado en un volcado de memoria del kernel generado desde una máquina virtual Hyper-V de Windows:
kd> vertarget
Windows 10 Kernel Version 18362 UP Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Edition build lab: 18362.1.amd64fre.19h1_release.190318-1202
Machine Name:
Kernel base = 0xfffff805`36800000 PsLoadedModuleList = 0xfffff805`36c432f0
Debug session time: Sat Jul 25 10:00:19.637 2020 (UTC - 8:00)
System Uptime: 0 days 0:18:53.609
Windows no parece estar usando páginas enormes (1GB), o al menos no he visto que se use alguna en ninguno de los volcados que recopilé.
Las páginas grandes se usan en abundancia para mapear algunos ejecutables del kernel, como el kernel de Windows nt, por ejemplo:
kd> ? nt
Evaluate expression: -8773703827456 = fffff805`36800000
VA:0xfffff80536800000, PA:0x2400000 (KernelReadWriteExec, Large, PML4E:0xd5745f80, PDPTE:0x42080a0, PDE:0x4209da0, PTE:0x0)
También hay un montón de páginas de kernel de lectura, escritura y ejecución que no son páginas grandes, lo cual fue una sorpresa. Sabía que el kernel / hal podía mapearse usando páginas grandes y que esas eran krwx. La razón es que 2MB es tan grande que abarca tanto las secciones ejecutables como las de datos; lo que significa que la página debe ser escribible y ejecutable.
La única mención pública de esto que pude encontrar está en esta entrada de blog (gracias `Ivan):
Me puse en contacto con Microsoft, que afirmó que esto es intencional ya que «en algunos casos el kernel se mapea con páginas grandes» y que esto se puede prevenir habilitando la protección basada en virtualización (VBS).
Un montón de grandes secciones de memoria del kernel se mapean contra la misma página física (rellena con ceros):
VA:0xffffc27ef4401000, PA:0x4200000 (KernelRead, Normal, ...)
VA:0xffffc27ef4402000, PA:0x4200000 (KernelRead, Normal, ...)
VA:0xffffc27ef4403000, PA:0x4200000 (KernelRead, Normal, ...)
...
VA:0xffffc27ef63fb000, PA:0x4200000 (KernelRead, Normal, ...)
VA:0xffffc27ef63fc000, PA:0x4200000 (KernelRead, Normal, ...)
VA:0xffffc27ef63fd000, PA:0x4200000 (KernelRead, Normal, ...)
VA:0xffffc27ef63fe000, PA:0x4200000 (KernelRead, Normal, ...)
VA:0xffffc27ef63ff000, PA:0x4200000 (KernelRead, Normal, ...)
Aquí hay una más pequeña (la región no es completamente contigua, hay algunos huecos):
VA:0xffffc27ed2201000, PA:0x4300000 (KernelRead, Normal, ...)
VA:0xffffc27ed2202000, PA:0x4300000 (KernelRead, Normal, ...)
VA:0xffffc27ed2203000, PA:0x4300000 (KernelRead, Normal, ...)
...
VA:0xffffc27ed25fc000, PA:0x4300000 (KernelRead, Normal, ...)
VA:0xffffc27ed25fd000, PA:0x4300000 (KernelRead, Normal, ...)
VA:0xffffc27ed25fe000, PA:0x4300000 (KernelRead, Normal, ...)
VA:0xffffc27ed25ff000, PA:0x4300000 (KernelRead, Normal, ...)
Esta es solo una sección que muestra algunos de los patrones geniales que puedes ver en algunas regiones de un espacio de direcciones.
Las asignaciones de Page heap y sus páginas de guardia son bastante llamativas y fáciles de detectar:
Las pilas del kernel también tienen una forma reconocible y agradable debido a su tamaño y sus páginas de guardia:
La región de caché del sistema en el kernel parece verse como una nebulosa en los volcados que he visto:
Axel '0vercl0k' Souchet