å°å ¥
XNUMXææ«ã«ç§ãã¡ã¯ã
å°ãåãUC ãã©ãŠã¶ã¯éåžžã«ç©æ¥µçã«å®£äŒãããé
åžãããŸããããã«ãŠã§ã¢ã䜿çšããŠãŠãŒã¶ãŒã®ããã€ã¹ã«ã€ã³ã¹ããŒã«ããããã㪠ãã¡ã€ã«ãè£
ã£ãŠããŸããŸãªãµã€ãããé
åžãããŸãã (ã€ãŸãããŠãŒã¶ãŒã¯ãããšãã°ãã«ã ãããªãããŠã³ããŒãããŠãããšæã£ãŠããŸãããã代ããã«ããã®ãã©ãŠã¶ã§ APK ãåãåããŸããïŒããã©ãŠã¶ãå€ããè匱ã§ãããªã©ã®ã¡ãã»ãŒãžãå«ãæããããããŒã䜿çšããŸããã VK ã®å
¬åŒ UC Browser ã°ã«ãŒãã«ã¯ã
ãã®èšäºã®å·çæç¹ã§ãUC Browser 㯠Google Play 㧠500 å件以äžã€ã³ã¹ããŒã«ãããŠããŸãã ããã¯å°è±¡çã§ãããã以äžã®æ©èœãåããŠããã®ã¯ Google Chrome ã ãã§ãã ã¬ãã¥ãŒã®äžã«ã¯ãåºåã Google Play äžã®äžéšã®ã¢ããªã±ãŒã·ã§ã³ãžã®ãªãã€ã¬ã¯ãã«é¢ããèŠæ
ãããªãå€ãèŠãããŸãã ãããç§ãã¡ã®èª¿æ»ã®çç±ã§ãããUC ãã©ãŠã¶ãŒãäœãæªãããšãããŠãããã©ããã確èªããããšã«ããŸããã ãããŠã圌ã¯ããããŠããããšãå€æããŸããïŒ
ã¢ããªã±ãŒã·ã§ã³ ã³ãŒãã§ã¯ãå®è¡å¯èœã³ãŒããããŠã³ããŒãããŠå®è¡ããæ©èœãçºèŠãããŸããã
以äžã«èšèŒãããŠããå 容ã¯ãã¹ãŠã調æ»æç¹ã§ Google Play ã§å ¥æå¯èœã ã£ã UC ãã©ãŠã¶ã®ããŒãžã§ã³ã«é¢é£ããŠããŸãã
package: com.UCMobile.intl
versionName: 12.10.8.1172
versionCode: 10598
sha1 APK-Ñайла: f5edb2243413c777172f6362876041eb0c3a928c
æ»æãã¯ãã«
UC ãã©ãŠã¶ãŒ ãããã§ã¹ãã§ã¯ãããããããååã®ãµãŒãã¹ãèŠã€ããããšãã§ããŸãã com.uc.deployment.UpgradeDeployService.
<service android_exported="false" android_name="com.uc.deployment.UpgradeDeployService" android_process=":deploy" />
ãã®ãµãŒãã¹ãéå§ããããšããã©ãŠã¶ã¯ POST ãªã¯ãšã¹ããéä¿¡ããŸãã
ãããã£ãŠããŠãŒã¶ãŒããã©ãŠã¶ã§çŽæ¥ PDF ãéãããšãããšããã©ãã£ãã¯å ã§æ¬¡ã®ãªã¯ãšã¹ããçºçããå¯èœæ§ããããŸãã
ãŸãã次ãžã® POST ãªã¯ãšã¹ãããããŸãã
PDF ããã³ Office 圢åŒã衚瀺ããããã®ã©ã€ãã©ãªãå«ãã¢ãŒã«ã€ããããŠã³ããŒããããŸãã æåã®ãªã¯ãšã¹ããã·ã¹ãã ã«é¢ããæ
å ± (å°ãªããšãå¿
èŠãªã©ã€ãã©ãªãæäŸããã¢ãŒããã¯ãã£) ãéä¿¡ããããã«å¿çããŠãã©ãŠã¶ãããŠã³ããŒãããå¿
èŠã®ããã©ã€ãã©ãªã«é¢ããæ
å ± (ã¢ãã¬ã¹ãšãããããã¯ã¢ãã¬ã¹) ãåãåããšæ³å®ããã®ãè«ççã§ãã ãäœãä»ã®ãã®ã åé¡ã¯ããã®ãªã¯ãšã¹ããæå·åãããŠããããšã§ãã
ãªã¯ãšã¹ããã©ã°ã¡ã³ã
åçã®æç
ã©ã€ãã©ãªèªäœã¯ ZIP ã§ããã±ãŒãžåãããŠãããæå·åãããŸããã
ãã©ãã£ãã¯åŸ©å·åã³ãŒããæ€çŽ¢ãã
ãµãŒããŒã®å¿çã解èªããŠã¿ãŸãããã ã¯ã©ã¹ã³ãŒããèŠãŠã¿ãŸããã com.uc.deployment.UpgradeDeployService: ã¡ãœãããã onStartã³ãã³ã ã«è¡ã com.uc.deployment.bxããããŠãããã com.uc.browser.core.dcfe:
public final void e(l arg9) {
int v4_5;
String v3_1;
byte[] v3;
byte[] v1 = null;
if(arg9 == null) {
v3 = v1;
}
else {
v3_1 = arg9.iGX.ipR;
StringBuilder v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]product:");
v4.append(arg9.iGX.ipR);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]version:");
v4.append(arg9.iGX.iEn);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]upgrade_type:");
v4.append(arg9.iGX.mMode);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]force_flag:");
v4.append(arg9.iGX.iEo);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_mode:");
v4.append(arg9.iGX.iDQ);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_type:");
v4.append(arg9.iGX.iEr);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_state:");
v4.append(arg9.iGX.iEp);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_file:");
v4.append(arg9.iGX.iEq);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apk_md5:");
v4.append(arg9.iGX.iEl);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]download_type:");
v4.append(arg9.mDownloadType);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]download_group:");
v4.append(arg9.mDownloadGroup);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]download_path:");
v4.append(arg9.iGH);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_child_version:");
v4.append(arg9.iGX.iEx);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_series:");
v4.append(arg9.iGX.iEw);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_cpu_arch:");
v4.append(arg9.iGX.iEt);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_cpu_vfp3:");
v4.append(arg9.iGX.iEv);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_cpu_vfp:");
v4.append(arg9.iGX.iEu);
ArrayList v3_2 = arg9.iGX.iEz;
if(v3_2 != null && v3_2.size() != 0) {
Iterator v3_3 = v3_2.iterator();
while(v3_3.hasNext()) {
Object v4_1 = v3_3.next();
StringBuilder v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_name:");
v5.append(((au)v4_1).getName());
v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_ver_name:");
v5.append(((au)v4_1).aDA());
v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_ver_code:");
v5.append(((au)v4_1).gBl);
v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_req_type:");
v5.append(((au)v4_1).gBq);
}
}
j v3_4 = new j();
m.b(v3_4);
h v4_2 = new h();
m.b(v4_2);
ay v5_1 = new ay();
v3_4.hS("");
v3_4.setImsi("");
v3_4.hV("");
v5_1.bPQ = v3_4;
v5_1.bPP = v4_2;
v5_1.yr(arg9.iGX.ipR);
v5_1.gBF = arg9.iGX.mMode;
v5_1.gBI = arg9.iGX.iEz;
v3_2 = v5_1.gAr;
c.aBh();
v3_2.add(g.fs("os_ver", c.getRomInfo()));
v3_2.add(g.fs("processor_arch", com.uc.b.a.a.c.getCpuArch()));
v3_2.add(g.fs("cpu_arch", com.uc.b.a.a.c.Pb()));
String v4_3 = com.uc.b.a.a.c.Pd();
v3_2.add(g.fs("cpu_vfp", v4_3));
v3_2.add(g.fs("net_type", String.valueOf(com.uc.base.system.a.Jo())));
v3_2.add(g.fs("fromhost", arg9.iGX.iEm));
v3_2.add(g.fs("plugin_ver", arg9.iGX.iEn));
v3_2.add(g.fs("target_lang", arg9.iGX.iEs));
v3_2.add(g.fs("vitamio_cpu_arch", arg9.iGX.iEt));
v3_2.add(g.fs("vitamio_vfp", arg9.iGX.iEu));
v3_2.add(g.fs("vitamio_vfp3", arg9.iGX.iEv));
v3_2.add(g.fs("plugin_child_ver", arg9.iGX.iEx));
v3_2.add(g.fs("ver_series", arg9.iGX.iEw));
v3_2.add(g.fs("child_ver", r.aVw()));
v3_2.add(g.fs("cur_ver_md5", arg9.iGX.iEl));
v3_2.add(g.fs("cur_ver_signature", SystemHelper.getUCMSignature()));
v3_2.add(g.fs("upgrade_log", i.bjt()));
v3_2.add(g.fs("silent_install", String.valueOf(arg9.iGX.iDQ)));
v3_2.add(g.fs("silent_state", String.valueOf(arg9.iGX.iEp)));
v3_2.add(g.fs("silent_file", arg9.iGX.iEq));
v3_2.add(g.fs("silent_type", String.valueOf(arg9.iGX.iEr)));
v3_2.add(g.fs("cpu_archit", com.uc.b.a.a.c.Pc()));
v3_2.add(g.fs("cpu_set", SystemHelper.getCpuInstruction()));
boolean v4_4 = v4_3 == null || !v4_3.contains("neon") ? false : true;
v3_2.add(g.fs("neon", String.valueOf(v4_4)));
v3_2.add(g.fs("cpu_cores", String.valueOf(com.uc.b.a.a.c.Jl())));
v3_2.add(g.fs("ram_1", String.valueOf(com.uc.b.a.a.h.Po())));
v3_2.add(g.fs("totalram", String.valueOf(com.uc.b.a.a.h.OL())));
c.aBh();
v3_2.add(g.fs("rom_1", c.getRomInfo()));
v4_5 = e.getScreenWidth();
int v6 = e.getScreenHeight();
StringBuilder v7 = new StringBuilder();
v7.append(v4_5);
v7.append("*");
v7.append(v6);
v3_2.add(g.fs("ss", v7.toString()));
v3_2.add(g.fs("api_level", String.valueOf(Build$VERSION.SDK_INT)));
v3_2.add(g.fs("uc_apk_list", SystemHelper.getUCMobileApks()));
Iterator v4_6 = arg9.iGX.iEA.entrySet().iterator();
while(v4_6.hasNext()) {
Object v6_1 = v4_6.next();
v3_2.add(g.fs(((Map$Entry)v6_1).getKey(), ((Map$Entry)v6_1).getValue()));
}
v3 = v5_1.toByteArray();
}
if(v3 == null) {
this.iGY.iGI.a(arg9, "up_encode", "yes", "fail");
return;
}
v4_5 = this.iGY.iGw ? 0x1F : 0;
if(v3 == null) {
}
else {
v3 = g.i(v4_5, v3);
if(v3 == null) {
}
else {
v1 = new byte[v3.length + 16];
byte[] v6_2 = new byte[16];
Arrays.fill(v6_2, 0);
v6_2[0] = 0x5F;
v6_2[1] = 0;
v6_2[2] = ((byte)v4_5);
v6_2[3] = -50;
System.arraycopy(v6_2, 0, v1, 0, 16);
System.arraycopy(v3, 0, v1, 16, v3.length);
}
}
if(v1 == null) {
this.iGY.iGI.a(arg9, "up_encrypt", "yes", "fail");
return;
}
if(TextUtils.isEmpty(this.iGY.mUpgradeUrl)) {
this.iGY.iGI.a(arg9, "up_url", "yes", "fail");
return;
}
StringBuilder v0 = new StringBuilder("[");
v0.append(arg9.iGX.ipR);
v0.append("]url:");
v0.append(this.iGY.mUpgradeUrl);
com.uc.browser.core.d.c.i v0_1 = this.iGY.iGI;
v3_1 = this.iGY.mUpgradeUrl;
com.uc.base.net.e v0_2 = new com.uc.base.net.e(new com.uc.browser.core.d.c.i$a(v0_1, arg9));
v3_1 = v3_1.contains("?") ? v3_1 + "&dataver=pb" : v3_1 + "?dataver=pb";
n v3_5 = v0_2.uc(v3_1);
m.b(v3_5, false);
v3_5.setMethod("POST");
v3_5.setBodyProvider(v1);
v0_2.b(v3_5);
this.iGY.iGI.a(arg9, "up_null", "yes", "success");
this.iGY.iGI.b(arg9);
}
ããã§ã¯ãPOST ãªã¯ãšã¹ãã®åœ¢æãããããŸãã 16 ãã€ãã®é åã®äœæãšãã®é å (0x5Fã0ã0x1Fã-50 (=0xCE)) ã®äœæã«æ³šç®ããŸãã äžèšã®ãªã¯ãšã¹ãã§ç¢ºèªããå 容ãšäžèŽããŸãã
åãã¯ã©ã¹å ã«ãå¥ã®èå³æ·±ãã¡ãœãããæã€ãã¹ããããã¯ã©ã¹ã衚瀺ãããŸãã
public final void a(l arg10, byte[] arg11) {
f v0 = this.iGQ;
StringBuilder v1 = new StringBuilder("[");
v1.append(arg10.iGX.ipR);
v1.append("]:UpgradeSuccess");
byte[] v1_1 = null;
if(arg11 == null) {
}
else if(arg11.length < 16) {
}
else {
if(arg11[0] != 0x60 && arg11[3] != 0xFFFFFFD0) {
goto label_57;
}
int v3 = 1;
int v5 = arg11[1] == 1 ? 1 : 0;
if(arg11[2] != 1 && arg11[2] != 11) {
if(arg11[2] == 0x1F) {
}
else {
v3 = 0;
}
}
byte[] v7 = new byte[arg11.length - 16];
System.arraycopy(arg11, 16, v7, 0, v7.length);
if(v3 != 0) {
v7 = g.j(arg11[2], v7);
}
if(v7 == null) {
goto label_57;
}
if(v5 != 0) {
v1_1 = g.P(v7);
goto label_57;
}
v1_1 = v7;
}
label_57:
if(v1_1 == null) {
v0.iGY.iGI.a(arg10, "up_decrypt", "yes", "fail");
return;
}
q v11 = g.b(arg10, v1_1);
if(v11 == null) {
v0.iGY.iGI.a(arg10, "up_decode", "yes", "fail");
return;
}
if(v0.iGY.iGt) {
v0.d(arg10);
}
if(v0.iGY.iGo != null) {
v0.iGY.iGo.a(0, ((o)v11));
}
if(v0.iGY.iGs) {
v0.iGY.a(((o)v11));
v0.iGY.iGI.a(v11, "up_silent", "yes", "success");
v0.iGY.iGI.a(v11);
return;
}
v0.iGY.iGI.a(v11, "up_silent", "no", "success");
}
}
ãã®ã¡ãœããã¯ãã€ãé
åãå
¥åãšããŠåãåãã0 ãã€ãã 60x0 ã§ãããã0 çªç®ã®ãã€ãã 1xD11 ã§ããã0 çªç®ã®ãã€ãã 1ã0ããŸã㯠60x0F ã§ããããšã確èªããŸãã ãµãŒããŒããã®å¿çã確èªããŸãããŒããã€ã㯠1x0ã60 çªç®ã®ãã€ã㯠XNUMXxXNUMXFãXNUMX çªç®ã®ãã€ã㯠XNUMXxXNUMX ã§ãã å¿
èŠãªãã®ã®ããã§ããã è¡ (ããšãã°ããup_decryptã) ããå€æãããšããµãŒããŒã®å¿çã埩å·åããã¡ãœãããããã§åŒã³åºãããã¯ãã§ãã
æ¹æ³ã«ç§»ããŸããã gjã æåã®åŒæ°ã¯ãªãã»ãã 2 ã®ãã€ã (ã€ãŸãããã®å Žå㯠0x1F) ã§ãããXNUMX çªç®ã®åŒæ°ã¯ãµãŒããŒã®å¿çã§ãã
æåã® 16 ãã€ãã
public static byte[] j(int arg1, byte[] arg2) {
if(arg1 == 1) {
arg2 = c.c(arg2, c.adu);
}
else if(arg1 == 11) {
arg2 = m.aF(arg2);
}
else if(arg1 != 0x1F) {
}
else {
arg2 = EncryptHelper.decrypt(arg2);
}
return arg2;
}
æããã«ãããã§ã¯åŸ©å·åã¢ã«ãŽãªãºã ãšãç§ãã¡ã®ãã¡ã€ã«ã«ãããã®ãšåããã€ããéžæããŸãã
0x1F ã«çããå Žåã¯ãXNUMX ã€ã®å¯èœãªãªãã·ã§ã³ã® XNUMX ã€ã瀺ããŸãã
ã³ãŒãã®åæãç¶ããŸãã ããã€ããžã£ã³ããããšãããããããååã®ã¡ãœããã«ãã©ãçããŸãã decryptBytesByKey.
ããã§ã¯ãå¿çããããã« XNUMX ãã€ããåé¢ãããããããæååãååŸãããŸãã ãã®ããã«ããŠãã¡ãã»ãŒãžã埩å·åããããã®ããŒãéžæãããããšã¯æããã§ãã
private static byte[] decryptBytesByKey(byte[] bytes) {
byte[] v0 = null;
if(bytes != null) {
try {
if(bytes.length < EncryptHelper.PREFIX_BYTES_SIZE) {
}
else if(bytes.length == EncryptHelper.PREFIX_BYTES_SIZE) {
return v0;
}
else {
byte[] prefix = new byte[EncryptHelper.PREFIX_BYTES_SIZE]; // 2 байÑа
System.arraycopy(bytes, 0, prefix, 0, prefix.length);
String keyId = c.ayR().d(ByteBuffer.wrap(prefix).getShort()); // ÐÑÐ±ÐŸÑ ÐºÐ»ÑÑа
if(keyId == null) {
return v0;
}
else {
a v2 = EncryptHelper.ayL();
if(v2 == null) {
return v0;
}
else {
byte[] enrypted = new byte[bytes.length - EncryptHelper.PREFIX_BYTES_SIZE];
System.arraycopy(bytes, EncryptHelper.PREFIX_BYTES_SIZE, enrypted, 0, enrypted.length);
return v2.l(keyId, enrypted);
}
}
}
}
catch(SecException v7_1) {
EncryptHelper.handleDecryptException(((Throwable)v7_1), v7_1.getErrorCode());
return v0;
}
catch(Throwable v7) {
EncryptHelper.handleDecryptException(v7, 2);
return v0;
}
}
return v0;
}
ä»åŸã«æ³šç®ããŠããã®æ®µéã§ã¯ãŸã ããŒãååŸããŠãããããã®ãèå¥åãã ããååŸããŠããããšã«æ³šæããŠãã ããã ããŒã®ååŸã¯å°ãè€éã§ãã
次ã®ã¡ãœããã§ã¯ãæ¢åã®ãã©ã¡ãŒã¿ã«ããã« 16 ã€ã®ãã©ã¡ãŒã¿ãè¿œå ãããããžã㯠ãã³ã㌠XNUMXãããŒèå¥åãæå·åãããããŒã¿ãããã³ç解ã§ããªãæåå (ãã®å Žåã¯ç©º) ã® XNUMX ã€ãäœæãããŸãã
public final byte[] l(String keyId, byte[] encrypted) throws SecException {
return this.ayJ().staticBinarySafeDecryptNoB64(16, keyId, encrypted, "");
}
äžé£ã®é·ç§»ãçµãŠãã¡ãœããã«å°éããŸãã staticBinarySafeDecryptNoB64 ã€ã³ã¿ãŒãã§ãŒã¹ã® com.alibaba.wireless.security.open.staticdataencrypt.IStaticDataEncryptComponentã ã¡ã€ã³ ã¢ããªã±ãŒã·ã§ã³ ã³ãŒãã«ã¯ããã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããã¯ã©ã¹ã¯ãããŸããã ãã¡ã€ã«å ã«ãã®ãããªã¯ã©ã¹ããããŸã lib/armeabi-v7a/libsgmain.soãå®éã«ã¯ .so ã§ã¯ãªã .jar ã§ãã ç§ãã¡ãèå³ã®ããã¡ãœããã¯æ¬¡ã®ããã«å®è£ ãããŸãã
package com.alibaba.wireless.security.a.i;
// ...
public class a implements IStaticDataEncryptComponent {
private ISecurityGuardPlugin a;
// ...
private byte[] a(int mode, int magicInt, int xzInt, String keyId, byte[] encrypted, String magicString) {
return this.a.getRouter().doCommand(10601, new Object[]{Integer.valueOf(mode), Integer.valueOf(magicInt), Integer.valueOf(xzInt), keyId, encrypted, magicString});
}
// ...
private byte[] b(int magicInt, String keyId, byte[] encrypted, String magicString) {
return this.a(2, magicInt, 0, keyId, encrypted, magicString);
}
// ...
public byte[] staticBinarySafeDecryptNoB64(int magicInt, String keyId, byte[] encrypted, String magicString) throws SecException {
if(keyId != null && keyId.length() > 0 && magicInt >= 0 && magicInt < 19 && encrypted != null && encrypted.length > 0) {
return this.b(magicInt, keyId, encrypted, magicString);
}
throw new SecException("", 301);
}
//...
}
ããã§ã¯ããã©ã¡ãŒã¿ã®ãªã¹ãã«ããã« 2 ã€ã®æŽæ°ã0 ãš XNUMX ãè¿œå ãããŠããŸãã
ãã¹ãŠã2 ã¯ã¡ãœããã®ããã«åŸ©å·åãæå³ããŸã ãã¡ã€ãã«ããã ã·ã¹ãã ã¯ã©ã¹ javax.crypto.Cipherã ãããŠãããããã¹ãŠã¯çªå·10601ãæã€ç¹å®ã®ã«ãŒã¿ãŒã«è»¢éãããŸã-ããã¯æããã«ã³ãã³ãçªå·ã§ãã
次ã®äžé£ã®é·ç§»ã®åŸãã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããã¯ã©ã¹ãèŠã€ãããŸãã Iã«ãŒã¿ãŒã³ã³ããŒãã³ã ãšæ¹æ³ doã³ãã³ã:
package com.alibaba.wireless.security.mainplugin;
import com.alibaba.wireless.security.framework.IRouterComponent;
import com.taobao.wireless.security.adapter.JNICLibrary;
public class a implements IRouterComponent {
public a() {
super();
}
public Object doCommand(int arg2, Object[] arg3) {
return JNICLibrary.doCommandNative(arg2, arg3);
}
}
ãããŠã¯ã©ã¹ã JNICã©ã€ãã©ãªããã€ãã£ã ã¡ãœããã宣èšãããŠãã doCommandãã€ãã£ã:
package com.taobao.wireless.security.adapter;
public class JNICLibrary {
public static native Object doCommandNative(int arg0, Object[] arg1);
}
ããã¯ããã€ãã£ã ã³ãŒãã§ã¡ãœãããèŠã€ããå¿ èŠãããããšãæå³ããŸã doCommandãã€ãã£ãã ããããã楜ãã¿ã®å§ãŸãã§ãã
ãã·ã³ã³ãŒãã®é£èªå
ãã¡ã€ã«å libsgmain.so (ããã¯å®éã«ã¯ .jar ã§ããããã®äžã«æå·åé¢é£ã®ã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ãäžèšã§èŠã€ãããŸãã) ãã€ãã£ã ã©ã€ãã©ãªã XNUMX ã€ãããŸãã libsgmainso-6.4.36.soã IDA ã§éããšããšã©ãŒã衚瀺ããããã€ã¢ãã° ããã¯ã¹ãå€æ°è¡šç€ºãããŸãã åé¡ã¯ãã»ã¯ã·ã§ã³ããããŒããŒãã«ãç¡å¹ã§ããããšã§ãã ããã¯åæãè€éã«ããããã«æå³çã«è¡ãããŸãã
ããããããã¯å¿
èŠãããŸãããELF ãã¡ã€ã«ãæ£ããããŒãããŠåæããã«ã¯ãããã°ã©ã ããã㌠ããŒãã«ãããã°ååã§ãã ãããã£ãŠãåã«ã»ã¯ã·ã§ã³ ããŒãã«ãåé€ããããããŒå
ã®å¯Ÿå¿ãããã£ãŒã«ãããŒãã«èšå®ããŸãã
IDA ã§ãã¡ã€ã«ãå床éããŸãã
Java ã³ãŒãã§ãã€ãã£ããšããŠå®£èšãããã¡ãœããã®å®è£ ããã€ãã£ã ã©ã€ãã©ãªå ã®ã©ãã«ãããã Java ä»®æ³ãã·ã³ã«æ£ç¢ºã«äŒããæ¹æ³ã¯ XNUMX ã€ãããŸãã ãŸãã¯çš®åãä»ããããšã§ã Java_ããã±ãŒãžå_ã¯ã©ã¹å_ã¡ãœããå.
XNUMX ã€ç®ã¯ãã©ã€ãã©ãªãããŒããããšãã« (é¢æ°å
ã§) ç»é²ããããšã§ãã JNI_OnLoad)
é¢æ°åŒã³åºãã䜿çšãã ãã€ãã£ããç»é²ãã.
ç§ãã¡ã®å Žåãæåã®æ¹æ³ã䜿çšãããšãååã¯æ¬¡ã®ããã«ãªããŸãã Java_com_taobao_wireless_security_adapter_JNICLibrary_doCommandNative.
ãšã¯ã¹ããŒããããé¢æ°ã®äžã«ãã®ãããªé¢æ°ã¯ãããŸãããã€ãŸããåŒã³åºããæ¢ãå¿
èŠããããŸãã ãã€ãã£ããç»é²ãã.
é¢æ°ã«è¡ããŸããã JNI_OnLoad ãããŠã次ã®å³ã衚瀺ãããŸãã
äœãèµ·ããŠãïŒ äžèŠãããšãé¢æ°ã®éå§ãšçµäºã¯ ARM ã¢ãŒããã¯ãã£ã®å
žåçãªãã®ã§ãã ã¹ã¿ãã¯äžã®æåã®åœä»€ã¯ãé¢æ°ããã®åäœã§äœ¿çšããã¬ãžã¹ã¿ãŒ (ãã®å Žå㯠R0ãR1ãããã³ R2) ã®å
容ãšãé¢æ°ããã®æ»ãã¢ãã¬ã¹ãå«ã LR ã¬ãžã¹ã¿ãŒã®å
容ãä¿ç®¡ããŸãã ã æåŸã®åœä»€ã¯ä¿åãããã¬ãžã¹ã¿ã埩å
ããæ»ãã¢ãã¬ã¹ãçŽã¡ã« PC ã¬ãžã¹ã¿ã«é
眮ããããããé¢æ°ããæ»ããŸãã ããããããèŠããšãæåŸãã XNUMX çªç®ã®åœä»€ãã¹ã¿ãã¯ã«æ ŒçŽãããŠãããªã¿ãŒã³ ã¢ãã¬ã¹ãå€æŽããŠããããšã«æ°ã¥ãã§ãããã ãã®åŸã©ããªãããèšç®ããŠã¿ãŸããã
ã³ãŒãã®å®è¡ã ç¹å®ã®ã¢ãã¬ã¹ 1xB0 ã R130 ã«ããŒãããããããã 5 ãæžç®ããããã®åŸ R0 ã«è»¢éãããããã« 0x10 ãå ç®ãããŸãã 0xB13B ã§ããããšãããããŸãã ãããã£ãŠãIDA ã¯æåŸã®åœä»€ãéåžžã®é¢æ°ãªã¿ãŒã³ã§ãããšèããŸãããå®éã«ã¯èšç®ãããã¢ãã¬ã¹ 0xB13B ã«ç§»åããŸãã
ããã§ãARM ããã»ããµã«ã¯ ARM ãš Thumb ãšãã 0 ã€ã®ã¢ãŒããš 13 ã€ã®åœä»€ã»ãããããããšãæãåºããŠãã ããã ã¢ãã¬ã¹ã®æäžäœãããã¯ãã©ã®åœä»€ã»ããã䜿çšãããŠããããããã»ããµã«äŒããŸãã ã€ãŸããã¢ãã¬ã¹ã¯å®éã«ã¯ XNUMXxBXNUMXA ã§ãæäžäœãããã® XNUMX ã€ã¯ Thumb ã¢ãŒãã瀺ããŸãã
åæ§ã®ãã¢ããã¿ãŒãããã®ã©ã€ãã©ãªã®åé¢æ°ã®å
é ã«è¿œå ãããŠããã
ãŽãã³ãŒãã ãã以äžè©³ããã¯èª¬æããŸãã - ãã èŠããŠããã ãã§ã
ã»ãšãã©ãã¹ãŠã®æ©èœã®æ¬åœã®å§ãŸãã¯ããå°ãå
ã ãšããããšã§ãã
ã³ãŒãã¯æ瀺çã« 0xB13A ã«ãžã£ã³ãããªããããIDA èªäœã¯ã³ãŒãããã®å Žæã«ããããšãèªèããŸããã§ããã åãçç±ã§ãã©ã€ãã©ãªå ã®ã³ãŒãã®ã»ãšãã©ãã³ãŒããšããŠèªèãããªããããåæãããå°é£ã«ãªããŸãã IDA ã«ãããã³ãŒãã§ãããšäŒãããšã次ã®ããšãèµ·ãããŸãã
ããŒãã«ã¯æããã« 0xB144 ããå§ãŸããŸãã sub_494C ã«ã¯äœãå
¥ã£ãŠããŸãã?
LR ã¬ãžã¹ã¿ã§ãã®é¢æ°ãåŒã³åºããšãåè¿°ã®ããŒãã«ã®ã¢ãã¬ã¹ (0xB144) ãååŸãããŸãã R0 - ãã®ããŒãã«ã®ã€ã³ããã¯ã¹ã ã€ãŸããããŒãã«ããå€ãååŸãããLR ã«å ç®ãããçµæã¯æ¬¡ã®ããã«ãªããŸãã
è¡ãå
ã®äœæã èšç®ããŠã¿ãŸããã: 0xB144 + [0xB144 + 8* 4] = 0xB144 + 0x120 = 0xB264ã åä¿¡ããã¢ãã¬ã¹ã«ç§»åãããšãæåéãããã€ãã®æçšãªåœä»€ã衚瀺ãããåã³ 0xB140 ã«ç§»åããŸãã
ããã§ãããŒãã«ããã®ã€ã³ããã¯ã¹ 0x20 ã®ãªãã»ããã«é·ç§»ãååšããŸãã
ããŒãã«ã®ãµã€ãºããå€æãããšãã³ãŒãå ã«ãã®ãããªé·ç§»ãå€æ°ããããšãããããŸãã ã¢ãã¬ã¹ãæåã§èšç®ããã«ãäœããã®æ¹æ³ã§ããèªåçã«ããã«å¯ŸåŠããããšãã§ãããã©ãããšããçåãçããŸãã ãããŠãIDA ã®ã¹ã¯ãªãããšã³ãŒãã«ããããé©çšããæ©èœã圹ã«ç«ã¡ãŸãã
def put_unconditional_branch(source, destination):
offset = (destination - source - 4) >> 1
if offset > 2097151 or offset < -2097152:
raise RuntimeError("Invalid offset")
if offset > 1023 or offset < -1024:
instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
instruction2 = 0xb800 | (offset & 0x7ff)
patch_word(source, instruction1)
patch_word(source + 2, instruction2)
else:
instruction = 0xe000 | (offset & 0x7ff)
patch_word(source, instruction)
ea = here()
if get_wide_word(ea) == 0xb503: #PUSH {R0,R1,LR}
ea1 = ea + 2
if get_wide_word(ea1) == 0xbf00: #NOP
ea1 += 2
if get_operand_type(ea1, 0) == 1 and get_operand_value(ea1, 0) == 0 and get_operand_type(ea1, 1) == 2:
index = get_wide_dword(get_operand_value(ea1, 1))
print "index =", hex(index)
ea1 += 2
if get_operand_type(ea1, 0) == 7:
table = get_operand_value(ea1, 0) + 4
elif get_operand_type(ea1, 1) == 2:
table = get_operand_value(ea1, 1) + 4
else:
print "Wrong operand type on", hex(ea1), "-", get_operand_type(ea1, 0), get_operand_type(ea1, 1)
table = None
if table is None:
print "Unable to find table"
else:
print "table =", hex(table)
offset = get_wide_dword(table + (index << 2))
put_unconditional_branch(ea, table + offset)
else:
print "Unknown code", get_operand_type(ea1, 0), get_operand_value(ea1, 0), get_operand_type(ea1, 1) == 2
else:
print "Unable to detect first instruction"
ã«ãŒãœã«ãè¡ 0xB26A ã«çœ®ããã¹ã¯ãªãããå®è¡ããŠã0xB4B0 ãžã®é·ç§»ã確èªããŸãã
IDAã¯åã³ãã®é åãã³ãŒããšããŠèªèããŸããã§ããã ç§ãã¡ã¯åœŒå¥³ãæäŒããããã§å¥ã®ãã¶ã€ã³ã確èªããŸãã
BLX ã®åŸã®æ瀺ã¯ããŸãæå³ããªãããã§ãããçš®ã®ç§»åã®ãããªãã®ã§ãã sub_4964 ãèŠãŠã¿ãŸãããã
å®éãããã§ã¯ LR ã«ããã¢ãã¬ã¹ã§ dword ãååŸããããã®ã¢ãã¬ã¹ã«è¿œå ããããã®åŸãçµæã®ã¢ãã¬ã¹ã®å€ãååŸãããŠã¹ã¿ãã¯ã«çœ®ãããŸãã ãŸããé¢æ°ããæ»ã£ãåŸããã®åããªãã»ãããã¹ããããããããã«ãLR ã« 4 ãè¿œå ãããŸãã ãã®åŸãPOP {R1} ã³ãã³ãã¯çµæã®å€ãã¹ã¿ãã¯ããååŸããŸãã ã¢ãã¬ã¹ 0xB4BA + 0xEA = 0xB5A4 ã«ãããã®ãèŠããšãã¢ãã¬ã¹ ããŒãã«ã®ãããªãã®ã衚瀺ãããŸãã
ãã®ãã¶ã€ã³ã«ããããé©çšããã«ã¯ãã³ãŒããã XNUMX ã€ã®ãã©ã¡ãŒã¿ãŒããªãã»ãããšçµæãæ ŒçŽããã¬ãžã¹ã¿çªå·ãååŸããå¿
èŠããããŸãã èããããã¬ãžã¹ã¿ããšã«ãäºåã«ã³ãŒããæºåããå¿
èŠããããŸãã
patches = {}
patches[0] = (0x00, 0xbf, 0x01, 0x48, 0x00, 0x68, 0x02, 0xe0)
patches[1] = (0x00, 0xbf, 0x01, 0x49, 0x09, 0x68, 0x02, 0xe0)
patches[2] = (0x00, 0xbf, 0x01, 0x4a, 0x12, 0x68, 0x02, 0xe0)
patches[3] = (0x00, 0xbf, 0x01, 0x4b, 0x1b, 0x68, 0x02, 0xe0)
patches[4] = (0x00, 0xbf, 0x01, 0x4c, 0x24, 0x68, 0x02, 0xe0)
patches[5] = (0x00, 0xbf, 0x01, 0x4d, 0x2d, 0x68, 0x02, 0xe0)
patches[8] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0x80, 0xd8, 0xf8, 0x00, 0x80, 0x01, 0xe0)
patches[9] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0x90, 0xd9, 0xf8, 0x00, 0x90, 0x01, 0xe0)
patches[10] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0xa0, 0xda, 0xf8, 0x00, 0xa0, 0x01, 0xe0)
patches[11] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0xb0, 0xdb, 0xf8, 0x00, 0xb0, 0x01, 0xe0)
ea = here()
if (get_wide_word(ea) == 0xb082 #SUB SP, SP, #8
and get_wide_word(ea + 2) == 0xb503): #PUSH {R0,R1,LR}
if get_operand_type(ea + 4, 0) == 7:
pop = get_bytes(ea + 12, 4, 0)
if pop[1] == 'xbc':
register = -1
r = get_wide_byte(ea + 12)
for i in range(8):
if r == (1 << i):
register = i
break
if register == -1:
print "Unable to detect register"
else:
address = get_wide_dword(ea + 8) + ea + 8
for b in patches[register]:
patch_byte(ea, b)
ea += 1
if ea % 4 != 0:
ea += 2
patch_dword(ea, address)
elif pop[:3] == 'x5dxf8x04':
register = ord(pop[3]) >> 4
if register in patches:
address = get_wide_dword(ea + 8) + ea + 8
for b in patches[register]:
patch_byte(ea, b)
ea += 1
patch_dword(ea, address)
else:
print "POP instruction not found"
else:
print "Wrong operand type on +4:", get_operand_type(ea + 4, 0)
else:
print "Unable to detect first instructions"
眮æããæ§é äœã®å é (0xB4B2) ã«ã«ãŒãœã«ã眮ããã¹ã¯ãªãããå®è¡ããŸãã
ãã§ã«è¿°ã¹ãæ§é ã«å ããŠãã³ãŒãã«ã¯æ¬¡ã®ãã®ãå«ãŸããŠããŸãã
åã®ã±ãŒã¹ãšåæ§ã«ãBLX åœä»€ã®åŸã«ãªãã»ããããããŸãã
LR ããã¢ãã¬ã¹ãžã®ãªãã»ãããååŸããããã LR ã«è¿œå ããŠãããã«ç§»åããŸãã 0x72044 + 0xC = 0x72050ã ãã®èšèšã®ã¹ã¯ãªããã¯éåžžã«åçŽã§ãã
def put_unconditional_branch(source, destination):
offset = (destination - source - 4) >> 1
if offset > 2097151 or offset < -2097152:
raise RuntimeError("Invalid offset")
if offset > 1023 or offset < -1024:
instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
instruction2 = 0xb800 | (offset & 0x7ff)
patch_word(source, instruction1)
patch_word(source + 2, instruction2)
else:
instruction = 0xe000 | (offset & 0x7ff)
patch_word(source, instruction)
ea = here()
if get_wide_word(ea) == 0xb503: #PUSH {R0,R1,LR}
ea1 = ea + 6
if get_wide_word(ea + 2) == 0xbf00: #NOP
ea1 += 2
offset = get_wide_dword(ea1)
put_unconditional_branch(ea, (ea1 + offset) & 0xffffffff)
else:
print "Unable to detect first instruction"
ã¹ã¯ãªããã®å®è¡çµæ:
é¢æ°å
ã§ãã¹ãŠã®ããããé©çšããããIDA ããã®æ¬åœã®å§ãŸãã«åããããšãã§ããŸãã ãã¹ãŠã®é¢æ°ã³ãŒããçµåãããHexRays ã䜿çšããŠéã³ã³ãã€ã«ã§ããŸãã
æååã®ãã³ãŒã
ç§ãã¡ã¯ã©ã€ãã©ãªå ã®ãã·ã³ã³ãŒãã®é£èªåã«å¯ŸåŠããæ¹æ³ãåŠã³ãŸãã libsgmainso-6.4.36.so UCãã©ãŠã¶ããæ©èœã³ãŒããåä¿¡ããŸãã JNI_OnLoad.
int __fastcall real_JNI_OnLoad(JavaVM *vm)
{
int result; // r0
jclass clazz; // r0 MAPDST
int v4; // r0
JNIEnv *env; // r4
int v6; // [sp-40h] [bp-5Ch]
int v7; // [sp+Ch] [bp-10h]
v7 = *(_DWORD *)off_8AC00;
if ( !vm )
goto LABEL_39;
sub_7C4F4();
env = (JNIEnv *)sub_7C5B0(0);
if ( !env )
goto LABEL_39;
v4 = sub_72CCC();
sub_73634(v4);
sub_73E24(&unk_83EA6, &v6, 49);
clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);
if ( clazz
&& (sub_9EE4(),
sub_71D68(env),
sub_E7DC(env) >= 0
&& sub_69D68(env) >= 0
&& sub_197B4(env, clazz) >= 0
&& sub_E240(env, clazz) >= 0
&& sub_B8B0(env, clazz) >= 0
&& sub_5F0F4(env, clazz) >= 0
&& sub_70640(env, clazz) >= 0
&& sub_11F3C(env) >= 0
&& sub_21C3C(env, clazz) >= 0
&& sub_2148C(env, clazz) >= 0
&& sub_210E0(env, clazz) >= 0
&& sub_41B58(env, clazz) >= 0
&& sub_27920(env, clazz) >= 0
&& sub_293E8(env, clazz) >= 0
&& sub_208F4(env, clazz) >= 0) )
{
result = (sub_B7B0(env, clazz) >> 31) | 0x10004;
}
else
{
LABEL_39:
result = -1;
}
return result;
}
次ã®è¡ã詳ããèŠãŠã¿ãŸãããã
sub_73E24(&unk_83EA6, &v6, 49);
clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);
æ©èœäž ãµã_73E24 ã¯ã©ã¹åã¯æããã«åŸ©å·åãããŠããŸãã ãã®é¢æ°ã®ãã©ã¡ãŒã¿ãšããŠãæå·åããŒã¿ãšåæ§ã®ããŒã¿ãžã®ãã€ã³ã¿ãç¹å®ã®ãããã¡ãããã³æ°å€ãæž¡ãããŸãã æããã«ãé¢æ°ãåŒã³åºããåŸã¯ãé¢æ°ã«æž¡ãããããããããã¡ãŒã«åŸ©å·åãããè¡ãååšããŸãã ã¯ã©ã¹ã®æ€çŽ¢ãã¯ã©ã¹åã XNUMX çªç®ã®ãã©ã¡ãŒã¿ãšããŠåãåããŸãã ãããã£ãŠããã®æ°å€ã¯ãããã¡ã®ãµã€ãºãŸãã¯è¡ã®é·ãã«ãªããŸãã ã¯ã©ã¹åã解èªããŠã¿ãŸããããæ£ããæ¹åã«é²ãã§ãããã©ããããããã¯ãã§ãã ã§äœãèµ·ãããã詳ããèŠãŠã¿ãŸããã ãµã_73E24ã
int __fastcall sub_73E56(unsigned __int8 *in, unsigned __int8 *out, size_t size)
{
int v4; // r6
int v7; // r11
int v8; // r9
int v9; // r4
size_t v10; // r5
int v11; // r0
struc_1 v13; // [sp+0h] [bp-30h]
int v14; // [sp+1Ch] [bp-14h]
int v15; // [sp+20h] [bp-10h]
v4 = 0;
v15 = *(_DWORD *)off_8AC00;
v14 = 0;
v7 = sub_7AF78(17);
v8 = sub_7AF78(size);
if ( !v7 )
{
v9 = 0;
goto LABEL_12;
}
(*(void (__fastcall **)(int, const char *, int))(v7 + 12))(v7, "DcO/lcK+h?m3c*q@", 16);
if ( !v8 )
{
LABEL_9:
v4 = 0;
goto LABEL_10;
}
v4 = 0;
if ( !in )
{
LABEL_10:
v9 = 0;
goto LABEL_11;
}
v9 = 0;
if ( out )
{
memset(out, 0, size);
v10 = size - 1;
(*(void (__fastcall **)(int, unsigned __int8 *, size_t))(v8 + 12))(v8, in, v10);
memset(&v13, 0, 0x14u);
v13.field_4 = 3;
v13.field_10 = v7;
v13.field_14 = v8;
v11 = sub_6115C(&v13, &v14);
v9 = v11;
if ( v11 )
{
if ( *(_DWORD *)(v11 + 4) == v10 )
{
qmemcpy(out, *(const void **)v11, v10);
v4 = *(_DWORD *)(v9 + 4);
}
else
{
v4 = 0;
}
goto LABEL_11;
}
goto LABEL_9;
}
LABEL_11:
sub_7B148(v7);
LABEL_12:
if ( v8 )
sub_7B148(v8);
if ( v9 )
sub_7B148(v9);
return v4;
}
æ©èœ ãµã_7AF78 æå®ããããµã€ãºã®ãã€ãé åã®ã³ã³ãããŒã®ã€ã³ã¹ã¿ã³ã¹ãäœæããŸã (ãããã®ã³ã³ãããŒã«ã€ããŠã¯è©³ãã説æããŸãã)ã ããã§ã¯ããã®ãããªã³ã³ããã XNUMX ã€äœæãããŸããXNUMX ã€ã¯æ¬¡ã®è¡ãå«ã¿ãŸãã ãDcO/lcK+h?m3c*q@ã (ãããããŒã§ããããšã¯ç°¡åã«æšæž¬ã§ããŸã)ãããäžæ¹ã«ã¯æå·åãããããŒã¿ãå«ãŸããŠããŸãã 次ã«ãäž¡æ¹ã®ãªããžã§ã¯ããç¹å®ã®æ§é äœã«é 眮ãããé¢æ°ã«æž¡ãããŸãã ãµã_6115Cã ãŸãããã®æ§é äœã®ãã£ãŒã«ãã«å€ 3 ãããŒã¯ããŠã次ã«ãã®æ§é äœã«äœãèµ·ããããèŠãŠã¿ãŸãããã
int __fastcall sub_611B4(struc_1 *a1, _DWORD *a2)
{
int v3; // lr
unsigned int v4; // r1
int v5; // r0
int v6; // r1
int result; // r0
int v8; // r0
*a2 = 820000;
if ( a1 )
{
v3 = a1->field_14;
if ( v3 )
{
v4 = a1->field_4;
if ( v4 < 0x19 )
{
switch ( v4 )
{
case 0u:
v8 = sub_6419C(a1->field_0, a1->field_10, v3);
goto LABEL_17;
case 3u:
v8 = sub_6364C(a1->field_0, a1->field_10, v3);
goto LABEL_17;
case 0x10u:
case 0x11u:
case 0x12u:
v8 = sub_612F4(
a1->field_0,
v4,
*(_QWORD *)&a1->field_8,
*(_QWORD *)&a1->field_8 >> 32,
a1->field_10,
v3,
a2);
goto LABEL_17;
case 0x14u:
v8 = sub_63A28(a1->field_0, v3);
goto LABEL_17;
case 0x15u:
sub_61A60(a1->field_0, v3, a2);
return result;
case 0x16u:
v8 = sub_62440(a1->field_14);
goto LABEL_17;
case 0x17u:
v8 = sub_6226C(a1->field_10, v3);
goto LABEL_17;
case 0x18u:
v8 = sub_63530(a1->field_14);
LABEL_17:
v6 = 0;
if ( v8 )
{
*a2 = 0;
v6 = v8;
}
return v6;
default:
LOWORD(v5) = 28032;
goto LABEL_5;
}
}
}
}
LOWORD(v5) = -27504;
LABEL_5:
HIWORD(v5) = 13;
v6 = 0;
*a2 = v5;
return v6;
}
switch ãã©ã¡ãŒã¿ã¯ã以åã«å€ 3 ãå²ãåœãŠãããŠããæ§é äœãã£ãŒã«ãã§ããã±ãŒã¹ 3 ãèŠãŠãã ãã: é¢æ°ãž ãµã_6364C ãã©ã¡ãŒã¿ã¯ãåã®é¢æ°ã§è¿œå ãããæ§é äœãã€ãŸãããŒãšæå·åãããããŒã¿ããæž¡ãããŸãã ããèŠããš ãµã_6364Cããã®äžã« RC4 ã¢ã«ãŽãªãºã ãããããšãããããŸãã
ã¢ã«ãŽãªãºã ãšéµããããŸãã ã¯ã©ã¹åã解èªããŠã¿ãŸãããã äœãèµ·ãã£ããã¯æ¬¡ã®ãšããã§ãã com/taobao/wireless/security/adapter/JNICLibraryã çŽ æŽãããïŒ ç§ãã¡ã¯æ£ããéãé²ãã§ããŸãã
ã³ãã³ãããªãŒ
ä»ãç§ãã¡ã¯èª²é¡ãèŠã€ããå¿ èŠããããŸã ãã€ãã£ããç»é²ãããé¢æ°ã瀺ããŸã doCommandãã€ãã£ãã ããåŒã³åºãããé¢æ°ãèŠãŠã¿ãŸããã JNI_OnLoadã ãããŠãããèŠã€ããŸã ãµã_B7B0:
int __fastcall sub_B7F6(JNIEnv *env, jclass clazz)
{
char signature[41]; // [sp+7h] [bp-55h]
char name[16]; // [sp+30h] [bp-2Ch]
JNINativeMethod method; // [sp+40h] [bp-1Ch]
int v8; // [sp+4Ch] [bp-10h]
v8 = *(_DWORD *)off_8AC00;
decryptString((unsigned __int8 *)&unk_83ED9, (unsigned __int8 *)name, 0x10u);// doCommandNative
decryptString((unsigned __int8 *)&unk_83EEA, (unsigned __int8 *)signature, 0x29u);// (I[Ljava/lang/Object;)Ljava/lang/Object;
method.name = name;
method.signature = signature;
method.fnPtr = sub_B69C;
return ((int (__fastcall *)(JNIEnv *, jclass, JNINativeMethod *, int))(*env)->RegisterNatives)(env, clazz, &method, 1) >> 31;
}
ãããŠç¢ºãã«ããã®ååã®ãã€ãã£ãã¡ãœãããããã«ç»é²ãããŠããŸã doCommandãã€ãã£ãã ä»ãç§ãã¡ã¯åœŒã®äœæãç¥ã£ãŠããŸãã 圌ãäœãããã®ãèŠãŠã¿ãŸãããã
int __fastcall doCommandNative(JNIEnv *env, jobject obj, int command, jarray args)
{
int v5; // r5
struc_2 *a5; // r6
int v9; // r1
int v11; // [sp+Ch] [bp-14h]
int v12; // [sp+10h] [bp-10h]
v5 = 0;
v12 = *(_DWORD *)off_8AC00;
v11 = 0;
a5 = (struc_2 *)malloc(0x14u);
if ( a5 )
{
a5->field_0 = 0;
a5->field_4 = 0;
a5->field_8 = 0;
a5->field_C = 0;
v9 = command % 10000 / 100;
a5->field_0 = command / 10000;
a5->field_4 = v9;
a5->field_8 = command % 100;
a5->field_C = env;
a5->field_10 = args;
v5 = sub_9D60(command / 10000, v9, command % 100, 1, (int)a5, &v11);
}
free(a5);
if ( !v5 && v11 )
sub_7CF34(env, v11, &byte_83ED7);
return v5;
}
ååããããããéçºè ããã€ãã£ã ã©ã€ãã©ãªã«ç§»è¡ããããšã決å®ãããã¹ãŠã®é¢æ°ã®ãšã³ã㪠ãã€ã³ãã§ããããšãæšæž¬ã§ããŸãã ç§ãã¡ã¯é¢æ°çªå· 10601 ã«èå³ããããŸãã
ã³ãŒããããã³ãã³ãçªå·ã«ãã£ãŠ XNUMX ã€ã®æ°åãçæãããããšãããããŸãã ã³ãã³ã/10000, ã³ãã³ã % 10000 / 100 О ã³ãã³ã %10ã€ãŸãããã®å Žå㯠1ã6ã1 ã§ããããã XNUMX ã€ã®æ°åãšããžã®ãã€ã³ã¿ã§ãã JNIç°å¢ é¢æ°ã«æž¡ãããåŒæ°ã¯æ§é äœã«è¿œå ãããŠæž¡ãããŸãã ååŸãã 1 ã€ã®æ°å€ (N2ãN3ãNXNUMX ãšããŸã) ã䜿çšããŠãã³ãã³ã ããªãŒãæ§ç¯ãããŸãã
ãã®ãããªãã®ïŒ
ããªãŒã¯åçã«åããããŸã JNI_OnLoad.
XNUMX ã€ã®æ°åãããªãŒå
ã®ãã¹ããšã³ã³ãŒãããŸãã ããªãŒã®åãªãŒãã«ã¯ã察å¿ããé¢æ°ã®ãããã³ã° ã¢ãã¬ã¹ãå«ãŸããŠããŸãã ããŒã¯èŠªããŒãã«ãããŸãã 䜿çšãããŠãããã¹ãŠã®æ§é ãç解ããŠããã°ãå¿
èŠãªé¢æ°ãããªãŒã«è¿œå ãããŠããã³ãŒãå
ã®å ŽæãèŠã€ããããšã¯é£ãããããŸãã (ãã§ã«ããªã倧ããªèšäºãè¥å€§åããªãããã«ãæ§é ã«ã€ããŠã¯èª¬æããŸãã)ã
ãããªãé£èªå
ãã©ãã£ãã¯ã埩å·åããå¿ èŠãããé¢æ°ã®ã¢ãã¬ã¹: 0x5F1AC ãåãåããŸããã ããããåã¶ã®ã¯ææå°æ©ã§ããUC ãã©ãŠã¶ã®éçºè ã¯ãç§ãã¡ã«å¥ã®ãµãã©ã€ãºãçšæããŠãããŸããã
Java ã³ãŒãã§åœ¢æãããé
åãããã©ã¡ãŒã¿ãåãåã£ãåŸã次ã®çµæãååŸããŸãã
ã¢ãã¬ã¹ 0x4D070 ã®é¢æ°ã«éä¿¡ããŸãã ãããŠããã§ãå¥ã®ã¿ã€ãã®ã³ãŒãé£èªåãç§ãã¡ãåŸ
ã£ãŠããŸãã
R7 ãš R4 ã« XNUMX ã€ã®ã€ã³ããã¯ã¹ã眮ããŸãã
æåã®ã€ã³ããã¯ã¹ã R11 ã«ã·ããããŸãã
ããŒãã«ããã¢ãã¬ã¹ãååŸããã«ã¯ãã€ã³ããã¯ã¹ã䜿çšããŸãã
æåã®ã¢ãã¬ã¹ã«ç§»åããåŸãR4 ã«ãã 230 çªç®ã®ã€ã³ããã¯ã¹ã䜿çšãããŸãã ããŒãã«ã«ã¯ XNUMX åã®èŠçŽ ããããŸãã
ããã«ã€ããŠã©ãããã°ããã§ããããïŒ ãããã¹ã€ããã§ããããšã IDA ã«äŒããããšãã§ããŸãã[ç·šé] -> [ãã®ä»] -> [ã¹ã€ãã ã€ãã£ãªã ãæå®] ãéžæããŸãã
çµæãšããŠåŸãããã³ãŒãã¯æããããã®ã§ãã ãããããžã£ã³ã°ã«ãæããŠãããšããã§ã«ããªãã¿ã®é¢æ°ãåŒã³åºãããŠããããšã«æ°ã¥ãã§ãããã ãµã_6115C:
ã±ãŒã¹ 3 ã§ã¯ãRC4 ã¢ã«ãŽãªãºã ã䜿çšãã埩å·åãè¡ãããã¹ã€ããããããŸããã ãã®å Žåãé¢æ°ã«æž¡ãããæ§é äœã«ã¯ãé¢æ°ã«æž¡ããããã©ã¡ãŒã¿ãå
¥åãããŸãã doCommandãã€ãã£ãã ããã§äœãé£ã¹ããæãåºããŸããã ããžãã¯ã€ã³ã 察å¿ããã±ãŒã¹ã調ã¹ãããã€ãã®é·ç§»ã®åŸãã¢ã«ãŽãªãºã ãèå¥ã§ããã³ãŒããèŠã€ããŸãã
ãããAESã§ãïŒ
ã¢ã«ãŽãªãºã ã¯ååšããŸããæ®ã£ãŠããã®ã¯ããã®ãã©ã¡ãŒã¿ãŒ (ã¢ãŒããããŒãããã³å Žåã«ãã£ãŠã¯åæåãã¯ãã«) ãååŸããããšã ãã§ã (ã¢ã«ãŽãªãºã ã®ååšã¯ AES ã¢ã«ãŽãªãºã ã®åäœã¢ãŒãã«ãã£ãŠç°ãªããŸã)ã ããããå«ãæ§é ã¯ãé¢æ°åŒã³åºãã®åã®ã©ããã§åœ¢æããå¿ èŠããããŸãã ãµã_6115Cããããã³ãŒãã®ãã®éšåã¯ç¹ã«ããé£èªåãããŠããããã埩å·åé¢æ°ã®ãã¹ãŠã®ãã©ã¡ãŒã¿ããã¡ã€ã«ã«ãã³ããããããã«ã³ãŒãã«ããããé©çšãããšããã¢ã€ãã¢ãçãŸããŸããã
ããã
ãã¹ãŠã®ããã ã³ãŒããæåã§ã¢ã»ã³ããªèšèªã§èšè¿°ããªãããã«ããã«ã¯ãAndroid Studio ãèµ·åãã埩å·åé¢æ°ãšåãå ¥åãã©ã¡ãŒã¿ãåãåãããã¡ã€ã«ã«æžã蟌ãé¢æ°ãããã«èšè¿°ããã³ã³ãã€ã©ãæå®ããã³ãŒããã³ããŒããŠè²Œãä»ããŸããçæããã
UC Browser ããŒã ã®å人ãã¡ããã³ãŒããè¿œå ããéã®å©äŸ¿æ§ãèæ ®ããŠãããŸããã åé¢æ°ã®å é ã«ã¯ãç°¡åã«ä»ã®é¢æ°ã«çœ®ãæããããšãã§ããã¬ããŒãž ã³ãŒããããããšãæãåºããŠãã ããã éåžžã«äŸ¿å©ã§ã ð ãã ããã¿ãŒã²ããé¢æ°ã®å é ã«ã¯ããã¹ãŠã®ãã©ã¡ãŒã¿ãŒããã¡ã€ã«ã«ä¿åããã³ãŒããé 眮ããããã®ååãªã¹ããŒã¹ããããŸããã ãããéšåã«åå²ããé£æ¥ããé¢æ°ã®ã¬ããŒãž ãããã¯ã䜿çšããå¿ èŠããããŸããã å šéšã§XNUMXã€ã®ããŒãããããŸããã
æåã®éšåïŒ
ARM ã¢ãŒããã¯ãã£ã§ã¯ãæåã® 0 ã€ã®é¢æ°ãã©ã¡ãŒã¿ã¯ã¬ãžã¹ã¿ R3 ïœ R0 ãä»ããŠæž¡ãããæ®ã㯠(ååšããå Žå) ã¹ã¿ãã¯ãä»ããŠæž¡ãããŸãã LR ã¬ãžã¹ã¿ã¯æ»ãã¢ãã¬ã¹ãä¿æããŸãã ãã©ã¡ãŒã¿ããã³ãããåŸã«é¢æ°ãåäœã§ããããã«ãããããã¹ãŠãä¿åããå¿
èŠããããŸãã ãŸããããã»ã¹ã§äœ¿çšãããã¹ãŠã®ã¬ãžã¹ã¿ãä¿åããå¿
èŠããããããPUSH.W {R10-R7,LR} ãå®è¡ããŸãã RXNUMX ã§ã¯ãã¹ã¿ãã¯çµç±ã§é¢æ°ã«æž¡ããããã©ã¡ãŒã¿ãŒã®ãªã¹ãã®ã¢ãã¬ã¹ãååŸããŸãã
æ©èœã®äœ¿çš ãã©ãã³ ãã¡ã€ã«ãéããŠã¿ãŸããã /data/local/tmp/aes ãè
¹çãã¢ãŒãã§
ã€ãŸãè¿œå çšã§ãã R0 ã«ã¯ãã¡ã€ã«åã®ã¢ãã¬ã¹ãããŒãããR1 ã«ã¯ã¢ãŒãã瀺ãè¡ã®ã¢ãã¬ã¹ãããŒãããŸãã ããã§ãŽãã³ãŒãã¯çµäºããã®ã§ã次ã®é¢æ°ã«é²ã¿ãŸãã åäœãç¶ããããã«ãæåã«é¢æ°ã®å®éã®ã³ãŒããžã®é·ç§»ãé
眮ããŠã¬ããŒãžããã€ãã¹ããã¬ããŒãžã®ä»£ããã«ãããã®ç¶ç¶ãè¿œå ããŸãã
åŒã³åºã ãã©ãã³.
é¢æ°ã®æåã® XNUMX ã€ã®ãã©ã¡ãŒã¿ ãšãŒã¹ ã¿ã€ãããã intåã æåã«ã¬ãžã¹ã¿ãã¹ã¿ãã¯ã«ä¿åããã®ã§ãåçŽã«é¢æ°ãæž¡ãããšãã§ããŸãã æžã蟌㿠ã¹ã¿ãã¯äžã®ã¢ãã¬ã¹ã
次ã«ãããŒã¿ ãµã€ãºãšãããŒãåæåãã¯ãã«ãããã³æå·åããŒã¿ã®ããŒã¿ãžã®ãã€ã³ã¿ãŒãå«ã XNUMX ã€ã®æ§é äœããããŸãã
æåŸã«ããã¡ã€ã«ãéããã¬ãžã¹ã¿ã埩å
ããå¶åŸ¡ãå®éã®é¢æ°ã«ç§»ããŸãã ãšãŒã¹.
ããããé©çšãããã©ã€ãã©ãªãå«ã APK ãåéãã眲åããããã€ã¹/ãšãã¥ã¬ãŒã¿ãŒã«ã¢ããããŒãããŠèµ·åããŸãã ãã³ããäœæãããããã«å€§éã®ããŒã¿ãæžã蟌ãŸããŠããããšãããããŸãã ãã©ãŠã¶ã¯ãã©ãã£ãã¯ã ãã§ãªãæå·åã䜿çšãããã¹ãŠã®æå·åã¯åœè©²ã®æ©èœãééããŸãã ããããäœããã®çç±ã§å¿ èŠãªããŒã¿ãååšãããå¿ èŠãªãªã¯ãšã¹ãããã©ãã£ãã¯å ã«è¡šç€ºãããŸããã UC ãã©ãŠã¶ãå¿ èŠãªãªã¯ãšã¹ããè¡ãããã«ãªããŸã§åŸ ããªãããã«ã以åã«åä¿¡ãããµãŒããŒããæå·åãããå¿çãååŸããŠãã¢ããªã±ãŒã·ã§ã³ã«å床ããããé©çšããŸããããã¡ã€ã³ ã¢ã¯ãã£ããã£ã® onCreate ã«åŸ©å·åãè¿œå ããŸãã
const/16 v1, 0x62
new-array v1, v1, [B
fill-array-data v1, :encrypted_data
const/16 v0, 0x1f
invoke-static {v0, v1}, Lcom/uc/browser/core/d/c/g;->j(I[B)[B
move-result-object v1
array-length v2, v1
invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v2
const-string v0, "ololo"
invoke-static {v0, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
ç§ãã¡ã¯çµã¿ç«ãŠã眲åãèšçœ®ãæã¡äžããè¡ããŸãã ã¡ãœããã null ãè¿ãããããNullPointerException ãåãåããŸãã
ã³ãŒããããã«åæãããšãèå³æ·±ãè¡ãMETA-INF/ããšã.RSAãã解èªããé¢æ°ãçºèŠãããŸããã ã¢ããªã±ãŒã·ã§ã³ã蚌ææžãæ€èšŒããŠããããã§ãã ãããã¯ãããããããŒãçæããããšãã§ããŸãã 蚌ææžã§äœãèµ·ãã£ãŠãããã«ã€ããŠã¯ããŸãæ±ããããªãã®ã§ãæ£ãã蚌ææžãå·®ã蟌ãã ãã§ãã æå·åãããè¡ã«ããããé©çšããŠããMETA-INF/ãã®ä»£ããã«ãBLABLINF/ããååŸããAPK å ã«ãã®ååã®ãã©ã«ããŒãäœæããããã«ãªã¹ ãã©ãŠã¶èšŒææžãè¿œå ããŸãããã
ç§ãã¡ã¯çµã¿ç«ãŠã眲åãèšçœ®ãæã¡äžããè¡ããŸãã ãã³ãŽïŒ ç§ãã¡ã¯éµãæã£ãŠããŸãïŒ
MitM
ããŒãšãã®ããŒã«çããåæåãã¯ãã«ãåãåããŸããã CBC ã¢ãŒãã§ãµãŒããŒå¿çã埩å·åããŠã¿ãŸãããã
MD5 ã«äŒŒãã¢ãŒã«ã€ã URLããextract_unzipsizeããšæ°åã衚瀺ãããŸãã ã¢ãŒã«ã€ãã® MD5 ãåãã§ããã解åãããã©ã€ãã©ãªã®ãµã€ãºãåãã§ããããšã確èªããŸãã ãã®ã©ã€ãã©ãªã«ããããé©çšããŠãã©ãŠã¶ã«æäŸããããšããŠããŸãã ããããé©çšããã©ã€ãã©ãªãããŒããããããšã瀺ãããã«ããPWNED!ããšããããã¹ããå«ã SMS ãäœæããã€ã³ãã³ããèµ·åããŸãã ãµãŒããŒããã® XNUMX ã€ã®å¿çã眮ãæããŸãã
ãã©ãŠã¶ã¯ã¢ãŒã«ã€ããæ°åããŠã³ããŒãããããšããŸããããã®åŸãšã©ãŒãçºçããŸãã ã©ãããäœã
圌ã¯å¥œããããªãã ãã®ææ§ãªåœ¢åŒãåæããçµæããµãŒããŒã¯ã¢ãŒã«ã€ãã®ãµã€ãºãéä¿¡ããŠããããšãå€æããŸããã
LEB128ã§ãšã³ã³ãŒããããŠããŸãã ãããåŸãã©ã€ãã©ãªãå«ãã¢ãŒã«ã€ãã®ãµã€ãºãå°ãå€æŽãããããããã©ãŠã¶ã¯ã¢ãŒã«ã€ããäžæ£ã«ããŠã³ããŒãããããšå€æããæ°åè©Šè¡ããåŸã«ãšã©ãŒãã¹ããŒããŸããã
ã¢ãŒã«ã€ãã®ãµã€ãºã調æŽããŸã...ãããŠãåå©! ð çµæã¯ãããªã«ãããŸãã
çµæãšéçºè ã®åå¿
åæ§ã«ãããã«ãŒã¯ UC ãã©ãŠã¶ã®å®å šã§ãªãæ©èœãå©çšããŠãæªæã®ããã©ã€ãã©ãªãé åžããå®è¡ããå¯èœæ§ããããŸãã ãããã®ã©ã€ãã©ãªã¯ãã©ãŠã¶ã®ã³ã³ããã¹ãã§åäœããããããã¹ãŠã®ã·ã¹ãã æš©éãåãåããŸãã ãã®çµæããã£ãã·ã³ã° ãŠã£ã³ããŠã衚瀺ã§ããã ãã§ãªããããŒã¿ããŒã¹ã«ä¿åãããŠãããã°ã€ã³æ å ±ããã¹ã¯ãŒããCookie ãªã©ã®ãªã¬ã³ãžè²ã®ãã£ã€ããŒãº ãªã¹ã®äœæ¥ãã¡ã€ã«ã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸãã
ç§ãã¡ã¯ UC Browser ã®éçºè
ã«é£çµ¡ããçºèŠããåé¡ã«ã€ããŠäŒããè匱æ§ãšãã®å±éºæ§ãææããããšããŸããããäœã話ããŠãããŸããã§ããã ãã®éããã©ãŠã¶ã¯ãã®å±éºãªæ©èœãå
¬ç¶ãšèªç€ºãç¶ããŸããã ããããè匱æ§ã®è©³çŽ°ãæããã«ãªããšã以åã®ããã«ç¡èŠããããšã¯ã§ããªããªããŸããã 27æXNUMXæ¥ã¯
UC ãã©ãŠã¶ã®æ°ããããŒãžã§ã³ 12.10.9.1193 ããªãªãŒã¹ãããŸãããããã¯ãHTTPS çµç±ã§ãµãŒããŒã«ã¢ã¯ã»ã¹ããŸããã
ããã«ããä¿®æ£ãåŸããã®èšäºãæžããŠããæç¹ãŸã§ããã©ãŠã¶ã§ PDF ãéãããšãããšãããã£ãšãåé¡ãçºçããŸãã!ããšããããã¹ãã®ãšã©ãŒ ã¡ãã»ãŒãžã衚瀺ãããŸããã PDF ãéãããšãããšãã«ãµãŒããŒãžã®ãªã¯ãšã¹ãã¯è¡ãããŸããã§ãããããã©ãŠã¶ã®èµ·åæã«ãªã¯ãšã¹ããè¡ãããŸãããããã¯ãGoogle Play ã®ã«ãŒã«ã«éåããŠå®è¡å¯èœã³ãŒããããŠã³ããŒãããèœåãç¶ç¶çã«ååšããããšã瀺åããŠããŸãã
åºæïŒ habr.com