static void HandleCapstoneOperand(Capstone & cp, int opindex, DISASM_ARG* arg)
{
    const cs_x86 & x86 = cp.x86();
    const cs_x86_op & op = x86.operands[opindex];
    arg->segment = SEG_DEFAULT;
    strcpy_s(arg->mnemonic, cp.OperandText(opindex).c_str());
    switch(op.type)
    {
    case X86_OP_REG:
    {
        const char* regname = cp.RegName((x86_reg)op.reg);
        arg->type = arg_normal;
        uint value;
        if(!valfromstring(regname, &value, true, true))
            value = 0;
        arg->constant = arg->value = value;
    }
    break;

    case X86_OP_IMM:
    {
        arg->type = arg_normal;
        arg->constant = arg->value = (duint)op.imm;
    }
    break;

    case X86_OP_MEM:
    {
        arg->type = arg_memory;
        const x86_op_mem & mem = op.mem;
        if(mem.base == X86_REG_RIP)  //rip-relative
            arg->constant = cp.Address() + (duint)mem.disp + cp.Size();
        else
            arg->constant = (duint)mem.disp;
        uint value;
        if(!valfromstring(arg->mnemonic, &value, true, true))
            return;
        arg->value = value;
        if(DbgMemIsValidReadPtr(value))
        {
            switch(op.size)
            {
            case 1:
                DbgMemRead(value, (unsigned char*)&arg->memvalue, 1);
                break;
            case 2:
                DbgMemRead(value, (unsigned char*)&arg->memvalue, 2);
                break;
            case 4:
                DbgMemRead(value, (unsigned char*)&arg->memvalue, 4);
                break;
            case 8:
                DbgMemRead(value, (unsigned char*)&arg->memvalue, 8);
                break;
            }
        }
    }
    break;
    }
}
bool HandleSegSelectorOperand(XEDPARSE* Parse, const char* Value, InstOperand* Operand)
{
    char selector[64];
    char offset[64];

    // Copy the prefix into a buffer
    strcpy(selector, Value);
    *strchr(selector, ':') = '\0';

    // Copy the offset
    strcpy(offset, strrchr(Value, ':') + 1);

    // The segment selector is always a number from 0 to 0xFFFF
    if(strlen(selector) > 0)
    {
        ULONGLONG selVal = 0;

        if(!valfromstring(selector, &selVal) || abs((LONGLONG)selVal) > USHRT_MAX)
        {
            strcpy(Parse->error, "Invalid segment selector value");
            return false;
        }

        Operand->Sel.Selector = selVal & 0xFFFF;
    }
    else
    {
        strcpy(Parse->error, "Invalid segment selector");
        return false;
    }

    // Determine offset
    if(strlen(offset) <= 0)
    {
        strcpy(Parse->error, "Invalid offset");
        return false;
    }

    // Ex: 033:X86SwitchTo64BitMode
    ULONGLONG offsetVal = 0;

    if(!valfromstring(offset, &offsetVal) && !(Parse->cbUnknown && Parse->cbUnknown(offset, &offsetVal)))
    {
        sprintf(Parse->error, "Unable to parse offset '%s'", offset);
        return false;
    }

    Operand->Sel.Offset = offsetVal & 0xFFFFFFFF;
    return true;
}
Beispiel #3
0
bool ExHandlerGetUnhandled(std::vector<duint> & Entries)
{
    // Try the address for Windows Vista+
    static duint addr_BasepCurrentTopLevelFilter = 0;

#ifdef _WIN64
    auto symbol = "BasepCurrentTopLevelFilter";
#else
    auto symbol = "_BasepCurrentTopLevelFilter";
#endif
    if(addr_BasepCurrentTopLevelFilter || valfromstring(symbol, &addr_BasepCurrentTopLevelFilter))
    {
        // Read external pointer
        duint handlerValue = 0;

        if(!MemRead(addr_BasepCurrentTopLevelFilter, &handlerValue, sizeof(duint)))
            return false;

        // Decode with remote process cookie
        if(!MemDecodePointer(&handlerValue, true))
            return false;

        Entries.push_back(handlerValue);
        return true;
    }

    return false;
}
Beispiel #4
0
bool cbInstrAssemble(int argc, char* argv[])
{
    if(IsArgumentsLessThan(argc, 3))
        return false;
    duint addr = 0;
    if(!valfromstring(argv[1], &addr))
    {
        dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid expression: \"%s\"!\n"), argv[1]);
        return false;
    }
    if(!DbgMemIsValidReadPtr(addr))
    {
        dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid address: %p!\n"), addr);
        return false;
    }
    bool fillnop = false;
    if(argc > 3)
        fillnop = true;
    char error[MAX_ERROR_SIZE] = "";
    int size = 0;
    if(!assembleat(addr, argv[2], &size, error, fillnop))
    {
        varset("$result", size, false);
        dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to assemble \"%s\" (%s)\n"), argv[2], error);
        return false;
    }
    varset("$result", size, false);
    GuiUpdateAllViews();
    return true;
}
bool AnalyzeOperand(XEDPARSE* Parse, const char* Value, InstOperand* Operand)
{
    REG registerVal     = RegFromString(Value);
    ULONGLONG immVal    = 0;

    if(registerVal != REG_INVALID)
    {
        // Register
        Operand->Type       = OPERAND_REG;
        Operand->Segment    = REG_INVALID;
        Operand->Size       = RegGetSize(registerVal);
        Operand->XedEOSZ    = OpsizeToEosz(Operand->Size);
        Operand->Reg.Reg    = registerVal;
        Operand->Reg.XedReg = RegToXed(registerVal);
    }
    else if(strchr(Value, '[') && strchr(Value, ']'))
    {
        // Memory
        Operand->Type       = OPERAND_MEM;
        Operand->Segment    = REG_INVALID;
        Operand->Size       = SIZE_UNSET;
        Operand->XedEOSZ    = EOSZ_64_32(Parse->x64);

        return HandleMemoryOperand(Parse, Value, Operand);
    }
    else if(strchr(Value, ':'))
    {
        // Segment selector operand
        Operand->Type       = OPERAND_SEGSEL;
        Operand->Segment    = REG_INVALID;
        Operand->Size       = SIZE_DWORD;
        Operand->XedEOSZ    = EOSZ_64_32(Parse->x64);

        return HandleSegSelectorOperand(Parse, Value, Operand);
    }
    else if(valfromstring(Value, &immVal) || (Parse->cbUnknown && Parse->cbUnknown(Value, &immVal)))
    {
        // Immediate
        Operand->Type       = OPERAND_IMM;
        Operand->Segment    = REG_INVALID;
        Operand->Size       = OpsizeFromValue(immVal);
        Operand->XedEOSZ    = EOSZ_64_32(Parse->x64);
        Operand->Imm.Signed = (Value[0] == '-');
        Operand->Imm.imm    = immVal;
    }
    else
    {
        // Unknown
        Operand->Type = OPERAND_INVALID;

        sprintf(Parse->error, "Unknown operand identifier '%s'", Value);
        return false;
    }

    return true;
}
Beispiel #6
0
bool cbInstrZzz(int argc, char* argv[])
{
    duint value = 100;
    if(argc > 1)
        if(!valfromstring(argv[1], &value, false))
            return false;
    auto ms = DWORD(value);
    if(ms == INFINITE)
        ms = 100;
    Sleep(ms);
    return true;
}
Beispiel #7
0
bool cbInstrGpa(int argc, char* argv[])
{
    if(IsArgumentsLessThan(argc, 2))
        return false;
    char newcmd[deflen] = "";
    if(argc >= 3)
        sprintf_s(newcmd, "\"%s\":%s", argv[2], argv[1]);
    else
        sprintf_s(newcmd, "%s", argv[1]);
    duint result = 0;
    if(!valfromstring(newcmd, &result, false))
        return false;
    varset("$RESULT", result, false);
    return true;
}
bool cbDelWatch(int argc, char* argv[])
{
    if(argc < 2)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "No enough arguments for delwatch\n"));
        return false;
    }
    duint id;
    bool ok = valfromstring(argv[1], &id);
    if(!ok)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error expression in argument 1.\n"));
        return false;
    }
    WatchDelete((unsigned int)id);
    return true;
}
Beispiel #9
0
void SetMemoryDisplacementOrBase(XEDPARSE* Parse, const char* Value, InstOperand* Operand)
{
    // Displacement = name or number
    // Base         = register
    REG registerVal = RegFromString(Value);
    ULONGLONG disp  = 0;

    if(registerVal != REG_INVALID)
    {
        // If the base is already set, then use IMPLICIT scale
        // REG + (REG * 1)
        if(Operand->Mem.Base)
        {
            SetMemoryIndexOrScale(Parse, Value, Operand);
            SetMemoryIndexOrScale(Parse, "1", Operand);
            return;
        }

        // It's the base
        Operand->Mem.Base       = true;
        Operand->Mem.BaseVal    = registerVal;
    }
    else if(valfromstring(Value, &disp) || (Parse->cbUnknown && Parse->cbUnknown(Value, &disp)))
    {
        // It's the displacement
        //
        // Displacement is either /8, /32, or /64
        // 5h = 101b
        Operand->Mem.Disp       = true;
        Operand->Mem.DispVal    = disp;
        bool sign               = (Value[0] == '-');

        if(sign)
            Operand->Mem.DispWidth = OpsizeFromInt(xed_shortest_width_signed(disp, 0x5));
        else
            Operand->Mem.DispWidth = OpsizeFromInt(xed_shortest_width_unsigned(disp, 0x5));

        Operand->Mem.DispWidth = PromoteImmediateWidth(sign, disp, Operand->Mem.DispWidth);
    }
    else
    {
        sprintf(Parse->error, "Unknown displacement or base '%s'", Value);
    }
}
Beispiel #10
0
bool cbSetWatchName(int argc, char* argv[])
{
    if(argc < 3)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "No enough arguments for SetWatchName"));
        return false;
    }
    duint id;
    bool ok = valfromstring(argv[1], &id);
    if(ok)
    {
        WatchModifyName((unsigned int)id, argv[2]);
        return true;
    }
    else
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error expression in argument 1.\n"));
        return false;
    }
}
Beispiel #11
0
bool ExHandlerGetVCH(std::vector<duint> & Entries, bool UseVEH)
{
    // VECTORED_HANDLER_LIST LdrpVectorHandlerList[2];
    static duint addr_LdrpVectorHandlerList = 0;

    if(!addr_LdrpVectorHandlerList && !valfromstring("ntdll:LdrpVectorHandlerList", &addr_LdrpVectorHandlerList))
        return false;

    // Increase array index when using continue handlers
    if(!UseVEH)
        addr_LdrpVectorHandlerList += (1 * sizeof(VECTORED_HANDLER_LIST));

    // Read head entry
    VECTORED_HANDLER_LIST list;
    memset(&list, 0, sizeof(VECTORED_HANDLER_LIST));

    if(!MemRead(addr_LdrpVectorHandlerList, &list, sizeof(VECTORED_HANDLER_LIST)))
        return false;

    // Sub-entries in list
    duint listCurrent = (duint)list.Next;
    duint listEnd = addr_LdrpVectorHandlerList;

    while(listCurrent && listCurrent != listEnd)
    {
        duint handler = (duint)list.VectoredHandler;

        MemDecodePointer(&handler);
        Entries.push_back(handler);

        // Move to next element
        memset(&list, 0, sizeof(VECTORED_HANDLER_LIST));

        if(!MemRead(listCurrent, &list, sizeof(VECTORED_HANDLER_LIST)))
            break;

        listCurrent = (duint)list.Next;
    }

    return true;
}
Beispiel #12
0
bool ExHandlerGetVCH(std::vector<duint> & Entries, bool GetVEH)
{
    // VECTORED_HANDLER_LIST LdrpVectorHandlerList[2];
    static duint addr_LdrpVectorHandlerList = 0;
    duint addrInc = sizeof(duint); //Vista+ has an extra ULONG_PTR in front of the structure

#ifdef _WIN64
    auto symbol = "LdrpVectorHandlerList";
#else
    auto symbol = "_LdrpVectorHandlerList";
#endif
    if(!addr_LdrpVectorHandlerList && !valfromstring(symbol, &addr_LdrpVectorHandlerList))
        return false;

    // Increase array index when using continue handlers
    if(!GetVEH)
        addrInc += sizeof(duint) + sizeof(LIST_ENTRY); //Vista+ has an extra ULONG_PTR

    // Read head entry
    auto list_head = addr_LdrpVectorHandlerList + addrInc;
    duint cur_entry;

    if(!MemRead(list_head, &cur_entry, sizeof(cur_entry)))
        return false;
    auto count = 0;

    while(cur_entry != list_head && count++ < MAX_HANDLER_DEPTH)
    {
        VEH_ENTRY_VISTA entry;
        if(!MemRead(cur_entry, &entry, sizeof(entry)))
            return false;
        auto handler = entry.VectoredHandler;
        if(!MemDecodePointer(&handler, true))
            return false;
        Entries.push_back(handler);
        if(!MemRead(cur_entry, &cur_entry, sizeof(cur_entry)))
            return false;
    }
    return true;
}
Beispiel #13
0
bool ExHandlerGetVEH(std::vector<duint> & Entries)
{
    // Try the address for Windows XP first (or older)
    //
    // VECTORED_EXCEPTION_NODE RtlpCalloutEntryList;
    static duint addr_RtlpCalloutEntryList = 0;

    if(addr_RtlpCalloutEntryList || valfromstring("ntdll:RtlpCalloutEntryList", &addr_RtlpCalloutEntryList))
    {
        // Read header node
        VECTORED_EXCEPTION_NODE node;
        memset(&node, 0, sizeof(VECTORED_EXCEPTION_NODE));

        if(!MemRead(addr_RtlpCalloutEntryList, &node, sizeof(VECTORED_EXCEPTION_NODE)))
            return false;

        // Move to the next link
        duint listCurrent = (duint)node.ListEntry.Flink;
        duint listEnd = addr_RtlpCalloutEntryList;

        while(listCurrent && listCurrent != listEnd)
        {
            duint handler = (duint)node.handler;

            MemDecodePointer(&handler);
            Entries.push_back(handler);

            // Move to next element
            memset(&node, 0, sizeof(VECTORED_EXCEPTION_NODE));

            if(!MemRead(listCurrent, &node, sizeof(VECTORED_EXCEPTION_NODE)))
                break;

            listCurrent = (duint)node.ListEntry.Flink;
        }
    }

    // Otherwise try the Windows Vista or newer version
    return ExHandlerGetVCH(Entries, true);
}
Beispiel #14
0
bool ExHandlerGetVEH(std::vector<duint> & Entries)
{
    // Try the address for Windows XP first (or older)
    //
    // VECTORED_EXCEPTION_NODE RtlpCalloutEntryList;
    static duint addr_RtlpCalloutEntryList = 0;

#ifdef _WIN64
    auto symbol = "RtlpCalloutEntryList";
#else
    auto symbol = "_RtlpCalloutEntryList";
#endif
    if(addr_RtlpCalloutEntryList || valfromstring(symbol, &addr_RtlpCalloutEntryList))
    {
        // Read head entry
        auto list_head = addr_RtlpCalloutEntryList;
        duint cur_entry;

        if(!MemRead(list_head, &cur_entry, sizeof(cur_entry)))
            return false;
        auto count = 0;

        while(cur_entry != list_head && count++ < MAX_HANDLER_DEPTH)
        {
            VEH_ENTRY_XP entry;
            if(!MemRead(cur_entry, &entry, sizeof(entry)))
                return false;
            auto handler = entry.VectoredHandler;
            MemDecodePointer(&handler, false); //TODO: Windows XP doesn't allow a remote process to query this value
            Entries.push_back(handler);
            if(!MemRead(cur_entry, &cur_entry, sizeof(cur_entry)))
                return false;
        }
        return true;
    }

    // Otherwise try the Windows Vista or newer version
    return ExHandlerGetVCH(Entries, true);
}
Beispiel #15
0
bool cbSetWatchdog(int argc, char* argv[])
{
    if(argc < 2)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "No enough arguments for delwatch\n"));
        return false;
    }
    duint id;
    bool ok = valfromstring(argv[1], &id);
    if(!ok)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error expression in argument 1.\n"));
        return false;
    }
    WATCHDOGMODE mode;
    if(argc > 2)
    {
        if(_stricmp(argv[2], "disabled") == 0)
            mode = WATCHDOGMODE::MODE_DISABLED;
        else if(_stricmp(argv[2], "changed") == 0)
            mode = WATCHDOGMODE::MODE_CHANGED;
        else if(_stricmp(argv[2], "unchanged") == 0)
            mode = WATCHDOGMODE::MODE_UNCHANGED;
        else if(_stricmp(argv[2], "istrue") == 0)
            mode = WATCHDOGMODE::MODE_ISTRUE;
        else if(_stricmp(argv[2], "isfalse") == 0)
            mode = WATCHDOGMODE::MODE_ISFALSE;
        else
        {
            dputs(QT_TRANSLATE_NOOP("DBG", "Unknown watchdog mode.\n"));
            return false;
        }
    }
    else
        mode = (WatchGetWatchdogEnabled((unsigned int)id) == WATCHDOGMODE::MODE_DISABLED) ? WATCHDOGMODE::MODE_CHANGED : WATCHDOGMODE::MODE_DISABLED;
    WatchSetWatchdogMode((unsigned int)id, mode);
    return true;
}
Beispiel #16
0
bool cbSetWatchExpression(int argc, char* argv[])
{
    if(argc < 3)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "No enough arguments for SetWatchExpression"));
        return false;
    }
    duint id;
    bool ok = valfromstring(argv[1], &id);
    if(ok)
    {
        WATCHVARTYPE varType;
        if(argc > 3)
        {
            if(_stricmp(argv[3], "uint") == 0)
                varType = WATCHVARTYPE::TYPE_UINT;
            else if(_stricmp(argv[3], "int") == 0)
                varType = WATCHVARTYPE::TYPE_INT;
            else if(_stricmp(argv[3], "float") == 0)
                varType = WATCHVARTYPE::TYPE_FLOAT;
            else if(_stricmp(argv[3], "ascii") == 0)
                varType = WATCHVARTYPE::TYPE_ASCII;
            else if(_stricmp(argv[3], "unicode") == 0)
                varType = WATCHVARTYPE::TYPE_UNICODE;
            else
                varType = WATCHVARTYPE::TYPE_UINT;
        }
        else
            varType = WATCHVARTYPE::TYPE_UINT;
        WatchModifyExpr((unsigned int)id, argv[2], varType);
        return true;
    }
    else
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error expression in argument 1.\n"));
        return false;
    }
}
Beispiel #17
0
void SetMemoryIndexOrScale(XEDPARSE* Parse, const char* Value, InstOperand* Operand)
{
    // Index = register
    // Scale = 1, 2, 4, or 8
    REG registerVal = RegFromString(Value);
    ULONGLONG scale = 0;

    if(registerVal != REG_INVALID)
    {
        // It's the index
        Operand->Mem.Index      = true;
        Operand->Mem.IndexVal   = registerVal;
    }
    else if(valfromstring(Value, &scale))
    {
        // It's the scale
        Operand->Mem.Scale      = true;
        Operand->Mem.ScaleVal   = scale;
    }
    else
    {
        sprintf(Parse->error, "Unknown index or scale '%s'", Value);
    }
}
Beispiel #18
0
extern "C" DLL_EXPORT bool _dbg_valfromstring(const char* string, duint* value)
{
    return valfromstring(string, value);
}
Beispiel #19
0
bool cbDebugLoadLib(int argc, char* argv[])
{
    if(argc < 2)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error: you must specify the name of the DLL to load\n"));
        return false;
    }

    LoadLibThreadID = fdProcessInfo->dwThreadId;
    HANDLE LoadLibThread = ThreadGetHandle((DWORD)LoadLibThreadID);

    DLLNameMem = MemAllocRemote(0, strlen(argv[1]) + 1);
    ASMAddr = MemAllocRemote(0, 0x1000);

    if(!DLLNameMem || !ASMAddr)
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error: couldn't allocate memory in debuggee"));
        return false;
    }

    if(!MemWrite(DLLNameMem, argv[1], strlen(argv[1])))
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error: couldn't write process memory"));
        return false;
    }

    int size = 0;
    int counter = 0;
    duint LoadLibraryA = 0;
    char command[50] = "";
    char error[MAX_ERROR_SIZE] = "";

    GetFullContextDataEx(LoadLibThread, &backupctx);

    if(!valfromstring("kernel32:LoadLibraryA", &LoadLibraryA, false))
    {
        dputs(QT_TRANSLATE_NOOP("DBG", "Error: couldn't get kernel32:LoadLibraryA"));
        return false;
    }

    // Arch specific asm code
#ifdef _WIN64
    sprintf_s(command, "mov rcx, %p", DLLNameMem);
#else
    sprintf_s(command, "push %p", DLLNameMem);
#endif // _WIN64

    assembleat(ASMAddr, command, &size, error, true);
    counter += size;

#ifdef _WIN64
    sprintf_s(command, "mov rax, %p", LoadLibraryA);
    assembleat(ASMAddr + counter, command, &size, error, true);
    counter += size;
    sprintf_s(command, "call rax");
#else
    sprintf_s(command, "call %p", LoadLibraryA);
#endif // _WIN64

    assembleat(ASMAddr + counter, command, &size, error, true);
    counter += size;

    SetContextDataEx(LoadLibThread, UE_CIP, ASMAddr);
    auto ok = SetBPX(ASMAddr + counter, UE_SINGLESHOOT | UE_BREAKPOINT_TYPE_INT3, (void*)cbDebugLoadLibBPX);

    ThreadSuspendAll();
    ResumeThread(LoadLibThread);

    unlock(WAITID_RUN);

    return ok;
}