DEX 함수 호출 Stack 추적
클래스명 입력하면 호출된 메소드 이름 확인이 가능합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var ThreadDef = Java.use('java.lang.Thread'); var ThreadObj = ThreadDef.$new(); function stackTrace() { var stack = ThreadObj.currentThread().getStackTrace(); for (var i = 0; i < stack.length; i++) { console.log(i + " => " + stack[i].toString()); } console.log("-------------------------------------"); } var StringDec = Java.use('클래스명'); StringDec.a.overload('java.lang.String').implementation = function (prop) { send("a() - string dec - got called! "); stackTrace(); var ret = this.a(prop); send("ret value : " + ret.toString()); return ret; }; |
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 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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | var logContentArray = new Array(); var singlePrefix = "|-" function uniqBy(array, key) { var seen = {}; return array.filter(function(item) { var k = key(item); return seen.hasOwnProperty(k) ? false : (seen[k] = true); }); } function traceClass(targetClass) { var hook = Java.use(targetClass); var methods = hook.class.getDeclaredMethods(); hook.$dispose; var parsedMethods = []; methods.forEach(function(method) { parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]); }); var targets = uniqBy(parsedMethods, JSON.stringify); targets.forEach(function(targetMethod) { traceMethod(targetClass + "." + targetMethod); }); } // usage examples function traceMethod(targetClassMethod) { var delim = targetClassMethod.lastIndexOf("."); if (delim === -1) return; var targetClass = targetClassMethod.slice(0, delim) var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length) var hook = Java.use(targetClass); var overloadCount = hook[targetMethod].overloads.length; console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]"); for (var i = 0; i < overloadCount; i++) { hook[targetMethod].overloads[i].implementation = function() { var logContent_1 = "entered--"+targetClassMethod; var prefixStr = gainLogPrefix(logContentArray); logContentArray.push(prefixStr + logContent_1); console.log(prefixStr + logContent_1); for (var j = 0; j < arguments.length; j++) { var tmpLogStr = prefixStr + "arg[" + j + "]: " + arguments[j]; console.log(tmpLogStr); } var retval = this[targetMethod].apply(this, arguments); var tmpReturnStr = prefixStr + "retval: " + retval; console.log(tmpReturnStr); var logContent_ex = "exiting--" + targetClassMethod; console.log(prefixStr + logContent_ex); return retval; } } } function gainLogPrefix(theArray) { var lastIndex = theArray.length - 1; if (lastIndex<0) { return singlePrefix; } for (var i = lastIndex; i >= 0; i--) { var tmpLogContent = theArray[i]; var cIndex = tmpLogContent.indexOf("entered--"); if ( cIndex == -1) { var cIndex2 = tmpLogContent.indexOf("exiting--"); if ( cIndex2 == -1) { continue; } else { var resultStr = tmpLogContent.slice(0,cIndex2); return resultStr; } } else { var resultStr = singlePrefix + tmpLogContent.slice(0,cIndex);//replace(/entered--/, ""); return resultStr; } } return ""; } setTimeout(function() { Java.perform(function() { traceClass("com.linforum.dialog"); //traceClass("com.xxx.Application"); }); }, 0); |