漁滒 发表于 2021-3-5 12:54

【2021春节】Android中级题

逆向之前需要准备以下一些工具
1.ApkScan-PKID(用于apk查壳)
2.jadx-gui-1.2.0(用于反编译apk)
3.IDA_Pro_v7.0(用于静态分析so文件)
4.python(运行frida注入js代码)
首先打开ApkScan-PKID,将待分析的apk拖进去,发现没有加固

那么就可以直接拉进jadx进行反编译,安装好apk后随便输入一个值,会提示【flag格式错误,请重试】

那么就在jadx中搜索这个字符串,可以找到在【cn.pojie52.cm01.MainActivity】这个类下

这里可以看到检测了输入的文本长度是否等于30,如果不是一律显示【flag格式错误,请重试】。长度是30的时候,会调用这个类下的check方法,如果返回真,则flag正确
但是这里的check方法是一个native函数,方法体在libnative-lib.so中,那么接着用ida分析这个so。ida加载so后,加载jni.h分析头文件,查看导出函数,发现是一个静态注册的方法

双击进入这个函数,然后按F5转换为伪C代码,大概浏览一下,发现有一个与处级题中相似的结构

也就是说只要拿到v11与v27,就可以知道在对比什么了。首先分析v11,网上可以看到,输入的内容经过sub_B90和sub_D90两个函数以后,就得到了v11

那么首先来hook一下这两个函数
python代码
import frida
import sys

def message(message, data):
    pass

with open('jscode.js', 'r', encoding='utf-8') as f:
    jscode = f.read()

process = frida.get_remote_device().attach('cn.pojie52.cm01')
script = process.create_script(jscode)
script.on("message", message)
script.load()
sys.stdin.read()

js代码
function main() {
        Java.perform(function (){
                var libnative = Module.findBaseAddress("libnative-lib.so");
                console.log("libnative: " + libnative);
                var sub_B90 = libnative.add(0xB90);
                var sub_B90arge0;
                console.log("sub_B90: " + sub_B90);
                Interceptor.attach(sub_B90, {
                        onEnter: function(args){
                                console.log("sub_B90 onEnter");
                                sub_B90arge0 = args;
                                console.log("参数1:");
                                console.log(Memory.readCString(args));
                                console.log("参数2:");
                                console.log(args.toInt32());
                                console.log("参数3:");
                                console.log(Memory.readCString(args));
                        },
                        onLeave: function(){
                                console.log("sub_B90 onLeave");
                                console.log("运算结果");
                                console.log(Memory.readByteArray(sub_B90arge0, 30));
                        }
                });
                var sub_D90 = libnative.add(0xD90);
                console.log("sub_D90: " + sub_D90);
                Interceptor.attach(sub_D90, {
                        onEnter: function(args){
                                console.log("sub_D90 onEnter");
                                console.log("参数1:");
                                console.log(Memory.readByteArray(args, 30));
                                console.log("参数2:");
                                console.log(args.toInt32());
                        },
                        onLeave: function(retval){
                                console.log("sub_D90 onLeave");
                                console.log("运算结果");
                                console.log(Memory.readCString(retval));
                        }
                });
        })
}
main();

开启hook脚本后,随意输入30位字符,例如【111112222233333444445555566666】,可以得到下面内容

可以看到sub_B90对输入的内容进行了加密,而sub_D90实际是一个base64编码。接下来看看v27,v27没有比较好的函数可以hook,那么就需要考虑hook寄存器的值
回到一开始汇编指令的图,找到进行对比前面的汇编指令

这里还需要设置显示汇编指令的地址,教程链接:https://blog.csdn.net/weixin_45780275/article/details/109600482
此时可以看到汇编指令的地址是【B34】,同时我们需要的是x9寄存器的值

