class Metasm::Python

Constants

CMP_OP

Public Class Methods

new(prog = nil) click to toggle source
Calls superclass method
# File metasm/cpu/python/main.rb, line 10
def initialize(prog = nil)
        super()
        @program = prog
        @endianness = (prog.respond_to?(:endianness) ? prog.endianness : :little)
        @size = (prog.respond_to?(:size) ? prog.size : 32)
end

Public Instance Methods

addop(name, bin, *args) click to toggle source
# File metasm/cpu/python/opcodes.rb, line 12
def addop(name, bin, *args)
        o = Opcode.new(name)
        o.bin = bin

        args.each { |a|
                o.args << a if @valid_args[a]
                o.props[a] = true if @valid_props[a]
        }
        o.args << :i16 if o.bin >= 90 and o.props.empty?      # HAVE_ARGUMENT

        @opcode_list << o
end
backtrace_is_function_return(expr, di=nil) click to toggle source
# File metasm/cpu/python/decode.rb, line 112
def backtrace_is_function_return(expr, di=nil)
        #Expression[expr].reduce == Expression['wtf']
end
build_bin_lookaside() click to toggle source
# File metasm/cpu/python/decode.rb, line 11
def build_bin_lookaside
        opcode_list.inject({}) { |la, op| la.update op.bin => op }
end
decode_findopcode(edata) click to toggle source
# File metasm/cpu/python/decode.rb, line 15
def decode_findopcode(edata)
        di = DecodedInstruction.new(self)

        byte = edata.decode_imm(:u8, :little)

        di if di.opcode = @bin_lookaside[byte]
end
decode_instr_interpret(di, addr) click to toggle source
# File metasm/cpu/python/decode.rb, line 50
def decode_instr_interpret(di, addr)
        case di.opcode.name
        when 'LOAD_CONST'
                if c = prog_code(addr)
                        cst = c[:consts][di.instruction.args.first.reduce]
                        if cst.kind_of? Hash and cst[:type] == :code
                                di.add_comment "lambda #{Expression[cst[:fileoff]]}"
                        else
                                di.add_comment cst.inspect
                        end
                end
        when 'LOAD_NAME', 'LOAD_ATTR', 'LOAD_GLOBAL', 'STORE_NAME', 'IMPORT_NAME', 'LOAD_FAST'
                if c = prog_code(addr)
                        di.add_comment c[:names][di.instruction.args.first.reduce].inspect
                end
        end
        di
end
decode_instr_op(edata, di) click to toggle source
# File metasm/cpu/python/decode.rb, line 23
def decode_instr_op(edata, di)
        di.bin_length = 1

        di.instruction.opname = di.opcode.name

        di.opcode.args.each { |a|
                case a
                when :cmp
                        di.bin_length += 2
                        v = edata.decode_imm(:i16, @endianness)
                        di.instruction.args << (CMP_OP[v] || Expression[v])
                when :i16
                        di.bin_length += 2
                        di.instruction.args << Expression[edata.decode_imm(:i16, @endianness)]
                when :u8
                        di.bin_length += 1
                        di.instruction.args << Expression[edata.decode_imm(:u8, @endianness)]
                else
                        raise "unsupported arg #{a.inspect}"
                end
        }

        return if edata.ptr > edata.length

        di
end
get_xrefs_x(dasm, di) click to toggle source
# File metasm/cpu/python/decode.rb, line 82
def get_xrefs_x(dasm, di)
        return [] if not di.opcode.props[:setip]

        arg = case di.opcode.name
                when 'JUMP_FORWARD', 'FOR_ITER'
                        # relative offset
                        di.instruction.args.last.reduce + di.next_addr
                when 'CALL_FUNCTION_VAR'
                        'lol'
                when /CALL/
                                :unknown
                else
                        # absolute offset from :code start
                        off = di.instruction.args.last.reduce
                        if c = prog_code(di)
                                off += c[:fileoff]
                        end
                        off
                end

        [Expression[(arg.kind_of?(Var) ? arg.symbolic : arg)]]
