Kap chèche vilnerabilite nan navigatè UC

Kap chèche vilnerabilite nan navigatè UC

Entwodiksyon

Nan fen mwa mas nou rapòte, ke yo te dekouvri yon kapasite kache pou chaje ak kouri kòd ki pa verifye nan navigatè UC. Jodi a nou pral gade an detay sou ki jan download sa a rive ak ki jan entru ka itilize li pou pwòp rezon yo.

Kèk tan de sa, UC Browser te pibliye ak distribye trè agresif: li te enstale sou aparèy itilizatè yo lè l sèvi avèk malveyan, distribye nan divès sit anba laparans nan dosye videyo (sa vle di, itilizatè yo te panse yo t ap telechaje, pou egzanp, yon videyo pònografi, men olye te resevwa yon APK ak navigatè sa a), te itilize bandwòl pè ak mesaj ke navigatè a te demode, vilnerab, ak bagay konsa. Nan gwoup ofisyèl navigatè UC sou VK genyen sijè a, nan ki itilizatè yo ka pote plent sou piblisite enjis, gen anpil egzanp la. Nan 2016 te gen menm piblisite videyo an Ris (wi, piblisite pou yon navigatè ki bloke piblisite).

Nan moman sa a, navigatè UC gen plis pase 500 enstalasyon sou Google Play. Sa a se enpresyonan - sèlman Google Chrome gen plis. Pami revizyon yo ou ka wè yon anpil nan plent sou piblisite ak redireksyon nan kèk aplikasyon sou Google Play. Sa a se rezon ki fè rechèch nou an: nou deside wè si navigatè UC t ap fè yon move bagay. Epi li te tounen soti ke li fè sa!

Nan kòd aplikasyon an, yo te dekouvri kapasite pou telechaje ak kouri kòd ègzèkutabl, ki kontrè ak règ yo pou pibliye aplikasyon yo sou Google Play. Anplis telechaje kòd ègzèkutabl, UC Browser fè sa nan yon fason ki pa ansekirite, ki ka itilize pou lanse yon atak MitM. Ann wè si nou ka fè yon atak konsa.

Tout sa ki ekri anba a enpòtan pou vèsyon UC Browser ki te disponib sou Google Play nan moman etid la:

package: com.UCMobile.intl
versionName: 12.10.8.1172
versionCode: 10598
sha1 APK-файла: f5edb2243413c777172f6362876041eb0c3a928c

Vektè atak

Nan manifès UC Browser ou ka jwenn yon sèvis ki gen yon non ki eksplikasyon com.uc.deployment.UpgradeDeployService.

    <service android_exported="false" android_name="com.uc.deployment.UpgradeDeployService" android_process=":deploy" />

Lè sèvis sa a kòmanse, navigatè a fè yon demann POST puds.ucweb.com/upgrade/index.xhtml, ki ka wè nan trafik kèk tan apre kòmansman an. Kòm repons, li ka resevwa yon lòd pou telechaje kèk aktyalizasyon oswa nouvo modil. Pandan analiz la, sèvè a pa t bay kòmandman sa yo, men nou remake ke lè nou eseye louvri yon PDF nan navigatè a, li fè yon dezyèm demann nan adrès ki espesifye pi wo a, apre sa li telechaje bibliyotèk natif natal la. Pou fè atak la, nou deside sèvi ak karakteristik sa a nan navigatè UC: kapasite nan louvri PDF lè l sèvi avèk yon bibliyotèk natif natal, ki pa nan APK a epi li telechaje sou entènèt la si sa nesesè. Li se vo anyen ke, teyorikman, UC Browser ka fòse telechaje yon bagay san entèraksyon itilizatè - si ou bay yon repons byen fòme a yon demann ki egzekite apre navigatè a te lanse. Men, pou fè sa, nou bezwen etidye pwotokòl la nan entèraksyon ak sèvè a nan plis detay, kidonk nou deside ke li ta pi fasil edite repons entèsepte a ak ranplase bibliyotèk la pou travay ak PDF.

