吾爱新年题目Android01
来玩玩新年题目Android的第一题:抓小猫咪。
体验
打开app之后是这样的: 尝试捕捉猫猫。
运气真好,居然抓到了。app开始白屏,我点击了一下屏幕,居然是一个在播放视频,我继续等待视频播放完成。
居然是它。
继续等待之后。就弹出了flag了。
代码分析
环境:root的手机,macOS,frida,jadx。
抓猫猫有点运气的,看看apk的逻辑。
jdax打开apk。
打开app的第一个页面,就是刚刚打开apk后的页面,不要动。
使用命令dump
下当前的activity栈
信息,看看当前的页面是哪个activity。
Android低版本,应该是10以下,可以尝试用这个命令,我是用的macOS或者Ubuntu,win不支持grep
命令需要安装一个grep支持插件
adb shell dumpsys window | grep mFocusedApp
大于等于Android10,使用这个命令:
adb shell dumpsys activity | grep -i run
执行dump之后拿到了app的包名信息和当前的activity的名字信息。
ACTIVITY com.zj.wuaipojie2024_1/.MainActivity 9c3b5be pid=21527
jdax中打开app发现了MainActivity
:
分析MainActivity
# 页面加载UI的回调函数
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
// 复制了Asset中文件,先不管
copyAssets();
// 初始化一个webview,应该加载那个抓小猫游戏
WebView webView = (WebView) findViewById(R.id.webView);
this.webView = webView;
webView.setInitialScale(100);
this.webView.getSettings().setJavaScriptEnabled(true);
this.webView.setWebViewClient(new WebViewClient());
// 这个就是小猫游戏的HTML页面,有兴趣可以看看怎么写,或者修改这个游戏直接通关
this.webView.loadUrl("file:///android_asset/index.html");
// webview和原生交互的接口定义部分
this.webView.addJavascriptInterface(new MyJavaScriptInterface(this), "AndroidInterface");
}
按照正常流程,webview
游戏抓小猫,如果成功了,就应该通知原生代码做某事,比如刚刚抓小猫成功了,开始播放视频。
this.webView.addJavascriptInterface(new MyJavaScriptInterface(this), "AndroidInterface");
这里就是表示webview
和原生
之间通信的定义,关注MyJavaScriptInterface
这个类。里面就是通信的逻辑。
MyJavaScriptInterface的代码复制出来:
public class MyJavaScriptInterface {
private Context mContext;
public MyJavaScriptInterface(Context context) {
this.mContext = context;
}
@JavascriptInterface
public void onSolverReturnValue(int i) {
if (i == -1) {
this.mContext.startActivity(new Intent(this.mContext, YSQDActivity.class));
}
}
}
代码除了构造函数之外还有一个函数:onSolverReturnValue
,有一个参数i
,下面判断i如果等于-1
就跳转
到新一个Activity:YSQDActivity
。
进入这个Activity看看做了什么事情。
1、设置页面横屏。
2、初始化一个视频播放组件,播放/data/user/0/com.zj.wuaipojie2024_1/files/ys.mp4
3、播放完成后处理flag
,最后显示在TextView上面。
也就是抓到小猫就进入这个页面自动播放视频,最后得到flag。
那如果我一直抓不到小猫怎么办,就一直无法跳转到这个YSQDActivity
页面了。
解题方案1
还记得webview和原生代码交互的类:MyJavaScriptInterface
里面有一个函数就是跳转flag
页面的。
@JavascriptInterface
public void onSolverReturnValue(int i) {
if (i == -1) {
this.mContext.startActivity(new Intent(this.mContext, YSQDActivity.class));
}
}
假设我们主动调用
这个函数,给他传递i == -1
,就可以跳了。jadx可以直接帮我们写hook代码:
拿到hook代码之后修改一下:
Java.perform(function() {
setTimeout(function() {
// 找到 MyJavaScriptInterface 类
var MyJavaScriptInterface = Java.use('com.zj.wuaipojie2024_1.MyJavaScriptInterface');
// 获取当前 Activity 实例
Java.choose('com.zj.wuaipojie2024_1.MainActivity', {
onMatch: function(instance) {
console.log("Found MainActivity instance: " + instance);
// 在这里可以对找到的实例进行操作
var myJSInterface = MyJavaScriptInterface.$new(instance);
// 主动调用函数
myJSInterface.onSolverReturnValue(-1);
},
onComplete: function() {
console.log("Search completed");
}
});
}
手机启动frida server,电脑启动脚本:
frida -U -f com.zj.wuaipojie2024_1 -l hook_hunter.js
成功进入flag页面。
解题方案2
上面是主动调用函数
,触发启动flag页面的思路,既然是这样,Android系统本身也支持通过命令行方式主动启动一个app的Activity。就好比你在某个app内有一个商品广告,点击后进入某个购物app的商品详情这个流程。
要进入第三方app的某个Activity需要知道最简单的2个参数,目标app的包名
,Activity的全路径
。
app包名:com.zj.wuaipojie2024_1
flag的Activity路径:com.zj.wuaipojie2024_1.YSQDActivity
adb命令是这样的:adb shell am start -n com.zj.wuaipojie2024_1/com.zj.wuaipojie2024_1.YSQDActivity
终端执行命令之后遇到这样错误
adb shell am start -n com.zj.wuaipojie2024_1/com.zj.wuaipojie2024_1.YSQDActivity
Starting: Intent { cmp=com.zj.wuaipojie2024_1/.YSQDActivity }
Exception occurred while executing 'start':
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x10000000 cmp=com.zj.wuaipojie2024_1/.YSQDActivity } from null (pid=26521, uid=2000) not exported from uid 10114
at com.android.server.wm.ActivityTaskSupervisor.checkStartAnyActivityPermission(ActivityTaskSupervisor.java:1047)
at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:975)
at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:665)
at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1201)
at com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(ActivityTaskManagerService.java:1173)
at com.android.server.am.ActivityManagerService.startActivityAsUserWithFeature(ActivityManagerService.java:2926)
at com.android.server.am.ActivityManagerShellCommand.runStartActivity(ActivityManagerShellCommand.java:562)
at com.android.server.am.ActivityManagerShellCommand.onCommand(ActivityManagerShellCommand.java:193)
at com.android.modules.utils.BasicShellCommandHandler.exec(BasicShellCommandHandler.java:97)
at android.os.ShellCommand.exec(ShellCommand.java:38)
at com.android.server.am.ActivityManagerService.onShellCommand(ActivityManagerService.java:8609)
at android.os.Binder.shellCommand(Binder.java:950)
at android.os.Binder.onTransact(Binder.java:834)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:5106)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2498)
at android.os.Binder.execTransactInternal(Binder.java:1184)
at android.os.Binder.execTransact(Binder.java:1143)
错误原因:java.lang.SecurityException: Permission Denial
权限不够,OK,提升权限
就行了。
adb shell
su
# 进入shell之后就不用adb shell了
am start -n com.zj.wuaipojie2024_1/com.zj.wuaipojie2024_1.YSQDActivity
# 看到下面提示,观察app,可以看到进入播放视频页面
Starting: Intent { cmp=com.zj.wuaipojie2024_1/.YSQDActivity }
最后
1、直接玩游戏抓小猫挺好玩的。
2、通过分析代码找到flag需要Android的基础知识,组件,页面的常用逻辑。
3、可以通过am命令快速进入一个Activity,注意权限问题。第二天同理秒过。