diff --git b/.gitignore a/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ a/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git b/.idea/.gitignore a/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ a/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git b/.idea/compiler.xml a/.idea/compiler.xml
new file mode 100644
index 0000000..61a9130
--- /dev/null
+++ a/.idea/compiler.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <bytecodeTargetLevel target="1.8" />
+  </component>
+</project>
\ No newline at end of file
diff --git b/.idea/gradle.xml a/.idea/gradle.xml
new file mode 100644
index 0000000..23a89bb
--- /dev/null
+++ a/.idea/gradle.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleMigrationSettings" migrationVersion="1" />
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="testRunner" value="PLATFORM" />
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleJvm" value="1.8" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+          </set>
+        </option>
+        <option name="resolveModulePerSourceSet" value="false" />
+        <option name="useQualifiedModuleNames" value="true" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git b/.idea/jarRepositories.xml a/.idea/jarRepositories.xml
new file mode 100644
index 0000000..a5f05cd
--- /dev/null
+++ a/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="BintrayJCenter" />
+      <option name="name" value="BintrayJCenter" />
+      <option name="url" value="https://jcenter.bintray.com/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="Google" />
+      <option name="name" value="Google" />
+      <option name="url" value="https://dl.google.com/dl/android/maven2/" />
+    </remote-repository>
+  </component>
+</project>
\ No newline at end of file
diff --git b/.idea/misc.xml a/.idea/misc.xml
new file mode 100644
index 0000000..d5d35ec
--- /dev/null
+++ a/.idea/misc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git b/.idea/vcs.xml a/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ a/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git b/app/.gitignore a/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ a/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git b/app/build.gradle a/app/build.gradle
new file mode 100644
index 0000000..5098667
--- /dev/null
+++ a/app/build.gradle
@@ -0,0 +1,37 @@
+plugins {
+    id 'com.android.application'
+}
+
+android {
+    compileSdkVersion 30
+
+    defaultConfig {
+        applicationId "com.fear1ess.reyunadihookplugin"
+        minSdkVersion 21
+        targetSdkVersion 30
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+    compileOnly 'de.robv.android.xposed:api:82'
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation 'com.google.android.material:material:1.2.1'
+    testImplementation 'junit:junit:4.+'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}
\ No newline at end of file
diff --git b/app/proguard-rules.pro a/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ a/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git b/app/src/androidTest/java/com/fear1ess/reyunaditool/ExampleInstrumentedTest.java a/app/src/androidTest/java/com/fear1ess/reyunaditool/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..55cbadc
--- /dev/null
+++ a/app/src/androidTest/java/com/fear1ess/reyunaditool/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.fear1ess.reyunaditool;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.fear1ess.reyunadihookplugin", appContext.getPackageName());
+    }
+}
\ No newline at end of file
diff --git b/app/src/main/AndroidManifest.xml a/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..68e8dea
--- /dev/null
+++ a/app/src/main/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.fear1ess.reyunaditool">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.ReyunAdiHookPlugin">
+        <meta-data
+            android:name="xposedmodule"
+            android:value="true" />
+        <meta-data
+            android:name="xposedminversion"
+            android:value="40" />
+        <meta-data
+            android:name="xposeddescription"
+            android:value="ReyunAdi hook广告sdk接口插件" />
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git b/app/src/main/aidl/com/fear1ess/reyunaditool/IDoCommandService.aidl a/app/src/main/aidl/com/fear1ess/reyunaditool/IDoCommandService.aidl
new file mode 100644
index 0000000..559fc79
--- /dev/null
+++ a/app/src/main/aidl/com/fear1ess/reyunaditool/IDoCommandService.aidl
@@ -0,0 +1,17 @@
+// IHandleDataService.aidl
+package com.fear1ess.reyunaditool;
+
+// Declare any non-default types here with import statements
+
+interface IDoCommandService {
+    /**
+     * Demonstrates some basic types that you can use as parameters
+     * and return values in AIDL.
+     */
+    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+            double aDouble, String aString);
+
+  //  void handleData(int cmd, in Map args);
+
+    String doCommand(int cmd, String args);
+}
\ No newline at end of file
diff --git b/app/src/main/assets/xposed_init a/app/src/main/assets/xposed_init
new file mode 100644
index 0000000..798cb5c
--- /dev/null
+++ a/app/src/main/assets/xposed_init
@@ -0,0 +1 @@
+com.fear1ess.reyunaditool.HookEntry
\ No newline at end of file
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/AdsSdkExistsFlag.java a/app/src/main/java/com/fear1ess/reyunaditool/AdsSdkExistsFlag.java
new file mode 100644
index 0000000..264674b
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/AdsSdkExistsFlag.java
@@ -0,0 +1,10 @@
+package com.fear1ess.reyunaditool;
+
+public class AdsSdkExistsFlag {
+    public final static int ADMOB = 1;
+    public final static int UNITY = 2;
+    public final static int VUNGLE = 4;
+    public final static int FACEBOOK = 8;
+    public final static int IRONSOURCE = 16;
+    public final static int PANGLEMODULE = 32;
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/ExecuteCmdUtils.java a/app/src/main/java/com/fear1ess/reyunaditool/ExecuteCmdUtils.java
new file mode 100644
index 0000000..cb4bc44
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/ExecuteCmdUtils.java
@@ -0,0 +1,82 @@
+package com.fear1ess.reyunaditool;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ExecuteCmdUtils {
+    public static String TAG = "reyunaditool_log";
+    public static int executeCmd(String cmd){
+        Process p = null;
+        int exitCode = 0;
+        try {
+            p = Runtime.getRuntime().exec("su -c " + cmd);
+            exitCode = p.waitFor();
+            if(exitCode != 0){
+                byte[] b = new byte[1024];
+                InputStream is = p.getErrorStream();
+                ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                int len = 0;
+                while((len = is.read(b)) != -1){
+                    bos.write(b,0,len);
+                    bos.flush();
+                }
+                String cmdErrMsg = new String(bos.toByteArray());
+                bos.close();
+                is.close();
+                Log.e(TAG, cmdErrMsg + " when execute cmd: " + cmd);
+            }
+        } catch (IOException | InterruptedException e) {
+            e.printStackTrace();
+        }
+        return exitCode;
+    }
+
+    public static int installApp(String downloadPath){
+        String cmd = "pm install " + downloadPath;
+        Log.d(TAG, "installApp " + downloadPath);
+        return executeCmd(cmd);
+    }
+
+    public static int finishApp(String packageName){
+        String cmd = "am force-stop " + packageName;
+        Log.d(TAG, "finishApp " + packageName);
+        return executeCmd(cmd);
+    }
+
+    public static int uninstallApp(String packageName){
+        String cmd = "pm uninstall " + packageName;
+        Log.d(TAG, "uninstallapp " + packageName);
+        return executeCmd(cmd);
+    }
+
+    public static int deletePkg(String downloadPath){
+        if(!downloadPath.startsWith("/sdcard/reyundownload")){
+            Log.e(TAG, "delete path is not reyundownload!!!" );
+            return -1;
+        }
+        String cmd = "rm -f " + downloadPath;
+        return executeCmd(cmd);
+    }
+
+    public static int startApp(Context appContext, String packageName) {
+        PackageManager pm = appContext.getPackageManager();
+        Intent intent = pm.getLaunchIntentForPackage(packageName);
+        if(intent == null) return -1;
+        ComponentName cn = intent.getComponent();
+        String pkgName = cn.getPackageName();
+        String className = cn.getClassName();
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        appContext.startActivity(intent);
+        return 0;
+     //   Log.d(TAG, "startApp " + packageName);
+     //   String cmd = "am start -n " + pkgName + "/" + className;
+      //  return executeCmd(cmd);
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/HookEntry.java a/app/src/main/java/com/fear1ess/reyunaditool/HookEntry.java
new file mode 100644
index 0000000..0aa4014
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/HookEntry.java
@@ -0,0 +1,140 @@
+package com.fear1ess.reyunaditool;
+
+import android.app.Activity;
+import android.app.Application;
+import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.adsfinder.AdmobFinder;
+import com.fear1ess.reyunaditool.adsfinder.Finder;
+import com.fear1ess.reyunaditool.adsfinder.FinderUtils;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import de.robv.android.xposed.IXposedHookLoadPackage;
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XC_MethodReplacement;
+import de.robv.android.xposed.XposedBridge;
+import de.robv.android.xposed.XposedHelpers;
+import de.robv.android.xposed.callbacks.XC_LoadPackage;
+
+import static com.fear1ess.reyunaditool.pangle.pangleModule.hook_AppID;
+import static com.fear1ess.reyunaditool.pangle.pangleModule.hook_SlotID;
+import static com.fear1ess.reyunaditool.pangle.pangleModule.hook_doFinal;
+
+public class HookEntry implements IXposedHookLoadPackage {
+    public Context cxt = null;
+    public static ClassLoader cl = null;
+    public static ArrayList<String> admobDataList = new ArrayList<>();
+    public static IDoCommandService hdService = null;
+    public static ServiceConnection conn = null;
+    public static String processName = null;
+    public static String TAG = "adihookplugin_log";
+    public static String[] notNeedAppList = {"android", "system_server", "org.meowcat.edxposed.manager"};
+
+    @Override
+    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
+        processName = (String)Class.forName("android.app.ActivityThread").getDeclaredMethod("currentProcessName").invoke(null);
+
+        Log.d(TAG, "handleLoadPackage processName :" + processName);
+
+        if((lpparam.appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) return;
+
+
+        for(String item : notNeedAppList) {
+            if(item.contains(processName)) return;
+        }
+//        MLog.d(lpparam.packageName);
+//        if(lpparam.packageName.contains("com.union_test.internationad")){
+//            MLog.d(lpparam.packageName+"进入了");
+////            hook_AppID(lpparam);
+////            hook_SlotID(lpparam);
+//            hook_doFinal(lpparam);
+//        }
+        cl = lpparam.classLoader;
+        XposedHelpers.findAndHookMethod("android.view.ContextThemeWrapper", cl, "attachBaseContext",
+                Context.class, new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        Log.d(TAG, "enter app attach....");
+                        cxt = (Context) param.args[0];
+
+                        if(processName.equals("com.topjohnwu.magisk")){
+                            Log.d(TAG, "open app");
+                            ExecuteCmdUtils.startApp(cxt, "com.fear1ess.reyunaditool");
+                            return;
+                        }
+
+                        if(lpparam.processName.contains("com.fear1ess.reyunaditool")) return;
+
+                        Log.d(TAG, "start hook " + processName);
+
+                        Log.d(TAG, "start bindservice...");
+                        bindAdiToolService();
+                        Log.d("reyunadihookplugin_adsfinder", "beforeHookedMethod: "+lpparam.packageName);
+                        FinderUtils.doWork(cl,null);
+                    }
+                });
+
+
+    }
+
+
+
+    public void bindAdiToolService(){
+        Intent intent = new Intent();
+        intent.setComponent(new ComponentName("com.fear1ess.reyunaditool",
+                "com.fear1ess.reyunaditool.DoCommandService"));
+
+        conn = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                hdService = IDoCommandService.Stub.asInterface(service);
+
+                new Thread(){
+                    @Override
+                    public void run() {
+                        try {
+                            String curPkgName = hdService.doCommand(OperateCmd.QUERY_CURRENT_PKGNAME, null);
+                        //    if(!processName.equals(curPkgName)) return;
+                        } catch (RemoteException e) {
+                            e.printStackTrace();
+                        }
+                        FinderUtils.notifyServiceBound(hdService);
+                    }
+                }.start();
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+
+            }
+        };
+
+        boolean res = cxt.bindService(intent, conn, Service.BIND_AUTO_CREATE);
+        if(res == false) Log.d(TAG, "bindAdiToolService failed!");
+        if(res == true) Log.d(TAG, "bindAdiToolService success!");
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/HttpParser.java a/app/src/main/java/com/fear1ess/reyunaditool/HttpParser.java
new file mode 100644
index 0000000..de3ff1c
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/HttpParser.java
@@ -0,0 +1,123 @@
+// by fear1ess 2020/12/25
+
+package com.fear1ess.reyunaditool;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+
+public class HttpParser {
+    private String method;
+    private String path;
+    private Map<String, String> urlParams = new HashMap<>();
+    private Map<String, String> headers = new HashMap<>();
+    private Map<String, String> formBodyParams = null;
+    private Map<String, Object> jsonBodyParams = null;
+    private JSONObject jsonBody = null;
+
+    public String getMethod(){
+        return method;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public String getUrlParam(String key){
+        return urlParams.get(key);
+    }
+
+    public String getHeader(String key) {
+        return headers.get(key);
+    }
+
+    public String getFormBodyParam(String key) {
+        return formBodyParams.get(key);
+    }
+
+    public Object getjsonObjectParam(String key) {
+        return jsonBodyParams.get(key);
+    }
+
+    public JSONObject getJsonBody(){
+        return jsonBody;
+    }
+
+    public HttpParser(byte[] payload){
+        doParse(new String(payload));
+    }
+
+    public HttpParser(String payload){
+        doParse(payload);
+    }
+
+    private boolean doParse(String payload) {
+        String httpStr = new String(payload);
+        if (!httpStr.startsWith("GET") && !httpStr.startsWith("POST")) return false;
+        try {
+            String[] items = httpStr.split("\r\n\r\n");
+            String urlAndHeaderItem = items[0];
+            String[] items_1 = urlAndHeaderItem.split("\r\n", 2);
+            String urls = items_1[0];
+            String[] items_2 = urls.split(" ");
+            method = items_2[0];
+            String[] items_3 = items_2[1].split("\\?");
+            path = items_3[0];
+            if (items_3.length > 1) {
+                String[] urlParamStrs = items_3[1].split("&");
+                for (String item : urlParamStrs) {
+                    String[] paramItem = item.split("=");
+                    String key = URLDecoder.decode(paramItem[0], "utf-8");
+                    String value = URLDecoder.decode(paramItem[1], "utf-8");
+                    urlParams.put(key, value);
+                }
+            }
+            if(items_1.length > 1){
+                String headerStr = items_1[1];
+                String[] headerStrs = headerStr.split("\r\n");
+                headers = new HashMap<>();
+                for (String item : headerStrs) {
+                    String[] headerItem = item.split(": ");
+                    String key = URLDecoder.decode(headerItem[0], "utf-8");
+                    String value = URLDecoder.decode(headerItem[1], "utf-8");
+                    headers.put(key, value);
+                }
+            }
+
+            if (items.length > 1 && httpStr.startsWith("POST")) {
+                String body = items[1];
+                if(headers.get("Content-Type").contains("application/x-www-form-urlencoded")){
+                    formBodyParams = new HashMap<>();
+                    String[] urlParamStrs = body.split("&");
+                    for (String item : urlParamStrs) {
+                        String[] paramItem = item.split("=");
+                        String key = URLDecoder.decode(paramItem[0], "utf-8");
+                        String value = URLDecoder.decode(paramItem[1], "utf-8");
+                        formBodyParams.put(key, value);
+                    }
+                }
+
+                if(headers.get("Content-Type").contains("application/json")){
+                    jsonBodyParams = new HashMap<>();
+                    JSONObject jo = new JSONObject(body);
+                    jsonBody = jo;
+                    Iterator iterator = jo.keys();
+                    while(iterator.hasNext()){
+                        String key = (String) iterator.next();
+                        jsonBodyParams.put(key, jo.get(key));
+                    }
+                }
+            }
+
+        } catch (UnsupportedEncodingException | JSONException e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/MLog.java a/app/src/main/java/com/fear1ess/reyunaditool/MLog.java
new file mode 100644
index 0000000..fc9f31e
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/MLog.java
@@ -0,0 +1,15 @@
+package com.fear1ess.reyunaditool;
+
+import android.util.Log;
+
+public class MLog {
+    private static final String TAG = "ReYunADI";
+    private static boolean is_open=true;
+    public static void d(Object object){
+//        if(is_open)return;
+        synchronized (object){
+
+            Log.d(TAG, ""+object);
+        }
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/OperateCmd.java a/app/src/main/java/com/fear1ess/reyunaditool/OperateCmd.java
new file mode 100644
index 0000000..e34fc54
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/OperateCmd.java
@@ -0,0 +1,8 @@
+package com.fear1ess.reyunaditool;
+
+public class OperateCmd {
+    public final static int SHUTDOWN_APP = 0;
+    public final static int UPLOAD_ADSDK_DATA = 1;
+    public final static int QUERY_CURRENT_PKGNAME = 2;
+    public final static int UPLOAD_ADSDK_EXISTS_STATE = 3;
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/RyTag.java a/app/src/main/java/com/fear1ess/reyunaditool/RyTag.java
new file mode 100644
index 0000000..8caf625
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/RyTag.java
@@ -0,0 +1,5 @@
+package com.fear1ess.reyunaditool;
+
+public class RyTag {
+    public final static String TAG = "reyunadihookplugin_log";
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/AdmobFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/AdmobFinder.java
new file mode 100644
index 0000000..2fbeb63
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/AdmobFinder.java
@@ -0,0 +1,85 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.HookEntry;
+import com.fear1ess.reyunaditool.HttpParser;
+import com.fear1ess.reyunaditool.IDoCommandService;
+import com.fear1ess.reyunaditool.OperateCmd;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XposedBridge;
+import de.robv.android.xposed.XposedHelpers;
+
+public class AdmobFinder extends Finder {
+    public AdmobFinder(String adsClassName, String adsName, ClassLoader cl, IDoCommandService service) {
+        super(adsClassName, adsName, cl, service);
+    }
+
+    public class AdmobApiHook extends AdsApiHook{
+
+        private AdmobApiHook(String s, String dataName, int posInArgs){
+            super(s, dataName, posInArgs);
+        }
+
+        public AdmobApiHook(String s, int posInArgs){
+            this(s, "data", posInArgs);
+        }
+
+        public Map buildAdsData(String adUnitId){
+            String[] vals = adUnitId.split("/");
+            if(vals.length != 2) return null;
+            Map<String,String> map = new HashMap<>();
+            map.put("client", vals[0]);
+            map.put("slotname", vals[1]);
+            map.put("adType", this.mAdType);
+            return map;
+        }
+    }
+
+    public void hookAdsApi() {
+        registerSSLHook(new SSLOutputStreamHookedCallback() {
+            @Override
+            public void onSSLOutputStreamHooked(HttpParser hp) {
+                if(!hp.getMethod().equals("GET") || !hp.getPath().contains("/mads/gma")) return;
+                String slotname = hp.getUrlParam("slotname");
+                String client = hp.getUrlParam("client");
+                Map<String,String> map = new HashMap<>();
+                map.put("client", client);
+                map.put("slotname", slotname);
+                uploadAdsData(map);
+            }
+        });
+
+
+
+        XposedHelpers.findAndHookMethod("com.google.android.gms.ads.BaseAdView", mAppClassLoader, "setAdUnitId",
+                String.class, new AdmobApiHook("bannerAd", 0));
+
+        XposedHelpers.findAndHookConstructor("com.google.android.gms.ads.AdLoader$Builder", mAppClassLoader,
+                Context.class, String.class, new AdmobApiHook("nativeAd", 1));
+
+
+        XposedHelpers.findAndHookConstructor("com.google.android.gms.ads.rewarded.RewardedAd", mAppClassLoader,
+                Context.class, String.class, new AdmobApiHook("rewardedAd", 1));
+
+        try {
+
+            XposedBridge.hookAllMethods(mAppClassLoader.loadClass("com.google.android.gms.ads.reward.RewardedVideoAd"), "loadAd",
+                    new AdmobApiHook("rewardedAd(legacy)", 0));
+
+            XposedBridge.hookAllMethods(mAppClassLoader.loadClass("import com.google.android.gms.ads.appopen.AppOpenAd"), "load",
+                    new AdmobApiHook("openAd", 1));
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/DefaultFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/DefaultFinder.java
new file mode 100644
index 0000000..af530bf
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/DefaultFinder.java
@@ -0,0 +1,14 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import com.fear1ess.reyunaditool.IDoCommandService;
+
+public class DefaultFinder extends Finder {
+    public DefaultFinder(String adsName, String adsClassName, ClassLoader cl, IDoCommandService service) {
+        super(adsName, adsClassName, cl, service);
+    }
+
+    @Override
+    public void hookAdsApi() {
+        return;
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/FacebookFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/FacebookFinder.java
new file mode 100644
index 0000000..36a6bb3
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/FacebookFinder.java
@@ -0,0 +1,63 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.HttpParser;
+import com.fear1ess.reyunaditool.IDoCommandService;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FacebookFinder extends Finder {
+
+    public FacebookFinder(String adsName, String adsClassName, ClassLoader cl, IDoCommandService service) {
+        super(adsName, adsClassName, cl, service);
+    }
+
+    @Override
+    public void hookAdsApi() {
+        registerSSLHook(new SSLOutputStreamHookedCallback() {
+            @Override
+            public void onSSLOutputStreamHooked(HttpParser hp) {
+                if(!hp.getMethod().equals("POST")) return;
+                if(!hp.getPath().contains("network_ads_common") && (!hp.getPath().contains("/adnw_sync"))) return;
+                Map<String, String> map = new HashMap<>();
+                // PLACEMENT_ID, IDFA, M_BANNER_KEY, PLACEMENT_TYPE, APPNAME, AFP, ASHAS
+                if(hp.getPath().contains("network_ads_common")){
+                    String placementId = hp.getFormBodyParam("PLACEMENT_ID");
+                    String idfa = hp.getFormBodyParam("IDFA");
+                    String afp = hp.getFormBodyParam("AFP");
+                    String ashas = hp.getFormBodyParam("ASHAS");
+                    String mBannerKey = hp.getFormBodyParam("M_BANNER_KEY");
+                    String placementType = hp.getFormBodyParam("PLACEMENT_TYPE");
+                    map.put("PLACEMENT_ID", placementId);
+                    map.put("IDFA", idfa);
+                    map.put("AFP", afp);
+                    map.put("ASHAS", ashas);
+                    map.put("PLACEMENT_TYPE", placementType);
+                    map.put("M_BANNER_KEY", mBannerKey);
+                }else{
+                    String payload = (String) hp.getFormBodyParam("payload");
+                    try {
+                        JSONObject jo = new JSONObject(payload);
+                        JSONObject context = jo.getJSONObject("context");
+                        String placementId = context.getString("PLACEMENT_ID");
+                        String idfa = context.getString("IDFA");
+                        String afp = context.getString("AFP");
+                        String ashas = context.getString("ASHAS");
+                        map.put("PLACEMENT_ID", placementId);
+                        map.put("IDFA", idfa);
+                        map.put("AFP", afp);
+                        map.put("ASHAS", ashas);
+                    } catch (JSONException e) {
+                        e.printStackTrace();
+                    }
+                }
+                uploadAdsData(map);
+            }
+        });
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/Finder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/Finder.java
new file mode 100644
index 0000000..2c30c3f
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/Finder.java
@@ -0,0 +1,273 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.graphics.Path;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.AdsSdkExistsFlag;
+import com.fear1ess.reyunaditool.HookEntry;
+import com.fear1ess.reyunaditool.HttpParser;
+import com.fear1ess.reyunaditool.IDoCommandService;
+import com.fear1ess.reyunaditool.MLog;
+import com.fear1ess.reyunaditool.OperateCmd;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XposedHelpers;
+
+public abstract class Finder {
+    public static SSLOutputStreamHook sslHook = new SSLOutputStreamHook();
+    public static Map<String, Map<String, String>>  adsMap = new HashMap<>();
+    protected String mAdsClassName;
+    protected String mAdsName;
+    protected ClassLoader mAppClassLoader;
+    protected IDoCommandService mDoCommandService;
+    protected List<Map> mRemainAdsDataList = new ArrayList<>();
+    protected volatile boolean isServiceBound = false;
+    public static String TAG = "reyunadihookplugin_adsfinder";
+    private static int adsSdkState = 0;
+    private static int adsDataState = 0;
+
+    public Finder(String adsName,String adsClassName,ClassLoader cl,IDoCommandService service){
+        mAdsClassName = adsClassName;
+        mAdsName = adsName;
+        mAppClassLoader = cl;
+        mDoCommandService = service;
+    }
+
+    static {
+        hookSSLOutputStream(sslHook);
+    }
+
+    public boolean isAdsExisted(){
+        Class<?> cls = null;
+        try{
+            Log.d(TAG, "start find " + mAdsClassName);
+            cls = mAppClassLoader.loadClass(mAdsClassName);
+        } catch (ClassNotFoundException e) {
+            Log.d(TAG, "not find ads: " + mAdsName);
+        } finally {
+            if(cls == null) return false;
+            Log.d(TAG, "find ads: " + mAdsName);
+            updateAdsSdkState(mAdsName);
+            return true;
+        }
+    }
+
+    public static int getAdsSdkState(){
+        return adsSdkState;
+    }
+
+
+    public static int getAdsDataState() {
+        return adsDataState;
+    }
+
+    public static void updateAdsSdkState(String adsName){
+        switch (adsName){
+            case "admob":
+                adsSdkState |= AdsSdkExistsFlag.ADMOB;
+                break;
+            case "unity":
+                adsSdkState |= AdsSdkExistsFlag.UNITY;
+                break;
+            case "vungle":
+                adsSdkState |= AdsSdkExistsFlag.VUNGLE;
+                break;
+            case "facebook":
+                adsSdkState |= AdsSdkExistsFlag.FACEBOOK;
+            case "ironsource":
+                adsSdkState |= AdsSdkExistsFlag.IRONSOURCE;
+            case "pangle":
+                adsSdkState |= AdsSdkExistsFlag.PANGLEMODULE;
+            default: break;
+        }
+    }
+
+    public static void updateAdsDataState(String adsName){
+        switch (adsName){
+            case "admob":
+                adsDataState |= AdsSdkExistsFlag.ADMOB;
+                break;
+            case "unity":
+                adsDataState |= AdsSdkExistsFlag.UNITY;
+                break;
+            case "vungle":
+                adsDataState |= AdsSdkExistsFlag.VUNGLE;
+                break;
+            case "facebook":
+                adsDataState |= AdsSdkExistsFlag.FACEBOOK;
+                break;
+            case "ironsource":
+                adsSdkState |= AdsSdkExistsFlag.IRONSOURCE;
+            case "pangle":
+                adsDataState |= AdsSdkExistsFlag.PANGLEMODULE;
+            default: break;
+        }
+    }
+
+    public void startWork(){
+        if(!isAdsExisted()) return;
+        hookAdsApi();
+    }
+
+    public void registerSSLHook(SSLOutputStreamHookedCallback cb){
+        sslHook.registerSSLOutputStreamCallback(cb);
+    }
+
+    public void hookAdsApi(){
+        return;
+    }
+
+
+    public void uploadRemainAdsData(IDoCommandService service){
+        isServiceBound = true;
+        mDoCommandService = service;
+        for(Map map : mRemainAdsDataList){
+            uploadAdsData(map);
+        }
+    }
+
+    public void uploadAdsData(Map<String,String> map){
+        //ad map to global ads map
+        adsMap.put(mAdsName, map);
+
+
+        if(isServiceBound == false){
+            mRemainAdsDataList.add(map);
+            Log.d(TAG, "uploadAdsData failed, service is not bound" );
+            return;
+        }
+
+        try {
+            JSONObject adsDataJson = new JSONObject();
+            for(Map.Entry<String,String> entry : map.entrySet()){
+                adsDataJson.put(entry.getKey(),entry.getValue());
+            }
+            JSONObject jo2 = new JSONObject();
+            jo2.put(mAdsName, adsDataJson);
+            JSONObject jo3 = new JSONObject();
+            jo2.put("package_name", HookEntry.processName);
+            jo3.put("data",jo2);
+            String uploadData = jo3.toString();
+            Log.d(TAG, "uploadAdsData: " + uploadData);
+            MLog.d("uploadAdsData: " + uploadData);
+            String res = mDoCommandService.doCommand(OperateCmd.UPLOAD_ADSDK_DATA, uploadData);
+
+            updateAdsDataState(mAdsName);
+            FinderUtils.uploadAdsSdkExistsState(mDoCommandService, adsSdkState, adsDataState);
+            if(res.equals("success")){
+                Log.d(TAG, "uploadAdsData success");
+            }
+        } catch (RemoteException | JSONException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    public static void hookSSLOutputStream(XC_MethodHook hook){
+        XposedHelpers.findAndHookMethod("com.android.org.conscrypt.ConscryptFileDescriptorSocket$SSLOutputStream", HookEntry.cl, "write",
+                byte[].class, int.class, int.class, hook);
+    }
+
+    public static class SSLOutputStreamHook extends XC_MethodHook {
+        private List<SSLOutputStreamHookedCallback> mCallbacks = new ArrayList<>();
+
+        public void registerSSLOutputStreamCallback(SSLOutputStreamHookedCallback cb){
+            mCallbacks.add(cb);
+        }
+
+        @Override
+        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+            super.beforeHookedMethod(param);
+            byte[] data = (byte[]) param.args[0];
+            int pos = (int) param.args[1];
+            int len = (int) param.args[2];
+            String payload = new String(data, pos, len);
+            Log.d(TAG, "SSLOutputSteam data: " + payload);
+            HttpParser hp = new HttpParser(payload);
+            for(SSLOutputStreamHookedCallback cb : mCallbacks){
+                cb.onSSLOutputStreamHooked(hp);
+            }
+        }
+    }   JSONObject jo = new JSONObject(Finder.adsMap);
+
+    public interface SSLOutputStreamHookedCallback {
+        void onSSLOutputStreamHooked(HttpParser hp);
+    }
+
+    public class AdsApiHook extends XC_MethodHook {
+        public String mAdType;
+        public String mDataName;
+        public int mPos;
+
+        public AdsApiHook(String s, String dataName, int posInArgs) {
+            super();
+            mAdType = s;
+            mDataName = dataName;
+            mPos = posInArgs;
+        }
+
+        public Map buildAdsData(String data) {
+            Map<String, String> map = new HashMap<>();
+            map.put(mDataName, data);
+            map.put("adType", this.mAdType);
+            return map;
+        }
+
+        public void handleAdUnitId(String adUnitId) {
+            if (adUnitId == null) return;
+            Map map = buildAdsData(adUnitId);
+            if (map == null) return;
+            uploadAdsData(map);
+        }
+
+
+        @Override
+        protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
+            super.beforeHookedMethod(param);
+            String data = (String) param.args[mPos];
+            Log.d(TAG, "find " + mAdsName + " " + mAdType + ", " + mDataName + ": " + data);
+            handleAdUnitId(data);
+        }
+    }
+
+    public String matchQueryValue(String str, String key) {
+        String patternStr = key + "=((.*&)|(.* ))";
+        String matchStr = match(str, patternStr);
+        if(matchStr == null) return null;
+        String value = matchStr.replace(key + "=","").
+                replace("&","").replace(" ","");
+        Log.d(TAG, "matchQueryValue key: " + key + ", value: " + value);
+        return value;
+    }
+
+    public String matchJsonBodyValue(String str, String key) {
+        String patternStr = "\"" + key + "\":" + "((.*,)|(.*\\}))";
+        String matchStr = match(str, patternStr);
+        if(matchStr == null) return null;
+        String value = matchStr.replace("\"" + key + "\":", "")
+                .replace(",", "").replace("}","");
+        Log.d(TAG, "matchJsonBodyValue key: " + key + ", value: " + value);
+        return value;
+    }
+
+    public String match(String str, String patternStr) {
+        Pattern pattern = Pattern.compile(patternStr);
+        Matcher matcher = pattern.matcher(str);
+        if(!matcher.find()) return null;
+        String value = matcher.group(0);
+        return value;
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/FinderUtils.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/FinderUtils.java
new file mode 100644
index 0000000..f8530d7
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/FinderUtils.java
@@ -0,0 +1,146 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.net.VpnManager;
+import android.net.VpnService;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.HookEntry;
+import com.fear1ess.reyunaditool.IDoCommandService;
+import com.fear1ess.reyunaditool.MLog;
+import com.fear1ess.reyunaditool.OperateCmd;
+import com.fear1ess.reyunaditool.RyTag;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static com.fear1ess.reyunaditool.adsfinder.Finder.TAG;
+
+public class FinderUtils {
+    public static Map<String,String> adsInfoMap = new HashMap<>();
+    public static List<Finder> finderArray = new ArrayList<>();
+
+    static{
+        adsInfoMap.put("admob", "com.google.android.gms.ads.MobileAds");
+        adsInfoMap.put("unity", "com.unity3d.ads.UnityAds");
+        adsInfoMap.put("vungle", "com.vungle.warren.Vungle");
+        adsInfoMap.put("facebook", "com.facebook.ads.AudienceNetworkAds");
+        adsInfoMap.put("ironsource", "com.ironsource.mediationsdk.IronSource");
+        adsInfoMap.put("pangle", "com.bytedance.sdk.openadsdk.TTAdConfig");       //海外穿山甲
+    }
+
+    public static Finder createFinder(String adsName, String adsClsName, ClassLoader cl, IDoCommandService service){
+        switch(adsName){
+            case "admob":
+                return new AdmobFinder(adsName, adsClsName, cl, service);
+            case "unity":
+                return new UnityFinder(adsName, adsClsName, cl, service);
+            case "vungle":
+                return new VungleFinder(adsName, adsClsName, cl, service);
+            case "facebook":
+                return new FacebookFinder(adsName, adsClsName, cl, service);
+            case "ironsource":
+                return new IronSourceFinder(adsName, adsClsName, cl, service);
+            case "pangle":
+                MLog.d("createFinder: PangLeFinder");
+                return new PangLeFinder(adsName, adsClsName, cl, service);
+            default:
+                return new DefaultFinder(adsName, adsClsName, cl, service);
+        }
+    }
+
+    public static void uploadAdsSdkExistsState(IDoCommandService service, int sdkState, int dataState){
+        if(service == null){
+            Log.d(RyTag.TAG, "uploadAdsData failed, service is not bound" );
+            return;
+        }
+        try {
+            JSONObject jo = new JSONObject();
+            jo.put("ads_sdk_state", sdkState);
+            jo.put("ads_data_state", dataState);
+            jo.put("package_name", HookEntry.processName);
+            JSONObject jo2 = new JSONObject();
+            jo2.put("data", jo);
+            String uploadData = jo2.toString();
+            Log.d(RyTag.TAG, "uploadAdsExistsStateData: " + uploadData);
+            String res = service.doCommand(OperateCmd.UPLOAD_ADSDK_EXISTS_STATE, uploadData);
+            if(res.equals("success")){
+                Log.d(RyTag.TAG, "uploadAdsExistsStateData success");
+            }
+        } catch (JSONException | RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void notifyServiceBound(IDoCommandService service){
+        uploadAdsSdkExistsState(service, Finder.getAdsSdkState(), Finder.getAdsDataState());
+        for(Finder finder : finderArray){
+            finder.uploadRemainAdsData(service);
+        }
+
+        //do upload...
+        ExecutorService es = Executors.newSingleThreadExecutor();
+        es.execute(new UploadDataProceduce(service));
+        es.shutdown();
+    }
+
+    public static void doWork(ClassLoader cl, IDoCommandService service){
+        for(Map.Entry<String,String> entry : adsInfoMap.entrySet()){
+            Finder finder = createFinder(entry.getKey(), entry.getValue(), cl, service);
+            finderArray.add(finder);
+            finder.startWork();
+        }
+
+    }
+
+    public static class UploadDataProceduce implements Runnable {
+
+        IDoCommandService hdService;
+
+        public UploadDataProceduce(IDoCommandService service){
+            hdService = service;
+        }
+
+        @Override
+        public void run(){
+
+            // wait for some time
+            try {
+                Thread.sleep(50*1000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+            String curPkg = null;
+            try {
+                curPkg = hdService.doCommand(OperateCmd.QUERY_CURRENT_PKGNAME, null);
+                Log.d(RyTag.TAG, "currentPkg: " + curPkg);
+                Log.d(RyTag.TAG, "processName: " + HookEntry.processName);
+                //    if(!HookEntry.processName.equals(curPkg)) return;
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+
+            //upload ads data
+            try {
+                JSONObject jo = new JSONObject(Finder.adsMap);
+                jo.put("app_id", HookEntry.processName);
+                String data = jo.toString();
+                Log.d(RyTag.TAG, "upload ads data: " + data);
+                MLog.d( "upload ads data: " + data);
+                if(!HookEntry.processName.equals(curPkg)) return;
+                hdService.doCommand(OperateCmd.UPLOAD_ADSDK_DATA, data);
+              //  hdService.doCommand(OperateCmd.SHUTDOWN_APP, null);
+            } catch (JSONException | RemoteException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/IronSourceFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/IronSourceFinder.java
new file mode 100644
index 0000000..d3ffeb8
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/IronSourceFinder.java
@@ -0,0 +1,30 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import com.fear1ess.reyunaditool.HttpParser;
+import com.fear1ess.reyunaditool.IDoCommandService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class IronSourceFinder extends Finder {
+    public IronSourceFinder(String adsClassName, String adsName, ClassLoader cl, IDoCommandService service) {
+        super(adsClassName, adsName, cl, service);
+    }
+
+    @Override
+    public void hookAdsApi() {
+        registerSSLHook(new SSLOutputStreamHookedCallback() {
+            @Override
+            public void onSSLOutputStreamHooked(HttpParser hp) {
+                if(!hp.getMethod().equals("GET")) return;
+                if(!hp.getPath().contains("/gateway/sdk/request")) return;
+                String applicationKey = hp.getUrlParam("applicationKey");
+                if(applicationKey != null) {
+                    Map<String,String> map = new HashMap<>();
+                    map.put("applicationKey", applicationKey);
+                    uploadAdsData(map);
+                }
+            }
+        });
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/PangLeFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/PangLeFinder.java
new file mode 100644
index 0000000..b92820e
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/PangLeFinder.java
@@ -0,0 +1,227 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.os.RemoteException;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.HookEntry;
+import com.fear1ess.reyunaditool.IDoCommandService;
+import com.fear1ess.reyunaditool.MLog;
+import com.fear1ess.reyunaditool.OperateCmd;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XposedHelpers;
+import de.robv.android.xposed.callbacks.XC_LoadPackage;
+
+public class PangLeFinder extends Finder  {
+    private static String m_appID="";
+    private static String m_temp="";
+    private static boolean m_flag=false;
+    public PangLeFinder(String adsName, String adsClassName, ClassLoader cl, IDoCommandService service) {
+        super(adsName, adsClassName, cl, service);
+    }
+    public void hookAdsApi() {
+        hook_doFinal(mAppClassLoader);
+        hook_JSON_Put(mAppClassLoader);
+    }
+    public  void hook_doFinal(ClassLoader classLoader){
+        XposedHelpers.findAndHookMethod("javax.crypto.Cipher",
+                classLoader, "doFinal",byte[].class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        try{
+                            String content= new String((byte[]) param.args[0]);
+                            try{
+                                JSONObject jsonObject=new JSONObject(content);
+                                JSONArray adslots= (JSONArray) jsonObject.get("adslots");
+//                                JSONObject item= (JSONObject) adslots.get(0);
+                                if( adslots!=null){
+//                                    MLog.d("打印原内容:"+content);
+                                    if((m_temp.hashCode()==content.hashCode())){
+                                        return;
+                                    }
+                                    m_temp=content;
+                                    m_flag=true;
+                                }
+                            }catch (Exception e){
+
+                            }
+//                            if(content.contains("\"adslots\":[{\"id\":\"")){
+//                                if((m_temp.hashCode()==content.hashCode())){
+//                                   return;
+//                                }
+//                                m_temp=content;
+//                                m_flag=true;
+////                                JSONObject jsonObject=new JSONObject(content);
+////                                String ad_sdk_version=(String) jsonObject.get("ad_sdk_version");
+////                                JSONObject app= (JSONObject) jsonObject.get("app");
+////                                String appid= (String) app.get("appid");
+////                                String package_name= (String) app.get("package_name");
+////                                String version_code= (String) app.get("version_code");
+////                                String version= (String) app.get("version");
+////
+////                                JSONArray adslots= (JSONArray) jsonObject.get("adslots");
+//////                                MLog.d("adslots-> "+adslots.toString());
+////                                JSONArray my_Adslots=new JSONArray();
+////                                for (int i = 0; i < adslots.length(); i++) {
+////                                    JSONObject item= (JSONObject) adslots.get(i);
+////                                    JSONObject object= new JSONObject();
+////                                    object.put("id",item.get("id"));
+////                                    object.put("adtype",item.get("adtype"));
+////                                    my_Adslots.put(object);
+////                                }
+////
+////                                Map<String,String> map = new HashMap<>();
+////                                map.put("appid", appid);
+////                                map.put("ad_sdk_version", ad_sdk_version);
+////                                map.put("package_name", package_name);
+////                                map.put("version_code", version_code);
+////                                map.put("version", version);
+////                                map.put("adslots", my_Adslots.toString());
+////                                MLog.d("穿山甲上传数据: "+map.toString());
+////                                uploadAdsData(map);
+//                            }
+                        }catch (Exception e){
+                            MLog.d(e.toString());
+                        }
+
+
+                    }
+                }
+        );
+    }
+
+    public  void hook_JSON_Put(ClassLoader classLoader){
+        XposedHelpers.findAndHookMethod(JSONObject.class, "put",
+                String.class, int.class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                       String key= (String) param.args[0];
+
+                       if(key.equals("cypher")){
+                           if(!m_flag){
+                              return;
+                           }
+                           m_flag=false;
+//                           MLog.d("key= "+param.args[0]+"  "+param.args[1]);
+                           JSONObject jsonObject=new JSONObject(m_temp);
+                           String ad_sdk_version=(String) jsonObject.get("ad_sdk_version");
+                           JSONObject app= (JSONObject) jsonObject.get("app");
+                           String appid= (String) app.get("appid");
+                           String package_name= (String) app.get("package_name");
+                           String version_code= (String) app.get("version_code");
+                           String version= (String) app.get("version");
+
+                           JSONArray adslots= (JSONArray) jsonObject.get("adslots");
+//                                MLog.d("adslots-> "+adslots.toString());
+                           JSONArray my_Adslots=new JSONArray();
+                           for (int i = 0; i < adslots.length(); i++) {
+                               JSONObject item= (JSONObject) adslots.get(i);
+                               JSONObject object= new JSONObject();
+                               object.put("id",item.get("id"));
+                               object.put("adtype",item.get("adtype"));
+                               my_Adslots.put(object);
+                           }
+
+                           Map<String,String> map = new HashMap<>();
+                           map.put("appid", appid);
+                           map.put("ad_sdk_version", ad_sdk_version);
+                           map.put("package_name", package_name);
+                           map.put("version_code", version_code);
+                           map.put("version", version);
+                           map.put("adslots", my_Adslots.toString());
+                           map.put("cypher", String.valueOf(param.args[1]));
+                           MLog.d("穿山甲上传数据: "+map.toString());
+                           uploadAdsData(map);
+
+                       }
+                    }
+                });
+
+    }
+
+
+    public void uploadAdsData(Map<String,String> map){
+        //ad map to global ads map
+        adsMap.put(mAdsName, map);
+
+
+        if(isServiceBound == false){
+            mRemainAdsDataList.add(map);
+            Log.d(TAG, "uploadAdsData failed, service is not bound" );
+            return;
+        }
+
+        try {
+            JSONObject adsDataJson = new JSONObject();
+            for(Map.Entry<String,String> entry : map.entrySet()){
+                adsDataJson.put(entry.getKey(),entry.getValue());
+            }
+            JSONObject jo2 = new JSONObject();
+            jo2.put(mAdsName, adsDataJson);
+//            JSONObject jo3 = new JSONObject();
+            jo2.put("app_id", HookEntry.processName+System.currentTimeMillis());
+//            jo3.put("data",jo2);
+            String uploadData = jo2.toString();
+            Log.d(TAG, "uploadAdsData: " + uploadData);
+            MLog.d("uploadAdsData: " + uploadData);
+            String res = mDoCommandService.doCommand(OperateCmd.UPLOAD_ADSDK_DATA, uploadData);
+
+            updateAdsDataState(mAdsName);
+            FinderUtils.uploadAdsSdkExistsState(mDoCommandService, 32, 32);
+            if(res.equals("success")){
+                Log.d(TAG, "uploadAdsData success");
+            }
+        } catch (RemoteException | JSONException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    private void hook_AppID(ClassLoader classLoader){
+        XposedHelpers.findAndHookMethod("com.bytedance.sdk.openadsdk.TTAdConfig",
+                classLoader, "setAppId",String.class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        m_appID= (String) param.args[0];
+                        MLog.d( "beforeHookedMethod: 穿山甲APPID: "+m_appID);
+                    }
+                }
+        );
+    }
+
+
+    private void hook_SlotID(ClassLoader classLoader){
+        XposedHelpers.findAndHookMethod("com.bytedance.sdk.openadsdk.AdSlot$Builder",
+                classLoader, "setCodeId",String.class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        String slotID= (String) param.args[0];
+                        Map<String,String> map = new HashMap<>();
+                        if(TextUtils.isEmpty(m_appID)){
+                            m_appID="error";
+                        }
+                        map.put("appID", m_appID);
+                        map.put("slotID", slotID);
+                        MLog.d( "beforeHookedMethod: 上传的数据: "+map.toString());
+                        uploadAdsData(map);
+                    }
+                }
+        );
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/UnityFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/UnityFinder.java
new file mode 100644
index 0000000..59048e4
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/UnityFinder.java
@@ -0,0 +1,121 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.HttpParser;
+import com.fear1ess.reyunaditool.IDoCommandService;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XposedBridge;
+import de.robv.android.xposed.XposedHelpers;
+
+public class UnityFinder extends Finder {
+    public UnityFinder(String adsName, String adsClassName, ClassLoader cl, IDoCommandService service) {
+        super(adsName, adsClassName, cl, service);
+    }
+
+    @Override
+    public void hookAdsApi() {
+        registerSSLHook(new SSLOutputStreamHookedCallback() {
+            @Override
+            public void onSSLOutputStreamHooked(HttpParser hp) {
+                if(!hp.getMethod().equals("POST") || !hp.getPath().contains("/v6/games")) return;
+                Log.d(TAG, "onSSLOutputStreamHooked: unity0");
+                String unityGameId = match(hp.getPath(), "v6/games/.*/requests").replace("v6/games/","")
+                        .replace("/requests","");
+                if(unityGameId == null) return;
+                Log.d(TAG, "onSSLOutputStreamHooked: unity1");
+                JSONObject jo = hp.getJsonBody();
+                String gameSessionId = null;
+                try {
+                    gameSessionId = jo.getString("gameSessionId");
+                    Log.d(TAG, "onSSLOutputStreamHooked: unity2");
+                    String projectId = jo.getString("projectId");
+                    String token = jo.getString("token");
+                 //   if(gameSessionId == null || projectId == null || token == null) return;
+                    Map<String, String> map = new HashMap<>();
+                    map.put("gameSessionId", gameSessionId);
+                    map.put("token", token);
+                    map.put("projectId", projectId);
+                    map.put("unityGameId", unityGameId);
+                    uploadAdsData(map);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+        /*
+        try {
+            XposedBridge.hookAllMethods(mAppClassLoader.loadClass("com.unity3d.ads.UnityAds"), "initialize",
+                    new AdsApiHook("AD", "unityGameId", 1));
+
+            XposedHelpers.findAndHookMethod("com.unity3d.services.core.request.WebRequest", mAppClassLoader,
+                    "makeRequest", new UnityNetWorkHook("AD", "unityParam", 0));
+
+            XposedHelpers.findAndHookMethod("java.net.SocketOutputStream", mAppClassLoader, "write",
+                    byte[].class, int.class, int.class, new XC_MethodHook() {
+                        @Override
+                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                            super.beforeHookedMethod(param);
+                            Log.d(TAG, "socketos hook success!!!!");
+                         //   String data = new String((byte[])param.args[0]);
+                         //   Log.d(TAG, "SocketOutput data: " + data);
+                        }
+                    });
+
+            XposedHelpers.findAndHookMethod("sun.nio.cs.StreamEncoder", mAppClassLoader, "write",
+                    String.class, int.class, int.class, new XC_MethodHook() {
+                        @Override
+                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                            super.beforeHookedMethod(param);
+                            Log.d(TAG, "streamencoder hook success!!!!");
+                            //   String data = new String((byte[])param.args[0]);
+                                 Log.d(TAG, "streamencoder data: " + param.args[0]);
+                        }
+                    });
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }*/
+    }
+
+    public class UnityNetWorkHook extends AdsApiHook{
+
+        public UnityNetWorkHook(String s, String dataName, int posInArgs) {
+            super(s, dataName, posInArgs);
+        }
+
+        @Override
+        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+            Object o = param.thisObject;
+            URL url = (URL) XposedHelpers.getObjectField(o, "_url");
+            String urlStr = url.toString();
+            Log.d(TAG, "urlStr: " + urlStr);
+            Pattern pattern = Pattern.compile("v6/games/.*/requests");
+            Matcher matcher = pattern.matcher(urlStr);
+            if(!matcher.find()) return;
+            Log.d(TAG, "1");
+            String body = (String) XposedHelpers.getObjectField(o, "_body");
+            JSONObject jo = new JSONObject(body);
+            Log.d(TAG, "2");
+            if(!jo.has("gameSessionId") || !jo.has("token") || !jo.has("projectId")) return;
+            Log.d(TAG, "3");
+            Map<String,String> map = new HashMap<>();
+            map.put("gameSessionId", jo.getString("gameSessionId"));
+            map.put("token", jo.getString("token"));
+            map.put("projectId", jo.getString("projectId"));
+            String unityGameId = matcher.group(0).replace("v6/games/","").replace("/requests","");
+            map.put("unityGameId", unityGameId);
+            uploadAdsData(map);
+        }
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/VungleFinder.java a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/VungleFinder.java
new file mode 100644
index 0000000..3e41d28
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/adsfinder/VungleFinder.java
@@ -0,0 +1,67 @@
+package com.fear1ess.reyunaditool.adsfinder;
+
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.HttpParser;
+import com.fear1ess.reyunaditool.IDoCommandService;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XposedBridge;
+import de.robv.android.xposed.XposedHelpers;
+
+public class VungleFinder extends Finder{
+    public VungleFinder(String adsName, String adsClassName, ClassLoader cl, IDoCommandService service) {
+        super(adsName, adsClassName, cl, service);
+    }
+
+    @Override
+    public void hookAdsApi() {
+        registerSSLHook(new SSLOutputStreamHookedCallback() {
+            @Override
+            public void onSSLOutputStreamHooked(HttpParser hp) {
+                if(!hp.getMethod().equals("POST") || !hp.getPath().contains("api/v5/ads")) return;
+                JSONObject jo = hp.getJsonBody();
+                try {
+                    JSONObject app = jo.getJSONObject("app");
+                    String id = app.getString("id");
+                    JSONObject request = jo.getJSONObject("request");
+                    JSONArray pArr = request.getJSONArray("placements");
+                    String placement = null;
+                    for(int i = 0;i < pArr.length(); ++i){
+                        placement = pArr.getString(i);
+                    }
+                    Map<String, String> map = new HashMap<>();
+                    map.put("id", id);
+                    map.put("placement", placement);
+                    uploadAdsData(map);
+                } catch (JSONException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+        /*
+        try {
+            XposedBridge.hookAllMethods(mAppClassLoader.loadClass("com.vungle.warren.network.VungleApiImpl"), "createNewPostCall",
+                    new XC_MethodHook() {
+                        @Override
+                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                            super.beforeHookedMethod(param);
+                            Log.d(TAG, "vungle ads ua: " + param.args[0]);
+                            Log.d(TAG, "vungle ads path: " + param.args[1]);
+                            Log.d(TAG, "vungle ads body: " + XposedHelpers.callMethod(param.args[2],"toString"));
+                        }
+                    });
+
+
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }*/
+    }
+}
diff --git b/app/src/main/java/com/fear1ess/reyunaditool/pangle/pangleModule.java a/app/src/main/java/com/fear1ess/reyunaditool/pangle/pangleModule.java
new file mode 100644
index 0000000..8dc4952
--- /dev/null
+++ a/app/src/main/java/com/fear1ess/reyunaditool/pangle/pangleModule.java
@@ -0,0 +1,110 @@
+package com.fear1ess.reyunaditool.pangle;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.fear1ess.reyunaditool.MLog;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.robv.android.xposed.XC_MethodHook;
+import de.robv.android.xposed.XposedHelpers;
+import de.robv.android.xposed.callbacks.XC_LoadPackage;
+
+import static com.fear1ess.reyunaditool.adsfinder.Finder.TAG;
+//--------------------------------------------------测试代码
+public class pangleModule {
+    private static String m_appID="";
+    public static void hook_AppID(XC_LoadPackage.LoadPackageParam lpparam){
+
+        XposedHelpers.findAndHookMethod("com.bytedance.sdk.openadsdk.TTAdConfig",
+                lpparam.classLoader, "setAppId",String.class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        m_appID= (String) param.args[0];
+                        MLog.d( "测试:beforeHookedMethod: "+m_appID);
+                    }
+                }
+        );
+    }
+
+
+    public static void hook_SlotID(XC_LoadPackage.LoadPackageParam lpparam){
+        XposedHelpers.findAndHookMethod("com.bytedance.sdk.openadsdk.AdSlot$Builder",
+                lpparam.classLoader, "setCodeId",String.class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        String slotID= (String) param.args[0];
+                        Map<String,String> map = new HashMap<>();
+                        if(TextUtils.isEmpty(m_appID)){
+                            m_appID=lpparam.packageName;
+                        }
+                        map.put("appID", m_appID);
+                        map.put("slotID", slotID);
+                        MLog.d("测试:beforeHookedMethod: "+map.toString());
+                    }
+                }
+        );
+    }
+
+
+    public static void hook_doFinal(XC_LoadPackage.LoadPackageParam lpparam){
+        XposedHelpers.findAndHookMethod("javax.crypto.Cipher",
+                lpparam.classLoader, "doFinal",byte[].class,
+                new XC_MethodHook() {
+                    @Override
+                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
+                        super.beforeHookedMethod(param);
+                        try{
+                            String content= new String((byte[]) param.args[0]);
+                            if(content.contains("\"adslots\":[{\"id\":\"")){
+//                                MLog.d(content);
+                                JSONObject jsonObject=new JSONObject(content);
+                                String ad_sdk_version=(String) jsonObject.get("ad_sdk_version");
+                                JSONObject app= (JSONObject) jsonObject.get("app");
+                                String appid= (String) app.get("appid");
+                                String package_name= (String) app.get("package_name");
+                                String version_code= (String) app.get("version_code");
+                                String version= (String) app.get("version");
+
+                                JSONArray adslots= (JSONArray) jsonObject.get("adslots");
+//                                MLog.d("adslots-> "+adslots.toString());
+                                JSONArray my_Adslots=new JSONArray();
+                                for (int i = 0; i < adslots.length(); i++) {
+                                    JSONObject item= (JSONObject) adslots.get(i);
+                                    JSONObject object= new JSONObject();
+                                    object.put("id",item.get("id"));
+                                    object.put("adtype",item.get("adtype"));
+                                    my_Adslots.put(object);
+                                }
+
+                                Map<String,String> map = new HashMap<>();
+                                if(TextUtils.isEmpty(m_appID)){
+                                    m_appID=lpparam.packageName;
+                                }
+                                map.put("appID", appid);
+                                map.put("ad_sdk_version", ad_sdk_version);
+                                map.put("package_name", package_name);
+                                map.put("version_code", version_code);
+                                map.put("version", version);
+                                map.put("slotID", my_Adslots.toString());
+                                MLog.d("测试:beforeHookedMethod: "+map.toString());
+                            }
+                        }catch (Exception e){
+                           MLog.d(e.toString());
+                        }
+
+
+                    }
+                }
+        );
+    }
+}
diff --git b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="85.84757"
+                android:endY="92.4963"
+                android:startX="42.9492"
+                android:startY="49.59793"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+</vector>
\ No newline at end of file
diff --git b/app/src/main/res/drawable/ic_launcher_background.xml a/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ a/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#3DDC84"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>
diff --git b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git b/app/src/main/res/mipmap-hdpi/ic_launcher.png a/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..a571e60
Binary files /dev/null and a/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..61da551
Binary files /dev/null and a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git b/app/src/main/res/mipmap-mdpi/ic_launcher.png a/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c41dd28
Binary files /dev/null and a/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..db5080a
Binary files /dev/null and a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git b/app/src/main/res/mipmap-xhdpi/ic_launcher.png a/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6dba46d
Binary files /dev/null and a/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..da31a87
Binary files /dev/null and a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..15ac681
Binary files /dev/null and a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..b216f2d
Binary files /dev/null and a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..f25a419
Binary files /dev/null and a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..e96783c
Binary files /dev/null and a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git b/app/src/main/res/values-night/themes.xml a/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..5c04abb
--- /dev/null
+++ a/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Theme.ReyunAdiHookPlugin" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/purple_200</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/black</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/teal_200</item>
+        <item name="colorSecondaryVariant">@color/teal_200</item>
+        <item name="colorOnSecondary">@color/black</item>
+        <!-- Status bar color. -->
+        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
+        <!-- Customize your theme here. -->
+    </style>
+</resources>
\ No newline at end of file
diff --git b/app/src/main/res/values/colors.xml a/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ a/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="purple_200">#FFBB86FC</color>
+    <color name="purple_500">#FF6200EE</color>
+    <color name="purple_700">#FF3700B3</color>
+    <color name="teal_200">#FF03DAC5</color>
+    <color name="teal_700">#FF018786</color>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+</resources>
\ No newline at end of file
diff --git b/app/src/main/res/values/strings.xml a/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..059a5de
--- /dev/null
+++ a/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">ReyunAdiHookPlugin</string>
+</resources>
\ No newline at end of file
diff --git b/app/src/main/res/values/themes.xml a/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..622a250
--- /dev/null
+++ a/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Theme.ReyunAdiHookPlugin" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+        <!-- Primary brand color. -->
+        <item name="colorPrimary">@color/purple_500</item>
+        <item name="colorPrimaryVariant">@color/purple_700</item>
+        <item name="colorOnPrimary">@color/white</item>
+        <!-- Secondary brand color. -->
+        <item name="colorSecondary">@color/teal_200</item>
+        <item name="colorSecondaryVariant">@color/teal_700</item>
+        <item name="colorOnSecondary">@color/black</item>
+        <!-- Status bar color. -->
+        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
+        <!-- Customize your theme here. -->
+    </style>
+</resources>
\ No newline at end of file
diff --git b/app/src/test/java/com/fear1ess/reyunaditool/ExampleUnitTest.java a/app/src/test/java/com/fear1ess/reyunaditool/ExampleUnitTest.java
new file mode 100644
index 0000000..2c8dca2
--- /dev/null
+++ a/app/src/test/java/com/fear1ess/reyunaditool/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.fear1ess.reyunaditool;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git b/build.gradle a/build.gradle
new file mode 100644
index 0000000..38aef93
--- /dev/null
+++ a/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.6.0'
+
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
\ No newline at end of file
diff --git b/gradle.properties a/gradle.properties
new file mode 100644
index 0000000..52f5917
--- /dev/null
+++ a/gradle.properties
@@ -0,0 +1,19 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
\ No newline at end of file
diff --git b/gradle/wrapper/gradle-wrapper.jar a/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and a/gradle/wrapper/gradle-wrapper.jar differ
diff --git b/gradle/wrapper/gradle-wrapper.properties a/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..8bb258a
--- /dev/null
+++ a/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Jul 08 14:50:33 CST 2021
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
diff --git b/gradlew a/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ a/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git b/gradlew.bat a/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ a/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git b/settings.gradle a/settings.gradle
new file mode 100644
index 0000000..7b353a4
--- /dev/null
+++ a/settings.gradle
@@ -0,0 +1,2 @@
+include ':app'
+rootProject.name = "ReyunAdiHookPlugin"
\ No newline at end of file