Se konsa, lè yon itilizatè vle louvri yon PDF dirèkteman nan navigatè a, demann sa yo ka wè nan trafik la:

Kap chèche vilnerabilite nan navigatè UC

Premye gen yon demann POST puds.ucweb.com/upgrade/index.xhtml, lè sa a
Yo telechaje yon achiv ki gen yon bibliyotèk pou gade PDF ak fòma biwo. Li lojik pou asime ke premye demann lan transmèt enfòmasyon sou sistèm nan (omwen achitekti a bay bibliyotèk ki nesesè yo), epi an repons a li navigatè a resevwa kèk enfòmasyon sou bibliyotèk la ki bezwen telechaje: adrès la ak, pètèt. , yon lòt bagay. Pwoblèm lan se ke demann sa a se chiffres.

Mande fragman

Fragman repons

Kap chèche vilnerabilite nan navigatè UC

Kap chèche vilnerabilite nan navigatè UC

Bibliyotèk la li menm yo pake nan ZIP epi li pa ankode.

Kap chèche vilnerabilite nan navigatè UC

Chèche kòd dechifre trafik

Ann eseye dechifre repons sèvè a. Ann gade kòd klas la com.uc.deployment.UpgradeDeployService: soti nan metòd onStartCommand ale nan com.uc.deployment.bx, ak soti nan li 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);
}

Nou wè fòmasyon yon demann POST isit la. Nou peye atansyon sou kreyasyon yon etalaj 16 bytes ak ranpli li yo: 0x5F, 0, 0x1F, -50 (=0xCE). Kowenside ak sa nou te wè nan demann ki anwo a.

Nan menm klas la ou ka wè yon klas enbrike ki gen yon lòt metòd enteresan:

        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");
}
}

Metòd la pran yon etalaj de bytes kòm opinyon epi tcheke ke byte a zewo se 0x60 oswa twazyèm byte a se 0xD0, ak dezyèm byte a se 1, 11 oswa 0x1F. Nou gade repons ki soti nan sèvè a: byte zewo a se 0x60, dezyèm lan se 0x1F, twazyèm lan se 0x60. Son tankou sa nou bezwen. Jije pa liy yo ("up_decrypt", pou egzanp), yo ta dwe rele yon metòd isit la ki pral dechifre repons sèvè a.
Ann ale nan metòd la gj. Remake byen ke premye agiman an se byte nan konpanse 2 (sa vle di 0x1F nan ka nou an), ak dezyèm lan se repons sèvè a san yo pa.
premye 16 bytes.

     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;
}

Li evidan, isit la nou chwazi yon algorithm dechifre, ak byte a menm ki nan nou an
ka egal a 0x1F, vle di youn nan twa opsyon posib.

Nou kontinye analize kòd la. Apre yon koup nan so nou jwenn tèt nou nan yon metòd ak yon non-eksplikasyon pwòp tèt ou decryptBytesByKey.

Isit la de lòt byte yo separe de repons nou an, epi yo jwenn yon fisèl nan men yo. Li klè ke nan fason sa a se kle a pou dechifre mesaj la chwazi.

    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;
}

Gade pi devan, nou remake ke nan etap sa a nou poko jwenn yon kle, men se sèlman "idantifyan" li yo. Jwenn kle a se yon ti kras pi konplike.

Nan pwochen metòd la, de lòt paramèt yo ajoute nan sa yo ki deja egziste, fè kat nan yo: nimewo a majik 16, idantifyan kle a, done yo chiffres, ak yon fisèl enkonpreyansib (nan ka nou an, vid).

    public final byte[] l(String keyId, byte[] encrypted) throws SecException {
return this.ayJ().staticBinarySafeDecryptNoB64(16, keyId, encrypted, "");
}

