
Un framework de depuración, trazado y manipulación de procesos multinúcleo basado en eventos.
libptrace es un framework de depuración, trazado y manipulación de procesos/hilos basado en eventos. Está escrito en C y tiene enlaces para Python 2.7 y 3.7.
Está pensado para ser utilizado como biblioteca. La API se ha diseñado teniendo en cuenta la compatibilidad multiplataforma. Aunque la versión actual solo se ejecuta en versiones de 32 y 64 bits (wow64 es compatible) de Windows, el diseño y las abstracciones permiten añadir otras plataformas e incluso soporte de depuración remota bajo la misma API.
Reconoce múltiples núcleos/hilos y puede utilizarse fácilmente para ejecutar múltiples bucles de eventos concurrentemente. La depuración de grupos de procesos o líneas de comandos, o el trazado de un gran número de procesos, se puede escalar aumentando los núcleos de ejecución de esta manera.
Escribí la versión inicial de libptrace en 2006, mientras aún estaba en la universidad, y la relicencié para uso completo de Immunity Inc. en 2011, mi empleador en ese momento. Alrededor de esta época, el framework debía integrarse en Immunity Debugger, aunque siempre me he asegurado de mantener el framework separado, para que pudiera usarse de forma independiente.
Con ese objetivo, tuvo mucho desarrollo en Immunity, y estoy agradecido de haber podido desarrollarlo activamente durante mi horario laboral y ver cómo el framework se volvía más maduro. Rediseñé la mayor parte para que reconociera múltiples núcleos, proporcionara enlaces Python y creara mejores abstracciones.
Con el lanzamiento eventual de x64dbg, se decidió que ya no trabajaríamos en Immunity Debugger y, en cambio, centraríamos nuestros esfuerzos en otras cosas. Esto también frenó el desarrollo de libptrace, y durante los años siguientes acumuló polvo en el repositorio interno de git, hasta que después de la adquisición de Immunity Inc. por Cyxtera Technologies, ahora bajo Cyxtera Cybersecurity Inc., se decidió liberar el proyecto bajo la LGPL versión 2.1 para que esperemos pueda tener adopción y un desarrollo continuo.
Quiero agradecer cordialmente a Immunity Inc., así como a Cyxtera Technologies y Cyxtera Cybersecurity Inc. por hacer posible este lanzamiento. También me gustaría agradecer especialmente a Dave Aitel por impulsar este lanzamiento a través de capas de gestión y por protegerme de las partes burocráticas del proceso. Habría sido triste ver mi trabajo perdido y sin propósito, y sin su voluntad de liberar el desarrollo de libptrace que se hizo internamente como código abierto, eso es lo que habría sucedido.
También quiero agradecer a varios compañeros de trabajo que dedicaron tiempo a usar o trabajar en el framework, especialmente a Massimiliano Oldani, Roderick Asselineau y Christos Kalkanis. Mi agradecimiento también se extiende a Lennert Buytenhek por sus implementaciones de árbol AVL intrusivo y lista enlazada que terminé usando.
Aunque han pasado más de 4 años desde que se realizó cualquier trabajo en el proyecto, espero que la gente lo encuentre útil. Creo que el diseño y el código fuente son relativamente limpios, y en este punto permiten que el framework se extienda y se porte a otras plataformas con relativa facilidad. Espero que algún día esto pueda convertirse en una verdadera biblioteca de depuración multiplataforma bajo una API consistente.
Finalmente, me gustaría dedicar este proyecto a mi hija perdida, Yuzuyu Huizer, con quien espero reunirme algún día. Te amo.
-- Ronald Huizer [email protected]
El método de compilación actual compatible es mediante compilación cruzada del proyecto usando MinGW y CMake. El sistema de compilación se ha probado en Ubuntu 19.04.
Se puede compilar un instalador de 32 bits usando:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=mingw-w64-x86.cmake .
make
makensis libptrace-setup.nsi
Se puede compilar un instalador de 64 bits usando:
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=mingw-w64-x64.cmake .
make
makensis -DUSE64 libptrace-setup.nsi
Después de seguir los pasos de compilación anteriores, el instalador de 32 bits estará en libptrace-setup32.exe y el instalador de 64 bits estará en libptrace-setup64.exe.
El instalador determinará automáticamente qué versiones de Python están instaladas y si son de 32 o 64 bits. Las versiones que se encuentren serán ofrecidas por el instalador, y las que no se encuentren aparecerán atenuadas.
Las descargas de las versiones publicadas se pueden encontrar aquí.
El directorio doc/ está irremediablemente desactualizado. Se incluye como punto de partida para documentación más actual. Por favor, no lo use.
Varios scripts de ejemplo se pueden encontrar en el directorio python/scripts. Se instalarán en Program Files\Immunity Inc\libptrace o, en el caso de la versión de 32 bits, en Program Files (x86)\Immunity Inc\libptrace.
Estos ejemplos no muestran el framework de manera exhaustiva, pero deberían proporcionar un buen punto de partida para cualquiera que quiera usar el framework. La API en C no está bien documentada, pero se pueden encontrar algunos ejemplos en el directorio unittests/windows. El directorio python/, que contiene los enlaces de Python, también proporciona una buena visión general. Finalmente, el directorio include/libptrace contiene los archivos de cabecera que son públicos y, por lo tanto, proporcionan una buena lista de funciones de la API.
Cabe señalar que la API de Python es actualmente un subconjunto bastante limitado de la API de C.
Como ejemplo, el flujo de trabajo general para trazar llamadas a RegOpenKeyExW en un ejecutable sería:
import _ptrace
def bp_handler(bp, thread):
(key, subkey, options, sam, result) = _ptrace.cconv.args_get(thread, "%u%p%u%u%p")
subkey = thread.process.read_utf16(subkey)
print('T{}: RegOpenKeyEx({}, "{}", 0x{:08x}, 0x{:08x}, 0x{:08x})'
.format(thread.id, key, subkey, options, sam, result), end='')
def attached_handler(process):
bp = _ptrace.breakpoint_sw("advapi32!RegOpenKeyExW", bp_handler)
process.breakpoint_set(bp)
handlers = _ptrace.event_handlers()
handlers.attached = attached_handler
_ptrace.execv(r"C:\Windows\Notepad.exe", [], handlers, 0)
_ptrace.main()
Si también se desea el valor de retorno de RegOpenKeyExW, lo más fácil es establecer un punto de interrupción en la dirección de retorno de la llamada a la función. Esto evita la necesidad de análisis de código para determinar las rutas de salida de la función de forma estática:
def bp_end_handler(bp, thread):
print("=", _ptrace.cconv.retval_get(thread))
def bp_handler(bp, thread):
(key, subkey, options, sam, result) = _ptrace.cconv.args_get(thread, "%u%p%u%u%p")
subkey = thread.process.read_utf16(subkey)
print('T{}: RegOpenKeyEx({}, "{}", 0x{:08x}, 0x{:08x}, 0x{:08x})'
.format(thread.id, key, subkey, options, sam, result), end='')
retaddr = _ptrace.cconv.retaddr_get(thread)
if thread.process.breakpoint_find(retaddr) is None:
bp_end = _ptrace.breakpoint_sw(retaddr, bp_end_handler)
thread.process.breakpoint_set(bp_end)
La situación de los derechos de autor se aclara en cada archivo individual. En su mayoría pertenecen a Cyxtera Cybersecurity Inc., Ronald Huizer, o ambos al mismo tiempo. Algunos archivos seleccionados tienen titulares de derechos de autor de terceros, como Lennert Buytenhek.
Distribuido bajo la versión 2.1 de la Licencia Pública General Reducida de GNU (GNU Lesser General Public License). Consulte COPYING y COPYING.LESSER para obtener más información.