首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【安卓安全】你的第一个安卓 APP

【安卓安全】你的第一个安卓 APP

作者头像
yichen
发布2025-05-26 17:45:08
发布2025-05-26 17:45:08
4080
举报

HexTree.io

HexTree 与 谷歌合作推出的安卓 APP 安全课程,希望让更多安全研究者来挖安卓 APP 的漏洞,拿来学一学安卓吧。要开始这一系列教程,首先要有 Android Studio,从这里下载:

https://developer.android.com/studio

https://app.hextree.io/map/android

创建一个APP

安装过程要挂代理!安装完成 Android Studio 后打开,选择新建项目

新建一个 Empty Views Activity 项目

名字随意起,创建好项目后找到右侧的 Device Manager 添加一个安卓虚拟机,用来跑我们的程序,点击加号按钮可以添加虚拟机

可以选择不同的安卓版本,随便选一个直接下一步即可

你的所有安卓虚拟机都在 Device Manager 中,点击启动按钮可以运行虚拟机,在上面的下拉菜单中可以选择使用哪个虚拟机运行 APP,选择好后点击旁边的启动按钮就会自动编译 APP 并在虚拟机上运行了

当然因为我们创建的是一个空的 APP 所以打开之后是默认的 Hello World 字样

来到代码部分,接下来尝试修改一下 APP 显示的内容,首先来观察一下代码,MainActivity.java 内容如下:

代码语言:javascript
复制
package com.example.myapplication1;
import android.os.Bundle;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

publicclass MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
            Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
            return insets;
        });
    }
}

Android 应用程序的入口通常是由系统启动的一个 Activity 类,如 MainActivity;onCreate() 方法在 Activity 第一次被创建时由系统调用

setContentView(R.layout.activity_main); 设置 Activity 的内容视图为 activity_main.xml 布局文件,这个文件在 res 文件夹的 layout 目录下,定义了用户界面的结构与组件,可以通过修改这个文件修改用户界面

想要操作布局中的一个文本,可以先给他指定一个 id,然后在代码中调用这个 id 显示变量等信息

代码语言:javascript
复制
TextView homeText = findViewById(R.id.my_text);
homeText.setText("Hello Yichen!");

在实际攻击中可能会需要一个按钮,当点击按钮时发起攻击,如果想添加按钮,直接在 activity_main.xml 选中 Button 往下拖到组件树中即可

修改右侧的约束宽度,直接拖拽到某个你认为合适的位置

可以为按钮添加点击监听 setOnClickListener ,当点击时进行一些操作,例如在 logcat 中输出字符串

代码语言:javascript
复制
Button homeButton = findViewById(R.id.my_button);
homeButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.i("HEXTREE", "Welcome from the Button");
    }
});

还可以添加一个变量,例如用来记录点击次数,当变量达到一个值时,做一些操作:代码中定义了一个 Intent,intent 是意图的意思,这段代码表示当 click 点击次数到 10 次后,打开一个链接,这时候安卓系统会找到可以满足我们这个意图的 APP 来打开这个链接

代码语言:javascript
复制
Button homeButton = findViewById(R.id.my_button);
homeButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.i("HEXTREE", "Welcome from the Button");
        clicknum++;
        homeText.setText(String.format("You clicked %d", clicknum));
        if(clicknum==10){
            Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.yuque.com/hxfqg9"));
            startActivity(browserIntent);
        }
    }
});

但是安卓系统怎么知道哪个应用可以用来打开什么呢?原因就是在每个应用的 AndroidManifest.xml 中有一个叫 intent-filter 的标签定义,例如 Chrome APP 的 AndroidManifest.xml 中可以找到当想要访问 https 时,会打开:

org.chromium.chrome.browser.document.ChromeLauncherActivity

如何自己编写一个 APP 实现类似上面的效果呢?首先创建一个新的 activity,我起名为 Security

在 AndroidManifest.xml 设置其 exported 为 true,这样才能让别的 APP 访问到,然后加上 intent-fliter 用来标识可以接收哪些意图,此处我们为 Security 这个 Activity 添加了一个 intent-filter,使其能够接收 SEND 类型的 Intent,当在安卓系统中使用“发送到”这个功能时就可以看到我们的 APP 啦

代码语言:javascript
复制
<activity
  android:name=".Security"
  android:exported="true" >
  <intent-filter>
    <action android:name="android.intent.action.SEND" />
    <data android:mimeType="text/plain"/>
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

在 Security 对应的布局文件 activity_security.xml 中,添加一个文本框,设置其 id 为 debug_text 并调整位置,在 Securtiy.java 的代码中使用 getIntent 函数获取数据,然后提取出来具体的 Intent 数据,将其设置为文本框中的内容

代码语言:javascript
复制
Intent receivedIntent = getIntent();
String sharedText = receivedIntent.getStringExtra(Intent.EXTRA_TEXT);
if(sharedText!=null){
    TextView debug_text = findViewById(R.id.debug_text);
    debug_text.setText("Shared: "+sharedText);
}

可以看到 share 过来的数据

使用 Build -> Build AppBundle(s) / APK(s) -> Build APK(s) 可以编译为一个 apk 文件,编译好的 app 可以在 output 文件夹找到

反编译第一个 APP

通过 jadx 这个开源工具可以很方便的将 APP 反编译,下载完后将压缩包解压,应该会得到一个 jadx-gui.exe 双击打开,将我们自己写的 app 拖进去,会进行自动的反编译,然后你就可以通过左侧的目录看到所有的信息了,比如打开 Security 这个 activity 可以看到没有经过混淆/加壳的 APP 跟看源码没啥区别

调试安卓 APP

在 Android Studio 中也可以给某一行下断点,然后点击菜单栏的 debug 按钮即可进行调试

当运行到这一行时就会断住,然后你就可以找到这个变量,右键 -> Set Value 修改变量的值

解决一个挑战

hextreeio 在 github 上分享了一个 app 源码,下载下来后使用 Android Studio 打开

阅读代码可知,在 MainActivity 中点击按钮超过 9999 次就会调用 ChallengeActivity,因此可以通过下断点,修改点击数量跳过去,来到 ChallengeActivity 后会发现有很多按钮,通过阅读源码可知,只有点击 button9 会打开 FlagActivity 其他的都会退回到 MainActivity,因此点击 button9

在 FlagActivity 阅读源码得知,需要调节滚动条到 42 的位置,然后就可以获得 flag 啦

当然这只是常规思路,源码都在你手上,你直接调用函数把 flag 打印出来就好了呀,在 FlagActivity 中找到解密 flag 相关的代码复制到 MainActivity,直接通过 text.setText(decryptFlag()); 即可将解密结果显示在界面上

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陈冠男的游戏人生 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建一个APP
    • 安装过程要挂代理!安装完成 Android Studio 后打开,选择新建项目
  • 反编译第一个 APP
  • 调试安卓 APP
  • 解决一个挑战
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档