Пример #1
0
uint disasmnext(unsigned char* data, uint base, uint size, uint ip, int n)
{
    int i;
    uint cmdsize;
    unsigned char* pdata;

    // Reset Disasm Structure
    Capstone cp;

    if(data == NULL)
        return 0;

    if(ip >= size)
        ip = size - 1;

    if(n <= 0)
        return ip;

    pdata = data + ip;
    size -= ip;

    for(i = 0; i < n && size > 0; i++)
    {
        if(!cp.Disassemble(0, pdata, (int)size))
            cmdsize = 1;
        else
            cmdsize = cp.Size();

        pdata += cmdsize;
        ip += cmdsize;
        size -= cmdsize;
    }

    return ip;
}
Пример #2
0
int disasmgetsize(uint addr, unsigned char* data)
{
    Capstone cp;
    if(!cp.Disassemble(addr, data, MAX_DISASM_BUFFER))
        return 1;
    return cp.Size();
}
Пример #3
0
void disasmget(unsigned char* buffer, uint addr, DISASM_INSTR* instr)
{
    if(!DbgIsDebugging())
    {
        if(instr)
            instr->argcount = 0;
        return;
    }
    memset(instr, 0, sizeof(DISASM_INSTR));
    Capstone cp;
    if(!cp.Disassemble(addr, buffer, MAX_DISASM_BUFFER))
    {
        strcpy_s(instr->instruction, "???");
        instr->instr_size = 1;
        instr->type = instr_normal;
        instr->argcount = 0;
        return;
    }
    const cs_insn* cpInstr = cp.GetInstr();
    sprintf_s(instr->instruction, "%s %s", cpInstr->mnemonic, cpInstr->op_str);
    const cs_x86 & x86 = cpInstr->detail->x86;
    instr->instr_size = cpInstr->size;
    if(cp.InGroup(CS_GRP_JUMP) || cp.IsLoop() || cp.InGroup(CS_GRP_RET) || cp.InGroup(CS_GRP_CALL))
        instr->type = instr_branch;
    else if(strstr(cpInstr->op_str, "sp") || strstr(cpInstr->op_str, "bp"))
        instr->type = instr_stack;
    else
        instr->type = instr_normal;
    instr->argcount = cp.x86().op_count <= 3 ? cp.x86().op_count : 3;
    for(int i = 0; i < instr->argcount; i++)
        HandleCapstoneOperand(cp, i, &instr->arg[i]);
}
Пример #4
0
uint disasmback(unsigned char* data, uint base, uint size, uint ip, int n)
{
    int i;
    uint abuf[131], addr, back, cmdsize;
    unsigned char* pdata;

    // Reset Disasm Structure
    Capstone cp;

    // Check if the pointer is not null
    if(data == NULL)
        return 0;

    // Round the number of back instructions to 127
    if(n < 0)
        n = 0;
    else if(n > 127)
        n = 127;

    // Check if the instruction pointer ip is not outside the memory range
    if(ip >= size)
        ip = size - 1;

    // Obvious answer
    if(n == 0)
        return ip;

    if(ip < (uint)n)
        return ip;

    back = MAX_DISASM_BUFFER * (n + 3); // Instruction length limited to 16

    if(ip < back)
        back = ip;

    addr = ip - back;

    pdata = data + addr;

    for(i = 0; addr < ip; i++)
    {
        abuf[i % 128] = addr;

        if(!cp.Disassemble(0, pdata, (int)size))
            cmdsize = 1;
        else
            cmdsize = cp.Size();

        pdata += cmdsize;
        addr += cmdsize;
        back -= cmdsize;
        size -= cmdsize;
    }

    if(i < n)
        return abuf[0];
    else
        return abuf[(i - n + 128) % 128];
}
Пример #5
0
int RefFindInRange(duint scanStart, duint scanSize, CBREF Callback, void* UserData, bool Silent, REFINFO & refInfo, Capstone & cp, bool initCallBack, CBPROGRESS cbUpdateProgress)
{
    // Allocate and read a buffer from the remote process
    Memory<unsigned char*> data(scanSize, "reffind:data");

    if(!MemRead(scanStart, data(), scanSize))
    {
        if(!Silent)
            dprintf("Error reading memory in reference search\n");

        return 0;
    }

    if(initCallBack)
        Callback(0, 0, &refInfo);

    //concurrency::parallel_for(duint (0), scanSize, [&](duint i)
    for(duint i = 0; i < scanSize;)
    {
        // Print the progress every 4096 bytes
        if((i % 0x1000) == 0)
        {
            // Percent = (current / total) * 100
            // Integer = floor(percent)
            int percent = (int)floor(((float)i / (float)scanSize) * 100.0f);

            cbUpdateProgress(percent);
        }

        // Disassemble the instruction
        int disasmMaxSize = min(MAX_DISASM_BUFFER, (int)(scanSize - i)); // Prevent going past the boundary
        int disasmLen = 1;

        if(cp.Disassemble(scanStart, data() + i, disasmMaxSize))
        {
            BASIC_INSTRUCTION_INFO basicinfo;
            fillbasicinfo(&cp, &basicinfo);

            if(Callback(&cp, &basicinfo, &refInfo))
                refInfo.refcount++;

            disasmLen = cp.Size();
        }
        else
        {
            // Invalid instruction detected, so just skip the byte
        }

        scanStart += disasmLen;
        i += disasmLen;
    }

    cbUpdateProgress(100);
    return refInfo.refcount;
}
Пример #6
0
const char* disasmtext(uint addr)
{
    unsigned char buffer[MAX_DISASM_BUFFER] = "";
    DbgMemRead(addr, buffer, sizeof(buffer));
    Capstone cp;
    static char instruction[64] = "";
    if(!cp.Disassemble(addr, buffer))
        strcpy_s(instruction, "???");
    else
        sprintf_s(instruction, "%s %s", cp.GetInstr()->mnemonic, cp.GetInstr()->op_str);
    return instruction;
}
Пример #7
0
bool disasmfast(const unsigned char* data, duint addr, BASIC_INSTRUCTION_INFO* basicinfo)
{
    if(!data || !basicinfo)
        return false;
    Capstone cp;
    if(!cp.Disassemble(addr, data, MAX_DISASM_BUFFER))
    {
        strcpy_s(basicinfo->instruction, "???");
        basicinfo->size = 1;
        return false;
    }
    fillbasicinfo(&cp, basicinfo);
    return true;
}
Пример #8
0
void LinearPass::AnalysisWorker(duint Start, duint End, BBlockArray* Blocks)
{
    Capstone disasm;

    duint blockBegin = Start;        // BBlock starting virtual address
    duint blockEnd = 0;              // BBlock ending virtual address

    bool blockPrevPad = false;       // Indicator if the last instruction was padding
    BasicBlock* lastBlock = nullptr; // Avoid an expensive call to std::vector::back()

    int insnCount = 0;               // Temporary number of instructions counted for a block

    for(duint i = Start; i < End;)
    {
        if(!disasm.Disassemble(i, TranslateAddress(i), int(End - i)))
        {
            // Skip instructions that can't be determined
            i++;
            continue;
        }

        // Increment counters
        i += disasm.Size();
        blockEnd = i;
        insnCount++;

        // The basic block ends here if it is a branch
        bool call = disasm.InGroup(CS_GRP_CALL);    // CALL
        bool jmp = disasm.InGroup(CS_GRP_JUMP);     // JUMP
        bool ret = disasm.InGroup(CS_GRP_RET);      // RETURN
        bool padding = disasm.IsFilling();          // INSTRUCTION PADDING

        if(padding)
        {
            // PADDING is treated differently. They are all created as their
            // own separate block for more analysis later.
            duint realBlockEnd = blockEnd - disasm.Size();

            if((realBlockEnd - blockBegin) > 0)
            {
                // The next line terminates the BBlock before the INT instruction.
                // Early termination, faked as an indirect JMP. Rare case.
                lastBlock = CreateBlockWorker(Blocks, blockBegin, realBlockEnd, false, false, false, false);
                lastBlock->SetFlag(BASIC_BLOCK_FLAG_PREPAD);

                blockBegin = realBlockEnd;
                lastBlock->InstrCount = insnCount;
                insnCount = 0;
            }
        }

        if(call || jmp || ret || padding)
        {
            // Was this a padding instruction?
            if(padding && blockPrevPad)
            {
                // Append it to the previous block
                lastBlock->VirtualEnd = blockEnd;
            }
            else
            {
                // Otherwise use the default route: create a new entry
                auto block = lastBlock = CreateBlockWorker(Blocks, blockBegin, blockEnd, call, jmp, ret, padding);

                // Counters
                lastBlock->InstrCount = insnCount;
                insnCount = 0;

                if(!padding)
                {
                    // Check if absolute jump, regardless of operand
                    if(disasm.GetId() == X86_INS_JMP)
                        block->SetFlag(BASIC_BLOCK_FLAG_ABSJMP);

                    // Figure out the operand type(s)
                    const auto & operand = disasm.x86().operands[0];

                    if(operand.type == X86_OP_IMM)
                    {
                        // Branch target immediate
                        block->Target = (duint)operand.imm;
                    }
                    else
                    {
                        // Indirects (no operand, register, or memory)
                        block->SetFlag(BASIC_BLOCK_FLAG_INDIRECT);

                        if(operand.type == X86_OP_MEM &&
                                operand.mem.base == X86_REG_RIP &&
                                operand.mem.index == X86_REG_INVALID &&
                                operand.mem.scale == 1)
                        {
                            /*
                            block->SetFlag(BASIC_BLOCK_FLAG_INDIRPTR);
                            block->Target = (duint)operand.mem.disp;
                            */
                        }
                    }
                }
            }

            // Reset the loop variables
            blockBegin = i;
            blockPrevPad = padding;
        }
    }
}