DEX 함수 호출 Stack 추적

홈 > 안드로이드 > 안드로이드
안드로이드

DEX 함수 호출 Stack 추적

M LIN 16 16297 4

클래스명 입력하면 호출된 메소드 이름 확인이 가능합니다. 

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 === -1return;
 
    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);




 

, ,

16 Comments
6 지존 2019.10.17 22:01  
감사합니다 :)
S 코드몽키 2019.10.18 21:15  
유용한정보 감사합니다
6 하늘사자 2019.10.18 23:54  
공유 감사합니다.
린님.. 혹시 가능하시면 arm 모드 so파일에서 호출함수 스택 추적 가능할까요? frida에서 보면 바로 앞에 콜함수 (ld레지스터)만 확인이 가능하더라구요.
M LIN 2019.10.19 18:27  
넵 가능합니다만... 따로 쓰는 기능이긴 한데 UI상에 남겨주기까지는 구현하는데 좀 걸릴것같아요~

Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n');
요거 쓰심 웬만한건 분석됩니당
6 하늘사자 2019.10.20 12:08  
예전에 frida 내부 백트레이스 테스트 했을때는 원하는 만큼 보여주지 못했던거 같은데.. 다시 한번 해 보겠습니다^^
감사합니다..
1 rok795 2019.10.21 12:03  
감사합니다.
3 안녕하새우 2019.10.22 15:35  
공유 감사합니다 :)
1 drockefeler007 2019.10.22 22:05  
감사합니다
1 unlimit 2019.11.07 13:11  
감사합니다.
2 루미에르 2020.03.20 10:50  
공유 감사합니다 (__)
7 래바리 2020.04.03 18:40  
감사합니다.
1 Akii 2020.07.17 22:47  
감사합니다
1 2Doll 2020.07.19 15:32  
감사합니다.
공부하는데 좋은 자료네요
2 knooouix 2020.10.18 14:59  
감사합니다~ 공부하는데 많은 도움 받았습니다 :)
1 김사람 2020.11.14 01:52  
감사합니다
1 lucider 2021.03.04 14:10  
감사합니다