Banner 1

Automatizando los volcados de memoria

Pues resulta que andaba yo revisando uno de los PCs traídos de un cliente para ser reparado en taller, y tal como tengo por costumbre, y por eso de ir aprendiendo, me disponía a utilizar windd para volcar la memoria del sistema en un fichero. En esas me encontraba cuando apareció por allí mi compañero, una grandísima persona y aún mejor administrador de sistemas Linux, interesándose por mis maniobras. Después de contarle un poco por encima lo que aquí acabo de describir y verme consultar la ayuda del comando en un par de ocasiones me dijo - yo personalmente, cuando tengo que repetir una tarea al menos dos veces, siempre me genero un script.

Análisis de objetivos

Como suele pasarme con las palabras de mi compañero, no suelo darles importancia en el momento, pero siempre acaban influenciándome. Dándole vueltas al tema me planteé los siguientes requerimientos para el script:
  • Recibirá como argumento la letra de unidad en la que almacenar el volcado resultante.
  • Debería poder detectar si en la unidad indicada hay sufiente espacio disponible para almacenar el volcado, por lo tanto tiene que ser capaz de averiguar la cantidad de memoria física de que dispone el equipo.
  • Tiene que poder detectar el tipo de sistema operativo, 32 ó 64 bits, para lanzar la versión de windd adecuada.
  • El resultado debería almacenarse en un directorio con un nombre significativo y el nombre del fichero debería ser lo suficientemente particular como para no sobreescribir ninguno existente, o ser susceptible de ser sobreescrito.

Si a todo lo anterior le sumamos la posibilidad de ejecutarlo con el menor número de modificaciones en las diferentes versiones NT del sistema operativo Windows, el primer "lenguaje" que me vino a la mente fue "batch scripting", así que lo primero tener a mano los "Assorted NT/2000/XP CMD.EXE Script Tricks", mantenidos por el profesor Timo Salmi.

Descomponiendo el problema en partes mas pequeñas

Empezaré primero tratando de determinar el número de bits del sistema operativo en el que se ejecuta el script. Tal y como sugieren en el siguiente enlace, quedaría algo así:
@echo off & setlocal enableextensions
 
if "%PROCESSOR_ARCHITECTURE%" == "x86" (
 if NOT DEFINED "%PROCESSOR_ARCHITEW6432%" (
  echo Sistema de 32 bits
 ) else (
  echo Sistema de 64 bits
 )
) else (
    echo Sistema de 64 bits
)

Otra alternativa sería la mencionada en el siguiente artículo de la base de conocmientos de Microsoft, How To Check If Computer Is Running A 32 Bit or 64 Bit Operating System, el cual se basa en la comprobación de la siguiente clave del registro:
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0

y más concretamente en el valor asociado al parametro Platform ID. Sin embargo descarto de inmediato éste método debido a su limitada universalidad (sólo sirve para sistemas W2k y W2k3).

Una vez salvado este punto continúo, por ejemplo, obteniendo la cantidad de memoria física de que dispone el sistema, utilizando para ello el comando integrado systeminfo y algo de parseo de los resultados. Así que añado las siguientes líneas al script:
for /f "tokens=6,7" %%a in (
    'systeminfo^|find "Cantidad total de memoria"') do (
  set memory_=%%a
  set units_=%%b)
echo Memoria total = %memory_% %units_%

Y ya de seguido procedo utilizando el comando fsutil para obtener el espacio libre de una unidad concreta indicada directamente en el script para simplificar así el proceso:
set drive_=C:
for /f "tokens=2 delims=:" %%a in (
    'fsutil volume diskfree %drive_%^|
    findstr /i /c:"bytes libres"') do (
        set totalSizeBytes_=%%a)
if defined totalSizeBytes_ echo Espacio libre en %drive_% %totalSizeBytes_% bytes
if not defined totalSizeBytes_ echo %drive_% The size could not be resolved

El resultado obtenido ejecutando el "programa" en mi portatil sería:
C:\Users\javi\Desktop\pruebas>testsystem.bat
Sistema de 32 bits
Memoria total = 2.047 MB
Espacio libre en C:  17223503872 bytes

La solución encontrada sería "casi perfecta", pero el problema es que me gustaría poder ejecutar el script también en sistemas Windows 2000 y éstos no disponen ni del comando systeminfo ni del comando fsutil. Si además tenemos en cuenta que no es posible realizar
operaciones aritméticas desde la línea de comandos de Windows sin utilizar herramientas de terceros decido currarme yo mismo un programa para suplir estas carencias.

El API de Windows y yo

Si partimos de la base de que no soy programador ni de lejos, pero que me encanta probar y aprender además de ser un experto en cortar, pegar y encajar, seguro que el código es infinitamente mejorable. De hecho os invito a descargarlo, modificarlo y arreglarlo, pero eso sí, compartiendo aquí vuestras mejoras para que aprendamos todos.

Para generar el ejecutable yo he utilizado MS Visual C++ 2008 Express Edition, entorno que puede descargarse de forma gratuita desde la web de Microsoft; el tipo de proyecto es una aplicación de consola Win32. Para los más impacientes he incluido una versión ya compilada junto con el resto de los ficheros que acompañan esta entrada.

