吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4689|回复: 10
收起左侧

[Android 原创] 2018xman冬令营选拔赛第2题wp-Android结合js的逆向实践

[复制链接]
文远张辽 发表于 2018-1-7 17:42
本帖最后由 文远张辽 于 2018-1-7 18:00 编辑

2wp 绕着绕着就出来了

1.      使用jd-gui反编译apk源代码。


2.      查看主进程中的OnCreate()函数:


2

2


点击按钮a的时候,会创建b对象,b对象会执行url中的js


3.      查看b类的源代码:


点击的响应函数是调用a对象的a方法对输入的字符串进行处理,之后主进程中的b对象加载url中的“javascript:o0O0oo0o0o0o0oO()”js代码。

3

3

4.      查看a对象的a方法是如何对输入字符串处理的。
主要有以下几个关键点:
(1)      输入由‘-’分成了四组;
(2)      输入除了’-‘可以包含数字、大小写字母;
(3)      最后交由b方法处理输入字符串。
这大概是一个注册码,我们应该是做一个逆向,推出其中正确的注册码。

[Java] 纯文本查看 复制代码
public static void a(String paramString)
  {
    a = 0;
    b = 0;
    MainActivity.b.getSettings().setUserAgentString(MainActivity.b.getSettings().getUserAgentString() + ";" + a + ";" + b);
    String[] arrayOfString = paramString.split("-");
    if (arrayOfString.length != 4) {
      return;
    }
    for (int i = 0;; i++)
    {
      if (i >= arrayOfString.length) {
        break label192;
      }
      if (arrayOfString[i].length() != 4) {
        break;
      }
      int j = 0;
      label95:
      if (j < arrayOfString[i].length())
      {
        if ((arrayOfString[i].charAt(j) > '/') && (arrayOfString[i].charAt(j) < ':')) {}
        for (;;)
        {
          j++;
          break label95;
          if ((arrayOfString[i].charAt(j) <= '@') || (arrayOfString[i].charAt(j) >= '[')) {
            if ((arrayOfString[i].charAt(j) <= '`') || (arrayOfString[i].charAt(j) >= '{')) {
              break;
            }
          }
        }
      }
    }
    label192:
    b(paramString);
  }


5.      查看a对象的b方法是如何对输入字符串处理的。


主要有以下几个关键点:
(1)      原来输入的顺序被重新排列,变成了1 3 4 2
(2)      包含了一系列的判断条件,只要满足其中一个,就不会执行最下面的语句,所以应该让所有的判断条件不满足;
(3)      出现了很多奇怪的字符,是反编译的时候错误将负数当成了字符处理,具体的数值要查看smali代码获得(可以参考下面的逆向脚本);
(4)      ab是其中关键了两个数字,他们由字符串的某一位异或而来。根据判断条件可知,这一位和其他位有着联系;
(5)      最后,主进程的b对象(WebView)UserAgent后面加上了";" + a + ";" + b,其中的a大于b,并且a小于100


[Java] 纯文本查看 复制代码
public static void b(String paramString)
  {
    String[] arrayOfString = paramString.split("-");
    char[] arrayOfChar1 = arrayOfString[0].toCharArray();
    char[] arrayOfChar2 = arrayOfString[3].toCharArray();
    if (arrayOfChar1[0] != '&#65533;' + arrayOfChar2[1]) {}
    label33:
    char[] arrayOfChar3;
    char[] arrayOfChar4;
    do
    {
      do
      {
        do
        {
          break label33;
          do
          {
            return;
          } while ((arrayOfChar1[3] != (char)(0x1 | arrayOfChar2[2])) || (arrayOfChar2[2] % '\002' == 1));
          a = 0x37 ^ arrayOfChar2[3];
        } while ((arrayOfChar2[2] != arrayOfChar1[2] + 2 * arrayOfChar1.length) || (arrayOfChar2[0] != arrayOfChar1[0] - arrayOfChar1.length / 2) || (arrayOfChar2[1] != (char)(0x12 ^ arrayOfChar1[3])) || ('\002' * arrayOfChar1[1] != '&#65528;' + arrayOfChar1[2]) || (arrayOfChar2[3] != arrayOfChar1[2]));
        arrayOfChar3 = arrayOfString[1].toCharArray();
        arrayOfChar4 = arrayOfString[2].toCharArray();
      } while ((arrayOfChar3[1] + 3 * arrayOfString.length != arrayOfChar3[3]) || ('\002' * arrayOfChar4[1] != '&#65525;' + arrayOfChar3[3]));
      b = 0x71 ^ arrayOfChar3[2] - arrayOfChar4.length;
    } while ((arrayOfChar3[0] + arrayOfChar4[0] != 187) || (arrayOfChar3[0] + arrayOfChar4[3] != 210) || ((arrayOfChar3[3] ^ arrayOfChar3[2]) != '/') || ((arrayOfChar3[0] ^ arrayOfChar3[1]) != '\017') || ((arrayOfChar4[2] ^ arrayOfChar3[1]) != '\005') || (a <= b) || (a >= 100));
    MainActivity.b.getSettings().setUserAgentString(MainActivity.b.getSettings().getUserAgentString() + ";" + a + ";" + b);
  }

6.      查看完a对象的a方法后,查看./android_asset/check_flag.html这个文件的 javascript:o0O0oo0o0o0o0oO()”js代码。


可以看到有相当大的混淆代码,进行优化。

6

6

