編輯:關於Android編程
這篇文章是Android研發安全之Activity組件安全第二篇,本文將給大家分享Activity界面劫持方面的預防知識。
簡單的說就是APP正常的Activity界面被惡意攻擊者替換上仿冒的惡意Activity界面進行攻擊和非法用途。界面劫持攻擊通常難被識別出來,其造成的後果不僅會給用戶帶來嚴重損失,更是移動應用開發者們的惡夢。舉個例子來說,當用戶打開安卓手機上的某一應用,進入到登陸頁面,這時,惡意軟件偵測到用戶的這一動作,立即彈出一個與該應用界面相同的Activity,覆蓋掉了合法的Activity,用戶幾乎無法察覺,該用戶接下來輸入用戶名和密碼的操作其實是在惡意軟件的Activity上進行的,最終會發生什麼就可想而知了。
很多網友發現,如果在啟動一個Activity時,給它加入一個標志位FLAG_ACTIVITY_NEW_TASK,就能使它置於棧頂並立馬呈現給用戶。針對這一操作,假使這個Activity是用於盜號的偽裝Activity呢?在Android系統當中,程序可以枚舉當前運行的進程而不需要聲明其他權限,這樣子我們就可以寫一個程序,啟動一個後台的服務,這個服務不斷地掃描當前運行的進程,當發現目標進程啟動時,就啟動一個偽裝的Activity。如果這個Activity是登錄界面,那麼就可以從中獲取用戶的賬號密碼。
監聽系統Logocat日志,一旦監聽到發生Activity界面切換行為,即進行攻擊,覆蓋上假冒Activity界面實施欺騙。開發者通常都知道,系統的Logcat日志會由ActivityManagerService打印出包含了界面信息的日志文件,惡意程序就是通過Logocat獲取這些信息,從而監控客戶端的啟動、Activity界面的切換。
監聽系統API,一旦惡意程序監聽到相關界面的API組件調用,即可發起攻擊。
逆向APK,惡意攻擊者通過反編譯和逆向分析APK,了解應用的業務邏輯之後針對性的進行Activity界面劫持攻擊Android手機均有一個HOME鍵(即小房子的那個圖標),長按可以查看到近期任務。用戶在要輸入密碼進行登錄時,可以通過長按HOME鍵查看近期任務,比如說登錄微信時長按發現近期任務出現了微信,那麼我現在的這個登錄界面就極有可能是一個惡意偽裝的Activity,切換到另一個程序,再查看近期任務,就可以知道這個登錄界面是來源於哪個程序了。
研發人員通常的做法是,在登錄窗口或者用戶隱私輸入等關鍵Activity的onPause方法中檢測最前端Activity應用是不是自身或者是系統應用,如果發現惡意風險,則給用戶一些警示信息,提示用戶其登陸界面以被覆蓋,並給出覆蓋正常Activity的類名。
下面參考網友分享,給出一個研發人員常用的activity界面劫持防范措施代碼:
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { //判斷程序進入後台是否是用戶自身造成的(觸摸返回鍵或HOME鍵),是則無需彈出警示。 if((keyCode==KeyEvent.KEYCODE_BACK || keyCode==KeyEvent.KEYCODE_HOME) && event.getRepeatCount()==0){ needAlarm = false; } return super.onKeyDown(keyCode, event); } @Override protected void onPause() { //若程序進入後台不是用戶自身造成的,則需要彈出警示 if(needAlarm) { //彈出警示信息 Toast.makeText(getApplicationContext(), "您的登陸界面被覆蓋,請確認登陸環境是否安全", Toast.LENGTH_SHORT).show(); //啟動我們的AlarmService,用於給出覆蓋了正常Activity的類名 Intent intent = new Intent(this, AlarmService.class); startService(intent); } super.onPause(); }
import android.app.ActivityManager; import android.app.Service; import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.widget.Toast; public class AlarmService extends Service{ boolean isStart = false; Handler handler = new Handler(); Runnable alarmRunnable = new Runnable() { @Override public void run() { //得到ActivityManager ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE); //getRunningTasks會返回一個List,List的大小等於傳入的參數。 //get(0)可獲得List中的第一個元素,即棧頂的task ActivityManager.RunningTaskInfo info = activityManager.getRunningTasks(1).get(0); //得到當前棧頂的類名,按照需求,也可以得到完整的類名和包名 String shortClassName = info.topActivity.getShortClassName(); //類名 //完整類名 //String className = info.topActivity.getClassName(); //包名 //String packageName = info.topActivity.getPackageName(); Toast.makeText(getApplicationContext(), "當前運行的程序為"+shortClassName, Toast.LENGTH_LONG).show(); } }; @Override public int onStartCommand(Intent intent, int flag, int startId) { super.onStartCommand(intent, flag, startId); if(!isStart) { isStart = true; //啟動alarmRunnable handler.postDelayed(alarmRunnable, 1000); stopSelf(); } return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } }
社會化分享社會化分享,指的是用戶通過互聯網這個媒介,把文本/圖片/多媒體信息分享到該用戶的交際圈,從而加快信息傳播的行為。對於app來說,網絡社區雖多,但用戶量足夠大的就
前言這篇文章沒有什麼可看性,主要是源碼注釋太多,推薦自己看源碼,更容易理解些,在這裡主要介紹,其運作流程,貼代碼片段。自定義View要重寫三個方法:onMeasure,o
Android提供了實現按照秒計時的API,今天就是用這個API實現簡單的倒計時。來個布局: 對應活動中的代碼如下: pa
前言:有一天在寫代碼的時候,我想達到如下效果: AndroidManifest中的windowSoftInputMode屬性,我將其設置為adjustResize,正常來