Seguridad de la red | Aprendizaje de entrada de prueba de penetración, desde cero entrada básica hasta competencia: explicación detallada de la tecnología de análisis estático

Tabla de contenido

prefacio 

 1. Análisis del tipo de archivo

 2. Desmontaje del motor

2.1, OllyDbg y ODDisasm

 2.2, BeaEngine

 2.3、Udis86

2.5, AsmJit

 2.6, Keystone

 2.7 Resumen


prefacio 

Los programas escritos en lenguajes de alto nivel vienen en dos formas. Un programa se compila en lenguaje de máquina para ejecutarse en la CPU, como Visual C++. El lenguaje de máquina y el lenguaje ensamblador son casi correspondientes, por lo tanto, el lenguaje de máquina se puede convertir en lenguaje ensamblador, este proceso se llama desensamblado (Disassembler). Por ejemplo, en el sistema x86, el lenguaje ensamblador correspondiente al código máquina "EB" es "jmp short xx". Otro tipo de programa se ejecuta mientras se explica.El lenguaje utilizado para escribir este programa se llama lenguaje interpretado, como Visual Basic 5.0/6.0, Java. El programa compilado de este tipo de lenguaje puede restaurarse a la estructura original del lenguaje de alto nivel.Este proceso se llama decompiler (Descompilador).

El llamado análisis estático se refiere a obtener el código ensamblador del programa o el código fuente mediante el desensamblado y la descompilación, y luego analizar el flujo del programa de acuerdo con la lista de programas para comprender las funciones realizadas por el módulo.

 

 1. Análisis del tipo de archivo

