
Ro-rĂ dh
Aig deireadh aâ MhĂ irt tha sinn , gun do lorg iad comas falaichte airson còd neo-dhearbhte a luchdachadh agus a ruith ann am Brabhsair UC. An-diugh bheir sinn sĂšil mhionaideach air mar a bhios an luchdachadh sĂŹos seo a âtachairt agus mar as urrainn do luchd-hackers a chleachdadh airson an adhbharan fhèin.
O chionn Ăšine, chaidh Brabhsair UC a shanasachadh agus a sgaoileadh gu math ionnsaigheach: chaidh a chuir a-steach air innealan luchd-cleachdaidh a âcleachdadh malware, air a chuairteachadh bho dhiofar lĂ raich fo chruth faidhlichean bhidio (ie, bha luchd-cleachdaidh den bheachd gu robh iad aâ luchdachadh sĂŹos, mar eisimpleir, bhidio porn, ach an Ă ite sin fhuair e APK leis aâ bhrobhsair seo), cleachd brataichean eagallach le teachdaireachdan gu robh am brabhsair seann-fhasanta, so-leònte, agus stuth mar sin. Anns a 'bhuidheann oifigeil UC Browser air VK tha , anns am faod luchd-cleachdaidh gearan a dhèanamh mu sanasachd mĂŹ-chothromach, tha mòran eisimpleirean ann an sin. Ann an 2016 bha eadhon ann ann an Ruisis (tha, sanasachd airson brabhsair bacadh sanasachd).
Aig Ă m sgrĂŹobhaidh, tha còrr air 500 stĂ ladh aig UC Browser air Google Play. Tha seo drĂšidhteach - chan eil ach barrachd aig Google Chrome. Am measg nan lèirmheasan chĂŹ thu tòrr ghearanan mu shanasachd agus ath-sheòlaidhean gu cuid de thagraidhean air Google Play. Bâ e seo adhbhar an rannsachaidh againn: chuir sinn romhainn faicinn an robh Brabhsair UC aâ dèanamh rudeigin dona. Agus thionndaidh e a-mach gun do rinn e!
Anns aâ chòd tagraidh, lorgadh an comas còd so-ghnĂŹomhaichte a luchdachadh sĂŹos agus a ruith, air Google Play. A bharrachd air an fhĂŹrinn gu bheil Brabhsair UC aâ luchdachadh sĂŹos còd so-ghnĂŹomhaichte, bidh e a âdèanamh sin ann an dòigh neo-chinnteach, a dhâ fhaodar a chleachdadh gus ionnsaigh MitM a dhèanamh. Feuch an dèan sinn a leithid de ionnsaigh.
Tha a h-uile dad a tha sgrĂŹobhte gu h-ĂŹosal buntainneach airson an dreach de Brabhsair UC a bha ri fhaighinn air Google Play aig Ă m an sgrĂšdaidh:
package: com.UCMobile.intl
versionName: 12.10.8.1172
versionCode: 10598
sha1 APK-ŃаКНа: f5edb2243413c777172f6362876041eb0c3a928cVector ionnsaigh a thoirt air a
Ann am foillseachadh Brabhsair UC gheibh thu seirbheis le ainm fèin-mhÏneachaidh com.uc.deployment.UpgradeDeployService.
<service android_exported="false" android_name="com.uc.deployment.UpgradeDeployService" android_process=":deploy" />
Nuair a thòisicheas an t-seirbheis seo, nĂŹ am brabhsair iarrtas POST gu , a chithear ann an trafaic beagan Ăšine Ă s deidh tòiseachadh. Mar fhreagairt, is dòcha gum faigh e òrdugh airson Ăšrachadh no modal Ăšr a luchdachadh sĂŹos. Rè an anailis, cha tug an frithealaiche òrdughan mar sin, ach mhothaich sinn nuair a dhâ fheuchas sinn ri PDF fhosgladh sa bhrobhsair, gun dèan e dĂ rna iarrtas chun t-seòladh a chaidh a shònrachadh gu h-Ă rd, agus Ă s deidh sin bidh e a âluchdachadh sĂŹos an leabharlann dĂšthchasach. Gus an ionnsaigh a dhèanamh, chuir sinn romhainn am feart seo de UC Browser a chleachdadh: an comas PDF fhosgladh a âcleachdadh leabharlann dĂšthchasach, nach eil san APK agus a bhios e aâ luchdachadh sĂŹos bhon eadar-lĂŹn ma tha sin riatanach. Is fhiach a bhith mothachail, gu teòiridheach, gum faodar toirt air Brabhsair UC rudeigin a luchdachadh sĂŹos Ă s aonais eadar-obrachadh luchd-cleachdaidh - ma bheir thu seachad freagairt air a dheagh chruthachadh do iarrtas a thèid a chuir gu bĂ s Ă s deidh don bhrobhsair a chuir air bhog. Ach airson seo a dhèanamh, feumaidh sinn sgrĂšdadh nas mionaidiche a dhèanamh air aâ phròtacal eadar-obrachaidh leis an t-seirbheisiche, agus mar sin cho-dhĂšin sinn gum biodh e na bâ fhasa am freagairt eadar-ghluasaid a dheasachadh agus an leabharlann a chuir na Ă ite airson a bhith ag obair le PDF.
Mar sin, nuair a tha neach-cleachdaidh airson PDF fhosgladh gu dĂŹreach sa bhrobhsair, chithear na h-iarrtasan a leanas anns an trafaic:

An toiseach tha iarrtas POST gu Ă s deidh sin
Tha tasglann le leabharlann airson coimhead air PDF agus cruthan oifis air a luchdachadh sÏos. Tha e loidsigeach a bhith den bheachd gu bheil a 'chiad iarrtas a' sgaoileadh fiosrachadh mun t-siostam (co-dhiÚ an ailtireachd gus an leabharlann a tha a dhÏth a thoirt seachad), agus mar fhreagairt dha gheibh am brabhsair beagan fiosrachaidh mun leabharlann a dh'fheumar a luchdachadh sÏos: an seòladh agus, 's dòcha , rudeigin eile. 'S e an duilgheadas a th' ann gu bheil an t-iarrtas seo air a chrioptachadh.
Iarr criomag
Freagair criomag


Tha an leabharlann fhèin air a phacaigeadh ann an ZIP agus chan eil e air a chrioptachadh.

Lorg còd dÏ-chrioptachaidh trafaic
Feuchaidh sinn ri freagairt an fhrithealaiche a mhĂŹneachadh. Bheir sinn sĂšil air còd aâ chlas com.uc.deployment.UpgradeDeployService: bho mhodh onStartCommand Rach gu com.uc.deployment.bx, agus uaith gu 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);
}ChÏ sinn foirm iarrtas POST an seo. Bidh sinn a 'toirt aire do bhith a' cruthachadh sreath de 16 bytes agus a lÏonadh: 0x5F, 0, 0x1F, -50 (= 0xCE). Co-chòrdadh ris na chunnaic sinn san iarrtas gu h-à rd.
Anns an aon chlas chÏ thu clas neadachaidh aig a bheil dòigh inntinneach eile:
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");
}
} Bidh an dòigh aâ toirt sreath de bytes mar chur-a-steach agus aâ dèanamh cinnteach gur e 0x60 am byte neoni no gur e 0xD0 an treas byte, agus gur e 1, 11 no 0x1F an dĂ rna byte. Bidh sinn a 'coimhead air an fhreagairt bhon fhrithealaiche: is e neoni byte 0x60, is e an dĂ rna fear 0x1F, is e an treas fear 0x60. Tha e coltach ris na tha a dhĂŹth oirnn. Aâ breithneachadh leis na loidhnichean (âup_decryptâ, mar eisimpleir), bu chòir dòigh a ghairm an seo a dhĂŹ-chrioptaicheas freagairt an fhrithealaiche.
Gluaisidh sinn air adhart chun a 'mhodh-obrachaidh gj. Thoir an aire gur e aâ chiad argamaid am byte aig offset 2 (ie 0x1F sa chĂšis againn), agus an dĂ rna fear freagairt an fhrithealaiche Ă s aonais
chiad 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;
} Gu follaiseach, an seo tha sinn aâ taghadh algairim dĂŹ-chrioptachaidh, agus an aon bhite a tha nar
cĂšis co-ionann ri 0x1F, aâ comharrachadh aon de thrĂŹ roghainnean a dhâ fhaodadh a bhith ann.
Tha sinn a 'leantainn oirnn a' sgrĂšdadh a 'chòd. Ăs deidh leum no dhĂ lorg sinn sinn fhĂŹn ann an dòigh le ainm fèin-mhĂŹneachaidh dĂŹ-chrioptachadhBytesByKey.
An seo tha dà byte eile air an sgaradh bhon fhreagairt againn, agus gheibhear sreang bhuapa. Tha e soilleir gur ann san dòigh seo a tha an iuchair airson an teachdaireachd a dhÏ-chrioptachadh air a thaghadh.
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;
}Aâ coimhead air adhart, tha sinn aâ toirt fa-near nach eil sinn fhathast aâ faighinn iuchair aig an ĂŹre seo, ach dĂŹreach an âaithnichearâ. Tha a bhith aâ faighinn an iuchair beagan nas iom-fhillte.
Anns an ath dhòigh, thèid dà pharamadair eile a chur ris an fheadhainn a th 'ann mar-thà , a' dèanamh ceithir dhiubh: an à ireamh draoidheachd 16, am prÏomh aithnichear, an dà ta crioptaichte, agus sreang neo-thuigsinn (anns a 'chÚis againn, falamh).
public final byte[] l(String keyId, byte[] encrypted) throws SecException {
return this.ayJ().staticBinarySafeDecryptNoB64(16, keyId, encrypted, "");
}Ăs deidh sreath de ghluasadan ruigidh sinn am modh staticBinarySafeDecryptNoB64 eadar-aghaidh com.alibaba.wireless.security.open.staticdataencrypt.IStaticDataEncryptComponent. Chan eil clasaichean anns aâ phrĂŹomh chòd tagraidh a chuireas an eadar-aghaidh seo an gnĂŹomh. Tha leithid de chlas anns an fhaidhle lib/armeabi-v7a/libsgmain.so, rud nach e fĂŹor .so a th' ann, ach .jar. Tha an dòigh anns a bheil Ăšidh againn air a bhuileachadh mar a leanas:
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);
}
//...
} An seo tha an liosta de pharamadairean againn air a chur ris le dĂ chunntas a bharrachd: 2 agus 0. Aâ breithneachadh le
a h-uile cĂ il, tha 2 aâ ciallachadh dĂŹ-chrioptachadh, mar anns an dòigh do Dheireannach clas siostam javax.crypto.Cipher. Agus tha seo uile air a ghluasad gu Router sònraichte leis an Ă ireamh 10601 - tha e coltach gur e seo an Ă ireamh Ă ithne.
Ăs deidh an ath shreath de ghluasadan lorg sinn clas a chuireas an eadar-aghaidh an gnĂŹomh Co-phĂ irt IRouter agus modh 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);
}
}Agus cuideachd clas Leabharlann JNICL, anns a bheil am modh dĂšthchasach air ainmeachadh doCommandNative:
package com.taobao.wireless.security.adapter;
public class JNICLibrary {
public static native Object doCommandNative(int arg0, Object[] arg1);
}Tha seo aâ ciallachadh gum feum sinn dòigh a lorg anns aâ chòd dhĂšthchasach doCommandNative. Agus seo far a bheil an spòrs a 'tòiseachadh.
Cur às do chòd inneal
Ann am faidhle libsgmain.so (a tha dha-rĂŹribh na .jar agus anns an do lorg sinn cur an gnĂŹomh cuid de eadar-aghaidh co-cheangailte ri crioptachadh dĂŹreach gu h-Ă rd) tha aon leabharlann dĂšthchasach: libsgmainso-6.4.36.so. Bidh sinn ga fhosgladh ann an IDA agus aâ faighinn dòrlach de bhogsaichean còmhraidh le mearachdan. Is e an duilgheadas a thâ ann gu bheil clĂ r cinn na h-earrainn neo-dhligheach. Tha seo air a dhèanamh a dh'aona ghnothach gus an anailis a dhèanamh nas duilghe.

Ach chan eil feum air: gus faidhle ELF a luchdachadh gu ceart agus a sgrĂšdadh, tha clĂ r cinn a âphrògraim gu leòr. Mar sin, bidh sinn dĂŹreach aâ cuir Ă s don chlĂ r earrannan, aâ toirt a-mach na raointean co-fhreagarrach anns aâ bhann-cinn.

Fosgail am faidhle ann an IDA a-rithist.
Tha dĂ dhòigh air innse don inneal mas-fhĂŹor Java far a bheil dĂŹreach anns an leabharlann dhĂšthchasach a tha buileachadh modh a chaidh ainmeachadh ann an còd Java mar dhĂšthchasach. Is e aâ chiad fhear ainm gnè a thoirt dha Java_package_name_ClassName_MethodName.
Is e an dĂ rna fear a chlĂ radh nuair a bhios tu aâ luchdachadh an leabharlann (anns aâ ghnĂŹomh JNI_OnLoad)
aâ cleachdadh gairm gnĂŹomh Luchd-clĂ raidh.
Anns a 'chÚis againn, ma chleachdas sinn a' chiad dhòigh, bu chòir an t-ainm a bhith mar seo: Java_com_taobao_wireless_security_adapter_JNICLibrary_doCommandNative.
Chan eil an leithid de ghnĂŹomh am measg nan gnĂŹomhan Ă s-mhalairt, a tha aâ ciallachadh gum feum thu gairm a choimhead Luchd-clĂ raidh.
Rachamaid chun an gnĂŹomh JNI_OnLoad agus chĂŹ sinn an dealbh seo:

Dè tha dol an seo? Aig aâ chiad sealladh, tha toiseach is deireadh na h-obrach Ă bhaisteach airson ailtireachd ARM. Bidh a 'chiad stiĂšireadh air a' chruach a 'stòradh susbaint nan clĂ ran a chleachdas an gnĂŹomh san obair aice (sa chĂšis seo, R0, R1 agus R2), a bharrachd air susbaint a' chlĂ r LR, anns a bheil an seòladh tilleadh bhon ghnĂŹomh . Bidh an stiĂšireadh mu dheireadh ag ath-nuadhachadh na clĂ ran a chaidh a shĂ bhaladh, agus thèid an seòladh tilleadh a chuir sa chlĂ r PC sa bhad - mar sin a âtilleadh bhon ghnĂŹomh. Ach ma choimheadas tu gu dlĂšth, chĂŹ thu gu bheil an stiĂšireadh mu dheireadh ag atharrachadh an t-seòladh tilleadh a tha air a stòradh air aâ chruach. Feuch an obraich sinn cò ris a bhios e coltach Ă s deidh sin
cur an gnĂŹomh còd. Tha seòladh sònraichte 1xB0 air a luchdachadh a-steach do R130, tha 5 air a thoirt air falbh bhuaithe, an uairsin thèid a ghluasad gu R0 agus tha 0x10 air a chur ris. Tha e a 'tionndadh a-mach 0xB13B. Mar sin, tha IDA den bheachd gur e tilleadh gnĂŹomh Ă bhaisteach a thâ anns an stiĂšireadh mu dheireadh, ach gu dearbh tha e aâ dol chun t-seòladh Ă ireamhaichte 0xB13B.
Is fhiach cuimhneachadh an seo gu bheil dĂ mhodh agus dĂ sheata stiĂširidh aig pròiseasairean ARM: ARM agus Thumb. Tha am pĂ irt as lugha den t-seòladh ag innse don phròiseasar dè an seata stiĂširidh a thathas aâ cleachdadh. Is e sin, is e an seòladh 0xB13A gu dearbh, agus tha aon anns aâ phĂŹos as cudromaiche aâ comharrachadh modh an òrdag.
Chaidh âadapterâ coltach ris a chuir ri toiseach gach gnĂŹomh san leabharlann seo agus
còd sgudail. Cha bhi sinn a 'fuireach orra nas mionaidiche - tha sinn dÏreach a' cuimhneachadh
gu bheil fÏor thoiseach cha mhòr a h-uile gnÏomh beagan nas fhaide air falbh.
Leis nach eil an còd aâ leum gu soilleir gu 0xB13A, cha do dhâ aithnich IDA fhèin gun robh an còd suidhichte san Ă ite seo. Airson an aon adhbhar, chan eil e ag aithneachadh a 'mhòr-chuid den chòd anns an leabharlann mar chòd, a tha a' dèanamh mion-sgrĂšdadh rudeigin duilich. Bidh sinn ag innse don IDA gur e seo an còd, agus seo a thachras:

Tha an clĂ r gu soilleir aâ tòiseachadh aig 0xB144. Dè tha ann am sub_494C?

Nuair a bhios sinn aâ gairm aâ ghnĂŹomh seo ann an clĂ r LR, gheibh sinn seòladh aâ chlĂ ir a chaidh ainmeachadh roimhe (0xB144). Ann an R0 - clĂ r-amais sa chlĂ r seo. Is e sin, tha an luach air a thoirt bhon chlĂ r, air a chur ri LR agus tha an toradh
an seòladh airson a dhol. Feuchaidh sinn ri obrachadh a-mach: 0xB144 + [0xB144 + 8* 4] = 0xB144 + 0x120 = 0xB264. Bidh sinn a 'dol chun an t-seòlaidh a fhuair sinn agus a' faicinn gu litireil stiÚireadh feumail no dhà agus a-rithist a 'dol gu 0xB140:

A-nis bidh eadar-ghluasad aig aâ chothromachadh le clĂ r-amais 0x20 bhon chlĂ r.
A rèir meud a 'bhĂšird, bidh mòran de na h-eadar-ghluasadan sin anns a' chòd. Tha aâ cheist ag èirigh a bheil e comasach dòigh air choireigin dèiligeadh ri seo ann an dòigh nas fèin-ghluasadach, gun a bhith ag obrachadh a-mach seòlaidhean le lĂ imh. Agus thig sgriobtaichean agus an comas còd a ghleusadh ann an IDA gu ar taic:
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"Cuir an cursair air loidhne 0xB26A, ruith an sgriobt agus faic an gluasad gu 0xB4B0:

Cha do dh'aithnich IDA an raon seo mar chòd a-rithist. Bidh sinn ga cuideachadh agus aâ faicinn dealbhadh eile an sin:

Chan eil coltas gu bheil an stiĂšireadh Ă s deidh BLX aâ dèanamh mòran ciall, tha e nas coltaiche ri gluasad de sheòrsa air choreigin. Bheir sinn sĂšil air sub_4964:

Agus gu dearbh, an seo tha dword air a thoirt aig an t-seòladh a tha na laighe ann an LR, air a chur ris an t-seòladh seo, Ă s deidh sin thèid an luach aig an t-seòladh a thig Ă s a thoirt agus a chuir air aâ chruach. Cuideachd, tha 4 air a chur ri LR gus an tèid an aon chothromachadh seo a sheachnadh Ă s deidh dha tilleadh bhon ghnĂŹomh. Ăs deidh sin bheir an Ă ithne POP {R1} an luach a thig Ă s aâ chruach. Ma choimheadas tu air na tha suidhichte aig seòladh 0xB4BA + 0xEA = 0xB5A4, chĂŹ thu rudeigin coltach ri clĂ r seòlaidh:

Gus an dealbhadh seo a ghleusadh, feumaidh tu dĂ pharamadair fhaighinn bhon chòd: an chothromachadh agus an Ă ireamh clĂ raidh anns a bheil thu airson an toradh a chuir. Airson gach clĂ r a dhâ fhaodadh a bhith ann, feumaidh tu pĂŹos còd ullachadh ro-lĂ imh.
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"Cuiridh sinn an cursair aig toiseach an structair a tha sinn airson a chur na Ă ite - 0xB4B2 - agus ruith an sgriobt:

A bharrachd air na structaran a chaidh ainmeachadh roimhe, tha na leanas anns aâ chòd cuideachd:

Mar a thachair sa chĂšis roimhe, Ă s deidh an stiĂšireadh BLX tha cothromachadh ann:

Bidh sinn aâ toirt aâ chothromachadh chun t-seòlaidh bho LR, ga chur ri LR agus aâ dol ann. 0x72044 + 0xC = 0x72050. Tha an sgriobt airson an dealbhadh seo gu math sĂŹmplidh:
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"Toradh coileanadh an sgriobt:

Aon uair âs gu bheil a h-uile cĂ il glaiste sa ghnĂŹomh, faodaidh tu IDA a chomharrachadh chun fhĂŹor thoiseach aige. Cuiridh e an còd gnĂŹomh gu lèir ri chèile, agus faodar a thoirt air falbh le bhith aâ cleachdadh HexRays.
Sreathan dÏ-chòdachadh
Tha sinn air ionnsachadh dèiligeadh ri obfuscation còd inneal anns an leabharlann libsgmainso-6.4.36.so bho UC Browser agus fhuair e an còd gnÏomh 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;
}Bheir sinn sĂšil nas mionaidiche air na loidhnichean a leanas:
sub_73E24(&unk_83EA6, &v6, 49);
clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);Ann an gnĂŹomh fo_73E24 tha e soilleir gu bheil ainm aâ chlas air a dhĂŹ-chrioptachadh. Mar pharamadairean don ghnĂŹomh seo, thathas aâ dol seachad air comharradh dĂ ta coltach ri dĂ ta crioptaichte, bufair sònraichte agus Ă ireamh. Gu follaiseach, Ă s deidh an gnĂŹomh a ghairm, bidh loidhne dĂŹ-chrioptaichte anns a âbhufair, leis gu bheil e air a chuir chun ghnĂŹomh LorgClas, a bheir ainm aâ chlas mar an dĂ rna paramadair. Mar sin, is e an Ă ireamh meud a 'bhufair no fad na loidhne. Feuchaidh sinn ri ainm aâ chlas a mhĂŹneachadh, bu chòir dha innse dhuinn a bheil sinn aâ dol san t-slighe cheart. Bheir sinn sĂšil nas mionaidiche air na thachras ann an fo_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;
}gnĂŹomh fo_7AF78 aâ cruthachadh eisimpleir de shoitheach airson arrays byte den mheud ainmichte (cha bhith sinn aâ fuireach gu mionaideach air na soithichean sin). An seo tha dĂ shoitheach den leithid air an cruthachadh: tha an loidhne ann an aon "DcO/lcK+h?m3c*q@" (tha e furasta tomhas gur e iuchair a tha seo), tha dĂ ta crioptaichte anns an fhear eile. An uairsin, tha an dĂ rud air an cur ann an structar sònraichte, a thèid a thoirt don ghnĂŹomh fo_6115C. Comharraichidh sinn cuideachd raon leis an luach 3 san structar seo. ChĂŹ sinn an ath rud a thachras don structar seo.
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;
}Tha am paramadair suidse na raon structair a chaidh a shònrachadh roimhe seo leis an luach 3. Thoir sĂšil air cĂšis 3: chun ghnĂŹomh fo_6364C thèid paramadairean a thoirt seachad bhon structar a chaidh a chur ris an sin anns aâ ghnĂŹomh roimhe, ie an iuchair agus dĂ ta crioptaichte. Ma bheir thu sĂšil gheur air fo_6364C, faodaidh tu an algairim RC4 aithneachadh ann.
Tha algorithm agus iuchair againn. Feuchaidh sinn ri ainm aâ chlas a mhĂŹneachadh. Seo na thachair: com/taobao/uèir/tèarainteachd/adapter/JNICLibrary. Sgoinneil! Tha sinn air an t-slighe cheart.
Craobh Ă ithne
A-nis feumaidh sinn dĂšbhlan a lorg Luchd-clĂ raidh, a chomharraicheas sinn don ghnĂŹomh doCommandNative. Bheir sinn sĂšil air na gnĂŹomhan ris an canar bho JNI_OnLoad, agus gheibh sinn a-staigh e fo_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;
}Agus gu dearbh, tha modh dÚthchasach leis an ainm clà raichte an seo doCommandNative. A-nis tha fios againn air an t-seòladh aige. ChÏ sinn dè nÏ e.
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;
}Leis an ainm faodaidh tu tomhas gur e seo an t-Ă ite inntrigidh airson a h-uile gnĂŹomh a cho-dhĂšin an luchd-leasachaidh gluasad chun leabharlann dĂšthchasach. Tha Ăšidh againn ann an gnĂŹomh Ă ireamh 10601.
ChĂŹ thu bhon chòd gu bheil an Ă ireamh Ă ithne aâ toirt a-mach trĂŹ Ă ireamhan: Ă ithne/10000, Ă ithne % 10000/100 и Ă ithne % 10, i.e., nar cĂšis, 1, 6 agus 1. Tha na trĂŹ Ă ireamhan seo, a bharrachd air comharran airson JNIEnv agus tha na h-argamaidean a thèid a thoirt don ghnĂŹomh air an cur ri structar agus air an toirt seachad. Aâ cleachdadh nan trĂŹ Ă ireamhan a fhuaireadh (sònraichidh sinn iad N1, N2 agus N3), thèid craobh-Ă ithne a thogail.
Rud mar seo:

Tha an craobh air a lĂŹonadh a-steach gu fiĂšghantach JNI_OnLoad.
Bidh trĂŹ Ă ireamhan aâ còdachadh na slighe sa chraoibh. Anns gach duilleag den chraoibh tha seòladh pòcaidh na gnĂŹomh co-fhreagarrach. Tha an iuchair anns an nĂłd pĂ rant. Chan eil e duilich a bhith aâ lorg an Ă ite anns aâ chòd far a bheil an gnĂŹomh a dhâ fheumas sinn air a chur ris aâ chraoibh ma thuigeas tu a h-uile structar a thathar aâ cleachdadh (chan eil sinn aâ toirt cunntas orra gus nach cuir thu Ă s do artaigil a tha caran mòr mar-thĂ ).
Tuilleadh uireasbhuidh
Fhuair sinn seòladh na gnÏomh a bu chòir trafaic a dhÏ-chrioptachadh: 0x5F1AC. Ach tha e ro thrà th airson gà irdeachas a dhèanamh: tha luchd-leasachaidh Brabhsair UC air iongnadh eile ullachadh dhuinn.
Ăs deidh dhuinn na paramadairean fhaighinn bhon raon a chaidh a chruthachadh ann an còd Java, gheibh sinn
chun ghnĂŹomh aig seòladh 0x4D070. Agus an seo tha seòrsa eile de obfuscation còd aâ feitheamh rinn.
Chuir sinn dĂ chlĂ r-amais ann an R7 agus R4:

Bidh sinn aâ gluasad aâ chiad chlĂ r-amais gu R11:

Gus seòladh fhaighinn bho bhòrd, cleachd clà r-amais:

An dèidh a dhol chun a 'chiad sheòladh, thèid an dà rna clà r-amais a chleachdadh, a tha ann an R4. Tha 230 eileamaidean sa chlà r.
Dè a nÏ thu mu dheidhinn? Faodaidh tu innse don IDA gur e tionndadh a tha seo: Deasaich -> Eile -> Sònraich gnà thasan-cainnt suidse.

Tha an còd mar thoradh air sin uamhasach. Ach, aâ dèanamh do shlighe tron ââjungle aige, chĂŹ thu gairm gu gnĂŹomh air a bheil sinn eòlach mu thrĂ th fo_6115C:

Bha tionndadh ann far an robh cĂšis 3 ann gun robh dĂŹ-chrioptachadh aâ cleachdadh an algairim RC4. Agus anns a 'chĂšis seo, tha an structar a chaidh a thoirt don ghnĂŹomh air a lĂŹonadh bho na crĂŹochan a chaidh a thoirt seachad doCommandNative. Cuimhnicheamaid na bha againn an sin draoidheachdInt leis an luach 16. Bidh sinn a 'coimhead air a' chĂšis fhreagarrach - agus an dèidh grunn eadar-ghluasadan lorg sinn an còd leis an aithnichear an algairim.

Is e seo AES!
Tha an algairim ann, chan eil air fhà gail ach na crÏochan aige fhaighinn: modh, iuchair agus, is dòcha, an vectar tòiseachaidh (tha a là thaireachd an urra ri modh obrachaidh an algairim AES). Feumaidh an structar leotha a bhith air a chruthachadh an à iteigin mus gairm an gnÏomh fo_6115C, ach tha am pà irt seo den chòd gu sònraichte mÏ-mhodhail, agus mar sin tha am beachd ag èirigh gus an còd a ghleusadh gus am bi a h-uile paramadair den ghnÏomh dÏ-chrioptachaidh air a thilgeil a-steach do fhaidhle.
Patch
Gus nach sgrĂŹobh thu an còd paiste gu lèir ann an cĂ nan cruinneachaidh le lĂ imh, faodaidh tu ruith Android StiĂšidio, sgrĂŹobh gnĂŹomh an sin a gheibh na h-aon pharaimeatairean cuir-a-steach ris aâ ghnĂŹomh dĂŹ-chrioptachaidh againn agus sgrĂŹobhas e gu faidhle, an uairsin dèan lethbhreac is pasgadh den chòd a bhios an co-chruinneadair aâ gineadh.
Thug ar caraidean bho sgioba Brabhsair UC aire cuideachd do ghoireasachd còd a chuir ris. Cuimhnichidh sinn gu bheil còd sgudail againn aig toiseach gach gnĂŹomh a tha furasta a chuir na Ă ite le gin eile. Gu math goireasach đ Ach, aig toiseach na gnĂŹomh targaid chan eil Ă ite gu leòr ann airson aâ chòd a shĂ bhaileas a h-uile paramadair gu faidhle. Bâ fheudar dhomh a roinn ann am pĂ irtean agus blocaichean sgudail bho ghnĂŹomhan nĂ baidh a chleachdadh. Bha ceithir earrannan ann uile gu lèir.
A âchiad phĂ irt:

Ann an ailtireachd ARM, thèid aâ chiad ceithir paramadairean gnĂŹomh a dhol tro chlĂ ran R0-R3, thèid an còrr, ma tha gin ann, tron ââââchruach. Tha an seòladh tilleadh air aâ chlĂ r LR. Feumar seo uile a shĂ bhaladh gus an obraich an gnĂŹomh Ă s deidh dhuinn na crĂŹochan aige a dhumpadh. Feumaidh sinn cuideachd a h-uile clĂ r a chleachdas sinn sa phròiseas a shĂ bhaladh, mar sin nĂŹ sinn PUSH.W {R0-R10,LR}. Ann an R7 gheibh sinn seòladh liosta nam paramadairean a thèid a thoirt don ghnĂŹomh tron ââââchruach.
A âcleachdadh aâ ghnĂŹomh fopen leig leinn am faidhle fhosgladh /data/ionadail/tmp/aes ann am modh "ab".
i.e. airson cur-ris. Ann an R0 bidh sinn aâ luchdachadh seòladh ainm an fhaidhle, ann an R1 - seòladh na loidhne a tha aâ comharrachadh aâ mhodh. Agus an seo thig an còd sgudail gu crĂŹch, agus mar sin gluaisidh sinn air adhart chun ath ghnĂŹomh. Gus an lean e air ag obair, chuir sinn aig an toiseach an gluasad gu fĂŹor chòd na h-obrach, a 'dol seachad air an sgudal, agus an Ă ite an sgudail bidh sinn a' cur ris a 'phaiste leantainneach.

A' gairm fopen.
Aâ chiad trĂŹ paramadairean den ghnĂŹomh aes tha seòrsa agad int. Leis gun do shĂ bhail sinn na clĂ ran don stac an toiseach, is urrainn dhuinn dĂŹreach an gnĂŹomh a thoirt seachad sgrĂŹobhadh na seòlaidhean aca air aâ chruaich.

An uairsin tha trÏ structaran againn anns a bheil meud an dà ta agus comharradh don dà ta airson an iuchair, vectar tòiseachaidh agus dà ta crioptaichte.

Aig an deireadh, dĂšin am faidhle, cuir air ais na clĂ ran agus gluais smachd chun fhĂŹor ghnĂŹomh aes.
Bidh sinn aâ cruinneachadh APK le leabharlann glaiste, ga shoidhnigeadh, ga luchdachadh suas chun inneal / emuladair, agus ga chuir air bhog. Tha sinn a 'faicinn gu bheil an dump againn ga chruthachadh, agus tha tòrr dĂ ta ga sgrĂŹobhadh an sin. Bidh am brabhsair aâ cleachdadh crioptachadh chan ann a-mhĂ in airson trafaic, agus bidh a h-uile crioptachadh aâ dol tron ââââghnĂŹomh sin. Ach airson adhbhar air choireigin chan eil an dĂ ta riatanach ann, agus chan eil an t-iarrtas a tha a dhĂŹth ri fhaicinn anns an trafaic. Gus nach fuirich sinn gus an dèan Brabhsair UC an t-iarrtas riatanach a dhèanamh, gabhamaid am freagairt crioptaichte bhon t-seirbheisiche a fhuaireadh na bu thrĂ ithe agus an tagradh a-rithist: cuir an dĂŹ-chrioptachadh ri onCreate of the main activity.
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;)IBidh sinn a 'cruinneachadh, a' soidhnigeadh, a 'stĂ ladh, a' cur air bhog. Gheibh sinn NullPointerException oir thill am modh null.
Rè tuilleadh sgrĂšdaidh air aâ chòd, chaidh gnĂŹomh a lorg a tha aâ mĂŹneachadh loidhnichean inntinneach: âMETA-INF/â agus â.RSAâ. Tha e coltach gu bheil an aplacaid aâ dearbhadh an teisteanais aige. No eadhon aâ gineadh iuchraichean bhuaithe. Chan eil mi dha-rĂŹribh ag iarraidh dèiligeadh ris na tha aâ tachairt leis an teisteanas, agus mar sin sleamhnaichidh sinn an teisteanas ceart e. Feuch an gleidh sinn an loidhne chrioptaichte gus am faigh sinn âBLABLINF/â an Ă ite âMETA-INF/â, cruthaich pasgan leis an ainm sin san APK agus cuir teisteanas brabhsair na feòraig an sin.
Bidh sinn a 'cruinneachadh, a' soidhnigeadh, a 'stĂ ladh, a' cur air bhog. Bingo! Tha an iuchair againn!
MhitM
Fhuair sinn iuchair agus vectar tòiseachaidh co-ionann ris an iuchair. Feuchaidh sinn ri freagairt an fhrithealaiche a dhÏ-chrioptachadh ann am modh CBC.

ChĂŹ sinn URL an tasglann, rudeigin coltach ri MD5, âextract_unzipsizeâ agus Ă ireamh. NĂŹ sinn sgrĂšdadh: tha MD5 an tasglann mar an ceudna, tha meud an leabharlainn gun phacaid mar an ceudna. Tha sinn aâ feuchainn ris an leabharlann seo a ghleusadh agus a thoirt don bhrobhsair. Gus sealltainn gu bheil an leabharlann glaiste againn air luchdachadh, cuiridh sinn air bhog RĂšn airson SMS a chruthachadh leis an teacsa âPWNED!â Cuiridh sinn an Ă ite dĂ fhreagairt bhon fhrithealaiche: agus gus an tasglann a luchdachadh sĂŹos. Anns a 'chiad fhear bidh sinn a' cur an Ă ite MD5 (chan eil am meud ag atharrachadh Ă s deidh a bhith air a dhĂŹ-phapadh), anns an dĂ rna fear bidh sinn a 'toirt seachad an tasglann leis an leabharlann sgĂ inte.
Bidh am brabhsair aâ feuchainn ris an tasglann a luchdachadh sĂŹos grunn thursan, Ă s deidh sin bheir e mearachd. A rèir choltais rudeigin
cha toigh leis. Mar thoradh air mion-sgrĂšdadh a dhèanamh air aâ chruth meallta seo, thionndaidh e a-mach gu bheil am frithealaiche cuideachd aâ sgaoileadh meud an tasglann:

Tha e air a chòdachadh ann an LEB128. Ăs deidh a âphaiste, dhâ atharraich meud an tasglann leis an leabharlann beagan, agus mar sin bha am brabhsair den bheachd gun deach an tasglann a luchdachadh sĂŹos gu cam, agus Ă s deidh grunn oidhirpean thilg e mearachd.
Bidh sinn ag atharrachadh meud an tasglann ... Agus - buaidh! đ Tha an toradh anns aâ bhidio.
Builean agus freagairt leasaiche
San aon dòigh, dhâ fhaodadh luchd-hackers am feart mĂŹ-chinnteach de UC Browser a chleachdadh gus leabharlannan droch-rĂšnach a sgaoileadh agus a ruith. Obraichidh na leabharlannan sin ann an co-theacs aâ bhrabhsair, agus mar sin gheibh iad a h-uile cead siostam. Mar thoradh air an sin, tha an comas air uinneagan fiasgach a thaisbeanadh, a bharrachd air ruigsinneachd air faidhlichean obrach an fheòrag SĂŹneach orains, a âtoirt a-steach logins, faclan-faire agus briosgaidean a tha air an stòradh san stòr-dĂ ta.
Chuir sinn fios gu luchd-leasachaidh Brabhsair UC agus dhâ innis sinn dhaibh mun duilgheadas a lorg sinn, dhâ fheuch sinn ri so-leòntachd agus an cunnart a chomharrachadh, ach cha do bhruidhinn iad rinn idir. Aig an aon Ă m, lean am brobhsair aâ nochdadh a feart cunnartach ann an sealladh soilleir. Ach aon uair âs gun do nochd sinn mion-fhiosrachadh mun so-leòntachd, cha robh e comasach tuilleadh a leigeil seachad mar a bha e roimhe. Bha 27 am MĂ rt
chaidh dreach Ăšr de UC Browser 12.10.9.1193 a leigeil ma sgaoil, a fhuair cothrom air an fhrithealaiche tro HTTPS: .
A bharrachd air an sin, Ă s deidh an âcĂ radhâ agus gus an deach an artaigil seo a sgrĂŹobhadh, dhâ adhbhraich feuchainn ri PDF fhosgladh ann am brobhsair teachdaireachd mearachd leis an teacsa âOops, chaidh rudeigin ceĂ rr!â Cha deach iarrtas a chuir chun t-seirbheisiche nuair a bha e aâ feuchainn ri PDF fhosgladh, ach chaidh iarrtas a dhèanamh nuair a chaidh am brabhsair a chuir air bhog, a tha aâ nochdadh comas leantainneach còd so-ghnĂŹomhaichte a luchdachadh sĂŹos a tha aâ dol an aghaidh riaghailtean Google Play.
Source: www.habr.com
