【2024春节】解题之Android中级题 详细过程

查看 67|回复 6
作者:Botton   
0x01、前言
最近在学安卓逆向,正好把春节的Android中级题给做一做
0x02、过程
先把apk丢到GDA里面看一下
包名:com.zj.wuaipojie2024_2 入口:com.zj.wuaipojie2024_2.MainActivity


1.jpg (99.66 KB, 下载次数: 0)
下载附件
2024-7-28 07:17 上传

然后用jadx看下MainActivity下面有什么东西,发现有个叫checkPassword的方法


2.png (142.89 KB, 下载次数: 0)
下载附件
2024-7-28 07:23 上传

用frIDA来hook看一下
[JavaScript] 纯文本查看 复制代码Java.perform(function () {
        let MainActivity = Java.use("com.zj.wuaipojie2024_2.MainActivity");
        MainActivity["checkPassword"].implementation = function (str) {
                let ret = this["checkPassword"](str);
                console.log(str,ret);
                return ret;
        };
});
随便滑一个密码,可以发现方法被调用了,手势的索引是
0 1 2
3 4 5
6 7 8
传入的str就是我们的密码


3.jpg (74.19 KB, 下载次数: 0)
下载附件
2024-7-28 07:30 上传

那么看一下
[color=]checkPassword

面进行了哪些操作
checkPassword方法先是从apk的assets目录下拿到classes.dex,复制了一份到app内部空间的data目录下,命名为1.dex,然后加载这个1.dex,调用com.zj.wuaipojie2024_2.C类下的isValidate方法
这里看一下app的运行日志,
adb logcat | grep
[color=]com.zj.wuaipojie2024_2.MainActivity
这里用cmder来执行命令,因为
grep
是linux下的命令


4.png (341.05 KB, 下载次数: 0)
下载附件
2024-7-28 07:51 上传

可以发现有这么一条日志
Suppressed: java.io.IOException: Failed to open dex files from /data/user/0/com.zj.wuaipojie2024_2/app_data/1.dex because: Failure to verify dex file '/data/user/0/com.zj.wuaipojie2024_2/app_data/1.dex': Bad checksum (c607ea12, expected 22dcea4c)
查一下关于dex的资料 https://source.android.com/docs/core/runtime/dex-format?hl=zh-cn
我们把这个1.dex
下载来
用010 Editor打开看看,模板选dex


5.png (154.85 KB, 下载次数: 0)
下载附件
2024-7-28 08:04 上传

可以看到
[color=]checksum

[color=]signature
是红色的,也就是因为
[color=]checksum
的值错误让app以为文件损坏导致
[color=]1.dex
没有成功加载
写一份脚本修复一下
[Python] 纯文本查看 复制代码import hashlib,zlib
def repairChecksum(dex_file):
    self = open(dex_file, "rb+")
    self.seek(8)
    # checksum是uint32,小端存储
    sourceData = self.read(4)[::-1]
    self.seek(12)
    checkdata = self.read()
    checksum = format(zlib.adler32(checkdata), 'x')
    print ("头部原checksum:",sourceData.hex())
    print ("计算checksum:",checksum)
    if sourceData.hex() == checksum:
        print('checksum校验正常')
    else:
        self.seek(8)
        # 小端写入
        self.write(bytes.fromhex(checksum)[::-1])
        print('checksum效验异常,修复成功')
def repairSignature(dex_file):
    self = open(dex_file, "rb+")
    self.seek(12)
    sourceData = self.read(20)
    self.seek(32)
    sigdata = self.read()
    sha1 = hashlib.sha1()
    sha1.update(sigdata)
    sha0 = sha1.hexdigest()
    print ("计算signature:",sha0)
    print ("现在signature:",sourceData.hex())
    if sourceData.hex() == sha0:
        print('SHA1效验正常')
    else:
        self.seek(12)
        self.write(bytes.fromhex(sha0))
        print('SHA1效验异常,修复成功')
if __name__ == '__main__':
    repairSignature('1.dex')
    repairChecksum('1.dex')
查一下app的安装路径
[color=]adb shell pm path com.zj.wuaipojie2024_2
package:/data/app/com.zj.wuaipojie2024_2-KFnHRFDetvCIbKXjR_4LTQ==/base.apk
这里用mt管理器把修复后的1.dex
替换到
[color=]base.apk

assets
目录下的
classes.dex
因为调用
checkPassword

法执行时会从这拿原来的classes.dex

复制一份到app内部空间的data目录下,不能直接替换data
目录下的
1.dex
,不然又被没修复的
classes.dex
覆盖掉了
然后我们重新运行app看一下日志


6.png (243.56 KB, 下载次数: 0)
下载附件
2024-7-28 08:26 上传

可以发现日志不一样了,没有之前那个加载dex的报错
分析一下
[color=]com.zj.wuaipojie2024_2
这个类下的执行过程


7.png (169.68 KB, 下载次数: 0)
下载附件
2024-7-28 09:12 上传

[color=]isValidate
方法中调用了
[color=]getStaticMethod
方法,
getStaticMethod
方法中调用了
read
方法和
fix
方法
getStaticMethod
中先用
read
方法中读入app运行目录
data
下的
decode.dex
,传入到
fix
方法后
生成了
2.dex
,然后加载
2.dex

com.zj.wuaipojie2024_2.A
类下的
d
方法

最后再将
2.dex
删除
将修复后的
1.dex
复制一份到
data
目录下,命名为
decode.dex


8.jpg (132.55 KB, 下载次数: 0)
下载附件
2024-7-28 09:27 上传