Su funcionamiento es muy simple, tal y como puede apreciarse por la escueta ayuda que muestra al invocarlo sin indicar ningún parametro:
C:\Users\javi\Desktop\mkmemdmp>mkmemdmp.exe
Usage: mkmemdmp.exe 

Example: mkmemdmp.exe C:

Básicamente su función es la de comprobar si el volcado de memoria a realizar cabe en la unidad indicada y lanzar el batch script adecuado en función del sistema operativo en que se ejecute.

Como fuentes de documentación he utilizado los siguientes enlaces:

MEMORYSTATUSEX Structure
GlobalMemoryStatusEx Function
Driver Installation for 32-bit and 64-bit Platforms
GetSystemWow64Directory Function
SYSTEM_INFO Structure
GetSystemInfo Function
PROCESS_INFORMATION Structure
STARTUPINFO Structure
Processes: How can I start a process?

Otro poquito de batch scripting

Ya tengo el programa, el cual se encarga de hacer las comprobaciones oportunas y lanzar en consecuencia el script adecuado, dump32.bat para sistemas de 32 bits o dump64.bat para sistemas de 64 bits, indicándole la unidad a utilizar para almacenar los resultados.

El script en primer lugar comprueba si ya existe el directorio almacén, creándolo en caso contrario utilizando para ello el nombre de máquina:
set dir_=%1
set dir_=%dir_%memdmp_%COMPUTERNAME%
 
if not exist %dir_% (
 mkdir %dir_%
)

A continuación genera de forma automática los nombres para los ficheros, tanto para el de volcado como para el de log, utilizando una combinación de la fecha y hora en que se ejecuta:
for /f "tokens=1-3 delims=./-" %%f in ("%date%") do (
    set filename_=%%h%%g%%f
)
for /f "tokens=1-3 delims=:, " %%i in ("%time%") do (
 set filenamedmp_=%filename_%_%%i%%j%%k.dmp
 set filenamelog_=%filename_%_%%i%%j%%k.log
)

Ya por último lanza la herramienta windd, la verdadera estrella de la función, almacenando sus mensajes de salida en el fichero de log y mostrando los parámetros utilizados para ejecutarla. Por defecto el volcado se obtiene en formato raw y se genera el hash SHA1 del mismo.

Juntándolo todo

Para que todo funcione correctamente crearemos primero el directorio mkmemdmp y moveremos allí el ejecutable mkmemdmp.exe y los scripts dump32.bat y dump64.bat. Ahora descargaremos el paquete windd y extraeremos en el directorio anterior los binarios de 32 y 64 bits incluyendo sus drivers correspondientes:
C:\mkmemdmp>dir
 El volumen de la unidad C es SYSTEM
 El número de serie del volumen es: B00D-25C9
 
 Directorio de C:\mkmemdmp
 
08/12/2009  22:03              .
08/12/2009  22:03              ..
08/12/2009  21:46             1.379 dump32.bat
08/12/2009  19:03             1.375 dump64.bat
07/12/2009  21:19             9.216 mkmemdmp.exe
13/11/2009  13:02            92.088 win32dd.exe
13/11/2009  13:02            50.872 win32dd.sys
13/11/2009  13:02           101.304 win64dd.exe
13/11/2009  13:02            58.296 win64dd.sys
               7 archivos        314.530 bytes
               2 dirs  17.214.128.128 bytes libres

Suponiendo ahora que pretendemos almacenar el volcado y los ficheros resultantes en la unidad C: el comando a ejecutar sería:
C:\mkmemdmp>mkmemdmp.exe C:
 
  +---------------------------------------------------------------+
  |              -      Neo System Forensics       -              |
  |              http://neosysforensics.blogspot.com              |
  +---------------------------------------------------------------+
 
  Script para volcado automatizado de la memoria fisica del sistema
  Detecta y utiliza la version adecuada de la herramienta windd (*)
 
  Fichero de dmp generado:
  C:\memdmp_OSIRIS\20091208_220938.dmp
 
  Fichero de log generado:
  C:\memdmp_OSIRIS\20091208_220938.log
 
  Comando windd utilizado:
  win32dd.exe /a /s 1 /f C:\memdmp_OSIRIS\20091208_220938.dmp
 
  (*) windd - Kernel land physical memory acquisition
  Copyright (c) 2007 - 2009, Matthieu Suiche 
  Copyright (c) 2008 - 2009, MoonSols 

Y el contenido del directorio con los resultados sería:
C:\mkmemdmp>dir ..\memdmp_OSIRIS
 El volumen de la unidad C es SYSTEM
 El número de serie del volumen es: B00D-25C9
 
 Directorio de C:\memdmp_OSIRIS
 
08/12/2009  22:09              .
08/12/2009  22:09              ..
08/12/2009  22:10     2.147.155.968 20091208_220938.dmp
08/12/2009  22:10             2.589 20091208_220938.log
               2 archivos  2.147.158.557 bytes
               2 dirs  12.927.860.736 bytes libres


Correción 09/12/2009:

Para que el binario compilado incluido en el paquete comprimido funcione, es necesario tener instalado el Microsoft Visual C++ 2008 Redistributable Package (x86).

Código, scripts y ejecutable: mkmemdmp.zip


Muy buen post de neofito.

FUENTE:
http://neosysforensics.blogspot.com/2009/12/automatizando-los-volcados-de-memoria.html

No hay comentarios:

Powered by Bad Robot
Helped by Blackubay