@@ -113,6 +113,167 @@ ab fridadescribe console.log(Object.getOwnPropertyNames(Java.use('$').__proto__)
113113
114114</details >
115115
116+
117+ <details >
118+ <summary >JEB</summary >
119+
120+ Place cursor at Java method's signature and press ` Ctrl+Shift+F ` , it will copy the code to system clipboard using ` xclip ` .
121+
122+ * Add to ` ~/$JEB$/scripts `
123+
124+
125+ ``` python
126+ # ?shortcut=Mod1+Shift+F
127+ # !/usr/bin/env python3
128+ # -*- coding: utf-8 -*-
129+
130+ from com.pnfsoftware.jeb.client.api import IScript
131+ from com.pnfsoftware.jeb.core import RuntimeProjectUtil
132+ from com.pnfsoftware.jeb.core.units.code.android import IDexUnit
133+ from subprocess import Popen, PIPE
134+
135+
136+ def arg_format (i ):
137+ return ' arg_%d ' % i
138+
139+
140+ def generate_body_code (types , retval , method_name , orig_method_name , class_name ):
141+ body_code = " \n\t console.log('[{} #{} ] ' + JSON.strigify({{ \n\t " .format(
142+ FridaCodeGenerator.to_canonical_name(class_name), method_name)
143+ for i, typ in enumerate (types):
144+ body_code += ' \t {} : {} , // {} \n\t ' .format(' a%d ' % i, arg_format(i), typ)
145+
146+ if retval != ' void' :
147+ body_code = ' \n\t var retval = this.{} .apply(this, arguments);{} \t retv: retval\n\t }} );' .format(
148+ orig_method_name, body_code)
149+ else :
150+ body_code += ' }} );\n\t this.{} .apply(this, arguments);' .format(method_name)
151+
152+ return body_code + ' \n '
153+
154+
155+ class JavaMethod (object ):
156+ def __init__ (self ):
157+ self .class_name = None
158+ self .class_orig_name = None
159+ self .name = None
160+ self .orig_name = None
161+ self .arg = []
162+ self .retType = None
163+
164+ def get_parameters (self ):
165+ return self .arg
166+
167+ def get_return_type (self ):
168+ return self .retType
169+
170+ def get_name (self ):
171+ return self .name
172+
173+ def get_orig_name (self ):
174+ return self .orig_name
175+
176+ def get_class_orig_name (self ):
177+ return self .class_orig_name
178+
179+ def get_class_name (self ):
180+ return self .class_name
181+
182+ def __str__ (self ):
183+ return ' JavaMethod[name: %s , orig_name: %s , args: %s , return type: %s ]' % (
184+ self .name, self .orig_name, self .arg, self .retType)
185+
186+
187+ class FridaCodeGenerator (IScript ):
188+
189+ @ staticmethod
190+ def to_canonical_name (mname ):
191+ mname = mname.replace(' /' , ' .' )
192+ return {
193+ ' C' : ' char' ,
194+ ' I' : ' int' ,
195+ ' B' : ' byte' ,
196+ ' Z' : ' boolean' ,
197+ ' F' : ' float' ,
198+ ' D' : ' double' ,
199+ ' S' : ' short' ,
200+ ' J' : ' long' ,
201+ ' V' : ' void' ,
202+ ' L' : mname[1 :- 1 ],
203+ ' [' : mname
204+ }[mname[0 ]]
205+
206+ def run (self , ctx ):
207+ project = ctx.getEnginesContext().getProjects()[0 ] # Get current project(IRuntimeProject)
208+ self .dexunit = RuntimeProjectUtil.findUnitsByType(project, IDexUnit, False )[0 ] # Get dex context, needs >=V2.2.1
209+ try :
210+ self .current_unit = ctx.getFocusedView().getActiveFragment().getUnit() # Get current Source Tab in Focus
211+ java_class = self .current_unit.getClassElement().getName()
212+ current_addr = ctx.getFocusedView().getActiveFragment().getActiveAddress()
213+ m = FridaCodeGenerator.get_decompiled_method(self .dexunit, current_addr, java_class)
214+ method_name = m.get_name()
215+ class_name = FridaCodeGenerator.to_canonical_name(m.get_class_orig_name())
216+ return_type = FridaCodeGenerator.to_canonical_name(str (m.get_return_type()))
217+ if method_name == ' <clinit>' :
218+ raise Exception (' Class initializer' )
219+ args_code = ' , ' .join([arg_format(i) for i in range (len (m.get_parameters()))])
220+
221+ if method_name == ' <init>' : method_name = ' $init'
222+
223+ types = [FridaCodeGenerator.to_canonical_name(param) for param in m.get_parameters()]
224+ # TODO get original type class names
225+ type_code = ' , ' .join([" '{0} '" .format(t) for t in types])
226+ body_code = generate_body_code(types, return_type, method_name, m.get_orig_name(), m.get_class_name())
227+ hook = " Java.use('{class_name} ').{method} .overload({sig} ).implementation = function({args} ) {{{body}}} " .format(
228+ class_name = class_name,
229+ method = m.get_orig_name() if method_name != ' $init' else method_name,
230+ sig = type_code,
231+ args = args_code,
232+ body = body_code
233+ )
234+ print (hook)
235+ # copy to system's clipboard
236+ Popen([' xclip' , ' -sel' , ' c' , ' -i' ], stdin = PIPE ).communicate(input = (hook.encode()))
237+ except Exception as e:
238+ print (e)
239+ ctx.displayMessageBox(None , ' Place the cursor in the function you want to generate the Frida code' , None , None )
240+
241+ @ staticmethod
242+ def get_decompiled_method (dex , addr , class_orig_name ):
243+ method_info = JavaMethod()
244+ method_info.orig_name = dex.getMethod(addr).getName(False )
245+ msig = addr.split(' +' )[0 ]
246+ infos = str (msig).split(' ->' )
247+ if len (infos) == 2 :
248+ method_info.class_name = infos[0 ]
249+ method_info.class_orig_name = class_orig_name
250+ if len (infos[1 ].split(' (' )) == 2 :
251+ method_info.name = infos[1 ].split(' (' )[0 ]
252+ if len (infos[1 ].split(' )' )) == 2 :
253+ method_info.retType = infos[1 ].split(' )' )[1 ]
254+ if len (infos[1 ].split(' (' )) == 2 and len (infos[1 ].split(' )' )) == 2 :
255+ args = infos[1 ].split(' (' )[- 1 ].split(' )' )[0 ]
256+ while args:
257+ if args[0 ] in [' C' , ' I' , ' B' , ' Z' , ' F' , ' D' , ' S' , ' J' , ' V' ]:
258+ method_info.arg.append(str (args[0 ]))
259+ args = args[1 :]
260+ elif args[0 ] == ' [' :
261+ if args[1 ] == ' L' :
262+ offset = args.find(' ;' )
263+ method_info.arg.append(str (args[0 :offset + 1 ]))
264+ args = args[offset + 1 :]
265+ else :
266+ method_info.arg.append(str (args[0 :2 ]))
267+ args = args[2 :]
268+ elif args[0 ] == ' L' :
269+ offset = args.find(" ;" )
270+ method_info.arg.append(str (args[0 :offset + 1 ]))
271+ args = args[offset + 1 :]
272+ print (method_info)
273+ return method_info
274+ ```
275+
276+ </details >
116277<hr />
117278
118279#### Load CPP module
0 commit comments