丶诺熙 发表于 2020-1-11 00:02

攻防世界题解1-easyjni

## easyjni

根据题目,可以猜测肯定需要分析so文件。
上来先通过JEB反编译一下安卓代码。首先需要看MainActivity,这个是程序的入口,可以看到这里对我们输入的内容做做了判断。
![](http://img.5am3.com/5am3/img/20200110231530.png)

进而继续跟,可以看到这里进行了两次处理,首先传入a这个类中,处理过一次,然后传到ncheck。分析可以发现ncheck是我们so文件中的函数。而a这个类是java代码。
![](http://img.5am3.com/5am3/img/20200110231705.png)

继续对a类反编译,并分析。
![](http://img.5am3.com/5am3/img/20200110231854.png)

首先可以看到,这个应该是一个加密,看到上面存在密码表。根据其字符可以猜测为变种base64。提取出其密码表,尝试拿python重写一个。(网上有现成的)

然后和java代码执行结果相比对,可以发现猜测正确。
对123加密,结果如下:
![](http://img.5am3.com/5am3/img/20200110232158.png)

此时java层代码分析完毕。接下来看so文件内代码。
直接解压apk,从lib目录中提取出so文件。拖入ida。根据我们的关键字ncheck。可以找到这个函数,进而F5,可以看到伪代码。

![](http://img.5am3.com/5am3/img/20200110232347.png)

这里看着就迷很多了。在参考iyzyi师傅的wp后,以及询问apeng师傅后,逐渐理清了很多。

首先,我们可以猜测到v6为传入的字符串。
![](http://img.5am3.com/5am3/img/20200110232601.png)

然后我们来看第一个循环,看一下第一次执行结果,可以看到。

```c
do
    {
      // 首先v8保存了s1字符串的起始位地址,即s1
      v8 = &s1;
      // 然后将v6的v7+16位赋值给s1的v7位,即s1=v6
      s1 = v6;
      // v9保存了v6的值,然后v7+1 (后++),即v9=v6,v7=1
      v9 = v6;
      // 将v9 赋值给 s1[起始位+16],即s1=v6
      v8 = v9;
    }
    while ( v7 != 16 );
   
```

可以看出,该逻辑是将前16位与后16位对调。
然后继续分析下一个循环。

```c
do
    {
      v12 = __OFSUB__(v10, 30);
      v11 = v10 - 30 < 0;
      
      // v16 = s1
      v16 = s1;
      
      // s1=s1
      s1 = s1;
      // s1 = v16
      s1 = v16;
      v10 += 2;
    }
while ( v11 ^ v12 );
```

分析代码,可以发现,是两位两位,进行位置对调。

然后进而分析循环结束条件:
查阅资料。`__OFSUB__` 表示x-y是否溢出,溢出返回1,没有溢出返回0。在此情况下,应该不存在溢出,则返回均为0,即v12=0,当v10>30时,v11=0。此时异或得0,循环结束。

此时已经将整个程序分析完毕,接下来写poc解题。

```python
base64_charset = "i5jLW7S0GX6uf1cv3ny4q8es2Q+bdkYgKOIT/tAxUrFlVPzhmow9BHCMDpEaJRZN"

# 百度嫖的base64解码
def decode(base64_str):
    base64_bytes = ['{:0>6}'.format(str(bin(base64_charset.index(s))).replace('0b', '')) for s in base64_str if
                  s != '=']
    resp = bytearray()
    nums = len(base64_bytes) // 4
    remain = len(base64_bytes) % 4
    integral_part = base64_bytes

    while integral_part:
      tmp_unit = ''.join(integral_part)
      tmp_unit = , 2) for x in ]
      for i in tmp_unit:
            resp.append(i)
      integral_part = integral_part

    if remain:
      remain_part = ''.join(base64_bytes)
      tmp_unit = , 2) for i in range(remain - 1)]
      for i in tmp_unit:
            resp.append(i)

    return resp

# MbT3sQgX039i3g==AQOoMQFPskB1Bsc7
flag_enc = "AQOoMQFPskB1Bsc7MbT3sQgX039i3g=="
tmp=""
for i in range(len(flag_enc)//2):
        tmp += flag_enc + flag_enc
print(tmp)
print(decode(tmp))



```

丶诺熙 发表于 2020-1-11 11:55

昨夜星辰恰似你 发表于 2020-1-11 09:46
这是哪个哪个ctf呢

攻防世界的练习题、
https://adworld.xctf.org.cn/

丶诺熙 发表于 2020-1-11 00:04

附件地址:https://adworld.xctf.org.cn/media/task/attachments/633a06ba88a142bc9527e9b00bbb55ce.apk

judgecx 发表于 2020-1-11 03:20

虽然我不懂我还是给你顶?

zhngypng 发表于 2020-1-11 08:45

好奇点进来,一脸懵走出去。没看懂

frankB4 发表于 2020-1-11 09:18

虽然看不懂但还是感谢分享

昨夜星辰恰似你 发表于 2020-1-11 09:46

本帖最后由 昨夜星辰恰似你 于 2020-1-11 09:48 编辑

这是哪个哪个ctf呢

人小鬼大666 发表于 2020-1-11 16:58

一脸的懵逼。

冰封天堂 发表于 2020-1-11 21:55

这这这,上来就是这种难度的吗,完全懵逼状态

拖地僧 发表于 2020-1-12 16:13

虽然看不懂,但是还是想看!
页: [1] 2
查看完整版本: 攻防世界题解1-easyjni