攻防世界 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
相关推荐
小小工匠1 小时前
Web安全 - 路径穿越(Path Traversal)
安全·web安全·路径穿越
不灭锦鲤3 小时前
ssrf学习(ctfhub靶场)
网络·学习·安全
网络研究院6 小时前
如何安全地大规模部署 GenAI 应用程序
网络·人工智能·安全·ai·部署·观点
DonciSacer10 小时前
TryHackMe 第6天 | Web Fundamentals (一)
安全
云卓科技14 小时前
无人机之数据提取篇
科技·安全·机器人·无人机·制造
山兔114 小时前
工控安全防护机制与技术
安全
HEX9CF15 小时前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
小小工匠16 小时前
加密与安全_HOTP一次性密码生成算法
算法·安全·htop·一次性密码
Tandy12356_16 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
什么鬼昵称18 小时前
Pikachu-xxe-xxe漏洞
网络·安全·xxe