├── README.md ├── unico ├── fibonacci ├── test └── test2.py ├── 脱壳 ├── FRIDA-DEXDump-master │ ├── screenshot.png │ ├── README.md │ ├── __init__.py │ ├── agent.js │ └── main.py ├── dump_so.js ├── README.md └── dump_dex.js ├── modules.js ├── debugBypass.js ├── setProxy.js ├── template.js ├── jsonObject.js ├── start.py ├── te.js ├── socket.js ├── RevealNativeMethods.js ├── sslPinning.js ├── script.js ├── hookOkhttp.js ├── trace.js ├── hookXlog.js └── encrypt.js /README.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | ##### 开始学习frida,一些简单脚本。 3 | -------------------------------------------------------------------------------- /unico/fibonacci: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hzzheyang/frida-scripts/HEAD/unico/fibonacci -------------------------------------------------------------------------------- /脱壳/FRIDA-DEXDump-master/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hzzheyang/frida-scripts/HEAD/脱壳/FRIDA-DEXDump-master/screenshot.png -------------------------------------------------------------------------------- /modules.js: -------------------------------------------------------------------------------- 1 | 2 | Java.perform(function(){ 3 | var utils=Java.use("com.ss.sys.ces.a"); 4 | console.log(utils); 5 | Process.enumerateModules({ 6 | onMatch: function(module){ 7 | 8 | send(module); 9 | }, 10 | onComplete: function(){} 11 | 12 | 13 | }); 14 | 15 | }); -------------------------------------------------------------------------------- /debugBypass.js: -------------------------------------------------------------------------------- 1 | // debug bypass 2 | Java.perform(function () { 3 | // send("[Debugger Check Bypass] Activated"); 4 | var Debug = Java.use('android.os.Debug'); 5 | Debug.isDebuggerConnected.implementation = function () { 6 | send('[Debugger Check Bypass] isDebuggerConnected() bypassed'); 7 | return false; 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /setProxy.js: -------------------------------------------------------------------------------- 1 | Java.perform(function () { 2 | var ActivityThread = Java.use('android.app.ActivityThread'); 3 | var ConnectivityManager = Java.use('android.net.ConnectivityManager'); 4 | var ProxyInfo = Java.use('android.net.ProxyInfo'); 5 | 6 | var proxyInfo = ProxyInfo.$new('127.0.0.1', 10809, ''); // change to null in order to disable the proxy. 7 | var context = ActivityThread.currentApplication().getApplicationContext(); 8 | var connectivityManager = Java.cast(context.getSystemService('connectivity'), ConnectivityManager); 9 | connectivityManager.setGlobalProxy(proxyInfo); 10 | }); -------------------------------------------------------------------------------- /template.js: -------------------------------------------------------------------------------- 1 | 2 | Java.perform(function () { 3 | const Jstring=Java.use("java.lang.String"); 4 | const base64=Java.use("android.util.Base64"); 5 | ['com.ss.sys.ces.a'].forEach(function (clazz,i) { 6 | var func = 'meta'; 7 | Java.use(clazz)[func].implementation = function (a,b,c) { 8 | 9 | console.log("============================================="); 10 | console.log(a); 11 | console.log(b); 12 | console.log(c); 13 | var ret = this[func](a,b,c); 14 | send(Bytes2Str(ret)); 15 | send(base64.encode(ret, 0)); 16 | send(Jstring.$new(ret)); 17 | console.log("-----------------------------------------------"); 18 | return ret; 19 | } 20 | }); 21 | }); -------------------------------------------------------------------------------- /jsonObject.js: -------------------------------------------------------------------------------- 1 | Java.perform(function () { 2 | ['org.json.JSONObject'].forEach(function (clazz, i) { 3 | var func = 'putOpt'; 4 | Java.use(clazz)[func].implementation = function (a, b) { 5 | var ret = this[func](a, b); 6 | send('[HY] [String Catch] [' + i + '] ' + ret); 7 | return ret; 8 | } 9 | }); 10 | }); 11 | 12 | 13 | Java.perform(function () { 14 | ['org.json.JSONObject'].forEach(function (clazz, i) { 15 | var func = 'put'; 16 | Java.use(clazz)[func].overload("java.lang.String", "java.lang.Object").implementation = function (a, b) { 17 | var ret = this[func](a, b); 18 | send('[HY] [String Catch] [' + i + '] ' + ret); 19 | send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new())); 20 | return ret; 21 | } 22 | }); 23 | }); 24 | 25 | -------------------------------------------------------------------------------- /start.py: -------------------------------------------------------------------------------- 1 | import time 2 | import frida 3 | 4 | 5 | def on_message(message, data): 6 | if message['type'] == 'send': 7 | print(message['payload']) 8 | elif message['type'] == 'error': 9 | print(message['stack']) 10 | 11 | 12 | def javaByteArrayToString(data): 13 | return ''.join(map(lambda x: chr(x % 256), data)) 14 | 15 | 16 | def start_hook(package_name): 17 | device = frida.get_usb_device(timeout=50) 18 | # device = frida.get_device_manager().add_remote_device("127.0.0.1:1234") 19 | print(device) 20 | device.attach("com.android.systemui") 21 | pid = device.spawn([package_name]) 22 | device.resume(pid) 23 | time.sleep(1) 24 | session = device.attach(pid) 25 | 26 | with open("trace.js", encoding="utf-8") as f: 27 | script = session.create_script(f.read()) 28 | script.on("message", on_message) 29 | script.load() 30 | input() 31 | 32 | 33 | if __name__ == "__main__": 34 | start_hook("com.meitu.meipaimv") -------------------------------------------------------------------------------- /脱壳/FRIDA-DEXDump-master/README.md: -------------------------------------------------------------------------------- 1 | # FRIDA-DEXDump 2 | 3 | [Chinese WriteUp](https://bbs.pediy.com/thread-257829.htm) 4 | 5 | Fast search and dump dex on memory. 6 | 7 | ## Features 8 | 1. support fuzzy search no-magic dex. (eg: baidu protect) 9 | 2. auto fill magic into dex-header. 10 | 3. compatible with full android version(frida supported). 11 | 4. support loading as objection plugin~ 12 | 13 | ## Usage 14 | 1. update your frida-server and frida python binding to latest. 15 | 2. launch app. 16 | 3. run: python main.py. 17 | 4. check `SavePath`. 18 | 19 | ### objection plugin 20 | 21 | 1. clone this repo to your plugins folder, eg: 22 | > git clone https://github.com/hluwa/FRIDA-DEXDump ~/.objection/plugins/dexdump 23 | 2. start objection with `-P` or `--plugin-folder` your plugins folder, eg: 24 | > objection -g com.app.name explore -P ~/.objection/plugins 25 | 3. run command: 26 | 1. ` plugin dexdump search ` to search and print all dex 27 | 2. ` plugin dexdump dump ` to dump all found dex. 28 | 29 | ## Screenshot 30 | 31 | ![](screenshot.png) 32 | -------------------------------------------------------------------------------- /脱壳/dump_so.js: -------------------------------------------------------------------------------- 1 | function dump_so(so_name) { 2 | Java.perform(function () { 3 | var currentApplication = Java.use("android.app.ActivityThread").currentApplication(); 4 | var dir = currentApplication.getApplicationContext().getFilesDir().getPath(); 5 | var libso = Process.getModuleByName(so_name); 6 | console.log("[name]:", libso.name); 7 | console.log("[base]:", libso.base); 8 | console.log("[size]:", ptr(libso.size)); 9 | console.log("[path]:", libso.path); 10 | var file_path = dir + "/" + libso.name + "_" + libso.base + "_" + ptr(libso.size) + ".so"; 11 | var file_handle = new File(file_path, "wb"); 12 | if (file_handle && file_handle != null) { 13 | Memory.protect(ptr(libso.base), libso.size, 'rwx'); 14 | var libso_buffer = ptr(libso.base).readByteArray(libso.size); 15 | file_handle.write(libso_buffer); 16 | file_handle.flush(); 17 | file_handle.close(); 18 | console.log("[dump]:", file_path); 19 | } 20 | }); 21 | } -------------------------------------------------------------------------------- /te.js: -------------------------------------------------------------------------------- 1 | // Java.perform(function () { 2 | // ['com.homelink.midlib.util.HttpUtil'].forEach(function (clazz,i) { 3 | // var func = 'b'; 4 | // Java.use(clazz)[func].overload("java.lang.String","java.util.Map").implementation = function (a,b,c) { 5 | // 6 | // console.log("============================================="); 7 | // console.log(a); 8 | // console.log(b); 9 | // var ret = this[func](a,b); 10 | // console.log(ret); 11 | // console.log("-----------------------------------------------"); 12 | // return ret; 13 | // } 14 | // }); 15 | // }); 16 | Java.perform(function () { 17 | ['com.homelink.midlib.util.HttpUtil'].forEach(function (clazz,i) { 18 | var func = 'd'; 19 | Java.use(clazz)[func].overload("java.lang.String").implementation = function (a) { 20 | 21 | console.log("============================================="); 22 | console.log(a); 23 | var ret = this[func](a); 24 | console.log(ret); 25 | console.log("-----------------------------------------------"); 26 | return ret; 27 | } 28 | }); 29 | }); -------------------------------------------------------------------------------- /unico/test: -------------------------------------------------------------------------------- 1 | from unicorn import * 2 | from unicorn.x86_const import * 3 | import struct 4 | 5 | instructions_skip_list = [0x00000000004004EF, 0x00000000004004F6, 0x0000000000400502, 0x000000000040054F] 6 | 7 | 8 | def read(name): 9 | with open(name, "rb") as f: 10 | return f.read() 11 | 12 | 13 | def hook_code(mu, address, size, user_data): 14 | print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' % (address, size)) 15 | 16 | if address in instructions_skip_list: 17 | mu.reg_write(UC_X86_REG_RIP, address + size) 18 | 19 | elif address == 0x400560: # that instruction writes a byte of the flag 20 | c = mu.reg_read(UC_X86_REG_RDI) 21 | # print(chr(c)) 22 | mu.reg_write(UC_X86_REG_RIP, address + size) 23 | 24 | 25 | def u32(data): 26 | return struct.unpack("I", data)[0] 27 | 28 | 29 | def p32(num): 30 | return struct.pack("I", num) 31 | 32 | 33 | if __name__ == '__main__': 34 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 35 | BASE = 0x400000 36 | STACK_ADDR = 0x0 37 | STACK_SIZE = 1024 * 1024 38 | mu.mem_map(BASE, 1024 * 1024) 39 | mu.mem_map(STACK_ADDR, STACK_SIZE) 40 | mu.mem_write(BASE, read("./fibonacci")) 41 | mu.reg_write(UC_X86_REG_RSP, STACK_ADDR + STACK_SIZE - 1) 42 | mu.hook_add(UC_HOOK_CODE, hook_code) 43 | mu.emu_start(0x00000000004004E0, 0x0000000000400575) 44 | -------------------------------------------------------------------------------- /脱壳/FRIDA-DEXDump-master/__init__.py: -------------------------------------------------------------------------------- 1 | # Author: hluwa 2 | # HomePage: https://github.com/hluwa 3 | # CreatedTime: 2020/3/5 19:14 4 | 5 | 6 | __description__ = "a objection plugin to fast search and dump dex on memory." 7 | 8 | from objection.state.connection import state_connection 9 | from objection.utils.plugin import Plugin 10 | 11 | from .main import * 12 | 13 | 14 | class DEXDump(Plugin): 15 | 16 | def __init__(self, ns): 17 | """ 18 | Creates a new instance of the plugin 19 | :param ns: 20 | """ 21 | 22 | self.script_path = os.path.join(os.path.dirname(__file__), "agent.js") 23 | 24 | implementation = { 25 | 'meta': 'fast search and dump dex on memory.', 26 | 'commands': { 27 | 'search': { 28 | 'meta': 'search all dex', 29 | 'exec': self.search 30 | }, 31 | 'dump': { 32 | 'meta': 'dump all dex', 33 | 'exec': self.dump 34 | } 35 | } 36 | } 37 | 38 | super().__init__(__file__, ns, implementation) 39 | 40 | self.inject() 41 | 42 | def search(self, args=None): 43 | main.search(self.api) 44 | 45 | def dump(self, args=None): 46 | """ 47 | """ 48 | main.dump(state_connection.gadget_name, self.api) 49 | 50 | 51 | namespace = 'dexdump' 52 | plugin = DEXDump 53 | -------------------------------------------------------------------------------- /脱壳/README.md: -------------------------------------------------------------------------------- 1 | # frida_dump 2 | 3 | ## 1. 使用dump_so 4 | 5 | ```Text 6 | > frida -U packagename -l dump_so.js 7 | ____ 8 | / _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit 9 | | (_| | 10 | > _ | Commands: 11 | /_/ |_| help -> Displays the help system 12 | . . . . object? -> Display information about 'object' 13 | . . . . exit/quit -> Exit 14 | . . . . 15 | . . . . More info at http://www.frida.re/docs/home/ 16 | 17 | [LGE AOSP on HammerHead::packagename]-> dump_so("name.so") 18 | [name]: name.so 19 | [base]: 0x99adf000 20 | [size]: 0x2d4000 21 | [path]: /data/app/packagename-2/lib/arm/name.so 22 | [dump]: /data/user/0/packagename/files/name.so_0x99adf000_0x2d4000.so 23 | undefined 24 | [LGE AOSP on HammerHead::packagename]-> 25 | ``` 26 | 27 | ## 2. 使用dump_dex 28 | 29 | 更新了查找DefineClass的函数签名 30 | 31 | ```Text 32 | frida -U --no-pause -f packagename -l dump_dex.js 33 | ____ 34 | / _ | Frida 12.4.8 - A world-class dynamic instrumentation toolkit 35 | | (_| | 36 | > _ | Commands: 37 | /_/ |_| help -> Displays the help system 38 | . . . . object? -> Display information about 'object' 39 | . . . . exit/quit -> Exit 40 | . . . . 41 | . . . . More info at http://www.frida.re/docs/home/ 42 | Spawned `packagename`. Resuming main thread! 43 | [Google Pixel XL::packagename]-> [dlopen:] libart.so 44 | _ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE 0x7ac6dc4f74 45 | [DefineClass:] 0x7ac6dc4f74 46 | [dump dex]: /data/data/packagename/files/7aab800000_8341c4.dex 47 | ``` 48 | -------------------------------------------------------------------------------- /socket.js: -------------------------------------------------------------------------------- 1 | var objectsToLookFor = ["java.net.Socket", "dalvik.system.DexClassLoader", "java.net.URLConnection", "java.net.URL", "java.security.cert.X509Certificate"]; 2 | for (var i in objectsToLookFor) { 3 | Java.perform(function () { 4 | Java.choose(objectsToLookFor[i], { 5 | "onMatch": function (instance) { 6 | if (objectsToLookFor[i] == "java.net.URL" && instance.getProtocol() != "file") { 7 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 8 | console.log("[*] Process is communicating via " + instance.getProtocol()); 9 | console.log("[+] Communication Details: " + instance.toString()); 10 | } 11 | if (objectsToLookFor[i] == "dalvik.system.DexClassLoader") { 12 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 13 | console.log("[*] Process is making use of DexClassLoader"); 14 | console.log("[+] Loader Details: " + instance.toString()); 15 | } 16 | if (objectsToLookFor[i] == "java.net.Socket") { 17 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 18 | console.log("[*] Process is making use of a Socket Connection"); 19 | console.log("[+] Socket Details: " + instance.toString()); 20 | } 21 | if (objectsToLookFor[i] == "java.net.URLConnection") { 22 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 23 | console.log("[*] Process is making use of a URL Connection"); 24 | console.log("[+] Details: " + instance.toString()); 25 | } 26 | if (objectsToLookFor[i] == "java.security.cert.X509Certificate") { 27 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 28 | console.log("[*] Process is making use of a X509Certificate"); 29 | console.log("[+] X509Certificate Details: " + instance.toString()); 30 | } 31 | }, 32 | "onComplete": function () { 33 | } 34 | }); 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /RevealNativeMethods.js: -------------------------------------------------------------------------------- 1 | 2 | var RevealNativeMethods = function() { 3 | var pSize = Process.pointerSize; 4 | var env = Java.vm.getEnv(); 5 | var RegisterNatives = 215, FindClassIndex = 6; // search "215" @ https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html 6 | var jclassAddress2NameMap = {}; 7 | function getNativeAddress(idx) { 8 | return env.handle.readPointer().add(idx * pSize).readPointer(); 9 | } 10 | // intercepting FindClass to populate Map 11 | Interceptor.attach(getNativeAddress(FindClassIndex), { 12 | onEnter: function(args) { 13 | jclassAddress2NameMap[args[0]] = args[1].readCString(); 14 | } 15 | }); 16 | // RegisterNative(jClass*, .., JNINativeMethod *methods[nMethods], uint nMethods) // https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#977 17 | Interceptor.attach(getNativeAddress(RegisterNatives), { 18 | onEnter: function(args) { 19 | for (var i = 0, nMethods = parseInt(args[3]); i < nMethods; i++) { 20 | 21 | // https://android.googlesource.com/platform/libnativehelper/+/master/include_jni/jni.h#129 22 | // typedef struct { 23 | // const char* name; 24 | // const char* signature; 25 | // void* fnPtr; 26 | // } JNINativeMethod; 27 | 28 | var structSize = pSize * 3; // = sizeof(JNINativeMethod) 29 | var methodsPtr = ptr(args[2]); 30 | var signature = methodsPtr.add(i * structSize + pSize).readPointer(); 31 | var fnPtr = methodsPtr.add(i * structSize + (pSize * 2)).readPointer(); // void* fnPtr 32 | var jClass = jclassAddress2NameMap[args[0]].split('/'); 33 | console.log('\x1b[3' + '6;01' + 'm', JSON.stringify({ 34 | module: DebugSymbol.fromAddress(fnPtr)['moduleName'], // https://www.frida.re/docs/javascript-api/#debugsymbol 35 | package: jClass.slice(0, -1).join('.'), 36 | class: jClass[jClass.length - 1], 37 | method: methodsPtr.readPointer().readCString(), // char* name 38 | signature: signature.readCString(), // char* signature TODO Java bytecode signature parser { Z: 'boolean', B: 'byte', C: 'char', S: 'short', I: 'int', J: 'long', F: 'float', D: 'double', L: 'fully-qualified-class;', '[': 'array' } https://github.com/skylot/jadx/blob/master/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java 39 | address: fnPtr 40 | }), '\x1b[39;49;00m'); 41 | } 42 | } 43 | }); 44 | } 45 | 46 | Java.perform(RevealNativeMethods); 47 | -------------------------------------------------------------------------------- /脱壳/FRIDA-DEXDump-master/agent.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Author: hluwa 3 | * HomePage: https://github.com/hluwa 4 | * CreatedTime: 2020/1/7 20:44 5 | * */ 6 | 7 | rpc.exports = { 8 | memorydump: function memorydump(address, size) { 9 | return new NativePointer(address).readByteArray(size); 10 | }, 11 | scandex: function scandex() { 12 | var result = []; 13 | Process.enumerateRanges('r--').forEach(function (range) { 14 | try{ 15 | // @TODO improve fuzz 16 | if ( 17 | range.size >= 0x60 18 | && range.base.readCString(4) != "dex\n" 19 | && range.base.add(0x20).readInt() <= range.size //file_size 20 | // && range.base.add(0x24).readInt() == 112 //header_size 21 | && range.base.add(0x34).readInt() < range.size 22 | && range.base.add(0x3C).readInt() == 112 //string_id_off 23 | ) { 24 | result.push({ 25 | "addr": range.base, 26 | "size": range.base.add(0x20).readInt() 27 | }); 28 | } 29 | } catch(e){ 30 | 31 | } 32 | try { 33 | Memory.scanSync(range.base, range.size, "64 65 78 0a 30 33 35 00").forEach(function (match) { 34 | var range = Process.findRangeByAddress(match.address); 35 | 36 | if (range != null && range.size < match.address.toInt32() + 0x24 - range.base.toInt32()) { 37 | return; 38 | } 39 | 40 | var dex_size = match.address.add("0x20").readInt(); 41 | 42 | if (range != null) { 43 | 44 | if (range.file && range.file.path 45 | && (// range.file.path.startsWith("/data/app/") 46 | range.file.path.startsWith("/data/dalvik-cache/") 47 | || range.file.path.startsWith("/system/"))) { 48 | return; 49 | } 50 | 51 | if (match.address.toInt32() + dex_size > range.base.toInt32() + range.size) { 52 | return; 53 | } 54 | } 55 | 56 | result.push({ 57 | "addr": match.address, 58 | "size": dex_size 59 | }); 60 | }); 61 | } catch (e) { 62 | } 63 | }); 64 | return result; 65 | } 66 | }; 67 | -------------------------------------------------------------------------------- /sslPinning.js: -------------------------------------------------------------------------------- 1 | setTimeout(function(){ 2 | Java.perform(function (){ 3 | console.log(""); 4 | console.log("[.] Cert Pinning Bypass/Re-Pinning"); 5 | 6 | var CertificateFactory = Java.use("java.security.cert.CertificateFactory"); 7 | var FileInputStream = Java.use("java.io.FileInputStream"); 8 | var BufferedInputStream = Java.use("java.io.BufferedInputStream"); 9 | var X509Certificate = Java.use("java.security.cert.X509Certificate"); 10 | var KeyStore = Java.use("java.security.KeyStore"); 11 | var TrustManagerFactory = Java.use("javax.net.ssl.TrustManagerFactory"); 12 | var SSLContext = Java.use("javax.net.ssl.SSLContext"); 13 | 14 | // Load CAs from an InputStream 15 | console.log("[+] Loading our CA..."); 16 | var cf = CertificateFactory.getInstance("X.509"); 17 | 18 | try { 19 | var fileInputStream = FileInputStream.$new("/data/local/tmp/cert-der.crt"); 20 | } 21 | catch(err) { 22 | console.log("[o] " + err); 23 | } 24 | 25 | var bufferedInputStream = BufferedInputStream.$new(fileInputStream); 26 | var ca = cf.generateCertificate(bufferedInputStream); 27 | bufferedInputStream.close(); 28 | 29 | var certInfo = Java.cast(ca, X509Certificate); 30 | console.log("[o] Our CA Info: " + certInfo.getSubjectDN()); 31 | 32 | // Create a KeyStore containing our trusted CAs 33 | console.log("[+] Creating a KeyStore for our CA..."); 34 | var keyStoreType = KeyStore.getDefaultType(); 35 | var keyStore = KeyStore.getInstance(keyStoreType); 36 | keyStore.load(null, null); 37 | keyStore.setCertificateEntry("ca", ca); 38 | 39 | // Create a TrustManager that trusts the CAs in our KeyStore 40 | console.log("[+] Creating a TrustManager that trusts the CA in our KeyStore..."); 41 | var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 42 | var tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 43 | tmf.init(keyStore); 44 | console.log("[+] Our TrustManager is ready..."); 45 | 46 | console.log("[+] Hijacking SSLContext methods now..."); 47 | console.log("[-] Waiting for the app to invoke SSLContext.init()..."); 48 | 49 | SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").implementation = function(a,b,c) { 50 | console.log("[o] App invoked javax.net.ssl.SSLContext.init..."); 51 | SSLContext.init.overload("[Ljavax.net.ssl.KeyManager;", "[Ljavax.net.ssl.TrustManager;", "java.security.SecureRandom").call(this, a, tmf.getTrustManagers(), c); 52 | console.log("[+] SSLContext initialized with our custom TrustManager!"); 53 | } 54 | }); 55 | },0); -------------------------------------------------------------------------------- /unico/test2.py: -------------------------------------------------------------------------------- 1 | from unicorn import * 2 | from unicorn.x86_const import * 3 | 4 | import struct 5 | 6 | 7 | def read(name): 8 | with open(name,"rb") as f: 9 | return f.read() 10 | 11 | 12 | def u32(data): 13 | return struct.unpack("I", data)[0] 14 | 15 | 16 | def p32(num): 17 | return struct.pack("I", num) 18 | 19 | 20 | mu = Uc(UC_ARCH_X86, UC_MODE_64) 21 | 22 | BASE = 0x400000 23 | STACK_ADDR = 0x0 24 | STACK_SIZE = 1024 * 1024 25 | 26 | mu.mem_map(BASE, 1024 * 1024) 27 | mu.mem_map(STACK_ADDR, STACK_SIZE) 28 | 29 | mu.mem_write(BASE, read("./fibonacci")) 30 | mu.reg_write(UC_X86_REG_RSP, STACK_ADDR + STACK_SIZE - 1) 31 | 32 | instructions_skip_list = [0x00000000004004EF, 0x00000000004004F6, 0x0000000000400502, 0x000000000040054F] 33 | 34 | FIBONACCI_ENTRY = 0x0000000000400670 35 | FIBONACCI_END = [0x00000000004006F1, 0x0000000000400709] 36 | 37 | stack = [] # Stack for storing the arguments 38 | d = {} # Dictionary that holds return values for given function arguments 39 | 40 | 41 | def hook_code(mu, address, size, user_data): 42 | # print('>>> Tracing instruction at 0x%x, instruction size = 0x%x' %(address, size)) 43 | 44 | if address in instructions_skip_list: 45 | mu.reg_write(UC_X86_REG_RIP, address + size) 46 | 47 | elif address == 0x400560: # That instruction writes a byte of the flag 48 | c = mu.reg_read(UC_X86_REG_RDI) 49 | print(chr(c)) 50 | mu.reg_write(UC_X86_REG_RIP, address + size) 51 | 52 | elif address == FIBONACCI_ENTRY: # Are we at the beginning of fibonacci function? 53 | arg0 = mu.reg_read(UC_X86_REG_RDI) # Read the first argument. Tt is passed via RDI 54 | r_rsi = mu.reg_read(UC_X86_REG_RSI) # Read the second argument which is a reference 55 | arg1 = u32(mu.mem_read(r_rsi, 4)) # Read the second argument from reference 56 | 57 | if (arg0, arg1) in d: # Check whether return values for this function are already saved. 58 | (ret_rax, ret_ref) = d[(arg0, arg1)] 59 | mu.reg_write(UC_X86_REG_RAX, ret_rax) # Set return value in RAX register 60 | mu.mem_write(r_rsi, p32(ret_ref)) # Set retun value through reference 61 | mu.reg_write(UC_X86_REG_RIP, 62 | 0x400582) # Set RIP to point at RET instruction. We want to return from fibonacci function 63 | 64 | else: 65 | stack.append((arg0, arg1, r_rsi)) # If return values are not saved for these arguments, add them to stack. 66 | 67 | elif address in FIBONACCI_END: 68 | (arg0, arg1, r_rsi) = stack.pop() # We know arguments when exiting the function 69 | 70 | ret_rax = mu.reg_read(UC_X86_REG_RAX) # Read the return value that is stored in RAX 71 | ret_ref = u32(mu.mem_read(r_rsi, 4)) # Read the return value that is passed reference 72 | d[(arg0, arg1)] = (ret_rax, ret_ref) # Remember the return values for this argument pair 73 | 74 | 75 | mu.hook_add(UC_HOOK_CODE, hook_code) 76 | 77 | mu.emu_start(0x00000000004004E0, 0x0000000000400575) 78 | -------------------------------------------------------------------------------- /脱壳/FRIDA-DEXDump-master/main.py: -------------------------------------------------------------------------------- 1 | # Author: hluwa 2 | # HomePage: https://github.com/hluwa 3 | # CreatedTime: 2020/1/7 20:57 4 | 5 | import os 6 | import sys 7 | 8 | import click 9 | import frida 10 | import logging 11 | 12 | logging.basicConfig(level=logging.INFO, 13 | format="%(asctime)s %(levelname)s %(message)s", 14 | datefmt='%m-%d/%H:%M:%S') 15 | 16 | 17 | def get_all_process(device, pkgname): 18 | return [process for process in device.enumerate_processes() if process.name == pkgname] 19 | 20 | 21 | def search(api, args=None): 22 | """ 23 | """ 24 | 25 | matches = api.scandex() 26 | for info in matches: 27 | click.secho("[DEXDump] Found: DexAddr={}, DexSize={}" 28 | .format(info['addr'], hex(info['size'])), fg='green') 29 | return matches 30 | 31 | 32 | def dump(pkg_name, api): 33 | """ 34 | """ 35 | matches = api.scandex() 36 | for info in matches: 37 | try: 38 | bs = api.memorydump(info['addr'], info['size']) 39 | if not os.path.exists("./" + pkg_name + "/"): 40 | os.mkdir("./" + pkg_name + "/") 41 | if bs[:4] != "dex\n": 42 | bs = b"dex\n035\x00" + bs[8:] 43 | with open(pkg_name + "/" + info['addr'] + ".dex", 'wb') as out: 44 | out.write(bs) 45 | click.secho("[DEXDump]: DexSize={}, SavePath={}/{}/{}.dex" 46 | .format(hex(info['size']), os.getcwd(), pkg_name, info['addr']), fg='green') 47 | except Exception as e: 48 | click.secho("[Except] - {}: {}".format(e, info), bg='yellow') 49 | 50 | 51 | if __name__ == "__main__": 52 | try: 53 | device = frida.get_usb_device(timeout=50) 54 | except: 55 | device = frida.get_remote_device() 56 | target = device.get_frontmost_application() 57 | pkg_name = target.identifier 58 | 59 | processes = get_all_process(device, pkg_name) 60 | if len(processes) == 1: 61 | target = processes[0] 62 | else: 63 | s_processes = "" 64 | for index in range(len(processes)): 65 | s_processes += "\t[{}] {}\n".format(index, str(processes[index])) 66 | input_id = int(input("[{}] has multiprocess: \n{}\nplease choose target process: " 67 | .format(pkg_name, s_processes))) 68 | target = processes[input_id] 69 | try: 70 | for index in range(len(processes)): 71 | if index == input_id: 72 | os.system("adb shell \"su -c 'kill -18 {}'\"".format(processes[index].pid)) 73 | else: 74 | os.system("adb shell \"su -c 'kill -19 {}'\"".format(processes[index].pid)) 75 | except: 76 | pass 77 | 78 | logging.info("[DEXDump]: found target [{}] {}".format(target.pid, pkg_name)) 79 | session = device.attach(target.pid) 80 | path = os.path.dirname(sys.argv[0]) 81 | path = path if path else "." 82 | script = session.create_script(open(path + "/agent.js").read()) 83 | script.load() 84 | 85 | dump("com.meitu.meipaimv", script.exports) 86 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | //hook 遍历class 2 | function allclass(){ 3 | 4 | var classes = Java.enumerateLoadedClassesSync(); 5 | console.log('[HY] Loaded Classes'); 6 | classes.forEach(function(aClass) { 7 | try{ 8 | console.log('[HY] ' + aClass); 9 | } 10 | catch(err){} 11 | }); 12 | } 13 | 14 | 15 | //String转byte[] 16 | function stringToBytes(str) { 17 | var ch, st, re = []; 18 | for (var i = 0; i < str.length; i++ ) { 19 | ch = str.charCodeAt(i); 20 | st = []; 21 | 22 | do { 23 | st.push( ch & 0xFF ); 24 | ch = ch >> 8; 25 | } 26 | while ( ch ); 27 | re = re.concat( st.reverse() ); 28 | } 29 | return re; 30 | } 31 | 32 | //byte[]转String 33 | function byteToString(arr) { 34 | if(typeof arr === 'string') { 35 | return arr; 36 | } 37 | var str = '', 38 | _arr = arr; 39 | for(var i = 0; i < _arr.length; i++) { 40 | var one = _arr[i].toString(2), 41 | v = one.match(/^1+?(?=0)/); 42 | if(v && one.length == 8) { 43 | var bytesLength = v[0].length; 44 | var store = _arr[i].toString(2).slice(7 - bytesLength); 45 | for(var st = 1; st < bytesLength; st++) { 46 | store += _arr[st + i].toString(2).slice(2); 47 | } 48 | str += String.fromCharCode(parseInt(store, 2)); 49 | i += bytesLength - 1; 50 | } else { 51 | str += String.fromCharCode(_arr[i]); 52 | } 53 | } 54 | return str; 55 | } 56 | 57 | function getStackTrace(){ 58 | var android_util_Log = Java.use('android.util.Log'), java_lang_Exception = Java.use('java.lang.Exception'); 59 | send('[HY] [stack]' +android_util_Log.getStackTraceString(java_lang_Exception.$new())); 60 | } 61 | 62 | function Bytes2Str(arr){ 63 | var str = ""; 64 | for (var i = 0; i < arr.length; i++) { 65 | var tmp = arr[i].toString(16); 66 | if (tmp.length == 1) { 67 | tmp = "0" + tmp; 68 | } 69 | str += tmp; 70 | } 71 | return str; 72 | } 73 | 74 | //overloads 75 | function hookOverloads(className, func) { 76 | var clazz = Java.use(className); 77 | var overloads = clazz[func].overloads; 78 | for (var i in overloads) { 79 | if (overloads[i].hasOwnProperty('argumentTypes')) { 80 | var parameters = []; 81 | var curArgumentTypes = overloads[i].argumentTypes, args = [], argLog = '['; 82 | for (var j in curArgumentTypes) { 83 | var cName = curArgumentTypes[j].className; 84 | parameters.push(cName); 85 | argLog += "'(" + cName + ") ' + v" + j + ","; 86 | args.push('v' + j); 87 | } 88 | argLog += ']'; 89 | var script = "var ret = this." + func + '(' + args.join(',') + ") || '';\n" 90 | + "console.log(JSON.stringify(" + argLog + "));\n" 91 | + "return ret;"; 92 | args.push(script); 93 | clazz[func].overload.apply(this, parameters).implementation = Function.apply(null, args); 94 | } 95 | } 96 | } 97 | 98 | setTimeout(function() { 99 | Java.perform(function() { 100 | allclass(); 101 | hookOverloads('java.util.HashMap', 'put'); 102 | }); 103 | }, 0); -------------------------------------------------------------------------------- /hookOkhttp.js: -------------------------------------------------------------------------------- 1 | function hook_okhttp3() { 2 | Java.perform(function () { 3 | var ByteString = Java.use("com.android.okhttp.okio.ByteString"); 4 | var Buffer = Java.use("com.android.okhttp.okio.Buffer"); 5 | var Interceptor = Java.use("okhttp3.Interceptor"); 6 | var MyInterceptor = Java.registerClass({ 7 | name: "okhttp3.MyInterceptor", 8 | implements: [Interceptor], 9 | methods: { 10 | intercept: function (chain) { 11 | var request = chain.request(); 12 | try { 13 | console.log("MyInterceptor.intercept onEnter:", request, "\nrequest headers:\n", request.headers()); 14 | var requestBody = request.body(); 15 | var contentLength = requestBody ? requestBody.contentLength() : 0; 16 | if (contentLength > 0) { 17 | var BufferObj = Buffer.$new(); 18 | requestBody.writeTo(BufferObj); 19 | try { 20 | console.log("\nrequest body String:\n", BufferObj.readString(), "\n"); 21 | } catch (error) { 22 | try { 23 | console.log("\nrequest body ByteString:\n", ByteString.of(BufferObj.readByteArray()).hex(), "\n"); 24 | } catch (error) { 25 | console.log("error 1:", error); 26 | } 27 | } 28 | } 29 | } catch (error) { 30 | console.log("error 2:", error); 31 | } 32 | var response = chain.proceed(request); 33 | try { 34 | console.log("MyInterceptor.intercept onLeave:", response, "\nresponse headers:\n", response.headers()); 35 | var responseBody = response.body(); 36 | var contentLength = responseBody ? responseBody.contentLength() : 0; 37 | if (contentLength > 0) { 38 | console.log("\nresponsecontentLength:", contentLength, "responseBody:", responseBody, "\n"); 39 | 40 | var ContentType = response.headers().get("Content-Type"); 41 | console.log("ContentType:", ContentType); 42 | if (ContentType.indexOf("video") == -1) { 43 | if (ContentType.indexOf("application") == 0) { 44 | var source = responseBody.source(); 45 | if (ContentType.indexOf("application/zip") != 0) { 46 | try { 47 | console.log("\nresponse.body StringClass\n", source.readUtf8(), "\n"); 48 | } catch (error) { 49 | try { 50 | console.log("\nresponse.body ByteString\n", source.readByteString().hex(), "\n"); 51 | } catch (error) { 52 | console.log("error 4:", error); 53 | } 54 | } 55 | } 56 | } 57 | 58 | } 59 | 60 | } 61 | 62 | } catch (error) { 63 | console.log("error 3:", error); 64 | } 65 | return response; 66 | } 67 | } 68 | }); 69 | var ArrayList = Java.use("java.util.ArrayList"); 70 | var OkHttpClient = Java.use("okhttp3.OkHttpClient"); 71 | console.log(OkHttpClient); 72 | OkHttpClient.$init.overload('okhttp3.OkHttpClient$Builder').implementation = function (Builder) { 73 | console.log("OkHttpClient.$init:", this, Java.cast(Builder.interceptors(), ArrayList)); 74 | this.$init(Builder); 75 | }; 76 | 77 | var MyInterceptorObj = MyInterceptor.$new(); 78 | var Builder = Java.use("okhttp3.OkHttpClient$Builder"); 79 | console.log(Builder); 80 | Builder.build.implementation = function () { 81 | this.interceptors().clear(); 82 | //var MyInterceptorObj = MyInterceptor.$new(); 83 | this.interceptors().add(MyInterceptorObj); 84 | var result = this.build(); 85 | return result; 86 | }; 87 | 88 | Builder.addInterceptor.implementation = function (interceptor) { 89 | this.interceptors().clear(); 90 | //var MyInterceptorObj = MyInterceptor.$new(); 91 | this.interceptors().add(MyInterceptorObj); 92 | return this; 93 | //return this.addInterceptor(interceptor); 94 | }; 95 | 96 | console.log("hook_okhttp3..."); 97 | }); 98 | } -------------------------------------------------------------------------------- /脱壳/dump_dex.js: -------------------------------------------------------------------------------- 1 | function get_self_process_name() { 2 | var openPtr = Module.getExportByName('libc.so', 'open'); 3 | var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']); 4 | 5 | var readPtr = Module.getExportByName("libc.so", "read"); 6 | var read = new NativeFunction(readPtr, "int", ["int", "pointer", "int"]); 7 | 8 | var closePtr = Module.getExportByName('libc.so', 'close'); 9 | var close = new NativeFunction(closePtr, 'int', ['int']); 10 | 11 | var path = Memory.allocUtf8String("/proc/self/cmdline"); 12 | var fd = open(path, 0); 13 | if (fd !== -1) { 14 | var buffer = Memory.alloc(0x1000); 15 | 16 | var result = read(fd, buffer, 0x1000); 17 | close(fd); 18 | result = ptr(buffer).readCString(); 19 | return result; 20 | } 21 | 22 | return "-1"; 23 | } 24 | 25 | function dump_dex() { 26 | var libart = Process.findModuleByName("libart.so"); 27 | var addr_DefineClass = null; 28 | var symbols = libart.enumerateSymbols(); 29 | for (var index = 0; index < symbols.length; index++) { 30 | var symbol = symbols[index]; 31 | var symbol_name = symbol.name; 32 | //这个DefineClass的函数签名是Android9的 33 | //_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE 34 | if (symbol_name.indexOf("ClassLinker") >= 0 && 35 | symbol_name.indexOf("DefineClass") >= 0 && 36 | symbol_name.indexOf("Thread") >= 0 && 37 | symbol_name.indexOf("DexFile") >= 0 ) { 38 | console.log(symbol_name, symbol.address); 39 | addr_DefineClass = symbol.address; 40 | } 41 | } 42 | var dex_maps = {}; 43 | 44 | console.log("[DefineClass:]", addr_DefineClass); 45 | if (addr_DefineClass) { 46 | Interceptor.attach(addr_DefineClass, { 47 | onEnter: function (args) { 48 | var dex_file = args[5]; 49 | //ptr(dex_file).add(Process.pointerSize) is "const uint8_t* const begin_;" 50 | //ptr(dex_file).add(Process.pointerSize + Process.pointerSize) is "const size_t size_;" 51 | var base = ptr(dex_file).add(Process.pointerSize).readPointer(); 52 | var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt(); 53 | 54 | if (dex_maps[base] === undefined) { 55 | dex_maps[base] = size; 56 | var magic = ptr(base).readCString(); 57 | if (magic.indexOf("dex") === 0) { 58 | var process_name = get_self_process_name(); 59 | if (process_name !== "-1") { 60 | var dex_path = "/data/data/" + process_name + "/files/" + base.toString(16) + "_" + size.toString(16) + ".dex"; 61 | console.log("[find dex]:", dex_path); 62 | var fd = new File(dex_path, "wb"); 63 | if (fd && fd != null) { 64 | var dex_buffer = ptr(base).readByteArray(size); 65 | fd.write(dex_buffer); 66 | fd.flush(); 67 | fd.close(); 68 | console.log("[dump dex]:", dex_path); 69 | 70 | } 71 | } 72 | } 73 | } 74 | }, onLeave: function (retval) { 75 | } 76 | }); 77 | } 78 | } 79 | 80 | var is_hook_libart = false; 81 | 82 | function hook_dlopen() { 83 | Interceptor.attach(Module.findExportByName(null, "dlopen"), { 84 | onEnter: function (args) { 85 | var pathptr = args[0]; 86 | if (pathptr !== undefined && pathptr != null) { 87 | var path = ptr(pathptr).readCString(); 88 | //console.log("dlopen:", path); 89 | if (path.indexOf("libart.so") >= 0) { 90 | this.can_hook_libart = true; 91 | console.log("[dlopen:]", path); 92 | } 93 | } 94 | }, 95 | onLeave: function (retval) { 96 | if (this.can_hook_libart && !is_hook_libart) { 97 | dump_dex(); 98 | is_hook_libart = true; 99 | } 100 | } 101 | }) 102 | 103 | Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), { 104 | onEnter: function (args) { 105 | var pathptr = args[0]; 106 | if (pathptr !== undefined && pathptr != null) { 107 | var path = ptr(pathptr).readCString(); 108 | //console.log("android_dlopen_ext:", path); 109 | if (path.indexOf("libart.so") >= 0) { 110 | this.can_hook_libart = true; 111 | console.log("[android_dlopen_ext:]", path); 112 | } 113 | } 114 | }, 115 | onLeave: function (retval) { 116 | if (this.can_hook_libart && !is_hook_libart) { 117 | dump_dex(); 118 | is_hook_libart = true; 119 | } 120 | } 121 | }); 122 | } 123 | 124 | 125 | setImmediate(hook_dlopen); 126 | -------------------------------------------------------------------------------- /trace.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_trace.js - Code tracer for Android 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script to trace arbitrary Java Methods and 6 | * Module functions for debugging and reverse engineering. 7 | * See https://www.frida.re/ and https://codeshare.frida.re/ 8 | * for further information on this powerful tool. 9 | * 10 | * "We want to help others achieve interop through reverse 11 | * engineering" -- @oleavr 12 | * 13 | * Many thanks to @inode-, @federicodotta, @leonjza, and 14 | * @dankluev. 15 | * 16 | * Example usage: 17 | * # frida -U -f com.target.app -l raptor_frida_android_trace.js --no-pause 18 | * 19 | * Get the latest version at: 20 | * https://github.com/0xdea/frida-scripts/ 21 | */ 22 | 23 | // generic trace 24 | function trace(pattern) 25 | { 26 | var type = (pattern.toString().indexOf("!") === -1) ? "java" : "module"; 27 | 28 | if (type === "module") { 29 | 30 | // trace Module 31 | var res = new ApiResolver("module"); 32 | var matches = res.enumerateMatchesSync(pattern); 33 | var targets = uniqBy(matches, JSON.stringify); 34 | targets.forEach(function(target) { 35 | traceModule(target.address, target.name); 36 | }); 37 | 38 | } else if (type === "java") { 39 | 40 | // trace Java Class 41 | var found = false; 42 | Java.enumerateLoadedClasses({ 43 | onMatch: function(aClass) { 44 | if (aClass.match(pattern)) { 45 | found = true; 46 | var className = aClass.match(/[L](.*);/)[1].replace(/\//g, "."); 47 | traceClass(className); 48 | } 49 | }, 50 | onComplete: function() {} 51 | }); 52 | 53 | // trace Java Method 54 | if (!found) { 55 | try { 56 | traceMethod(pattern); 57 | } 58 | catch(err) { // catch non existing classes/methods 59 | console.error(err); 60 | } 61 | } 62 | } 63 | } 64 | 65 | // find and trace all methods declared in a Java Class 66 | function traceClass(targetClass) 67 | { 68 | var hook = Java.use(targetClass); 69 | var methods = hook.class.getDeclaredMethods(); 70 | hook.$dispose; 71 | 72 | var parsedMethods = []; 73 | methods.forEach(function(method) { 74 | parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]); 75 | }); 76 | 77 | var targets = uniqBy(parsedMethods, JSON.stringify); 78 | targets.forEach(function(targetMethod) { 79 | traceMethod(targetClass + "." + targetMethod); 80 | }); 81 | } 82 | 83 | // trace a specific Java Method 84 | function traceMethod(targetClassMethod) 85 | { 86 | var delim = targetClassMethod.lastIndexOf("."); 87 | if (delim === -1) return; 88 | 89 | var targetClass = targetClassMethod.slice(0, delim) 90 | var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length) 91 | 92 | var hook = Java.use(targetClass); 93 | var overloadCount = hook[targetMethod].overloads.length; 94 | send(hook[targetMethod].overloads) 95 | 96 | console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]"); 97 | 98 | for (var i = 0; i < overloadCount; i++) { 99 | 100 | hook[targetMethod].overloads[i].implementation = function() { 101 | console.warn("\n*** entered " + targetClassMethod); 102 | 103 | // print backtrace 104 | 105 | // var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()); 106 | // console.log("\nBacktrace:\n" + bt); 107 | 108 | // print args 109 | if (arguments.length) console.log(); 110 | for (var j = 0; j < arguments.length; j++) { 111 | console.log("arg[" + j + "]: " + arguments[j]); 112 | } 113 | 114 | // print retval 115 | var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?) 116 | console.log("\nretval: " + retval); 117 | console.warn("\n*** exiting " + targetClassMethod); 118 | return retval; 119 | } 120 | } 121 | } 122 | 123 | // trace Module functions 124 | function traceModule(impl, name) 125 | { 126 | console.log("Tracing " + name); 127 | 128 | Interceptor.attach(impl, { 129 | 130 | onEnter: function(args) { 131 | 132 | // debug only the intended calls 133 | this.flag = false; 134 | // var filename = Memory.readCString(ptr(args[0])); 135 | // if (filename.indexOf("XYZ") === -1 && filename.indexOf("ZYX") === -1) // exclusion list 136 | // if (filename.indexOf("my.interesting.file") !== -1) // inclusion list 137 | this.flag = true; 138 | 139 | if (this.flag) { 140 | console.warn("\n*** entered " + name); 141 | 142 | // print backtrace 143 | console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) 144 | .map(DebugSymbol.fromAddress).join("\n")); 145 | } 146 | }, 147 | 148 | onLeave: function(retval) { 149 | 150 | if (this.flag) { 151 | // print retval 152 | console.log("\nretval: " + retval); 153 | console.warn("\n*** exiting " + name); 154 | } 155 | } 156 | 157 | }); 158 | } 159 | 160 | // remove duplicates from array 161 | function uniqBy(array, key) 162 | { 163 | var seen = {}; 164 | return array.filter(function(item) { 165 | var k = key(item); 166 | return seen.hasOwnProperty(k) ? false : (seen[k] = true); 167 | }); 168 | } 169 | 170 | // usage examples 171 | setTimeout(function() { // avoid java.lang.ClassNotFoundException 172 | 173 | Java.perform(function() { 174 | 175 | // trace("com.bytedance.ies.weboffline.IESOfflineCache.shouldInterceptRequest"); 176 | trace("com.meitu.secret.SigEntity.generatorSigWithFinal"); 177 | // trace("java.security.MessageDigest.digest"); 178 | // trace("java.net.URLEncoder.encode"); 179 | // trace("org.json.JSONObject.put"); 180 | // trace("org.json.JSONObject.put"); 181 | // trace("okhttp3.RequestBody.create"); 182 | // trace("retrofit2.Retrofit$Builder.build"); 183 | // trace("com.tencent.weseevideo.common.report.g$u.g"); 184 | // trace("com.target.utils.CryptoUtils"); 185 | // trace("CryptoUtils"); 186 | // trace(/crypto/i); 187 | // trace("exports:*!open*"); 188 | 189 | }); 190 | }, 0); -------------------------------------------------------------------------------- /hookXlog.js: -------------------------------------------------------------------------------- 1 | // Java.perform(function () { 2 | // ['java.lang.String'].forEach(function (clazz) { 3 | // var func = 'toString'; 4 | // const JavaString = Java.use('java.lang.String'); 5 | // var JavaBase64 = Java.use('java.util.Base64'); 6 | // Java.use(clazz)[func].implementation = function () { 7 | // 8 | // console.log("============================================="); 9 | // var ret = this[func](); 10 | // if (ret.indexOf("xlog")!=-1) { 11 | // var android_util_Log = Java.use('android.util.Log'), 12 | // java_lang_Exception = Java.use('java.lang.Exception'); 13 | // console.log('[HY] [stack]' + android_util_Log.getStackTraceString(java_lang_Exception.$new())); 14 | // } 15 | // console.log(ret); 16 | // send('[HY] [String Catch] [' + i + '] ' + JavaString.$new(ret)); 17 | // send('[HY] [Base64 Code] ['+i+']'+JavaBase64.$new().getEncoder().encodeToString(ret)); 18 | // 19 | // console.log("-----------------------------------------------"); 20 | // return ret; 21 | // } 22 | // }); 23 | // }); 24 | 25 | 26 | // Java.perform(function () { 27 | // ['com.bytedance.ttnet.a.a'].forEach(function (clazz,i) { 28 | // var func = 'aW'; 29 | // Java.use(clazz)[func].implementation = function (a,b,c) { 30 | // 31 | // console.log("============================================="); 32 | // console.log(a); 33 | // console.log(b); 34 | // console.log(c); 35 | // var ret = this[func](a,b,c); 36 | // console.log(ret); 37 | // console.log("-----------------------------------------------"); 38 | // return ret; 39 | // } 40 | // }); 41 | // }); 42 | 43 | // Java.perform(function () { 44 | 45 | 46 | // ['com.bytedance.ttnet.a.a'].forEach(function (clazz,i) { 47 | // var func = 'aW'; 48 | // Java.use(clazz)[func].implementation = function (a,b,c) { 49 | // console.log("============================================="); 50 | // console.log(a); 51 | // console.log(b); 52 | // console.log(c); 53 | // var ret = this[func](a,b,c); 54 | // console.log(ret); 55 | // console.log("-----------------------------------------------"); 56 | // return ret; 57 | // } 58 | // }); 59 | // com.ss.sys.ces.b.e$1 60 | // console.log("statrt"); 61 | // 62 | // ['com.ss.sys.ces.b.e'].forEach(function (clazz, i) { 63 | // var func = 'i'; 64 | // Java.use(clazz)[func].implementation = function () { 65 | // 66 | // console.log("=====================ei======================"); 67 | // // console.log(a); 68 | // // console.log(b); 69 | // var ret = this[func](); 70 | // 71 | // console.log(ret); 72 | // // console.log(this.r); 73 | // console.log("---------------------ei-----------------------"); 74 | // return ret; 75 | // } 76 | // }); 77 | // ['com.ss.sys.ces.b.a'].forEach(function (clazz, i) { 78 | // var func = 'd'; 79 | // Java.use(clazz)[func].implementation = function () { 80 | // 81 | // console.log("=====================ad======================"); 82 | // // console.log(a); 83 | // // console.log(b); 84 | // var ret = this[func](); 85 | // 86 | // console.log(ret); 87 | // // console.log(this.r); 88 | // console.log("---------------------ad-----------------------"); 89 | // return ret; 90 | // } 91 | // }); 92 | // 93 | // ['com.ss.sys.ces.b.b'].forEach(function (clazz, i) { 94 | // var func = 'd'; 95 | // Java.use(clazz)[func].implementation = function () { 96 | // 97 | // console.log("=====================bd======================"); 98 | // // console.log(a); 99 | // // console.log(b); 100 | // var ret = this[func](); 101 | // 102 | // console.log(ret); 103 | // // console.log(this.r); 104 | // console.log("---------------------bd-----------------------"); 105 | // return ret; 106 | // } 107 | // }); 108 | // ['com.ss.sys.ces.b.d'].forEach(function (clazz, i) { 109 | // var func = 'i'; 110 | // Java.use(clazz)[func].implementation = function () { 111 | // 112 | // console.log("=====================di======================"); 113 | // // console.log(a); 114 | // // console.log(b); 115 | // var ret = this[func](); 116 | // 117 | // console.log(ret); 118 | // // console.log(this.r); 119 | // console.log("---------------------di-----------------------"); 120 | // return ret; 121 | // } 122 | // }); 123 | 124 | 125 | // ['com.bytedance.ttnet.f.f'].forEach(function (clazz, i) { 126 | // var func = 'b'; 127 | // Java.use(clazz)[func].implementation = function (a) { 128 | // 129 | // console.log("=====================di======================"); 130 | // console.log(a); 131 | // // console.log(b); 132 | // var ret = this[func](a); 133 | // 134 | // send(ret.o); 135 | // send(ret.d); 136 | // send(ret.h); 137 | // // console.log(this.r); 138 | // console.log("---------------------di-----------------------"); 139 | // return ret; 140 | // } 141 | // }); 142 | 143 | 144 | // var hookclass = Java.use("com.ss.sys.ces.b.c"); 145 | // hookclass.a.overload("java.lang.String","java.util.List").implementation = function (v0,v1) { 146 | // var ret = this.a(v0,v1); 147 | // send(v0); 148 | // send(v1); 149 | // return ret; 150 | // }; 151 | 152 | // var hookclass = Java.use("com.bytedance.ttnet.f.c"); 153 | // hookclass.b.implementation = function (v0,v1) { 154 | // var ret = this.b(v0,v1); 155 | // console.log(v0); 156 | // console.log(v1); 157 | // console.log(ret.toString()); 158 | // // send(v1); 159 | // // send(v2); 160 | // return ret; 161 | // }; 162 | // var hookclass = Java.use("com.ss.sys.ces.out.StcSDKFactory"); 163 | // hookclass.E.implementation = function (a,b,c) { 164 | // console.log(a); 165 | // console.log(b); 166 | // console.log(c); 167 | // 168 | // var ret = this.E(a,b,c); 169 | // 170 | // // console.log(ret.toString()); 171 | // // send(v1); 172 | // // send(v2); 173 | // return ret; 174 | // }; 175 | 176 | 177 | 178 | // }); 179 | 180 | /** 181 | * 字节数组转十六进制字符串 182 | * [16, 1, 2, 3, 4, 5, 6, 7, 8] 转换 100102030405060708 183 | * @param {Array} arr 符合16进制数组 184 | */ 185 | function Bytes2Str(arr){ 186 | var str = ""; 187 | for (var i = 0; i < arr.length; i++) { 188 | var tmp = arr[i].toString(16); 189 | if (tmp.length == 1) { 190 | tmp = "0" + tmp; 191 | } 192 | str += tmp; 193 | } 194 | return str; 195 | } 196 | 197 | 198 | 199 | function byteToString(arr) { 200 | try{ 201 | if(typeof arr === 'string') { 202 | return arr; 203 | } 204 | var str = '', 205 | _arr = arr; 206 | for(var i = 0; i < _arr.length; i++) { 207 | var one = _arr[i].toString(2), 208 | v = one.match(/^1+?(?=0)/); 209 | if(v && one.length == 8) { 210 | var bytesLength = v[0].length; 211 | var store = _arr[i].toString(2).slice(7 - bytesLength); 212 | for(var st = 1; st < bytesLength; st++) { 213 | store += _arr[st + i].toString(2).slice(2); 214 | } 215 | str += String.fromCharCode(parseInt(store, 2)); 216 | i += bytesLength - 1; 217 | } else { 218 | str += String.fromCharCode(_arr[i]); 219 | } 220 | } 221 | return str; 222 | }catch(err){ 223 | return "nnn"; 224 | } 225 | 226 | } 227 | 228 | // Java.perform(function () { 229 | // // const Jstring=Java.use("java.lang.String"); 230 | // // const base64=Java.use("android.util.Base64"); 231 | // ['com.ss.sys.ces.a'].forEach(function (clazz,i) { 232 | // var func = 'meta'; 233 | // Java.use(clazz)[func].implementation = function (a,b,c) { 234 | // 235 | // console.log("============================================="); 236 | // console.log(a); 237 | // console.log(b); 238 | // console.log(c); 239 | // var ret = this[func](a,b,c); 240 | // send(Bytes2Str(ret)); 241 | // // send(base64.encode(ret, 0)); 242 | // // send(Jstring.$new(ret)); 243 | // console.log("-----------------------------------------------"); 244 | // return ret; 245 | // } 246 | // }); 247 | // }); 248 | 249 | 250 | // Java.perform(function () { 251 | // // const Jstring=Java.use("java.lang.String"); 252 | // // const base64=Java.use("android.util.Base64"); 253 | // ['com.ss.sys.ces.c.g'].forEach(function (clazz,i) { 254 | // var func = '$init'; 255 | // Java.use(clazz)[func].implementation = function (a,b) { 256 | 257 | // console.log("============================================="); 258 | // console.log("params1:"+a); 259 | // console.log("params2:"+b); 260 | // // send(a); 261 | // var reta = this[func](a,b); 262 | // // console.log("ret:"+reta); 263 | // console.log("-----------------------------------------------"); 264 | // return reta; 265 | // } 266 | // }); 267 | // }); 268 | 269 | // Java.perform(function () { 270 | // var tt1 = Java.use("com.ss.sys.ces.a"); 271 | // tt1.leviathan.implementation = function (a, b,c) { 272 | // console.log(a); 273 | // console.log(b); 274 | // console.log(c); 275 | // var ret = this.leviathan(a,b,c); 276 | // console.log(ret); 277 | // return ret; 278 | // } 279 | // }); 280 | 281 | -------------------------------------------------------------------------------- /encrypt.js: -------------------------------------------------------------------------------- 1 | function showStacks() { 2 | Java.perform(function () { 3 | send(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new())); 4 | }); 5 | } 6 | 7 | const base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 8 | const base64DecodeChars = new Array((-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), 62, (-1), (-1), (-1), 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, (-1), (-1), (-1), (-1), (-1), (-1), (-1), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, (-1), (-1), (-1), (-1), (-1), (-1), 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, (-1), (-1), (-1), (-1), (-1)); 9 | 10 | function stringToBase64(e) { 11 | var r, a, c, h, o, t; 12 | for (c = e.length, a = 0, r = ''; a < c;) { 13 | if (h = 255 & e.charCodeAt(a++), a === c) { 14 | r += base64EncodeChars.charAt(h >> 2), 15 | r += base64EncodeChars.charAt((3 & h) << 4), 16 | r += '=='; 17 | break; 18 | } 19 | if (o = e.charCodeAt(a++), a === c) { 20 | r += base64EncodeChars.charAt(h >> 2), 21 | r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), 22 | r += base64EncodeChars.charAt((15 & o) << 2), 23 | r += '='; 24 | break; 25 | } 26 | t = e.charCodeAt(a++), 27 | r += base64EncodeChars.charAt(h >> 2), 28 | r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), 29 | r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6), 30 | r += base64EncodeChars.charAt(63 & t) 31 | } 32 | return r; 33 | } 34 | 35 | function base64ToString(e) { 36 | var r, a, c, h, o, t, d; 37 | for (t = e.length, o = 0, d = ''; o < t;) { 38 | do 39 | r = base64DecodeChars[255 & e.charCodeAt(o++)]; 40 | while (o < t && r === -1); 41 | if (r === -1) 42 | break; 43 | do 44 | a = base64DecodeChars[255 & e.charCodeAt(o++)]; 45 | while (o < t && a === -1); 46 | if (a === -1) 47 | break; 48 | d += String.fromCharCode(r << 2 | (48 & a) >> 4); 49 | do { 50 | if (c = 255 & e.charCodeAt(o++), 61 === c) 51 | return d; 52 | c = base64DecodeChars[c] 53 | } while (o < t && c === -1); 54 | if (c === -1) 55 | break; 56 | d += String.fromCharCode((15 & a) << 4 | (60 & c) >> 2); 57 | do { 58 | if (h = 255 & e.charCodeAt(o++), 61 === h) 59 | return d; 60 | h = base64DecodeChars[h] 61 | } while (o < t && h === -1); 62 | if (h === -1) 63 | break; 64 | d += String.fromCharCode((3 & c) << 6 | h) 65 | } 66 | return d; 67 | } 68 | 69 | function hexToBase64(str) { 70 | return base64Encode(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" "))); 71 | } 72 | 73 | function base64ToHex(str) { 74 | for (var i = 0, bin = base64Decode(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) { 75 | var tmp = bin.charCodeAt(i).toString(16); 76 | if (tmp.length === 1) 77 | tmp = "0" + tmp; 78 | hex[hex.length] = tmp; 79 | } 80 | return hex.join(""); 81 | } 82 | 83 | function hexToBytes(str) { 84 | var pos = 0; 85 | var len = str.length; 86 | if (len % 2 !== 0) { 87 | return null; 88 | } 89 | len /= 2; 90 | var hexA = new Array(); 91 | for (var i = 0; i < len; i++) { 92 | var s = str.substr(pos, 2); 93 | var v = parseInt(s, 16); 94 | hexA.push(v); 95 | pos += 2; 96 | } 97 | return hexA; 98 | } 99 | 100 | function bytesToHex(arr) { 101 | var str = ''; 102 | var k, j; 103 | for (var i = 0; i < arr.length; i++) { 104 | k = arr[i]; 105 | j = k; 106 | if (k < 0) { 107 | j = k + 256; 108 | } 109 | if (j < 16) { 110 | str += "0"; 111 | } 112 | str += j.toString(16); 113 | } 114 | return str; 115 | } 116 | 117 | function stringToHex(str) { 118 | var val = ""; 119 | for (var i = 0; i < str.length; i++) { 120 | if (val === "") 121 | val = str.charCodeAt(i).toString(16); 122 | else 123 | val += str.charCodeAt(i).toString(16); 124 | } 125 | return val; 126 | } 127 | 128 | function stringToBytes(str) { 129 | var ch, st, re = []; 130 | for (var i = 0; i < str.length; i++) { 131 | ch = str.charCodeAt(i); 132 | st = []; 133 | do { 134 | st.push(ch & 0xFF); 135 | ch = ch >> 8; 136 | } 137 | while (ch); 138 | re = re.concat(st.reverse()); 139 | } 140 | return re; 141 | } 142 | 143 | function bytesToString(arr) { 144 | var str = ''; 145 | var i; 146 | arr = new Uint8Array(arr); 147 | for (i in arr) { 148 | str += String.fromCharCode(arr[i]); 149 | } 150 | return str; 151 | } 152 | 153 | function bytesToBase64(e) { 154 | var r, a, c, h, o, t; 155 | for (c = e.length, a = 0, r = ''; a < c;) { 156 | if (h = 255 & e[a++], a === c) { 157 | r += base64EncodeChars.charAt(h >> 2), 158 | r += base64EncodeChars.charAt((3 & h) << 4), 159 | r += '=='; 160 | break; 161 | } 162 | if (o = e[a++], a === c) { 163 | r += base64EncodeChars.charAt(h >> 2), 164 | r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), 165 | r += base64EncodeChars.charAt((15 & o) << 2), 166 | r += '='; 167 | break; 168 | } 169 | t = e[a++], 170 | r += base64EncodeChars.charAt(h >> 2), 171 | r += base64EncodeChars.charAt((3 & h) << 4 | (240 & o) >> 4), 172 | r += base64EncodeChars.charAt((15 & o) << 2 | (192 & t) >> 6), 173 | r += base64EncodeChars.charAt(63 & t) 174 | } 175 | return r; 176 | } 177 | 178 | function base64ToBytes(e) { 179 | var r, a, c, h, o, t, d; 180 | for (t = e.length, o = 0, d = []; o < t;) { 181 | do 182 | r = base64DecodeChars[255 & e.charCodeAt(o++)]; 183 | while (o < t && r === -1); 184 | if (r === -1) 185 | break; 186 | do 187 | a = base64DecodeChars[255 & e.charCodeAt(o++)]; 188 | while (o < t && a === -1); 189 | if (a === -1) 190 | break; 191 | d.push(r << 2 | (48 & a) >> 4); 192 | do { 193 | if (c = 255 & e.charCodeAt(o++), 61 === c) 194 | return d; 195 | c = base64DecodeChars[c] 196 | } while (o < t && c === -1); 197 | if (c === -1) 198 | break; 199 | d.push((15 & a) << 4 | (60 & c) >> 2); 200 | do { 201 | if (h = 255 & e.charCodeAt(o++), 61 === h) 202 | return d; 203 | h = base64DecodeChars[h] 204 | } while (o < t && h === -1); 205 | if (h === -1) 206 | break; 207 | d.push((3 & c) << 6 | h) 208 | } 209 | return d; 210 | } 211 | 212 | 213 | // stringToBase64 stringToHex stringToBytes 214 | // base64ToString base64ToHex base64ToBytes 215 | // hexToBase64 hexToBytes 216 | // bytesToBase64 bytesToHex bytesToString 217 | 218 | Java.perform(function () { 219 | var secretKeySpec = Java.use('javax.crypto.spec.SecretKeySpec'); 220 | secretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function (a, b) { 221 | showStacks(); 222 | var result = this.$init(a, b); 223 | send("======================================"); 224 | send("算法名:" + b + "|Dec密钥:" + bytesToString(a)); 225 | send("算法名:" + b + "|Hex密钥:" + bytesToHex(a)); 226 | return result; 227 | }; 228 | var mac = Java.use('javax.crypto.Mac'); 229 | mac.getInstance.overload('java.lang.String').implementation = function (a) { 230 | showStacks(); 231 | var result = this.getInstance(a); 232 | send("======================================"); 233 | send("算法名:" + a); 234 | return result; 235 | }; 236 | mac.update.overload('[B').implementation = function (a) { 237 | showStacks(); 238 | this.update(a); 239 | send("======================================"); 240 | send("update:" + bytesToString(a)) 241 | }; 242 | mac.update.overload('[B', 'int', 'int').implementation = function (a, b, c) { 243 | showStacks(); 244 | this.update(a, b, c); 245 | send("======================================"); 246 | send("update:" + bytesToString(a) + "|" + b + "|" + c); 247 | }; 248 | mac.doFinal.overload().implementation = function () { 249 | showStacks(); 250 | var result = this.doFinal(); 251 | send("======================================"); 252 | send("doFinal结果:" + bytesToHex(result)); 253 | send("doFinal结果:" + bytesToBase64(result)); 254 | return result; 255 | }; 256 | mac.doFinal.overload('[B').implementation = function (a) { 257 | showStacks(); 258 | var result = this.doFinal(a); 259 | send("======================================"); 260 | send("doFinal参数:" + bytesToString(a)); 261 | send("doFinal结果:" + bytesToHex(result)); 262 | send("doFinal结果:" + bytesToBase64(result)); 263 | return result; 264 | }; 265 | var md = Java.use('java.security.MessageDigest'); 266 | md.getInstance.overload('java.lang.String', 'java.lang.String').implementation = function (a, b) { 267 | showStacks(); 268 | send("======================================"); 269 | send("算法名:" + a); 270 | return this.getInstance(a, b); 271 | }; 272 | md.getInstance.overload('java.lang.String').implementation = function (a) { 273 | showStacks(); 274 | send("======================================"); 275 | send("算法名:" + a); 276 | return this.getInstance(a); 277 | }; 278 | md.update.overload('[B').implementation = function (a) { 279 | showStacks(); 280 | send("======================================"); 281 | send("update:" + bytesToString(a)); 282 | return this.update(a); 283 | }; 284 | md.update.overload('[B', 'int', 'int').implementation = function (a, b, c) { 285 | showStacks(); 286 | send("======================================"); 287 | send("update:" + bytesToString(a) + "|" + b + "|" + c); 288 | return this.update(a, b, c); 289 | }; 290 | md.digest.overload().implementation = function () { 291 | showStacks(); 292 | send("======================================"); 293 | var result = this.digest(); 294 | send("digest结果:" + bytesToHex(result)); 295 | send("digest结果:" + bytesToBase64(result)); 296 | return result; 297 | }; 298 | md.digest.overload('[B').implementation = function (a) { 299 | showStacks(); 300 | send("======================================"); 301 | send("digest参数:" + bytesToString(a)); 302 | var result = this.digest(a); 303 | send("digest结果:" + bytesToHex(result)); 304 | send("digest结果:" + bytesToBase64(result)); 305 | return result; 306 | }; 307 | var ivParameterSpec = Java.use('javax.crypto.spec.IvParameterSpec'); 308 | ivParameterSpec.$init.overload('[B').implementation = function (a) { 309 | showStacks(); 310 | var result = this.$init(a); 311 | send("======================================"); 312 | send("iv向量:" + bytesToString(a)); 313 | send("iv向量:" + bytesToHex(a)); 314 | return result; 315 | }; 316 | var cipher = Java.use('javax.crypto.Cipher'); 317 | cipher.getInstance.overload('java.lang.String').implementation = function (a) { 318 | showStacks(); 319 | var result = this.getInstance(a); 320 | send("======================================"); 321 | send("模式填充:" + a); 322 | return result; 323 | }; 324 | cipher.update.overload('[B').implementation = function (a) { 325 | showStacks(); 326 | var result = this.update(a); 327 | send("======================================"); 328 | send("update:" + bytesToString(a)); 329 | return result; 330 | }; 331 | cipher.update.overload('[B', 'int', 'int').implementation = function (a, b, c) { 332 | showStacks(); 333 | var result = this.update(a, b, c); 334 | send("======================================"); 335 | send("update:" + bytesToString(a) + "|" + b + "|" + c); 336 | return result; 337 | }; 338 | cipher.doFinal.overload().implementation = function () { 339 | showStacks(); 340 | var result = this.doFinal(); 341 | send("======================================"); 342 | send("doFinal结果:" + bytesToHex(result)); 343 | send("doFinal结果:" + bytesToBase64(result)); 344 | return result; 345 | }; 346 | cipher.doFinal.overload('[B').implementation = function (a) { 347 | showStacks(); 348 | var result = this.doFinal(a); 349 | send("======================================"); 350 | send("doFinal参数:" + bytesToString(a)); 351 | send("doFinal结果:" + bytesToHex(result)); 352 | send("doFinal结果:" + bytesToBase64(result)); 353 | return result; 354 | }; 355 | var x509EncodedKeySpec = Java.use('java.security.spec.X509EncodedKeySpec'); 356 | x509EncodedKeySpec.$init.overload('[B').implementation = function (a) { 357 | showStacks(); 358 | var result = this.$init(a); 359 | send("======================================"); 360 | send("RSA密钥:" + bytesToBase64(a)); 361 | return result; 362 | }; 363 | var rSAPublicKeySpec = Java.use('java.security.spec.RSAPublicKeySpec'); 364 | rSAPublicKeySpec.$init.overload('java.math.BigInteger', 'java.math.BigInteger').implementation = function (a, b) { 365 | showStacks(); 366 | var result = this.$init(a, b); 367 | send("======================================"); 368 | send("RSA密钥:" + bytesToBase64(a)); 369 | send("RSA密钥N:" + a.toString(16)); 370 | send("RSA密钥E:" + b.toString(16)); 371 | return result; 372 | } 373 | }); --------------------------------------------------------------------------------