Apre yon seri tranzisyon nou rive nan metòd la staticBinarySafeDecryptNoB64 koòdone com.alibaba.wireless.security.open.staticdataencrypt.IStaticDataEncryptComponent. Pa gen okenn klas nan kòd aplikasyon prensipal ki aplike koòdone sa a. Gen yon klas konsa nan dosye a lib/armeabi-v7a/libsgmain.so, ki se pa aktyèlman yon .so, men yon .bokal. Metòd nou enterese nan aplike jan sa a:

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);
}
//...
}

Isit la nou lis paramèt complétée ak de plis nonb antye relatif: 2 ak 0. Jije pa
tout bagay, 2 vle di dechifre, tankou nan metòd la doFinal klas sistèm javax.crypto.Cipher. Ak tout bagay sa yo transfere nan yon Routeur sèten ak nimewo a 10601 - sa a se aparamman nimewo a lòd.

Apre pwochen chèn tranzisyon an nou jwenn yon klas ki aplike koòdone a IRouterComponent ak metòd doCommand:

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);
}
}

Epi tou klas JNICLibrary, kote yo deklare metòd natif natal la doCommandNative:

package com.taobao.wireless.security.adapter;
public class JNICLibrary {
public static native Object doCommandNative(int arg0, Object[] arg1);
}

Sa vle di nou bezwen jwenn yon metòd nan kòd natif natal la doCommandNative. Lè sa a se kote plezi a kòmanse.

Konfizyon nan kòd machin

Nan dosye libsgmain.so (ki se aktyèlman yon .jar epi nan ki nou jwenn aplikasyon an nan kèk koòdone ki gen rapò ak chifreman jis pi wo a) gen yon bibliyotèk natif natal: libsgmainso-6.4.36.so. Nou louvri li nan IDA epi jwenn yon pakèt bwat dyalòg ak erè. Pwoblèm lan se ke tablo header seksyon an pa valab. Sa fè espre pou konplike analiz la.

Kap chèche vilnerabilite nan navigatè UC

Men, li pa nesesè: kòrèkteman chaje yon fichye ELF ak analize li, yon tablo header pwogram se ase. Se poutèt sa, nou tou senpleman efase tab la seksyon, zewo soti jaden korespondan yo nan header la.

Kap chèche vilnerabilite nan navigatè UC

Louvri fichye a nan IDA ankò.

Gen de fason pou di machin vityèl Java a ki kote egzakteman nan bibliyotèk natif natal la se aplikasyon yon metòd ki te deklare nan kòd Java kòm natif natal. Premye a se bay li yon non espès Java_package_name_ClassName_MethodName.

Dezyèm lan se anrejistre li lè w ap chaje bibliyotèk la (nan fonksyon an JNI_OnChajman)
lè l sèvi avèk yon apèl fonksyon EnskriNatif.

Nan ka nou an, si nou itilize premye metòd la, non an ta dwe tankou sa a: Java_com_taobao_wireless_security_adapter_JNICLibrary_doCommandNative.

Pa gen okenn fonksyon sa yo nan mitan fonksyon yo ekspòte, ki vle di ou bezwen chèche yon apèl EnskriNatif.
Ann ale nan fonksyon an JNI_OnChajman epi nou wè foto sa a:

Kap chèche vilnerabilite nan navigatè UC

Kisa k ap pase la a? Nan premye gade, kòmansman ak fen fonksyon an tipik pou achitekti ARM. Premye enstriksyon sou pil la estoke sa ki nan rejis yo ke fonksyon an pral itilize nan operasyon li yo (nan ka sa a, R0, R1 ak R2), osi byen ke sa ki nan rejis la LR, ki gen adrès retounen nan fonksyon an. . Dènye enstriksyon an retabli rejis ki sove yo, epi adrès retounen imedyatman mete l nan rejis PC a - konsa retounen nan fonksyon an. Men, si w gade ak anpil atansyon, w ap remake ke anpenultyèm enstriksyon an chanje adrès retounen ki estoke sou pil la. Ann kalkile kisa sa pral ye apre
ekzekisyon kòd. Yon sèten adrès 1xB0 chaje nan R130, 5 yo soustraksyon nan li, Lè sa a, li transfere nan R0 ak 0x10 yo ajoute nan li. Li sanble 0xB13B. Kidonk, IDA panse ke dènye enstriksyon an se yon retounen fonksyon nòmal, men an reyalite li pral nan adrès kalkile 0xB13B.

