1 2import logging 3 4from archinfo.arch_soot import (ArchSoot, SootAddressDescriptor, SootArgument, 5 SootMethodDescriptor) 6 7from . import JNISimProcedure 8from ...calling_conventions import SimCCSoot 9from ...engines.soot.method_dispatcher import resolve_method 10 11l = logging.getLogger('angr.procedures.java_jni.callmethod') 12 13# pylint: disable=arguments-differ,unused-argument 14 15# 16# GetMethodID / GetStaticMethodID 17# 18 19class GetMethodID(JNISimProcedure): 20 21 return_ty = 'reference' 22 23 def run(self, ptr_env, class_, ptr_method_name, ptr_method_sig): 24 25 method_class = self.state.jni_references.lookup(class_) 26 method_name = self._load_string_from_native_memory(ptr_method_name) 27 method_sig = self._load_string_from_native_memory(ptr_method_sig) 28 29 # derive parameter type from signature 30 params, _ = ArchSoot.decode_method_signature(method_sig) 31 32 # create method ID and return reference to it 33 method_id = SootMethodDescriptor(method_class.name, method_name, params) 34 return self.state.jni_references.create_new_reference(method_id) 35 36# 37# Call<Type>Method / CallNonvirtual<Type>Method / CallStatic<Type>Method 38# 39 40class CallMethodBase(JNISimProcedure): 41 42 return_ty = None 43 44 def _invoke(self, method_id, obj=None, dynamic_dispatch=True, args_in_array=None): 45 # get invoke target 46 class_name = obj.type if dynamic_dispatch else method_id.class_name 47 invoke_target = resolve_method(self.state, method_id.name, class_name, method_id.params) 48 invoke_addr = SootAddressDescriptor(invoke_target, 0, 0) 49 50 # get args 51 no_of_args = len(invoke_target.params) 52 if args_in_array is not None: 53 arg_values = self._get_arg_values_from_array(args_in_array, no_of_args) 54 else: 55 arg_values = self._get_arg_values(no_of_args) 56 57 # setup java args 58 java_args = self._setup_java_args(arg_values, invoke_target, this_ref=obj) 59 60 # call java method 61 # => after returning, the execution will be continued in _return_result_of_computation 62 self.call(invoke_addr, java_args, "return_from_invocation", cc=SimCCSoot(ArchSoot())) 63 64 def _get_arg_values(self, no_of_args): 65 return [ self.arg(self.num_args+idx).to_claripy() for idx in range(no_of_args) ] 66 67 def _get_arg_values_from_array(self, array, no_of_args): 68 return self._load_from_native_memory(addr=array, data_size=self.arch.bytes, 69 no_of_elements=no_of_args, return_as_list=True) 70 71 def _setup_java_args(self, arg_values, method_id, this_ref=None): 72 args = [] 73 74 # if available, add 'this' reference 75 if this_ref: 76 args += [ SootArgument(this_ref, this_ref.type, is_this_ref=True) ] 77 78 # function arguments 79 for arg_value_, arg_type in zip(arg_values, method_id.params): 80 81 if arg_type in ArchSoot.primitive_types: 82 # argument has a primitive integral type 83 # => cast native value to java type 84 arg_value = self.project.simos.cast_primitive(self.state, 85 value=arg_value_, 86 to_type=arg_type) 87 88 else: 89 # argument has a relative type 90 # => lookup java object 91 arg_value = self.state.jni_references.lookup(arg_value_) 92 93 args += [ SootArgument(arg_value, arg_type) ] 94 95 return args 96 97 def _return_from_invocation(self): 98 if self.return_ty != 'void': 99 ret_value = self.state.javavm_registers.load('invoke_return_value') 100 if self.return_ty == 'reference': 101 return self.state.jni_references.create_new_reference(ret_value) 102 else: 103 return ret_value 104 105# 106# Call<Type>Method 107# 108 109class CallMethod(CallMethodBase): 110 def run(self, ptr_env, obj_, method_id_): 111 method_id = self.state.jni_references.lookup(method_id_) 112 obj = self.state.jni_references.lookup(obj_) 113 self._invoke(method_id, obj, dynamic_dispatch=True) 114 115 def return_from_invocation(self, ptr_env, obj_, method_id_): 116 return self._return_from_invocation() 117 118class CallMethodA(CallMethodBase): 119 def run(self, ptr_env, obj_, method_id_, ptr_args): 120 method_id = self.state.jni_references.lookup(method_id_) 121 obj = self.state.jni_references.lookup(obj_) 122 self._invoke(method_id, obj, dynamic_dispatch=True, args_in_array=ptr_args) 123 124 def return_from_invocation(self, ptr_env, obj_, method_id_, ptr_args): 125 return self._return_from_invocation() 126 127class CallObjectMethod(CallMethod): 128 return_ty = 'reference' 129class CallBooleanMethod(CallMethod): 130 return_ty = 'boolean' 131class CallByteMethod(CallMethod): 132 return_ty = 'byte' 133class CallCharMethod(CallMethod): 134 return_ty = 'char' 135class CallShortMethod(CallMethod): 136 return_ty = 'short' 137class CallIntMethod(CallMethod): 138 return_ty = 'int' 139class CallLongMethod(CallMethod): 140 return_ty = 'long' 141class CallVoidMethod(CallMethod): 142 return_ty = 'void' 143class CallObjectMethodA(CallMethodA): 144 return_ty = 'reference' 145class CallBooleanMethodA(CallMethodA): 146 return_ty = 'boolean' 147class CallByteMethodA(CallMethodA): 148 return_ty = 'byte' 149class CallCharMethodA(CallMethodA): 150 return_ty = 'char' 151class CallShortMethodA(CallMethodA): 152 return_ty = 'short' 153class CallIntMethodA(CallMethodA): 154 return_ty = 'int' 155class CallLongMethodA(CallMethodA): 156 return_ty = 'long' 157class CallVoidMethodA(CallMethodA): 158 return_ty = 'void' 159 160# 161# CallNonVirtual<Type>Method 162# 163 164class CallNonvirtualMethod(CallMethodBase): 165 def run(self, ptr_env, obj_, class_, method_id_): 166 method_id = self.state.jni_references.lookup(method_id_) 167 obj = self.state.jni_references.lookup(obj_) 168 self._invoke(method_id, obj, dynamic_dispatch=False) 169 170 def return_from_invocation(self, ptr_env, obj_, class_, method_id_): 171 return self._return_from_invocation() 172 173class CallNonvirtualMethodA(CallMethodBase): 174 def run(self, ptr_env, obj_, method_id_, ptr_args): 175 method_id = self.state.jni_references.lookup(method_id_) 176 obj = self.state.jni_references.lookup(obj_) 177 self._invoke(method_id, obj, dynamic_dispatch=False, args_in_array=ptr_args) 178 179 def return_from_invocation(self, ptr_env, obj_, method_id_, ptr_args): 180 return self._return_from_invocation() 181 182class CallNonvirtualObjectMethod(CallNonvirtualMethod): 183 return_ty = 'reference' 184class CallNonvirtualBooleanMethod(CallNonvirtualMethod): 185 return_ty = 'boolean' 186class CallNonvirtualByteMethod(CallNonvirtualMethod): 187 return_ty = 'byte' 188class CallNonvirtualCharMethod(CallNonvirtualMethod): 189 return_ty = 'char' 190class CallNonvirtualShortMethod(CallNonvirtualMethod): 191 return_ty = 'short' 192class CallNonvirtualIntMethod(CallNonvirtualMethod): 193 return_ty = 'int' 194class CallNonvirtualLongMethod(CallNonvirtualMethod): 195 return_ty = 'long' 196class CallNonvirtualVoidMethod(CallNonvirtualMethod): 197 return_ty = 'void' 198class CallNonvirtualObjectMethodA(CallNonvirtualMethodA): 199 return_ty = 'reference' 200class CallNonvirtualBooleanMethodA(CallNonvirtualMethodA): 201 return_ty = 'boolean' 202class CallNonvirtualByteMethodA(CallNonvirtualMethodA): 203 return_ty = 'byte' 204class CallNonvirtualCharMethodA(CallNonvirtualMethodA): 205 return_ty = 'char' 206class CallNonvirtualShortMethodA(CallNonvirtualMethodA): 207 return_ty = 'short' 208class CallNonvirtualIntMethodA(CallNonvirtualMethodA): 209 return_ty = 'int' 210class CallNonvirtualLongMethodA(CallNonvirtualMethodA): 211 return_ty = 'long' 212class CallNonvirtualVoidMethodA(CallNonvirtualMethodA): 213 return_ty = 'void' 214 215# 216# CallStatic<Type>Method 217# 218 219class CallStaticMethod(CallMethodBase): 220 def run(self, ptr_env, class_, method_id_): 221 method_id = self.state.jni_references.lookup(method_id_) 222 self._invoke(method_id, dynamic_dispatch=False) 223 224 def return_from_invocation(self, ptr_env, class_, method_id_): 225 return self._return_from_invocation() 226 227class CallStaticMethodA(CallMethodBase): 228 def run(self, ptr_env, obj_, method_id_, ptr_args): 229 method_id = self.state.jni_references.lookup(method_id_) 230 self._invoke(method_id, dynamic_dispatch=False, args_in_array=ptr_args) 231 232 def return_from_invocation(self, ptr_env, class_, method_id_, ptr_args): 233 return self._return_from_invocation() 234 235class CallStaticObjectMethod(CallStaticMethod): 236 return_ty = 'reference' 237class CallStaticBooleanMethod(CallStaticMethod): 238 return_ty = 'boolean' 239class CallStaticByteMethod(CallStaticMethod): 240 return_ty = 'byte' 241class CallStaticCharMethod(CallStaticMethod): 242 return_ty = 'char' 243class CallStaticShortMethod(CallStaticMethod): 244 return_ty = 'short' 245class CallStaticIntMethod(CallStaticMethod): 246 return_ty = 'int' 247class CallStaticLongMethod(CallStaticMethod): 248 return_ty = 'long' 249class CallStaticVoidMethod(CallStaticMethod): 250 return_ty = 'void' 251class CallStaticObjectMethodA(CallStaticMethodA): 252 return_ty = 'reference' 253class CallStaticBooleanMethodA(CallStaticMethodA): 254 return_ty = 'boolean' 255class CallStaticByteMethodA(CallStaticMethodA): 256 return_ty = 'byte' 257class CallStaticCharMethodA(CallStaticMethodA): 258 return_ty = 'char' 259class CallStaticShortMethodA(CallStaticMethodA): 260 return_ty = 'short' 261class CallStaticIntMethodA(CallStaticMethodA): 262 return_ty = 'int' 263class CallStaticLongMethodA(CallStaticMethodA): 264 return_ty = 'long' 265class CallStaticVoidMethodA(CallStaticMethodA): 266 return_ty = 'void' 267