记得给文件权限
现在要想办法拿到2.dex
这里我通过frida来hook,阻止
2.dex
被删除
[JavaScript] 纯文本查看 复制代码Java.perform(function () {
    var deleteFile = Java.use("java.io.File").delete;
        deleteFile.implementation = function () {
                console.log("delete file: " + this);
                return
        };
});
把2.dex
丢到jadx里看一下


9.png (123.98 KB, 下载次数: 0)
下载附件
2024-7-28 09:34 上传

可以看到d
方法已经正常了,转换成python代码执行得到密码为
[color=]048531267
[Python] 纯文本查看 复制代码def calculate_str():
    stringBuffer = []
    i = 0
    fixed_string = "0485312670fb07047ebd2f19b91e1c5f"
    while len(stringBuffer)


10.jpg (85.71 KB, 下载次数: 0)
下载附件
2024-7-28 09:38 上传

可以得到提示在
[color=]B.d



11.jpg (86.32 KB, 下载次数: 0)
下载附件
2024-7-28 09:39 上传

但是这个B.d
显然还有问题,需要再修复
看一下
fix
方法需要的参数,是从
[color=]checkPassword
方法传过来的
[color=]String

str2

=

[color=](
[color=]String
[color=])

new

DexClassLoader
[color=](
file
.
getAbsolutePath
[color=](
[color=])
,

getDir
[color=](
[color=]"dex"
,

[color=]0
[color=])
.
getAbsolutePath
[color=](
[color=])
,

null
,

getClass
[color=](
[color=])
.
getClassLoader
[color=](
[color=])
[color=])
.
loadClass
[color=](
[color=]"com.zj.wuaipojie2024_2.C"
[color=])
.
getDeclaredMethod
[color=](
[color=]"isValidate"
,

Context
.
class
,

[color=]String
.
class
,

int
[color=][
.
class
[color=])
.
invoke
[color=](
null
,

this
,

str
,

getResources
[color=](
[color=])
.
getIntArray
[color=](
R
.
array
.
A_offset
[color=])
[color=])
;
getResources
[color=](
[color=])
[color=].
[color=]getIntArray
[color=](
[color=]R
[color=].
[color=]array
[color=].
[color=]A_offset
[color=])
得到
[color=]fix
方法中的
int i, int i2, int i3
jadx中点进去看一下
[color=]R.array.A_offset


12.png (170.62 KB, 下载次数: 0)
下载附件
2024-7-28 09:53 上传

发现还有一个叫R.array.D_offset
的,那我们把传入
fix
方法中的参数改成这个试试
[JavaScript] 纯文本查看 复制代码Java.perform(function () {
        let AppCompatActivity = Java.use("androidx.appcompat.app.AppCompatActivity");
        AppCompatActivity["getResources"].implementation = function () {
                let resources = this["getResources"]();
                resources.getIntArray.implementation = function (resId) {
            let ret = this.getIntArray(resId);
                        console.log(resId,ret);
                        if(resId == 2130903040){
                                return this.getIntArray(0x7f030001);
                        }
                        return ret;
        };
                return resources;
        };
        
        var deleteFile = Java.use("java.io.File").delete;
        deleteFile.implementation = function () {
                console.log("delete file: " + this);
                return
        };
});
把修复后的
[color=]2.dex
下载来丢到jadx中看一下


13.png (70.47 KB, 下载次数: 0)
下载附件
2024-7-28 10:00 上传

可以看到B.d
已经显示正常
最后把
Utils
复制下来稍微修改下即可
[Java] 纯文本查看 复制代码import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
public class Utils {
    public static final String SHA1 = "SHA1";
    public static byte[] toULEB128(int i) {
        int i2 = i >> 28;
        if (i2 > 0) {
            return new byte[]{(byte) ((i & 127) | 128), (byte) (((i >> 7) & 127) | 128), (byte) (((i >> 14) & 127) | 128), (byte) (((i >> 21) & 127) | 128), (byte) (i2 & 15)};
        }
        int i3 = i >> 21;
        if (i3 > 0) {
            return new byte[]{(byte) ((i & 127) | 128), (byte) (((i >> 7) & 127) | 128), (byte) (((i >> 14) & 127) | 128), (byte) (i3 & 127)};
        }
        int i4 = i >> 14;
        if (i4 > 0) {
            return new byte[]{(byte) ((i & 127) | 128), (byte) (((i >> 7) & 127) | 128), (byte) (i4 & 127)};
        }
        int i5 = i >> 7;
        return i5 > 0 ? new byte[]{(byte) ((i & 127) | 128), (byte) (i5 & 127)} : new byte[]{(byte) (i & 127)};
    }
    public static byte[] getSha1(byte[] bArr) {
        try {
            return MessageDigest.getInstance("SHA").digest(bArr);
        } catch (Exception unused) {
            return null;
        }
    }
    public static String md5(byte[] bArr) {
        try {
            String bigInteger = new BigInteger(1, MessageDigest.getInstance("md5").digest(bArr)).toString(16);
            for (int i = 0; i  127) {
            int i3 = byteBuffer.get() & 255;
            i2 = (i2 & 127) | ((i3 & 127)  127) {
                int i4 = byteBuffer.get() & 255;
                i2 |= (i4 & 127)  127) {
                    int i5 = byteBuffer.get() & 255;
                    i2 |= (i5 & 127)  127) {
                        i2 |= (byteBuffer.get() & 255)


14.png (95.14 KB, 下载次数: 0)
下载附件
2024-7-28 10:03 上传

下载次数, 方法

tomboy666   

厉害看起来挺难解的题
MrYuxuan   

感谢分享
lyz19860209   

等级太高了点→点看不懂。
ecco13   

感谢分享!
danwangdexiaoyi   

好多技术呀,够我学很久了
abc1234567890   

牛,用到好多技术,还得继续学习
您需要登录后才可以回帖 登录 | 立即注册

返回顶部