Li vo sonje isit la ke processeurs ARM gen de mòd ak de seri enstriksyon: ARM ak Thumb. Ti moso ki pi piti nan adrès la di processeur a ki seri enstriksyon yo itilize. Sa vle di, adrès la se aktyèlman 0xB13A, ak youn nan ti kras ki pi piti a endike mòd Thumb la.

Yon "adaptè" menm jan an te ajoute nan kòmansman chak fonksyon nan bibliyotèk sa a ak
kòd fatra. Nou pa pral rete sou yo an detay pi lwen - nou jis sonje
ke kòmansman reyèl la nan prèske tout fonksyon se yon ti kras pi lwen.

Depi kòd la pa klèman sote nan 0xB13A, IDA li menm pa t 'rekonèt ke kòd la te lokalize nan kote sa a. Pou menm rezon an, li pa rekonèt pi fò nan kòd la nan bibliyotèk la kòm kòd, ki fè analiz yon ti jan difisil. Nou di IDA ke sa a se kòd la, epi sa a se sa k ap pase:

Kap chèche vilnerabilite nan navigatè UC

Tablo a byen klè kòmanse nan 0xB144. Ki sa ki nan sub_494C?

Kap chèche vilnerabilite nan navigatè UC

Lè w ap rele fonksyon sa a nan rejis LR a, nou jwenn adrès tab mansyone deja (0xB144). Nan R0 - endèks nan tablo sa a. Sa vle di, yo pran valè a nan tablo a, yo ajoute nan LR ak rezilta a se
adrès la pou ale nan. Ann eseye kalkile li: 0xB144 + [0xB144 + 8* 4] = 0xB144 + 0x120 = 0xB264. Nou ale nan adrès ou resevwa a epi wè literalman yon koup nan enstriksyon itil epi ankò ale nan 0xB140:

Kap chèche vilnerabilite nan navigatè UC

Koulye a, pral gen yon tranzisyon nan konpanse ak endèks 0x20 soti nan tab la.

Jije pa gwosè tab la, pral gen anpil tranzisyon sa yo nan kòd la. Kesyon an rive si li posib pou yon jan kanmenm fè fas ak sa a plis otomatikman, san yo pa manyèlman kalkile adrès. Epi scripts ak kapasite pou patch kòd nan IDA vin ede nou:

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"

Mete kurseur a sou liy 0xB26A, kouri script la epi wè tranzisyon an nan 0xB4B0:

Kap chèche vilnerabilite nan navigatè UC

IDA ankò pa t rekonèt zòn sa a kòm yon kòd. Nou ede l 'ak wè yon lòt konsepsyon la:

Kap chèche vilnerabilite nan navigatè UC

Enstriksyon yo apre BLX yo pa sanble yo fè anpil sans, li plis tankou kèk kalite deplasman. Ann gade nan sub_4964:

Kap chèche vilnerabilite nan navigatè UC

Ak tout bon, isit la se yon dword pran nan adrès la kouche nan LR, ajoute nan adrès sa a, apre yo fin ki valè a nan adrès la ki kapab lakòz yo pran epi li mete sou pil la. Epitou, 4 ajoute nan LR pou ke apre yo fin retounen soti nan fonksyon an, se menm konpanse sa a sote. Apre sa, kòmandman POP {R1} la pran valè ki soti nan pil la. Si ou gade sa ki sitiye nan adrès 0xB4BA + 0xEA = 0xB5A4, ou pral wè yon bagay ki sanble ak yon tablo adrès:

Kap chèche vilnerabilite nan navigatè UC

Pou patch konsepsyon sa a, w ap bezwen jwenn de paramèt nan kòd la: konpanse a ak nimewo enskri nan kote ou vle mete rezilta a. Pou chak enskri posib, w ap oblije prepare yon moso kòd davans.

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"

Nou mete kurseur a nan kòmansman estrikti a ke nou vle ranplase - 0xB4B2 - epi kouri script la:

Kap chèche vilnerabilite nan navigatè UC

Anplis de estrikti ki deja mansyone yo, kòd la gen tou sa ki annapre yo:

Kap chèche vilnerabilite nan navigatè UC

Kòm nan ka anvan an, apre enstriksyon BLX la gen yon konpanse:

Kap chèche vilnerabilite nan navigatè UC

Nou pran konpanse a nan adrès la soti nan LR, ajoute li nan LR epi ale la. 0x72044 + 0xC = 0x72050. Script pou konsepsyon sa a se byen senp:

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"

Rezilta ekzekisyon script:

Kap chèche vilnerabilite nan navigatè UC

Yon fwa tout bagay patched nan fonksyon an, ou ka montre IDA nan kòmansman reyèl li yo. Li pral mete ansanm tout kòd fonksyon an, epi li ka dekonpile lè l sèvi avèk HexRays.

Dekode fisèl

Nou te aprann fè fas ak obfuscation nan kòd machin nan bibliyotèk la libsgmainso-6.4.36.so soti nan UC Browser epi li te resevwa kòd fonksyon an JNI_OnChajman.

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;
}

Ann pran yon gade pi pre nan liy sa yo:

  sub_73E24(&unk_83EA6, &v6, 49);
clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);

Nan fonksyon sub_73E24 se non klas la klèman ke yo te dechifre. Kòm paramèt nan fonksyon sa a, yon konsèy sou done ki sanble ak done chiffres, yon sèten tanpon ak yon nimewo yo pase. Li evidan, apre yo fin rele fonksyon an, pral gen yon liy dechifre nan tanpon an, depi li pase nan fonksyon an. FindClass, ki pran non klas la kòm dezyèm paramèt la. Se poutèt sa, nimewo a se gwosè a nan tanpon an oswa longè liy lan. Ann eseye dechifre non klas la, li ta dwe di nou si nou prale nan bon direksyon an. Ann pran yon gade pi pre nan sa k ap pase nan sub_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;
}

Fonksyon sub_7AF78 kreye yon egzanp nan yon veso pou etalaj byte nan gwosè espesifye (nou pa pral rete sou resipyan sa yo an detay). Isit la yo kreye de resipyan sa yo: youn gen liy lan "DcO/lcK+h?m3c*q@" (li fasil pou devine ke sa a se yon kle), lòt la gen done chiffres. Apre sa, tou de objè yo mete nan yon estrikti sèten, ki se pase nan fonksyon an sub_6115C. Ann make tou yon jaden ki gen valè 3 nan estrikti sa a.

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;
}

Paramèt switch la se yon jaden estrikti ki te deja asiyen valè a 3. Gade nan ka 3: nan fonksyon an sub_6364C paramèt yo pase soti nan estrikti a ki te ajoute la nan fonksyon anvan an, sa vle di kle a ak done chiffres. Si w byen gade sub_6364C, ou ka rekonèt algorithm RC4 ladan l.

Nou gen yon algorithm ak yon kle. Ann eseye dechifre non klas la. Men sa ki te pase: com/taobao/wireless/security/adapter/JNICLibrary. Gwo! Nou sou bon chemen an.

Kòmand pye bwa

Koulye a, nou bezwen jwenn yon defi EnskriNatif, ki pral montre nou nan fonksyon an doCommandNative. Ann gade nan fonksyon yo rele soti nan JNI_OnLoad, epi nou jwenn li nan sub_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;
}

