Pregunta:
En IDA, ¿hay alguna forma de agregar una referencia a una función importada dinámicamente en la pestaña Importaciones?
0xC0000022L
2013-05-29 21:04:24 UTC
view on stackexchange narkive permalink

El título dice la mayor parte. Supongamos que tengo un binario de Windows PE (x86, 32 bits) (solo para que tengamos un caso para discutir), la lista de importaciones generalmente solo mostrará las importaciones que se encuentran en el directorio de importación. Los atributos que muestra son la dirección de la función, el nombre y la biblioteca desde la que se importó, como se muestra en este fragmento de captura de pantalla:

Screenshot of import tab in IDA Pro

¿Hay alguna forma para mí a través de scripts (IDC o Python, no me importa demasiado), para agregar mis propias importaciones a la lista y, por ejemplo, hacer que apunten (el atributo de dirección) a un código como este (línea resaltada)?:

Dynamically imported function in IDA Pro

Es decir en tal caso, la línea se vería así:

  0DCBA987 GetLongPathNameW kernel32.dll  

o incluso simplemente

  0DCBA987 GetLongPathNameW ???  

asumiendo que la llamada GetProcAddress anterior estaría en la dirección 0DCBA987.

La ventaja para mí sería legibilidad. Pero también produciría una lista más completa de importaciones (y en consecuencia xrefs) ya que algunas funciones se importan dinámicamente con frecuencia debido a su disponibilidad en las distintas versiones de Windows.

Debería ser bastante trivial dado un cierto binario averigüe todas las referencias externas a las funciones candidatas que recuperan la dirección de la función importada (como GetProcAddress ) y luego recorra sus llamadas para encontrar qué función se importó. La parte DLL puede ser más complicada de averiguar, pero se puede dejar vacía o ingresar manualmente. Pero no encontré una función que me permitiera agregar importaciones. ¿Hay alguna forma?

Pregunta interesante, que sería útil al analizar un programa desde un volcado de memoria. Tener la capacidad de editar las importaciones agregaría referencias cruzadas y facilitaría el análisis.
Si no lo ha visto, consulte [reiat.py] (https://bitbucket.org/Alexander_Hanel/reiat/src/). Hace la mayor parte de lo que discutiste, excepto agregar a las pestañas de importación.
@alexanderh: no lo había hecho, aunque vi algunos de los otros repositorios que tienes en Bitbucket antes. ¿Tiene alguna idea de cómo hacer ese último paso?
@0xC0000022L No, no lo hago. Intentaré intentarlo este fin de semana. Mi correo electrónico está en el código fuente. No dude en enviar la muestra por correo electrónico si puede compartirla. Nota al margen estúpida, el comentario "GetLongPathNameW" se puede utilizar para recopilar referencias cruzadas no comentadas mediante la tecla de acceso rápido X. No es útil para el análisis automatizado, pero sigue siendo útil.
Puede intentar actualizar `import_node` (exportado desde nalt.hpp del SDK), pero no está claro si IDA vuelve a leer esos` netnode` cada vez que vuelve a dibujar la lista de importaciones.
Si no puede agregar algo a la pestaña de importaciones, puede escribir la pestaña de importaciones por su cuenta, es bastante fácil. ¿Será esa solución suficientemente satisfactoria?
Tres respuestas:
#1
+13
NirIzr
2013-05-31 22:15:56 UTC
view on stackexchange narkive permalink

No sé si mucha gente lo sabe, pero IDA utiliza algún tipo de truco para decidir si un segmento es un segmento de importación y lo maneja de manera completamente diferente.

IDA usa algunos segmentos propiedades para tratar un segmento como un segmento de importaciones. por ejemplo, nombrar un segmento .idata , o establecer la clase del segmento en XTRN lo convertirá inmediatamente en un segmento de importación. dichos segmentos no mostrarán los listados habituales de código / datos, definiciones de funciones y la mayoría de las otras cosas a las que estamos acostumbrados en la Vista de código.

Más específicamente, agregar código a esos segmentos se ocultará en IDA, que se negará a mostrar cualquier conjunto en esos segmentos. Un buen truco Anti-IDA diría :)

