首页
社区
课程
招聘
[原创]攻防世界easyjni精析
2022-9-29 15:06 7116

[原创]攻防世界easyjni精析

2022-9-29 15:06
7116

前言

这题应该是原本在攻防世界的,但由于近期改版,在平台未找到原题,我也是从别的帖子上下载的题目。

考察apk

0、首先夜神模拟器跑看看,虽然无卵用,知道大概就是输入个flag,验证是否正确。

 

APK逆向

1、下载apk,拖入jadx-gui-1.4.4

 

里面有个函数叫a,重命名为localCheck,另外一个类叫a,重命名为aClass,发现调用了aClass的encode方法为用户输入编码,然后调用ncheck来检查,ncheck是native函数,在so文件可以找到。

 

 

2、考察aClass的encode方法

 

 

看到了这个charSets数组,数一下数量,发现有64个字符,猜测是base64编码

 

新编码表:

 

{'i', '5', 'j', 'L', 'W', '7', 'S', '0', 'G', 'X', '6', 'u', 'f', '1', 'c', 'v', '3', 'n', 'y', '4', 'q', '8', 'e', 's', '2', 'Q', '+', 'b', 'd', 'k', 'Y', 'g', 'K', 'O', 'I', 'T', '/', 't', 'A', 'x', 'U', 'r', 'F', 'l', 'V', 'P', 'z', 'h', 'm', 'o', 'w', '9', 'B', 'H', 'C', 'M', 'D', 'p', 'E', 'a', 'J', 'R', 'Z', 'N'}

 

正常的base64编码表如下:

 

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

Base64编码详解

既然猜测是base64编码,就不得不提到base64的编码过程。

 

暂时无法在飞书文档外展示此内容

 

简而言之,base64编码过程就是把用8bit表示的ASCII“数字”,转成6bit表示的“数字”。

 

举例来说,假如有字符串abcd转成YWJjZA==。

Base64编码过程

0、待编码字符串按照3个一组分组

 

1、字符转ascii码值

 

2、ascii码值转换为8bit二进制表示

 

3、按照6bit一组重新组合

 

4、6bit数转10进制

 

5、查表

Base64 编码图解

(建议读者在纸上手写一遍)

 

根据替换的base64编码表还原

如果base64编码表被替换,那么在第5步查表的过程,将发现查出来的字符串会不一样,

 

但无论如何,查表所得的字符串所代表的(0-63)10进制数字是不变的

 

假如有个字符串:QAoOQMPFks1BsB7cbM3TQsXg30i9g3==

 

 

按照上述的新编码表,替换为正常的base64字符串为:

 

ZmxhZ3tqdXN0X0FOb3QjZXJfQHAzfQ==

 

 

替换过程可以利用Excel完成,或者写代码完成

 

注意要用LOOKUP函数,不能用Vlookup,不然Excel会不区分大小写

 

关键代码:

1
2
=LOOKUP(1,0/EXACT(改写后的编码表!B:B,A2),改写后的编码表!C:C)
=LOOKUP(1,0/EXACT(Base64编码表!A:A,B2),Base64编码表!B:B)

小贴士:字符串行转列

利用零宽断言字符串行转列,拖入sublime

 

(?<=.) 替换为\n

python替换脚本

(抄来的,py3才能用)

1
2
3
4
5
6
7
8
9
10
import base64
import string
str1 = "QAoOQMPFks1BsB7cbM3TQsXg30i9g3=="
string1 = 'i'+'5'+'j'+'L'+'W'+'7'+'S'+'0'+'G'+'X'+'6'+'u'+'f'+'1'+'c'+'v'+'3'+'n'+'y'+'4'+'q'+'8'+'e'+'s'+'2'+'Q'+'+'+'b'+'d'+'k'+'Y'+'g'+'K'+'O'+'I'+'T'+'/'+'t'+'A'+'x'+'U'+'r'+'F'+'l'+'V'+'P'+'z'+'h'+'m'+'o'+'w'+'9'+'B'+'H'+'C'+'M'+'D'+'p'+'E'+'a'+'J'+'R'+'Z'+'N'  
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
print (str1)
print (string1)
print (string2)
print (str1.translate(str.maketrans(string1,string2)))
print (base64.b64decode(str1.translate(str.maketrans(string1,string2))))