Ak tout bon, yon metòd natif natal ak non an anrejistre isit la doCommandNative. Kounye a nou konnen adrès li. Ann wè sa li fè.

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;
}

Sou non an ou ka devine ke isit la se pwen an antre nan tout fonksyon yo ke devlopè yo deside transfere nan bibliyotèk natif natal la. Nou enterese nan nimewo fonksyon 10601.

Ou ka wè nan kòd la ke nimewo a kòmand pwodui twa nimewo: komand/10000, kòmand % 10000 / 100 и kòmand % 10, sa vle di, nan ka nou an, 1, 6 ak 1. Twa nimewo sa yo, osi byen ke yon konsèy sou JNIEnv ak agiman yo pase nan fonksyon an ajoute nan yon estrikti epi yo pase sou. Sèvi ak twa nimewo yo jwenn (an nou endike yo N1, N2 ak N3), yo bati yon pye bwa kòmand.

Yon bagay tankou sa a:

Kap chèche vilnerabilite nan navigatè UC

Pye bwa a plen dinamik JNI_OnChajman.
Twa nimewo kode chemen an nan pye bwa a. Chak fèy pye bwa a gen adrès pocked fonksyon korespondan an. Kle a se nan ne paran an. Jwenn plas nan kòd la kote fonksyon nou bezwen an ajoute nan pye bwa a pa difisil si ou konprann tout estrikti yo itilize yo (nou pa dekri yo pou yo pa gonfle yon atik deja pito gwo).

Plis konfizyon

Nou te resevwa adrès fonksyon an ki ta dwe dechifre trafik: 0x5F1AC. Men, li twò bonè pou nou kontan: devlopè UC Browser te prepare yon lòt sipriz pou nou.

Apre nou fin resevwa paramèt yo nan etalaj ki te fòme nan kòd Java a, nou jwenn
nan fonksyon an nan adrès 0x4D070. Ak isit la yon lòt kalite ofiskasyon kòd ap tann nou.

Nou mete de endis nan R7 ak R4:

Kap chèche vilnerabilite nan navigatè UC

Nou chanje premye endèks la nan R11:

Kap chèche vilnerabilite nan navigatè UC

Pou jwenn yon adrès nan yon tablo, sèvi ak yon endèks:

Kap chèche vilnerabilite nan navigatè UC

Apre yo fin ale nan premye adrès la, dezyèm endèks la itilize, ki nan R4. Gen 230 eleman nan tablo a.

Kisa pou fè sou li? Ou ka di IDA ke sa a se yon switch: Edit -> Lòt -> Espesifye idiom switch.

Kap chèche vilnerabilite nan navigatè UC

Kòd la ki kapab lakòz se terib. Men, fè wout ou nan forè li a, ou ka remake yon apèl nan yon fonksyon deja abitye pou nou sub_6115C:

Kap chèche vilnerabilite nan navigatè UC

Te gen yon switch nan ki nan ka 3 te gen yon dechifre lè l sèvi avèk algorithm RC4 la. Ak nan ka sa a, estrikti a pase nan fonksyon an plen soti nan paramèt yo pase a doCommandNative. Ann sonje sa nou te genyen la magicInt ak valè 16. Nou gade ka korespondan an - epi apre plizyè tranzisyon nou jwenn kòd ki ka idantifye algorithm la.

Kap chèche vilnerabilite nan navigatè UC

Sa a se AES!

Algorithm la egziste, tout sa ki rete se jwenn paramèt li yo: mòd, kle ak, pètèt, vektè inisyalizasyon (prezans li depann de mòd nan fonksyone nan algorithm AES). Estrikti a ak yo dwe fòme yon kote anvan apèl la fonksyon sub_6115C, men pati sa a nan kòd la espesyalman byen obfuscate, kidonk lide a rive patch kòd la pou ke tout paramèt nan fonksyon an dechifre yo jete nan yon dosye.

Patch

