首页
社区
课程
招聘
攻防世界-mobile-easy-app详解
发表于: 2024-5-5 19:21 22845

攻防世界-mobile-easy-app详解

2024-5-5 19:21
22845

这道题网上很多分析,但是分析的都是arm版本的,我选了arm64的来分析,arm64相比arm难度高一些,因为arm64编译器搞了inline优化,看起来略抽象

这道题逻辑很简单,输入flag然后一个check函数验证,check函数是c层的,但是arm32和arm64差别很大,给大家瞄一眼,先32后64

可以看到,32位的逻辑非常清晰,拿到char*之后,弄成std::string,之后sub_9670函数对比是否是flag{开头,往后CheckM函数把flag{xxx}中的xxx的左16和右16组合在一起,形成一个32字节的字符串,之后check1进行一些简单的逻辑运算,再往后的encry是一个tea,之后是一个魔改的base64,就完事,逻辑很简单,但是到了arm64,就很难看了


说说主要的区别吧,首先是内联了很多函数,可以看到sub_9670已经没了,encry函数也没了,代码的复杂度提高了很多,还有就是,函数的返回值不按套路出牌,不放在x0寄存器中,不知道放在哪里,得去动态看才知道,比如check1之后的返回值,arm32中一看就知道是指针接受了返回值,但在arm64中莫名其妙放在了一个其他地方。

接下来说说,是怎么分析解决arm64的,首先,经过看这个so的代码以及一些搜索,发现string的内存结构为,string的大小为3个dq(8个字节),24字节,如果字符串小于0x17,那么首字节存放字符串长度乘以2,第二个字节开始放字符串内容;如果是长字符串,那么第一个dq放的是容量,并且这个容量会是奇数,也就是&&1会=1;编译器也是通过这个标志位判断是长字符串还是短字符串,第二个dq放的是字符串的真实长度,第三个dq放的是一个char*,指向真实的字符串;另外一个关于string的问题是,string的很多内部细节也被inline出来了,比如动态扩容,这部分的特征是,会出现一个grow_by_函数,这个函数执行扩容的细节,细节不说了,紧跟这个grow_by_函数后,会看到设置字符串长度的代码,根据这两个特征就能知道实在动态扩容了;

函数返回值不是放在x0,会放在莫名奇妙的地方,栈上的某个地方,这一块我采用的解决办法是用frida的stalker trace来分析,非常爽,文末会附上trace脚本


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2024-5-8 09:19 被kanxue编辑 ,原因: 去除广告
上传的附件:
收藏
免费 3
支持
分享
最新回复 (3)
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2024-5-6 10:42
2
雪    币: 22
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2024-5-7 00:03
1
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
感谢分享
2024-5-7 18:26
1
游客
登录 | 注册 方可回帖
返回
//