PDA

Ver la Versión Completa : Peticion de revision de metodos


aguml
22-01-2015, 12:43:48
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:
bool __fastcall InsertDLL(char *DllName, int NameDllLength);
bool __fastcall DeleteDLL(void *hLibModule);Y en el "private":
TList *ListapMemoriaAuxDllsInyectadas, *ListapMemoriaAuxDllsALiberar, *ListaBPsLoadDll, *ListaBPsUnloadDll, *ListaBackupEIPOnLoadDll, *ListaBackupEIPOnUnloadDll;
unsigned long *pLoadDLL, *pUnloadDLL, *BPLoadDll, *BPUnloadDll, *BackupEIPOnLoadDll, *BackupEIPOnUnloadDll;
Funcion que inserta el codigo para cargar la dll:
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:
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:
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:
AnsiString dllInyectada = "DLLHack.dll";
void *hDllHack = NULL;Funcion para gestionar el evento OnEntryPoint:
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:
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.