Yo nan lòd yo pa ekri tout kòd patch la nan lang asanble manyèlman, ou ka lanse Android Studio, ekri yon fonksyon la ki resevwa paramèt opinyon yo menm jan ak fonksyon dechifre nou an epi ekri nan yon dosye, Lè sa a, kopye-kole kòd la ke konpilatè a pral. jenere.

Zanmi nou yo nan ekip navigatè UC la te pran swen tou konvenyans pou ajoute kòd. Se pou nou sonje ke nan kòmansman chak fonksyon nou gen kòd fatra ki ka fasil pou ranplase ak nenpòt lòt. Trè pratik 🙂 Sepandan, nan kòmansman fonksyon sib la pa gen ase espas pou kòd la ki sove tout paramèt yo nan yon dosye. Mwen te oblije divize li an pati epi sèvi ak blòk fatra nan fonksyon vwazen yo. Te gen kat pati nan total.

Premye pati a:

Kap chèche vilnerabilite nan navigatè UC

Nan achitekti ARM, premye kat paramèt fonksyon yo pase nan rejis R0-R3, rès la, si genyen, yo pase nan pil la. Rejis LR a pote adrès retounen an. Tout bagay sa a bezwen sove pou fonksyon an ka travay apre nou jete paramèt li yo. Nou bezwen tou sove tout rejis ke nou pral itilize nan pwosesis la, kidonk nou fè PUSH.W {R0-R10,LR}. Nan R7 nou jwenn adrès la nan lis la nan paramèt pase nan fonksyon an atravè chemine a.

Sèvi ak fonksyon an fopen ann ouvri fichye a /data/local/tmp/aes nan mòd "ab".
sa vle di pou adisyon. Nan R0 nou chaje adrès la nan non dosye a, nan R1 - adrès la nan liy ki endike mòd la. Ak isit la kòd la fatra fini, se konsa nou deplase sou pwochen fonksyon an. Nan lòd pou li kontinye travay, nou mete nan kòmansman an tranzisyon an nan kòd la reyèl nan fonksyon an, kontoune fatra a, epi olye pou yo fatra a nou ajoute yon kontinyasyon nan patch la.

Kap chèche vilnerabilite nan navigatè UC

Rele fopen.

Twa premye paramèt fonksyon an AES gen kalite int. Depi nou te sove rejis yo nan pil la nan kòmansman an, nou ka tou senpleman pase fonksyon an fw ekri adrès yo sou pil la.

Kap chèche vilnerabilite nan navigatè UC

Apre sa, nou gen twa estrikti ki genyen gwosè done a ak yon konsèy sou done yo pou kle a, vektè inisyalizasyon ak done chiffres.

Kap chèche vilnerabilite nan navigatè UC

Nan fen a, fèmen dosye a, retabli rejis yo epi transfere kontwòl nan fonksyon reyèl la AES.

Nou kolekte yon APK ak yon bibliyotèk patched, siyen li, telechaje li sou aparèy/emulateur la, epi lanse li. Nou wè ke pil fatra nou an ap kreye, epi anpil done ap ekri la. Navigatè a sèvi ak chifreman pa sèlman pou trafik, ak tout chifreman ale nan fonksyon an nan kesyon an. Men, pou kèk rezon done ki nesesè yo pa la, epi demann ki nesesè yo pa vizib nan trafik la. Pou nou pa rete tann jiskaske UC Browser deign fè demann ki nesesè yo, ann pran repons kode nan sèvè a te resevwa pi bonè epi patch aplikasyon an ankò: ajoute dechifre nan onCreate nan aktivite prensipal la.

    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

Nou rasanble, siyen, enstale, lanse. Nou resevwa yon NullPointerException paske metòd la tounen nil.

Pandan plis analiz nan kòd la, yo te dekouvri yon fonksyon ki dekode liy enteresan: "META-INF/" ak ".RSA". Li sanble ke aplikasyon an ap verifye sètifika li a. Oswa menm jenere kle nan li. Mwen pa reyèlman vle fè fas ak sa k ap pase ak sètifika a, kidonk nou pral jis glise li sètifika ki kòrèk la. Ann patch liy chiffré a pou olye pou yo "META-INF/" nou jwenn "BLABLINF/", kreye yon katab ak non sa a nan APK a epi ajoute sètifika navigatè a ekirèy la.

