Encontrar la funcion main en un binario

Iniciado por Usuario887, 26 Mayo 2020, 17:27 PM

0 Miembros y 1 Visitante están viendo este tema.

Usuario887

Hola,

Estaba practicando con un hackme que programe. Precisamente el desbordamiento de pila; puedo enviarle el payload y el codigo por mensaje privado a quien le interese.
En resumen, tarde un buen rato buscando la funcion main en el binario resultante. De hecho, en el codigo fuente integre ciertas instrucciones en ensamblador (inutiles) que luego utilice como una 'firma' de la funcion para luego buscar la cadena con el depurador (llamenme novato).
Mi pregunta es: ¿existe una manera mas, digamos, eficiente de encontrarla?

Saludos.



Edito: Se me acaba de ocurrir una buena manera. Si a alguien le interesa, pues lo mismo. :)
Sin embargo me gustaria leer sus opiniones, igualmente.

fary

Un byte a la izquierda.

Usuario887

Cita de: fary en  1 Junio 2020, 07:30 AM
Como buscaste la función main?
Lo se... demasiado facil para preguntarse. La expectativa brota de tu mensaje como el veneno del colmillo, pero me refiero a medios manuales.

Este es el codigo del programa de prueba:
#include <stdio.h>
#include <string.h>

int main ()
{
    int i;
    char bPassword[BUFSIZ];
    const char *password=
    "p2u4ingr9pnqeofig2-94rm8g[nqeifggp2u45gn230p89e";
   
    printf ("introduzca la contrasena: ");
    fflush (stdin);
    gets (bPassword); 

    if (strcmp (bPassword, password))
    {
        printf ("\r\naccess denied.");
        return 0;
    }
       
    else
        printf ("\r\naccess granted.");

    printf ("\r\n\r\nuser name\tpassword");
    printf (    "\r\n---- ----\t--------");

    for (i=0;i<5;i++) printf ("\r\n%c%c%c\t\t%c%c%c",
    i+33,i+33,i+33,i+1+33,i+1+33,i+1+33);

    return 0xffff;
}


Mi pregunta hace referencia a un ejecutable cuyo codigo fuente no posees. Pero para introducirte mejor en el contexto, ahi esta  :rolleyes:.

Si se ejecuta el programa, puedes ver que evidetemente una cadena de caracteres esta siendo impresa en el buffer de salida estandar:



La impresion puede ser parte del algoritmo de una funcion o de la funcion principal. En el primer caso seria una cuestion de perseguir los retornos con el depurador hasta dar con ella. Sin embargo este caso es el segundo.

Para encontrar la funcion, se me ocurrio primero buscar la RVA de la cadena. Lo hice asi con DEBUG (si, es modo real y son 16 bits, pero no avanzo hasta pisar bien):


(si, ademas es un COM)

Ahora la pregunta que te haces en este punto es: ¿de donde viene la funcion que imprime los caracteres?
La funcion, cual sea, tendra que hacer referencia a la cadena que esta siendo impresa, localizada en 24FCh. y ¿cual es la unica forma en la que (un programador normal, que yo la verdad no soy tan normal...) se haria esto? Utilizando su RVA como parametro, es decir, poniendola en la pila. Un compilador corriente lo haria asi:

Código (asm) [Seleccionar]
MOV AX, 24FCh
PUSH AX


La codificacion de MOV AX, 24FCh es B8 FC 24. Por tanto hay que buscarlo:



Luego basta con analizar el codigo maquina en busca de la logica de una funcion principal.


fary

Si lo quieres hacer desde depurador es la primera función que se muestra al cargar el ejecutable.

Si lo quieres hacer desde código, lee sobre el formato PE.

https://foro.elhacker.net/analisis_y_diseno_de_malware/formato_pe-t446963.0.html

IMAGE_OPTIONAL_HEADER   -> AddressOfEntryPoint

https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_optional_header32

saludos.
Un byte a la izquierda.

ThunderCls

@fary
AddressOfEntryPoint y la direccion de inicio de la funcion "main" son dos cosas diferentes, el primero no tiene porque ser necesariamente el segundo (y casi nunca lo es).

@marax
Con IDA y Ghidra es muy sencillo localizar la funcion main en el listado de funciones.
Por otra parte si lo quieres manualmente, como ya mencionaste, localizando referencias en instrucciones a cadenas dentro del ejecutable es una forma muy utilizada para localizar zonas de codigo y funciones en general. Tambien puedes hacer "stalk walking" en el caso que lo estes depurando, o incluso puedes usar ciertas llamadas a funciones como guia para llevarte a la funcion main, la cual casi siempre esta algunas lineas mas abajo de estas. En este caso entre las que serian usadas con mas probabilidad tienes "kernel32.GetCommandLineX", "kernel32.GetEnvironemStringX" o si usa los runtimes de c++ "__getmainargs" y "__p__environ", finalmente "kernel32.ExitProcess" o "_cexit" probablemente te pueden llevar justo unas instrucciones despues de la salida de la funcion main

Saludos
-[ "...I can only show you the door. You're the one that has to walk through it." – Morpheus (The Matrix) ]-
http://reversec0de.wordpress.com
https://github.com/ThunderCls/

Usuario887

Cita de: ThunderCls en  3 Junio 2020, 17:56 PM
localizando referencias en instrucciones a cadenas dentro del ejecutable es una forma muy utilizada para localizar zonas de codigo y funciones en general.
No se si alegrarme de redescubrir la rueda... en la comunidad hacker parece moralmente ilegal.

Cita de: ThunderCls en  3 Junio 2020, 17:56 PM
finalmente "kernel32.ExitProcess" o "_cexit"
Esto es realmente mas logico y eficiente que lo que yo estaba haciendo. Leerlo se sintio como una epifania.

Muchas gracias por tu ayuda.