那些年Android黑科技③:干大事不择手段
2019獨角獸企業重金招聘Python工程師標準>>>
?“我在發抖么?
你開什么玩笑。我只是在跳愉快的尬舞。
暗影是不會向邪惡勢力低頭的。 萬歲(≧▽≦)/!!”
-- 來自暗世界android工程師
前言:
本篇是本系列的最后一個篇章。其實這些活兒也不全是在干壞事用。我們的重點不應該放在那某個技術點上。應該從中舉一反三的思考。在好的一方面把學到的技術落到實處。比如往下面會講到的往桌面添加快捷方式,你可以選擇結合時下最火的插件化技術搭配添加快捷方式,實現一個無需安裝app就完整的擁有啟動圖標和應用生命周期的附屬app。用戶喜歡的情況下,這不挺好的嗎?畢竟也是一把雙刃劍。
這個世界上手機有三大系統,蘋果、 安卓、 中國安卓 。本篇強烈呼吁大家不要去做哪些違反用戶體驗的黑科技功能,研究研究玩玩就好了啦。全當增長技術,在真實的項目開發中盡量能不用就不要用得好。道理大家都懂的。
目錄
那些年Android黑科技①:只要活著,就有希望
- android應用內執行shell
- 雙進程保活aidl版
- 雙進程保活jni版
- 保活JobService版
那些年Android黑科技②:欺騙的藝術
- hook技術
- 欺騙系統之偷梁換柱
那些年Android黑科技③:干大事不擇手段
- 應用卸載反饋
- Home鍵監聽
- 桌面添加快捷方式
- 無法卸載app(DevicePolicManager)
- 無網絡權限偷偷上傳數據
應用卸載反饋
早在國內某app上有看到一旦卸載該app就立馬彈出一個網頁來讓我填寫為什么要卸載它。從產品的角度來說,這無疑是非常好的反饋設計。但是這件事情對手機和用戶來說并不好事。實現上技術上會不斷的輪訓手機的目錄。
原理剖析:
我們知道當apk正常安裝在手機上時會寫入到/data/data/包名目錄下。被卸載后系統會刪除掉。
所以借助NDK開發fork出來的C語言寫的的子進程代碼,在應用被卸載后不會被銷毀的特性。做進程內不斷輪訓/data/data/包名是否存在。
當apk被卸載后如果你輪訓的代碼是java寫的。他會伴隨虛擬機一起銷毀。但是由于是用C來做輪訓,利用了Linux子進程和java虛擬機不在一個進程中的特性就不怕被殺,這點和第一篇我們講到的雙進程守護有異曲同工之妙。但是android 5.0谷歌還是干掉了這件事,所以請君放心。哈哈
下面是C的實現部分。
Java_com_charon_uninstallfeedback_MainActivity_initUninstallFeedback(JNIEnv* env, jobject thiz, jstring packageDir, jint sdkVersion) {char * pd = Jstring2CStr(env, packageDir);//fork子進程,以執行輪詢任務pid_t pid = fork();if (pid < 0) { // fork失敗了} else if (pid == 0) {// 可以一直采用一直判斷文件是否存在的方式去判斷,但是這樣效率稍低,下面使用監聽的方式,死循環,每個一秒判斷一次,這樣太浪費資源了。int check = 1;while (check) {FILE* file = fopen(pd, "rt");if (file == NULL) {if (sdkVersion >= 17) { // Android4.2系統之后支持多用戶操作,所以得指定用戶execlp("am", "am", "start", "--user", "0", "-a","android.intent.action.VIEW", "-d","http://shouji.360.cn/web/uninstall/uninstall.html",(char*) NULL);} else {// Android4.2以前的版本無需指定用戶execlp("am", "am", "start", "-a","android.intent.action.VIEW", "-d","http://shouji.360.cn/web/uninstall/uninstall.html",(char*) NULL);}check = 0;} else {}sleep(1);}} }java層調用部分
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);String packageDir = "/data/data/" + getPackageName();initUninstallFeedback(packageDir, Build.VERSION.SDK_INT);}private native void initUninstallFeedback(String packagePath, int sdkVersion);static {System.loadLibrary("uninstall_feedback");} }細節代碼請參考Github
https://github.com/CharonChui/UninstallFeedback
Home鍵監聽
一般在開發中,我們無法直接在活動中收到用戶點擊Home返回這樣的操作回調。但多數情況下,我們開發的應用是需要感知用戶離開的狀態的。這里我們可以利用廣播來做這件事情。
有這樣一個動態廣播來做監聽。
android.intent.action.CLOSE_SYSTEM_DIALOGS我們繼承一個廣播類,在里面可以收到用戶按下Home鍵和長按Home(或任務鍵,取決于手機的設計)
?
在activity里注冊一下這個廣播
非常簡單的就實現了。下面是展示效果,可以看到日志上的結果,我們點擊Home按鍵時收到了廣播。
?
GitHub地址:https://github.com/BolexLiu/AndroidHomeKeyListen
桌面添加快捷方式
不知道大家有沒有被這種流氓軟件襲擊過,你打開過他一次,后面就淚流滿面的給你裝了滿滿的一屏幕其他亂七八糟的一堆快捷方式。注意可能會誤認為被偷偷安裝了其他App,實際上他只是一個帶圖標的Intent在你的桌面上,但不排除root后的機器安裝app是真的,但我們今天這里只講快捷方式。
快捷方式有什么用?
- 1.可以給用戶一個常用功能的快捷入口(推薦)
- 2.搭配插件化技術實現模擬安裝后的app體驗(推薦)
- 3.做黑產(黑色產業鏈的東西我不想說了,只需要記得咱們是有原則的開發者,堅決抵制做垃圾App。即使別人給錢也不做。就這么任性 (ˇ^ˇ〉)
原理解析:
我們已經把AndroidManifest寫爛了,一眼看過去就知道這個標簽的作用。
沒錯,我們再熟悉不過了,一般我們理解成將作為App的第一個被啟動的Activity聲明。實際上我們知道Android的桌面(launcher ,一般做rom層的同學接觸比較多)上點擊任意一個app都是通過Intent啟動的。
神曾經說過,不懂的地方。read the fucking source code,那么我們來趴一趴launcher的源碼,它是如何接收到我們要添加的快捷方式的。(別害怕,源碼沒有想象中那么難度,跳著看。屏蔽我們不關注的部分。)
拿到一個Android應用層的項目第一件事情干嘛?看配置文件唄。來我們瞅一眼launcher的AndroidManifest。
注意我們發現了兩個receiver標簽,從上面的注釋可以發現
接收其他應用安裝的快捷方式意圖。這里就表明了launcher 是通過廣播來添加快捷方式的。我們接著翻源碼,看他是怎么處理這條廣播的。根據receiver里的name標簽我們找到InstallShortcutReceiver.java這個類。
首先我們發現他繼承了BroadcastReceiver ,很明顯就是一個廣播接收者,我們直接看onReceive方法里如何處理的。
//代碼細節部分省略太長了,不方便貼。可以自己去下載源碼看。public class InstallShortcutReceiver extends BroadcastReceiver {//做了很多處理,比如尋找將接受到的快捷方式放在屏幕的哪個位置、重復的圖標提示等public void onReceive(Context context, Intent data) {//判斷這條廣播的合法性if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {return;}·····略}//最終我們發現了這個方法,將快捷方式添加到桌面并存儲到數據庫private static boolean installShortcut(Context context, Intent data, ...參數省略) { ·····略if (intent.getAction() == null) {intent.setAction(Intent.ACTION_VIEW);} else if (intent.getAction().equals(Intent.ACTION_MAIN) &&intent.getCategories() != null &&intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);} ····略 } ····略}重點看下面這幾行,順藤摸瓜得知這個Intent來自來自別的app或系統發過來的廣播。下面黃橫線的部分已經解釋了,我們自己平時開發的app配置的主啟動項Activitiy intent-filter在哪里被用到了。這里接收到后的intent將加到桌面并存儲到數據庫中。由此算是明白了系統到底是怎么做的。
實現添加快捷方式:
好,既然已經知道原理了,我們現在就來實現一把,怎么添加一個任意的圖標到桌面。
首先我們需要配置權限聲明
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /><uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT" />第二步捏造一個添加快捷方式的廣播,具體請看下面的代碼。注意里面有兩個Intent,其中一個是廣播的,一個是我們自己下次啟動快捷方式時要用的,啟動時可以攜帶Intent參數。(能做什么,知道了吧?哈哈)
public static void addShortcut(Activity cx, String name) {// TODO: 2017/6/25 創建快捷方式的intent廣播Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");// TODO: 2017/6/25 添加快捷名稱shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);// 快捷圖標是允許重復shortcut.putExtra("duplicate", false);// 快捷圖標Intent.ShortcutIconResource iconRes = Intent.ShortcutIconResource.fromContext(cx, R.mipmap.ic_launcher);shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes);// TODO: 2017/6/25 我們下次啟動要用的Intent信息Intent carryIntent = new Intent(Intent.ACTION_MAIN);carryIntent.putExtra("name", name);carryIntent.setClassName(cx.getPackageName(),cx.getClass().getName());carryIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//添加攜帶的Intentshortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, carryIntent);// TODO: 2017/6/25 發送廣播cx.sendBroadcast(shortcut);}下面們調用一下看看。這里我添加了四個快捷方式,分別是abcd、abc、ab、a,然后我們返回桌面看一眼。他們都是可以啟動的。
github地址:https://github.com/BolexLiu/AddShortcut
無法卸載app(DevicePolicManager)
DevicePolicManager 可以做什么?
- 1.恢復出廠設置
- 2.修改屏幕解鎖密碼
- 3.修改屏幕密碼規則長度和字符
- 4.監視屏幕解鎖次數
- 5.鎖屏幕
- 6.設置鎖屏密碼有效期
- 7.設置應用數據加密
- 8.禁止相機服務,所有app將無法使用相機
首先我想,如果你是一個Android重度體驗用戶,在Rom支持一鍵鎖屏之前,你也許裝過一種叫快捷鎖屏、一鍵鎖屏之類的替代實體鍵鎖屏的應用。其中導致的問題就是當我們不需要用它的時候卻發現無法被卸載。
原理解析:
從功能上來看,本身該項服務是用來控制設備管理,它是Android用來提供對系統進行管理的。所以一但獲取到權限,不知道Android出于什么考慮,系統是不允許將其卸載掉的。我們只是在這里鉆了空子。
實現步驟:
繼承DeviceAdminReceiver類,里面的可以不要做任何邏輯處理。
注冊一下,description可以寫一下你給用戶看的描述。
<receiverandroid:name=".MyDeviceAdminReceiver"android:description="@string/description"android:label="防卸載"android:permission="android.permission.BIND_DEVICE_ADMIN" ><meta-dataandroid:name="android.app.device_admin"android:resource="@xml/deviceadmin" /><intent-filter><action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /></intent-filter></receiver>調用系統激活服務
// 激活設備超級管理員public void activation() {Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);// 初始化要激活的組件ComponentName mDeviceAdminSample = new ComponentName(MainActivity.this, MyDeviceAdminReceiver.class);intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mDeviceAdminSample);intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "激活可以防止隨意卸載應用");startActivity(intent);}我們來看下運行的效果。激活以前是可以被卸載的。
?
激活以后無法被卸載,連刪除按鈕都沒有了。就算你拿其他安全工具或系統的卸載也不能卸載哦。
?
但是我們可以在設備管理器中可以取消激活就恢復了。這里我們是正常的方式來激活,不能排除root后的設備,當app拿到root權限后將自己提權自動激活,或者將自身寫入到系統app區域,達到無法卸載的目的。所以我們常說root后的設備是不安全的也就在這里能說明問題。
github地址:https://github.com/BolexLiu/SuPerApp
無網絡權限偷偷上傳數據
這是一種超流氓的方式,目前市面上是存在這種app的。普通用戶不太注意的話一般發現不了。另一個對立面說用戶把app的訪問網絡權限禁用了如何告訴服務器消息呢?
原理解析:
雖然應用沒有權限,或者我們之前有權限被用戶屏蔽了。但是我們可以借雞下蛋,調用系統瀏覽器帶上我們要訪問的參數。實際在服務端收到的時候就是一個get請求可以解析后面拼接出的參數。比如: http://192.168.0.2/send?user=1&pwd=2 這樣就可以把user和pwd提交上去。當然這一切還不能被用戶發現,所以很變態的判斷用戶鎖屏后就打開瀏覽器發送消息,用戶一旦解鎖就回到桌面上,假裝一切都沒有發生過。
實現代碼:
本來我不準備把代碼貼出來的,但想了一下又有何妨。即便我不貼出來你也能找到,也能跟著思路寫出來。但是千萬千萬不要給用戶做這種東西。拜托了各位。
謝幕
本系列到這里算是完結了。這個系列的技術大多數來自互聯網上。我只是感興趣做了一些自己的研究。做這些事情告訴我一個道理,論閱讀源碼的重要性。我也不是什么大神,只是普通的一個程序員。別再叫我大佬了。雖然我在過往的文風中老是大佬大佬的。但那只是編的故事。哈哈
我們這代人就像紅橙Darren說的給了我們年輕人太多。這一路上我總是在特殊的時間點是上遇到貴人,在他們的幫助下少走不少彎路。真的很感謝這一切的發生。還有在看文章的你。真的,你們每一次點贊、喜歡、評論和關注都成為了我繼續努力的動力 ,以前我只是寫給自己看做一下筆記,當我發現越來越多的人在看我寫的東西的時候,我想我就必須對此負責,而不是隨便搞搞。
特別感謝公眾號碼個蛋 ****BaseRecyclerViewAdapterHelper****的作者陳宇明。最近兩天交流之中感受頗多。在這里表示謝謝他的指點。老哥,穩!
那些年Android黑科技①:只要活著,就有希望
- android應用內執行shell
- 雙進程保活aidl版
- 雙進程保活jni版
- 保活JobService版
那些年Android黑科技②:欺騙的藝術
- hook技術
- 欺騙系統之偷梁換柱
那些年Android黑科技③:干大事不擇手段
- 應用卸載反饋
- Home鍵監聽
- 桌面添加快捷方式
- 無法卸載app(DevicePolicManager)
- 無網絡權限偷偷上傳數據
作者:香脆的大雞排
鏈接:http://www.jianshu.com/p/8f9b44302139
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
轉載于:https://my.oschina.net/JiangTun/blog/1555240
總結
以上是生活随笔為你收集整理的那些年Android黑科技③:干大事不择手段的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: truelicense中的maven配置
- 下一篇: Linux的企业-Mfs高可用coros