En su lugar, solo mostrarán definiciones de nombres, compensaciones y comentarios. Una vez que se asigna a una compensación un nombre de una API almacenada en la base de datos de IDA, IDA obtenga el prototipo de la API y otra información, asigne la definición de tipo y los comentarios.

IIRC Estas API también se mostrarán en la ventana de importaciones pero no estoy seguro de qué es exactamente lo que desencadena esto. también podría depender de las versiones IDA y otras propiedades de PE relacionadas con la importación.

EDITAR
Han pasado más de tres años y, obviamente, no pude encontrar el script entonces, y acabo de repasar un código antiguo mío y pude reconstruir lo que hice en ese script, y aquí está la esencia:

  import idaapiimport idcfor import_rva, import_name in LIST_OF_IMPORTS: ea = imagebase + import_rva if idaapi.get_segm_class (getseg (ea)) == "XTRN": print ("la importación ya está dentro de un segmento XTRN," "asumiendo que tiene el nombre correcto") continuar elif idaapi.get_segm_class (getseg (ea-1 )) == "XTRN": print ("La importación está justo debajo de un segmento de importación", "extendiendo el segmento para incluir esta importación adicional") # reduciendo su segmento actual # ADVERTENCIA: esto supone que la importación actual está en la parte superior de su segmento
# de lo contrario tendremos que DIVIDIR el segmento actual de la importación # y a eso digo CBA también conocido como dejado como ejercicio para el lector idaapi.set_segm_start (ea, SegStart (ea) +4, 0) # expandiendo su nuevo segmento idaapi.set_segm_end (ea-1, SegEnd (ea-1) +4, 0) else: print ("Creando un nuevo segmento para importar") idc.AddSeg (ea, ea + 4, 0, 1, 4, 0) idc.SetSegClass ( ea, "XTRN") # cambio de nombre de importación a nombre de API. Esto hará que IDA agregue información de tipo # y comentarios automáticos para cualquier función que esté # familiarizada con idc.MakeName (ea, import_name) # Haciendo un desplazamiento para que IDA lo muestre como una importación en lugar de # ocultarlo idc.MakeDword (ea)  
@Nirlzr: por supuesto, tendría curiosidad por ver esta respuesta desarrollada un poco. Gracias.
@Nirlzr: ¿alguna noticia relacionada con el script mencionado?
@0xC0000022L: ¡Lo siento mucho! Actualmente estoy en servicio de reserva y no puedo acceder a las cosas que tengo en el trabajo. no lo olvidé.
@0xC0000022L Sé que ha pasado mucho tiempo (y eso es un eufemismo), pero he editado mi respuesta para incluir el guión)
#2
+8
blabb
2015-03-25 04:28:05 UTC
view on stackexchange narkive permalink

si agregar una sección de importación adicional al archivo PE es una opción aceptable

use herramientas como iidking y agregue una sección de importación con todas las importaciones que se resuelvan dinámicamente

use add diálogo de referencias cruzadas o idc add_dref () para agregar referencias cruzadas a ellos

código para demostración

  #include <stdio.h> # include <windows.h> # pragma comment (lib "user32.lib") DWORD (WINAPI * MyGetShortPathName) (LPCTSTR, LPTSTR, DWORD); int main (void) {MessageBox (NULL, "testing add import", "Test", MB_OK); char modname [MAX_PATH] = {0}; GetModuleFileName (NULL, modname, MAX_PATH); printf ("% s \ n", modname); HMODULE hMod = LoadLibrary ("kernel32.dll"); if (hMod) {* (FARPROC *) &MyGetShortPathName = GetProcAddress (hMod, "GetShortPathNameA"); if (MyGetShortPathName) {MyGetShortPathName (modname, modname, MAX_PATH); printf ("% s \ n", modname); }} return 0;}  

compilado y ejecutado

  C: \ codesnips \ addimp \ addimp.exeC: \ CODESN ~ 1 \ addimp \ addimp. exe  

importaciones sin modificar

  00412000 GetCurrentThread KERNEL32 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX00412130 MessageBoxA USER32 

