android中级,【2021春节】Android中级题

本文通过一系列工具,如ApkScan-PKID、jadx、IDA Pro和frida,详细介绍了如何对APK进行逆向分析。在分析过程中,作者发现了输入验证、加密函数以及对比值,并利用hook技术获取了加密和解密过程中的关键信息。最终,通过异或操作还原了原始字符串,成功解密出隐藏的FLAG。
摘要由CSDN通过智能技术生成

逆向之前需要准备以下一些工具

1.ApkScan-PKID(用于apk查壳)

2.jadx-gui-1.2.0(用于反编译apk)

3.IDA_Pro_v7.0(用于静态分析so文件)

4.python(运行frida注入js代码)

首先打开ApkScan-PKID,将待分析的apk拖进去,发现没有加固

55fd2b2273b5a8b4531f72773c469d6e.gif

0.jpg (33.28 KB, 下载次数: 0)

2021-3-5 11:08 上传

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

55fd2b2273b5a8b4531f72773c469d6e.gif

0.png (72.34 KB, 下载次数: 0)

2021-3-5 11:10 上传

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

55fd2b2273b5a8b4531f72773c469d6e.gif

1.jpg (111.85 KB, 下载次数: 0)

2021-3-5 11:12 上传

这里可以看到检测了输入的文本长度是否等于30,如果不是一律显示【flag格式错误,请重试】。长度是30的时候,会调用这个类下的check方法,如果返回真,则flag正确

但是这里的check方法是一个native函数,方法体在libnative-lib.so中,那么接着用ida分析这个so。ida加载so后,加载jni.h分析头文件,查看导出函数,发现是一个静态注册的方法

55fd2b2273b5a8b4531f72773c469d6e.gif

2.jpg (19.03 KB, 下载次数: 0)

2021-3-5 11:24 上传

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

55fd2b2273b5a8b4531f72773c469d6e.gif

3.jpg (32.82 KB, 下载次数: 0)

2021-3-5 11:36 上传

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

55fd2b2273b5a8b4531f72773c469d6e.gif

4.jpg (57.3 KB, 下载次数: 0)

2021-3-5 11:41 上传

那么首先来hook一下这两个函数

python代码

[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代码

[JavaScript] 纯文本查看 复制代码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[0];

console.log("参数1:");

console.log(Memory.readCString(args[0]));

console.log("参数2:");

console.log(args[1].toInt32());

console.log("参数3:");

console.log(Memory.readCString(args[2]));

},

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[0], 30));

console.log("参数2:");

console.log(args[1].toInt32());

},

onLeave: function(retval){

console.log("sub_D90 onLeave");

console.log("运算结果");

console.log(Memory.readCString(retval));

}

});

})

}

main();

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

55fd2b2273b5a8b4531f72773c469d6e.gif

5.jpg (40.68 KB, 下载次数: 0)

2021-3-5 11:59 上传

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

回到一开始汇编指令的图,找到进行对比前面的汇编指令

55fd2b2273b5a8b4531f72773c469d6e.gif

6.jpg (135.42 KB, 下载次数: 0)

2021-3-5 12:36 上传

这里还需要设置显示汇编指令的地址,教程链接:https://blog.csdn.net/weixin_45780275/article/details/109600482

此时可以看到汇编指令的地址是【B34】,同时我们需要的是x9寄存器的值

55fd2b2273b5a8b4531f72773c469d6e.gif

7.jpg (24.53 KB, 下载次数: 0)

2021-3-5 12:37 上传

js代码

[JavaScript] 纯文本查看 复制代码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】

55fd2b2273b5a8b4531f72773c469d6e.gif

8.jpg (6.74 KB, 下载次数: 0)

2021-3-5 12:41 上传

也就是说,我们输入的字符串是正确的,那么经过sub_B90加密,然后base64编码,应该是要与前面的值完全一样,这时重点就来到了sub_B90函数

进入sub_B90函数,大致浏览一下,a1就是我们输入的字符串,然后a1赋值给了v4,而v4只有一个地方进行了异或变化

55fd2b2273b5a8b4531f72773c469d6e.gif

9.jpg (63.45 KB, 下载次数: 0)

2021-3-5 12:46 上传

既然是异或,那么就好解决很多了,因为我们已经拿到了异或后的结果,如果能知道异或的内容是什么,就可以直接拿到异或前的内容了

那么就直接hook这条异或的汇编指令,可以看到汇编指令的地址是【D58】,需要的寄存器是x12

js代码

[JavaScript] 纯文本查看 复制代码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

55fd2b2273b5a8b4531f72773c469d6e.gif

11.jpg (26.25 KB, 下载次数: 0)

2021-3-5 12:51 上传

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

[Python] 纯文本查看 复制代码import base64

xordata = [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]

data = base64.b64decode('5Gh2/y6Poq2/WIeLJfmh6yesnK7ndnJeWREFjRx8'.encode())

flag = bytes([xordata[i] ^ data[i] for i in range(len(xordata))]).decode()

print(flag)

得到flag【52pojieHappyChineseNewYear2021】

输入apk里面尝试一下

55fd2b2273b5a8b4531f72773c469d6e.gif

1.png (82.94 KB, 下载次数: 0)

2021-3-5 12:54 上传

结果正确

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值