end
init_backtrace_binding() click to toggle source
# File metasm/cpu/python/decode.rb, line 69
def init_backtrace_binding
        @backtrace_binding ||= {}

        opcode_list.each { |op|
                binding = case op
                          when 'nop'; lambda { |*a| {} }
                          end
                @backtrace_binding[op] ||= binding if binding
        }

        @backtrace_binding
end
init_opcode_list() click to toggle source
# File metasm/cpu/python/opcodes.rb, line 25
def init_opcode_list
        @opcode_list = []

        @valid_args[:u8] = true
        @valid_args[:i16] = true
        @valid_args[:cmp] = true

        addop 'STOP_CODE', 0, :stopexec
        addop 'POP_TOP', 1
        addop 'ROT_TWO', 2
        addop 'ROT_THREE', 3
        addop 'DUP_TOP', 4
        addop 'ROT_FOUR', 5
        addop 'NOP', 9

        addop 'UNARY_POSITIVE', 10
        addop 'UNARY_NEGATIVE', 11
        addop 'UNARY_NOT', 12
        addop 'UNARY_CONVERT', 13

        addop 'UNARY_INVERT', 15

        addop 'BINARY_POWER', 19

        addop 'BINARY_MULTIPLY', 20
        addop 'BINARY_DIVIDE', 21
        addop 'BINARY_MODULO', 22
        addop 'BINARY_ADD', 23
        addop 'BINARY_SUBTRACT', 24
        addop 'BINARY_SUBSCR', 25
        addop 'BINARY_FLOOR_DIVIDE', 26
        addop 'BINARY_TRUE_DIVIDE', 27
        addop 'INPLACE_FLOOR_DIVIDE', 28
        addop 'INPLACE_TRUE_DIVIDE', 29

        addop 'SLICE', 30
        addop 'SLICE_1', 31
        addop 'SLICE_2', 32
        addop 'SLICE_3', 33

        addop 'STORE_SLICE', 40
        addop 'STORE_SLICE_1', 41
        addop 'STORE_SLICE_2', 42
        addop 'STORE_SLICE_3', 43

        addop 'DELETE_SLICE', 50
        addop 'DELETE_SLICE_1', 51
        addop 'DELETE_SLICE_2', 52
        addop 'DELETE_SLICE_3', 53

        addop 'STORE_MAP', 54
        addop 'INPLACE_ADD', 55
        addop 'INPLACE_SUBTRACT', 56
        addop 'INPLACE_MULTIPLY', 57
        addop 'INPLACE_DIVIDE', 58
        addop 'INPLACE_MODULO', 59
        addop 'STORE_SUBSCR', 60
        addop 'DELETE_SUBSCR', 61

        addop 'BINARY_LSHIFT', 62
        addop 'BINARY_RSHIFT', 63
        addop 'BINARY_AND', 64
        addop 'BINARY_XOR', 65
        addop 'BINARY_OR', 66
        addop 'INPLACE_POWER', 67
        addop 'GET_ITER', 68

        addop 'PRINT_EXPR', 70
        addop 'PRINT_ITEM', 71
        addop 'PRINT_NEWLINE', 72
        addop 'PRINT_ITEM_TO', 73
        addop 'PRINT_NEWLINE_TO', 74
        addop 'INPLACE_LSHIFT', 75
        addop 'INPLACE_RSHIFT', 76
        addop 'INPLACE_AND', 77
        addop 'INPLACE_XOR', 78
        addop 'INPLACE_OR', 79
        addop 'BREAK_LOOP', 80
        addop 'WITH_CLEANUP', 81
        addop 'LOAD_LOCALS', 82
        addop 'RETURN_VALUE', 83
        addop 'IMPORT_STAR', 84
        addop 'EXEC_STMT', 85
        addop 'YIELD_VALUE', 86
        addop 'POP_BLOCK', 87
        addop 'END_FINALLY', 88
        addop 'BUILD_CLASS', 89

        #addop 'HAVE_ARGUMENT', 90      #/* Opcodes from here have an argument: */

        addop 'STORE_NAME', 90      #/* Index in name list */
        addop 'DELETE_NAME', 91      #/* "" */
        addop 'UNPACK_SEQUENCE', 92      #/* Number of sequence items */
        addop 'FOR_ITER', 93, :setip
        addop 'LIST_APPEND', 94

        addop 'STORE_ATTR', 95      #/* Index in name list */
        addop 'DELETE_ATTR', 96      #/* "" */
        addop 'STORE_GLOBAL', 97      #/* "" */
        addop 'DELETE_GLOBAL', 98      #/* "" */
        addop 'DUP_TOPX', 99      #/* number of items to duplicate */
        addop 'LOAD_CONST', 100     #/* Index in const list */
        addop 'LOAD_NAME', 101     #/* Index in name list */
        addop 'BUILD_TUPLE', 102     #/* Number of tuple items */
        addop 'BUILD_LIST', 103     #/* Number of list items */
        addop 'BUILD_SET', 104     #/* Number of set items */
        addop 'BUILD_MAP', 105     #/* Always zero for now */
        addop 'LOAD_ATTR', 106     #/* Index in name list */
        addop 'COMPARE_OP', 107, :cmp     #/* Comparison operator */
        addop 'IMPORT_NAME', 108     #/* Index in name list */
        addop 'IMPORT_FROM', 109     #/* Index in name list */
        addop 'JUMP_FORWARD', 110, :setip, :stopexec     #/* Number of bytes to skip */

        addop 'JUMP_IF_FALSE_OR_POP', 111, :setip #/* Target byte offset from beginning of code */
        addop 'JUMP_IF_TRUE_OR_POP', 112, :setip #/* "" */
        addop 'JUMP_ABSOLUTE', 113, :setip, :stopexec     #/* "" */
        addop 'POP_JUMP_IF_FALSE', 114, :setip   #/* "" */
        addop 'POP_JUMP_IF_TRUE', 115, :setip    #/* "" */

        addop 'LOAD_GLOBAL', 116     #/* Index in name list */

        addop 'CONTINUE_LOOP', 119     #/* Start of loop (absolute) */
        addop 'SETUP_LOOP', 120     #/* Target address (relative) */
        addop 'SETUP_EXCEPT', 121     #/* "" */
        addop 'SETUP_FINALLY', 122     #/* "" */

        addop 'LOAD_FAST', 124     #/* Local variable number */
        addop 'STORE_FAST', 125     #/* Local variable number */
        addop 'DELETE_FAST', 126     #/* Local variable number */

        addop 'RAISE_VARARGS', 130     #/* Number of raise arguments (1, 2 or 3) */
        #/* CALL_FUNCTION_XXX opcodes defined below depend on this definition */
        addop 'CALL_FUNCTION', 131, :u8, :u8, :setip     #/* #args + (#kwargs<<8) */
        addop 'MAKE_FUNCTION', 132     #/* #defaults */
        addop 'BUILD_SLICE', 133     #/* Number of items */

        addop 'MAKE_CLOSURE', 134     #/* #free vars */
        addop 'LOAD_CLOSURE', 135     #/* Load free variable from closure */
        addop 'LOAD_DEREF', 136     #/* Load and dereference from closure cell */
        addop 'STORE_DEREF', 137     #/* Store into cell */

        #/* The next 3 opcodes must be contiguous and satisfy (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1  */
        addop 'CALL_FUNCTION_VAR', 140, :u8, :u8, :setip  #/* #args + (#kwargs<<8) */
        addop 'CALL_FUNCTION_KW', 141, :u8, :u8, :setip  #/* #args + (#kwargs<<8) */
        addop 'CALL_FUNCTION_VAR_KW', 142, :u8, :u8, :setip  #/* #args + (#kwargs<<8) */

        addop 'SETUP_WITH', 143

        #/* Support for opargs more than 16 bits long */
        addop 'EXTENDED_ARG', 145

        addop 'SET_ADD', 146
        addop 'MAP_ADD', 147
end
prog_code(addr) click to toggle source
# File metasm/cpu/python/decode.rb, line 105
def prog_code(addr)
        addr = addr.address if addr.kind_of? DecodedInstruction
        @last_prog_code ||= nil
        return @last_prog_code if @last_prog_code and @last_prog_code[:fileoff] <= addr and @last_prog_code[:fileoff] + @last_prog_code[:code].length > addr
        @last_prog_code = @program.code_at_off(addr) if @program
end