PDA

Ver la Versión Completa : Problemas con CloseHandle y atacheo de proceso


aguml
07-05-2020, 12:27:59
Buenas, estoy modificando la clase que tengo creada para depurar aplicaciones y si creo el proceso a depurar con CreateProcess no tengo problemas pero al atachearme al proceso tengo el problema de que no puedo obtener la información de la estructura PROCESS_INFORMATION y cuando quiero terminar el proceso uso CloseHandle y ahí me explota en la cara. También uso TerminateProcess y tampoco funciona. Os adjunto la parte del código necesaria:
void __fastcall THiloDebugger::Execute()
{
DEBUG_EVENT DebugEv;
HANDLE CurrentExceptionThread;
DWORD dwContinueStatus;
int Error;
TDll *ItemDLL;
bool salir=false;

ListaBPs = new TList;
ListaDlls = new TList;
ListaThreads = new TList;

Synchronize(OnInitLoopDebugThread); //Usaremos este evento para inizialización de variables en la clase usuario si se requiere.

si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
// El proceso se tiene que crear en la misma función donde está el hilo del depurador sino no vale
if(Atached){
if(!AtachProcessByNameWindow(WindowName.c_str(),Error))
return;
}else{
CreateProcess(PathFile.c_str(),NULL, NULL, NULL, FALSE, DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
}

InfoProcess.hProcess = pi.hProcess;
InfoProcess.ProcessID = pi.dwProcessId;

do{
if (WaitForDebugEvent(&DebugEv,1) == true)
{
if(TerminateDebugger == false){
// Paró por depuración
// Tomamos el contexto del hilo que generó el evento
CurrentExceptionThread = GetHandleThread(DebugEv.dwThreadId);
DWORD actual;
if(CurrentExceptionThread != NULL){
con.ContextFlags= CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(CurrentExceptionThread, &con);
}

switch(DebugEv.dwDebugEventCode)
{
case EXIT_PROCESS_DEBUG_EVENT:
// llamamos a funciones dentro del Hilo para evitar código espaqueti
// estas funciones no requieren del syncronice
dwContinueStatus = OnExitProcessDebugEventThread(&DebugEv.u.ExitProcess);
salir = true;
break;

case CREATE_PROCESS_DEBUG_EVENT:
// Carga del proceso en el depurador
CurrentExceptionThread = DebugEv.u.CreateProcessInfo.hThread;
con.ContextFlags= CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(CurrentExceptionThread, &con);
dwContinueStatus = OnCreateProcessDebugEventThread(&DebugEv.u.CreateProcessInfo, DebugEv.dwThreadId);
break;

case EXCEPTION_DEBUG_EVENT:
// Excepciones y BPs
LastExceptionAddress = (DWORD)DebugEv.u.Exception.ExceptionRecord.ExceptionAddress;
ExceptionCode = DebugEv.u.Exception.ExceptionRecord.ExceptionCode;

switch(ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
dwContinueStatus = OnBreakpointDebugEventThread(LastExceptionAddress);
break;

case EXCEPTION_SINGLE_STEP: // Aqui se gestionan los HW hay que crear otro Callback
dwContinueStatus = OnSingleStepEventThread(&DebugEv.u.Exception);
break;

case EXCEPTION_GUARD_PAGE_VIOLATION:
dwContinueStatus = OnExceptionGuardPageEventThread(&DebugEv.u.Exception);
break;

case EXCEPTION_ACCESS_VIOLATION:
//Esto es para controlar los MemoryBPs
//primero tengo que ver como funciona este
//tipo de bps
dwContinueStatus = OnExceptionGuardPageEventThread(&DebugEv.u.Exception);
break;

case EXCEPTION_INVALID_HANDLE:
//Aqui gestiono cuando CloseHandle use un handle invalido
dwContinueStatus = OnExceptionInvalidHandleEventThread(&DebugEv.u.Exception);
break;

default:
dwContinueStatus = OnExceptionDefault(DebugEv.dwDebugEventCode,LastExceptionAddress);
}
break;

case CREATE_THREAD_DEBUG_EVENT:
// Parada por creacion de hilos
dwContinueStatus = OnCreateThreadDebugEventThread(&DebugEv.u.CreateThread,DebugEv.dwThreadId);
break;

case EXIT_THREAD_DEBUG_EVENT:
// Parada por destrucción de hilos
dwContinueStatus =OnExitThreadDebugEventThread(&DebugEv.u.ExitThread,(DWORD)DebugEv.dwThreadId);
break;

case LOAD_DLL_DEBUG_EVENT:
// Parada por carga de dll
dwContinueStatus =OnLoadDllDebugEventThread(&DebugEv.u.LoadDll);
break;

case UNLOAD_DLL_DEBUG_EVENT:
// liberación de dll
dwContinueStatus =OnUnloadDllDebugEventThread(&DebugEv.u.UnloadDll);
break;

case OUTPUT_DEBUG_STRING_EVENT:
// Envío de cadenas al depurador
dwContinueStatus = OnOutputDebugStringEventThread(&DebugEv.u.DebugString);
break;

case RIP_EVENT:
// system debugging error ?? ni idea que es esto
dwContinueStatus = OnRipEventThread(&DebugEv.u.RipInfo);
break;

default:
// evento desconocido
dwContinueStatus=DBG_EXCEPTION_NOT_HANDLED;

}

if(CurrentExceptionThread != NULL){
SetThreadContext(CurrentExceptionThread, &con);
}

ContinueDebugEvent(DebugEv.dwProcessId,DebugEv.dwThreadId,dwContinueStatus);
if(Detach_Debugger == true){
DebugActiveProcessStop(pi.dwProcessId);
salir = true;
}
}
else{ // TerminateDebugger == true
DebugActiveProcessStop(pi.dwProcessId);
TerminateProcess(pi.hProcess,0);
salir = true;
}
}
else
{
// Paro por tiempo
if(TerminateDebugger == true)
{
DebugActiveProcessStop(pi.dwProcessId);
TerminateProcess(pi.hProcess,0);
salir= true;
}
}
}while(salir == false);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

Synchronize(OnExitLoopDebugThread);

for(int x=0; x != ListaBPs->Count;)
{
delete ListaBPs->Items[x];
ListaBPs->Delete(x);
}
delete ListaBPs;
ListaBPs = NULL;


for(int x=0; x != ListaThreads->Count;)
{
delete ListaThreads->Items[x];
ListaThreads->Delete(x);
}
delete ListaThreads;
ListaThreads = NULL;

for(int x=0; x != ListaDlls->Count;)
{
ItemDLL = (TDll *)ListaDlls->Items[x];
for (int i = 0; i < ItemDLL->APIs->Count;) {
delete ItemDLL->APIs->Items[i];
ItemDLL->APIs->Delete(i);
}
delete ListaDlls->Items[x];
ListaDlls->Delete(x);
}
delete ListaDlls;
ListaDlls = NULL;
}
//---------------------------------------------------------------------------

bool THiloDebugger::AtachProcessByNameWindow(char *wName,int &Error)
{
HWND HParent;
DWORD ProcessId;
DWORD ThreadId;
int retval=false;

HParent=FindWindow(NULL,wName);
if(HParent){
ThreadId=GetWindowThreadProcessId(HParent,&ProcessId);
if(ThreadId){
if(DebugActiveProcess(ProcessId)){
pi.dwProcessId=ProcessId;
pi.dwThreadId=ThreadId;
pi.hProcess=HParent;
retval=true;
Error=0;
}else{
Error=-1;
}
}else{
Error=-2;
}
}else{
Error=-3;
}
return retval;
}
¿Alguien me puede ayudar?
Gracias por adelantado.

aguml
07-05-2020, 13:32:51
Casi lo solucioné así pero no se si será la mejor solución:
bool THiloDebugger::AtachProcessByNameWindow(char *wName,int &Error)
{
HWND HParent;
DWORD ProcessId;
DWORD ThreadId;
int retval=false;

HParent=FindWindow(NULL,wName);
if(HParent){
ThreadId=GetWindowThreadProcessId(HParent,&ProcessId);
if(ThreadId){
if(DebugActiveProcess(ProcessId)){

pi.dwThreadId=ThreadId;
pi.hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, ProcessId);
pi.dwProcessId=ProcessId;
retval=true;
Error=0;

}else{
Error=-1;
}
}else{
Error=-2;
}
}else{
Error=-3;
}
return retval;
}
Con esto ya obtengo el Handle del proceso atacheado pero me sigue faltando el pi.hThread. ¿como puedo obtenerlo? No da error pero estoy haciendo un CloseHandle(NULL) porque es lo que pale al salir del depurado porque pi.hThread no la he inicializado con el valor y vale NULL.

