aguml |
22-01-2015 12:43:48 |
Peticion de revision de metodos
Hola amigos, ya tengo implementado los metodos de mi clase para depuración y me va genial pero me gustaria que vieran esas funciones a ver que opinan:
En el "public" del TDebugger.cpp puse estos métodos:
Código PHP:
bool __fastcall InsertDLL(char *DllName, int NameDllLength); bool __fastcall DeleteDLL(void *hLibModule);
Y en el "private":
Código PHP:
TList *ListapMemoriaAuxDllsInyectadas, *ListapMemoriaAuxDllsALiberar, *ListaBPsLoadDll, *ListaBPsUnloadDll, *ListaBackupEIPOnLoadDll, *ListaBackupEIPOnUnloadDll; unsigned long *pLoadDLL, *pUnloadDLL, *BPLoadDll, *BPUnloadDll, *BackupEIPOnLoadDll, *BackupEIPOnUnloadDll;
Funcion que inserta el codigo para cargar la dll:
Código PHP:
bool __fastcall TDebugger::InsertDLL(char *DllName, int NameDllLength) { BYTE LoadDLL[] = {0x60, 0x68, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x61, 0x90}; bool ret = false; LPTHREAD_START_ROUTINE hLib; unsigned long pNameDll, pDirCall;
//Obtengo memoria para los punteros que irán a las listas pLoadDLL = new (std::nothrow)unsigned long; BPLoadDll = new (std::nothrow)unsigned long; BackupEIPOnLoadDll = new (std::nothrow)unsigned long;
if(pLoadDLL == NULL || BPLoadDll == NULL || BackupEIPOnLoadDll == NULL) { //Si hubo algun problema if(pLoadDLL != NULL){ //Si se obtuvo memoria para esta, la libero delete pLoadDLL; } if(BPLoadDll == NULL){ //Si se obtuvo memoria para esta, la libero delete BPLoadDll; } if(BackupEIPOnLoadDll == NULL){ //Si se obtuvo memoria para esta, la libero delete BackupEIPOnLoadDll; } }else{ //Si no hubo error try{ ListapMemoriaAuxDllsInyectadas->Add(pLoadDLL); //Añado la nueva direccion allocada a la lista de inyecciones ListaBPsLoadDll->Add(BPLoadDll); //Añado el nuevo BP de salida a la lista de BPs de salida ListaBackupEIPOnLoadDll->Add(BackupEIPOnLoadDll); //Añado la nueva direccion al nuevo EIP de retorno
// Localizo memoria en el espacio de direcciones de la víctima *pLoadDLL = (unsigned long)VirtualAllocEx((HANDLE)GetHProcess(), NULL, (sizeof(LoadDLL) + NameDllLength + 1), MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if(*pLoadDLL){ //Si se obtuvo memoria pNameDll = *pLoadDLL + sizeof(LoadDLL); //Calculo la direccion donde se escribirá el nombre de la dll hLib = (LPTHREAD_START_ROUTINE)GetAddressAPIByName("Kernel32.dll", "LoadLibraryA"); //Obtengo el puntero a la api LoadLibraryA
if(hLib){ //Si se obtuvo correctamente la direccion de LoadLibraryA pDirCall = (unsigned long)hLib - (*pLoadDLL + 6 + 5); //Calculo el valor a escribir para que el call apunte a esa api
if(WriteMemory(*pLoadDLL, LoadDLL, sizeof(LoadDLL))){ //Escribo el inline cargador en bruto if(WriteMemory(pNameDll, DllName, NameDllLength)){ //Escribo el path de la dll if(WriteMemory(*pLoadDLL + 2, &pNameDll, sizeof(pNameDll))){ //Sobreescribo el push redirigiendolo a la direccion donde está el path if(WriteMemory(*pLoadDLL + 7, &pDirCall, sizeof(pDirCall))){ //Sobreescribo el call redirigiendolo al LoadLibraryA *BPLoadDll = *pLoadDLL + 12; //Calculo la direccion donde se colocará el BP de retorno if(SetBP(*BPLoadDll)){ //Coloco un BP detras del POPAD del codigo injertado //Si llego hasta aqui es porque todo salió bien asi que cambio el valor de retorno ret = true; *BackupEIPOnLoadDll = GetEIP(); //Obtengo la direccion actual de EIP y la guardo para poder restaurarla cuando caiga en el BP SetEIP(*pLoadDLL); //Cambio EIP a la direccion donde he escrito el codigo de carga de dll } } } } } } } }catch(...){ ret = false; }
if(ret == false && *pLoadDLL != NULL){ //Si hubo algun problema //Libero la memoria allocada VirtualFreeEx((HANDLE)GetHProcess(), (void*)*pLoadDLL, 0, MEM_RELEASE); // Libero memoria
//Elimino la direccion donde se obtuvo la memoria de la lista ListapMemoriaAuxDllsInyectadas->Delete(ListapMemoriaAuxDllsInyectadas->Count - 1); delete pLoadDLL;
//Elimino la direccion del bp donde tendria que parar al cargar la dll de la lista ListaBPsLoadDll->Delete(ListaBPsLoadDll->Count - 1); delete BPLoadDll;
//Elimino la direccion EIP donde retornaria al parar en el bp de la lista ListaBackupEIPOnLoadDll->Delete(ListaBackupEIPOnLoadDll->Count - 1); delete BackupEIPOnLoadDll; } } return ret; }
Funcion que inserta el codigo necesario para liberar una dll:
Código PHP:
bool __fastcall TDebugger::DeleteDLL(void *hLibModule) { BYTE UnloadDLL[] = {0x60, 0x68, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x61, 0x90}; bool ret = false; LPTHREAD_START_ROUTINE hLib; unsigned long pDirCall;
//Obtengo memoria para los punteros que irán a las listas pUnloadDLL = new (std::nothrow)unsigned long; BPUnloadDll = new (std::nothrow)unsigned long; BackupEIPOnUnloadDll = new (std::nothrow)unsigned long;
if(pUnloadDLL == NULL || BPUnloadDll == NULL || BackupEIPOnUnloadDll == NULL) { //Si hubo algun problema if(pUnloadDLL != NULL){ //Si se obtuvo memoria para esta, la libero delete pUnloadDLL; } if(BPUnloadDll == NULL){ //Si se obtuvo memoria para esta, la libero delete BPUnloadDll; } if(BackupEIPOnUnloadDll == NULL){ //Si se obtuvo memoria para esta, la libero delete BackupEIPOnUnloadDll; } }else{ //Si no hubo error try{ ListapMemoriaAuxDllsALiberar->Add(pUnloadDLL); //Añado la nueva direccion allocada a la lista de liberaciones ListaBPsUnloadDll->Add(BPUnloadDll); //Añado el nuevo BP de salida a la lista de BPs de salida ListaBackupEIPOnUnloadDll->Add(BackupEIPOnUnloadDll); //Añado la nueva direccion al nuevo EIP de retorno
// Localizo memoria en el espacio de direcciones de la víctima *pUnloadDLL = (unsigned long)VirtualAllocEx((HANDLE)GetHProcess(), NULL, sizeof(UnloadDLL), MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if(*pUnloadDLL){ //Si se obtuvo memoria hLib = (LPTHREAD_START_ROUTINE)GetAddressAPIByName("Kernel32.dll", "FreeLibrary"); //Obtengo el puntero a la api FreeLibrary
if(hLib){ //Si se obtuvo correctamente la direccion de FreeLibrary pDirCall = (unsigned long)hLib - (*pUnloadDLL + 6 + 5); //Calculo el valor a escribir para que el call apunte a esa api
if(WriteMemory(*pUnloadDLL, UnloadDLL, sizeof(UnloadDLL))){ //Escribo el inline descargador en bruto if(WriteMemory(*pUnloadDLL + 2, &hLibModule, sizeof(hLibModule))){ //Sobreescribo el valor del push cambiandolo por el hModule de la dll a descargar if(WriteMemory(*pUnloadDLL + 7, &pDirCall, sizeof(pDirCall))){ //Sobreescribo el call redirigiendolo al FreeLibrary *BPUnloadDll = *pUnloadDLL + 12; //Calculo la direccion donde se colocará el BP de retorno if(SetBP(*BPUnloadDll)){ //Coloco un BP detras del POPAD del codigo injertado //Si llego hasta aqui es porque todo salió bien asi que cambio el valor de retorno ret = true; *BackupEIPOnUnloadDll = GetEIP(); //Obtengo la direccion actual de EIP y la guardo para poder restaurarla cuando caiga en el BP SetEIP(*pUnloadDLL); //Cambio EIP a la direccion donde he escrito el codigo de descarga de dll } } } } } } }catch(...){ ret = false; }
if(ret == false && *pUnloadDLL != NULL){ //Si hubo algun problema //Libero la memoria allocada VirtualFreeEx((HANDLE)GetHProcess(), (void*)*pUnloadDLL, 0, MEM_RELEASE); // Libero memoria
//Elimino la direccion donde se obtuvo la memoria de la lista ListapMemoriaAuxDllsALiberar->Delete(ListapMemoriaAuxDllsALiberar->Count - 1); delete pUnloadDLL;
//Elimino la direccion del bp donde tendria que parar al liberar la dll de la lista ListaBPsUnloadDll->Delete(ListaBPsUnloadDll->Count - 1); delete BPUnloadDll;
//Elimino la direccion EIP donde retornaria al parar en el bp de la lista ListaBackupEIPOnUnloadDll->Delete(ListaBackupEIPOnUnloadDll->Count - 1); delete BackupEIPOnUnloadDll; } } return ret; }
Funcion modificada de gestion de los BPs:
Código PHP:
void __fastcall TDebugger::OnBreakpointDebugEvent(DWORD address) { bool IsLoadDll = false, IsUnloadDll = false; //Estas dos variables son necesarias para saber si esta en una de las dos listas int index; //Esta variable es necesaria para trabajar con el elemento de la lista oportuna unsigned long *pItemLista; //Este es un puntero auxiliar que uso para trabajar con los items de las listas try{ //Busco el valor de address en la lista de BPs de carga de dlls for (index = 0; index < ListaBPsLoadDll->Count; index++){ pItemLista = (unsigned long*)ListaBPsLoadDll->List[index]; if((unsigned long)*pItemLista == address){ //Si coinciden es porque ha parado al cargar la dll indicada IsLoadDll = true; //Indico que se ha ejecutado ese codigo que carga la dll break; } } if(!IsLoadDll){ //Si no se encontró en la lista de carga de dlls //Busco el valor de address en la lista de BPs de liberación de dlls for (index = 0; index < ListaBPsUnloadDll->Count; index++){ pItemLista = (unsigned long*)ListaBPsUnloadDll->List[index]; if((unsigned long)*pItemLista == address){ //Si coinciden es porque ha parado al liberar la dll indicada IsUnloadDll = true; //Indico que se ha ejecutado ese codigo que libera la dll break; } } }
if(IsLoadDll == true) { //Si se encontró la direccion el la lista de bps de carga de dlls RemoveBP((unsigned long)*pItemLista); //Desinstalo ese BP delete ListaBPsLoadDll->List[index]; //Libero la memoria que almacena la direccion en la lista de bps de carga de dlls ListaBPsLoadDll->Delete(index); //Elimino ese elemento de la lista de bps de carga de dlls
pItemLista = (unsigned long*)ListaBackupEIPOnLoadDll->List[index]; SetEIP((unsigned long)*pItemLista); //Restauro la direccion de EIP delete ListaBackupEIPOnLoadDll->List[index]; //Libero la memoria que almacena la direccion en la lista de direcciones EIP ListaBackupEIPOnLoadDll->Delete(index); //Elimino ese elemento de la lista de direcciones EIP
pItemLista = (unsigned long*)ListapMemoriaAuxDllsInyectadas->List[index]; VirtualFreeEx((HANDLE)GetHProcess(), (void*)*pItemLista, 0, MEM_RELEASE); // Libero la memoria solicitada para esa carga de dll delete ListapMemoriaAuxDllsInyectadas->List[index]; //Libero la memoria que almacena la direccion de la memoria solicitada para la carga de la dll ListapMemoriaAuxDllsInyectadas->Delete(index); //Elimino ese elemento de la lista de direcciones de memorias allocadas } else if(IsUnloadDll == true) { //Si se encontró la direccion el la lista de bps de carga de dlls RemoveBP((unsigned long)*pItemLista); //Desinstalo ese BP delete ListaBPsUnloadDll->List[index]; //Libero la memoria que almacena la direccion en la lista de bps de liberación de dlls ListaBPsUnloadDll->Delete(index); //Elimino ese elemento de la lista de bps de liberación de dlls
pItemLista = (unsigned long*)ListaBackupEIPOnUnloadDll->List[index]; SetEIP((unsigned long)*pItemLista); //Restauro la direccion de EIP delete ListaBackupEIPOnUnloadDll->List[index]; //Libero la memoria que almacena la direccion en la lista de direcciones EIP ListaBackupEIPOnUnloadDll->Delete(index); //Elimino ese elemento de la lista de direcciones EIP
pItemLista = (unsigned long*)ListapMemoriaAuxDllsALiberar->List[index]; VirtualFreeEx((HANDLE)GetHProcess(), (void*)*pItemLista, 0, MEM_RELEASE); // Libero la memoria solicitada para esa liberacion de dll delete ListapMemoriaAuxDllsALiberar->List[index]; //Libero la memoria que almacena la direccion de la memoria solicitada para la liberación de la dll ListapMemoriaAuxDllsALiberar->Delete(index); //Elimino ese elemento de la lista de direcciones de memorias allocadas }else if(FuncBPs != NULL){ //Si no está en ninguna de las dos listas anteriores y existe una funcion para gestionar los BPs FuncBPs(address); //Ejecutamos la funcion de gestion de BPs } }catch(...){ } }
Luego para probarla hago esto en mi Unit1.cpp:
Variables globales:
Código PHP:
AnsiString dllInyectada = "DLLHack.dll"; void *hDllHack = NULL;
Funcion para gestionar el evento OnEntryPoint:
Código PHP:
void __fastcall TFormMain::OnEntryPoint(DWORD Address) { bool error = !Depurador->InsertDLL(dllInyectada.c_str(),dllInyectada.Length()); }
Al cargarse las dlls voy buscando la que intento cargar y cuando la encuentro asigno los punteros a las funciones deseadas: void __fastcall TFormMain::OnLoadDll(LOAD_DLL_DEBUG_INFO *info) { if(info->lpImageName != NULL) { unsigned long dir; AnsiString nombre;
//Obtenemos la direccion del puntero al path de la dll cargada Depurador->ReadMemory((unsigned long)info->lpImageName,sizeof(dir),&dir, sizeof(dir));
//Obtenemos el path completo de la dll if(info->fUnicode != 0){ WideString aux = Depurador->ReadUnicodeString(dir, 0); nombre = aux; }else{ nombre = Depurador->ReadString(dir, 0); }
//Obtenemos el nombre de la dll nombre = ExtractFileName(nombre);
//No se porque pero si hago "if(nombre == dllInyectada)" aunque sean iguales no entra nunca pero con strcmp si entra if(strcmp(nombre.c_str(), dllInyectada.c_str())== 0) { //Si es nuestra dll hDllHack = info->lpBaseOfDll; //Necesario para poder liberar la dll cuando queramos
//Obtengo los punteros de las funciones deseadas pCopySelecteds = (LPTHREAD_START_ROUTINE)Depurador->GetAddressAPIByName("DLLHack.dll", "CopySelecteds"); pPaste = (LPTHREAD_START_ROUTINE)Depurador->GetAddressAPIByName("DLLHack.dll", "Paste"); pCopyAll = (LPTHREAD_START_ROUTINE)Depurador->GetAddressAPIByName("DLLHack.dll", "CopyAll"); pSaveImageToFile = (LPTHREAD_START_ROUTINE)Depurador->GetAddressAPIByName("DLLHack.dll", "SaveImageToFile"); pCopyImageToClipboard = (LPTHREAD_START_ROUTINE)Depurador->GetAddressAPIByName("DLLHack.dll", "CopyImageToClipboard"); pSaveFile = (LPTHREAD_START_ROUTINE)Depurador->GetAddressAPIByName("DLLHack.dll", "SaveFile"); } } }
Las siguientes dos lineas tendria que ponerlas en el evento donde quiera liberar la dll:
Código PHP:
Depurador->DeleteDLL(hDllHack); hDllHack = NULL;
Si veis algo incorrecto por favor indicadmelo y ademas tengo la duda de por qué no funciona la comparacion que comento en el evento OnLoad que a ver si podeis aclararme por qué falla de una manera y no de la otra.
Gracias por adelantado.
|