illusion题解
题目特征!(https://s2.loli.net/2024/09/29/HeO9aUKMEZ2dXpj.png)
查看是否存在壳
!(https://s2.loli.net/2024/09/29/hdqAQnaEcsMpVil.png)
Jeb反编译查看oncreate(),观察到一个点击事件监听
!(https://s2.loli.net/2024/09/29/jNsB4qF9w3QxLoy.png)
在事件监听上观察到先从assets文件下读取Flag文件内容再和用户输入字符串作为参数传给CheckFlag()函数,而CheckFlag方法有native修饰,说明是由so库加载的
!(https://s2.loli.net/2024/09/29/FtjS6yLgiTQWIcE.png)
IDA找到lib文件夹下的libnative-lib.so并加载,老方法直接搜java_包名,F5后,可以看到逻辑很简单:**将用户输入的每个字符,加上内置data字符串对应的下标的字符,然后再减去64。在和93一起作为参数传给sub_C40290C0(),运行后结果同Flag中的字符串进行比较得出。**
!(https://s2.loli.net/2024/09/29/uzU49rsMiDtgveY.png)
其中内置data字符串为
!(https://s2.loli.net/2024/09/29/ZG4rngPszcMJfSq.png)
进入sub_C40290C0(),可以看到恒跳转到sub_C4029028()处,继续跟进
!(https://s2.loli.net/2024/09/29/B54KovnxUeQEqWm.png)
可以看到这里的逻辑也很简单,通过位运算和循环逻辑来模拟除法
1. **位移操作**:使用右移(`>>`)将 `a2` 缩小,等价于除以2的幂,这样可以快速找到 `a1` 和 `a2` 的比值。
2. **逐步减法**:通过不断从 `a1` 中减去 `a2` 的不同倍数(如 `a2`、`a2 >> 1`、`a2 >> 2` 等),积累结果到 `v4`,这实际上是实现了除法的过程。
3. **乘法扩展**:通过不断乘以16和2来扩展 `a2`,实现了找到合适的倍数以提高计算效率。
综合这些步骤,最终可以得到 `a1` 除以 `a2` 的结果,反映了除法的本质。
!(https://s2.loli.net/2024/09/29/vJMLBKiP6hkYaw8.png)
**综上所诉,该题是通过将用户输入的每个字符,加上内置data字符串对应的下标的字符,然后再减去64; 得到的结果,取余93后,进行比较**
可以写逆向脚本来破解:
!(https://s2.loli.net/2024/09/29/LSz4s1t7TvfblpM.png)
结果如下,明显不符合flag的格式
!(https://s2.loli.net/2024/09/29/7zYEwdhraBGJKUo.png)
考虑是动态注册,函数处搜索JNI_Load(),看到`RegisterNatives`函数果然存在
!(https://s2.loli.net/2024/09/29/pEJTjBMFlOu3fyY.png)
跟进后发现其CheckFlag()同上面的代码逻辑一摸一样,不同的是内置data字符串发生改变
!(https://s2.loli.net/2024/09/29/rOP9CFGSblqa682.png)
动态注册的内置data字符串:
!(https://s2.loli.net/2024/09/29/47TLNj6BI8DYzpb.png)
只需更改上面脚本的data字符串即可,运行结果如下:
!(https://s2.loli.net/2024/09/29/N51xtCzGXfwOimu.png)
------
补充知识:
在 Android NDK 开发中,如果静态注册和动态注册的函数命名相同,Java 层会优先调用动态注册的函数。这是因为动态注册函数是在运行时通过 JNI_OnLoad 函数注册的,而静态注册函数在编译时被固化。具体来说,动态注册的函数会覆盖静态注册的同名函数,因此 Java 调用的会是动态注册的实现。
!(https://s2.loli.net/2024/09/29/INlqZV51jgRvACi.webp)
| 特性 | 静态注册 | 动态注册 |
| -------------- | ------------------------------------- | ---------------------------------------------- |
| 注册方式 | 根据JNI命名规则自动查找方法 | 通过`RegisterNatives`在运行时绑定方法 |
| 方法签名和命名 | 方法名遵循`Java_包名_类名_方法名`格式 | 通过`RegisterNatives`函数进行注册 |
| JNI_OnLoad | 无需使用动态注册相关API | 包含`RegisterNatives`调用 |
| 实现查找 | C/C++实现文件中存在静态注册命名方式 | C/C++实现文件中通过`RegisterNatives`绑定的方法 |
题目及:
链接: https://pan.baidu.com/s/1LXN1v-4HW5_Wgzv9bI9FyA?pwd=ic6w 提取码: ic6w
------
## 参考博客
(https://www.cnblogs.com/pengxurui/p/16526272.html)
[深入浅出Android NDK之使用RegisterNatives函数动态注册native函数_registernatives() 最后一个参数-CSDN博客](https://blog.csdn.net/taohongtaohuyiwei/article/details/104938240)
(https://blog.csdn.net/wangzhongshun/article/details/101273128)
(https://zhuanlan.zhihu.com/p/357885076)
(https://david1840.github.io/2020/11/09/Android-JNI函数动态注册/#:~:text=不同于静态注册中在Java类中定义好native方法后由编译器生成JNI方法,动态注册基本思想是在JNI_Onload ()函数中通过JNI中提供的RegisterNatives ()方法来将C%2FC%2B%2B方法和java方法对应起来%2C,JNI_OnLoad ()函数会在我们调用 System.loadLibrary的时候回调,注册整体流程如下%3A) 跟着大佬学逆向 学习一下 牛逼,我想知道有没有压缩文件加密后破解的资料 不错的学习资料 不错的教程啊 学到了plus
页:
[1]