Hola amigos, tengo un problemilla, estoy con una pequeña tool la cual usa trucos antidebug y funcionaba muy bien pero el caso es que para las detecciones por tiempo tenia un Sleep el cual me congelaba el formulario por lo que he decidido meterlo en un hilo y ahí empezaron todos mis problemas.
La cabecera la tengo así:
Código PHP:
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *ButtonPEB;
TMemo *MemoPEB;
TCheckBox *CheckBox1;
void __fastcall FormCreate(TObject *Sender);
void __fastcall ButtonPEBClick(TObject *Sender);
private: // User declarations
typedef struct _PEB_Protection{
UCHAR BeingDebugger;
UCHAR NTGlobalFlag;
UCHAR ProcessHeapFlags;
UCHAR ProcessHeapForceFlags;
}PEB_Protection;
typedef struct _Return_Detection{
WideString BeingDebugger;
WideString NTGlobalFlag;
WideString ProcessHeapFlags;
WideString ProcessHeapForceFlags;
WideString DebugPort;
WideString NtSetInformationThread;
WideString CloseHandleWithInvalidHandle;
WideString GetTickCount;
WideString timeGetTime;
WideString QueryPerformanceCounter;
WideString OutputDebugString;
}Return_Detection;
void __fastcall CheckDebug(void);
void __fastcall ObtenerDatosPEB(PEB_Protection *Peb_Protection);
void __fastcall QueryDetectionPEB(PEB_Protection *Peb_Protection, Return_Detection *Detection);
WideString __fastcall QueryDebugPortDetection(void);
WideString __fastcall QueryNtSetInformationThread(void);
bool __stdcall ObjectListCheck(Return_Detection *Detection);
WideString __fastcall CheckOutputDebugString(void);
public: // User declarations
DWORD TimeInitGTC, TimeEndGTC; //Para truco con GetTickCount
DWORD TimeInitTGT, TimeEndTGT; //Para truco con timeGetTime
__int64 TimeInitQPC=0, TimeEndQPC=0, frec=0; //Para truco con QueryPerformanceCounter
Return_Detection *Deteccion;
class TMyThread : public TThread
{
private:
void __fastcall ShowMessages();
protected:
virtual void __fastcall Execute();
public:
__fastcall TMyThread(bool CreateSuspended);
void __fastcall ObtainStringsTimes(void);
void __fastcall ShowMessagesTimes(void);
};
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Y el .cpp:
Código PHP:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <Windows.h>
#include <Mmsystem.h>
#include <winnt.h>
#pragma hdrstop
#include "Unit1.h"
#define ObjectAllInformation 3
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ObtenerDatosPEB(PEB_Protection *Peb_Protection)
{
DWORD64 PEB;
DWORD64 read;
DWORD64 dwBeingDebugger, dwNTGlobalFlag, dwProcessHeapFlags, dwProcessHeapForceFlags;
//Obtengo el PEB
__asm
{
mov rax, gs:[0x60];
mov PEB, rax;
}
//Obtenemos el valor de BeingDebugger
dwBeingDebugger = PEB+0x2;
ReadProcessMemory(GetCurrentProcess(),(LPVOID)dwBeingDebugger,&Peb_Protection->BeingDebugger ,sizeof(Peb_Protection->BeingDebugger),(DWORD64*)&read);
//Obtenemos el valor de NtGlobalFlag
dwNTGlobalFlag = PEB+0xBC;
ReadProcessMemory(GetCurrentProcess(),(LPVOID)dwNTGlobalFlag,&Peb_Protection->NTGlobalFlag,sizeof(Peb_Protection->NTGlobalFlag),(DWORD64*)&read);
//Obtenemos el valor de ProcessHeapFlags
ReadProcessMemory(GetCurrentProcess(),(LPVOID)(PEB+0x30),&dwProcessHeapFlags ,sizeof(dwProcessHeapFlags),(DWORD64*)&read);
dwProcessHeapFlags += 0x70;
ReadProcessMemory(GetCurrentProcess(),(LPVOID)(dwProcessHeapFlags),&Peb_Protection->ProcessHeapFlags ,sizeof(Peb_Protection->ProcessHeapFlags),(DWORD64*)&read);
//Obtenemos el valor de ProcessHeapForceFlags
ReadProcessMemory(GetCurrentProcess(),(LPVOID)(PEB+0x30),&dwProcessHeapForceFlags ,sizeof(dwProcessHeapForceFlags),(DWORD64*)&read);
dwProcessHeapForceFlags += 0x74;
ReadProcessMemory(GetCurrentProcess(),(LPVOID)(dwProcessHeapForceFlags),&Peb_Protection->ProcessHeapForceFlags ,sizeof(Peb_Protection->ProcessHeapForceFlags),(DWORD64*)&read);
}
//---------------------------------------------------------------------------
WideString __fastcall TForm1::QueryDebugPortDetection(void)
{
ULONG ProcessDebugPort = 7;
DWORD read;
HMODULE NtDll;
ULONG status;
WideString retval;
NtDll = LoadLibrary(L"ntdll.dll");
LONG (WINAPI *NtQueryInformationProcess)(HANDLE ProcessHandle, ULONG ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength);
*(FARPROC *)&NtQueryInformationProcess = GetProcAddress(NtDll, "NtQueryInformationProcess");
HANDLE DebugPort;
status = NtQueryInformationProcess(GetCurrentProcess(), ProcessDebugPort, &DebugPort, sizeof(DebugPort), &read);
if(DebugPort)
{
retval = "DebugPort te ha detectado.";
}
else
{
retval = "DebugPort no te ha detectado.";
}
return retval;
}
//---------------------------------------------------------------------------
WideString __fastcall TForm1::QueryNtSetInformationThread(void)
{
HMODULE NtDll;
ULONG status;
WideString retval;
int ThreadHideFromDebugger = 0x11;
DWORD ThreadInfo;
NtDll = LoadLibrary(L"ntdll.dll");
LONG (WINAPI *NtSetInformationThread)(HANDLE ThreadHandle, ULONG ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength);
*(FARPROC *)&NtSetInformationThread = GetProcAddress(NtDll, "NtSetInformationThread");
status = NtSetInformationThread(GetCurrentThread(),ThreadHideFromDebugger,0,0);
if(status == 0)
{
retval = "NtSetInformationThread pasado con éxito.";
}else{
retval = "NtSetInformationThread nos ha desatacheado.";
}
return retval;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::QueryDetectionPEB(PEB_Protection *Peb_Protection, Return_Detection *Detection)
{
ObtenerDatosPEB(Peb_Protection);
if(Peb_Protection->BeingDebugger == 0x1)
{
Detection->BeingDebugger = "BeingDebugger te ha detectado.";
}else{
Detection->BeingDebugger = "BeingDebugger no te ha detectado.";
}
if(Peb_Protection->NTGlobalFlag == 0x70)
{
Detection->NTGlobalFlag = "NtGlobalFlag te ha detectado.";
}else{
Detection->NTGlobalFlag = "NtGlobalFlag no te ha detectado.";
}
if(Peb_Protection->ProcessHeapFlags != 2)
{
Detection->ProcessHeapFlags = "ProcessHeapFlags te ha detectado.";
}else{
Detection->ProcessHeapFlags = "ProcessHeapFlags no te ha detectado.";
}
if(Peb_Protection->ProcessHeapForceFlags != 0)
{
Detection->ProcessHeapForceFlags = "ProcessHeapForceFlags te ha detectado.";
}else{
Detection->ProcessHeapForceFlags = "ProcessHeapForceFlags no te ha detectado.";
}
}
//---------------------------------------------------------------------------
WideString __fastcall TForm1::CheckOutputDebugString(void)
{
wchar_t lpOutputString[]=L"Hello Debugger!";
char outputDebugStringBuffer[1000] = {0};
WideString retval;
WideCharToMultiByte(CP_ACP, 0, lpOutputString, -1, outputDebugStringBuffer, sizeof(outputDebugStringBuffer), 0, 0);
ULONG_PTR args[4];
//unicode
args[0] = (ULONG_PTR)wcslen(lpOutputString) + 1;
args[1] = (ULONG_PTR)lpOutputString;
//ansi for compatibility
args[2] = (ULONG_PTR)wcslen(lpOutputString) + 1;
args[3] = (ULONG_PTR)outputDebugStringBuffer;
__try
{
RaiseException(0x4001000A, 0, 4, args);//DBG_PRINTEXCEPTION_WIDE_C
retval = "Debugger detectado con OutputDebugString.";
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
retval = "Debugger no detectado con OutputDebugString.";
}
return retval;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
CheckDebug();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::CheckDebug(void)
{
PEB_Protection *ProtectPeb= new(PEB_Protection);
Deteccion = new(Return_Detection);
HANDLE hTrucho = (HANDLE)1234; //Para truco con CloseHandle
TMyThread *hilo = (TMyThread*) new TThread(true);
QueryPerformanceCounter((LARGE_INTEGER*)&TimeInitQPC); //Obtenemos el tiempo inicial con QueryPerformanceCounter
TimeInitTGT = timeGetTime();
TimeInitGTC = GetTickCount(); //Obtenemos el tiempo inicial con GetTickCount
if(ProtectPeb != NULL && Deteccion != NULL)
{
Deteccion->CloseHandleWithInvalidHandle = "No detectado por CloseHandle con un handle inválido.";
__try{
CloseHandle(hTrucho);
}
__except(EXCEPTION_EXECUTE_HANDLER){
Deteccion->CloseHandleWithInvalidHandle = "Detectado por CloseHandle con un handle inválido.";
}
QueryDetectionPEB(ProtectPeb, Deteccion);
Deteccion->DebugPort = QueryDebugPortDetection();
//Deteccion->NtSetInformationThread = QueryNtSetInformationThread();
Deteccion->OutputDebugString = CheckOutputDebugString();
//Mostramos los datos
MemoPEB->Lines->Clear();
MemoPEB->Lines->Add(Deteccion->BeingDebugger + " Resultado = 0x"+AnsiString(IntToHex((int)ProtectPeb->BeingDebugger,2)));
MemoPEB->Lines->Add(Deteccion->NTGlobalFlag + " Resultado = 0x"+AnsiString(IntToHex((int)ProtectPeb->NTGlobalFlag,2)));
MemoPEB->Lines->Add(Deteccion->ProcessHeapFlags + " Resultado = 0x"+AnsiString(IntToHex((int)ProtectPeb->ProcessHeapFlags,2)));
MemoPEB->Lines->Add(Deteccion->ProcessHeapForceFlags + " Resultado = 0x"+AnsiString(IntToHex((int)ProtectPeb->ProcessHeapForceFlags,2)));
MemoPEB->Lines->Add(Deteccion->DebugPort);
MemoPEB->Lines->Add(Deteccion->CloseHandleWithInvalidHandle);
MemoPEB->Lines->Add(Deteccion->NtSetInformationThread);
MemoPEB->Lines->Add(Deteccion->OutputDebugString);
}
if(CheckBox1->Checked == true)
hilo->Resume();
else{
hilo->ObtainStringsTimes(); //Obtengo los resultados
hilo->ShowMessagesTimes(); //Muestro los resultados
delete ProtectPeb;
delete Deteccion;
}
}
//---------------------------------------------------------------------------
__fastcall TMyThread::TMyThread(bool CreateSuspended): TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::ShowMessagesTimes()
{
//Mostramos si nos ha detectado con GetTickCount o no y posicionamos al inicio el TMEMO
MemoPEB->Lines->Add(Deteccion->GetTickCount);
MemoPEB->Lines->Add(Deteccion->timeGetTime);
MemoPEB->Lines->Add(Deteccion->QueryPerformanceCounter);
MemoPEB->SelStart=0;
MemoPEB->SelLength = 0;
MemoPEB->Perform(EM_SCROLLCARET, 0,(__int64) 0);
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::ObtainStringsTimes()
{
TimeEndGTC = GetTickCount(); //Obtenemos el tiempo final con GetTickCount
TimeEndTGT = timeGetTime(); //Obtenemos el tiempo final con timeGetTime
QueryPerformanceCounter((LARGE_INTEGER*)&TimeEndQPC); //Obtenemos el tiempo final con QueryPerformanceCounter
//Obtenemos la frecuencia
QueryPerformanceFrequency((LARGE_INTEGER*)&frec);
//Aqui comprobamos que el tiempo transcurrido no pase de 2 segundos en milisegundos
if((TimeEndGTC - TimeInitGTC) > 2000)
{
Deteccion->GetTickCount = "Detectado con método GetTickCount.";
}else{
Deteccion->GetTickCount = "No detectado con método GetTickCount.";
}
//Aqui comprobamos que el tiempo transcurrido usando timeGetTime no pase de 2 segundos en milisegundos
if((TimeEndTGT - TimeInitTGT) > 2000)
{
Deteccion->timeGetTime = "Detectado con método timeGetTime.";
}else{
Deteccion->timeGetTime = "No detectado con método timeGetTime.";
}
//Aqui comprobamos que el tiempo transcurrido usando QueryPerformanceCounter no pase de 2 segundos en milisegundos
if((TimeEndQPC - TimeInitQPC)/(frec/1000) > 2000)
{
Deteccion->QueryPerformanceCounter = "Detectado con método QueryPerformanceCounter.";
}else{
Deteccion->QueryPerformanceCounter = "No detectado con método QueryPerformanceCounter.";
}
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::Execute()
{
Sleep(3000); //Necesario para comprobar si nos detectan por tiempo aunque asi nos detecte siempre
ObtainStringsTimes();
Synchronize(ShowMessages);
delete ProtectPeb;
delete Deteccion;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonPEBClick(TObject *Sender)
{
CheckDebug();
}
//---------------------------------------------------------------------------
Y esto chilla por todas partes, sobre todo con las declaraciones de los metodos de la clase del hilo que no se como se tienen que declarar cuando están anidadas y tambien falla al intentar crear el hilo.
Código:
[bcc64 Error] Unit1.cpp(185): allocating an object of abstract class type 'System::Classes::TThread'
System.Classes.hpp(2624): unimplemented pure virtual method 'Execute' in 'TThread'
[bcc64 Error] Unit1.cpp(231): use of undeclared identifier 'TMyThread'
[bcc64 Error] Unit1.cpp(231): C++ requires a type specifier for all declarations
[bcc64 Error] Unit1.cpp(231): only constructors take base initializers
[bcc64 Error] Unit1.cpp(237): expected a class or namespace
[bcc64 Error] Unit1.cpp(249): expected a class or namespace
[bcc64 Error] Unit1.cpp(285): expected a class or namespace