攻防世界 XCTF 【Mobile】基础 android

首先下载 apk,然后使用 JADX 直接反编译,然后保存一下,使用 IDEA 打开即可

解法 一

可以看到,主 activity 是 MainActivity。我们安装 apk 后打开图像界面对照代码看看。

java 复制代码
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.acticity_main_1);
    this.passWord = (EditText) findViewById(R.id.passWord);
    this.login = (Button) findViewById(R.id.button);
    this.login.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf02.MainActivity.1
        @Override // android.view.View.OnClickListener
        public void onClick(View v) {
            String str = MainActivity.this.passWord.getText().toString();
            Check check = new Check();
            if (check.checkPassword(str)) {
                Toast.makeText(MainActivity.this, "Good,Please go on!", 0).show();
                Intent intent = new Intent(MainActivity.this, MainActivity2.class);
                MainActivity.this.startActivity(intent);
                MainActivity.this.finish();
                return;
            }
            Toast.makeText(MainActivity.this, "Failed", 0).show();
        }
    });
}

这里可以看到,当我们点击按钮的时候,系统会获取我们输入的字符串,然后放到 checkPassword() 这个函数里去,如果检测通过的话,就会开启 MainActivity2。

那么我们看一下 checkPassword() 是什么

java 复制代码
public static boolean checkPassword(String str) {
    char[] pass = str.toCharArray();
    if (pass.length != 12) {
        return false;
    }
    for (int len = 0; len < pass.length; len++) {
        pass[len] = (char) (((255 - len) - 100) - pass[len]);
        if (pass[len] != '0' || len >= 12) {
            return false;
        }
    }
    return true;
}

简单看看,调试一下,其实也不难,就是控制必须是 12 长度,然后每一位字符都必须经过处理后是 '0',其实就是一个一元一次方程,简单写个逆函数即可:

java 复制代码
public static void main(String[] args) {
    char[] pass = new char[12];

    for(int i=0; i<12; i++){
        pass[i] = (char) ((255 - i - 100) - 48);
    }

    System.out.println(Arrays.toString(pass));

}

跑一遍就能得出答案了:

java 复制代码
kjihgfedcba`

OK,输入密码后就进入了第二个页面,我们对照代码看看需要干什么。

java 复制代码
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main_2);
    init();
    this.button.setOnClickListener(new View.OnClickListener() { 
        @Override // android.view.View.OnClickListener
        public void onClick(View v) {
            String str = MainActivity2.this.editText.getText().toString();
            Intent intent = new Intent(str);
            MainActivity2.this.sendBroadcast(intent);
        }
    });
}

可以看到,当点击按钮的时候,获取收入的文本的值,然后发送广播。

发送广播?为啥要发送广播呢?发送广播干啥呢?

好吧,其实在看 AndroidManifest.xml 的时候,还可以看到这里注册了一个广播接受者 receiver 实现类是 GetAndChange,接受的关键词是 android.is.very.fun

也就是说,广播的关键字是 android.is.very.fun

那么我们输入android.is.very.fun就行了

确认即可,flag 就出来了

解法二

我们这里直接去看看这个接受广播的类,内部是如何实现的呢?

java 复制代码
public class GetAndChange extends BroadcastReceiver {
    @Override // android.content.BroadcastReceiver
    public void onReceive(Context context, Intent intent) {
        Intent intent1 = new Intent(context, NextContent.class);
        context.startActivity(intent1);
    }
}

当接受广播后,开启一个 activiye ,目标类是 NextContent

那么看看,NextContent 类如何实现的

java 复制代码
public class NextContent extends AppCompatActivity {
    ImageView imageView;
    
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_next_content);
        init();
        Change();
    }

    public void init() {
        this.imageView = (ImageView) findViewById(R.id.imageview);
    }

    public void Change() {
        String strFile = getApplicationContext().getDatabasePath("img.jpg").getAbsolutePath();
        try {
            File f = new File(strFile);
            if (f.exists()) {
                f.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            InputStream is = getApplicationContext().getResources().getAssets().open("timg_2.zip");
            FileOutputStream fos = new FileOutputStream(strFile);
            byte[] buffer = new byte[1024];
            while (true) {
                int count = is.read(buffer);
                if (count <= 0) {
                    break;
                }
                fos.write(buffer, 0, count);
            }
            fos.flush();
            fos.close();
            is.close();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        this.imageView.setImageBitmap(BitmapFactory.decodeFile(strFile));
    }
}

主要看 Change() 方法,这里新建一个 img.jpg 的图像对象,然后读取资源 timg_2.zip 的内容,写到 img.jpg 中去,然后显示这个图片就完事了。

好吧,也就是说我们完全可以自己去改个文件名就行了。

直接在反编译的文件内容中找到 /resources/assets/timg_2.zip 重命名为 img.jpg 即可

解法 三

由解法一可得,其实只要发起一个广播,然后广播的关键词为 android.is.very.fun ,软件自动就展示 falg 了,那么使用 adb 发起一个广播。

打开 app ,然后使用命令即可

java 复制代码
./adb shell am broadcast -a android.is.very.fun
相关推荐
程序员清洒2 小时前
CANN模型安全:从对抗防御到隐私保护的全栈安全实战
人工智能·深度学习·安全
秋邱2 小时前
不仅是极速:从 CANN SHMEM 看 AIGC 集群通信的“安全微操”艺术
安全·aigc
初恋叫萱萱2 小时前
CANN 生态安全加固指南:构建可信、鲁棒、可审计的边缘 AI 系统
人工智能·安全
麦聪聊数据3 小时前
为何通用堡垒机无法在数据库运维中实现精准风控?
数据库·sql·安全·低代码·架构
m0_466525294 小时前
绿盟科技风云卫AI安全能力平台成果重磅发布
大数据·数据库·人工智能·安全
晚霞的不甘5 小时前
守护智能边界:CANN 的 AI 安全机制深度解析
人工智能·安全·语言模型·自然语言处理·前端框架
枷锁—sha5 小时前
【SRC】SQL注入快速判定与应对策略(一)
网络·数据库·sql·安全·网络安全·系统安全
数字护盾(和中)5 小时前
信创生态 + 国密算法 筑牢数字安全韧性根基
安全
devmoon6 小时前
在 Polkadot 上部署独立区块链Paseo 测试网实战部署指南
开发语言·安全·区块链·polkadot·erc-20·测试网·独立链
成茂峰6 小时前
软考高级·系统架构设计师 | 四、信息技术安全知识
安全·信息安全·系统架构·架构设计师