├── README.md
├── TestAppsFlyer
├── .gitignore
├── .idea
│ ├── codeStyles
│ │ └── Project.xml
│ ├── gradle.xml
│ ├── misc.xml
│ └── runConfigurations.xml
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── king
│ │ │ └── testappsflyer
│ │ │ └── ExampleInstrumentedTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── test
│ │ │ │ └── flyer
│ │ │ │ ├── InstallReceiver.java
│ │ │ │ └── MainActivity.java
│ │ └── res
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ │ ├── layout
│ │ │ └── activity_main.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── king
│ │ └── testappsflyer
│ │ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
└── raptor_frida_android_trace_luoyanbei.js
/README.md:
--------------------------------------------------------------------------------
1 | # android_frida_trace_myTrace
2 | android使用frida脚本追踪方法调用,方法之间的关系一目了然。
3 |
4 | ### 开始
5 | 在 [android逆向__超级好用,使用frida追踪方法](https://juejin.im/post/5d0ca6c8e51d45777b1a3db2) 一文中,介绍了如何使用firda脚本追踪android的方法调用,在实际的使用中,方法被调用,就会在终端打印方法的开始标记、方法的参数和方法的结束标记。但是看起来有些凌乱:
6 | ```
7 | *** entered com.test.flyer.MainActivity$1.onClick
8 | arg[0]: android.support.v7.widget.AppCompatButton{4267c9c8 VFED..C. ...P.... 0,0-264,144 #7f070022 app:id/button}
9 | *** entered com.test.flyer.MainActivity.test
10 | arg[0]: Jack
11 | *** entered com.test.flyer.MainActivity.gainAge
12 | arg[0]: 16
13 | retval: 26
14 | *** exiting com.test.flyer.MainActivity.gainAge
15 | *** entered com.test.flyer.MainActivity.gainEnjoy
16 | arg[0]: 篮球
17 | retval: 我喜欢篮球
18 | *** exiting com.test.flyer.MainActivity.gainEnjoy
19 | retval: OK
20 | *** exiting com.test.flyer.MainActivity.test
21 | retval: undefined
22 | *** exiting com.test.flyer.MainActivity$1.onClick
23 | ```
24 | 截图效果:
25 |
26 | 
27 |
28 | ### 改进
29 | 在这样一堆打印中,我们不能清晰的分辨各个方法的嵌套关系,总之一句话,就是不够醒目。于是乎对 raptor_frida_android_trace.js 脚本做了改进,下面是部分内容:
30 | ```
31 | var logContentArray = new Array();
32 |
33 | var singlePrefix = "|----"
34 |
35 |
36 | // find and trace all methods declared in a Java Class
37 | function traceClass(targetClass)
38 | {
39 | var hook = Java.use(targetClass);
40 | var methods = hook.class.getDeclaredMethods();
41 | hook.$dispose;
42 |
43 | var parsedMethods = [];
44 | methods.forEach(function(method) {
45 | parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]);
46 | });
47 |
48 | var targets = uniqBy(parsedMethods, JSON.stringify);
49 | targets.forEach(function(targetMethod) {
50 | traceMethod(targetClass + "." + targetMethod);
51 | });
52 | }
53 |
54 | // trace a specific Java Method
55 | function traceMethod(targetClassMethod)
56 | {
57 | var delim = targetClassMethod.lastIndexOf(".");
58 | if (delim === -1) return;
59 |
60 | // slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分
61 | var targetClass = targetClassMethod.slice(0, delim)
62 | var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length)
63 |
64 | var hook = Java.use(targetClass);
65 | var overloadCount = hook[targetMethod].overloads.length;
66 |
67 | console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]");
68 |
69 | for (var i = 0; i < overloadCount; i++) {
70 |
71 | // hook方法
72 | hook[targetMethod].overloads[i].implementation = function() {
73 |
74 | var logContent_1 = "entered--"+targetClassMethod;
75 |
76 | var prefixStr = gainLogPrefix(logContentArray);
77 |
78 | logContentArray.push(prefixStr + logContent_1);
79 |
80 | console.warn(prefixStr + logContent_1);
81 |
82 | // print backtrace, 打印调用堆栈
83 | // Java.perform(function() {
84 | // var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
85 | // console.log(prefixStr +"Backtrace:" + bt);
86 | // });
87 |
88 | // print args
89 | // if (arguments.length) console.log();
90 |
91 | // 打印参数
92 | for (var j = 0; j < arguments.length; j++)
93 | {
94 | var tmpLogStr = prefixStr + "arg[" + j + "]: " + arguments[j];
95 | console.log(tmpLogStr);
96 | logContentArray.push(tmpLogStr);
97 | }
98 | // print retval
99 | var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?)
100 | // 打印返回值
101 | // console.log("\n"+ targetClassMethod +"--retval: " + retval);
102 | var tmpReturnStr = prefixStr + "retval: " + retval;
103 | logContentArray.push(tmpReturnStr);
104 | console.log(tmpReturnStr);
105 | //结束标志
106 | var logContent_ex = "exiting--" + targetClassMethod;
107 | logContentArray.push(prefixStr + logContent_ex);
108 | console.warn(prefixStr + logContent_ex);
109 | return retval;
110 | }
111 | }
112 | }
113 |
114 | // 获取打印前缀
115 | function gainLogPrefix(theArray)
116 | {
117 | var lastIndex = theArray.length - 1;
118 |
119 | if (lastIndex<0)
120 | {
121 | return singlePrefix;
122 | }
123 |
124 | for (var i = lastIndex; i >= 0; i--)
125 | {
126 | var tmpLogContent = theArray[i];
127 | var cIndex = tmpLogContent.indexOf("entered--");
128 |
129 | if ( cIndex == -1)
130 | {
131 | var cIndex2 = tmpLogContent.indexOf("exiting--");
132 | if ( cIndex2 == -1)
133 | {
134 | continue;
135 | }
136 | else
137 | {
138 | //与上个方法平级
139 | var resultStr = tmpLogContent.slice(0,cIndex2);
140 | return resultStr;
141 | }
142 | }
143 | else
144 | {
145 | //在上个方法的内部
146 | var resultStr = singlePrefix + tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
147 | // console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
148 | return resultStr;
149 |
150 | }
151 | }
152 | return "";
153 | }
154 |
155 | // usage examples
156 | setTimeout(function() { // avoid java.lang.ClassNotFoundException
157 |
158 | Java.perform(function() {
159 |
160 | trace("com.test.flyer.MainActivity");
161 | // trace("com.test.flyer.MainActivity.gainAge");
162 |
163 | // trace("com.target.utils.CryptoUtils.decrypt");
164 | // trace("com.target.utils.CryptoUtils");
165 | // trace("CryptoUtils");
166 | // trace(/crypto/i);
167 | // trace("exports:*!open*");
168 |
169 | });
170 | }, 0);
171 | ```
172 | js文件内,主要新增 gainLogPrefix方法和 gainLogPrefix_Module方法,用于生成"|----"标记。
173 |
174 | 使用新的js追踪方法,终端打印如下:
175 | ```
176 | |----entered--com.test.flyer.MainActivity$1.onClick
177 | |----arg[0]: android.support.v7.widget.AppCompatButton{426a5f40 VFED..C. ...P.... 0,0-264,144 #7f070022 app:id/button}
178 | |----|----entered--com.test.flyer.MainActivity.test
179 | |----|----arg[0]: Jack
180 | |----|----|----entered--com.test.flyer.MainActivity.gainAge
181 | |----|----|----arg[0]: 16
182 | |----|----|----retval: 26
183 | |----|----|----exiting--com.test.flyer.MainActivity.gainAge
184 | |----|----|----entered--com.test.flyer.MainActivity.gainEnjoy
185 | |----|----|----arg[0]: 篮球
186 | |----|----|----retval: 我喜欢篮球
187 | |----|----|----exiting--com.test.flyer.MainActivity.gainEnjoy
188 | |----|----retval: OK
189 | |----|----exiting--com.test.flyer.MainActivity.test
190 | |----retval: undefined
191 | |----exiting--com.test.flyer.MainActivity$1.onClick
192 | ```
193 | 截图效果:
194 |
195 | 
196 |
197 | 看起来顺眼多了,哈哈哈,希望各位大佬能喜欢。
198 |
199 | ### 结束
200 | 本次测试项目和js脚本获取方式:
201 |
202 | 1、关注公众号"逆向APP",回复"frida追踪方法02"
203 | 
204 |
205 | 2、[github地址](https://github.com/luoyanbei/android_frida_trace_myTrace),可以帮忙点个 Star
206 |
--------------------------------------------------------------------------------
/TestAppsFlyer/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches/build_file_checksums.ser
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | .DS_Store
9 | /build
10 | /captures
11 | .externalNativeBuild
12 |
--------------------------------------------------------------------------------
/TestAppsFlyer/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/TestAppsFlyer/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/TestAppsFlyer/.idea/misc.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/TestAppsFlyer/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 28
5 | defaultConfig {
6 | applicationId "com.example.king.testappsflyer"
7 | minSdkVersion 15
8 | targetSdkVersion 28
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
12 | }
13 | buildTypes {
14 | release {
15 | minifyEnabled false
16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17 | }
18 | }
19 | }
20 |
21 | dependencies {
22 | implementation fileTree(dir: 'libs', include: ['*.jar'])
23 | implementation 'com.android.support:appcompat-v7:28.0.0'
24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3'
25 | testImplementation 'junit:junit:4.12'
26 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
28 | }
29 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/androidTest/java/com/example/king/testappsflyer/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.king.testappsflyer;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals( "com.example.king.testappsflyer", appContext.getPackageName() );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/java/com/test/flyer/InstallReceiver.java:
--------------------------------------------------------------------------------
1 | package com.test.flyer;
2 |
3 | import java.util.Timer;
4 | import java.util.TimerTask;
5 |
6 | import android.content.BroadcastReceiver;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.util.Log;
10 |
11 | import java.util.logging.Handler;
12 | import java.util.logging.LogRecord;
13 |
14 | /**
15 | * 广告显示进行安装监听进行上报
16 | */
17 |
18 | public class InstallReceiver extends BroadcastReceiver {
19 |
20 | private static String TAG = "InstallReceiver";
21 | private Context mContext;
22 |
23 | /**
24 | *
25 | *
26 | * @param context
27 | * @param intent
28 | */
29 | @Override
30 | public void onReceive(Context context, Intent intent) {
31 |
32 |
33 |
34 | }
35 |
36 | private void send(String packageName, String referrer) {
37 |
38 | }
39 |
40 |
41 |
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/java/com/test/flyer/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.test.flyer;
2 |
3 | import android.content.Intent;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.os.Bundle;
6 | import android.util.Log;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.Toast;
10 |
11 | import com.example.king.testappsflyer.R;
12 |
13 | public class MainActivity extends AppCompatActivity {
14 |
15 | private Button testBtn;
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate( savedInstanceState );
20 | setContentView( R.layout.activity_main );
21 |
22 | testBtn = (Button) findViewById(R.id.button);
23 | testBtn.setOnClickListener( new View.OnClickListener() {
24 | @Override
25 | public void onClick(View v) {
26 | Log.d( "test", "do--click--testBtn" );
27 | String text = test("Jack");
28 | Log.d( "test", "do--test--return= "+text );
29 | // send("step.tracker.stepcounter.walking", "utm_source=google-play&utm_medium=WJ");
30 |
31 | }
32 | } );
33 |
34 | }
35 |
36 | private void send(String packageName, String referrer) {
37 | Intent intent = new Intent();
38 | intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
39 | intent.putExtra("referrer", referrer);
40 | intent.setAction("com.android.vending.INSTALL_REFERRER");
41 | intent.setPackage(packageName);
42 | this.sendBroadcast(intent);
43 | Log.d("InstallReceiver", "sendBroadcast: success");
44 | }
45 |
46 |
47 | public String test(String name) {
48 | Log.d("test", "do--test");
49 | int age = gainAge( 16 );
50 | String enjoy = gainEnjoy("篮球");
51 | Toast toast=Toast.makeText(MainActivity.this, "do--test--success--"+name+"--age="+age, Toast.LENGTH_LONG);
52 | //显示toast信息
53 | toast.show();
54 | return "OK";
55 | }
56 |
57 |
58 | private int gainAge(int age) {
59 |
60 | Log.d("test", "do--gainAge--age= "+age);
61 |
62 | return age+10;
63 |
64 | }
65 |
66 | private String gainEnjoy(String enjoy) {
67 |
68 | Log.d("test", "do--gainEnjoy--enjoy= "+enjoy);
69 |
70 | return "我喜欢"+enjoy;
71 |
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
25 |
26 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | TestAppsFlyer
3 |
4 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/TestAppsFlyer/app/src/test/java/com/example/king/testappsflyer/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.king.testappsflyer;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals( 4, 2 + 2 );
16 | }
17 | }
--------------------------------------------------------------------------------
/TestAppsFlyer/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.0'
11 |
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/TestAppsFlyer/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 |
15 |
--------------------------------------------------------------------------------
/TestAppsFlyer/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/luoyanbei/android_frida_trace_myTrace/be961387faa24f1297b5264c320769b5ccf95d74/TestAppsFlyer/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/TestAppsFlyer/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/TestAppsFlyer/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/TestAppsFlyer/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/TestAppsFlyer/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/raptor_frida_android_trace_luoyanbei.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 | //公众号:逆向APP
24 |
25 | var logContentArray = new Array();
26 |
27 | var singlePrefix = "|----"
28 |
29 | // generic trace
30 | function trace(pattern)
31 | {
32 | // indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置,未出现则返回-1
33 | var type = (pattern.toString().indexOf("!") === -1) ? "java" : "module";
34 |
35 | if (type === "module") {
36 | console.log("is--module")
37 | // trace Module
38 | var res = new ApiResolver("module");
39 | var matches = res.enumerateMatchesSync(pattern);
40 | var targets = uniqBy(matches, JSON.stringify);
41 | targets.forEach(function(target) {
42 | traceModule(target.address, target.name);
43 | });
44 |
45 | } else if (type === "java") {
46 | console.log("is--java")
47 |
48 | // trace Java Class, 遍历加载的类,判断追踪的是否是类
49 | var found = false;
50 | Java.enumerateLoadedClasses({
51 | onMatch: function(aClass) {
52 | // console.log("is--java--1--"+aClass.toString())
53 |
54 | if (aClass.match(pattern)) {
55 |
56 | console.log("is--java--2--"+aClass.toString())
57 |
58 | found = true;
59 | //match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。
60 | // 该方法类似 indexOf() 和 lastIndexOf(),但是它返回指定的值,而不是字符串的位置。
61 | var className = aClass.match(/[L](.*);/)[1].replace(/\//g, ".");
62 |
63 | console.log('('+aClass.toString()+')-----'+className.toString());
64 |
65 | traceClass(className);
66 | }
67 | },
68 | onComplete: function() {}
69 | });
70 |
71 | // trace Java Method, 追踪方法
72 | if (!found) {
73 | try {
74 | console.log('trace---method---'+pattern.toString())
75 | traceMethod(pattern);
76 | }
77 | catch(err) { // catch non existing classes/methods
78 | console.error(err);
79 | }
80 | }
81 | }
82 | }
83 |
84 | // find and trace all methods declared in a Java Class
85 | function traceClass(targetClass)
86 | {
87 | var hook = Java.use(targetClass);
88 | var methods = hook.class.getDeclaredMethods();
89 | hook.$dispose;
90 |
91 | var parsedMethods = [];
92 | methods.forEach(function(method) {
93 | parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]);
94 | });
95 |
96 | var targets = uniqBy(parsedMethods, JSON.stringify);
97 | targets.forEach(function(targetMethod) {
98 | traceMethod(targetClass + "." + targetMethod);
99 | });
100 | }
101 |
102 | // trace a specific Java Method
103 | function traceMethod(targetClassMethod)
104 | {
105 | var delim = targetClassMethod.lastIndexOf(".");
106 | if (delim === -1) return;
107 |
108 | // slice() 方法可提取字符串的某个部分,并以新的字符串返回被提取的部分
109 | var targetClass = targetClassMethod.slice(0, delim)
110 | var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length)
111 |
112 | var hook = Java.use(targetClass);
113 | var overloadCount = hook[targetMethod].overloads.length;
114 |
115 | console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]");
116 |
117 | for (var i = 0; i < overloadCount; i++) {
118 |
119 | // hook方法
120 | hook[targetMethod].overloads[i].implementation = function() {
121 |
122 | var logContent_1 = "entered--"+targetClassMethod;
123 |
124 | var prefixStr = gainLogPrefix(logContentArray);
125 |
126 | logContentArray.push(prefixStr + logContent_1);
127 |
128 | console.warn(prefixStr + logContent_1);
129 |
130 | // print backtrace, 打印调用堆栈
131 | // Java.perform(function() {
132 | // var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new());
133 | // console.log(prefixStr +"Backtrace:" + bt);
134 | // });
135 |
136 | // print args
137 | // if (arguments.length) console.log();
138 |
139 | // 打印参数
140 | for (var j = 0; j < arguments.length; j++)
141 | {
142 | var tmpLogStr = prefixStr + "arg[" + j + "]: " + arguments[j];
143 | console.log(tmpLogStr);
144 | logContentArray.push(tmpLogStr);
145 | }
146 |
147 | // print retval
148 | var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?)
149 | // 打印返回值
150 | // console.log("\n"+ targetClassMethod +"--retval: " + retval);
151 |
152 | var tmpReturnStr = prefixStr + "retval: " + retval;
153 | logContentArray.push(tmpReturnStr);
154 | console.log(tmpReturnStr);
155 |
156 | //结束标志
157 | var logContent_ex = "exiting--" + targetClassMethod;
158 | logContentArray.push(prefixStr + logContent_ex);
159 | console.warn(prefixStr + logContent_ex);
160 |
161 |
162 | return retval;
163 | }
164 | }
165 | }
166 |
167 | // 获取打印前缀
168 | function gainLogPrefix(theArray)
169 | {
170 | var lastIndex = theArray.length - 1;
171 |
172 | if (lastIndex<0)
173 | {
174 | return singlePrefix;
175 | }
176 |
177 |
178 | for (var i = lastIndex; i >= 0; i--)
179 | {
180 | var tmpLogContent = theArray[i];
181 | var cIndex = tmpLogContent.indexOf("entered--");
182 |
183 | if ( cIndex == -1)
184 | {
185 | var cIndex2 = tmpLogContent.indexOf("exiting--");
186 | if ( cIndex2 == -1)
187 | {
188 | continue;
189 | }
190 | else
191 | {
192 | //与上个方法平级
193 | var resultStr = tmpLogContent.slice(0,cIndex2);
194 | return resultStr;
195 | }
196 | }
197 | else
198 | {
199 | //在上个方法的内部
200 | var resultStr = singlePrefix + tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
201 | // console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
202 | return resultStr;
203 |
204 | }
205 | }
206 |
207 |
208 | return "";
209 |
210 | }
211 |
212 |
213 |
214 | // 获取打印前缀
215 | function gainLogPrefix_Module(theArray,status)
216 | {
217 | var lastIndex = theArray.length - 1;
218 |
219 | if (lastIndex<0)
220 | {
221 | return singlePrefix;
222 | }
223 |
224 |
225 | for (var i = lastIndex; i >= 0; i--)
226 | {
227 | var tmpLogContent = theArray[i];
228 | var cIndex = tmpLogContent.indexOf("entered--");
229 |
230 | if ( cIndex == -1)
231 | {
232 | var cIndex2 = tmpLogContent.indexOf("exiting--");
233 | if ( cIndex2 == -1)
234 | {
235 | continue;
236 | }
237 | else
238 | {
239 | //与上个方法平级
240 | var resultStr = tmpLogContent.slice(0,cIndex2);
241 | return resultStr;
242 | }
243 | }
244 | else
245 | {
246 | if (tmpLogContent.indexOf(status)==-1)
247 | {
248 | //与上一条输出 平级
249 | var resultStr = tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
250 | // console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
251 | return resultStr;
252 | }
253 | else
254 | {
255 | //在上个方法的内部
256 | var resultStr = singlePrefix + tmpLogContent.slice(0,cIndex);//replace(/entered--/, "");
257 | // console.log("("+tmpLogContent+")前缀是:("+resultStr+")");
258 | return resultStr;
259 | }
260 |
261 | }
262 | }
263 |
264 |
265 | return "";
266 |
267 | }
268 |
269 | // trace Module functions
270 | function traceModule(impl, name)
271 | {
272 | console.log("Tracing " + name);
273 |
274 | Interceptor.attach(impl, {
275 |
276 |
277 | onEnter: function(args) {
278 |
279 |
280 | // debug only the intended calls
281 | this.flag = false;
282 | // var filename = Memory.readCString(ptr(args[0]));
283 | // if (filename.indexOf("XYZ") === -1 && filename.indexOf("ZYX") === -1) // exclusion list
284 | // if (filename.indexOf("my.interesting.file") !== -1) // inclusion list
285 | this.flag = true;
286 |
287 | if (this.flag) {
288 | var prefixStr = gainLogPrefix_Module(logContentArray,"entered--");
289 | // console.warn("\n*** entered " + name);
290 |
291 | var logContent_1 = "entered--"+name;
292 | logContentArray.push(prefixStr + logContent_1);
293 | console.warn(prefixStr + logContent_1);
294 |
295 | // print backtrace, 打印调用堆栈
296 | // console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"));
297 | }
298 | },
299 |
300 | onLeave: function(retval) {
301 |
302 |
303 | if (this.flag) {
304 |
305 | var prefixStr = gainLogPrefix_Module(logContentArray,"non6soidjs3kejf6sle8ifsjie");
306 |
307 | // print retval
308 | // console.log("\nretval: " + retval);
309 | var logContent_1 = "retval:"+retval;
310 | logContentArray.push(prefixStr + logContent_1);
311 | console.warn(prefixStr + logContent_1);
312 |
313 | var logContent_2 = "exiting--"+name;
314 | logContentArray.push(prefixStr + logContent_2);
315 | console.warn(prefixStr + logContent_2);
316 |
317 |
318 | // console.warn("\n*** exiting " + name);
319 | }
320 | }
321 |
322 | });
323 | }
324 |
325 | // remove duplicates from array
326 | function uniqBy(array, key)
327 | {
328 | var seen = {};
329 | return array.filter(function(item) {
330 | var k = key(item);
331 | return seen.hasOwnProperty(k) ? false : (seen[k] = true);
332 | });
333 | }
334 |
335 | // usage examples
336 | setTimeout(function() { // avoid java.lang.ClassNotFoundException
337 |
338 | Java.perform(function() {
339 |
340 | trace("com.test.flyer.MainActivity");
341 | // trace("com.test.flyer.MainActivity.gainAge");
342 |
343 | // trace("com.target.utils.CryptoUtils.decrypt");
344 | // trace("com.target.utils.CryptoUtils");
345 | // trace("CryptoUtils");
346 | // trace(/crypto/i);
347 | // trace("exports:*!open*");
348 |
349 | });
350 | }, 0);
351 |
--------------------------------------------------------------------------------