release 1.0

This commit is contained in:
Dr-TSNG 2021-03-27 14:38:32 +08:00
commit dd09be95ab
19 changed files with 115 additions and 100 deletions

View file

@ -1,8 +1,16 @@
# Hide My Applist
An android app using loopholes to detect specific package names like Magisk and Edxposed Manager.
Also works as an xposed module to reject/hide other apps from detecting some packages.
## About this module
Although "It is incorrect to detect specific app's installation", yet not every app using root provides random packagename support.
In this case, detected apps that use root (such as Fake Location and Storage Isolation) is equal to detected root itself.
At the same time, some "smart" apps use various loopholes to acquire your applist, so that it can draw a persona for you.
This module provides some methods to test whether you have already hided your applist nicely.
Also, it can work as an Xposed module to hide some apps or reject applist requests to protect your privacy.
Todo: xposed module isn't finished
## 关于该模块
虽然“检测安装的应用是不正确的做法”,而且很蠢,但是并不是所有的插件类应用都提供了随机包名支持。在这种情况下,检测到安装了root类应用(如Fake Location、存储重定向)与检测到了root本身区别不大。(会使用检测手段的app可不会认为你是在“我就蹭蹭不进去”)
与此同时,部分“不安分”的app会使用各种漏洞绕过系统权限来获取你的应用列表,从而对你建立用户画像。(如陈叔叔将安装了V2Ray的用户分为一类)
该模块提供了一些检测方式用于测试您是否成功的隐藏了带有root印记的包名,如Magisk/Edxposed Manager。
同时可作为Xposed模块用于隐藏应用列表或特定应用,保护你的隐私。
一个利用系统漏洞获取应用列表的app,可以用来检测特定包名,如Magisk/Edxposed Manager
同时可作为xposed模块用于隐藏应用列表或特定应用
## TODO
+ Add native detection

View file

@ -12,8 +12,8 @@ android {
applicationId "com.tsng.hidemyapplist"
minSdkVersion 26
targetSdkVersion 30
versionCode 5
versionName "0.5"
versionCode 6
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@ -31,16 +31,14 @@ android {
}
dependencies {
implementation 'com.github.medyo:android-about-page:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'org.jetbrains:annotations:15.0'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.navigation:navigation-fragment:2.3.4'
implementation 'androidx.navigation:navigation-ui:2.3.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0'
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.4'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.4'
implementation 'com.google.android.material:material:1.3.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'

View file

@ -1,26 +0,0 @@
package com.tsng.hidemyapplist;
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.tsng.hidemyapplist", appContext.getPackageName());
}
}

View file

@ -1,5 +1,10 @@
package com.tsng.hidemyapplist;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.util.Log;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
@ -10,11 +15,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.util.Log;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XSharedPreferences;

View file

@ -2,13 +2,13 @@ package com.tsng.hidemyapplist;
import android.os.Bundle;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.NavigationUI;
import com.google.android.material.bottomnavigation.BottomNavigationView;
public class MainActivity extends AppCompatActivity {
@Override

View file

@ -4,7 +4,9 @@ import android.content.pm.ApplicationInfo
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.*
import androidx.preference.ListPreference
import androidx.preference.PreferenceFragmentCompat
import kotlin.collections.set
class ScopeManageActivity : AppCompatActivity() {

View file

@ -1,7 +1,5 @@
package com.tsng.hidemyapplist;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@ -11,6 +9,8 @@ import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.File;

View file

@ -1,20 +0,0 @@
package com.tsng.hidemyapplist.ui.about;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import com.tsng.hidemyapplist.R;
public class AboutFragment extends Fragment {
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_about, container, false);
return root;
}
}

View file

@ -0,0 +1,37 @@
package com.tsng.hidemyapplist.ui.about
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tsng.hidemyapplist.R
import mehdi.sakout.aboutpage.AboutPage
import mehdi.sakout.aboutpage.Element
class AboutFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return AboutPage(activity)
.setDescription(getString(R.string.about_my_description))
.addItem(Element().apply {
title = "Version " + requireContext().packageManager.getPackageInfo(requireContext().packageName, 0).versionName
iconDrawable = R.drawable.ic_baseline_language_24
})
.addItem(Element().apply {
title = getString(R.string.about_my_how_to_use_title)
iconDrawable = R.drawable.ic_baseline_help_24
setOnClickListener {
MaterialAlertDialogBuilder(requireContext())
.setTitle(title)
.setMessage(getString(R.string.about_my_how_to_use_message))
.setPositiveButton(getString(R.string.accept), null)
.show()
}
})
.addWebsite("http://www.coolapk.com/u/1911298", getString(R.string.about_my_author))
.addGitHub("Dr-TSNG/Hide-My-Applist", getString(R.string.about_my_project_address))
.addItem(Element())
.create()
}
}