js代码
function main() {
        Java.perform(function (){
                var libnative = Module.findBaseAddress("libnative-lib.so");
                console.log("libnative: " + libnative);
                //获取flag加密后的内容
                var LDRB = libnative.add(0xB30);
                send("LDRB: " + LDRB);
                Interceptor.attach(LDRB, {
                        onEnter: function(args){
                                send("LDRB onEnter");
                                console.log(Memory.readCString(this.context.x9));
                        }
                });
        })
}
main();
继续输入30位字符进行hook,就可以得到进行对比的值【5Gh2/y6Poq2/WIeLJfmh6yesnK7ndnJeWREFjRx8】

也就是说,我们输入的字符串是正确的,那么经过sub_B90加密,然后base64编码,应该是要与前面的值完全一样,这时重点就来到了sub_B90函数
进入sub_B90函数,大致浏览一下,a1就是我们输入的字符串,然后a1赋值给了v4,而v4只有一个地方进行了异或变化

既然是异或,那么就好解决很多了,因为我们已经拿到了异或后的结果,如果能知道异或的内容是什么,就可以直接拿到异或前的内容了
那么就直接hook这条异或的汇编指令,可以看到汇编指令的地址是【D58】,需要的寄存器是x12
js代码
function main() {
        Java.perform(function (){
                var libnative = Module.findBaseAddress("libnative-lib.so");
                console.log("libnative: " + libnative);
                // 获取异或的字节,开了会报错,但是可以获取
                var ishook = true;
                var EOR = libnative.add(0xD58);
                var eor = [];
                var eorlen = 0;
                send("EOR: " + EOR);
                Interceptor.attach(EOR, {
                        onEnter: function(args){
                                if (ishook){
                                        if (eorlen < 30){
                                                eor.push(this.context.x12);
                                                eorlen += 1;
                                        }else{
                                                ishook = false;
                                                console.log(eor);
                                        }
                                }
                        }
                })
        })
}
main();
最后一次hook,但是这次hook会闪退,原因我也不知道,但是已经拿到了需要的内容
0xd1,0x5a,0x6,0x90,0x44,0xe6,0xc7,0xe5,0xde,0x28,0xf7,0xf2,0x66,0x91,0xc8,0x85,0x42,0xdf,0xf9,0xe0,0x82,0x1,0x2b,0x3b,0x38,0x63,0x37,0xbd,0x2e,0x4d


这时可以用python进行异或还原

import base64
xordata =
data = base64.b64decode('5Gh2/y6Poq2/WIeLJfmh6yesnK7ndnJeWREFjRx8'.encode())
flag = bytes( ^ data for i in range(len(xordata))]).decode()
print(flag)
得到flag【52pojieHappyChineseNewYear2021】
输入apk里面尝试一下

结果正确

goda 发表于 2021-3-7 11:51

感谢楼主又学到了,还能hook寄存器
      var libnative = Module.findBaseAddress("libnative-lib.so");
      var LDRB = libnative.add(0xB30);
      Interceptor.attach(LDRB, {
            onEnter: function(args){
                send("LDRB onEnter");
                console.log(Memory.readCString(this.context.x9));   //hook LDRB位置的x9寄存器
            }
      });

xyc520 发表于 2021-3-5 13:11

谢谢分享,有空了试一试。

asojdp 发表于 2021-3-5 13:25

{:301_973:} 练成楼主这样的水平大概需要几辈子??

爱玩的蛋黄 发表于 2021-3-5 13:33

一脸懵进来,一脸懵出去。;www

单纯滴情 发表于 2021-3-5 14:27

试试看,虽然挺蒙蔽的

罩到胸前必有沟 发表于 2021-3-5 14:28

乍一看很难,其实对于我这种外行人来说,根本看不懂

DearRoach 发表于 2021-3-5 16:06

        谢谢@Thanks!

szslzx 发表于 2021-3-5 16:09


试试看,虽然挺蒙蔽的

mo211683 发表于 2021-3-5 16:51

这是那方大佬,这么牛皮。佩服佩服{:1_937:}

blackzhangwei 发表于 2021-3-5 17:01

学习了!! 真的确实牛啊~~
页: [1] 2 3 4 5
查看完整版本: 【2021春节】Android中级题