username StaticPubKey StaticPriKey phone_id
样例:可以找我拿
安卓苹果模拟器都行。价格好商量
q185582795
参考
http://www.xjishu.com/zhuanli/62/202010208090.html
当用户第一次做备份的时候密钥随之产生,但密钥并不会在云端存储,仅仅被保存在智能手机端而且每个手机所产生的密钥都是不同的。因此为了对加密型数据库进行解密,我们必须从创建了备份的智能设备中提取密钥。我们可以从下列位置找到密钥: userdata/data/com.whatsapp/files/key
renrenAPP逆向
.method public static N6(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Landroid/content/Context;Lcom/renren/mobile/android/loginfree/LoginStatusListener;)V
.locals 1
.annotation system Ldalvik/annotation/MethodParameters;
accessFlags = {
0x10,
0x10,
0x0,
0x0,
0x0,
0x10,
0x10
}
names = {
"account",
"passwordMd5",
"isVerify",
"verifyCode",
"rkey",
"context",
"loginStatusListener"
}
.end annotation
const/4 p2, 0x0
.line 1
invoke-static {p2}, Lcom/renren/mobile/android/service/ServiceProvider;->U6(Z)Lcom/renren/mobile/utils/json/JsonObject;
move-result-object p2
if-eqz p4, :cond_0
const-string p3, "rkey"
.line 2
invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
:cond_0
const-string p3, "v"
const-string p4, "1.0"
.line 3
invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
const-string p3, "format"
const-string p4, "JSON"
.line 4
invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
const-string p3, "user"
.line 5
invoke-virtual {p2, p3, p0}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
const-string p3, "password"
.line 6
invoke-virtual {p2, p3, p1}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
.line 7
sget-object p3, Lcom/renren/mobile/android/utils/Variables;->O:Ljava/lang/String;
const-string p4, "uniq_id"
invoke-virtual {p2, p4, p3}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
const-string p3, "session_key"
.line 8
invoke-virtual {p2, p3}, Lcom/renren/mobile/utils/json/JsonObject;->f(Ljava/lang/Object;)V
const-string p3, "gz"
const-string p4, "compression"
.line 9
invoke-virtual {p2, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
const-wide/16 p3, 0x1
const-string v0, "tab_sequence"
.line 10
invoke-virtual {p2, v0, p3, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;J)V
.line 11
new-instance p3, Lcom/renren/mobile/utils/json/JsonObject;
invoke-direct {p3}, Lcom/renren/mobile/utils/json/JsonObject;-><init>()V
.line 12
sget-object p4, Lcom/renren/mobile/android/utils/Variables;->J:Ljava/lang/String;
const-string v0, "station_id"
invoke-virtual {p3, v0, p4}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
const-string p4, "ext_info"
.line 13
invoke-virtual {p2, p4, p3}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Lcom/renren/mobile/utils/json/JsonValue;)V
.line 14
invoke-static {p2}, Lcom/renren/mobile/android/service/ServiceProvider;->Z4(Lcom/renren/mobile/utils/json/JsonObject;)Ljava/lang/String;
move-result-object p3
const-string p4, "sig"
invoke-virtual {p2, p4, p3}, Lcom/renren/mobile/utils/json/JsonObject;->put(Ljava/lang/String;Ljava/lang/String;)V
.line 15
new-instance p3, Lcom/renren/mobile/android/service/ServiceProvider$2;
invoke-direct {p3, p6, p0, p1, p5}, Lcom/renren/mobile/android/service/ServiceProvider$2;-><init>(Lcom/renren/mobile/android/loginfree/LoginStatusListener;Ljava/lang/String;Ljava/lang/String;Landroid/content/Context;)V
.line 16
new-instance p0, Lcom/renren/mobile/net/http/HttpRequestWrapper;
invoke-direct {p0}, Lcom/renren/mobile/net/http/HttpRequestWrapper;-><init>()V
.line 17
new-instance p1, Ljava/lang/StringBuilder;
invoke-direct {p1}, Ljava/lang/StringBuilder;-><init>()V
sget-object p4, Lcom/renren/mobile/utils/ConstantUrls;->t:Ljava/lang/String;
invoke-virtual {p1, p4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
const-string p4, "/client/login"
invoke-virtual {p1, p4}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
invoke-virtual {p1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object p1
invoke-interface {p0, p1}, Lcom/renren/mobile/net/INetRequest;->setUrl(Ljava/lang/String;)V
.line 18
invoke-interface {p0, p2}, Lcom/renren/mobile/net/INetRequest;->setData(Lcom/renren/mobile/utils/json/JsonObject;)V
.line 19
invoke-interface {p0, p3}, Lcom/renren/mobile/net/INetRequest;->setResponse(Lcom/renren/mobile/net/INetResponse;)V
.line 20
sget-object p1, Lcom/renren/mobile/android/service/ServiceProvider;->O:Ljava/lang/String;
invoke-interface {p0, p1}, Lcom/renren/mobile/net/INetRequest;->setSecretKey(Ljava/lang/String;)V
.line 21
invoke-static {}, Lcom/renren/mobile/net/http/HttpProviderWrapper;->getInstance()Lcom/renren/mobile/net/http/HttpProviderWrapper;
move-result-object p1
invoke-virtual {p1, p0}, Lcom/renren/mobile/net/http/HttpProviderWrapper;->addRequest(Lcom/renren/mobile/net/INetRequest;)V
return-void
.end method
点击登录按钮执行的分支 登录按钮的RSA方法
private void Q0() {
RSA.g();
this.G = this.r.findViewById(R.id.error_hint);
this.F = this.r.findViewById(R.id.back);
View findViewById = this.r.findViewById(R.id.welcome_hot_spot_visitor_experience_iv);
this.E = findViewById;
findViewById.setOnClickListener(this);
if (!this.N) {
this.E.setVisibility(4);
this.F.setVisibility(0);
}
this.F.setOnClickListener(this);
this.r.findViewById(R.id.telephone_login).setOnClickListener(this);
this.s = (Button) this.r.findViewById(R.id.planb_login_from_publish_login_btn);
this.t = (Button) this.r.findViewById(R.id.service_configuration);
this.z = (EditText) this.r.findViewById(R.id.planb_login_from_publish_account_edt);
EditText editText = (EditText) this.r.findViewById(R.id.planb_login_from_publish_input_password_edt);
this.y = editText;
editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
this.v = (ImageView) this.r.findViewById(R.id.password_inputtype_change);
this.u = (TextView) this.r.findViewById(R.id.planb_login_from_publish_forgetpsd_btn);
this.D = (ViewStub) this.r.findViewById(R.id.third_account_login_enter_bottom);
P0();
ProgressDialog progressDialog = new ProgressDialog(getActivity());
this.H = progressDialog;
progressDialog.setMessage(RenRenApplication.getContext().getResources().getString(R.string.v5_0_1_guide_register_progress_login));
if (DebugManager.g()) {
this.t.setVisibility(0);
this.t.setOnClickListener(this);
}
CheckBox checkBox = (CheckBox) this.r.findViewById(R.id.cb_login_agreement);
this.w = checkBox;
checkBox.setVisibility(0);
TextView textView = (TextView) this.r.findViewById(R.id.tv_login_agreement);
textView.setVisibility(0);
AgreementUtils.a.a(textView, getActivity(), this.w);
}
package com.renren.mobile.utils;
import com.baidu.android.common.security.RSAUtil;
import com.xiaomi.mipush.sdk.Constants;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.net.URL;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import kotlin.UByte;
public final class RSA {
public static String a;
public static String b;
public static String c;
private static String d;
public static int e;
private static String a(byte[] bArr) {
StringBuilder sb = new StringBuilder();
for (byte b2 : bArr) {
sb.append(Integer.toString((b2 & UByte.b) + 256, 16).substring(1));
}
return sb.toString();
}
public static String b(String str, String str2, String str3) throws Exception {
Cipher instance = Cipher.getInstance(RSAUtil.ALGORITHM_RSA);
instance.init(1, c(str2, str3));
return a(instance.doFinal(str.getBytes()));
}
private static RSAPublicKey c(String str, String str2) throws Exception {
try {
return (RSAPublicKey) KeyFactory.getInstance(RSAUtil.ALGORITHM_RSA).generatePublic(new RSAPublicKeySpec(new BigInteger(str, 16), new BigInteger(str2, 16)));
} catch (InvalidKeySpecException e2) {
throw new Exception(e2.getMessage());
}
}
public static String d() {
return b;
}
public static String e() {
return c;
}
public static String f() {
return a;
}
public static void g() {
new Thread(a.a).start();
}
static /* synthetic */ void h() {
try {
String i = i();
d = i;
if (i != null) {
b = i.split(Constants.COLON_SEPARATOR)[2].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
c = d.split(Constants.COLON_SEPARATOR)[3].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
a = d.split(Constants.COLON_SEPARATOR)[5].split("\\}")[0].trim();
String str = b;
b = str.substring(1, str.length() - 1);
String str2 = c;
c = str2.substring(1, str2.length() - 1);
String str3 = a;
a = str3.substring(1, str3.length() - 1);
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
private static String i() throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new URL(" http://login.renren.com/ajax/getEncryptKey").openStream(), "GB2312"));
String readLine = bufferedReader.readLine();
bufferedReader.close();
return readLine;
}
}
请求回来的数据
{"isEncrypt":true,"e":"10001","n":"aaf27564c44eeadde41e97467137764e415f80c0b1f75ad09be3013980d4cceb","maxdigits":"19","rkey":"f5a0aefc7cf49cacfe0c8c5e149cc0bb"}
得到数据
e是b
n是c
rkey 是a
static /* synthetic */ void h() {
try {
String i = i();
d = i;
if (i != null) {
b = i.split(Constants.COLON_SEPARATOR)[2].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
c = d.split(Constants.COLON_SEPARATOR)[3].split(Constants.ACCEPT_TIME_SEPARATOR_SP)[0].trim();
a = d.split(Constants.COLON_SEPARATOR)[5].split("\\}")[0].trim();
String str = b;
b = str.substring(1, str.length() - 1);
String str2 = c;
c = str2.substring(1, str2.length() - 1);
String str3 = a;
a = str3.substring(1, str3.length() - 1);
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
密码和账号
s是密码
Variables.r = this.z.getText().toString().trim();
Variables.s = this.y.getText().toString().trim();
q = RSA.f();
this.P = RSA.e();
String d = RSA.d();
this.Q = d;
if (q != null) {
try {
Variables.s = RSA.b(Variables.s, this.P, d);
RSA.e = 1;
} catch (Exception e) {
e.printStackTrace();
}
} else {
Variables.s = Md5.toMD5(Variables.s);
RSA.e = 2;
}
String str4 = Variables.r;
if (str4 != null && str4.length() > 0 && (str = Variables.s) != null && str.length() > 0) {
if (this.I == null) {
BaseActivity activity = getActivity();
Objects.requireNonNull(activity);
Dialog dialog = new Dialog(activity);
this.I = dialog;
dialog.setContentView(R.layout.login_dialog);
}
this.I.show();
if (RSA.e != 1) {
q = null;
}
ServiceProvider.N6(Variables.r, Variables.s, 1, "", q, getActivity(), this.R);
MD5算法
public static String toMD5(String str) {
if (str == null) {
return null;
}
try {
return d(str.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
return d 算法部分
private static synchronized String d(byte[] bArr) {
String sb;
synchronized (Md5.class) {
try {
MessageDigest instance = MessageDigest.getInstance("MD5");
instance.update(bArr);
byte[] digest = instance.digest();
StringBuilder sb2 = new StringBuilder();
for (byte b : digest) {
sb2.append(Integer.toHexString((b & UByte.b) | InputDeviceCompat.u).substring(6));
}
sb = sb2.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
}
}
return sb;
}
api_key 直接写死9e1874c67e0b42d79cc16f787b644339
public static final String M = RenRenApplication.getContext().getResources().getString(R.string.apikey);
str4是q,往回倒
if (str4 != null) {
U6.put("rkey", str4);
}
q = RSA.f();
public static String f() {
return a;
}
a = d.split(Constants.COLON_SEPARATOR)[5].split("\\}")[0].trim();
String str3 = a;
a = str3.substring(1, str3.length() - 1);
sig
U6.put("sig", Z4(U6));
private static String Z4(JsonObject jsonObject) {
String[] keys = jsonObject.getKeys();
StringBuilder sb = new StringBuilder();
Vector vector = new Vector();
for (String str : keys) {
String jsonValue = jsonObject.getJsonValue(str).toString();
sb.append(str);
sb.append('=');
sb.append(URLEncoder.encode(jsonValue));
sb.append(Typography.c);
if (jsonValue.length() > 50) {
jsonValue = jsonValue.substring(0, 50);
}
vector.add(str + ContainerUtils.KEY_VALUE_DELIMITER + jsonValue);
}
String[] strArr = new String[vector.size()];
vector.copyInto(strArr);
return Y4(strArr, O);
}
public static String Y4(String[] strArr, String str) {
for (int i2 = 0; i2 < strArr.length; i2++) {
for (int length = strArr.length - 1; length > i2; length--) {
int i3 = length - 1;
if (strArr[length].compareTo(strArr[i3]) < 0) {
String str2 = strArr[length];
strArr[length] = strArr[i3];
strArr[i3] = str2;
}
}
}
StringBuffer stringBuffer = new StringBuffer();
for (String str3 : strArr) {
stringBuffer.append(str3);
}
stringBuffer.append(str);
return Md5.toMD5(stringBuffer.toString());
}
u6的算法
public static JsonObject V6(boolean z2, boolean z3) {
JsonObject jsonObject = new JsonObject();
jsonObject.put(NotifyType.VIBRATE, "1.0");
jsonObject.put(Constants.q, M);
jsonObject.put("call_id", System.currentTimeMillis());
if (!z2 && !TextUtils.isEmpty(Q)) {
jsonObject.put("session_key", Q);
Log.d("zxc", "session " + Q);
}
i(jsonObject, z3);
return jsonObject;
}
第二个sig 由此可以看出secretkey和前面所有的字段组成MD5
public void setSecretKey(String str) {
this.B = str;
}
public String p() {
return this.B;
}
static {
String string = RenRenApplication.getContext().getResources().getString(R.string.secretkey);
O = string;
P = string;
}
public String t() {
if (this.q == null) {
return "";
}
StringBuilder sb = new StringBuilder();
int i = this.u;
if (i == 6 || i == 7) {
sb.append(this.q.getString(RemoteMessageConst.MSGBODY));
} else {
String[] keys = this.q.getKeys();
if (keys == null || keys.length == 0) {
return "";
}
Vector vector = new Vector();
for (String str : keys) {
String jsonValue = this.q.getJsonValue(str).toString();
sb.append(str);
sb.append('=');
sb.append(URLEncoder.encode(jsonValue));
sb.append(Typography.c);
if (jsonValue.length() > 50) {
jsonValue = jsonValue.substring(0, 50);
}
vector.add(str + ContainerUtils.KEY_VALUE_DELIMITER + jsonValue);
}
String[] strArr = new String[vector.size()];
vector.copyInto(strArr);
String str2 = this.B;
if (!(str2 == null || str2.length() == 0)) {
sb.append("sig=");
sb.append(ServiceProvider.Y4(strArr, this.B));
}
}
return sb.toString();
}
私钥保存的目录,现在无法读取了(如果有android低版本的手机有可能成功)
需要用手机号登录之后才会生成密钥,但是模拟器无法用手机号登录...
https://www.anquanke.com/post/id/85330
https://3g.163.com/dy/article/E5GNN7VU0511CJ6O.html?spss=adap_pc