1
0
Fork 0
x64dbg/x64_dbg_dbg/debugger_commands.cpp

1639 lines
49 KiB
C++

#include "debugger_commands.h"
#include "debugger.h"
#include "console.h"
#include "value.h"
#include "thread.h"
#include "memory.h"
#include "threading.h"
#include "variable.h"
#include "argument.h"
#include "plugin_loader.h"
#include "simplescript.h"
#include "symbolinfo.h"
static bool bScyllaLoaded = false;
CMDRESULT cbDebugInit(int argc, char* argv[])
{
if(DbgIsDebugging())
DbgCmdExecDirect("stop");
static char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, false))
return STATUS_ERROR;
if(!FileExists(arg1))
{
dputs("file does not exist!");
return STATUS_ERROR;
}
HANDLE hFile = CreateFileA(arg1, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(hFile == INVALID_HANDLE_VALUE)
{
dputs("could not open file!");
return STATUS_ERROR;
}
GetFileNameFromHandle(hFile, arg1); //get full path of the file
CloseHandle(hFile);
//do some basic checks
switch(GetFileArchitecture(arg1))
{
case invalid:
dputs("invalid PE file!");
return STATUS_ERROR;
#ifdef _WIN64
case x32:
dputs("use x32_dbg to debug this file!");
#else //x86
case x64:
dputs("use x64_dbg to debug this file!");
#endif //_WIN64
return STATUS_ERROR;
default:
break;
}
static char arg2[deflen] = "";
argget(*argv, arg2, 1, true);
char* commandline = 0;
if(strlen(arg2))
commandline = arg2;
char arg3[deflen] = "";
argget(*argv, arg3, 2, true);
static char currentfolder[deflen] = "";
strcpy(currentfolder, arg1);
int len = (int)strlen(currentfolder);
while(currentfolder[len] != '\\' and len != 0)
len--;
currentfolder[len] = 0;
if(DirExists(arg3))
strcpy(currentfolder, arg3);
//initialize
wait(WAITID_STOP); //wait for the debugger to stop
waitclear(); //clear waiting flags NOTE: thread-unsafe
static INIT_STRUCT init;
memset(&init, 0, sizeof(INIT_STRUCT));
init.exe = arg1;
init.commandline = commandline;
if(*currentfolder)
init.currentfolder = currentfolder;
CloseHandle(CreateThread(0, 0, threadDebugLoop, &init, 0, 0));
return STATUS_CONTINUE;
}
CMDRESULT cbStopDebug(int argc, char* argv[])
{
scriptreset(); //reset the currently-loaded script
StopDebug();
unlock(WAITID_RUN);
wait(WAITID_STOP);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugRun(int argc, char* argv[])
{
if(!waitislocked(WAITID_RUN))
{
dputs("program is already running");
return STATUS_ERROR;
}
GuiSetDebugState(running);
unlock(WAITID_RUN);
PLUG_CB_RESUMEDEBUG callbackInfo;
callbackInfo.reserved = 0;
plugincbcall(CB_RESUMEDEBUG, &callbackInfo);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugErun(int argc, char* argv[])
{
if(waitislocked(WAITID_RUN))
dbgsetskipexceptions(true);
return cbDebugRun(argc, argv);
}
CMDRESULT cbDebugSetBPXOptions(int argc, char* argv[])
{
char argtype[deflen] = "";
DWORD type = 0;
if(!argget(*argv, argtype, 0, false))
return STATUS_ERROR;
const char* a = 0;
uint setting_type;
if(strstr(argtype, "long"))
{
setting_type = 1; //break_int3long
a = "TYPE_LONG_INT3";
type = UE_BREAKPOINT_LONG_INT3;
}
else if(strstr(argtype, "ud2"))
{
setting_type = 2; //break_ud2
a = "TYPE_UD2";
type = UE_BREAKPOINT_UD2;
}
else if(strstr(argtype, "short"))
{
setting_type = 0; //break_int3short
a = "TYPE_INT3";
type = UE_BREAKPOINT_INT3;
}
else
{
dputs("invalid type specified!");
return STATUS_ERROR;
}
SetBPXOptions(type);
BridgeSettingSetUint("Engine", "BreakpointType", setting_type);
dprintf("default breakpoint type set to: %s\n", a);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSetBPX(int argc, char* argv[]) //bp addr [,name [,type]]
{
char argaddr[deflen] = "";
if(!argget(*argv, argaddr, 0, false))
return STATUS_ERROR;
char argname[deflen] = "";
argget(*argv, argname, 1, true);
char argtype[deflen] = "";
bool has_arg2 = argget(*argv, argtype, 2, true);
if(!has_arg2 and (scmp(argname, "ss") or scmp(argname, "long") or scmp(argname, "ud2")))
{
strcpy(argtype, argname);
*argname = 0;
}
_strlwr(argtype);
uint addr = 0;
if(!valfromstring(argaddr, &addr))
{
dprintf("invalid addr: \"%s\"\n", argaddr);
return STATUS_ERROR;
}
int type = 0;
bool singleshoot = false;
if(strstr(argtype, "ss"))
{
type |= UE_SINGLESHOOT;
singleshoot = true;
}
else
type |= UE_BREAKPOINT;
if(strstr(argtype, "long"))
type |= UE_BREAKPOINT_TYPE_LONG_INT3;
else if(strstr(argtype, "ud2"))
type |= UE_BREAKPOINT_TYPE_UD2;
else if(strstr(argtype, "short"))
type |= UE_BREAKPOINT_TYPE_INT3;
short oldbytes;
const char* bpname = 0;
if(*argname)
bpname = argname;
if(bpget(addr, BPNORMAL, bpname, 0))
{
dputs("breakpoint already set!");
return STATUS_CONTINUE;
}
if(IsBPXEnabled(addr))
{
dprintf("error setting breakpoint at "fhex"!\n (IsBPXEnabled)", addr);
return STATUS_ERROR;
}
else if(!memread(fdProcessInfo->hProcess, (void*)addr, &oldbytes, sizeof(short), 0))
{
dprintf("error setting breakpoint at "fhex"!\n (memread)", addr);
return STATUS_ERROR;
}
else if(!bpnew(addr, true, singleshoot, oldbytes, BPNORMAL, type, bpname))
{
dprintf("error setting breakpoint at "fhex"!\n (bpnew)", addr);
return STATUS_ERROR;
}
else if(!SetBPX(addr, type, (void*)cbUserBreakpoint))
{
dprintf("error setting breakpoint at "fhex"! (SetBPX)\n", addr);
return STATUS_ERROR;
}
dprintf("breakpoint at "fhex" set!\n", addr);
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDeleteBPX(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
{
if(!bpgetcount(BPNORMAL))
{
dputs("no breakpoints to delete!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbDeleteAllBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs("all breakpoints deleted!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(bpget(0, BPNORMAL, arg1, &found)) //found a breakpoint with name
{
if(!bpdel(found.addr, BPNORMAL))
{
dprintf("delete breakpoint failed (bpdel): "fhex"\n", found.addr);
return STATUS_ERROR;
}
else if(found.enabled && !DeleteBPX(found.addr))
{
dprintf("delete breakpoint failed (DeleteBPX): "fhex"\n", found.addr);
GuiUpdateAllViews();
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPNORMAL, 0, &found)) //invalid breakpoint
{
dprintf("no such breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(!bpdel(found.addr, BPNORMAL))
{
dprintf("delete breakpoint failed (bpdel): "fhex"\n", found.addr);
return STATUS_ERROR;
}
else if(found.enabled && !DeleteBPX(found.addr))
{
dprintf("delete breakpoint failed (DeleteBPX): "fhex"\n", found.addr);
GuiUpdateAllViews();
return STATUS_ERROR;
}
dputs("breakpoint deleted!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugEnableBPX(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //enable all breakpoints
{
if(!bpgetcount(BPNORMAL))
{
dputs("no breakpoints to enable!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbEnableAllBreakpoints)) //at least one enable failed
return STATUS_ERROR;
dputs("all breakpoints enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(bpget(0, BPNORMAL, arg1, &found)) //found a breakpoint with name
{
if(!bpenable(found.addr, BPNORMAL, true) or !SetBPX(found.addr, found.titantype, (void*)cbUserBreakpoint))
{
dprintf("could not enable breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPNORMAL, 0, &found)) //invalid breakpoint
{
dprintf("no such breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(found.enabled)
{
dputs("breakpoint already enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
if(!bpenable(found.addr, BPNORMAL, true) or !SetBPX(found.addr, found.titantype, (void*)cbUserBreakpoint))
{
dprintf("could not enable breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("breakpoint enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDisableBPX(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
{
if(!bpgetcount(BPNORMAL))
{
dputs("no breakpoints to disable!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbDisableAllBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs("all breakpoints disabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(bpget(0, BPNORMAL, arg1, &found)) //found a breakpoint with name
{
if(!bpenable(found.addr, BPNORMAL, false) or !DeleteBPX(found.addr))
{
dprintf("could not disable breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPNORMAL, 0, &found)) //invalid breakpoint
{
dprintf("no such breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(!found.enabled)
{
dputs("breakpoint already disabled!");
return STATUS_CONTINUE;
}
if(!bpenable(found.addr, BPNORMAL, false) or !DeleteBPX(found.addr))
{
dprintf("could not disable breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("breakpoint disabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugBplist(int argc, char* argv[])
{
bpenumall(cbBreakpointList);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugStepInto(int argc, char* argv[])
{
StepInto((void*)cbStep);
dbgsetstepping(true);
return cbDebugRun(argc, argv);
}
CMDRESULT cbDebugeStepInto(int argc, char* argv[])
{
dbgsetskipexceptions(true);
return cbDebugStepInto(argc, argv);
}
CMDRESULT cbDebugStepOver(int argc, char* argv[])
{
StepOver((void*)cbStep);
dbgsetstepping(true);
return cbDebugRun(argc, argv);
}
CMDRESULT cbDebugeStepOver(int argc, char* argv[])
{
dbgsetskipexceptions(true);
return cbDebugStepOver(argc, argv);
}
CMDRESULT cbDebugSingleStep(int argc, char* argv[])
{
char arg1[deflen] = "";
uint stepcount = 1;
if(argget(*argv, arg1, 0, true))
{
if(!valfromstring(arg1, &stepcount))
stepcount = 1;
}
SingleStep((DWORD)stepcount, (void*)cbStep);
dbgsetstepping(true);
return cbDebugRun(argc, argv);
}
CMDRESULT cbDebugeSingleStep(int argc, char* argv[])
{
dbgsetskipexceptions(true);
return cbDebugSingleStep(argc, argv);
}
CMDRESULT cbDebugHide(int argc, char* argv[])
{
if(HideDebugger(fdProcessInfo->hProcess, UE_HIDE_PEBONLY))
dputs("debugger hidden");
else
dputs("something went wrong");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDisasm(int argc, char* argv[])
{
char arg1[deflen] = "";
uint addr = GetContextDataEx(hActiveThread, UE_CIP);
if(argget(*argv, arg1, 0, true))
if(!valfromstring(arg1, &addr))
addr = GetContextDataEx(hActiveThread, UE_CIP);
if(!memisvalidreadptr(fdProcessInfo->hProcess, addr))
return STATUS_CONTINUE;
DebugUpdateGui(addr, false);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSetMemoryBpx(int argc, char* argv[])
{
char arg1[deflen] = ""; //addr
if(!argget(*argv, arg1, 0, false))
return STATUS_ERROR;
uint addr;
if(!valfromstring(arg1, &addr))
return STATUS_ERROR;
bool restore = false;
char arg2[deflen] = ""; //restore
char arg3[deflen] = ""; //type
argget(*argv, arg3, 2, true);
if(argget(*argv, arg2, 1, true))
{
if(*arg2 == '1')
restore = true;
else if(*arg2 == '0')
restore = false;
else
strcpy(arg3, arg2);
}
DWORD type = UE_MEMORY;
if(*arg3)
{
switch(*arg3)
{
case 'r':
type = UE_MEMORY_READ;
break;
case 'w':
type = UE_MEMORY_WRITE;
break;
case 'x':
type = UE_MEMORY_EXECUTE; //EXECUTE
break;
default:
dputs("invalid type (argument ignored)");
break;
}
}
uint size = 0;
uint base = memfindbaseaddr(addr, &size, true);
bool singleshoot = false;
if(!restore)
singleshoot = true;
if(bpget(base, BPMEMORY, 0, 0))
{
dputs("hardware breakpoint already set!");
return STATUS_CONTINUE;
}
if(!bpnew(base, true, singleshoot, 0, BPMEMORY, type, 0) or !SetMemoryBPXEx(base, size, type, restore, (void*)cbMemoryBreakpoint))
{
dputs("error setting memory breakpoint!");
return STATUS_ERROR;
}
dprintf("memory breakpoint at "fhex" set!\n", addr);
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDeleteMemoryBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
{
if(!bpgetcount(BPMEMORY))
{
dputs("no memory breakpoints to delete!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbDeleteAllMemoryBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs("all memory breakpoints deleted!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(bpget(0, BPMEMORY, arg1, &found)) //found a breakpoint with name
{
uint size;
memfindbaseaddr(found.addr, &size);
if(!bpdel(found.addr, BPMEMORY) or !RemoveMemoryBPX(found.addr, size))
{
dprintf("delete memory breakpoint failed: "fhex"\n", found.addr);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPMEMORY, 0, &found)) //invalid breakpoint
{
dprintf("no such memory breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
uint size;
memfindbaseaddr(found.addr, &size);
if(!bpdel(found.addr, BPMEMORY) or !RemoveMemoryBPX(found.addr, size))
{
dprintf("delete memory breakpoint failed: "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("memory breakpoint deleted!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugRtr(int argc, char* argv[])
{
StepOver((void*)cbRtrStep);
cbDebugRun(argc, argv);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugeRtr(int argc, char* argv[])
{
dbgsetskipexceptions(true);
return cbDebugRtr(argc, argv);
}
CMDRESULT cbDebugSetHardwareBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = ""; //addr
if(!argget(*argv, arg1, 0, false))
return STATUS_ERROR;
uint addr;
if(!valfromstring(arg1, &addr))
return STATUS_ERROR;
DWORD type = UE_HARDWARE_EXECUTE;
char arg2[deflen] = ""; //type
if(argget(*argv, arg2, 1, true))
{
switch(*arg2)
{
case 'r':
type = UE_HARDWARE_READWRITE;
break;
case 'w':
type = UE_HARDWARE_WRITE;
break;
case 'x':
break;
default:
dputs("invalid type, assuming 'x'");
break;
}
}
char arg3[deflen] = ""; //size
uint size = UE_HARDWARE_SIZE_1;
if(argget(*argv, arg3, 2, true))
{
if(!valfromstring(arg3, &size))
return STATUS_ERROR;
switch(size)
{
case 2:
size = UE_HARDWARE_SIZE_2;
break;
case 4:
size = UE_HARDWARE_SIZE_4;
break;
#ifdef _WIN64
case 8:
size = UE_HARDWARE_SIZE_8;
break;
#endif // _WIN64
default:
dputs("invalid size, using 1");
break;
}
if((addr % size) != 0)
{
dprintf("address not aligned to %d\n", size);
return STATUS_ERROR;
}
}
DWORD drx = 0;
if(!GetUnusedHardwareBreakPointRegister(&drx))
{
dputs("you can only set 4 hardware breakpoints");
return STATUS_ERROR;
}
int titantype = 0;
TITANSETDRX(titantype, drx);
TITANSETTYPE(titantype, type);
TITANSETSIZE(titantype, size);
//TODO: hwbp in multiple threads TEST
if(bpget(addr, BPHARDWARE, 0, 0))
{
dputs("hardware breakpoint already set!");
return STATUS_CONTINUE;
}
if(!bpnew(addr, true, false, 0, BPHARDWARE, titantype, 0) or !SetHardwareBreakPoint(addr, drx, type, (DWORD)size, (void*)cbHardwareBreakpoint))
{
dputs("error setting hardware breakpoint!");
return STATUS_ERROR;
}
dprintf("hardware breakpoint at "fhex" set!\n", addr);
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDeleteHardwareBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //delete all breakpoints
{
if(!bpgetcount(BPHARDWARE))
{
dputs("no hardware breakpoints to delete!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbDeleteAllHardwareBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs("all hardware breakpoints deleted!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
if(bpget(0, BPHARDWARE, arg1, &found)) //found a breakpoint with name
{
if(!bpdel(found.addr, BPHARDWARE) or !DeleteHardwareBreakPoint(TITANGETDRX(found.titantype)))
{
dprintf("delete hardware breakpoint failed: "fhex"\n", found.addr);
return STATUS_ERROR;
}
return STATUS_CONTINUE;
}
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPHARDWARE, 0, &found)) //invalid breakpoint
{
dprintf("no such hardware breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(!bpdel(found.addr, BPHARDWARE) or !DeleteHardwareBreakPoint(TITANGETDRX(found.titantype)))
{
dprintf("delete hardware breakpoint failed: "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("hardware breakpoint deleted!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugAlloc(int argc, char* argv[])
{
char arg1[deflen] = ""; //size
uint size = 0x1000;
if(argget(*argv, arg1, 0, true))
if(!valfromstring(arg1, &size, false))
return STATUS_ERROR;
uint mem = (uint)memalloc(fdProcessInfo->hProcess, 0, size, PAGE_EXECUTE_READWRITE);
if(!mem)
dputs("VirtualAllocEx failed");
else
dprintf(fhex"\n", mem);
if(mem)
varset("$lastalloc", mem, true);
dbggetprivateusage(fdProcessInfo->hProcess, true);
memupdatemap(fdProcessInfo->hProcess);
varset("$res", mem, false);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugFree(int argc, char* argv[])
{
uint lastalloc;
varget("$lastalloc", &lastalloc, 0, 0);
char arg1[deflen] = ""; //addr
uint addr = lastalloc;
if(argget(*argv, arg1, 0, true))
{
if(!valfromstring(arg1, &addr, false))
return STATUS_ERROR;
}
else if(!lastalloc)
{
dputs("lastalloc is zero, provide a page address");
return STATUS_ERROR;
}
if(addr == lastalloc)
varset("$lastalloc", (uint)0, true);
bool ok = !!VirtualFreeEx(fdProcessInfo->hProcess, (void*)addr, 0, MEM_RELEASE);
if(!ok)
dputs("VirtualFreeEx failed");
dbggetprivateusage(fdProcessInfo->hProcess, true);
memupdatemap(fdProcessInfo->hProcess);
varset("$res", ok, false);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugMemset(int argc, char* argv[])
{
char arg3[deflen] = ""; //size
uint addr;
uint value;
uint size;
if(argc < 3)
{
dputs("not enough arguments");
return STATUS_ERROR;
}
if(!valfromstring(argv[1], &addr, false) or !valfromstring(argv[2], &value, false))
return STATUS_ERROR;
if(argget(*argv, arg3, 2, true))
{
if(!valfromstring(arg3, &size, false))
return STATUS_ERROR;
}
else
{
uint base = memfindbaseaddr(addr, &size, true);
if(!base)
{
dputs("invalid address specified");
return STATUS_ERROR;
}
uint diff = addr - base;
addr = base + diff;
size -= diff;
}
BYTE fi = value & 0xFF;
if(!Fill((void*)addr, size & 0xFFFFFFFF, &fi))
dputs("memset failed");
else
dprintf("memory "fhex" (size: %.8X) set to %.2X\n", addr, size & 0xFFFFFFFF, value & 0xFF);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugBenchmark(int argc, char* argv[])
{
uint addr = memfindbaseaddr(GetContextDataEx(hActiveThread, UE_CIP), 0);
DWORD ticks = GetTickCount();
char comment[MAX_COMMENT_SIZE] = "";
for(uint i = addr; i < addr + 100000; i++)
{
commentset(i, "test", false);
labelset(i, "test", false);
bookmarkset(i, false);
functionadd(i, i, false);
}
dprintf("%ums\n", GetTickCount() - ticks);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugPause(int argc, char* argv[])
{
if(waitislocked(WAITID_RUN))
{
dputs("program is not running");
return STATUS_ERROR;
}
dbgsetispausedbyuser(true);
DebugBreakProcess(fdProcessInfo->hProcess);
return STATUS_CONTINUE;
}
static DWORD WINAPI scyllaThread(void* lpParam)
{
typedef INT (WINAPI * SCYLLASTARTGUI)(DWORD pid, HINSTANCE mod);
SCYLLASTARTGUI ScyllaStartGui = 0;
HINSTANCE hScylla = LoadLibraryA("Scylla.dll");
if(!hScylla)
{
dputs("error loading Scylla.dll!");
bScyllaLoaded = false;
return 0;
}
ScyllaStartGui = (SCYLLASTARTGUI)GetProcAddress(hScylla, "ScyllaStartGui");
if(!ScyllaStartGui)
{
dputs("could not find export 'ScyllaStartGui' inside Scylla.dll");
bScyllaLoaded = false;
return 0;
}
if(dbgisdll())
ScyllaStartGui(fdProcessInfo->dwProcessId, (HINSTANCE)dbgdebuggedbase());
else
ScyllaStartGui(fdProcessInfo->dwProcessId, 0);
FreeLibrary(hScylla);
bScyllaLoaded = false;
return 0;
}
CMDRESULT cbDebugStartScylla(int argc, char* argv[])
{
if(bScyllaLoaded)
{
dputs("Scylla is already loaded");
return STATUS_ERROR;
}
bScyllaLoaded = true;
CloseHandle(CreateThread(0, 0, scyllaThread, 0, 0, 0));
return STATUS_CONTINUE;
}
CMDRESULT cbDebugAttach(int argc, char* argv[])
{
if(argc < 2)
{
dputs("not enough arguments!");
return STATUS_ERROR;
}
uint pid = 0;
if(!valfromstring(argv[1], &pid, false))
return STATUS_ERROR;
if(argc > 2)
{
uint eventHandle = 0;
if(!valfromstring(argv[2], &eventHandle, false))
return STATUS_ERROR;
dbgsetattachevent((HANDLE)eventHandle);
}
if(DbgIsDebugging())
DbgCmdExecDirect("stop");
Handle hProcess = TitanOpenProcess(PROCESS_ALL_ACCESS, false, (DWORD)pid);
if(!hProcess)
{
dprintf("could not open process %X!\n", pid);
return STATUS_ERROR;
}
BOOL wow64 = false, mewow64 = false;
if(!IsWow64Process(hProcess, &wow64) or !IsWow64Process(GetCurrentProcess(), &mewow64))
{
dputs("IsWow64Process failed!");
return STATUS_ERROR;
}
if((mewow64 and !wow64) or (!mewow64 and wow64))
{
#ifdef _WIN64
dputs("Use x32_dbg to debug this process!");
#else
dputs("Use x64_dbg to debug this process!");
#endif // _WIN64
return STATUS_ERROR;
}
if(!GetModuleFileNameExA(hProcess, 0, szFileName, sizeof(szFileName)))
{
dprintf("could not get module filename %X!\n", pid);
return STATUS_ERROR;
}
CloseHandle(CreateThread(0, 0, threadAttachLoop, (void*)pid, 0, 0));
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDetach(int argc, char* argv[])
{
unlock(WAITID_RUN); //run
dbgsetisdetachedbyuser(true); //detach when paused
StepInto((void*)cbDetach);
DebugBreakProcess(fdProcessInfo->hProcess);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDump(int argc, char* argv[])
{
if(argc < 2)
{
dputs("not enough arguments!");
return STATUS_ERROR;
}
duint addr = 0;
if(!valfromstring(argv[1], &addr))
{
dprintf("invalid address \"%s\"!\n", argv[1]);
return STATUS_ERROR;
}
GuiDumpAt(addr);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugStackDump(int argc, char* argv[])
{
duint addr = 0;
if(argc < 2)
addr = GetContextDataEx(hActiveThread, UE_CSP);
else if(!valfromstring(argv[1], &addr))
{
dprintf("invalid address \"%s\"!\n", argv[1]);
return STATUS_ERROR;
}
duint csp = GetContextDataEx(hActiveThread, UE_CSP);
duint size = 0;
duint base = memfindbaseaddr(csp, &size);
if(base && addr >= base && addr < (base + size))
GuiStackDumpAt(addr, csp);
else
dputs("invalid stack address!");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugContinue(int argc, char* argv[])
{
if(argc < 2)
{
SetNextDbgContinueStatus(DBG_CONTINUE);
dputs("exception will be swallowed");
}
else
{
SetNextDbgContinueStatus(DBG_EXCEPTION_NOT_HANDLED);
dputs("exception will be thrown in the program");
}
return STATUS_CONTINUE;
}
CMDRESULT cbDebugBpDll(int argc, char* argv[])
{
if(argc < 2)
{
dputs("not enough arguments!");
return STATUS_ERROR;
}
DWORD type = UE_ON_LIB_ALL;
if(argc > 2)
{
switch(*argv[2])
{
case 'l':
type = UE_ON_LIB_LOAD;
break;
case 'u':
type = UE_ON_LIB_UNLOAD;
break;
}
}
bool singleshoot = true;
if(argc > 3)
singleshoot = false;
LibrarianSetBreakPoint(argv[1], type, singleshoot, (void*)cbLibrarianBreakpoint);
dprintf("dll breakpoint set on \"%s\"!\n", argv[1]);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugBcDll(int argc, char* argv[])
{
if(argc < 2)
{
dputs("not enough arguments");
return STATUS_ERROR;
}
if(!LibrarianRemoveBreakPoint(argv[1], UE_ON_LIB_ALL))
{
dputs("failed to remove dll breakpoint...");
return STATUS_ERROR;
}
dputs("dll breakpoint removed!");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSwitchthread(int argc, char* argv[])
{
uint threadid = fdProcessInfo->dwThreadId; //main thread
if(argc > 1)
if(!valfromstring(argv[1], &threadid, false))
return STATUS_ERROR;
if(!threadisvalid((DWORD)threadid)) //check if the thread is valid
{
dprintf("invalid thread %X\n", threadid);
return STATUS_ERROR;
}
//switch thread
hActiveThread = threadgethandle((DWORD)threadid);
DebugUpdateGui(GetContextDataEx(hActiveThread, UE_CIP), true);
dputs("thread switched!");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSuspendthread(int argc, char* argv[])
{
uint threadid = fdProcessInfo->dwThreadId;
if(argc > 1)
if(!valfromstring(argv[1], &threadid, false))
return STATUS_ERROR;
if(!threadisvalid((DWORD)threadid)) //check if the thread is valid
{
dprintf("invalid thread %X\n", threadid);
return STATUS_ERROR;
}
//suspend thread
if(SuspendThread(threadgethandle((DWORD)threadid)) == -1)
{
dputs("error suspending thread");
return STATUS_ERROR;
}
dputs("thread suspended");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugResumethread(int argc, char* argv[])
{
uint threadid = fdProcessInfo->dwThreadId;
if(argc > 1)
if(!valfromstring(argv[1], &threadid, false))
return STATUS_ERROR;
if(!threadisvalid((DWORD)threadid)) //check if the thread is valid
{
dprintf("invalid thread %X\n", threadid);
return STATUS_ERROR;
}
//resume thread
if(ResumeThread(threadgethandle((DWORD)threadid)) == -1)
{
dputs("error resuming thread");
return STATUS_ERROR;
}
dputs("thread resumed!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugKillthread(int argc, char* argv[])
{
uint threadid = fdProcessInfo->dwThreadId;
if(argc > 1)
if(!valfromstring(argv[1], &threadid, false))
return STATUS_ERROR;
uint exitcode = 0;
if(argc > 2)
if(!valfromstring(argv[2], &exitcode, false))
return STATUS_ERROR;
if(!threadisvalid((DWORD)threadid)) //check if the thread is valid
{
dprintf("invalid thread %X\n", threadid);
return STATUS_ERROR;
}
//terminate thread
if(TerminateThread(threadgethandle((DWORD)threadid), (DWORD)exitcode) != 0)
{
GuiUpdateAllViews();
dputs("thread terminated");
return STATUS_CONTINUE;
}
dputs("error terminating thread!");
return STATUS_ERROR;
}
CMDRESULT cbDebugSetPriority(int argc, char* argv[])
{
if(argc < 3)
{
dputs("not enough arguments!");
return STATUS_ERROR;
}
uint threadid;
if(!valfromstring(argv[1], &threadid, false))
return STATUS_ERROR;
uint priority;
if(!valfromstring(argv[2], &priority))
{
if(_strcmpi(argv[2], "Normal") == 0)
priority = THREAD_PRIORITY_NORMAL;
else if(_strcmpi(argv[2], "AboveNormal") == 0)
priority = THREAD_PRIORITY_ABOVE_NORMAL;
else if(_strcmpi(argv[2], "TimeCritical") == 0)
priority = THREAD_PRIORITY_TIME_CRITICAL;
else if(_strcmpi(argv[2], "Idle") == 0)
priority = THREAD_PRIORITY_IDLE;
else if(_strcmpi(argv[2], "BelowNormal") == 0)
priority = THREAD_PRIORITY_BELOW_NORMAL;
else if(_strcmpi(argv[2], "Highest") == 0)
priority = THREAD_PRIORITY_HIGHEST;
else if(_strcmpi(argv[2], "Lowest") == 0)
priority = THREAD_PRIORITY_LOWEST;
else
{
dputs("unknown priority value, read the help!");
return STATUS_ERROR;
}
}
else
{
switch(priority) //check if the priority value is valid
{
case THREAD_PRIORITY_NORMAL:
case THREAD_PRIORITY_ABOVE_NORMAL:
case THREAD_PRIORITY_TIME_CRITICAL:
case THREAD_PRIORITY_IDLE:
case THREAD_PRIORITY_BELOW_NORMAL:
case THREAD_PRIORITY_HIGHEST:
case THREAD_PRIORITY_LOWEST:
break;
default:
dputs("unknown priority value, read the help!");
return STATUS_ERROR;
}
}
if(!threadisvalid((DWORD)threadid)) //check if the thread is valid
{
dprintf("invalid thread %X\n", threadid);
return STATUS_ERROR;
}
//set thread priority
if(SetThreadPriority(threadgethandle((DWORD)threadid), (int)priority) == 0)
{
dputs("error setting thread priority");
return STATUS_ERROR;
}
dputs("thread priority changed!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugEnableHardwareBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = "";
DWORD drx = 0;
if(!GetUnusedHardwareBreakPointRegister(&drx))
{
dputs("you can only set 4 hardware breakpoints");
return STATUS_ERROR;
}
if(!argget(*argv, arg1, 0, true)) //enable all hardware breakpoints
{
if(!bpgetcount(BPHARDWARE))
{
dputs("no hardware breakpoints to enable!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbEnableAllHardwareBreakpoints)) //at least one enable failed
return STATUS_ERROR;
dputs("all hardware breakpoints enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPHARDWARE, 0, &found)) //invalid hardware breakpoint
{
dprintf("no such hardware breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(found.enabled)
{
dputs("hardware breakpoint already enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
TITANSETDRX(found.titantype, drx);
bpsettitantype(found.addr, BPHARDWARE, found.titantype);
if(!bpenable(found.addr, BPHARDWARE, true) or !SetHardwareBreakPoint(found.addr, drx, TITANGETTYPE(found.titantype), TITANGETSIZE(found.titantype), (void*)cbHardwareBreakpoint))
{
dprintf("could not enable hardware breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("hardware breakpoint enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDisableHardwareBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //delete all hardware breakpoints
{
if(!bpgetcount(BPHARDWARE))
{
dputs("no hardware breakpoints to disable!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbDisableAllHardwareBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs("all hardware breakpoints disabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPHARDWARE, 0, &found)) //invalid hardware breakpoint
{
dprintf("no such hardware breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(!found.enabled)
{
dputs("hardware breakpoint already disabled!");
return STATUS_CONTINUE;
}
if(!bpenable(found.addr, BPHARDWARE, false) or !DeleteHardwareBreakPoint(TITANGETDRX(found.titantype)))
{
dprintf("could not disable hardware breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("hardware breakpoint disabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugEnableMemoryBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = "";
DWORD drx = 0;
if(!GetUnusedHardwareBreakPointRegister(0))
{
dputs("you can only set 4 hardware breakpoints");
return STATUS_ERROR;
}
if(!argget(*argv, arg1, 0, true)) //enable all memory breakpoints
{
if(!bpgetcount(BPMEMORY))
{
dputs("no hardware breakpoints to enable!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbEnableAllHardwareBreakpoints)) //at least one enable failed
return STATUS_ERROR;
dputs("all memory breakpoints enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPMEMORY, 0, &found)) //invalid memory breakpoint
{
dprintf("no such memory breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(found.enabled)
{
dputs("hardware memory already enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
uint size = 0;
memfindbaseaddr(found.addr, &size);
if(!bpenable(found.addr, BPMEMORY, true) or !SetMemoryBPXEx(found.addr, size, found.titantype, !found.singleshoot, (void*)cbMemoryBreakpoint))
{
dprintf("could not enable memory breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("memory breakpoint enabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDisableMemoryBreakpoint(int argc, char* argv[])
{
char arg1[deflen] = "";
if(!argget(*argv, arg1, 0, true)) //delete all memory breakpoints
{
if(!bpgetcount(BPMEMORY))
{
dputs("no memory breakpoints to disable!");
return STATUS_CONTINUE;
}
if(!bpenumall(cbDisableAllMemoryBreakpoints)) //at least one deletion failed
return STATUS_ERROR;
dputs("all memory breakpoints disabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
BREAKPOINT found;
uint addr = 0;
if(!valfromstring(arg1, &addr) or !bpget(addr, BPMEMORY, 0, &found)) //invalid memory breakpoint
{
dprintf("no such memory breakpoint \"%s\"\n", arg1);
return STATUS_ERROR;
}
if(!found.enabled)
{
dputs("memory breakpoint already disabled!");
return STATUS_CONTINUE;
}
uint size = 0;
memfindbaseaddr(found.addr, &size);
if(!bpenable(found.addr, BPMEMORY, false) or !RemoveMemoryBPX(found.addr, size))
{
dprintf("could not disable memory breakpoint "fhex"\n", found.addr);
return STATUS_ERROR;
}
dputs("memory breakpoint disabled!");
GuiUpdateAllViews();
return STATUS_CONTINUE;
}
CMDRESULT cbDebugDownloadSymbol(int argc, char* argv[])
{
char szDefaultStore[MAX_PATH] = "";
const char* szSymbolStore = szDefaultStore;
if(!BridgeSettingGet("Symbols", "DefaultStore", szDefaultStore)) //get default symbol store from settings
{
strcpy(szDefaultStore, "http://msdl.microsoft.com/download/symbols");
BridgeSettingSet("Symbols", "DefaultStore", szDefaultStore);
}
if(argc < 2) //no arguments
{
symdownloadallsymbols(szSymbolStore); //download symbols for all modules
GuiSymbolRefreshCurrent();
dputs("done! See symbol log for more information");
return STATUS_CONTINUE;
}
//get some module information
uint modbase = modbasefromname(argv[1]);
if(!modbase)
{
dprintf("invalid module \"%s\"!\n", argv[1]);
return STATUS_ERROR;
}
char szModulePath[MAX_PATH] = "";
if(!GetModuleFileNameExA(fdProcessInfo->hProcess, (HMODULE)modbase, szModulePath, MAX_PATH))
{
dputs("GetModuleFileNameExA failed!");
return STATUS_ERROR;
}
char szOldSearchPath[MAX_PATH] = "";
if(!SymGetSearchPath(fdProcessInfo->hProcess, szOldSearchPath, MAX_PATH)) //backup current search path
{
dputs("SymGetSearchPath failed!");
return STATUS_ERROR;
}
char szServerSearchPath[MAX_PATH * 2] = "";
if(argc > 2)
szSymbolStore = argv[2];
sprintf_s(szServerSearchPath, "SRV*%s*%s", szSymbolCachePath, szSymbolStore);
if(!SymSetSearchPath(fdProcessInfo->hProcess, szServerSearchPath)) //set new search path
{
dputs("SymSetSearchPath (1) failed!");
return STATUS_ERROR;
}
if(!SymUnloadModule64(fdProcessInfo->hProcess, (DWORD64)modbase)) //unload module
{
SymSetSearchPath(fdProcessInfo->hProcess, szOldSearchPath);
dputs("SymUnloadModule64 failed!");
return STATUS_ERROR;
}
if(!SymLoadModuleEx(fdProcessInfo->hProcess, 0, szModulePath, 0, (DWORD64)modbase, 0, 0, 0)) //load module
{
dputs("SymLoadModuleEx failed!");
SymSetSearchPath(fdProcessInfo->hProcess, szOldSearchPath);
return STATUS_ERROR;
}
if(!SymSetSearchPath(fdProcessInfo->hProcess, szOldSearchPath))
{
dputs("SymSetSearchPath (2) failed!");
return STATUS_ERROR;
}
GuiSymbolRefreshCurrent();
dputs("done! See symbol log for more information");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugGetJITAuto(int argc, char* argv[])
{
bool jit_auto;
arch actual_arch;
if(argc == 1)
{
if(!dbggetjitauto(&jit_auto, notfound, & actual_arch, NULL))
{
dprintf("Error getting JIT auto %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
}
else if(argc == 2)
{
readwritejitkey_error_t rw_error;
if(_strcmpi(argv[1], "x64") == 0)
actual_arch = x64;
else if(_strcmpi(argv[1], "x32") == 0)
actual_arch = x32;
else
{
dputs("Unknown JIT auto entry type. Use x64 or x32 as parameter.");
return STATUS_ERROR;
}
if(!dbggetjitauto(& jit_auto, actual_arch, NULL, & rw_error))
{
if(rw_error == ERROR_RW_NOTWOW64)
dprintf("Error using x64 arg the debugger is not a WOW64 process\n");
else
dprintf("Error getting JIT auto %s\n", argv[1]);
return STATUS_ERROR;
}
}
else
{
dputs("Unknown JIT auto entry type. Use x64 or x32 as parameter");
}
dprintf("JIT auto %s: %s\n", (actual_arch == x64) ? "x64" : "x32", jit_auto ? "ON" : "OFF");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSetJITAuto(int argc, char* argv[])
{
arch actual_arch;
bool set_jit_auto;
if(argc < 2)
{
dprintf("Error setting JIT Auto. Use ON:1 or OFF:0 arg or x64/x32, ON:1 or OFF:0.\n");
return STATUS_ERROR;
}
else if(argc == 2)
{
if(_strcmpi(argv[1], "1") == 0 || _strcmpi(argv[1], "ON") == 0)
set_jit_auto = true;
else if(_strcmpi(argv[1], "0") == 0 || _strcmpi(argv[1], "OFF") == 0)
set_jit_auto = false;
else
{
dputs("Error unknown parameters. Use ON:1 or OFF:0");
return STATUS_ERROR;
}
if(!dbgsetjitauto(set_jit_auto, notfound, & actual_arch, NULL))
{
dprintf("Error setting JIT auto %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
}
else if(argc == 3)
{
readwritejitkey_error_t rw_error;
actual_arch = x64;
if(_strcmpi(argv[1], "x64") == 0)
actual_arch = x64;
else if(_strcmpi(argv[1], "x32") == 0)
actual_arch = x32;
else
{
dputs("Unknown JIT auto entry type. Use x64 or x32 as parameter");
return STATUS_ERROR;
}
if(_strcmpi(argv[2], "1") == 0 || _strcmpi(argv[2], "ON") == 0)
set_jit_auto = true;
else if(_strcmpi(argv[2], "0") == 0 || _strcmpi(argv[2], "OFF") == 0)
set_jit_auto = false;
else
{
return STATUS_ERROR;
dputs("Error unknown parameters. Use x86 or x64 and ON:1 or OFF:0\n");
}
if(!dbgsetjitauto(set_jit_auto, actual_arch, NULL, & rw_error))
{
if(rw_error == ERROR_RW_NOTWOW64)
dprintf("Error using x64 arg the debugger is not a WOW64 process\n");
else
dprintf("Error getting JIT auto %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
}
else
{
dputs("Error unknown parameters use x86 or x64, ON/1 or OFF/0\n");
return STATUS_ERROR;
}
dprintf("New JIT auto %s: %s\n", (actual_arch == x64) ? "x64" : "x32", set_jit_auto ? "ON" : "OFF");
return STATUS_CONTINUE;
}
CMDRESULT cbDebugSetJIT(int argc, char* argv[])
{
arch actual_arch;
char* jit_debugger_cmd;
char oldjit[MAX_SETTING_SIZE] = "";
if(argc < 2)
{
char path[JIT_ENTRY_DEF_SIZE];
dbggetdefjit(path);
char get_entry[JIT_ENTRY_MAX_SIZE] = "";
if(!dbggetjit(get_entry, notfound, & actual_arch, NULL))
{
dprintf("Error getting JIT %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
strcpy_s(oldjit, get_entry);
jit_debugger_cmd = path;
if(!dbgsetjit(jit_debugger_cmd, notfound, & actual_arch, NULL))
{
dprintf("Error setting JIT %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
if(_stricmp(oldjit, path))
BridgeSettingSet("JIT", "Old", oldjit);
}
else if(argc == 2)
{
if(!_strcmpi(argv[1], "restore"))
{
jit_debugger_cmd = oldjit;
if(!BridgeSettingGet("JIT", "Old", jit_debugger_cmd))
{
dputs("There is no old JIT entry stored. Please use the setjit command.");
return STATUS_ERROR; //nothing to restore
}
if(!dbgsetjit(jit_debugger_cmd, notfound, & actual_arch, NULL))
{
dprintf("Error setting JIT %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
BridgeSettingSet("JIT", 0, 0);
}
else
{
jit_debugger_cmd = argv[1];
if(!dbgsetjit(jit_debugger_cmd, notfound, & actual_arch, NULL))
{
dprintf("Error setting JIT %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
}
}
else if(argc == 3)
{
readwritejitkey_error_t rw_error;
if(_strcmpi(argv[1], "x64") == 0)
actual_arch = x64;
else if(_strcmpi(argv[1], "x32") == 0)
actual_arch = x32;
else
{
dputs("Unknown JIT entry type. Use x64 or x32 as parameter.");
return STATUS_ERROR;
}
jit_debugger_cmd = argv[2];
if(!dbgsetjit(jit_debugger_cmd, actual_arch, NULL, & rw_error))
{
if(rw_error == ERROR_RW_NOTWOW64)
dprintf("Error using x64 arg. The debugger is not a WOW64 process\n");
else
dprintf("Error getting JIT %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
}
else
{
dputs("Error unknown parameters. Use x86 or x64 as parameter.");
return STATUS_ERROR;
}
dprintf("New JIT %s: %s\n", (actual_arch == x64) ? "x64" : "x32", jit_debugger_cmd);
return STATUS_CONTINUE;
}
CMDRESULT cbDebugGetJIT(int argc, char* argv[])
{
char get_entry[JIT_ENTRY_MAX_SIZE] = "";
arch actual_arch;
if(argc < 2)
{
if(!dbggetjit(get_entry, notfound, & actual_arch, NULL))
{
dprintf("Error getting JIT %s\n", (actual_arch == x64) ? "x64" : "x32");
return STATUS_ERROR;
}
}
else
{
readwritejitkey_error_t rw_error;
if(_strcmpi(argv[1], "x64") == 0)
actual_arch = x64;
else if(_strcmpi(argv[1], "x32") == 0)
actual_arch = x32;
else
{
dputs("Unknown JIT entry type. Use x64 or x32 as parameter.");
return STATUS_ERROR;
}
if(!dbggetjit(get_entry, actual_arch, NULL, & rw_error))
{
if(rw_error == ERROR_RW_NOTWOW64)
dprintf("Error using x64 arg. The debugger is not a WOW64 process\n");
else
dprintf("Error getting JIT %s\n", argv[1]);
return STATUS_ERROR;
}
}
dprintf("JIT %s: %s\n", (actual_arch == x64) ? "x64" : "x32", get_entry);
return STATUS_CONTINUE;
}