exe modificado con iidking y una importación GetShort agregado en la sección de importación adicional

  C: \ codesnips \ addimp>fc / b addimp.exe modaddimp.exe Comparando archivos addimp.exe y MODADDIMP.EXE000000E6: 04 05 no de la sección 00000131: 90 A0 00000160: F4 0000000161: 47 9000000164: 3C 5000000278: 00 2E .00000279: 00 49 I0000027A: 00 49 I0000027B: 00 44 D0000027C: 00 4B K0000027D: 00 69 I0000027E: 00 6E N0000027F: 00 67 G00000281: 00 02 vs tamaño 0000000286: 00 0100000289: 00 020000028D: 00 5E0000028E: 00 010000029C: 00 200000029F: 00 E0  

ida importa ventana copiar pegar de exe modificado

  00412000 GetCurrentThread KERNEL32 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX00412130 MessageBoxA USER32 00419058 GetShortPathNameA kernel32  

doble clic en vista abierta -> referirse a subferencias abiertas ->

  Up P sub_401000 + 89 llame ds: GetProcAddress (data xref)  

o comando idc

  add_dref (0x401089,0x419058,53 ); AddCodeXref (0x419058,0x401089,53);  

AddImports

compilar estas tres líneas en un complemento agregará la importación deseada en la importación del primer módulo

  void idaapi run (int) {nodeidx_t index = import_node.alt1st (); unsigned long value = import_node.altval (index); netnode (value) .supset (0x410004, "GetShortPathNameA \ 0" );}  

el archivo idc para crear el segmento

  #include <idc.idc>static main () {auto addr; addr = 0x410000; SegCreate (addr, añadir r + 0x200,0,1,3,2); SetSegmentType (addr, SEG_XTRN); MakeDword (addr + 4); MakeName (addr + 4, "GetShortPathNameA");}  

abrir un exe / ejecutar idc / plugin / cerrar y guardar la base de datos / reabrir la base de datos para ver las importaciones agregadas en la pestaña de importaciones del primer módulo

editar
windows -> restablecer el escritorio funciona de la misma manera que cerrar y abrir la base de datos para eliminar el cierre y la apertura de la base de datos

¡Gracias por la respuesta! Desafortunadamente, esto no funcionará para algunos ejecutables descomprimidos o cuando se trate de código independiente de la posición.
¿Puede elaborar o publicar / señalar una muestra en la que esto no parece funcionar?
Podría estar equivocado, pero su ejemplo no funcionaría en muestras a las que les falta el encabezado ejecutable portátil. Ejemplos de estos serían shellcode, DLL inyectados que ponen a cero el encabezado o código independiente de posición (sin encabezado y resuelve la dirección de símbolos atravesando PEB para kernel32.dll). Claro, se podría agregar un encabezado PE, pero este no siempre es un enfoque factible porque se basa en tener y modificar el binario.
Si está convencido del razonamiento, estoy de acuerdo con eso, pero mi proceso de pensamiento es así, si ida tiene suficiente información para recuperar y crear las importaciones originales, entonces también debería ser capaz de encontrar esto. la consulta original parecía implicar que el pe está disponible y no dijo nada sobre la no disponibilidad del pe original, así que publiqué este enfoque con una advertencia si la modificación del exe es aceptable si sus nuevos requisitos son sobre mucking con un idb standlaone entonces no tengo ni idea
Entiendo su proceso de pensamiento, pero todavía no responde cómo agregar las importaciones a la pestaña de importación a través de IDC o Python en IDA. Cuál es la solicitud original. Echa un vistazo a la respuesta de NirIzr, es la más cercana.
actualizó la respuesta con una solución alternativa para los archivos idb
No puedo verificar el código en este momento, pero como la recompensa está a punto de caducar, se la otorgaré. Gracias por la actualización.
#3
+5
w s
2015-03-25 21:50:36 UTC
view on stackexchange narkive permalink

Si no puede agregar algo al visor de importaciones, puede escribir el suyo propio. Aquí está el ejemplo simple (es un ejemplo ligeramente modificado al que se hace referencia en esta entrada de hexblog y se encuentra aquí con funcionalidad de doble clic agregada, columnas agregadas, exportaciones eliminadas y error corregido para un caso de origen desconocido de la función importada). Consulte la función BuildImports para crear importaciones adicionales (manual_func1 y manual_func2)

  import idaapiimport idautilsfrom idaapi import PluginFormfrom PySide import QtGui, QtCoreclass ImpExpForm_t (PluginForm): def importaciones ord_names_cb (self, ea, name) : self.items.append ((ea, '' if not name else name, ord)) # True -> Continuar enumeración return True def BuildImports (self): tree = {} nimps = idaapi.get_import_module_qty () para i en xrange (0, nimps): name = idaapi.get_import_module_name (i) si no es name: name = "unknown" # Crear una lista de nombres importados self.items = [] # Enumerar las entradas importadas en este módulo idaapi.enum_import_names (i, self .imports_names_cb) si el nombre no está en el árbol: árbol [nombre] = [] árbol [nombre] .extend (self.items) árbol ["manualmente_added"] = [(0x01, "manual_func1", 3), (0x02, "manual_ func2 ", 4)] return tree def PopulateTree (self): # Borrar elementos anteriores self.tree.clear () # Construir importaciones root = QtGui.QTreeWidgetItem (self.tree) root.setText (0," Importaciones ") para dll_name , imp_entries en self.BuildImports (). items (): imp_dll = QtGui.QTreeWidgetItem (root) imp_dll.setText (0, dll_name) para imp_ea, imp_name, imp_ord en imp_entries: item = QtGui.QTreeWidgetItem (imp_Textll () elemento. 0, "% s"% imp_name) item.setText (1, "0x% 08x"% imp_ea) item.setText (2, "0x% 08x"% imp_ord) def dblclick (self, item):
try: idaapi.jumpto (int (item.text (1) .encode ("ascii", "ignore"), 16)) excepto: print "No se puede saltar" def OnCreate (self, form): "" "Llamado cuando se crea el formulario del complemento "" "# Obtener el widget principal self.parent = self.FormToPySideWidget (formulario) # Crear control de árbol self.tree = QtGui.QTreeWidget () self.tree.setColumnCount (4) self.tree.setHeaderLabels (( "Nombres", "Dirección", "Ordinal", "Fuente")) self.tree.itemDoubleClicked.connect (self.dblclick) self.tree.setColumnWidth (0, 100) # Crear diseño de diseño = QtGui.QVBoxLayout () diseño .addWidget (self.tree) self.PopulateTree () # Populate PluginForm self.parent.setLayout (layout) def OnClose (self, form): "" "Llamado cuando el formulario del plugin está cerrado" "" global ImpExpForm del ImpExpForm print " Cerrado "def Show (self):" "" Crea el formulario no se crea o se enfoca si era "" "return PluginForm.Show (self," Visor de importaciones / exportaciones ", opciones = PluginForm.FORM_PERSIST) # ---------------------- -------------------------------------------------- --def main (): Global ImpExpForm try: ImpExpForm excepto: ImpExpForm = ImpExpForm_t () ImpExpForm.Show () # ------------------------- -------------------------------------------------principal ()  
Gracias, he utilizado el enfoque de visor antes. Un problema que encontré es que una vez que el BID se cierra, el visor y los datos desaparecen. Sería genial encontrar algo un poco más permanente.
Puede utilizar OnClose para guardar los datos, por ejemplo. Requerirá un poco más de desarrollo, pero aún es fácil
En general, tiene algunas alternativas mejores. En primer lugar, puede almacenar el script en sí en la ventana del script (Archivo -> El comando Script tiene una interfaz para eso); esto le permitirá mantener todas sus últimas adiciones con el idb. También puede usar OnClose y almacenar sus datos en un archivo con un nombre derivado del nombre del idb que se puede obtener mediante idautils.GetIdbPath. También puede almacenar los datos en el nodo personalizado del idb.


Esta pregunta y respuesta fue traducida automáticamente del idioma inglés.El contenido original está disponible en stackexchange, a quien agradecemos la licencia cc by-sa 3.0 bajo la que se distribuye.
Loading...