东游亲友房搭建的一个小技巧。必须按步骤操作。
首先,必须选择一个合适的服务器,因为服务器的好坏,直接关系到搭接的成功于否。
vx:375467036
Last login:Sun Dec 1
welcome to aliyun Elastic Compute Servic
如上图中所示,里面明显有很多值得留意的内容。
一开始是想从Manifest.xml里看到的com.lumiunited.aqara开始分析的。 又恰巧有com.lumiunited.aqara.login.loginpage.LoginPageActivity这个类,我理所当然的认为这里就是相关的login逻辑了。但是在逆向的时候我想调试代码,断点这个activity上并不能断住,因此怀疑这里并不是最开始部分的login逻辑。 于是通过adb shell中运行dumpsys activity activities | grep mResumedActivity
找到当前正在活动的activity:com.lumi.module.login.ui.activity.LoginWrapperActivity。 所以真正的login部分其实在这里。
我们可以在k.u.j.g.f.d.b 类里看到大量的网络调用接口。用jeb进行调试的话很容易发现我们的password先经过了md5哈希,然后再使用了apk文件里带着的一个证书进行rsa公钥加密并转成base64编码,它的代码如下:
package com.lumi.external.utils;
import android.content.res.Resources;
import android.util.Base64;
import com.lumi.external.utils.log.Logs;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPublicKey;
import javax.crypto.Cipher;
import k.u.b.f.d.e;
import org.jetbrains.annotations.NotNull;
import s.b3.k;
import s.b3.w.Log;
import s.h0;
import s.i3.f;
@h0(bv = {1, 0, 3}, d1 = {"\u00000\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u000E\n\u0002\b\u0003\n\u0002\u0010\b\n\u0002\b\u0003\n\u0002\u0018\u0002\n\u0000\n\u0002\u0018\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\b\u0004\bÆ\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0010\u0010\t\u001A\u00020\u00042\u0006\u0010\n\u001A\u00020\u0004H\u0007J\u0010\u0010\u000B\u001A\u00020\f2\u0006\u0010\r\u001A\u00020\u000EH\u0002J%\u0010\u000F\u001A\n\u0012\u0006\u0012\u0004\u0018\u00010\u00040\u00102\u0006\u0010\u0011\u001A\u00020\u00042\u0006\u0010\u0012\u001A\u00020\bH\u0002¢\u0006\u0002\u0010\u0013R\u000E\u0010\u0003\u001A\u00020\u0004X\u0082T¢\u0006\u0002\n\u0000R\u000E\u0010\u0005\u001A\u00020\u0004X\u0082T¢\u0006\u0002\n\u0000R\u000E\u0010\u0006\u001A\u00020\u0004X\u0082T¢\u0006\u0002\n\u0000R\u000E\u0010\u0007\u001A\u00020\bX\u0082\u000E¢\u0006\u0002\n\u0000¨\u0006\u0014"}, d2 = {"Lcom/lumi/external/utils/RSA;", "", "()V", "CERT_TYPE", "", "CER_NAME", "ECB_PKCS1_PADDING", "keyLength", "", "encrypt", "str", "getCert", "Ljava/security/cert/Certificate;", "inputStream", "Ljava/io/InputStream;", "splitString", "", "string", "len", "(Ljava/lang/String;I)[Ljava/lang/String;", "externalCore_release"}, k = 1, mv = {1, 4, 1})
public final class RSA {
public static final String CERT_TYPE = "X.509";
public static final String CER_NAME = "lumiunited.cer";
public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";
@NotNull
public static final RSA INSTANCE;
public static int keyLength;
public static {
RSA.INSTANCE = new RSA();
}
@NotNull
@k
public static final String encrypt(@NotNull String s) throws Exception {
byte[] arr_b1;
Log.e(s, "str");
Logs.d(new Object[]{"encrypt content " + s});
byte[] arr_b = new byte[0x5000];
try {
Cipher cipher0 = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Resources resources0 = e.f.a().d().getResources();
Log.d(resources0, "AppManager.instance.getA…cationContext().resources");
InputStream inputStream0 = resources0.getAssets().open("lumiunited.cer");
Log.d(inputStream0, "AppManager.instance.getA…ces.assets.open(CER_NAME)");
cipher0.init(1, RSA.INSTANCE.getCert(inputStream0));
String[] arr_s = RSA.INSTANCE.splitString(s, RSA.keyLength - 11);
int v = 0;
int v1 = 0;
while(v < arr_s.length) {
String s1 = arr_s[v];
if(s1 != null) {
Charset charset0 = f.a;
if(s1 != null) {
arr_b1 = s1.getBytes(charset0);
Log.d(arr_b1, "(this as java.lang.String).getBytes(charset)");
goto label_62;
}
throw new NullPointerException("null cannot be cast to non-null type java.lang.String");
}
arr_b1 = null;
label_62:
byte[] arr_b2 = cipher0.doFinal(arr_b1);
int v2 = 0;
while(v2 < arr_b2.length) {
arr_b[v1] = arr_b2[v2];
++v2;
++v1;
}
++v;
}
String s2 = Base64.encodeToString(arr_b, 0, v1, 0);
Logs.d(new Object[]{"after encrypt " + s2});
Log.d(s2, "afterEncrypt");
return s2;
}
catch(Exception exception0) {
exception0.printStackTrace();
Logs.e(new Object[]{"RSA.Encrypt", exception0.getMessage()});
throw exception0;
}
}
private final Certificate getCert(InputStream inputStream0) throws CertificateException {
Certificate certificate0 = CertificateFactory.getInstance("X.509").generateCertificate(inputStream0);
Log.d(certificate0, "cert");
PublicKey publicKey0 = certificate0.getPublicKey();
if(publicKey0 != null) {
RSA.keyLength = ((RSAPublicKey)publicKey0).getModulus().bitLength() / 16;
return certificate0;
}
throw new NullPointerException("null cannot be cast to non-null type java.security.interfaces.RSAPublicKey");
}
private final String[] splitString(String s, int v) {
String s1;
int v1 = s.length() % v;
int v2 = 0;
int v3 = s.length() / v + (v1 == 0 ? 0 : 1);
String[] arr_s = new String[v3];
while(v2 < v3) {
if(v2 == v3 - 1 && v1 != 0) {
int v4 = v2 * v;
int v5 = v4 + v1;
if(s != null) {
s1 = s.substring(v4, v5);
Log.d(s1, "(this as java.lang.Strin…ing(startIndex, endIndex)");
goto label_35;
}
throw new NullPointerException("null cannot be cast to non-null type java.lang.String");
}
else {
int v6 = v2 * v;
int v7 = v6 + v;
if(s == null) {
throw new NullPointerException("null cannot be cast to non-null type java.lang.String");
}
s1 = s.substring(v6, v7);
Log.d(s1, "(this as java.lang.Strin…ing(startIndex, endIndex)");
}
label_35:
arr_s[v2] = s1;
++v2;
}
return arr_s;
}
}