aguml
07-05-2020, 13:54:27
Lo he solucionado así:
bool THiloDebugger::AtachProcessByNameWindow(char *wName,int &Error)
{
HWND HParent;
DWORD ProcessId;
DWORD ThreadId;
int retval=false;

HParent=FindWindow(NULL,wName);
if(HParent){
ThreadId=GetWindowThreadProcessId(HParent,&ProcessId);
if(ThreadId){
if(DebugActiveProcess(ProcessId)){

pi.dwThreadId=ThreadId;
pi.hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, ProcessId);
pi.hThread = OpenThread( THREAD_QUERY_INFORMATION | THREAD_TERMINATE, FALSE, ThreadId);
pi.dwProcessId=ProcessId;
retval=true;
Error=0;

}else{
Error=-1;
}
}else{
Error=-2;
}
}else{
Error=-3;
}
return retval;
}
Con esto ya obtengo el Handle del proceso atacheado y el del thread y aparentemente funciona todo ok. ¿está bien la solución?

aguml
07-05-2020, 15:04:01
Amigos ahora estoy con una variante pero que en vez del nombre de la ventana trabaje con el pid del proceso y tengo esto:
bool THiloDebugger::AtachProcessById(int id,int &Error)
{
DWORD ThreadId;
int retval=false;

//ThreadId=GetWindowThreadId(HParent,&ProcessId);
if(ThreadId)
{
if(DebugActiveProcess(id)){
pi.dwThreadId=ThreadId;
pi.hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, id);
pi.hThread = OpenThread( THREAD_QUERY_INFORMATION | THREAD_TERMINATE, FALSE, ThreadId);
pi.dwProcessId=id;
retval=true;
Error=0;
}else{
Error=-1;
}
}else{
Error=-2;
}
return retval;
}
El problema es que para hacerlo así necesito el hwnd de la ventana y no puedo usar FindWindow porque se supone que no tengo el titulo de la ventana y que lo hago con el pid. ¿como podria solucionarlo?