1、apktool_2.4.1.jar--用于反编和打包apk
2、jadx-gui-1.4.5--用于查看 apk 反编译源码,方便快速导出查找
3、Linux环境安装 zipalign 、apksigner--用于对齐和重新签名
1、反编后,啥也不改,直接再打包回 apk,z4 对齐并签名后安装失败,错误原因为
提示 so 未对齐,试了很多方法一直不都行,后来验证了下发现这货根本不是so,而是 jar 文件,这一招正是为了防止反编的手段。
file libsgmain.so: Java archive data (JAR)
将重打包后的 apk 再解压开,强制 so 不压缩,然后再进行对齐和签名即可,完整指令步骤如下
最终得到的 aligned.apk 就可以成功安装
先将 apk 通过 apktool 反编出来备用,一会方便修改 smali 代码 然后在 jadx-gui 中打开 apk,打开工程后,点击文件保存将所有代码保存出来,然后 cp 到 linux 下,这样方便快速查找关键词 比如界面显示未授权的设备,可以通过 grep 未授权 ./ -nir 快速搜索到具体位置,然后在 jadx-gui 中快速定位代码位置。
1、com.a.a.a.a.a.booleanValue() 为 false 则直接忽略检查,可能是为了测试模式留的 2、为 true,则检查指定包名的apk对应的 SHA-256 签名值是否和固定值相等,一致则认为设备已授权
看到蓝牙绑定时报错 log 如下
对应代码为先获取 BluetoothManager getAdapter 通过 getAddress 方法获取 mac,
取不到则再进行反射调用,调用时抛出权限异常
Caused by: java.lang.SecurityException: Need LOCAL_MAC_ADDRESS permission: Neither user 10032 nor current process has android.permission.LOCAL_MAC_ADDRESS.
高版本安卓此权限必须是系统 app 才能拥有,可以修改 smali 代码直接走下面的 Secure 查询 bluetooth_address 即可
扫码绑定后本地开始生成付款条码
调用对应 so 生成条码
本文内容仅用于技术研究与学习交流目的,不涉及任何商业用途。 文中所提及的技术手段、工具使用及分析过程均基于开源或公开信息进行探讨,不代表鼓励或支持任何非法行为。 若您使用相关技术从事违法行为,后果自负,与本文作者无关。 如有侵权,联系删文。
反编指令
java -jar apktool_2.4.1.jar d .\test.apk -o test
打包指令
java -jar apktool_2.4.1.jar b test -o testPack.apk
反编指令
java -jar apktool_2.4.1.jar d .\test.apk -o test
打包指令
java -jar apktool_2.4.1.jar b test -o testPack.apk
D NativeLibraryHelper: Library 'libsgmain.so' is not page-aligned - will not be able to open it directly from apk.
W NativeHelper: Failure copying native libraries [errorCode=-2]
D NativeLibraryHelper: Library 'libsgmain.so' is not page-aligned - will not be able to open it directly from apk.
W NativeHelper: Failure copying native libraries [errorCode=-2]
java -jar apktool_2.4.1.jar b .\test -o unsigned.apk
然后再到 linux 环境下处理
unzip unsigned.apk -d apk_unpacked/
cd apk_unpacked/
zip -r -0 ../repack-unsigned.apk *
zipalign -f -v -p 4 repack-unsigned.apk aligned.apk
apksigner sign --ks test.jks --ks-key-alias xxxx -ks-pass pass:xxxx ./aligned.apk
java -jar apktool_2.4.1.jar b .\test -o unsigned.apk
然后再到 linux 环境下处理
unzip unsigned.apk -d apk_unpacked/
cd apk_unpacked/
zip -r -0 ../repack-unsigned.apk *
zipalign -f -v -p 4 repack-unsigned.apk aligned.apk
apksigner sign --ks test.jks --ks-key-alias xxxx -ks-pass pass:xxxx ./aligned.apk
private void c() {
if (com.xpay.watch.utils.a.a(this)) {
getWindow().addFlags(128);
setContentView(com.xpay.watch.utils.g.a(this, R.layout.activity_watch_main));
com.xpay.android.watchsdk.g.a().g();
if (!com.xpay.android.watchsdk.l.a().e()) {
com.xpay.android.watchsdk.g.a().a(com.xpay.watch.utils.h.a(), com.xpay.watch.utils.h.b(), null);
try {
com.xpay.android.watchsdk.ble.d.a().f();
} catch (Throwable th) {
com.xpay.android.phone.inside.log.api.b.a(th);
}
this.a.postDelayed(this.h, 200L);
com.xpay.android.watchsdk.l.a().l();
} else {
d();
this.a.postDelayed(this.i, 200L);
}
} else {
DialogUtil.a aVar = new DialogUtil.a(this);
aVar.a(DialogUtil.DialogType.SINGLE_BUTTON);
aVar.a(getString(R.string.dlg_authorization_check_failed_title));
aVar.b(getString(R.string.dlg_authorization_check_failed_tips));
aVar.c("c-" + com.xpay.watch.utils.h.a() + " m-" + Build.MODEL);
aVar.a(new h(this));
DialogUtil.a(aVar);
}
public static boolean a(Context context) {
if (com.a.a.a.a.a.booleanValue()) {
String[] split = h.f().split(",");
String[] split2 = h.e().split(",");
if (split2 == null || split2.length <= 0) {
return false;
}
for (int i = 0; i < split2.length; i++) {
Log.w("xpay_watch", "packageName |" + split2[i]);
if (a(context, split2[i], split)) {
return true;
}
}
return false;
}
return true;
}
private static boolean a(Context context, String str, String[] strArr) {
List<String> a2 = a(context, str);
if (a2 == null || a2.size() <= 0) {
return false;
}
for (String str2 : strArr) {
String trim = str2.trim();
Log.w("xpay_watch", str + " " + a2.get(0).toUpperCase() + trim.toUpperCase());
if (TextUtils.equals(a2.get(0).toUpperCase(), trim.toUpperCase())) {
return true;
}
}
return false;
}
private static List<String> a(Context context, String str) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(str, 64);
if (packageInfo != null) {
Signature[] signatureArr = packageInfo.signatures;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
ArrayList arrayList = new ArrayList();
for (Signature signature : signatureArr) {
byte[] digest = messageDigest.digest(signature.toByteArray());
StringBuilder sb = new StringBuilder((digest.length * 3) - 1);
int length = digest.length - 1;
for (int i = 0; i <= length; i++) {
byte b = digest[i];
sb.append(a[(b & 240) >> 4]);
sb.append(a[b & 15]);
if (i < length) {
sb.append(':');
}
}
String sb2 = sb.toString();
arrayList.add(sb2);
com.xpay.android.phone.inside.log.api.b.a("package |" + str + "| fingerprint: " + sb2);
Log.w("xpay_watch", "package |" + str + "| fingerprint: " + sb2);
}
return arrayList;
}
return null;
} catch (Throwable th) {
th.printStackTrace();
return null;
}
}
private void c() {
if (com.xpay.watch.utils.a.a(this)) {
getWindow().addFlags(128);
setContentView(com.xpay.watch.utils.g.a(this, R.layout.activity_watch_main));
com.xpay.android.watchsdk.g.a().g();
if (!com.xpay.android.watchsdk.l.a().e()) {
com.xpay.android.watchsdk.g.a().a(com.xpay.watch.utils.h.a(), com.xpay.watch.utils.h.b(), null);
try {
com.xpay.android.watchsdk.ble.d.a().f();
} catch (Throwable th) {
com.xpay.android.phone.inside.log.api.b.a(th);
}
this.a.postDelayed(this.h, 200L);
com.xpay.android.watchsdk.l.a().l();
} else {
d();
this.a.postDelayed(this.i, 200L);
}
} else {
DialogUtil.a aVar = new DialogUtil.a(this);
aVar.a(DialogUtil.DialogType.SINGLE_BUTTON);
aVar.a(getString(R.string.dlg_authorization_check_failed_title));
aVar.b(getString(R.string.dlg_authorization_check_failed_tips));
aVar.c("c-" + com.xpay.watch.utils.h.a() + " m-" + Build.MODEL);
aVar.a(new h(this));
DialogUtil.a(aVar);
}
public static boolean a(Context context) {
if (com.a.a.a.a.a.booleanValue()) {
String[] split = h.f().split(",");
String[] split2 = h.e().split(",");
if (split2 == null || split2.length <= 0) {
return false;
}
for (int i = 0; i < split2.length; i++) {
Log.w("xpay_watch", "packageName |" + split2[i]);
if (a(context, split2[i], split)) {
return true;
}
}
return false;
}
return true;
}
private static boolean a(Context context, String str, String[] strArr) {
List<String> a2 = a(context, str);
if (a2 == null || a2.size() <= 0) {
return false;
}
for (String str2 : strArr) {
String trim = str2.trim();
Log.w("xpay_watch", str + " " + a2.get(0).toUpperCase() + trim.toUpperCase());
if (TextUtils.equals(a2.get(0).toUpperCase(), trim.toUpperCase())) {
return true;
}
}
return false;
}
private static List<String> a(Context context, String str) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(str, 64);
if (packageInfo != null) {
Signature[] signatureArr = packageInfo.signatures;
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
ArrayList arrayList = new ArrayList();
for (Signature signature : signatureArr) {
byte[] digest = messageDigest.digest(signature.toByteArray());
StringBuilder sb = new StringBuilder((digest.length * 3) - 1);
int length = digest.length - 1;
for (int i = 0; i <= length; i++) {
byte b = digest[i];
sb.append(a[(b & 240) >> 4]);
sb.append(a[b & 15]);
if (i < length) {
sb.append(':');
}
}
String sb2 = sb.toString();
arrayList.add(sb2);
com.xpay.android.phone.inside.log.api.b.a("package |" + str + "| fingerprint: " + sb2);
Log.w("xpay_watch", "package |" + str + "| fingerprint: " + sb2);
}
return arrayList;
}
return null;
} catch (Throwable th) {
th.printStackTrace();
return null;
}
}
14:05:57.870 9853 BluetoothGattServer D onServiceAdded() - handle=40 uuid=00003802-0000-1000-8000-00805f9b34fb status=0
14:05:57.874 9853 BluetoothGattServer W Unhandled exception in callback
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toUpperCase()' on a null object reference
at com.xpay.android.watchsdk.ble.d.b(SourceFile:542)
at com.xpay.android.watchsdk.ble.d.a(SourceFile:44)
at com.xpay.android.watchsdk.ble.d$a.onServiceAdded(SourceFile:441)
at android.bluetooth.BluetoothGattServer$1.onServiceAdded(BluetoothGattServer.java:136)
at android.bluetooth.IBluetoothGattServerCallback$Stub.onTransact(IBluetoothGattServerCallback.java:85)
at android.os.Binder.execTransact(Binder.java:723)
14:06:13.725 9853 zygote I Debugger is no longer active
14:05:57.870 9853 BluetoothGattServer D onServiceAdded() - handle=40 uuid=00003802-0000-1000-8000-00805f9b34fb status=0
14:05:57.874 9853 BluetoothGattServer W Unhandled exception in callback
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toUpperCase()' on a null object reference
at com.xpay.android.watchsdk.ble.d.b(SourceFile:542)
at com.xpay.android.watchsdk.ble.d.a(SourceFile:44)
at com.xpay.android.watchsdk.ble.d$a.onServiceAdded(SourceFile:441)
at android.bluetooth.BluetoothGattServer$1.onServiceAdded(BluetoothGattServer.java:136)
at android.bluetooth.IBluetoothGattServerCallback$Stub.onTransact(IBluetoothGattServerCallback.java:85)
at android.os.Binder.execTransact(Binder.java:723)
14:06:13.725 9853 zygote I Debugger is no longer active
public String b() {
if (this.k == null) {
if (this.h == null) {
this.h = (BluetoothManager) this.c.getSystemService("bluetooth");
if (this.h == null) {
com.xpay.android.phone.inside.log.api.b.b("Unable to initialize BluetoothManager.");
return null;
}
}
this.i = this.h.getAdapter();
if (this.i == null) {
com.xpay.android.phone.inside.log.api.b.b("Unable to obtain a BluetoothAdapter.");
return null;
}
this.k = this.i.getAddress();
if (TextUtils.isEmpty(this.k) || this.k.endsWith("00:00:00:00:00")) {
try {
this.k = a(this.i);
} catch (Throwable th) {
com.xpay.android.phone.inside.log.api.b.a(th);
}
}
if (TextUtils.isEmpty(this.k) || this.k.endsWith("00:00:00:00:00")) {
try {
this.k = Settings.Secure.getString(this.c.getContentResolver(), "bluetooth_address");
} catch (Throwable th2) {
com.xpay.android.phone.inside.log.api.b.a(th2);
}
}
com.xpay.android.phone.inside.log.api.b.a("ServerAddress:" + this.k);
}
return this.k;
}
private static String a(BluetoothAdapter bluetoothAdapter) {
Object obj;
try {
Field declaredField = BluetoothAdapter.class.getDeclaredField("mService");
declaredField.setAccessible(true);
obj = declaredField.get(bluetoothAdapter);
} catch (Throwable th) {
com.xpay.android.phone.inside.log.api.b.a(th);
}
if (obj == null) {
return null;
}
Method declaredMethod = obj.getClass().getDeclaredMethod("getAddress", new Class[0]);
declaredMethod.setAccessible(true);
Object invoke = declaredMethod.invoke(obj, new Object[0]);
if (invoke != null && (invoke instanceof String)) {
return (String) invoke;
}
return null;
}
public String b() {
if (this.k == null) {
if (this.h == null) {
this.h = (BluetoothManager) this.c.getSystemService("bluetooth");
if (this.h == null) {
com.xpay.android.phone.inside.log.api.b.b("Unable to initialize BluetoothManager.");
return null;
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!