Nou rasanble, siyen, enstale, lanse. Bingo! Nou gen kle a!

MitM

Nou te resevwa yon kle ak yon vektè inisyalizasyon ki egal ak kle a. Ann eseye dechifre repons sèvè a nan mòd CBC.

Kap chèche vilnerabilite nan navigatè UC

Nou wè URL achiv la, yon bagay ki sanble ak MD5, "extract_unzipsize" ak yon nimewo. Nou tcheke: MD5 nan achiv la se menm bagay la, gwosè a nan bibliyotèk la depake se menm bagay la. Nou ap eseye patch bibliyotèk sa a epi bay li nan navigatè a. Pou montre ke bibliyotèk patched nou an chaje, nou pral lanse yon Entansyon pou kreye yon SMS ak tèks "PWNED!" Nou pral ranplase de repons ki soti nan sèvè a: puds.ucweb.com/upgrade/index.xhtml epi telechaje achiv la. Nan premye a nou ranplase MD5 (gwosè a pa chanje apre debake), nan dezyèm nan nou bay achiv la ak bibliyotèk la patched.

Navigatè a eseye telechaje achiv la plizyè fwa, apre sa li bay yon erè. Aparamman yon bagay
li pa renmen. Kòm yon rezilta nan analiz fòma sa a twoub, li te tounen soti ke sèvè a tou transmèt gwosè a nan achiv la:

Kap chèche vilnerabilite nan navigatè UC

Li kode nan LEB128. Apre patch la, gwosè a nan achiv la ak bibliyotèk la chanje yon ti kras, kidonk navigatè a te konsidere ke achiv la te telechaje kwochi, epi apre plizyè tantativ li jete yon erè.

Nou ajiste gwosè achiv la... Epi – viktwa! 🙂 Rezilta a se nan videyo a.

https://www.youtube.com/watch?v=Nfns7uH03J8

Konsekans ak reyaksyon pwomotè

Menm jan an tou, entru yo ka itilize karakteristik ensekirite UC Browser pou distribye epi kouri bibliyotèk move. Bibliyotèk sa yo pral travay nan yon kontèks navigatè a, kidonk yo pral resevwa tout otorizasyon sistèm li yo. Kòm yon rezilta, kapasite nan montre èskrokri fenèt, osi byen ke aksè nan dosye yo k ap travay nan ekirèy la zoranj Chinwa, ki gen ladan koneksyon, modpas ak bonbon ki estoke nan baz done a.

Nou kontakte devlopè UC Browser epi nou te enfòme yo sou pwoblèm nou te jwenn, nou te eseye montre vilnerabilite a ak danje li yo, men yo pa t diskite anyen avèk nou. Pandan se tan, navigatè a te kontinye etale karakteristik danjere li yo nan je klè. Men, yon fwa nou te revele detay yo nan vilnerabilite a, li pa t posib ankò inyore li tankou anvan. 27 mas te
yon nouvo vèsyon UC Browser 12.10.9.1193 te lage, ki te jwenn aksè nan sèvè a atravè HTTPS: puds.ucweb.com/upgrade/index.xhtml.

Anplis de sa, apre "ranje" la ak jiskaske yo ekri atik sa a, eseye louvri yon PDF nan yon navigatè te lakòz yon mesaj erè ak tèks la "Oops, yon bagay ale mal!" Yon demann nan sèvè a pa te fè lè w ap eseye louvri yon PDF, men yo te fè yon demann lè navigatè a te lanse, ki allusion sou kapasite nan kontinye telechaje kòd ègzèkutabl an vyolasyon règ Google Play.

Sous: www.habr.com

Add nouvo kòmantè