Stalker.follow中的transform中的Instruction的属性

此处介绍Stalker.followtransform中的指令=instruction的属性的详情:

Instruction有哪些属性

参考官网文档:Frida的Instruction(和其他相关资料),可以总结出:

  • Instruction的属性
    • address
    • next
    • size
    • mnemonic
    • opStr
    • operands
    • regsRead
    • regsWritten
    • groups
    • toString()
    • regsAccessed
    • toJSON()

如何打印Instruction的属性

打印对应的属性值的代码:

console.log("instruction: address=" + instruction.address
  + ",next=" + instruction.next
  + ",size=" + instruction.size
  + ",mnemonic=" + instruction.mnemonic
  + ",opStr=" + instruction.opStr
  + ",operands=" + JSON.stringify(instruction.operands)
  + ",regsRead=" + JSON.stringify(instruction.regsRead)
  + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
  + ",groups=" + JSON.stringify(instruction.groups)
  + ",toString()=" + instruction.toString()
);

输出效果:

instruction: address=0x10f4ecef4,next=0x4,size=4,mnemonic=ldr,opStr=x0, #0x10f4ecf78,operands=[{"type":"reg","value":"x0","access":"w"},{"type":"imm","value":"4551790456","access":"r"}],regsRead=[],regsWritten=[],groups=[],toString()=ldr x0, #0x10f4ecf78
[0x10f4ecef4] ldr x0, #0x10f4ecf78

instruction: address=0x10f4ecef8,next=0x4,size=4,mnemonic=bl,opStr=#0x1091a500c,operands=[{"type":"imm","value":"4447686668","access":"r"}],regsRead=[],regsWritten=["lr"],groups=["call","jump","branch_relative"],toString()=bl #0x1091a500c
[0x10f4ecef8] bl #0x1091a500c

FridaUtil的printInstructionInfo

以及后续新版中,加上:regsAccessedtoJSON()后,经过整理,已提取到工具类函数中:

https://github.com/crifan/JsFridaUtil/blob/main/frida/FridaUtil.js

中的:

  static printInstructionInfo(instruction){
    // Instruction: address=0x252c0edf8,toString()=br x10,next=0x4,size=4,mnemonic=br,opStr=x10,operands=[{"type":"reg","value":"x10","access":"r"}],regsAccessed={"read":["x10"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c0edf8","next":"0x4","size":4,"mnemonic":"br","opStr":"x10","operands":[{"type":"reg","value":"x10","access":"r"}],"regsAccessed":{"read":["x10"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
    console.log("Instruction: address=" + instruction.address
      + ",toString()=" + instruction.toString()
      + ",toJSON()=" + JSON.stringify(instruction.toJSON())
      // + ",next=" + instruction.next
      // + ",size=" + instruction.size
      // + ",mnemonic=" + instruction.mnemonic
      // + ",opStr=" + instruction.opStr
      // + ",operands=" + JSON.stringify(instruction.operands)
      // + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
      // + ",regsRead=" + JSON.stringify(instruction.regsRead)
      // + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
      // + ",groups=" + JSON.stringify(instruction.groups)
    )
  }

以及之前的某次输出的效果是:

Instruction: address=0x252c0eca4,toString()=stp x20, x19, [sp, #0x40],next=0x4,size=4,mnemonic=stp,opStr=x20, x19, [sp, #0x40],operands=[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],regsAccessed={"read":["x20","x19","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0eca4","next":"0x4","size":4,"mnemonic":"stp","opStr":"x20, x19, [sp, #0x40]","operands":[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],"regsAccessed":{"read":["x20","x19","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}

供参考。

Instruction的属性的来源

而这些属性的来源:

下面摘录其相关的核心代码:

capstone/Capstone.java

capstone/Capstone.java

  protected static class _cs_insn extends Structure {
    // instruction ID.
    public int id;
    // instruction address.
    public long address;
    // instruction size.
    public short size;
    // machine bytes of instruction.
    public byte[] bytes;
    // instruction mnemonic. NOTE: irrelevant for diet engine.
    public byte[] mnemonic;
    // instruction operands. NOTE: irrelevant for diet engine.
    public byte[] op_str;
    // detail information of instruction.
    public _cs_detail.ByReference cs_detail;

...

  public static class CsInsn {
    private Pointer csh;
    private CS cs;
    private _cs_insn raw;
    private int arch;

    // instruction ID.
    public int id;
    // instruction address.
    public long address;
    // instruction size.
    public short size;
    // Machine bytes of this instruction, with number of bytes indicated by size above
    public byte[] bytes;
    // instruction mnemonic. NOTE: irrelevant for diet engine.
    public String mnemonic;
    // instruction operands. NOTE: irrelevant for diet engine.
    public String opStr;
    // list of all implicit registers being read.
    public short[] regsRead;
    // list of all implicit registers being written.
    public short[] regsWrite;
    // list of semantic groups this instruction belongs to.
    public byte[] groups;
    public OpInfo operands;

capstone/__init__.py

capstone/__init__.py

中相关核心代码:

class _cs_insn(ctypes.Structure):
    _fields_ = (
        ('id', ctypes.c_uint),
        ('alias_id', ctypes.c_uint64),
        ('address', ctypes.c_uint64),
        ('size', ctypes.c_uint16),
        ('bytes', ctypes.c_ubyte * 24),
        ('mnemonic', ctypes.c_char * 32),
        ('op_str', ctypes.c_char * 160),
        ('is_alias', ctypes.c_bool),
        ('usesAliasDetails', ctypes.c_bool),
        ('illegal', ctypes.c_bool),
        ('detail', ctypes.POINTER(_cs_detail)),
    )

...

# Python-style class to disasm code
class CsInsn(object):
    def __init__(self, cs, all_info):
        self._raw = copy_ctypes(all_info)
        self._cs = cs
        if self._cs._detail and not self.is_invalid_insn():
            # save detail
            self._raw.detail = ctypes.pointer(all_info.detail._type_())
            ctypes.memmove(ctypes.byref(self._raw.detail[0]), ctypes.byref(all_info.detail[0]),
                           ctypes.sizeof(type(all_info.detail[0])))

    def __repr__(self):
        return '<CsInsn 0x%x [%s]: %s %s>' % (self.address, self.bytes.hex(), self.mnemonic, self.op_str)

    # return if the instruction is invalid
    def is_invalid_insn(self):
        arch = self._cs.arch
        if arch == CS_ARCH_EVM:
            return self.id == evm.EVM_INS_INVALID
        else:
            return self.id == 0

    # return instruction's ID.
    @property
    def id(self):
        return self._raw.id

    # return instruction's address.
    @property
    def address(self):
        return self._raw.address

    # return instruction's size.
    @property
    def size(self):
        return self._raw.size

    # return instruction's is_alias flag
    @property
    def is_alias(self):
        return self._raw.is_alias

    # return instruction's illegal flag
    # Set if instruction can be decoded but is invalid
    # due to context or illegal operands.
    @property
    def illegal(self):
        return self._raw.illegal

    # return instruction's alias_id
    @property
    def alias_id(self):
        return self._raw.alias_id

    # return instruction's flag if it uses alias details
    @property
    def uses_alias_details(self):
        return self._raw.usesAliasDetails

    # return instruction's machine bytes (which should have @size bytes).
    @property
    def bytes(self):
        return bytearray(self._raw.bytes)[:self._raw.size]

    # return instruction's mnemonic.
    @property
    def mnemonic(self):
        if self._cs._diet:
            # Diet engine cannot provide @mnemonic.
            raise CsError(CS_ERR_DIET)

        return self._raw.mnemonic.decode('ascii')

    # return instruction's operands (in string).
    @property
    def op_str(self):
        if self._cs._diet:
            # Diet engine cannot provide @op_str.
            raise CsError(CS_ERR_DIET)

        return self._raw.op_str.decode('ascii')

    # return list of all implicit registers being read.
    @property
    def regs_read(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @regs_read.
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.regs_read[:self._raw.detail.contents.regs_read_count]

        raise CsError(CS_ERR_DETAIL)

    # return list of all implicit registers being modified
    @property
    def regs_write(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @regs_write
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.regs_write[:self._raw.detail.contents.regs_write_count]

        raise CsError(CS_ERR_DETAIL)

    # return list of semantic groups this instruction belongs to.
    @property
    def groups(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @groups
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.groups[:self._raw.detail.contents.groups_count]

        raise CsError(CS_ERR_DETAIL)

    # return whether instruction has writeback operands.
    @property
    def writeback(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @writeback.
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.writeback

        raise CsError(CS_ERR_DETAIL)

frida-gum/bindings/gumjs/gumquickinstruction.c

frida-gum/bindings/gumjs/gumquickinstruction.c at main · frida/frida-gum

的相关核心代码:

static const JSCFunctionListEntry gumjs_instruction_entries[] =
{
  JS_CGETSET_DEF ("address", gumjs_instruction_get_address, NULL),
  JS_CGETSET_DEF ("next", gumjs_instruction_get_next, NULL),
  JS_CGETSET_DEF ("size", gumjs_instruction_get_size, NULL),
  JS_CGETSET_DEF ("mnemonic", gumjs_instruction_get_mnemonic, NULL),
  JS_CGETSET_DEF ("opStr", gumjs_instruction_get_op_str, NULL),
  JS_CGETSET_DEF ("operands", gumjs_instruction_get_operands, NULL),
  JS_CGETSET_DEF ("regsAccessed", gumjs_instruction_get_regs_accessed, NULL),
  JS_CGETSET_DEF ("regsRead", gumjs_instruction_get_regs_read, NULL),
  JS_CGETSET_DEF ("regsWritten", gumjs_instruction_get_regs_written, NULL),
  JS_CGETSET_DEF ("groups", gumjs_instruction_get_groups, NULL),
  JS_CFUNC_DEF ("toString", 0, gumjs_instruction_to_string),
  JS_CFUNC_DEF ("toJSON", 0, gumjs_instruction_to_json),
};

results matching ""

    No results matching ""