View file

@ -2,7 +2,6 @@ package com.tsng.hidemyapplist.ui.xposed;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
@ -12,7 +11,6 @@ import android.widget.Button;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/>
</vector>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.about.AboutFragment">
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -19,6 +19,5 @@
<fragment
android:id="@+id/navigation_about"
android:name="com.tsng.hidemyapplist.ui.about.AboutFragment"
android:label="@string/title_about"
tools:layout="@layout/fragment_about" />
android:label="@string/title_about"/>
</navigation>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_my_description">
关于该模块\n虽然“检测安装的应用是不正确的做法”,而且很蠢,但是并不是所有的插件类应用都提供了随机包名支持。在这种情况下,检测到安装了root类应用(如Fake Location、存储重定向)与检测到了root本身区别不大。(会使用检测手段的app可不会认为你是在“我就蹭蹭不进去”)\n与此同时,部分“不安分”的app会使用各种漏洞绕过系统权限来获取你的应用列表,从而对你建立用户画像。(如陈叔叔将安装了V2Ray的用户分为一类)\n该模块提供了一些检测方式用于测试您是否成功的隐藏了带有root印记的包名,如Magisk/Edxposed Manager。\n同时可作为Xposed模块用于隐藏应用列表或特定应用,保护你的隐私。
</string>
<string name="about_my_how_to_use_title">如何使用该模块</string>
<string name="about_my_how_to_use_message">
首先创建一个模板,其次在选择生效应用里对目标应用启用模板,然后重启目标应用,完成。\n如何测试隐藏是否成功\n对本模块自身启用一个模板,之后激活“Hook模块自身”按钮,重启app,开始检测。\n几种隐藏方式的区别\n正常app读取应用列表使用API request,“不安分”的app会使用其他几种方式(相当于漏洞)进行检测。不过请注意,全局模式(禁止读取应用列表)下禁止intent query可能会影响分享、启动浏览器等功能。\n目前已知的bug\nEdXposed YAHFA后端无法进行datafile detection隐藏(测试版本:4683),请更换Sandhook后端或LSPosed。
</string>
<string name="about_my_project_address">项目地址</string>
<string name="about_my_author">作者:Dr-TSNG (酷安)</string>
</resources>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="about_my_description">
About this module\nAlthough "It is incorrect to detect specific app's installation", yet not every app using root provides random packagename support. In this case, detected apps that use root (such as Fake Location and Storage Isolation) is equal to detected root itself.\nAt the same time, some "smart" apps use various loopholes to acquire your applist, so that it can draw a persona for you.\nThis module provides some methods to test whether you have already hided your applist nicely.\nAlso, it can work as an Xposed module to hide some apps or reject applist requests to protect your privacy.
</string>
<string name="about_my_how_to_use_title">How to use this module</string>
<string name="about_my_how_to_use_message">
First create a template, then apply the template in "Select Effective Apps", and restart target apps, OK.\nHow to confirm whether hide is successful\nApply a template to the module itself, then activate "Hook Self" button, and restart the app, start detection.\nDifferences between hide methods\nNormal apps use API request to acquire applist, but "bad" apps will use other methods (loopholes) to detect it. Attention, under global mode (Reject applist requests) if hide "intent query" there may be some problems with share, start browser, etc.\nKnown bugs\nHide datafile detection does not work using EdXposed YAHFA (tested version: 4683). Please switch to Sandhook or LSPosed instead.
</string>
<string name="about_my_project_address">Project address</string>
<string name="about_my_author">Author: Dr-TSNG (CoolMarket)</string>
</resources>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen>
</PreferenceScreen>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen>
</PreferenceScreen>

View file

@ -1,17 +0,0 @@
package com.tsng.hidemyapplist;
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);
}
}