A ’coimhead airson so-leòntachd ann am Brabhsair UC

A ’coimhead airson so-leòntachd ann am Brabhsair UC

Ro-ràdh

Aig deireadh a’ Mhàirt tha sinn air aithris, 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 an cuspair, 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 sanasachd bhidio 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, a tha an aghaidh nan riaghailtean airson tagraidhean fhoillseachadh 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-файла: f5edb2243413c777172f6362876041eb0c3a928c

Vector 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 puds.ucweb.com/upgrade/index.xhtml, 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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

An toiseach tha iarrtas POST gu puds.ucweb.com/upgrade/index.xhtmlà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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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 ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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 ’coimhead airson so-leòntachd ann am Brabhsair UC

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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

Bidh sinn a’ gluasad a’ chiad chlàr-amais gu R11:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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 a h-uile còd paiste ann an cànan cruinneachaidh le làimh, faodaidh tu Android Studio a chuir air bhog, gnìomh a sgrìobhadh an sin a gheibh na h-aon pharaimearan cuir a-steach ris a ’ghnìomh dì-chrioptachaidh againn agus a sgrìobhas gu faidhle, agus an uairsin dèan lethbhreac-pas a-steach don chòd a bhios an neach-cruinneachaidh ghineadh.

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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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 ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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

Bidh 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.

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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: puds.ucweb.com/upgrade/index.xhtml 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:

A ’coimhead airson so-leòntachd ann am Brabhsair UC

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.

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

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: puds.ucweb.com/upgrade/index.xhtml.

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

Cuir beachd ann