吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2591|回复: 4
收起左侧

[Android CTF] 【CTF 安卓逆向】[SCTF2019]Strange_apk——安卓父子组件通信机制

  [复制链接]
hans7 发表于 2022-7-26 00:59
本帖最后由 hans7 于 2022-7-26 01:04 编辑

本文52pojie:https://www.52pojie.cn/thread-1666622-1-1.html

本文juejin:https://juejin.cn/post/7124354639419408414/

作者:hans774882968以及hans774882968

获取另一个APK

打开JEB:

    @Override  // android.content.ContextWrapper
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        try {
            File _ = this.getDir("sctf_odex", 0);
            File l = this.getDir("sctf_lib", 0);
            this.odexPath = _.getAbsolutePath();
            this.libPath = l.getAbsolutePath();
            this.apkFileName = _.getAbsolutePath() + "/sctf.apk";
            File File = new File(this.apkFileName);
            Log.i("demo", "apk size:" + File.length());
            if(!File.exists()) {
                File.createNewFile();
                this._(this.__("data"));
            }

            Object currentActivityThread = s.invokeStaticMethod("android.app.ActivityThread", "currentActivityThread", new Class[0], new Object[0]);
            String packageName = this.getPackageName();
            WeakReference v5 = Build.VERSION.SDK_INT >= 19 ? ((WeakReference)((ArrayMap)s.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mPackages")).get(packageName)) : ((WeakReference)((HashMap)s.getFieldOjbect("android.app.ActivityThread", currentActivityThread, "mPackages")).get(packageName));
            DexClassLoader dLoader = new DexClassLoader(this.apkFileName, this.odexPath, this.libPath, ((ClassLoader)s.getFieldOjbect("android.app.LoadedApk", v5.get(), "mClassLoader")));
            s.setFieldOjbect("android.app.LoadedApk", "mClassLoader", v5.get(), dLoader);
            Log.i("demo", "classloader:" + dLoader);
        }
        catch(Exception e) {
            Log.i("demo", "error:" + Log.getStackTraceString(e));
            e.printStackTrace();
        }
    }

这里有一个特殊的知识点:attachBaseContext方法调用时机早于onCreate。另外,查看代码易知this._(this.__("data"));会获得一个新的apk。那我们写个获取新apk的脚本:

def get_byte(v):
    return v.to_bytes(1, byteorder='little')

with open('data', 'rb') as f:
    a = f.read()
    with open('sctf.apk', 'wb') as g:
        for i in range(len(a)):
            g.write(get_byte(a[i] ^ ord("syclover"[i % 8])))

安卓父子组件通信机制

逐一查看sctf.demo.myapplication下的每个类。我们发现t这个类是主界面。如下:

package sctf.demo.myapplication;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.math.BigInteger;
import java.security.MessageDigest;

public class t extends AppCompatActivity {
    @Override  // android.support.v4.app.FragmentActivity
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        String v6;
        TextView tv = (TextView)this.findViewById(0x7F07008B);  // id:textView2
        Button bu = (Button)this.findViewById(0x7F070023);  // id:button2
        if(requestCode == 1 && resultCode == -1) {
            String key = "";
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update("syclover".getBytes());
                v6 = new BigInteger(1, md.digest()).toString(16);
            }
            catch(Exception e) {
                e.printStackTrace();
                goto label_29;
            }

            key = v6;
        label_29:
            if(f.encode(data.getStringExtra("data_return"), key).equals("~8t808_8A8n848r808i8d8-8w808r8l8d8}8")) {
                tv.setVisibility(0);
                bu.setVisibility(4);
                return;
            }

            Toast.makeText(this.getApplicationContext(), "one more step", 1).show();
        }
    }

    @Override  // android.support.v7.app.AppCompatActivity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(0x7F09001C);  // layout:activity
        ((Button)this.findViewById(0x7F070023)).setOnClickListener(new View.OnClickListener() {  // id:button2
            @Override  // android.view.View$OnClickListener
            public void onClick(View v) {
                Intent intent = new Intent("sctf.demo.myapplication.MAIN");
                intent.addCategory("sctf.demo.myapplication.LAUNCHER");
                t.this.startActivityForResult(intent, 1);
            }
        });
    }
}

这里使用了Intent类,找到参考链接1,可知这是安卓开发里父子组件的通信机制。因为sctf.demo.myapplication下就那几个类,我们很容易猜到子组件是s类:

package sctf.demo.myapplication;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View.OnClickListener;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class s extends AppCompatActivity {
    @Override  // android.support.v7.app.AppCompatActivity
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(0x7F09001D);  // layout:activity_main
        Button bu = (Button)this.findViewById(0x7F070022);  // id:button
        this.findViewById(0x7F07008A);  // id:textView
        bu.setOnClickListener(new View.OnClickListener() {
            @Override  // android.view.View$OnClickListener
            public void onClick(View v) {
                String s1 = "";
                String s2 = "";
                int i = 0;
                String v0 = ((EditText)this.findViewById(0x7F070037)).getText().toString();  // id:editText
                if(v0.length() == 30) {
                    while(i < 12) {
                        s1 = s1 + v0.charAt(i);
                        ++i;
                    }

                    String v1_1 = f.sctf(s1);
                    while(i < 30) {
                        s2 = s2 + v0.charAt(i);
                        ++i;
                    }

                    if(v1_1.equals("c2N0ZntXM2xjMG1l")) {
                        Intent intent = new Intent();
                        intent.putExtra("data_return", s2);
                        s.this.setResult(-1, intent);
                        s.this.finish();
                        return;
                    }

                    Toast.makeText(s.this.getApplicationContext(), "something wrong", 1).show();
                    return;
                }

                Toast.makeText(s.this.getApplicationContext(), "something wrong", 1).show();
            }
        });
    }
}

由参考链接1可知,"data_return"属性用来传递输入串的最后18个字符。

f.sctf()是base64编码,所以把"c2N0ZntXM2xjMG1l"进行base64解码,就是flag的前12个字符。

f.encode()如下:

    public static String encode(String str, String key) {
        int s = str.length();
        int c = key.length();
        StringBuilder t = new StringBuilder();
        int f;
        for(f = 0; f < s; ++f) {
            t.append(str.charAt(f));
            t.append(key.charAt(f / c));
        }
        return t.toString();
    }

所以取出"~8t808_8A8n848r808i8d8-8w808r8l8d8}8"下标为偶数的(0-indexed)字符就是flag的后18个字符。

import base64

lef = base64.b64decode("c2N0ZntXM2xjMG1l").decode()
print(lef)

enc, ky = "", ""
goal = "~8t808_8A8n848r808i8d8-8w808r8l8d8}8"
for i in range(len(goal)):
    if i % 2:
        ky += goal[i]
    else:
        enc += goal[i]
print(enc, ky)
print("ans = %s" % (lef + enc))

参考链接

  1. 安卓父子组件通信机制:onActivityResult() + Intent()https://blog.csdn.net/weixin_41008021/article/details/90346700

免费评分

参与人数 3吾爱币 +8 热心值 +3 收起 理由
Natrium + 1 我很赞同!
李佑辰 + 1 + 1 谢谢@Thanks!
正己 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Stkj 发表于 2022-7-27 08:31
挺不错,值得下载。
xuwei9663 发表于 2022-8-3 21:21
Natrium 发表于 2022-8-4 00:02
 楼主| hans7 发表于 2022-8-4 01:26

可以实操一遍,往往能有所收获(我觉得最难的还是装软件qwq)。
如果还是不懂就放弃这题,补上相关的软件和基础知识以后再回来看,就发现它变简单了。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 13:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表