那么你一定会好奇,QAoOQMPFks1BsB7cbM3TQsXg30i9g3== 这个串哪来的?

 

这时候就要研究so文件了。

考察so

把easyjni.apk当作zip解压,在lib\armeabi-v7a中发现libnative.so,拖入ida

ida逆向so

 

然后万能的F5,看到关键代码

 

 

只能连蒙带猜,从代码看出v6的长度,一定要为32个字符。

 

结合底下的MbT3sQgX039i3g==AQOoMQFPskB1Bsc7,长度恰好为32,猜测用户输入的字符串经过某种变换,和这个字符串比较刚好相等。

 

为了好读,就改下变量名。

第一轮变换

1
2
3
4
5
6
7
8
do
    {
      v8 = &s1[i];
      s1[i] = t_str[i + 16];
      v9 = t_str[i++];
      v8[16] = v9;
    }
    while ( i != 16 );

先考察这段代码,恕我眼拙,光看,真的看不懂,幸好我会VC6

 

随便给两个字符串赋值一下

 

​ char s1[33]="s1:abcdefghijklmnopqrstuvwxyz123";

 

​ char t_str[33]="t_str:ABCDEFGHIJKLMNOPQRSTUVWXYZ";

 

原样拖入vc6,竟然能跑

 

 

跑一跑可以发现,t_str没变,s1被从中间被切开,左右交换了。

 

 

接下来这一句啥意思真的不知道,所以只能跳过,

 

第二轮变换

下一个逻辑

1
2
3
4
5
6
7
8
9
10
do
    {
      v12 = __OFSUB__(v10, 30);
      v11 = v10 - 30 < 0;
      v16 = s1[v10];
      s1[v10] = s1[v10 + 1];
      s1[v10 + 1] = v16;
      v10 += 2;
    }
    while ( v11 ^ v12 );

说实话,OFSUB(v10, 30) 和 v10 - 30 < 0; 到底啥意思,真不知道,而且v11和v12还控制着整个循环。

 

但我们可以猜,因为前面的循环代码,是 do while ( i != 16 );

 

我们可以照抄,或者把16改成32,两种都试试,幸运的是,16改成32就是题目表示的逻辑

 

 

再跑跑看

 

 

发现字符串分成2个为一组,左右交换了。

 

按照这个逻辑,逆回来,我们的最终字符串是

 

MbT3sQgX039i3g==AQOoMQFPskB1Bsc7

 

那么2个为一组,左右交换一下,是

 

bM3TQsXg30i9g3==QAoOQMPFks1BsB7c

 

再从中间切开,左右交换,就是

 

QAoOQMPFks1BsB7cbM3TQsXg30i9g3==

解码

这个字符串,就是被替换过编码表的Base64编码,按照上一节所述,大概就是

 

QAoOQMPFks1BsB7cbM3TQsXg30i9g3== 变成

 

ZmxhZ3tqdXN0X0FOb3QjZXJfQHAzfQ== 变成

 

