在上一篇文章中,我记录了我对Android游戏进行反向工程的方法。但是,动手编写代码只是安全性研究的一部分。一旦发现潜在问题,我需要验证它是否确实可以利用。因此,没有办法解决实际的实时应用程序。理想情况下,这必须在具有仿真硬件的受控环境中进行。和以前一样,这主要是我为未来的自我写下来的东西,但对其他人也可能有用。
从历史上看,官方的Android仿真器几乎无法使用,这就是为什么我长期在VirtualBox中使用Androix x86图像的原因。但是,该解决方案在这里不起作用:存在问题的Android游戏包含为ARM平台编译的二进制代码,因此无法直接在x86硬件上执行。
但是请不要失望,Android 11带有内置的ARM仿真器!因此,当此游戏在x86硬件上运行时,操作系统应自动翻译ARM处理器指令,然后一切都会正常运行。听起来不错,除了在编写Android x86项目时仅提供Android 9图像而没有提供以上图像的事实。
进一步的搜索使我进入了基于Android 11的Bliss OS 14,并且可以作为Alpha版本发布。我在VirtualBox中尝试过,但安装失败。尝试直接从CD映像运行它也失败了。我的一些调查表明,安装脚本中的路径错误以及Grub的构建均已损坏。而且,甚至连升级操作系统的部件都没有改变,尽管有我的解决方法,但该操作系统仍会卡在启动系统中。本来可以在非虚拟硬件上运行的,但我对此表示强烈怀疑。我相当怀疑此“发行版”仅适用于手动安装所有内容并且对操作系统有深刻理解的人们。因此,或者开发人员与我对“ alpha版本”一词的理解不同(我的意思是至少可以使用),或者整个事情纯粹是宣传st头:“我们首先将Android 11引入台式机!”
然后,我转回Android模拟器。谁会想到,它完美地工作了!过去使我无法使用的所有问题都消失了。因此,下一节将介绍如何将此仿真器安装到您的计算机上。
无论如何,Android SDK都会大量下载。因此,建议您转到下载页面并下载Android Studio。设置起来更容易,文档也更好。
但是,就我个人而言,我不需要此IDE。我更喜欢使用命令行工具,在命令行工具中更容易获得可重复的结果,这对于自动化尤为重要。因此,对我来说,这是“仅命令行工具”下载,位于同一页面的下方。
Android SDK需要Java,但不必在系统上全局安装Java。您可以下载Java JDK并将其解压缩到系统中的任何位置。只要您在JAVA_HOME环境变量中公开其路径,所有命令行工具都将正确运行。
即使您最初安装的Android SDK除了命令行工具外,命令行工具也有望被解压缩到Android SDK的cmdline-tools / latest目录中。因此,除非您想每次都明确指定Android SDK路径,否则最好将它们放在此处。将/ path / to / sdk / cmdline-tools / latest / bin添加到PATH环境变量以使用命令。这允许运行sdkmanager安装其他组件:
这里的system-images; android-30; google_apis_playstore; x86_64是带有Play Store应用的Android 11映像(对应于API版本30)。该仿真器将自动安装,您需要将/ path / to / sdk / emulator添加到PATH中,以执行仿真器命令。
build-tools; 30.0.3和platform; android-30是必需的,以便为Android 11平台构建应用程序,需要将/path/to/sdk/build-tools/30.0.3添加到PATH中以进行APK签名命令。并且platform-tools包含adb二进制文件,因此/ path / to / sdk / platform-tools也应添加到PATH中。
现在,您可以为仿真器创建设备映像。我将图像命名为Android11,并将平板电脑用作可用的初始硬件配置。尽管此命令会建议您创建自定义硬件配置文件,但几乎不建议这样做。也就是说,除非您愿意回答一百个不相关的问题,否则每个错误都会使您重复该过程。
您仍然可以通过手动编辑〜/ .android / avd / Android11.avd / config.ini来更改硬件配置。对我来说,以下值需要调整或增加:
hw.ramSize:默认2048 MB不足以运行游戏应用程序,我将其更改为10240 MB
hw.keyboard:如果您希望使用计算机的键盘而不是屏幕上的变体,则应将其设置为yes
hw.keyboard.charmap:对于美国键盘,默认qwerty2应该可以,但是德语键盘布局为qwertz
您可以通过Play商店安装要测试的应用。但是话又说回来,您可能仍然拥有APK包,在我的例子中名为game.apk。因此,您可以直接安装它:
上一篇文章提到了公开服务。为了尝试访问它,需要通过另一个Android应用程序运行一些代码。显然,我宁愿避免使事情复杂化,那么如何构建一个最小的Android应用程序呢?
正如本博文或本博文所解释的那样,答案令人惊讶地复杂。最后,使用Gradle可能最简单。所以我下载了最新的软件包,在撰写本文时它是gradle-6.8.3-all.zip。解压缩后,您还有一个值要添加到PATH环境变量中:/ path / to / gradle / bin。现在可以使用gradle命令。
buildscript {存储库{google()jcenter()}依赖项{classpath' com.android.tools.build:gradle:4.1.0 +' }}所有专案{储存库{google()jcenter()}}应用外挂程式:' com.android.application' android {compileSdkVersion 30 buildToolsVersion' 30.0.3'}
其中大多数是通用的,只有Gradle的Android插件版本值得一提。该文档说4.1.0+是当前Gradle版本的正确插件版本。将来的Gradle版本可能在此处要求其他值。
Gradle期望使用复杂的目录结构,因此AndroidManifest.xml必须位于项目中的src / main下。我的是很基本的:
<?xml version =" 1.0" encoding =" utf-8"?> <清单xmlns:android =" http://schemas.android.com/apk/res/android" package =" com.example.test" > < application android:label =" Test app" > < activity android:name =" MainActivity" > <意图过滤器> < action android:name =" android.intent.action.MAIN" /> < category android:name =" android.intent.category.LAUNCHER" /> < / intent-filter> < / activity> < /应用程序> < / manifest>
如果将程序包ID保留为com.example.test,则必须将MainActivity.java文件放入项目的src / main / java / com / example / test子目录中。这样的事情会做:
包com.example.test;导入android.content.ComponentName;导入android.content.Intent;导入android.content.ServiceConnection;导入android.os.Bundle;导入android.os.IBinder;公共类MainActivity扩展了Activity {@Override public void onCreate(Bundle savedInstanceState){超级。 onCreate(savedInstanceState); Intent intent = new Intent();意向。 setComponent(新的ComponentName(" com.example.funnygame"," com.example.funnygame.MyFirebaseMessagingService"));意向。 setAction(" com.google.firebase.MESSAGING_EVENT");这 。 bindService(意图,新的ServiceConnection(){ ComponentName名称){}},BIND_AUTO_CREATE); }}
现在,您可以运行gradle installDebug(期望将ANDROID_HOME环境变量设置为Android SDK路径)。此命令将构建应用程序并将其自动安装到模拟器。当您运行它时,它将立即尝试从另一个应用程序连接到特定服务。也许然后它可以做一些有趣的事情。
现在我的第一次尝试没有成功。什么也没发生,从源代码中我还不太清楚为什么。因此,无法调试目标应用程序以查看发生了什么。例外:所有文档都说调试仅适用于调试版本。而且我无法确切地要求供应商向我提供其应用程序的调试版本。
幸运的是,仍然有一种方法。如果可以对Android应用程序进行反编译,则也可以对其进行修改。看来,执行此操作的最新框架是Soot,并且有一篇详细的文章介绍了如何使用它。它还提供了包含工作代码的存储库,这很有用,因为您不必从头开始编写Java代码。
Warning: Can only detect less than 5000 characters
这确实是无效的类型转换,zzt类型未实现(空)zzl接口。这是怎么工作的?我只能想象这个特定的结构使用了无效的字节码,这意味着重新编译时会出错。从未使用在此初始化的zzao变量。
但是由于我们正在重写代码,因此我们可以简单地删除此分配!在车身变压器上添加以下代码即可完成这项工作:
如果(className。等于(" com.google.android.gms.games.Games")&& body。getMethod()。getName()。等于("< clinit>& #34;)){身体。 getUnits()。 removeIf(unit-> {if(Unit instanceof AssignStmt){字符串typeName =((AssignStmt)unit)。getLeftOp()。getType()。toString(); if(typeName。等于(" com.google。 android.gms.games.appcontent.zzl"))返回true;}返回false;}); }
最后一点是对修改后的APK进行签名。测试证书足以将应用程序安装到模拟器中,但是您必须首先卸载原始应用程序。我使用以下命令来生成证书(keytool是Java安装的一部分):
keytool -genkey -v -keystore test.jks -alias test -keyalg RSA \ -keysize 2048 -keypass 123456 -validity 10000
现在,签名是从Android SDK运行以下两个命令的问题:
运行adb install game-signed.apk现在可以安装修改后的应用程序,它应该会产生漂亮的调试消息,这些消息在adb logcat输出中可见。