7.      只贴上优化后的关键代码。
主要有以下几个关键点:
(1)      Js 首先取出了userAgent中的数字,保存在bbb中;
(2)      Js 包含了较多的匿名函数;
(3)      Js中通过navigator函数使用数组中的字符串,进行函数的调用;
(4)      Js最后的语句是将result变量设置为"flagis XCTF{your input}" 或者 "try again",当然我们希望是前者,所以要ggg(bbb[bbb["length"] - 2])(bbb[bbb["length"] -1])true
(5)      ggg是一个匿名函数,首先通过传入一个参数,返回了再次使用一个参数的函数,这个函数也是匿名函数,包含一个递归函数返回了一系列的表达式的 值;
(6)      因此gggtrue,就要求调用的匿名函数中的一系列表达式都成立;
(7)      第一个表达式是一个二元二次方程,用平方差公式化简就是c-e==56,第二、三个表达式限定了一定的范围,第四个表达式表达的意义和辗转相除余7相似;
(8)      貌似这样的ce是有很多种的。
[Java] 纯文本查看 复制代码
var aaa = ["map", ";", "split", "userAgent", "innerHTML", "result", "getElementById", "length", "flag is XCTF{your input}", "try again"];
        var arr = [aaa[0], aaa[1], aaa[2], aaa[3], aaa[4], aaa[5], aaa[6], aaa[7], aaa[8], aaa[9]];
function F2() {
            const bbb = navigator["userAgent"]["split"](";")["map"]((fff) = > Number(fff));
            var ggg = function(c) 
            {
                return 
                function(e) 
                {                
                    var ddd = function(c, e) 
                    {
                        return 0 === e ? c : ddd(e, c % e)
                    };

                    return c * c - e * e == 56 * (c + e) && 1e4 < c * c + c * e + e * e && 1e4 > c * c - c * e - e * e && 7 == ddd(c, e)
                }
            };
            document["getElementById"]("result")["innerHTML"] = ggg(bbb[bbb["length"] - 2])(bbb[bbb["length"] - 1]) ? "flag is XCTF{your input}" : "try again"
        }




8.      理一下思路Apk内是对输入字符串合法性的检验,并将字符串转换为两个数字,通过加在userAgent后面传递到js中,如果这两个数字正确那么就会有相应的提示。那么应该根据js推出这两个数字,再根据字符串之间的制约关系,还原其中的一个可行注册码。


9.      第一步的脚本,还原两个数字。


结果只有一组,是91 35。那么对应到apk中,就是a=91,b=35

[Python] 纯文本查看 复制代码
def d(c,e):
        if e==0:
                return c
        else:
                return d(e, c % e)

for e in range(45):
        c=56+e
        if(1e4 < c * c + c * e + e * e):
                if(1e4 > c * c - c * e - e * e):
                        if(7 == d(c, e)):
                                print(str(c)+"   "+str(e))


10.  第二步的脚本,还原注册码。

Apk源代码中的错误字符,参考smali代码。结果就是flag

d2lu-bmVy-Y7hp-bgtl
[Python] 纯文本查看 复制代码
a=91
b=35
a1=[0,0,0,0]
a2=[0,0,0,0]
a3=[0,0,0,0]
a4=[0,0,0,0]
a2[3]=a^0x37
a1[2]=a2[3]
a2[2]=a1[2]+2*4
a1[1]=(int) ((a1[2]-8)/2)
a1[3]=0x1 | a2[2]
a2[1]=0x12^a1[3]
a1[0]=a2[1]-3
a2[0]=(int)(a1[0]-1/2*4)

a3[2]=(b+4)^0x71
a3[3]=47^a3[2]
a3[1]=a3[3]-3*4
a3[0]=a3[1]^15
a4[2]=a3[1]^5
a4[3]=210-a3[0]
a4[0]=187-a3[0]
a4[1]=(int)((a3[3]-0xb)/2)

for i in range(4):
        a1[i]=chr(a1[i])
for i in range(4):
        a2[i]=chr(a2[i])
for i in range(4):
        a3[i]=chr(a3[i])
for i in range(4):
        a4[i]=chr(a4[i])        
print(''.join(a1)+'-'+''.join(a3)+'-'+''.join(a4)+'-'+''.join(a2))


11.  这道题目思路比较简单,但是很绕,需要耐心细致的分析和琢磨。

链接:https://pan.baidu.com/s/1csbvtG 密码:gv62

第2题wp.zip

82.38 KB, 下载次数: 2, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 2威望 +1 吾爱币 +15 热心值 +2 收起 理由
qtfreet00 + 1 + 12 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
MXWXZ + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 文远张辽 发表于 2018-1-7 22:47
C0d3r1iu 发表于 2018-1-7 21:28
有米有其他题的呢,特想知道第一题和第三题怎么做,脑洞跟不上啊

第一题和第三题好好想想就出来了,等别的同志wp吧,哈哈哈
 楼主| 文远张辽 发表于 2018-1-7 22:48
chenjingyes 发表于 2018-1-7 21:43
现在越来越多用js架构实现的安卓应用   了

哈哈哈,那我要好好学习一下啦
LeiSir 发表于 2018-1-7 18:32
lghlth 发表于 2018-1-7 18:54
谢谢分享
云在天 发表于 2018-1-7 21:23
求其他题。
C0d3r1iu 发表于 2018-1-7 21:28
有米有其他题的呢,特想知道第一题和第三题怎么做,脑洞跟不上啊
chenjingyes 发表于 2018-1-7 21:43
现在越来越多用js架构实现的安卓应用   了
 楼主| 文远张辽 发表于 2018-1-7 22:44

诶,能力有限,分工合作,我做这一个。
云在天 发表于 2018-1-8 00:09
文远张辽 发表于 2018-1-7 22:44
诶,能力有限,分工合作,我做这一个。

我觉得难度还行,不是那么太烧脑。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-3 20:52

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表