Introduzzjoni
Fl-aħħar ta’ Marzu aħna
Xi żmien ilu, UC Browser ġie reklamat u mqassam b'mod aggressiv ħafna: ġie installat fuq it-tagħmir tal-utenti bl-użu ta 'malware, imqassam minn diversi siti taħt l-iskuża ta' fajls tal-vidjo (jiġifieri, l-utenti ħasbu li kienu qed iniżżlu, pereżempju, vidjo porn, iżda minflok irċieva APK ma 'dan il-browser), uża banners tal-biża' b'messaġġi li l-browser kien skadut, vulnerabbli, u affarijiet bħal dawn. Fil-grupp uffiċjali tal-UC Browser fuq VK hemm
Fiż-żmien tal-kitba, UC Browser għandu aktar minn 500 installazzjoni fuq Google Play. Dan huwa impressjonanti - Google Chrome biss għandu aktar. Fost ir-reviżjonijiet tista 'tara pjuttost ħafna ilmenti dwar ir-reklamar u redirects għal xi applikazzjonijiet fuq Google Play. Din kienet ir-raġuni għar-riċerka tagħna: iddeċidejna li naraw jekk UC Browser kienx qed jagħmel xi ħaġa ħażina. U rriżulta li jagħmel hekk!
Fil-kodiċi tal-applikazzjoni, ġiet skoperta l-abbiltà li tniżżel u tħaddem kodiċi eżekutibbli,
Dak kollu miktub hawn taħt huwa rilevanti għall-verżjoni tal-UC Browser li kienet disponibbli fuq Google Play fiż-żmien tal-istudju:
package: com.UCMobile.intl
versionName: 12.10.8.1172
versionCode: 10598
sha1 APK-файла: f5edb2243413c777172f6362876041eb0c3a928c
Vettur tal-attakk
Fil-manifest tal-UC Browser tista' ssib servizz b'isem li jispjega lilu nnifsu com.uc.deployment.UpgradeDeployService.
<service android_exported="false" android_name="com.uc.deployment.UpgradeDeployService" android_process=":deploy" />
Meta jibda dan is-servizz, il-browser jagħmel talba POST lil
Għalhekk, meta utent irid jiftaħ PDF direttament fil-browser, it-talbiet li ġejjin jistgħu jidhru fit-traffiku:
L-ewwel hemm talba POST biex
Jitniżżel arkivju b'librerija biex tara PDF u formati tal-uffiċċju. Huwa loġiku li wieħed jassumi li l-ewwel talba tittrasmetti informazzjoni dwar is-sistema (mill-inqas l-arkitettura biex tipprovdi l-librerija meħtieġa), u bi tweġiba għaliha l-browser jirċievi xi informazzjoni dwar il-librerija li jeħtieġ li titniżżel: l-indirizz u, possibilment , xi haga ohra. Il-problema hija li din it-talba hija encrypted.
Framment talba
Framment tweġiba
Il-librerija nnifisha hija ppakkjata f'ZIP u mhix encrypted.
Fittex għall-kodiċi tad-deċifrar tat-traffiku
Ejja nippruvaw niddeċifraw ir-rispons tas-server. Ejja nħarsu lejn il-kodiċi tal-klassi com.uc.deployment.UpgradeDeployService: mill-metodu onStart Command mur għand com.uc.deployment.bx, u minnha sa 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);
}
Naraw il-formazzjoni ta’ talba POST hawn. Aħna nagħtu attenzjoni għall-ħolqien ta 'firxa ta' 16 bytes u l-mili tagħha: 0x5F, 0, 0x1F, -50 (=0xCE). Jikkoinċidi ma' dak li rajna fit-talba ta' hawn fuq.
Fl-istess klassi tista 'tara klassi nested li għandha metodu ieħor interessanti:
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");
}
}
Il-metodu jirċievi firxa ta 'bytes bħala input u jiċċekkja li l-byte żero huwa 0x60 jew it-tielet byte huwa 0xD0, u t-tieni byte huwa 1, 11 jew 0x1F. Inħarsu lejn ir-rispons mis-server: il-byte żero huwa 0x60, it-tieni huwa 0x1F, it-tielet huwa 0x60. Ħsejjes bħal dak li għandna bżonn. Ġġudikati mill-linji ("up_decrypt", per eżempju), hawn għandu jissejjaħ metodu li jiddekofra r-rispons tas-server.
Ejja ngħaddu għall-metodu gj. Innota li l-ewwel argument huwa l-byte fl-offset 2 (jiġifieri 0x1F fil-każ tagħna), u t-tieni huwa r-rispons tas-server mingħajr
l-ewwel 16-il byte.
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;
}
Ovvjament, hawn aħna nagħżlu algoritmu ta 'decryption, u l-istess byte li huwa tagħna
każ ugwali għal 0x1F, jindika waħda minn tliet għażliet possibbli.
Aħna nkomplu nanalizzaw il-kodiċi. Wara ftit qabżiet insibu ruħna f'metodu b'isem li jispjega lilhom infushom decryptBytesByKey.
Hawnhekk żewġ bytes oħra huma separati mir-rispons tagħna, u string tinkiseb minnhom. Huwa ċar li b'dan il-mod tintgħażel iċ-ċavetta għad-decrypting tal-messaġġ.
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;
}
Meta nħarsu 'l quddiem, ninnutaw li f'dan l-istadju għadna ma niksbux ċavetta, iżda biss "l-identifikatur" tagħha. Li tikseb iċ-ċavetta hija ftit aktar ikkumplikata.
Fil-metodu li jmiss, żewġ parametri oħra huma miżjuda ma 'dawk eżistenti, li jagħmlu erbgħa minnhom: in-numru maġiku 16, l-identifikatur taċ-ċavetta, id-data encrypted, u string inkomprensibbli (fil-każ tagħna, vojta).
public final byte[] l(String keyId, byte[] encrypted) throws SecException {
return this.ayJ().staticBinarySafeDecryptNoB64(16, keyId, encrypted, "");
}
Wara serje ta 'tranżizzjonijiet naslu għall-metodu staticBinarySafeDecryptNoB64 interface com.alibaba.wireless.security.open.staticdataencrypt.IStaticDataEncryptComponent. M'hemm l-ebda klassijiet fil-kodiċi tal-applikazzjoni prinċipali li jimplimentaw din l-interface. Hemm klassi bħal din fil-fajl lib/armeabi-v7a/libsgmain.so, li fil-fatt mhuwiex .so, iżda .jar. Il-metodu li aħna interessati fih huwa implimentat kif ġej:
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);
}
//...
}
Hawnhekk il-lista tagħna ta 'parametri hija supplimentata b'żewġ interi oħra: 2 u 0. Ġġudikati minn
kollox, 2 tfisser decryption, bħal fil-metodu doFinal klassi tas-sistema javax.crypto.Cipher. U dan kollu jiġi trasferit għal ċertu Router bin-numru 10601 - dan jidher li huwa n-numru tal-kmand.
Wara l-katina ta 'tranżizzjonijiet li jmiss insibu klassi li timplimenta l-interface IRouterComponent u l-metodu doKmand:
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);
}
}
U wkoll klassi JNICLibrerija, li fiha jiġi ddikjarat il-metodu nattiv doCommandNative:
package com.taobao.wireless.security.adapter;
public class JNICLibrary {
public static native Object doCommandNative(int arg0, Object[] arg1);
}
Dan ifisser li għandna bżonn insibu metodu fil-kodiċi nattiv doCommandNative. U hawnhekk jibda l-gost.
Offuskazzjoni tal-kodiċi tal-magna
Fil-fajl libsgmain.so (li fil-fatt huwa .jar u li fih sibna l-implimentazzjoni ta 'xi interfaces relatati mal-encryption eżatt fuq) hemm librerija nattiva waħda: libsgmainso-6.4.36.so. Niftħuh f'IDA u nġibu mazz ta 'kaxxi ta' djalogu bi żbalji. Il-problema hija li t-tabella tal-header tat-taqsima hija invalida. Dan isir apposta biex tikkomplika l-analiżi.
Iżda mhux meħtieġ: biex tgħabbi b'mod korrett fajl ELF u tanalizzah, tabella tal-header tal-programm hija biżżejjed. Għalhekk, aħna sempliċement inħassru t-tabella tas-sezzjoni, billi niżżlu żero l-oqsma korrispondenti fl-intestatura.
Iftaħ il-fajl f'IDA mill-ġdid.
Hemm żewġ modi kif tgħid lill-magna virtwali Java fejn tinsab eżattament fil-librerija nattiva l-implimentazzjoni ta 'metodu ddikjarat fil-kodiċi Java bħala indiġeni. L-ewwel huwa li tagħtiha isem ta 'speċi Java_package_name_ClassName_MethodName.
It-tieni huwa li tirreġistraha meta tgħabbi l-librerija (fil-funzjoni JNI_OnLoad)
bl-użu ta' sejħa ta' funzjoni ReġistruNattivi.
Fil-każ tagħna, jekk nużaw l-ewwel metodu, l-isem għandu jkun bħal dan: Java_com_taobao_wireless_security_adapter_JNICLibrary_doCommandNative.
M'hemm l-ebda funzjoni bħal din fost il-funzjonijiet esportati, li jfisser li għandek bżonn tfittex sejħa ReġistruNattivi.
Ejja mmorru għall-funzjoni JNI_OnLoad u naraw din l-istampa:
X'qed jiġri hawn? L-ewwel daqqa t'għajn, il-bidu u t-tmiem tal-funzjoni huma tipiċi għall-arkitettura ARM. L-ewwel istruzzjoni fuq il-munzell taħżen il-kontenut tar-reġistri li l-funzjoni se tuża fit-tħaddim tagħha (f'dan il-każ, R0, R1 u R2), kif ukoll il-kontenut tar-reġistru LR, li fih l-indirizz tar-ritorn mill-funzjoni . L-aħħar istruzzjoni tirrestawra r-reġistri salvati, u l-indirizz tar-ritorn jitqiegħed immedjatament fir-reġistru tal-PC - u b'hekk jirritorna mill-funzjoni. Imma jekk tħares mill-qrib, tinduna li l-istruzzjoni ta’ qabel tal-aħħar tbiddel l-indirizz tar-ritorn maħżun fuq il-munzell. Ejja nikkalkulaw kif se jkun wara
eżekuzzjoni tal-kodiċi. Ċertu indirizz 1xB0 jitgħabba f'R130, 5 jitnaqqas minnu, imbagħad jiġi trasferit għal R0 u 0x10 jiżdied miegħu. Jirriżulta 0xB13B. Għalhekk, IDA jaħseb li l-aħħar istruzzjoni hija ritorn ta 'funzjoni normali, iżda fil-fatt sejjer għall-indirizz ikkalkulat 0xB13B.
Ta 'min ifakkar hawnhekk li l-proċessuri ARM għandhom żewġ modi u żewġ settijiet ta' struzzjonijiet: ARM u Thumb. L-inqas daqsxejn sinifikanti tal-indirizz jgħid lill-proċessur liema sett ta 'struzzjonijiet qed jintuża. Jiġifieri, l-indirizz huwa fil-fatt 0xB13A, u wieħed fl-inqas bit sinifikanti jindika l-modalità Thumb.
"Adapter" simili ġie miżjud mal-bidu ta 'kull funzjoni f'din il-librerija u
kodiċi taż-żibel. Mhux se noqogħdu aktar fuqhom fid-dettall - niftakru biss
li l-bidu reali ta 'kważi l-funzjonijiet kollha huwa ftit aktar 'il bogħod.
Peress li l-kodiċi ma jaqbiżx b'mod espliċitu għal 0xB13A, IDA nnifisha ma għarfetx li l-kodiċi kien jinsab f'dan il-post. Għall-istess raġuni, ma jirrikonoxxix il-biċċa l-kbira tal-kodiċi fil-librerija bħala kodiċi, li jagħmel l-analiżi kemmxejn diffiċli. Aħna ngħidu lill-IDA li dan huwa l-kodiċi, u dan huwa dak li jiġri:
It-tabella tibda b'mod ċar f'0xB144. X'hemm f'sub_494C?
Meta nsejħu din il-funzjoni fir-reġistru LR, inġibu l-indirizz tat-tabella msemmija qabel (0xB144). F'R0 - indiċi f'din it-tabella. Jiġifieri, il-valur jittieħed mit-tabella, miżjud ma 'LR u r-riżultat huwa
l-indirizz biex tmur. Ejja nippruvaw nikkalkulawha: 0xB144 + [0xB144 + 8* 4] = 0xB144 + 0x120 = 0xB264. Immorru fl-indirizz riċevuti u naraw litteralment ftit istruzzjonijiet utli u għal darb'oħra mmorru għal 0xB140:
Issa se jkun hemm transizzjoni b'offset b'indiċi 0x20 mit-tabella.
Ġġudikati mid-daqs tat-tabella, se jkun hemm ħafna tranżizzjonijiet bħal dawn fil-kodiċi. Tqum il-mistoqsija jekk huwiex possibbli li b'xi mod dan jiġi ttrattat b'mod aktar awtomatiku, mingħajr ma jiġu kkalkulati manwalment l-indirizzi. U l-iskripts u l-abbiltà li l-kodiċi tal-garża fl-IDA jiġu għall-għajnuna tagħna:
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"
Poġġi l-cursor fuq il-linja 0xB26A, mexxi l-iskript u ara t-tranżizzjoni għal 0xB4B0:
L-IDA għal darb'oħra ma għarfetx din il-qasam bħala kodiċi. Ngħinuha u naraw disinn ieħor hemmhekk:
L-istruzzjonijiet wara BLX ma jidhirx li jagħmlu ħafna sens, huwa aktar bħal xi tip ta 'spostament. Ejja nħarsu lejn sub_4964:
U tabilħaqq, hawnhekk tittieħed dword fl-indirizz li jinsab f'LR, miżjud ma 'dan l-indirizz, wara li jittieħed il-valur fl-indirizz li jirriżulta u jitqiegħed fuq il-munzell. Ukoll, 4 huwa miżjud ma 'LR sabiex wara li jirritornaw mill-funzjoni, dan l-istess offset jinqabeż. Wara dan il-kmand POP {R1} jieħu l-valur li jirriżulta mill-munzell. Jekk tħares lejn dak li jinsab fl-indirizz 0xB4BA + 0xEA = 0xB5A4, se tara xi ħaġa simili għal tabella tal-indirizzi:
Biex timla dan id-disinn, ser ikollok bżonn tikseb żewġ parametri mill-kodiċi: l-offset u n-numru tar-reġistru li fih trid tpoġġi r-riżultat. Għal kull reġistru possibbli, ikollok tipprepara biċċa kodiċi minn qabel.
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"
Aħna npoġġu l-cursor fil-bidu tal-istruttura li rridu nissostitwixxu - 0xB4B2 - u nħaddmu l-iskrittura:
Minbarra l-istrutturi diġà msemmija, il-kodiċi fih ukoll dan li ġej:
Bħal fil-każ preċedenti, wara l-istruzzjoni BLX hemm kumpens:
Nieħdu l-offset għall-indirizz minn LR, żidha ma 'LR u mmorru hemm. 0x72044 + 0xC = 0x72050. L-iskript għal dan id-disinn huwa pjuttost sempliċi:
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"
Riżultat tal-eżekuzzjoni tal-iskript:
Ladarba kollox huwa patched fil-funzjoni, inti tista 'tippunta IDA għall-bidu reali tagħha. Se tgħaqqad il-kodiċi tal-funzjoni kollu, u tista 'tiġi dekompilata bl-użu ta' HexRays.
Kordi ta' dekodifikazzjoni
Tgħallimna nittrattaw l-obfuscation tal-kodiċi tal-magni fil-librerija libsgmainso-6.4.36.so minn UC Browser u rċeviet il-kodiċi tal-funzjoni 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;
}
Ejja nagħtu ħarsa aktar mill-qrib lejn il-linji li ġejjin:
sub_73E24(&unk_83EA6, &v6, 49);
clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);
Fil-funzjoni sub_73E24 l-isem tal-klassi qed jiġi decrypted b'mod ċar. Bħala parametri għal din il-funzjoni, jiġu mgħoddija pointer għal data simili għal data encrypted, ċertu buffer u numru. Ovvjament, wara li ssejjaħ il-funzjoni, se jkun hemm linja decrypted fil-buffer, peress li hija mgħoddija lill-funzjoni SibKlassi, li tieħu l-isem tal-klassi bħala t-tieni parametru. Għalhekk, in-numru huwa d-daqs tal-buffer jew it-tul tal-linja. Ejja nippruvaw niddeċifraw l-isem tal-klassi, għandu jgħidilna jekk hux sejrin fid-direzzjoni t-tajba. Ejja nagħtu ħarsa aktar mill-qrib lejn dak li jiġri fi 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;
}
Funzjoni sub_7AF78 joħloq eżempju ta 'kontenitur għal arrays ta' byte tad-daqs speċifikat (mhux se noqogħdu fuq dawn il-kontenituri fid-dettall). Hawnhekk jinħolqu żewġ kontenituri bħal dawn: wieħed fih il-linja "DcO/lcK+h?m3c*q@" (huwa faċli li wieħed isib li din hija ċavetta), l-oħra fiha dejta kriptata. Sussegwentement, iż-żewġ oġġetti jitqiegħdu f'ċerta struttura, li tiġi mgħoddija lill-funzjoni sub_6115C. Ejja nimmarkaw ukoll qasam bil-valur 3 f'din l-istruttura.Ejja naraw x'jiġri minn din l-istruttura jmiss.
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;
}
Il-parametru tal-iswiċċ huwa qasam tal-istruttura li qabel kien assenjat il-valur 3. Ħares lejn il-każ 3: għall-funzjoni sub_6364C il-parametri huma mgħoddija mill-istruttura li ġew miżjuda hemm fil-funzjoni preċedenti, jiġifieri ċ-ċavetta u d-dejta kriptata. Jekk tħares mill-qrib lejn sub_6364C, tista 'tagħraf l-algoritmu RC4 fih.
Għandna algoritmu u ċavetta. Ejja nippruvaw niddeċifraw l-isem tal-klassi. Hawn x'ġara: com/taobao/wireless/security/adapter/JNICLibrary. Kbir! Aħna qegħdin fit-triq it-tajba.
Siġra tal-kmand
Issa rridu nsibu sfida ReġistruNattivi, li se jindikalna għall-funzjoni doCommandNative. Ejja nħarsu lejn il-funzjonijiet imsejħa minn JNI_OnLoad, u nsibuha fi 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;
}
U tabilħaqq, metodu nattiv bl-isem huwa rreġistrat hawn doCommandNative. Issa nafu l-indirizz tiegħu. Ejja naraw x'jagħmel.
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;
}
Bl-isem tista 'raden li hawn huwa l-punt tad-dħul tal-funzjonijiet kollha li l-iżviluppaturi ddeċidew li jittrasferixxu għal-librerija nattiva. Aħna interessati fil-funzjoni numru 10601.
Tista 'tara mill-kodiċi li n-numru tal-kmand jipproduċi tliet numri: kmand/10000, kmand % 10000 / 100 и kmand % 10, jiġifieri, fil-każ tagħna, 1, 6 u 1. Dawn it-tliet numri, kif ukoll pointer għal JNIEnv u l-argumenti mgħoddija lill-funzjoni huma miżjuda ma 'struttura u mgħoddija. Bl-użu tat-tliet numri miksuba (ejja nindikawhom N1, N2 u N3), tinbena siġra tal-kmand.
Xi ħaġa bħal din:
Is-siġra timtela b'mod dinamiku JNI_OnLoad.
Tliet numri jikkodifikaw il-mogħdija fis-siġra. Kull werqa tas-siġra fiha l-indirizz pocked tal-funzjoni korrispondenti. Iċ-ċavetta tinsab fin-node ġenitur. Is-sejba tal-post fil-kodiċi fejn il-funzjoni li neħtieġu hija miżjuda mas-siġra mhix diffiċli jekk tifhem l-istrutturi kollha użati (aħna ma niddeskrivuhomx sabiex ma nefħux artiklu diġà pjuttost kbir).
Aktar tfixkil
Irċevejna l-indirizz tal-funzjoni li għandha tiddikripta t-traffiku: 0x5F1AC. Imma għadu kmieni wisq biex nifirħu: l-iżviluppaturi tal-UC Browser ħejjew sorpriża oħra għalina.
Wara li tirċievi l-parametri mill-firxa li ġiet iffurmata fil-kodiċi Java, irridu
għall-funzjoni fl-indirizz 0x4D070. U hawn tip ieħor ta 'obfuscation tal-kodiċi jistenniena.
Aħna npoġġu żewġ indiċijiet f'R7 u R4:
Aħna nbiddlu l-ewwel indiċi għal R11:
Biex tikseb indirizz minn tabella, uża indiċi:
Wara li tmur għall-ewwel indirizz, jintuża t-tieni indiċi, li jinsab f'R4. Hemm 230 element fit-tabella.
X'għandek tagħmel dwarha? Tista' tgħid lill-IDA li dan huwa swiċċ: Edit -> Oħrajn -> Speċifika l-idjoma tal-iswiċċ.
Il-kodiċi li jirriżulta huwa terribbli. Iżda, waqt li tagħmel triqtek fil-ġungla tagħha, tista 'tinnota sejħa għal funzjoni diġà familjari għalina sub_6115C:
Kien hemm swiċċ li fih fil-każ 3 kien hemm decryption bl-użu tal-algoritmu RC4. U f'dan il-każ, l-istruttura mgħoddija lill-funzjoni hija mimlija mill-parametri mgħoddija lil doCommandNative. Ejja niftakru dak li kellna hemm magicInt bil-valur 16. Inħarsu lejn il-każ korrispondenti - u wara diversi tranżizzjonijiet insibu l-kodiċi li bih l-algoritmu jista 'jiġi identifikat.
Dan huwa AES!
L-algoritmu jeżisti, dak kollu li jibqa 'huwa li jinkisbu l-parametri tiegħu: mod, ċavetta u, possibilment, il-vettur tal-inizjalizzazzjoni (il-preżenza tiegħu tiddependi fuq il-mod operattiv tal-algoritmu AES). L-istruttura magħhom trid tiġi ffurmata x'imkien qabel is-sejħa tal-funzjoni sub_6115C, iżda din il-parti tal-kodiċi hija speċjalment moħbija sew, għalhekk tqum l-idea li l-kodiċi jiġi garża sabiex il-parametri kollha tal-funzjoni tad-decryption jintremew f'fajl.
Garża
Sabiex ma tiktebx il-kodiċi kollu tal-garża fil-lingwa tal-assemblaġġ manwalment, tista 'tniedi Android Studio, tikteb funzjoni hemmhekk li tirċievi l-istess parametri ta' input bħall-funzjoni tad-deċifrar tagħna u tikteb f'fajl, imbagħad kopja-pejst il-kodiċi li l-kompilatur se jiġġeneraw.
Il-ħbieb tagħna mit-tim tal-UC Browser ħadu ħsieb ukoll il-konvenjenza taż-żieda tal-kodiċi. Ejja niftakru li fil-bidu ta 'kull funzjoni għandna kodiċi taż-żibel li jista' faċilment jiġi sostitwit ma 'xi ieħor. Konvenjenti ħafna 🙂 Madankollu, fil-bidu tal-funzjoni fil-mira m'hemmx biżżejjed spazju għall-kodiċi li jiffranka l-parametri kollha f'fajl. Kelli naqsamha f'partijiet u nuża blokki taż-żibel minn funzjonijiet ġirien. B’kollox kien hemm erba’ partijiet.
L-ewwel parti:
Fl-arkitettura ARM, l-ewwel erba 'parametri tal-funzjoni huma mgħoddija mir-reġistri R0-R3, il-bqija, jekk ikun hemm, jgħaddu mill-munzell. Ir-reġistru LR iġorr l-indirizz tar-ritorn. Dan kollu jeħtieġ li jiġi ffrankat sabiex il-funzjoni tkun tista 'taħdem wara li niddempjaw il-parametri tagħha. Għandna bżonn ukoll insalvaw ir-reġistri kollha li se nużaw fil-proċess, għalhekk nagħmlu PUSH.W {R0-R10,LR}. F'R7 nikbru l-indirizz tal-lista ta 'parametri mgħoddija lill-funzjoni permezz tal-munzell.
Bl-użu tal-funzjoni miftuħa ejja niftħu l-fajl /data/local/tmp/aes fil-modalità "ab".
jiġifieri għaż-żieda. F'R0 aħna tagħbija l-indirizz tal-isem tal-fajl, f'R1 - l-indirizz tal-linja li tindika l-mod. U hawn jispiċċa l-kodiċi taż-żibel, għalhekk nimxu fuq il-funzjoni li jmiss. Sabiex tkompli taħdem, aħna npoġġu fil-bidu t-tranżizzjoni għall-kodiċi reali tal-funzjoni, billi taqbeż iż-żibel, u minflok iż-żibel inżidu kontinwazzjoni tal-garża.
Sejħa miftuħa.
L-ewwel tliet parametri tal-funzjoni aES għandhom tip int. Peress li ssejvjajna r-reġistri fil-munzell fil-bidu, nistgħu sempliċement ngħaddu l-funzjoni fwrite l-indirizzi tagħhom fuq il-munzell.
Sussegwentement għandna tliet strutturi li fihom id-daqs tad-dejta u pointer għad-dejta għaċ-ċavetta, il-vettur tal-inizjalizzazzjoni u d-dejta kriptata.
Fl-aħħar, agħlaq il-fajl, irrestawra r-reġistri u ttrasferixxi l-kontroll għall-funzjoni reali aES.
Aħna niġbru APK b'librerija patched, niffirmawha, intellgħuha fuq l-apparat/emulatur, u nnieduha. Naraw li d-dump tagħna qed jinħoloq, u hemm ħafna dejta qed tinkiteb. Il-browser juża encryption mhux biss għat-traffiku, u l-encryption kollha jgħaddi mill-funzjoni inkwistjoni. Iżda għal xi raġuni d-dejta meħtieġa mhix hemm, u t-talba meħtieġa mhix viżibbli fit-traffiku. Sabiex ma tistennax sakemm UC Browser jiddeignja li jagħmel it-talba meħtieġa, ejja nieħdu r-rispons kriptat mis-server li wasal qabel u erġa' waħħal l-applikazzjoni: żid id-decryption ma' onCreate tal-attività ewlenija.
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
Aħna niġbru, niffirmaw, ninstallaw, inniedu. Nirċievu NullPointerException minħabba li l-metodu rritorna null.
Waqt analiżi ulterjuri tal-kodiċi, ġiet skoperta funzjoni li tiddeċifra linji interessanti: "META-INF/" u ".RSA". Jidher li l-applikazzjoni qed tivverifika ċ-ċertifikat tagħha. Jew saħansitra jiġġenera ċwievet minnha. Ma rridx verament nittratta x'qed jiġri biċ-ċertifikat, għalhekk aħna niżżluh iċ-ċertifikat korrett. Ejja nimxu l-linja kriptata sabiex minflok "META-INF/" nikseb "BLABLINF/", oħloq folder b'dak l-isem fl-APK u żid iċ-ċertifikat tal-browser iskojjattlu hemmhekk.
Aħna niġbru, niffirmaw, ninstallaw, inniedu. Bingo! Għandna ċ-ċavetta!
MitM
Irċevejna ċavetta u vettur ta 'inizjalizzazzjoni ugwali għaċ-ċavetta. Ejja nippruvaw niddeċifraw ir-rispons tas-server fil-modalità CBC.
Naraw il-URL tal-arkivju, xi ħaġa simili għal MD5, "extract_unzipsize" u numru. Aħna niċċekkjaw: l-MD5 tal-arkivju huwa l-istess, id-daqs tal-librerija mhux ippakkjata huwa l-istess. Qed nippruvaw nagħtu garża lil din il-librerija u nagħtuha lill-browser. Biex nuru li l-librerija patched tagħna tagħbija, aħna se nniedu Intenzjoni li noħolqu SMS bit-test "PWNED!" Se nissostitwixxu żewġ tweġibiet mis-server:
Il-browser jipprova jniżżel l-arkivju diversi drabi, u wara jagħti żball. Apparentement xi ħaġa
hu ma jħobbx. Bħala riżultat tal-analiżi ta 'dan il-format mċajpra, irriżulta li s-server jittrasmetti wkoll id-daqs tal-arkivju:
Huwa kodifikat f'LEB128. Wara l-garża, id-daqs tal-arkivju bil-librerija nbidel ftit, għalhekk il-browser ikkunsidra li l-arkivju ġie mniżżel b'mod mgħawweġ, u wara diversi tentattivi tefa' żball.
Aħna naġġustaw id-daqs tal-arkivju... U – rebħa! 🙂 Ir-riżultat jinsab fil-video.
Konsegwenzi u reazzjoni tal-iżviluppatur
Bl-istess mod, il-hackers jistgħu jużaw il-karatteristika mhux sigura tal-UC Browser biex iqassmu u jmexxu libreriji malizzjużi. Dawn il-libreriji se jaħdmu fil-kuntest tal-browser, għalhekk se jirċievu l-permessi kollha tas-sistema tiegħu. Bħala riżultat, il-kapaċità li juru twieqi tal-phishing, kif ukoll aċċess għall-fajls tax-xogħol tal-iskojjattlu Ċiniż oranġjo, inklużi logins, passwords u cookies maħżuna fid-database.
Ikkuntattjana l-iżviluppaturi tal-UC Browser u infurmajnahom dwar il-problema li sibna, ippruvajna nirrimarkaw il-vulnerabbiltà u l-periklu tagħha, iżda ma ddiskutew xejn magħna. Sadanittant, il-browser kompla juri l-karatteristika perikoluża tiegħu fil-vista. Iżda ladarba żvelajna d-dettalji tal-vulnerabbiltà, ma kienx aktar possibbli li tinjoraha bħal qabel. Is-27 ta’ Marzu kien
ġiet rilaxxata verżjoni ġdida ta' UC Browser 12.10.9.1193, li aċċessat is-server permezz ta' HTTPS:
Barra minn hekk, wara l-"iffissar" u sal-ħin tal-kitba ta' dan l-artikolu, jekk tipprova tiftaħ PDF f'browser irriżulta f'messaġġ ta' żball bit-test "Oops, xi ħaġa marret ħażin!" Ma saritx talba lis-server meta pprova jiftaħ PDF, iżda saret talba meta tnieda l-browser, li tagħti ħjiel dwar il-kapaċità kontinwa li tniżżel kodiċi eżekutibbli bi ksur tar-regoli tal-Google Play.
Sors: www.habr.com