El primer paso en el análisis inverso de un programa es analizar el tipo de programa, comprender en qué idioma está escrito el programa o qué compilador se usa para compilarlo, y si el programa ha sido procesado por algún tipo de programa de encriptación, de modo que que el próximo paso puede ser dirigido. Este proceso de análisis requiere la asistencia de herramientas de análisis de archivos. Las herramientas comunes de análisis de archivos incluyen PEiDExeinfoPE, etc. Dichas herramientas pueden detectar la mayoría de los lenguajes compilados, virus y software de encriptación.Esta sección usa PEiD como ejemplo para explicar brevemente su uso.
PEiD es una herramienta de detección y análisis de archivos de uso común con una interfaz GUI. Detecta la mayoría de los lenguajes compilados, virus y shells cifrados. Como se muestra en la figura a continuación, los archivos analizados se compilan con Microsoft Visual C++ 5.0/6.0. Para los archivos que no se pueden analizar, puede informar "PEWin GUT" ("Win CUI" es el nombre general del usuario gráfico de Windows programa de interfaz Al usarlo a través de Marque la opción "RegisterShellExtensions" en el menú "Opciones" para agregar la opción correspondiente en el menú contextual del botón derecho.

Recordatorio: PEiD aquí recomienda usar la versión My Love, úsala con confianza y seguridad. Para descargar, descárguelo del sitio web oficial de Wuwuai.

 Las herramientas de análisis de archivos, como PEiD, utilizan búsquedas de características para completar el trabajo de identificación. Varios lenguajes de desarrollo tienen códigos de inicio fijos, que se pueden usar para identificar de qué idioma se compila el programa. El programa procesado por el programa de encriptación dejará información sobre el software de encriptación, que se puede usar para identificar qué tipo de software está encriptado.

El que se muestra a continuación no está cifrado.


PEiD proporciona un archivo de interfaz extendido userdb.txt, los usuarios pueden personalizar algunos códigos de funciones, para que se puedan reconocer nuevos tipos de archivos. La creación de la firma se puede completar con el complemento Add Sigmature, y si es necesario, se debe corregir con la ayuda de un depurador como 0llyDbg.


Con el fin de engañar al software de identificación de archivos como PEiD, algunos programas shell eliminarán parte de la información del embalaje y falsificarán los códigos de inicio. Por ejemplo, cambiar el código de entrada a un código similar al programado por VisuaC++6.0 puede lograr el propósito de engañar. Por lo tanto, los resultados proporcionados por la herramienta de identificación de archivos solo pueden usarse como referencia. En cuanto a si el archivo ha sido empaquetado, solo puede saberse rastreando y analizando el código del programa. 

 2. Desmontaje del motor

Los motores de ensamblaje y los motores de desensamblaje se utilizan a menudo en el desarrollo de software de seguridad y software de protección, como 0llyDhg, IDAVMProtect, Packer y Decompiler. La función del desensamblado es analizar el código de la máquina en instrucciones de ensamblaje. El desarrollo de un motor de desensamblaje requiere una comprensión profunda de la codificación de instrucciones de máquina 386 de Intel. Sin embargo, generalmente no es necesario desarrollar un motor de desensamblado usted mismo. Hay muchos motores de desensamblado de código abierto o de pago disponibles en Internet. El motor de ensamblaje y desensamblado x86-64 de código abierto convencional actual tiene sus propias ventajas en diferentes escenarios de uso. La siguiente es una comparación de motores de ensamblaje y motores de desensamblado comúnmente utilizados. Los motores de desensamblado incluyen ODDisasm, BeaEngine, Udis86 y Capstone, y los activadores de ensamblaje incluyen ODAssemhler, Keystone y AsmJit.

2.1, OllyDbg y ODDisasm

El motor de desensamblaje integrado de OllyDbg, ODDisasm, tiene la ventaja de tener una interfaz de ensamblaje (es decir, la solución de texto analiza las cadenas de texto y las codifica en valores binarios). Esta función fue única en el pasado. La función del depurador x64_dbg que apareció en los últimos años es similar a la función de análisis de texto de 0llyDbg. Admite un conjunto de instrucciones más completo, menos errores y es compatible con la plataforma x64.

Hay muchas desventajas de ODDisasm, los ejemplos son los siguientes.

  • El conjunto de instrucciones admitido está incompleto. 0llyDbg ya no se actualiza Se actualizó el soporte insuficiente para el conjunto de instrucciones MMX y varias versiones del estándar de conjunto de instrucciones extendido de InteAMD, por lo que no puede analizar los conjuntos de instrucciones SSE5, AVX y AESXOP.
  • La estructura decodificada no es lo suficientemente detallada. Por ejemplo, el soporte para prefijos de instrucciones no es lo suficientemente amigable, lo que se puede ver desde la ventana de desensamblaje de ollyDbg (a excepción de moscmps y otras instrucciones, repcc se muestra por separado cuando se combina con otras instrucciones).
  • El autor ya no mantiene la versión de código abierto después de abrir la fuente una vez, y es difícil corregir los errores en el desmontaje a tiempo.
  • No se admite el ensamblaje y desensamblaje de instrucciones de 64 bits.

Sin embargo, la existencia de estas deficiencias también es comprensible, porque el propósito del desarrollo de DDisasm del autor es realizar el ensamblaje y desensamblado de texto, por lo que no existe una estructura ni una interfaz para la información decodificada. En general, el motor de desmontaje de ODDisasm está muy atrasado.

 2.2, BeaEngine

BeaEngine no tiene deficiencias obvias y los conjuntos de instrucciones extendidas que se pueden analizar incluyen FPU, MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, VMX, CLMUL, AES y MPX. BeaEngine clasifica las instrucciones para juzgar diferentes instrucciones. Otra característica de BeaEngine es que puede decodificar los registros utilizados y afectados por cada instrucción, incluido el registro de bandera, e incluso decodificar con precisión todas las posiciones del registro de bandera. Esta función es muy ventajosa para usar como optimizador y ofuscador.

Además de admitir el desensamblado de instrucciones x86, BeaEngine también admite el desensamblado de instrucciones x64. El estilo de codificación de BeaEngine es un poco complicado, como lanzar varias variables y usar múltiples estilos de nombres. Si no le importan estos, el rendimiento de BeaEngine sigue siendo bueno.

 2.3、Udis86

Udis86 es un motor de desmontaje popular que admite extensiones x86, incluidas MMX, FPU (x87), AMD3D Nowl, SSE, SSE2, SSE3, SSSE3, SSE4. INTEL-VMX y SMXUdis86 no solo admiten el desmontaje de las instrucciones x86, sino que también admiten el desmontaje de instrucciones x64. El estilo de código de Udis86 está simplificado, las funciones son breves y pequeñas, la interfaz y la denominación de variables son claras, sencillas y flexibles. Si necesita mantener una rama usted mismo, puede familiarizarse con la estructura del código completo en decenas de minutos utilizando Udis86.

La ventaja de Udis86 es que la interfaz es flexible. Puede usar la función ud_decode para decodificar solo una instrucción y luego usar la función ud_translate_intel para convertir la estructura decodificada en un formato de texto. También puede usar directamente la función ud_disassemble para completar todo operaciones a la vez. Estas interfaces solo necesitan una línea de código. podrá lograr.

Este concepto de diseño de modo combinado de Udis86 lo hace adecuado para varios escenarios. Por ejemplo, desarrolle un desensamblador como IDA y desarrolle simuladores de instrucciones, analizadores, mezcladores optimizadores, etc. Esta filosofía le permite a Udis86 tener en cuenta el rendimiento mientras posee una gran adaptabilidad. Con detalles y capacidades de decodificación similares, Udis86 es el motor de desmontaje más rápido para decodificar.

2.4, piedra angular

Se puede decir que Capstone es el maestro de todas las referencias de desmontaje. Debido a que Capstone se trasplanta de parte del componente MC del marco LLVM, las arquitecturas de CPU compatibles con LLVM también son compatibles con Capstone. Las arquitecturas de CPU compatibles con Capstone incluyen ARM, ARM64 (ARMv8), M68K, MIPS, PowerPC, SPARC Systemz, TMS320C64X, XCORE, x86 (incluido x86-64) Además, el soporte de Capstone para el conjunto de instrucciones de la arquitectura x86 es el más completo y no tiene comparación con otros motores AVX512CD, AVX512ERAVX512F, AVX512PF, BMI, BMI2, FMA, FMA4, FSCSBASE, LZCNT, MMX , SCX, SHA, SLM SSE, SSE2, SSE3, SSE4.1, SSE4.2,
SSE4A, SSSE3, TBM, XOP en el terminal móvil actual En el contexto del desarrollo en caliente, hay pocas bibliotecas de desmontaje compatibles con ARM. Si desea desarrollar compiladores bajo x86 y ARM al mismo tiempo, es mejor utilizar una interfaz unificada. Desde la perspectiva de la plataforma x86-64, ya sea la capacidad de decodificación o la compatibilidad con el conjunto de instrucciones, Capstone supera por completo a BeaEngine.

2.5, AsmJit

AsmJit es un ensamblador y compilador JIT completo empaquetado en C++. Puede generar instrucciones de ensamblaje nativas para arquitecturas x86 y x64, y admite conjuntos de instrucciones x86 y x64, incluidos MMX, SSExBMIxADXTBMXOPAVXxFMAxAVX512, etc.


AsmJit es diferente de las bibliotecas de código abierto presentadas anteriormente. No desensambla ni analiza instrucciones binarias como BeaEngine, Udis86 y Capstone. Es solo un ensamblador. En comparación con el ensamblador XEDParse de OllyDbg (estos son ensambladores basados ​​en texto), AsmJit también se ensambla de una manera completamente diferente. Un ejemplo simple es el siguiente.

#include <asmjit/asmjit.h>

using namespace asmjit;

int main(int argc, char* argv[]) {
  // Create JitRuntime and X86 Compiler.
  JitRuntime runtime;
  X86Compiler c(&runtime);

  // Build function having two arguments and a return value of type 'int'.
  // First type in function builder describes the return value. kFuncConvHost
  // tells compiler to use a host calling convention.
  c.addFunc(kFuncConvHost, FuncBuilder2<int, int, int>());

  // Create 32-bit variables (virtual registers) and assign some names to
  // them. Using names is purely optional and only greatly helps while
  // debugging.
  X86GpVar a(c, kVarTypeInt32, "a");
  X86GpVar b(c, kVarTypeInt32, "b");

  // Tell asmjit to use these variables as function arguments.
  c.setArg(0, a);
  c.setArg(1, b);

  // a = a + b;
  c.add(a, b);

  // Tell asmjit to return 'a'.
  c.ret(a);

  // Finalize the current function.
  c.endFunc();

  // Now the Compiler contains the whole function, but the code is not yet
  // generated. To tell compiler to generate the function make() has to be
  // called.

  // Make uses the JitRuntime passed to Compiler constructor to allocate a
  // buffer for the function and make it executable.
  void* funcPtr = c.make();

  // In order to run 'funcPtr' it has to be casted to the desired type.
  // Typedef is a recommended and safe way to create a function-type.
  typedef int (*FuncType)(int, int);

  // Using asmjit_cast is purely optional, it's basically a C-style cast
  // that tries to make it visible that a function-type is returned.
  FuncType func = asmjit_cast<FuncType>(funcPtr);

  // Finally, run it and do something with the result...
  int x = func(1, 2);
  printf("x=%d\n", x); // Outputs "x=3".

  // The function will remain in memory after Compiler is destroyed, but
  // will be destroyed together with Runtime. This is just simple example
  // where we can just destroy both at the end of the scope and that's it.
  // However, it's a good practice to clean-up resources after they are
  // not needed and using runtime.release() is the preferred way to free
  // a function added to JitRuntime.
  runtime.release((void*)func);

  // Runtime and Compiler will be destroyed at the end of the scope.
  return 0;
}

 2.6, Keystone

Keystone y Capstone son la misma serie de motores, desarrollados por el mismo mantenedor. Capstone es el principal responsable del desmontaje de conjuntos de múltiples instrucciones multiplataforma y Keystone es el principal responsable de la compilación de conjuntos de múltiples instrucciones multiplataforma. Al igual que el ensamblador de 0llyDbg, Keystone solo admite el ensamblaje de texto y no admite el ensamblaje funcional como AsmJit.

Keystone también se trasplanta de una parte del componente MC en el marco LLVM, por lo que las arquitecturas de CPU admitidas por LLVM también son compatibles con Keystone. Las arquitecturas de CPU admitidas por Keystone incluyen ARM, ARM64 (AArch64/ARMv8), HexagonMIPS, PowerPC, SPARC y Systemzx86 (incluyendo 16 bits, 32 bits y 64 bits).

 2.7 Resumen

También hay motores de desmontaje de nicho como XDELDsm. El código de XDE es pequeño y flexible, y a muchos programas pequeños les gusta usarlo. También vale la pena mencionar un motor de desensamblaje de longitud en Blackbone. El nombre es "Ldasm". De hecho, no es un motor porque tiene una sola función, y su función es solo calcular la longitud de una instrucción, pero es muy Útil en la instrucción de salto de reubicación de Hook. Funciona.

El siguiente es un análisis comparativo de tres motores de desmontaje de uso común, Udis86BeaEngine y Capstone.

  • Rendimiento: Udis86>BeaEngine>Capstone.
  • Capacidad de decodificación: Capstone> BeaEngine> Udis86 (Udis86 no admite el análisis de registros y otras capacidades de decodificación son similares).
  • Soporte de plataforma: Capstone>Udis86; Udis86=BeaEngine.
  • Conjunto de instrucciones ampliadas x86: Capstone>Udis86;Udis86=BeaEnginea

Supongo que te gusta

Origin blog.csdn.net/qq_22903531/article/details/131412809
Recomendado
Clasificación