菜鸡浅尝CTF安卓逆向

浅尝CTF安卓逆向



前言

偶然接触到的一道简单CTF安卓逆向入门的题,感觉挺有意思的,故此开始学一学,看一看记录一下


一、题目描述

给出了一个安卓的apk,模拟器打开是这样的,试了一下,大概可能就是叫输入一个flag值正确的话返回right,错误的话则是wrong
在这里插入图片描述

二、解题过程

虽然以前没做过安卓逆向的题,但是打ctf耳濡目染也知道,逆向嘛,我要分析代码!先用jadx打开看看怎么个事儿。我们可以看到有这么多复杂的东西,不要紧张,这是简单的题目,我们找到函数的入口。即MainActivity中onCreate方法下的onClick点击事件。
jadx打开
来出来我们读一读

public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { // from class: com.test.easyapk1.MainActivity.1

            @Override // android.view.View.OnClickListener

            public void onClick(View v) {

                String input = ((EditText) MainActivity.this.findViewById(R.id.editText)).getText().toString();

                if (input.startsWith("flag{") && input.endsWith("}")) {

                    String input2 = input.substring(5, input.length() - 1);

                    String[] input_split = input2.split("_");

                    if (input_split.length == 4 && input2.length() == 26) {

                        long p1 = Long.parseLong(MainActivity.hexlong(input_split[0]), 16);

                        long p2 = Long.parseLong(MainActivity.hexlong(input_split[1]), 16);

                        long p3 = Long.parseLong(MainActivity.hexlong(input_split[2]), 16);

                        if ((p1 + p2) - p3 == 141187687 && p1 * p2 == 892043278776532616L && p3 - p2 == 956566027 && MainActivity.this.check2(input_split[3]) == 1) {

                            Toast.makeText(MainActivity.this, "right", 1).show();

                            return;

                        }

                    }

                }

                Toast.makeText(MainActivity.this, "wrong!", 1).show();

            }

        });

    }

简单读下代码

  1. 获取输入:
    获取 MainActivity 对象,并从中获取 EditText 控件的文本内容。
    检查文本是否以 “flag{” 开头,并以 “}” 结束。
  2. 分割输入:
    如果输入符合条件,则去除开头和结尾的标记,并按 _ 分割成数组 input_split。
  3. 验证长度:
    检查分割后的数组长度是否为 4,并且整个字符串长度为 26。
  4. 数值验证:
    将分割后的字符串转换为长整型数值 p1, p2, 和 p3。
    o 检查数值是否满足以下条件:
    (p1 + p2) - p3 == 141187687
    p1 * p2 == 892043278776532616L
    p3 - p2 == 956566027
  5. 本地方法验证:
    调用本地方法 check2 对输入的第四部分进行验证。
  6. 显示结果:
    如果所有条件都满足,则显示 “right” 的提示。
    否则,显示 “wrong!” 的提示
    那不就有思路了,就是解密四个数组,前三个的关系已经给我们了,是比较简单的数字关系。
    直接写个python脚本轻松拿捏
a = 141187687
b = 892043278776532616
c = 956566027

p1 = a+c
p2 = b//p1
p3 = c+p2

print(long_to_bytes(p1))
print(long_to_bytes(p2))
print(long_to_bytes(p3))

得到前三个数组如下:
前三个数组结果
现在就是这第四个数组了,因为我之前是真没接触过,所以这里卡了很久,查资料才搞清楚原来本地方法check2原来是要去so文件里面找,先把apk文件后缀改为zip解压打开找到这个文件。
在这里插入图片描述
idea打开这个文件,我们找check2方法
在这里插入图片描述
不出所料应该就是这个Java_com_test_easyapk1_MainActivity_check2,又读代码呗没啥好说的
在这里插入图片描述
我们主要找check2的判断逻辑,该函数通过 JNI 获取 Java 字符串的内容,并将其传递给 sub_E9F0 函数进行处理。然后,该函数比较处理后的字符串与目标字符串是否相同。他说传递给sub_E9F0 处理的我们就找E9F0 了。一阵好找,找到了。
在这里插入图片描述
继续我们来好好看看他是什么处理逻辑
在这里插入图片描述
我一看是一个类base64的加密方式,不过这里用的是特定的查找表 aZtsi01htnufVoe,(好家伙,自定表的base64嘛就是)接下来我们就需要找这个表和加密后的内容了,又是一阵好找。黄天不负有心人啊!最后找到了。
在这里插入图片描述
没啥好说的,下面都是easy的工作,CyberChef直接解一下
在这里插入图片描述
然后整合一下加上flag{},终于顺利拿下了说是

byte_strings = [b'Andr', b'0oid', b'isso', b'1nteResTing']

concatenated_bytes = b''.join(byte_strings)

final_string = concatenated_bytes.decode('utf-8')

flag_format = f"flag{{{final_string}}}"

print(flag_format)

在这里插入图片描述

总结

虽然做的过程小虐了我这个菜鸡一把,但是不得不说安卓逆向还是有趣哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值