📄 debugger.pas.svn-base
字号:
unit Debugger;
//just my place to play with all kinds of threading methods
//when i find out the best suited method I'll use that....
interface
uses Classes,windows,sysutils,cefuncproc,Messages,forms,SyncObjs,
dialogs,controls,Graphics,NewKernelHandler,symbolhandler,StrUtils
{$ifndef net}
,undochanges,assemblerunit,addressparser //handled in the client version or not at all
{$endif}
{$ifdef netserver}
,unit1
,idtcpserver
{$endif};
const reg0set= $3; //(00000000000000000000000000000011)
reg1set= $C; //(00000000000000000000000000001100)
reg2set= $30; //(00000000000000000000000000110000)
reg3set= $c0; //(00000000000000000000000011000000)
debugexact= $300;
gd_flag= $2000; //(00000000000000000010000000000000)
reg0w= $10000; //(00000000000000010000000000000000)
reg0rw= $30000; //(00000000000000110000000000000000)
reg0len2=$40000; //(00000000000001000000000000000000)
reg0len4=$c0000; //(00000000000011000000000000000000)
reg1w= $100000; //(00000000000100000000000000000000)
reg1rw= $300000; //(00000000001100000000000000000000)
reg1len2=$400000; //(00000000010000000000000000000000)
reg1len4=$c00000; //(00000000110000000000000000000000)
reg2w= $1000000; //(00000001000000000000000000000000)
reg2rw= $3000000; //(00000011000000000000000000000000)
reg2len2=$4000000; //(00000100000000000000000000000000)
reg2len4=$c000000; //(00001100000000000000000000000000)
reg3w= $10000000; //(00010000000000000000000000000000)
reg3rw= $30000000; //(00110000000000000000000000000000)
reg3len2=$40000000; //(01000000000000000000000000000000)
reg3len4=$c0000000; //(11000000000000000000000000000000)
reg0len0=0;
reg1len0=0;
reg2len0=0;
reg3len0=0;
type TReadonly = record
pagebase: dword;
pagesize: dword;
Address: dword;
size: integer;
originalprotection: dword;
end;
type tThreadEntry=record
threadHandle: thandle;
address: dword;
end;
type Process=record
ProcessID: dword;
running: boolean;
end;
type tbreakpoint = record
address:dword;
originalbyte: byte;
end;
type tregistermodificationBP=record
address:dword; //addres to break on
change_eax:boolean;
change_ebx:boolean;
change_ecx:boolean;
change_edx:boolean;
change_esi:boolean;
change_edi:boolean;
change_ebp:boolean;
change_esp:boolean;
change_eip:boolean;
change_cf:boolean;
change_pf:boolean;
change_af:boolean;
change_zf:boolean;
change_sf:boolean;
change_of:boolean;
new_eax:dword;
new_ebx:dword;
new_ecx:dword;
new_edx:dword;
new_esi:dword;
new_edi:dword;
new_ebp:dword;
new_esp:dword;
new_eip:dword;
new_cf:boolean;
new_pf:boolean;
new_af:boolean;
new_zf:boolean;
new_sf:boolean;
new_of:boolean;
end;
type PRegisterModificationBP=^TRegisterModificationBP;
type TNewProcedureData=record
processid: dword;
processhandle: dword;
filehandle: dword;
EntryPoint: dword;
OriginalEntryByte: byte;
DotNet: boolean;
FirstBreak: boolean;
end;
type TDebugger = class(TThread)
private
originalbyte: byte;
filename: String;
parameters: string;
CreateAProcess: boolean;
OpenProcessID: Thandle;
AddressFound: Dword;
HideDebugger: boolean;
HandleBreakpoints: boolean;
CanUseDebugRegs: boolean;
createdusingprocesswindow:boolean;
CurrentProcess: integer;
{$ifdef netserver}
coderecords: array of dword;
{$endif}
procedure addtochangeslist;
procedure ProcessCreated;
procedure RestoreNTOpenProcess;
procedure ResetBreakpoint;
procedure SetSingleStepping(Threadid: dword);
procedure AddDebugString;
function injectcode(AddressOfEntryPoint:dword;processhandle:thandle):dword;
function handledebuggerplugins(devent:PDebugEvent):integer;
procedure tracersync;
function tracer(devent: _Debug_EVENT):boolean;
public
//semaphore: THandle;
Processes: array of process;
Newprocesses: array of TNewProcedureData;
pausedthreadhandle: thandle;
running: boolean;
continueprocess: boolean;
continuehow: integer;
DRRegs: _CONTEXT;
FindWriter2: boolean;
attaching: boolean;
attached: boolean;
context: _CONTEXT;
debugging: boolean;
stepping: boolean;
HowToContinue: integer;
removed: boolean;
readonly: TReadonly;
readonlyset: boolean;
readonlyremoved: boolean;
findreaderset: boolean;
findreader: TReadOnly;
findreaderremoved:boolean;
alsowrites: boolean;
breakpointset: boolean;
breakpointaddress: dword;
lastbreakpoint: dword;
temps: string;
whattodo: integer; //ignore, continue, showwindow etc....
userisdebugging: boolean;
userbreakpoints: array of dword;
registermodificationBPs: array of tregistermodificationBP;
int3userbreakpoints: array of tbreakpoint;
int3CEBreakpoint: TBreakpoint;
threadlist: array of array [0..4] of dword;
threadinfo: array of dword;
testje: string;
breakpointlistsection: TCriticalSection;
threadentrys: array of tThreadEntry;
traceaddress: dword;
tracecount: integer;
Constructor MyCreate(filenm: String);
Constructor MyCreate2(processID: THandle);
destructor Destroy; override;
procedure Execute; override;
procedure Debuginfo;
procedure Updateregisters;
procedure FoundOne;
procedure RemoveBreakpoint;
procedure suspendallthreads;
procedure resumeallthreads;
end;
type TDbgUIDebugActiveProcess = function(processhandle:THandle):boolean; stdcall;
type TDebugBreakProcess = function(processhandle:THandle):boolean; stdcall;
type TDebugActiveProcessStop= function(pid: dword):boolean; stdcall;
type TDebugSetProcessKillOnExit=function(KillOnExit: boolean):boolean; stdcall;
type TIsDebuggerPresent=function:boolean; stdcall;
type TntSuspendProcess=function(ProcessID:Dword):DWORD; stdcall;
type TntResumeProcess=function(ProcessID:Dword):DWORD; stdcall;
type
TProcessBasicInformation = record
ExitStatus : Longint;
PebBaseAddress : Pointer;
AffinityMask : DWORD;
BasePriority : Longint;
UniqueProcessId : DWORD;
InheritedFromUniqueProcessId : DWORD
end;
TProcessInfoClass=(
ProcessBasicInformation,ProcessQuotaLimits,ProcessIoCounters,ProcessVmCounters,ProcessTimes,
ProcessBasePriority,ProcessRaisePriority,ProcessDebugPort,ProcessExceptionPort,ProcessAccessToken,
ProcessLdtInformation,ProcessLdtSize,ProcessDefaultHardErrorMode,ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,ProcessWorkingSetWatch,ProcessUserModeIOPL,ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,ProcessWx86Information,ProcessHandleCount,ProcessAffinityMask,ProcessPriorityBoost,
ProcessDeviceMap,ProcessSessionInformation,ProcessForegroundInformation,ProcessWow64Information,
MaxProcessInfoClass);
type TNtQueryInformationProcess=function(
Handle : THandle;
infoClass : TProcessInfoClass;
processInformation : Pointer;
processInformationLength : ULONG;
returnLength : PULONG
) : DWORD; stdcall;
var DebuggerThread: TDebugger;
Semaphore: Thandle;
DbgUIDebugActiveProcess:TDbgUIDebugActiveProcess;
DebugBreakProcess:TDebugBreakProcess;
DebugActiveProcessStop:TDebugActiveProcessStop;
DebugSetProcessKillOnExit:TDebugSetProcessKillOnExit;
IsDebuggerPresent:TIsDebuggerPresent;
ntSuspendProcess: TntSuspendProcess;
ntResumeProcess: tntResumeProcess;
NtQueryInformationProcess: TNtQueryInformationProcess;
IsDebuggerPresentLocation:dword;
DbgBreakPointLocation:dword;
krn: thandle;
ntdlllib: thandle;
CRDebugging: TCriticalSection;
function startdebuggerifneeded: boolean; overload;
function startdebuggerifneeded(ask:boolean): boolean; overload;
function breakthread(threadhandle: thandle):boolean;
function DebugActiveProcessStopProstitute(x: dword): boolean;
function ToggleBreakpoint(address:dword):boolean;
implementation
uses {$ifndef net}Mainunit,Memorybrowserformunit,{$endif}disassembler{$ifndef net},frmTracerUnit,foundcodeunit,debugger2,advancedoptionsunit,formChangedAddresses,frmstacktraceunit,frmThreadlistunit,formdebugstringsunit,formsettingsunit,processwindowunit,plugin,frmCreatedProcessListUnit{$endif};
function ToggleBreakpoint(address:dword):boolean;
{$ifndef net}
procedure setbreakpoints;
var i: integer;
begin
with debuggerthread do
begin
//set the debug breakpoint
suspend;
DRRegs.ContextFlags:=CONTEXT_DEBUG_REGISTERS;
DRRegs.Dr7:=reg0set or reg1set or reg2set or reg3set;
DRRegs.Dr0:=0;
drregs.dr1:=0;
drregs.dr2:=0;
for i:=0 to length(userbreakpoints)-1 do
begin
if i=0 then DRRegs.Dr0:=userbreakpoints[0] else
if i=1 then DRRegs.Dr1:=userbreakpoints[1] else
if i=2 then DRRegs.Dr2:=userbreakpoints[2];
end;
for i:=0 to length(threadlist)-1 do
begin
suspendthread(debuggerthread.threadlist[i][1]);
setthreadcontext(debuggerthread.threadlist[i][1],debuggerthread.DRRegs);
resumethread(debuggerthread.threadlist[i][1]);
end;
Resume;
end;
end;
var i,j,k: integer;
a,original,written: dword;
int3: byte;
{$endif}
begin
{$ifndef net}
result:=false;
if foundcodedialog<>nil then
raise exception.Create('I can''t do that! You are currently using one of the code finder options, please, stop it first');
if debuggerthread2<>nil then
begin
for i:=0 to 3 do
begin
if debuggerthread2.breakpoints[i]=address then
begin
outputdebugstring('Going to disable this changereg breakpoint');
if debuggerthread2.breakpointchanges[i].address<>0 then
begin
StopRegisterChange(i);
debuggerthread2.breakpointchanges[i].address:=0;
end;
debuggerthread2.breakpoints[i]:=0;
debuggerthread2.setbreakpoints;
memorybrowser.updatebplist;
result:=false;
for j:=0 to 3 do
if debuggerthread2.breakpoints[j]<>0 then
begin
result:=true;
break;
end;
if not result then freeandnil(debuggerthread2);
exit;
end;
end;
end;
if not startdebuggerifneeded then exit;
int3:=$cc;
//still here so the debugger has been attached to the process or i've fucked up again
with debuggerthread do
begin
try
WaitForSingleObject(semaphore,infinite);
userisdebugging:=true;
if formsettings.rbDebugAsBreakpoint.checked then
begin
//try to see if it already is in the list
for i:=0 to length(userbreakpoints)-1 do
if userbreakpoints[i]=address then
begin
//if it is then remove the breakpoint
for j:=i to length(userbreakpoints)-2 do
userbreakpoints[j]:=userbreakpoints[j+1];
setlength(userbreakpoints,length(userbreakpoints)-1);
//also remove the registermodificationBP
for j:=0 to length(debuggerthread.registermodificationBPs)-1 do
if registermodificationBPs[j].address=address then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -