No.1
环境配置
1.SDK Platform Tools配置
Android SDK Platform-Tools 是 Android SDK 的一个组件。它包含与 Android 平台进行交互的工具,主要是 adb 和 fastboot。
-
Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作,例如安装和调试应用。adb 提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。
-
想要解锁设备的引导加载程序并为其刷入新的系统映像,则需要 f•••••••••astboot。
参考链接:https://developer.android.com/studio/releases/platform-tools?hl=zh-cn
使用adb命令和手机进行交互,需要开启usb调试模式。
b uninstall : 卸载 Android 设备上的应用。
设备和连接管理
adb devices: 列出连接到计算机的所有 Android 设备和模拟器。
adb connect <IP>:<port>: 连接到一个网络上的 Android 设备。
文件和目录操作
adb pull <remote> <local>: 从 Android 设备复制文件或目录到本地系统。
adb push <local> <remote>: 将文件或目录从本地系统复制到 Android 设备。
应用管理
adb install <apk>: 在 Android 设备上安装 APK 文件。
adb uninstall <package>: 卸载 Android 设备上的应用。
adb shell pm list packages: 列出设备上所有已安装的包名。
Shell 访问和命令执行
adb shell: 在 Android 设备上打开一个 shell 会话。
adb shell <command>: 在 Android 设备上执行一个 shell 命令。
日志和调试
adb logcat: 查看 Android 设备的实时日志输出。
端口转发和网络
adb forward <local> <remote>: 在本地系统和 Android 设备之间转发端口。
adb reverse <local> <remote>: 在 Android 设备和本地系统之间反向转发端口。
输入模拟
adb shell input text <text>: 模拟输入文本。
系统和进程
adb shell ps: 列出设备上的进程。
adb shell top: 查看设备上的实时进程信息。
adb shell dumpsys: 获取设备系统服务的诊断输出。
重启设备
adb reboot: 重启 Android 设备。
adb reboot bootloader: 重启到 bootloader 模式。
备注:如果出现usb连接设备后,执行adb device无法看到设备信息
在开发者选项,将默认usb配置修改为文件传输模式
当然,adb的命令用法远不止如此,大家感兴趣的可以去查看官方文档:
https://developer.android.com/studio/command-line/adb?spm=wolai.workspace.0.0.46c433dcMbL8sD&hl=zh-cn#shellcommands
adb无法识别到模拟器设备:
https://blog.csdn.net/lovedingd/article/details/111039444?spm=wolai.workspace.0.0.46c433dcMbL8sD
,我是
No.2
Google手机刷机及root
小米。vivo,oppo, 一加:root刷机
谷歌系列手机刷机及root
工具准备
platform-tools:
https://developer.android.google.cn/studio/releases/platform-tools?spm=wolai.workspace.0.0.215433dcGG9vub
系统镜像
https://developers.google.com/android/images?spm=wolai.workspace.0.0.215433dcGG9vub#sailfish
TWRP
https://twrp.me/Devices/?spm=wolai.workspace.0.0.215433dcGG9vub
刷入系统
-
解压镜像包
2.拷贝platform-tools至镜像包文件夹
将platform-tools解压后拷贝到镜像包文件夹
3. 开发者选项中打开usb调试模式
4. 进入手机bootloader模式
1) 通过命令进入:
adb reboot bootloader
2) 关机后,同时按住开机键+音量下键不放,直至进入bootloader模式
5. 点击镜像包文件夹的flash-all.sh
flash-all.bat、flash-all.sh根据对应的系统选择
脚本执行完成后,即可开机进入新刷的系统。
刷入TWRP并root
-
打开开发者选项,打开usb调试模式
设置-系统-关于手机-版本号,连续点击5次版本号,即可打开开发者选项
然后进入开发者选项打开usb调试模式。
-
下载magisk并push到手机
将apk后缀改为zip后拷贝到手机sdcard目录
-
https://github.com/topjohnwu/Magisk/releases/download/v23.0/Magisk-v23.0.apk?spm=wolai.workspace.0.0.215433dcGG9vub&file=Magisk-v23.0.apk
3. 进入bootloader刷入twrp
fastboot flash recovery twrp.img (搜一下对应手机型号对应的这条命令,比如pixel系列就是fastboot boot twrp.img) Nexus
4. 刷入magisk
. 进入recovery模式,选择install,找到magisk.zip
5. 重启手机后即完成root
如果遇到提示安装包不完整,长按magisk图标卸载后,重新直接安装apk文件即可
6.以下是另一种刷入magisk进行root的方法
1. 提取镜像包中的boot.img拷贝至手机目录
2.在magisk Manager界面点magisk旁边的安装,选择并修补一个文件,选中boot.img 开始
3. 刷入成功后,将生成的/sdcard/magisk_patched.img文件拉出到电脑
adb pull /storage/emulated/0/Download/magisk_patched-23000_g1oMm.img ./
4. 再次进入bootloader
adb reboot bootloader
5. fastboot flash boot magiskxxx.img
6. 重启
Pixel3 无法输入twrp的情况下刷入Magisk
https://daily.elepover.com/2021/05/19/android-s/index.html?spm=wolai.workspace.0.0.46c4115fhAsevC
模拟器刷入面具:https://blog.csdn.net/Ruaki/article/details/135580772
No.3
常用工具安装
3.1 Android Killer
https://down.52pojie.cn/Tools/Android_Tools/?spm=wolai.workspace.0.0.46c4115fhAsevC
"Android Killer" 是一个用于 Android 应用逆向工程和分析的工具。它提供了一个图形用户界面(GUI),使得分析人员和开发人员能够更容易地进行 Android 应用的逆向工程,它提供了一种简单的方法来分析、编辑和重新打包 APK 文件,而无需深入了解 Android 的底层实现。以下是一些 Android Killer 工具的主要特点:
-
反编译:它可以反编译 APK 文件,将其转换为更易于理解和分析的格式(例如,Smali 代码)。
-
代码编辑:你可以直接在工具中编辑 Smali 代码,并将其重新编译为 APK 文件。
-
签名工具:它包含 APK 签名工具,允许你轻松地为你的应用签名。
-
调试:它提供了调试功能,帮助你分析和理解应用的运行时行为。
-
资源编辑:你可以编辑 APK 文件中的资源文件,例如图片、布局和字符串。
安装配置注意点
1)JDK环境配置选择JDK8版本
2)APKTool官网下载最新版,替换默认版本
https://github.com/iBotPeaches/Apktool?spm=wolai.workspace.0.0.46c4115fhAsevC
3.2 jadx
https://github.com/skylot/jadx/releases/tag/v1.4.7?spm=wolai.workspace.0.0.46c4115fhAsevC&file=v1.4.7
jadx(Java Decompiler)是一个开源的命令行和图形界面工具,用于将 Android 的 DEX(Dalvik Executable)和 APK(Android Package)文件反编译成人类可读的 Java 源代码。这个工具在安全研究员和开发人员中很受欢迎,因为它允许他们查看和理解 Android 应用程序的源代码。
以下是 jadx 的一些主要特点:
-
反编译到 Java 源代码
可以将 DEX 和 APK 文件反编译成较为清晰的 Java 源代码,使得分析人员能够理解和分析 Android 应用的工作原理。(交叉引用、全局搜索、frida/xp代码片段)
-
图形用户界面和命令行工具
提供了一个图形用户界面(GUI)版本,允许用户在一个友好的界面中浏览反编译的代码。同时,它也提供了一个命令行工具,方便在脚本和自动化流程中使用。
-
跨平台
是用 Java 编写的,因此它是跨平台的,可以在 Windows、Linux 和 macOS 上运行。
-
开源
是一个开源工具,这意味着任何人都可以查看其源代码,学习它是如何工作的,并根据需要进行修改或扩源。
-
高级代码优化
不仅仅是一个简单的反编译工具,它还尽可能地进行代码优化,以生成更易于理解的 Java 代码。
-
资源和清单查看
除了代码外,也允许用户查看 APK 文件中的资源(例如图片、布局文件等)和 AndroidManifest.xml 文件。
可以便捷的生成frida/xposed代码片段
直接反编译dex时,建议关闭以下选项:
3.3 jeb
JEB是一款付费工具,JEB 提供了一个强大的插件体系,用户可以编写自己的插件来扩展 JEB 的功能。
启动脚本中增加以下代码,指定JDK17运行路径。
rem Specify the path to the Java runtime
set JAVA="D:SoftInstallJEBJDK17Javajdk-17binjava.exe"
if exist %JAVA% goto :runinst
jadx反编译效果:
package c8;
import android.content.Context;
import android.text.TextUtils;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebSettings;
import ca.c;
import cn.jpush.android.service.WakedResultReceiver;
import com.tech.hope.lottery.commen.f;
import fb.b;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import okhttp3.Cache;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import za.d0;
import za.r;
/* compiled from: CookieManager.java */
/* loaded from: classes2.dex */
public class a {
/* renamed from: f reason: collision with root package name */
private static a f6755f;
/* renamed from: a reason: collision with root package name */
private eb.a f6756a;
/* renamed from: b reason: collision with root package name */
private Interceptor f6757b;
/* renamed from: d reason: collision with root package name */
private Context f6759d;
/* renamed from: e reason: collision with root package name */
private HttpLoggingInterceptor f6760e = new HttpLoggingInterceptor();
/* renamed from: c reason: collision with root package name */
private f f6758c = f.k();
/* JADX INFO: Access modifiers changed from: package-private */
/* compiled from: CookieManager.java */
/* renamed from: c8.a$a reason: collision with other inner class name */
/* loaded from: classes2.dex */
public class C0102a implements Interceptor {
/* renamed from: a reason: collision with root package name */
final /* synthetic */ Context f6761a;
C0102a(Context context) {
this.f6761a = context;
}
/* JADX WARN: Removed duplicated region for block: B:104:0x03b0 */
/* JADX WARN: Removed duplicated region for block: B:105:0x03eb */
/* JADX WARN: Removed duplicated region for block: B:47:0x025a A[Catch: Exception -> 0x02f9, TRY_LEAVE, TryCatch #4 {Exception -> 0x02f9, blocks: (B:45:0x0254, B:47:0x025a), top: B:115:0x0254 }] */
@Override // okhttp3.Interceptor
/*
Code decompiled incorrectly, please refer to instructions dump.
To view partially-correct code enable 'Show inconsistent code' option in preferences
*/
public okhttp3.Response intercept(okhttp3.Interceptor.Chain r29) throws java.io.IOException {
/*
Method dump skipped, instructions count: 1046
To view this dump change 'Code comments level' option to 'DEBUG'
*/
throw new UnsupportedOperationException("Method not decompiled: c8.a.C0102a.intercept(okhttp3.Interceptor$Chain):okhttp3.Response");
}
}
private a(Context context) {
this.f6759d = context;
d(context);
h(context);
}
jeb反编译效果
package c8;
import android.content.Context;
import android.text.TextUtils;
import android.webkit.CookieManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebSettings;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tech.hope.lottery.commen.f;
import fb.b;
import hb.d;
import hb.e;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
import okhttp3.Interceptor.Chain;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request.Builder;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import okhttp3.logging.HttpLoggingInterceptor;
import y7.c;
import za.d0;
import za.t;
public class a {
private eb.a a;
private Interceptor b;
private f c;
private Context d;
private HttpLoggingInterceptor e;
private static a f;
private a(Context context0) {
this.e = new HttpLoggingInterceptor();
this.c = f.k();
this.d = context0;
this.d(context0);
this.h(context0);
}
private void d(Context context0) {
this.b = new Interceptor() {
@Override // okhttp3.Interceptor
public Response intercept(Chain interceptor$Chain0) throws IOException {
HashMap hashMap1;
String s3;
int v1;
Integer integer2;
JSONObject jSONObject0;
Builder request$Builder2;
HttpUrl httpUrl1;
Builder request$Builder1;
Integer integer1;
String[] arr_s = d0.c().split(",");
Request request0 = interceptor$Chain0.request();
Builder request$Builder0 = request0.newBuilder();
request$Builder0.removeHeader("User-Agent").addHeader("User-Agent", a.f(context0));
request$Builder0.addHeader("model", arr_s[0]);
Integer integer0 = (int)1;
request$Builder0.addHeader("carrier", arr_s[1]);
request$Builder0.addHeader("systemVer", arr_s[2]);
request$Builder0.addHeader("sdk", arr_s[3]);
request$Builder0.addHeader("deviceId", d0.a(a.this.d));
request$Builder0.addHeader("SKEY", d0.b(a.this.d));
request$Builder0.addHeader("ver", d0.d(a.this.d));
request$Builder0.addHeader("rType", "3");
request$Builder0.addHeader("tpl", "1");
if((request0.method().equals("POST")) && a.this.c != null && a.this.c.s() != null) {
request$Builder0.addHeader("token", a.this.c.s());
}
if(t.a(context0) == t.a) {
request$Builder0.cacheControl(CacheControl.FORCE_CACHE).build();
}
String s = e.b(24);
HttpUrl httpUrl0 = request0.url();
long v = System.currentTimeMillis();
if((request0.method().equalsIgnoreCase("POST")) && (c.d.contains(httpUrl0.host()))) {
RequestBody requestBody0 = request0.body();
HashMap hashMap0 = new HashMap();
hashMap0.put("t", Long.valueOf(v));
integer1 = integer0;
if(requestBody0 == null) {
request$Builder1 = request$Builder0;
httpUrl1 = httpUrl0;
hashMap0.put("s", "");
hashMap0.put("d", "");
hashMap0.put("k", "");
}
else {
requestBody0.writeTo(new okio.f());
request$Builder1 = request$Builder0;
httpUrl1 = httpUrl0;
hashMap0.put("s", e.a(v, "", s, request0.url().encodedPath()));
hashMap0.put("d", hb.a.b(true, "", s, "12345678ABCDEFGH", "AES/CBC/PKCS5Padding"));
hashMap0.put("k", hb.c.c(d.a(s.getBytes(), c.h)));
}
String s1 = JSON.toJSONString(hashMap0);
RequestBody requestBody1 = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), s1);
request$Builder2 = request$Builder1;
request$Builder2.method(request0.method(), requestBody1);
request$Builder2.header("Content-Type", requestBody1.contentType().toString());
request$Builder2.header("Content-Length", String.valueOf(requestBody1.contentLength()));
}
else {
integer1 = integer0;
httpUrl1 = httpUrl0;
request$Builder2 = request$Builder0;
}
Response response0 = interceptor$Chain0.proceed(request$Builder2.build());
if(response0.code() == 200 && (request0.method().equalsIgnoreCase("POST")) && (c.d.contains(httpUrl1.host()))) {
String s2 = response0.body().string();
try {
if(!TextUtils.isEmpty(s2)) {
jSONObject0 = JSON.parseObject(s2);
goto label_59;
}
goto label_114;
}
catch(Exception exception0) {
integer2 = integer1;
v1 = 0;
goto label_104;
}
try {
label_59:
if(jSONObject0.containsKey("d")) {
boolean z = TextUtils.isEmpty(jSONObject0.getString("d"));
goto label_66;
}
goto label_114;
}
catch(Exception exception0) {
integer2 = integer1;
v1 = 1;
goto label_104;
}
label_66:
if(!z) {
try {
s3 = hb.a.b(false, jSONObject0.getString("d"), s, "12345678ABCDEFGH", "AES/CBC/PKCS5Padding");
}
catch(Exception exception0) {
integer2 = integer1;
v1 = 2;
goto label_104;
}
try {
String s4 = e.a(jSONObject0.getLongValue("t"), s3, s, request0.url().encodedPath());
}
catch(Exception exception0) {
integer2 = integer1;
v1 = 3;
goto label_104;
}
v1 = 4;
try {
if((TextUtils.isEmpty(s3)) && (TextUtils.isEmpty(s4))) {
v1 = 5;
}
else if(TextUtils.isEmpty(s3)) {
v1 = 6;
}
else if(TextUtils.isEmpty(s4)) {
v1 = 7;
}
if(s4.equals(jSONObject0.getString("s"))) {
goto label_112;
}
else {
hashMap1 = new HashMap();
goto label_94;
}
goto label_114;
}
catch(Exception exception0) {
integer2 = integer1;
goto label_104;
}
label_94:
integer2 = integer1;
try {
hashMap1.put("errcode", integer2);
}
catch(Exception exception0) {
goto label_104;
}
try {
hashMap1.put("errmsg", "签名错误");
s2 = JSON.toJSONString(hashMap1);
goto label_114;
}
catch(Exception exception0) {
}
label_104:
exception0.printStackTrace();
HashMap hashMap2 = new HashMap();
hashMap2.put("errcode", integer2);
hashMap2.put("errcontent", s2);
hashMap2.put("errmsg", "网路异常,请重试(" + v1 + ")");
s2 = JSON.toJSONString(hashMap2);
goto label_114;
label_112:
s2 = s3;
}
label_114:
ResponseBody responseBody0 = ResponseBody.create(s2, MediaType.parse("application/json; charset=utf-8"));
response0 = response0.newBuilder().body(responseBody0).build();
}
if(t.a(context0) != t.a) {
response0.newBuilder().header("Cache-Control", "public, max-age=" + 604800).addHeader("Cookie", "max-age=" + 604800).removeHeader("Pragma").build();
return response0;
}
response0.newBuilder().header("Cache-Control", "public, only-if-cached, max-state=" + 0x24EA00).removeHeader("Pragma").build();
return response0;
}
};
}
public static a e(Context context0) {
if(a.f == null) {
Class class0 = a.class;
synchronized(class0) {
if(a.f == null) {
a.f = new a(context0.getApplicationContext());
}
return a.f;
}
}
return a.f;
}
3.4 GDA
GJoy Dex Analyzer(GDA),亚洲第一款全交互式的现代反编译器,同时也是世界上最早实现的dalvik字节码反编译器。GDA不只是一款反编译器,同时也是一款轻便且功能强大的综合性逆向分析利器,其不依赖java且支持apk, dex, odex, oat, jar, class, aar文件的反编译, 支持python及java脚本自动化分析。
https://zhuanlan.zhihu.com/p/28354064?spm=wolai.workspace.0.0.46c4115fhAsevC
3.5 IDA pro
IDA Pro(Interactive Disassembler Professional)是一款极其流行的交互式反汇编器和调试器。它广泛用于软件逆向工程领域,特别是在分析二进制代码和开发漏洞利用方面。IDA Pro 提供了一系列强大的工具,用于分析二进制文件。
破解版下载地址:https://pan.baidu.com/s/1ZhhDevWxlNJZBT2Q4LxGQQ?pwd=52pj
以后分析安卓so层代码以及ios app 代码的时候会用到ida
3.6 面具插件
shamiko
https://github.com/LSPosed/LSPosed.github.io/releases?spm=wolai.workspace.0.0.46c4115fhAsevC
-
这是个magisk模块
-
这是在zygisk开启情况下,也可以使用的“magisk hide”。(24及以上版本的面具需要使用这个模块,因为官方取消了对magisk hide的支持,需要这个插件替代)
用途:
-
有些应用会检测系统是否已经ROOT,如果检测到ROOT,会进行提示,或干脆不让运行这个软件(如12123)。
以上情况当然是我们不愿意看到的,因此我们可以用shamiko来进行反检测,防止某个应用检测ROOT,以便在ROOT后正常使用这个软件。
Lsposed
安装方式和shamiko相同,最新版的面具推荐下载zygisk版本的lsposed使用
LSPosed 提供与传统 Xposed 框架相似的 API,以便现有的 Xposed 模块能够在 LSPosed 上运行。LSPosed 支持大多数传统的 Xposed 框架模块,允许用户利用现有的模块来修改和扩展应用的功能。LSPosed 提供了一个图形用户界面,允许用户轻松地管理和配置模块。
用途:
-
LSPosed 可以用于动态分析 Android 应用的行为,例如监视方法调用、修改方法参数和返回值等。
-
LSPosed 允许在运行时修改应用的行为,这在测试应用的安全性时非常有用。
-
LSPosed 可以用于绕过应用的一些安全检测和防护机制,例如 SSL 证书锁定、root 检测等。
lsp插件安装使用见后文
3.7 其他工具
QtScrcpy
投屏工具,方便在PC上远程操作手机以及截图等。
https://github.com/barry-ran/QtScrcpy?spm=wolai.workspace.0.0.46c4115fhAsevC
ApkMessage
解析APP
一款适用于以APP病毒分析、APP漏洞挖掘、APP开发、HW行动/红队/渗透测试团队为场景的移动端(Android、iOS)辅助分析工具,可以帮助APP开发工程师、病毒分析师、漏洞/安全研究员提高工作效率,帮助渗透测试工程师、攻击队成员/红队成员快速收集到移动端中关键的资产信息并提供基本的信息输出,如:包名(packageName)、版本(versionNameversionCode)、应用签名(Signature)、文件MD5、SDK、URL、APP漏洞等信息。
https://github.com/sulab999/AppMessenger?spm=wolai.workspace.0.0.46c4115fhAsevC
MT管理器
Android 平台文件管理 & 逆向修改神器
https://mt2.cn/guide/?spm=wolai.workspace.0.0.46c4115fhAsevC
No.4
原文始发于微信公众号(隐雾安全):Android APP——测试环境配置
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论