flag{justANot#er@p3}

 

思考题

1、假如字符串长度是n,那么转成base64后,长度为多少?

 

2、之前保存的ida工程,再按f5代码居然会不一样

 

 

3、

1
2
3
4
5
6
7
8
9
10
do
    {
      v12 = __OFSUB__(v10, 30);
      v11 = v10 - 30 < 0;
      v16 = s1[v10];
      s1[v10] = s1[v10 + 1];
      s1[v10 + 1] = v16;
      v10 += 2;
    }
    while ( v11 ^ v12 );

这些黄底的到底啥意思? OFSUB到底是啥?

附件

c++代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <stdio.h>
 int main()
{
        int i=0;
        int j=0;
        char *v8;
    char v9;
 
    char s1[33]="s1:abcdefghijklmnopqrstuvwxyz123";
    char t_str[33]="t_str:ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    do
    {
        v8 = &s1[i];
        s1[i] = t_str[i + 16];
        v9 = t_str[i++];
        v8[16] = v9;
    }
    while ( i != 16 );
        for(j=0;j<33;j++)
                printf("%c",t_str[j]);
 
        printf("\n");
        printf("\n");
        printf("\n");
 
        for(j=0;j<33;j++)
                printf("%c",s1[j]);
 
        printf("\n");
        printf("\n");
        printf("\n");
        printf("\n");
        printf("\n");
        printf("\n");
        printf("\n");
 
 
 
    i = 0;
        /*
    do
    {
      v12 = __OFSUB__(i, 30);
      v11 = (i - 30) < 0;
 
 
      v16 = s1[i];
      s1[i] = s1[i + 1];
      s1[i + 1] = v16;
      i += 2;
    }
    while ( v11 ^ v12 );
     */
        do
    {
 
      v9 = s1[i];
      s1[i] = s1[i + 1];
      s1[i + 1] = v9;
      i += 2;
    }
    while ( i != 32 );
 
   for(j=0;j<33;j++)
                printf("%c",s1[j]);
 
    return 0;
 
}

心灵鸡汤

1、教是最好的学,输出是最好的输入。

 

2、要多培养自己写文档分享的习惯。

 

3、基础不牢,地动山摇,base64解码的流程又是什么呢?

 

(1、查表 2、转6bit 3、合并8bit 4、8bit转ascii码)

 

4、题目说是easyjni,但感觉不是很easy。

参考

1、base64编码_动画演示 Base 64 编码

 

https://blog.csdn.net/weixin_39519741/article/details/110582856

 

2、一篇文章彻底弄懂Base64编码原理

 

https://blog.csdn.net/wo541075754/article/details/81734770

 

3、攻防世界--MOBILE区“easyjni.apk”逆向过程,附apk文件和python脚本

 

https://www.52pojie.cn//thread-1628993-1-1.html

鸣谢

从这个帖子找的题目附件

 

https://www.52pojie.cn//thread-1628993-1-1.html


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

最后于 2022-9-30 10:39 被xianxiong编辑 ,原因:
上传的附件:
收藏
点赞2
打赏
分享
最新回复 (7)
雪    币: 16428
活跃值: (59367)
能力值: (RANK:125 )
在线值:
发帖
回帖
粉丝
Editor 2022-9-29 18:06
2
0
图片丢失
雪    币: 404
活跃值: (329)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xianxiong 2022-9-30 10:39
3
0
Editor 图片丢失
已修复图片问题,感谢!
雪    币: 263
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
军哥i 2022-9-30 10:47
4
0
接下来这一句啥意思真的不知道,所以只能跳过
——————————————————————
这一句其实就是ReleaseStringUTFChars,你把a1的类型更改为JNIEnv*,这些代码就很好读了
雪    币: 263
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
军哥i 2022-9-30 10:55
5
0

雪    币: 404
活跃值: (329)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xianxiong 2022-10-1 10:26
6
0
军哥i
嚯,感谢大神!我去研究研究
雪    币: 404
活跃值: (329)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xianxiong 2022-10-1 10:28
7
0
军哥i 接下来这一句啥意思真的不知道,所以只能跳过 —————————————————————— 这一句其实就是ReleaseStringUTFChars,你把a1的类型更改为JNIEnv*,这些代码就很 ...
可以再弱弱的问下 OFSUB到底是啥 吗
雪    币: 263
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
军哥i 2022-10-7 16:00
8
0
xianxiong 可以再弱弱的问下 OFSUB到底是啥 吗
表示x-y是否溢出,溢出返回1,没有溢出返回0。
在高版本的ida中,被翻译为,x是否小于y
游客
登录 | 注册 方可回帖
返回