UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

හැඳින්වීම

මාර්තු අවසානයේ අපි වාර්තා කර ඇත, ඔවුන් UC බ්‍රවුසරයේ සත්‍යාපනය නොකළ කේතයක් පැටවීමට සහ ධාවනය කිරීමට සැඟවුණු හැකියාවක් සොයා ගත් බව. අද අපි විස්තරාත්මකව බලමු මෙම බාගත කිරීම සිදුවන්නේ කෙසේද සහ හැකර්වරුන්ට එය ඔවුන්ගේ අරමුණු සඳහා භාවිතා කළ හැකි ආකාරය.

කලකට පෙර, UC බ්‍රව්සරය ප්‍රචාරණය කර ඉතා ආක්‍රමණශීලී ලෙස බෙදා හරින ලදී: එය අනිෂ්ට මෘදුකාංග භාවිතයෙන් පරිශීලකයින්ගේ උපාංගවල ස්ථාපනය කර, වීඩියෝ ගොනු මුවාවෙන් විවිධ වෙබ් අඩවි වලින් බෙදා හරින ලදී (එනම්, පරිශීලකයින් ඔවුන් බාගත කරන්නේ යැයි සිතුවේ, උදාහරණයක් ලෙස, අසභ්‍ය වීඩියෝවක්, නමුත් ඒ වෙනුවට මෙම බ්‍රවුසරය සමඟ APK එකක් ලැබුණි), බ්‍රවුසරය යල් පැන ගිය, අවදානමට ලක්විය හැකි, සහ එවැනි දේවල් සහිත පණිවිඩ සහිත භයානක බැනර් භාවිතා කරන ලදී. VK හි නිල UC බ්‍රව්සර් සමූහයේ ඇත මාතෘකාවකි, අසාධාරණ වෙළඳ දැන්වීම් ගැන පරිශීලකයින්ට පැමිණිලි කළ හැකි අතර, එහි බොහෝ උදාහරණ තිබේ. 2016 දී පවා තිබුණා වීඩියෝ වෙළඳ දැන්වීම් රුසියානු භාෂාවෙන් (ඔව්, දැන්වීම් අවහිර කරන බ්‍රව්සරයක් සඳහා ප්‍රචාරණය).

ලියන අවස්ථාව වන විට, UC බ්‍රව්සරයට Google Play හි ස්ථාපනයන් 500කට වඩා ඇත. මෙය සිත් ඇදගන්නා සුළුයි - වැඩිපුර ඇත්තේ Google Chrome පමණි. සමාලෝචන අතර ඔබට Google Play හි සමහර යෙදුම් වෙත ප්‍රචාරණය සහ යළි-යොමුවීම් පිළිබඳ පැමිණිලි රාශියක් දැකිය හැකිය. අපගේ පර්යේෂණයට හේතුව මෙයයි: UC බ්‍රව්සරය නරක දෙයක් කරන්නේ දැයි බැලීමට අපි තීරණය කළෙමු. ඔහු එසේ කරන බව පෙනී ගියේය!

යෙදුම් කේතය තුළ, ක්‍රියාත්මක කළ හැකි කේතය බාගත කර ක්‍රියාත්මක කිරීමේ හැකියාව සොයා ගන්නා ලදී, යෙදුම් ප්‍රකාශනය කිරීමේ නීතිවලට පටහැනියි Google Play මත. ක්‍රියාත්මක කළ හැකි කේතය බාගත කිරීමට අමතරව, UC බ්‍රව්සරය එය අනාරක්ෂිත ආකාරයකින් සිදු කරයි, එය MitM ප්‍රහාරයක් දියත් කිරීමට භාවිතා කළ හැකිය. අපි බලමු එහෙම ප්‍රහාරයක් කරන්න පුළුවන්ද කියලා.

පහත ලියා ඇති සියල්ල අධ්‍යයනය කරන අවස්ථාවේ Google Play හි තිබූ UC බ්‍රව්සරයේ අනුවාදයට අදාළ වේ:

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

ප්රහාරක දෛශිකය

UC බ්‍රව්සර් මැනිෆෙස්ටයේ ඔබට ස්වයං පැහැදිලි කිරීමේ නමක් සහිත සේවාවක් සොයාගත හැකිය com.uc.deployment.UpgradeDeployService.

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

මෙම සේවාව ආරම්භ වූ විට, බ්‍රවුසරය POST ඉල්ලීමක් කරයි puds.ucweb.com/upgrade/index.xhtml, ආරම්භයේ සිට ටික වේලාවකට පසු ගමනාගමනය තුළ දැකිය හැකිය. ප්‍රතිචාර වශයෙන්, ඔහුට යම් යාවත්කාලීනයක් හෝ නව මොඩියුලයක් බාගැනීමට විධානයක් ලැබිය හැක. විශ්ලේෂණය අතරතුර, සේවාදායකයා එවැනි විධාන ලබා දී නැත, නමුත් අපි බ්‍රවුසරයේ PDF එකක් විවෘත කිරීමට උත්සාහ කරන විට, එය ඉහත දක්වා ඇති ලිපිනයට දෙවන ඉල්ලීමක් කරන බවත්, පසුව එය ස්වදේශීය පුස්තකාලය බාගත කරන බවත් අපි දුටුවෙමු. ප්‍රහාරය සිදු කිරීම සඳහා, අපි UC බ්‍රව්සරයේ මෙම විශේෂාංගය භාවිතා කිරීමට තීරණය කළෙමු: APK හි නොමැති සහ අවශ්‍ය නම් අන්තර්ජාලයෙන් බාගත කරන ස්වදේශීය පුස්තකාලයක් භාවිතයෙන් PDF විවෘත කිරීමේ හැකියාව. න්‍යායාත්මකව, UC බ්‍රව්සරයට පරිශීලක අන්තර්ක්‍රියා නොමැතිව යමක් බාගත කිරීමට බල කළ හැකි බව සඳහන් කිරීම වටී - ඔබ බ්‍රවුසරය දියත් කිරීමෙන් පසු ක්‍රියාත්මක කරන ලද ඉල්ලීමකට හොඳින් සැකසූ ප්‍රතිචාරයක් ලබා දෙන්නේ නම්. නමුත් මෙය සිදු කිරීම සඳහා, අපි සේවාදායකය සමඟ අන්තර්ක්‍රියා කිරීමේ ප්‍රොටෝකෝලය වඩාත් විස්තරාත්මකව අධ්‍යයනය කළ යුතුය, එබැවින් බාධා කළ ප්‍රතිචාරය සංස්කරණය කිරීම සහ PDF සමඟ වැඩ කිරීම සඳහා පුස්තකාලය ප්‍රතිස්ථාපනය කිරීම පහසු වනු ඇතැයි අපි තීරණය කළෙමු.

එබැවින්, පරිශීලකයෙකුට සෘජුවම බ්‍රවුසරයේ PDF විවෘත කිරීමට අවශ්‍ය වූ විට, ගමනාගමනය තුළ පහත ඉල්ලීම් දැකිය හැකිය:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

මුලින්ම POST ඉල්ලීමක් ඇත puds.ucweb.com/upgrade/index.xhtmlඊට පසු
PDF සහ කාර්යාල ආකෘති බැලීම සඳහා පුස්තකාලයක් සහිත ලේඛනාගාරයක් බාගත කර ඇත. පළමු ඉල්ලීම මඟින් පද්ධතිය පිළිබඳ තොරතුරු සම්ප්‍රේෂණය වන බව උපකල්පනය කිරීම තර්කානුකූල ය (අවම වශයෙන් අවශ්‍ය පුස්තකාලය සැපයීම සඳහා ගෘහ නිර්මාණ ශිල්පය), එයට ප්‍රතිචාර වශයෙන් බ්‍රව්සරයට බාගත කළ යුතු පුස්තකාලය පිළිබඳ යම් තොරතුරු ලැබේ: ලිපිනය සහ, සමහර විට , වෙන මොනවා හරි. ගැටලුව වන්නේ මෙම ඉල්ලීම සංකේතනය කර තිබීමයි.

ඛණ්ඩනය ඉල්ලන්න

පිළිතුරු කොටස

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

පුස්තකාලයම ZIP ඇසුරුම් කර ඇති අතර සංකේතනය කර නොමැත.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

රථවාහන විකේතන කේතය සොයන්න

සේවාදායක ප්‍රතිචාරය විකේතනය කිරීමට උත්සාහ කරමු. අපි පන්ති කේතය දෙස බලමු com.uc.deployment.UpgradeDeployService: ක්රමයෙන් on Start Command යන්න com.uc.deployment.bx, සහ එයින් com.uc.browser.core.dcfe:

    public final void e(l arg9) {
int v4_5;
String v3_1;
byte[] v3;
byte[] v1 = null;
if(arg9 == null) {
v3 = v1;
}
else {
v3_1 = arg9.iGX.ipR;
StringBuilder v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]product:");
v4.append(arg9.iGX.ipR);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]version:");
v4.append(arg9.iGX.iEn);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]upgrade_type:");
v4.append(arg9.iGX.mMode);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]force_flag:");
v4.append(arg9.iGX.iEo);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_mode:");
v4.append(arg9.iGX.iDQ);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_type:");
v4.append(arg9.iGX.iEr);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_state:");
v4.append(arg9.iGX.iEp);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]silent_file:");
v4.append(arg9.iGX.iEq);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apk_md5:");
v4.append(arg9.iGX.iEl);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]download_type:");
v4.append(arg9.mDownloadType);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]download_group:");
v4.append(arg9.mDownloadGroup);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]download_path:");
v4.append(arg9.iGH);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_child_version:");
v4.append(arg9.iGX.iEx);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_series:");
v4.append(arg9.iGX.iEw);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_cpu_arch:");
v4.append(arg9.iGX.iEt);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_cpu_vfp3:");
v4.append(arg9.iGX.iEv);
v4 = new StringBuilder("[");
v4.append(v3_1);
v4.append("]apollo_cpu_vfp:");
v4.append(arg9.iGX.iEu);
ArrayList v3_2 = arg9.iGX.iEz;
if(v3_2 != null && v3_2.size() != 0) {
Iterator v3_3 = v3_2.iterator();
while(v3_3.hasNext()) {
Object v4_1 = v3_3.next();
StringBuilder v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_name:");
v5.append(((au)v4_1).getName());
v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_ver_name:");
v5.append(((au)v4_1).aDA());
v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_ver_code:");
v5.append(((au)v4_1).gBl);
v5 = new StringBuilder("[");
v5.append(((au)v4_1).getName());
v5.append("]component_req_type:");
v5.append(((au)v4_1).gBq);
}
}
j v3_4 = new j();
m.b(v3_4);
h v4_2 = new h();
m.b(v4_2);
ay v5_1 = new ay();
v3_4.hS("");
v3_4.setImsi("");
v3_4.hV("");
v5_1.bPQ = v3_4;
v5_1.bPP = v4_2;
v5_1.yr(arg9.iGX.ipR);
v5_1.gBF = arg9.iGX.mMode;
v5_1.gBI = arg9.iGX.iEz;
v3_2 = v5_1.gAr;
c.aBh();
v3_2.add(g.fs("os_ver", c.getRomInfo()));
v3_2.add(g.fs("processor_arch", com.uc.b.a.a.c.getCpuArch()));
v3_2.add(g.fs("cpu_arch", com.uc.b.a.a.c.Pb()));
String v4_3 = com.uc.b.a.a.c.Pd();
v3_2.add(g.fs("cpu_vfp", v4_3));
v3_2.add(g.fs("net_type", String.valueOf(com.uc.base.system.a.Jo())));
v3_2.add(g.fs("fromhost", arg9.iGX.iEm));
v3_2.add(g.fs("plugin_ver", arg9.iGX.iEn));
v3_2.add(g.fs("target_lang", arg9.iGX.iEs));
v3_2.add(g.fs("vitamio_cpu_arch", arg9.iGX.iEt));
v3_2.add(g.fs("vitamio_vfp", arg9.iGX.iEu));
v3_2.add(g.fs("vitamio_vfp3", arg9.iGX.iEv));
v3_2.add(g.fs("plugin_child_ver", arg9.iGX.iEx));
v3_2.add(g.fs("ver_series", arg9.iGX.iEw));
v3_2.add(g.fs("child_ver", r.aVw()));
v3_2.add(g.fs("cur_ver_md5", arg9.iGX.iEl));
v3_2.add(g.fs("cur_ver_signature", SystemHelper.getUCMSignature()));
v3_2.add(g.fs("upgrade_log", i.bjt()));
v3_2.add(g.fs("silent_install", String.valueOf(arg9.iGX.iDQ)));
v3_2.add(g.fs("silent_state", String.valueOf(arg9.iGX.iEp)));
v3_2.add(g.fs("silent_file", arg9.iGX.iEq));
v3_2.add(g.fs("silent_type", String.valueOf(arg9.iGX.iEr)));
v3_2.add(g.fs("cpu_archit", com.uc.b.a.a.c.Pc()));
v3_2.add(g.fs("cpu_set", SystemHelper.getCpuInstruction()));
boolean v4_4 = v4_3 == null || !v4_3.contains("neon") ? false : true;
v3_2.add(g.fs("neon", String.valueOf(v4_4)));
v3_2.add(g.fs("cpu_cores", String.valueOf(com.uc.b.a.a.c.Jl())));
v3_2.add(g.fs("ram_1", String.valueOf(com.uc.b.a.a.h.Po())));
v3_2.add(g.fs("totalram", String.valueOf(com.uc.b.a.a.h.OL())));
c.aBh();
v3_2.add(g.fs("rom_1", c.getRomInfo()));
v4_5 = e.getScreenWidth();
int v6 = e.getScreenHeight();
StringBuilder v7 = new StringBuilder();
v7.append(v4_5);
v7.append("*");
v7.append(v6);
v3_2.add(g.fs("ss", v7.toString()));
v3_2.add(g.fs("api_level", String.valueOf(Build$VERSION.SDK_INT)));
v3_2.add(g.fs("uc_apk_list", SystemHelper.getUCMobileApks()));
Iterator v4_6 = arg9.iGX.iEA.entrySet().iterator();
while(v4_6.hasNext()) {
Object v6_1 = v4_6.next();
v3_2.add(g.fs(((Map$Entry)v6_1).getKey(), ((Map$Entry)v6_1).getValue()));
}
v3 = v5_1.toByteArray();
}
if(v3 == null) {
this.iGY.iGI.a(arg9, "up_encode", "yes", "fail");
return;
}
v4_5 = this.iGY.iGw ? 0x1F : 0;
if(v3 == null) {
}
else {
v3 = g.i(v4_5, v3);
if(v3 == null) {
}
else {
v1 = new byte[v3.length + 16];
byte[] v6_2 = new byte[16];
Arrays.fill(v6_2, 0);
v6_2[0] = 0x5F;
v6_2[1] = 0;
v6_2[2] = ((byte)v4_5);
v6_2[3] = -50;
System.arraycopy(v6_2, 0, v1, 0, 16);
System.arraycopy(v3, 0, v1, 16, v3.length);
}
}
if(v1 == null) {
this.iGY.iGI.a(arg9, "up_encrypt", "yes", "fail");
return;
}
if(TextUtils.isEmpty(this.iGY.mUpgradeUrl)) {
this.iGY.iGI.a(arg9, "up_url", "yes", "fail");
return;
}
StringBuilder v0 = new StringBuilder("[");
v0.append(arg9.iGX.ipR);
v0.append("]url:");
v0.append(this.iGY.mUpgradeUrl);
com.uc.browser.core.d.c.i v0_1 = this.iGY.iGI;
v3_1 = this.iGY.mUpgradeUrl;
com.uc.base.net.e v0_2 = new com.uc.base.net.e(new com.uc.browser.core.d.c.i$a(v0_1, arg9));
v3_1 = v3_1.contains("?") ? v3_1 + "&dataver=pb" : v3_1 + "?dataver=pb";
n v3_5 = v0_2.uc(v3_1);
m.b(v3_5, false);
v3_5.setMethod("POST");
v3_5.setBodyProvider(v1);
v0_2.b(v3_5);
this.iGY.iGI.a(arg9, "up_null", "yes", "success");
this.iGY.iGI.b(arg9);
}

අපි මෙහි POST ඉල්ලීමක් ගොඩනැගීම දකිමු. අපි බයිට් 16 ක අරාවක් නිර්මාණය කිරීම සහ එහි පිරවීම කෙරෙහි අවධානය යොමු කරමු: 0x5F, 0, 0x1F, -50 (=0xCE). ඉහත ඉල්ලීමේ අප දුටු දේ සමග සමපාත වේ.

එම පන්තියේම ඔබට තවත් රසවත් ක්‍රමයක් ඇති කැදැලි පන්තියක් දැකිය හැකිය:

        public final void a(l arg10, byte[] arg11) {
f v0 = this.iGQ;
StringBuilder v1 = new StringBuilder("[");
v1.append(arg10.iGX.ipR);
v1.append("]:UpgradeSuccess");
byte[] v1_1 = null;
if(arg11 == null) {
}
else if(arg11.length < 16) {
}
else {
if(arg11[0] != 0x60 && arg11[3] != 0xFFFFFFD0) {
goto label_57;
}
int v3 = 1;
int v5 = arg11[1] == 1 ? 1 : 0;
if(arg11[2] != 1 && arg11[2] != 11) {
if(arg11[2] == 0x1F) {
}
else {
v3 = 0;
}
}
byte[] v7 = new byte[arg11.length - 16];
System.arraycopy(arg11, 16, v7, 0, v7.length);
if(v3 != 0) {
v7 = g.j(arg11[2], v7);
}
if(v7 == null) {
goto label_57;
}
if(v5 != 0) {
v1_1 = g.P(v7);
goto label_57;
}
v1_1 = v7;
}
label_57:
if(v1_1 == null) {
v0.iGY.iGI.a(arg10, "up_decrypt", "yes", "fail");
return;
}
q v11 = g.b(arg10, v1_1);
if(v11 == null) {
v0.iGY.iGI.a(arg10, "up_decode", "yes", "fail");
return;
}
if(v0.iGY.iGt) {
v0.d(arg10);
}
if(v0.iGY.iGo != null) {
v0.iGY.iGo.a(0, ((o)v11));
}
if(v0.iGY.iGs) {
v0.iGY.a(((o)v11));
v0.iGY.iGI.a(v11, "up_silent", "yes", "success");
v0.iGY.iGI.a(v11);
return;
}
v0.iGY.iGI.a(v11, "up_silent", "no", "success");
}
}

ක්‍රමය ආදානය ලෙස බයිට් මාලාවක් ගන්නා අතර ශුන්‍ය බයිටය 0x60 හෝ තුන්වන බයිටය 0xD0 ද, දෙවන බයිටය 1, 11 හෝ 0x1F ද යන්න පරීක්ෂා කරයි. අපි සේවාදායකයේ ප්‍රතිචාරය දෙස බලමු: ශුන්‍ය බයිටය 0x60, දෙවැන්න 0x1F, තෙවනුව 0x60 වේ. අපිට අවශ්‍ය දේ වගේ. රේඛා මගින් විනිශ්චය කිරීම (උදාහරණයක් ලෙස "up_decrypt"), සේවාදායකයේ ප්‍රතිචාරය විකේතනය කරන ක්‍රමයක් මෙහි ඇමතිය යුතුය.
අපි ක්‍රමයට යමු gj. පළමු තර්කය ඕෆ්සෙට් 2 හි ඇති බයිටය (එනම් අපගේ නඩුවේ 0x1F) වන අතර දෙවැන්න සේවාදායක ප්‍රතිචාරය නොමැතිව බව සලකන්න.
පළමු බයිට් 16.

     public static byte[] j(int arg1, byte[] arg2) {
if(arg1 == 1) {
arg2 = c.c(arg2, c.adu);
}
else if(arg1 == 11) {
arg2 = m.aF(arg2);
}
else if(arg1 != 0x1F) {
}
else {
arg2 = EncryptHelper.decrypt(arg2);
}
return arg2;
}

නිසැකවම, මෙහිදී අපි විකේතන ඇල්ගොරිතමයක් තෝරා ගනිමු, සහ අපගේ බයිටයම
0x1F ට සමාන නඩුව, හැකි විකල්ප තුනෙන් එකක් දක්වයි.

අපි කේතය දිගටම විශ්ලේෂණය කරන්නෙමු. පැනීම් කිහිපයකට පසු අපි ස්වයං-පැහැදිලි නමක් සහිත ක්‍රමයක් තුළ අපව සොයා ගනිමු decryptBytesByKey.

මෙහිදී අපගේ ප්‍රතිචාරයෙන් තවත් බයිට් දෙකක් වෙන් කර ඇති අතර ඒවායින් තන්තුවක් ලබා ගනී. මේ ආකාරයෙන් පණිවිඩය විකේතනය කිරීමේ යතුර තෝරාගෙන ඇති බව පැහැදිලිය.

    private static byte[] decryptBytesByKey(byte[] bytes) {
byte[] v0 = null;
if(bytes != null) {
try {
if(bytes.length < EncryptHelper.PREFIX_BYTES_SIZE) {
}
else if(bytes.length == EncryptHelper.PREFIX_BYTES_SIZE) {
return v0;
}
else {
byte[] prefix = new byte[EncryptHelper.PREFIX_BYTES_SIZE];  // 2 байта
System.arraycopy(bytes, 0, prefix, 0, prefix.length);
String keyId = c.ayR().d(ByteBuffer.wrap(prefix).getShort()); // Выбор ключа
if(keyId == null) {
return v0;
}
else {
a v2 = EncryptHelper.ayL();
if(v2 == null) {
return v0;
}
else {
byte[] enrypted = new byte[bytes.length - EncryptHelper.PREFIX_BYTES_SIZE];
System.arraycopy(bytes, EncryptHelper.PREFIX_BYTES_SIZE, enrypted, 0, enrypted.length);
return v2.l(keyId, enrypted);
}
}
}
}
catch(SecException v7_1) {
EncryptHelper.handleDecryptException(((Throwable)v7_1), v7_1.getErrorCode());
return v0;
}
catch(Throwable v7) {
EncryptHelper.handleDecryptException(v7, 2);
return v0;
}
}
return v0;
}

ඉදිරිය දෙස බලන විට, මෙම අවස්ථාවෙහිදී අප තවමත් යතුරක් ලබා නොගන්නා නමුත් එහි "හඳුනාගැනීම" පමණක් බව අපි සටහන් කරමු. යතුර ලබා ගැනීම ටිකක් සංකීර්ණයි.

ඊළඟ ක්‍රමයේදී, පවතින ඒවාට තවත් පරාමිති දෙකක් එකතු කර ඒවායින් හතරක් සාදනු ලැබේ: මැජික් අංක 16, යතුරු හඳුනාගැනීම, සංකේතනය කළ දත්ත සහ තේරුම්ගත නොහැකි තන්තුවක් (අපගේ නඩුවේදී, හිස්).

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

සංක්‍රාන්ති මාලාවකින් පසු අපි ක්‍රමයට පැමිණෙමු staticBinarySafeDecryptNoB64 අතුරුමුහුණත com.alibaba.wireless.security.open.staticdataencrypt.IStaticDataEncryptComponent. මෙම අතුරුමුහුණත ක්රියාත්මක කරන ප්රධාන යෙදුම් කේතයේ පන්ති නොමැත. ගොනුවේ එවැනි පන්තියක් ඇත lib/armeabi-v7a/libsgmain.so, එය ඇත්ත වශයෙන්ම .සෝ නොවේ, නමුත් .ජරයකි. අප උනන්දු වන ක්‍රමය පහත පරිදි ක්‍රියාත්මක වේ:

package com.alibaba.wireless.security.a.i;
// ...
public class a implements IStaticDataEncryptComponent {
private ISecurityGuardPlugin a;
// ...
private byte[] a(int mode, int magicInt, int xzInt, String keyId, byte[] encrypted, String magicString) {
return this.a.getRouter().doCommand(10601, new Object[]{Integer.valueOf(mode), Integer.valueOf(magicInt), Integer.valueOf(xzInt), keyId, encrypted, magicString});
}
// ...
private byte[] b(int magicInt, String keyId, byte[] encrypted, String magicString) {
return this.a(2, magicInt, 0, keyId, encrypted, magicString);
}
// ...
public byte[] staticBinarySafeDecryptNoB64(int magicInt, String keyId, byte[] encrypted, String magicString) throws SecException {
if(keyId != null && keyId.length() > 0 && magicInt >= 0 && magicInt < 19 && encrypted != null && encrypted.length > 0) {
return this.b(magicInt, keyId, encrypted, magicString);
}
throw new SecException("", 301);
}
//...
}

මෙහිදී අපගේ පරාමිති ලැයිස්තුව තවත් පූර්ණ සංඛ්‍යා දෙකකින් අනුපූරක වේ: 2 සහ 0. විනිශ්චය කිරීම
සෑම දෙයක්ම, 2 ක්‍රමයේදී මෙන් විකේතනය වේ doFinal පද්ධති පන්තිය javax.crypto.Cipher. මේ සියල්ල 10601 අංකය සහිත නිශ්චිත රවුටරයකට මාරු කරනු ලැබේ - මෙය පෙනෙන පරිදි විධාන අංකය වේ.

ඊළඟ සංක්‍රාන්ති දාමයෙන් පසු අපට අතුරු මුහුණත ක්‍රියාත්මක කරන පන්තියක් හමු වේ IRouterComponent සහ ක්රමය 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);
}
}

ඒ වගේම පන්තිය JNIC පුස්තකාලය, දේශීය ක්‍රමය ප්‍රකාශ කර ඇත doCommandNative:

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

මෙයින් අදහස් කරන්නේ අපි දේශීය කේතයේ ක්‍රමයක් සොයා ගත යුතු බවයි doCommandNative. තවද විනෝදය ආරම්භ වන්නේ මෙතැනිනි.

යන්ත්‍ර කේතය අපැහැදිලි කිරීම

ගොනුවේ libsgmain.so (ඇත්ත වශයෙන්ම එය .jar වන අතර ඉහතින් ඇති සමහර සංකේතාංකන සම්බන්ධ අතුරුමුහුණත් ක්‍රියාත්මක කිරීම අපට හමු විය) එක් ස්වදේශීය පුස්තකාලයක් ඇත: libsgmainso-6.4.36.so. අපි එය IDA හි විවෘත කර දෝෂ සහිත සංවාද කොටු පොකුරක් ලබා ගනිමු. ගැටලුව වන්නේ අංශ ශීර්ෂ වගුව අවලංගු වීමයි. විශ්ලේෂණය සංකීර්ණ කිරීම සඳහා මෙය සිදු කරනු ලැබේ.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

නමුත් එය අවශ්ය නොවේ: ELF ගොනුවක් නිවැරදිව පැටවීමට සහ එය විශ්ලේෂණය කිරීමට, වැඩසටහන් ශීර්ෂ වගුව ප්රමාණවත් වේ. එමනිසා, අපි හුදෙක් කොටස් වගුව මකා දමමු, ශීර්ෂයේ අනුරූප ක්ෂේත්ර ශුන්ය කරන්න.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

IDA හි ගොනුව නැවත විවෘත කරන්න.

ජාවා අථත්‍ය යන්ත්‍රයට හරියටම දේශීය පුස්තකාලයේ ජාවා කේතයෙන් ස්වදේශික ලෙස ප්‍රකාශ කරන ලද ක්‍රමයක් ක්‍රියාත්මක කරන්නේ කොතැනද යන්න පැවසීමට ක්‍රම දෙකක් තිබේ. පළමුවැන්න නම් එයට විශේෂ නාමයක් ලබා දීමයි Java_package_name_ClassName_MethodName.

දෙවැන්න වන්නේ පුස්තකාලය පූරණය කිරීමේදී එය ලියාපදිංචි කිරීමයි (ක්‍රියාකාරීත්වය තුළ JNI_Onload)
කාර්යය ඇමතුමක් භාවිතා කරමින් ලියාපදිංචි ස්වදේශිකයන්.

අපගේ නඩුවේදී, අපි පළමු ක්රමය භාවිතා කරන්නේ නම්, නම පහත පරිදි විය යුතුය: Java_com_taobao_wireless_security_adapter_JNICLibrary_doCommandNative.

අපනයනය කරන ලද කාර්යයන් අතර එවැනි කාර්යයක් නොමැත, එයින් අදහස් වන්නේ ඔබ ඇමතුමක් සෙවිය යුතු බවයි ලියාපදිංචි ස්වදේශිකයන්.
අපි function එකට යමු JNI_Onload සහ අපි මෙම පින්තූරය දකිමු:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

මොකද මෙතන වෙන්නෙ? මුලින්ම බැලූ බැල්මට, ශ්‍රිතයේ ආරම්භය සහ අවසානය ARM ගෘහ නිර්මාණ ශිල්පය සඳහා සාමාන්‍ය වේ. තොගයේ පළමු උපදෙස් ශ්‍රිතය එහි ක්‍රියාකාරිත්වයේදී භාවිතා කරන රෙජිස්ටර් වල අන්තර්ගතය (මෙම අවස්ථාවේදී, R0, R1 සහ R2) මෙන්ම ශ්‍රිතයෙන් ආපසු එන ලිපිනය අඩංගු LR ලේඛනයේ අන්තර්ගතය ගබඩා කරයි. . අවසාන උපදෙස් මඟින් සුරකින ලද ලේඛන ප්‍රතිස්ථාපනය කරයි, සහ ආපසු එන ලිපිනය වහාම පරිගණක ලේඛනයේ තබා ඇත - එබැවින් ක්‍රියාකාරිත්වයෙන් ආපසු පැමිණේ. නමුත් ඔබ සමීපව බැලුවහොත්, අවසාන උපදෙස් තොගයේ ගබඩා කර ඇති ආපසු පැමිණීමේ ලිපිනය වෙනස් කරන බව ඔබට පෙනෙනු ඇත. පසුව එය කෙබඳු වේද යන්න ගණනය කරමු
කේතය ක්රියාත්මක කිරීම. නිශ්චිත ලිපිනයක් 1xB0 R130 වෙත පටවනු ලැබේ, එයින් 5 අඩු කරනු ලැබේ, පසුව එය R0 වෙත මාරු කර 0x10 එයට එකතු වේ. එය 0xB13B හැරෙනවා. මේ අනුව, IDA සිතන්නේ අවසාන උපදෙස් සාමාන්‍ය ශ්‍රිත ප්‍රතිලාභයක් බවයි, නමුත් ඇත්ත වශයෙන්ම එය 0xB13B ගණනය කළ ලිපිනයට පනිනවා.

ARM ප්‍රොසෙසරවල මාතයන් දෙකක් සහ උපදෙස් කට්ටල දෙකක් ඇති බව මෙහිදී සිහිපත් කිරීම වටී: ARM සහ Thumb. ලිපිනයෙහි අවම සැලකිය යුතු බිට් එක භාවිතා කරන්නේ කුමන උපදෙස් කට්ටලයක්ද යන්න ප්‍රොසෙසරයට කියයි. එනම්, ලිපිනය ඇත්ත වශයෙන්ම 0xB13A වන අතර, අවම වශයෙන් සැලකිය යුතු බිට් එකකින් Thumb මාදිලිය දක්වයි.

මෙම පුස්තකාලයේ එක් එක් කාර්යයේ ආරම්භයට සමාන "ඇඩප්ටරයක්" එකතු කර ඇත
කුණු කේතය. අපි ඒවා තවදුරටත් විස්තරාත්මකව වාසය නොකරමු - අපට මතකයි
සෑම කාර්යයකම පාහේ සැබෑ ආරම්භය තව ටිකක් ඈතින් ඇති බව.

කේතය පැහැදිලිවම 0xB13A වෙත නොපැමිණෙන බැවින්, කේතය මෙම ස්ථානයේ පිහිටා ඇති බව IDA විසින්ම හඳුනාගෙන නොමැත. එම හේතුව නිසාම, එය පුස්තකාලයේ ඇති බොහෝ කේතයන් කේතය ලෙස හඳුනා නොගන්නා අතර, විශ්ලේෂණය තරමක් අපහසු වේ. අපි IDA ට කියනවා කේතය මෙයයි, මෙය සිදු වන්නේ මෙයයි:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

වගුව පැහැදිලිවම 0xB144 න් ආරම්භ වේ. sub_494C හි ඇත්තේ කුමක්ද?

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

LR ලේඛනයේ මෙම ශ්‍රිතය ඇමතීමේදී, අපට කලින් සඳහන් කළ වගුවේ (0xB144) ලිපිනය ලැබේ. R0 හි - මෙම වගුවේ දර්ශකය. එනම්, අගය වගුවෙන් ගෙන, LR වෙත එකතු කර ප්රතිඵලය වේ
යා යුතු ලිපිනය. අපි එය ගණනය කිරීමට උත්සාහ කරමු: 0xB144 + [0xB144 + 8* 4] = 0xB144 + 0x120 = 0xB264. අපි ලැබුණු ලිපිනයට ගොස් වචනාර්ථයෙන් ප්‍රයෝජනවත් උපදෙස් කිහිපයක් දැක නැවත 0xB140 වෙත යන්න:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

දැන් වගුවේ සිට 0x20 දර්ශකය සමඟ ඕෆ්සෙට් හි සංක්රමණයක් සිදුවනු ඇත.

මේසයේ විශාලත්වය අනුව විනිශ්චය කිරීම, කේතයේ එවැනි සංක්රමණයන් බොහොමයක් ඇත. ලිපින අතින් ගණනය නොකර කෙසේ හෝ මෙය සමඟ ස්වයංක්‍රීයව කටයුතු කළ හැකිද යන ප්‍රශ්නය පැන නගී. ස්ක්‍රිප්ට් සහ IDA හි කේත පැච් කිරීමේ හැකියාව අපගේ ආධාරයට පැමිණේ:

def put_unconditional_branch(source, destination):
offset = (destination - source - 4) >> 1
if offset > 2097151 or offset < -2097152:
raise RuntimeError("Invalid offset")
if offset > 1023 or offset < -1024:
instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
instruction2 = 0xb800 | (offset & 0x7ff)
patch_word(source, instruction1)
patch_word(source + 2, instruction2)
else:
instruction = 0xe000 | (offset & 0x7ff)
patch_word(source, instruction)
ea = here()
if get_wide_word(ea) == 0xb503: #PUSH {R0,R1,LR}
ea1 = ea + 2
if get_wide_word(ea1) == 0xbf00: #NOP
ea1 += 2
if get_operand_type(ea1, 0) == 1 and get_operand_value(ea1, 0) == 0 and get_operand_type(ea1, 1) == 2:
index = get_wide_dword(get_operand_value(ea1, 1))
print "index =", hex(index)
ea1 += 2
if get_operand_type(ea1, 0) == 7:
table = get_operand_value(ea1, 0) + 4
elif get_operand_type(ea1, 1) == 2:
table = get_operand_value(ea1, 1) + 4
else:
print "Wrong operand type on", hex(ea1), "-", get_operand_type(ea1, 0), get_operand_type(ea1, 1)
table = None
if table is None:
print "Unable to find table"
else:
print "table =", hex(table)
offset = get_wide_dword(table + (index << 2))
put_unconditional_branch(ea, table + offset)
else:
print "Unknown code", get_operand_type(ea1, 0), get_operand_value(ea1, 0), get_operand_type(ea1, 1) == 2
else:
print "Unable to detect first instruction"

කර්සරය 0xB26A පේළියේ තබා, ස්ක්‍රිප්ට් ධාවනය කර 0xB4B0 වෙත සංක්‍රමණය බලන්න:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

IDA නැවතත් මෙම ප්‍රදේශය කේතයක් ලෙස හඳුනා ගත්තේ නැත. අපි ඇයට උදව් කරන අතර එහි තවත් නිර්මාණයක් දකිමු:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

BLX ට පසු ඇති උපදෙස් එතරම් තේරුමක් නැති බව පෙනේ, එය යම් ආකාරයක විස්ථාපනයක් වැනි ය. අපි sub_4964 දෙස බලමු:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ඇත්ත වශයෙන්ම, මෙහි dword එකක් LR හි ඇති ලිපිනයට ගෙන, මෙම ලිපිනයට එකතු කරනු ලැබේ, ඉන්පසු ලැබෙන ලිපිනයේ අගය ගෙන තොගය මත තබයි. තවද, LR වෙත 4 එකතු කරන අතර එමඟින් ශ්‍රිතයෙන් ආපසු පැමිණි පසු, මෙම ඕෆ්සෙට්ම මඟ හැරේ. ඉන් පසුව POP {R1} විධානය අට්ටියෙන් ලැබෙන අගය ලබා ගනී. ඔබ 0xB4BA + 0xEA = 0xB5A4 ලිපිනයෙහි පිහිටා ඇති දේ දෙස බැලුවහොත්, ලිපින වගුවකට සමාන යමක් ඔබට පෙනෙනු ඇත:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

මෙම සැලසුම ඇලවීම සඳහා, ඔබට කේතයෙන් පරාමිති දෙකක් ලබා ගැනීමට අවශ්ය වනු ඇත: ඕෆ්සෙට් සහ ඔබට ප්රතිඵලය තැබීමට අවශ්ය ලියාපදිංචි අංකය. හැකි සෑම ලියාපදිංචියක් සඳහාම, ඔබට කලින් කේතයක් සකස් කිරීමට සිදුවනු ඇත.

patches = {}
patches[0] = (0x00, 0xbf, 0x01, 0x48, 0x00, 0x68, 0x02, 0xe0)
patches[1] = (0x00, 0xbf, 0x01, 0x49, 0x09, 0x68, 0x02, 0xe0)
patches[2] = (0x00, 0xbf, 0x01, 0x4a, 0x12, 0x68, 0x02, 0xe0)
patches[3] = (0x00, 0xbf, 0x01, 0x4b, 0x1b, 0x68, 0x02, 0xe0)
patches[4] = (0x00, 0xbf, 0x01, 0x4c, 0x24, 0x68, 0x02, 0xe0)
patches[5] = (0x00, 0xbf, 0x01, 0x4d, 0x2d, 0x68, 0x02, 0xe0)
patches[8] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0x80, 0xd8, 0xf8, 0x00, 0x80, 0x01, 0xe0)
patches[9] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0x90, 0xd9, 0xf8, 0x00, 0x90, 0x01, 0xe0)
patches[10] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0xa0, 0xda, 0xf8, 0x00, 0xa0, 0x01, 0xe0)
patches[11] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0xb0, 0xdb, 0xf8, 0x00, 0xb0, 0x01, 0xe0)
ea = here()
if (get_wide_word(ea) == 0xb082 #SUB SP, SP, #8
and get_wide_word(ea + 2) == 0xb503): #PUSH {R0,R1,LR}
if get_operand_type(ea + 4, 0) == 7:
pop = get_bytes(ea + 12, 4, 0)
if pop[1] == 'xbc':
register = -1
r = get_wide_byte(ea + 12)
for i in range(8):
if r == (1 << i):
register = i
break
if register == -1:
print "Unable to detect register"
else:
address = get_wide_dword(ea + 8) + ea + 8
for b in patches[register]:
patch_byte(ea, b)
ea += 1
if ea % 4 != 0:
ea += 2
patch_dword(ea, address)
elif pop[:3] == 'x5dxf8x04':
register = ord(pop[3]) >> 4
if register in patches:
address = get_wide_dword(ea + 8) + ea + 8
for b in patches[register]:
patch_byte(ea, b)
ea += 1
patch_dword(ea, address)
else:
print "POP instruction not found"
else:
print "Wrong operand type on +4:", get_operand_type(ea + 4, 0)
else:
print "Unable to detect first instructions"

අපි ප්‍රතිස්ථාපනය කිරීමට අවශ්‍ය ව්‍යුහයේ ආරම්භයේ කර්සරය තබා - 0xB4B2 - සහ ස්ක්‍රිප්ට් ධාවනය කරන්න:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

දැනටමත් සඳහන් කර ඇති ව්‍යුහයන්ට අමතරව, කේතයේ පහත සඳහන් දෑ ද අඩංගු වේ:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

පෙර අවස්ථාවේ දී මෙන්, BLX උපදෙස් වලින් පසුව ඕෆ්සෙට් එකක් ඇත:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

අපි ඕෆ්සෙට් එක LR එකෙන් address එකට අරන් LR එකට add කරලා එතනට යනවා. 0x72044 + 0xC = 0x72050. මෙම නිර්මාණය සඳහා පිටපත ඉතා සරල ය:

def put_unconditional_branch(source, destination):
offset = (destination - source - 4) >> 1
if offset > 2097151 or offset < -2097152:
raise RuntimeError("Invalid offset")
if offset > 1023 or offset < -1024:
instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
instruction2 = 0xb800 | (offset & 0x7ff)
patch_word(source, instruction1)
patch_word(source + 2, instruction2)
else:
instruction = 0xe000 | (offset & 0x7ff)
patch_word(source, instruction)
ea = here()
if get_wide_word(ea) == 0xb503: #PUSH {R0,R1,LR}
ea1 = ea + 6
if get_wide_word(ea + 2) == 0xbf00: #NOP
ea1 += 2
offset = get_wide_dword(ea1)
put_unconditional_branch(ea, (ea1 + offset) & 0xffffffff)
else:
print "Unable to detect first instruction"

ස්ක්‍රිප්ට් ක්‍රියාත්මක කිරීමේ ප්‍රතිඵල:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ශ්‍රිතයේ සෑම දෙයක්ම පැච් කළ පසු, ඔබට IDA එහි සැබෑ ආරම්භයට යොමු කළ හැක. එය සියලුම ක්‍රියාකාරී කේතයන් එකට එකතු කරන අතර, එය HexRays භාවිතයෙන් විසංයෝජනය කළ හැක.

තන්තු විකේතනය කිරීම

පුස්තකාලයේ ඇති යන්ත්‍ර කේතය අපැහැදිලි කිරීම සම්බන්ධයෙන් කටයුතු කිරීමට අපි ඉගෙන ගෙන ඇත්තෙමු libsgmainso-6.4.36.so UC බ්‍රව්සරයෙන් සහ ක්‍රියාකාරී කේතය ලැබුණි JNI_Onload.

int __fastcall real_JNI_OnLoad(JavaVM *vm)
{
int result; // r0
jclass clazz; // r0 MAPDST
int v4; // r0
JNIEnv *env; // r4
int v6; // [sp-40h] [bp-5Ch]
int v7; // [sp+Ch] [bp-10h]
v7 = *(_DWORD *)off_8AC00;
if ( !vm )
goto LABEL_39;
sub_7C4F4();
env = (JNIEnv *)sub_7C5B0(0);
if ( !env )
goto LABEL_39;
v4 = sub_72CCC();
sub_73634(v4);
sub_73E24(&unk_83EA6, &v6, 49);
clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);
if ( clazz
&& (sub_9EE4(),
sub_71D68(env),
sub_E7DC(env) >= 0
&& sub_69D68(env) >= 0
&& sub_197B4(env, clazz) >= 0
&& sub_E240(env, clazz) >= 0
&& sub_B8B0(env, clazz) >= 0
&& sub_5F0F4(env, clazz) >= 0
&& sub_70640(env, clazz) >= 0
&& sub_11F3C(env) >= 0
&& sub_21C3C(env, clazz) >= 0
&& sub_2148C(env, clazz) >= 0
&& sub_210E0(env, clazz) >= 0
&& sub_41B58(env, clazz) >= 0
&& sub_27920(env, clazz) >= 0
&& sub_293E8(env, clazz) >= 0
&& sub_208F4(env, clazz) >= 0) )
{
result = (sub_B7B0(env, clazz) >> 31) | 0x10004;
}
else
{
LABEL_39:
result = -1;
}
return result;
}

පහත රේඛා දෙස සමීපව බලමු:

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

ක්‍රියාකාරීත්වයේ උප_73E24 පන්තියේ නම පැහැදිලිව විකේතනය වෙමින් පවතී. මෙම ශ්‍රිතයේ පරාමිති ලෙස, සංකේතනය කරන ලද දත්ත වලට සමාන දත්ත වෙත දර්ශකයක්, යම් බෆරයක් සහ අංකයක් සම්මත වේ. පැහැදිලිවම, ශ්‍රිතය ඇමතීමෙන් පසු, එය ශ්‍රිතයට යවන බැවින්, බෆරයේ විකේතනය කළ රේඛාවක් පවතිනු ඇත. FindClass, පන්තියේ නම දෙවන පරාමිතිය ලෙස ගනී. එබැවින්, අංකය යනු බෆරයේ විශාලත්වය හෝ රේඛාවේ දිග වේ. අපි පන්තියේ නම විකේතනය කිරීමට උත්සාහ කරමු, එය අප නිවැරදි දිශාවට යනවාද යන්න අපට පැවසිය යුතුය. සිදු වන්නේ කුමක්ද යන්න දෙස සමීපව බලමු උප_73E24.

int __fastcall sub_73E56(unsigned __int8 *in, unsigned __int8 *out, size_t size)
{
int v4; // r6
int v7; // r11
int v8; // r9
int v9; // r4
size_t v10; // r5
int v11; // r0
struc_1 v13; // [sp+0h] [bp-30h]
int v14; // [sp+1Ch] [bp-14h]
int v15; // [sp+20h] [bp-10h]
v4 = 0;
v15 = *(_DWORD *)off_8AC00;
v14 = 0;
v7 = sub_7AF78(17);
v8 = sub_7AF78(size);
if ( !v7 )
{
v9 = 0;
goto LABEL_12;
}
(*(void (__fastcall **)(int, const char *, int))(v7 + 12))(v7, "DcO/lcK+h?m3c*q@", 16);
if ( !v8 )
{
LABEL_9:
v4 = 0;
goto LABEL_10;
}
v4 = 0;
if ( !in )
{
LABEL_10:
v9 = 0;
goto LABEL_11;
}
v9 = 0;
if ( out )
{
memset(out, 0, size);
v10 = size - 1;
(*(void (__fastcall **)(int, unsigned __int8 *, size_t))(v8 + 12))(v8, in, v10);
memset(&v13, 0, 0x14u);
v13.field_4 = 3;
v13.field_10 = v7;
v13.field_14 = v8;
v11 = sub_6115C(&v13, &v14);
v9 = v11;
if ( v11 )
{
if ( *(_DWORD *)(v11 + 4) == v10 )
{
qmemcpy(out, *(const void **)v11, v10);
v4 = *(_DWORD *)(v9 + 4);
}
else
{
v4 = 0;
}
goto LABEL_11;
}
goto LABEL_9;
}
LABEL_11:
sub_7B148(v7);
LABEL_12:
if ( v8 )
sub_7B148(v8);
if ( v9 )
sub_7B148(v9);
return v4;
}

උත්සවය උප_7AF78 නියම කරන ලද ප්‍රමාණයේ බයිට් අරා සඳහා කන්ටේනරයක උදාහරණයක් නිර්මාණය කරයි (අපි මෙම බහාලුම්වල විස්තරාත්මකව වාසය නොකරමු). මෙන්න එවැනි බහාලුම් දෙකක් නිර්මාණය කර ඇත: එක් රේඛාවක් අඩංගු වේ "DcO/lcK+h?m3c*q@" (මෙය යතුරක් බව අනුමාන කිරීම පහසුය), අනෙක සංකේතාත්මක දත්ත අඩංගු වේ. ඊළඟට, වස්තු දෙකම යම් ව්‍යුහයක් තුළ තබා ඇති අතර එය ශ්‍රිතයට යවනු ලැබේ උප_6115C. අපි මේ ව්‍යුහයේ 3 අගය සහිත ක්ෂේත්‍රයක් සලකුණු කරමු.අපි බලමු මේ ව්‍යුහයට මොකද වෙන්නේ කියලා.

int __fastcall sub_611B4(struc_1 *a1, _DWORD *a2)
{
int v3; // lr
unsigned int v4; // r1
int v5; // r0
int v6; // r1
int result; // r0
int v8; // r0
*a2 = 820000;
if ( a1 )
{
v3 = a1->field_14;
if ( v3 )
{
v4 = a1->field_4;
if ( v4 < 0x19 )
{
switch ( v4 )
{
case 0u:
v8 = sub_6419C(a1->field_0, a1->field_10, v3);
goto LABEL_17;
case 3u:
v8 = sub_6364C(a1->field_0, a1->field_10, v3);
goto LABEL_17;
case 0x10u:
case 0x11u:
case 0x12u:
v8 = sub_612F4(
a1->field_0,
v4,
*(_QWORD *)&a1->field_8,
*(_QWORD *)&a1->field_8 >> 32,
a1->field_10,
v3,
a2);
goto LABEL_17;
case 0x14u:
v8 = sub_63A28(a1->field_0, v3);
goto LABEL_17;
case 0x15u:
sub_61A60(a1->field_0, v3, a2);
return result;
case 0x16u:
v8 = sub_62440(a1->field_14);
goto LABEL_17;
case 0x17u:
v8 = sub_6226C(a1->field_10, v3);
goto LABEL_17;
case 0x18u:
v8 = sub_63530(a1->field_14);
LABEL_17:
v6 = 0;
if ( v8 )
{
*a2 = 0;
v6 = v8;
}
return v6;
default:
LOWORD(v5) = 28032;
goto LABEL_5;
}
}
}
}
LOWORD(v5) = -27504;
LABEL_5:
HIWORD(v5) = 13;
v6 = 0;
*a2 = v5;
return v6;
}

ස්විච් පරාමිතිය යනු ව්‍යුහ ක්ෂේත්‍රයක් වන අතර එය කලින් අගය 3 ලබා දී ඇත. අවස්ථාව 3 බලන්න: ශ්‍රිතයට උප_6364C පෙර ශ්‍රිතයේ, එනම් යතුර සහ සංකේතාංකනය කරන ලද දත්තවල එකතු කරන ලද ව්‍යුහයෙන් පරාමිති සම්මත වේ. ඔබ සමීපව බැලුවහොත් උප_6364C, ඔබට එහි RC4 ඇල්ගොරිතම හඳුනාගත හැකිය.

අපට ඇල්ගොරිතමයක් සහ යතුරක් තිබේ. පන්තියේ නම විකේතනය කිරීමට උත්සාහ කරමු. සිදු වූ දේ මෙන්න: com/taobao/wireless/security/adapter/JNICLibrary. මහා! අපි හරි පාරේ.

විධාන ගස

දැන් අපි අභියෝගයක් සොයා ගත යුතුයි ලියාපදිංචි ස්වදේශිකයන්, එය අපව ශ්‍රිතයට යොමු කරයි doCommandNative. සිට කැඳවනු ලබන කාර්යයන් දෙස බලමු JNI_Onload, සහ අපි එය සොයා ගනිමු උප_B7B0:

int __fastcall sub_B7F6(JNIEnv *env, jclass clazz)
{
char signature[41]; // [sp+7h] [bp-55h]
char name[16]; // [sp+30h] [bp-2Ch]
JNINativeMethod method; // [sp+40h] [bp-1Ch]
int v8; // [sp+4Ch] [bp-10h]
v8 = *(_DWORD *)off_8AC00;
decryptString((unsigned __int8 *)&unk_83ED9, (unsigned __int8 *)name, 0x10u);// doCommandNative
decryptString((unsigned __int8 *)&unk_83EEA, (unsigned __int8 *)signature, 0x29u);// (I[Ljava/lang/Object;)Ljava/lang/Object;
method.name = name;
method.signature = signature;
method.fnPtr = sub_B69C;
return ((int (__fastcall *)(JNIEnv *, jclass, JNINativeMethod *, int))(*env)->RegisterNatives)(env, clazz, &method, 1) >> 31;
}

ඇත්ත වශයෙන්ම, නම සහිත දේශීය ක්‍රමයක් මෙහි ලියාපදිංචි කර ඇත doCommandNative. දැන් අපි ඔහුගේ ලිපිනය දන්නවා. බලමු මෙයා මොකද කරන්නේ කියලා.

int __fastcall doCommandNative(JNIEnv *env, jobject obj, int command, jarray args)
{
int v5; // r5
struc_2 *a5; // r6
int v9; // r1
int v11; // [sp+Ch] [bp-14h]
int v12; // [sp+10h] [bp-10h]
v5 = 0;
v12 = *(_DWORD *)off_8AC00;
v11 = 0;
a5 = (struc_2 *)malloc(0x14u);
if ( a5 )
{
a5->field_0 = 0;
a5->field_4 = 0;
a5->field_8 = 0;
a5->field_C = 0;
v9 = command % 10000 / 100;
a5->field_0 = command / 10000;
a5->field_4 = v9;
a5->field_8 = command % 100;
a5->field_C = env;
a5->field_10 = args;
v5 = sub_9D60(command / 10000, v9, command % 100, 1, (int)a5, &v11);
}
free(a5);
if ( !v5 && v11 )
sub_7CF34(env, v11, &byte_83ED7);
return v5;
}

සංවර්ධකයින් ස්වදේශීය පුස්තකාලයට මාරු කිරීමට තීරණය කළ සියලුම කාර්යයන් සඳහා පිවිසුම් ස්ථානය මෙහි ඇති බව නමෙන් ඔබට අනුමාන කළ හැකිය. අපි ශ්‍රිත අංක 10601 ගැන උනන්දු වෙමු.

විධාන අංකය අංක තුනක් නිපදවන බව කේතයෙන් ඔබට දැක ගත හැකිය: විධානය/10000, විධානය% 10000/100 и විධානය% 10, එනම්, අපගේ නඩුවේදී, 1, 6 සහ 1. මෙම අංක තුන, මෙන්ම දර්ශකයක් JNIEnv සහ ශ්‍රිතයට ලබා දුන් තර්ක ව්‍යුහයකට එකතු කර සම්මත කර ඇත. ලබාගත් අංක තුන භාවිතා කරමින් (ඒවා N1, N2 සහ N3 සඳහන් කරමු), විධාන ගසක් ඉදිකර ඇත.

මේ වගේ දෙයක්:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ගස ගතිකව පුරවා ඇත JNI_Onload.
අංක තුනක් ගසේ මාර්ගය සංකේත කරයි. ගසේ සෑම පත්‍රයකම අනුරූප ශ්‍රිතයේ පොඩ් ලිපිනය අඩංගු වේ. යතුර මාපිය නෝඩයේ ඇත. භාවිතා කරන සියලුම ව්‍යුහයන් ඔබ තේරුම් ගන්නේ නම්, අපට අවශ්‍ය කාර්යය ගසට එකතු කරන කේතයේ ස්ථානය සොයා ගැනීම අපහසු නැත (දැනටමත් තරමක් විශාල ලිපියක් පුම්බා නොයන ලෙස අපි ඒවා විස්තර නොකරමු).

වඩාත් අපැහැදිලි

ගමනාගමනය විකේතනය කළ යුතු ශ්‍රිතයේ ලිපිනය අපට ලැබුණි: 0x5F1AC. නමුත් ප්‍රීති වීමට ඉක්මන් වැඩියි: UC බ්‍රව්සරයේ සංවර්ධකයින් අප වෙනුවෙන් තවත් පුදුමයක් සූදානම් කර ඇත.

Java code එකේ හදපු array එකෙන් parameters ලැබුනට පස්සේ අපිට ලැබෙනවා
0x4D070 ලිපිනයෙහි ශ්‍රිතයට. තවද මෙහි තවත් ආකාරයේ කේත අපැහැදිලි කිරීමක් අපව බලා සිටියි.

අපි R7 සහ R4 හි දර්ශක දෙකක් තබමු:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

අපි පළමු දර්ශකය R11 වෙත මාරු කරමු:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

වගුවකින් ලිපිනයක් ලබා ගැනීමට, දර්ශකයක් භාවිතා කරන්න:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

පළමු ලිපිනයට ගිය පසු, දෙවන දර්ශකය භාවිතා කරනු ලැබේ, එය R4 හි ඇත. වගුවේ මූලද්රව්ය 230 ක් ඇත.

ඒකට මොනවා කරන්නද? මෙය ස්විචයක් බව ඔබට IDA හට පැවසිය හැක: සංස්කරණය කරන්න -> වෙනත් -> ස්විච් මෝඩිය නියම කරන්න.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ප්රතිඵලයක් ලෙස කේතය භයානකයි. එහෙත්, එහි වනාන්තරය හරහා ගමන් කරමින්, දැනටමත් අපට හුරුපුරුදු කාර්යයකට ඇමතුමක් ඔබට දැක ගත හැකිය උප_6115C:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

3 නඩුවේ RC4 ඇල්ගොරිතම භාවිතයෙන් විකේතනයක් ඇති ස්විචයක් තිබුණි. තවද මෙම අවස්ථාවෙහිදී, ශ්‍රිතයට යවන ලද ව්‍යුහය පුරවනු ලබන්නේ සම්මත කරන ලද පරාමිති වලින්ය doCommandNative. අපි එහි තිබූ දේ මතක තබා ගනිමු magicInt අගය සමඟ 16. අපි අදාළ අවස්ථාව දෙස බලමු - සහ සංක්‍රාන්ති කිහිපයකට පසු ඇල්ගොරිතම හඳුනාගත හැකි කේතය අපට හමු වේ.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

මෙය AES වේ!

ඇල්ගොරිතම පවතී, ඉතිරිව ඇත්තේ එහි පරාමිතීන් ලබා ගැනීම පමණි: මාදිලිය, යතුර සහ, සමහර විට, ආරම්භක දෛශිකය (එහි පැවැත්ම AES ඇල්ගොරිතමයේ මෙහෙයුම් ආකාරය මත රඳා පවතී). කාර්යය ඇමතුමට පෙර ඔවුන් සමඟ ව්යුහය කොහේ හරි පිහිටුවා ගත යුතුය උප_6115C, නමුත් කේතයේ මෙම කොටස විශේෂයෙන් හොඳින් අපැහැදිලි වේ, එබැවින් විකේතන ශ්‍රිතයේ සියලුම පරාමිතීන් ගොනුවකට දමනු ලබන පරිදි කේතය පැච් කිරීමට අදහස පැන නගී.

පැච්

එකලස් කිරීමේ භාෂාවෙන් සියලුම පැච් කේතය අතින් ලිවීම නොකිරීමට, ඔබට ඇන්ඩ්‍රොයිඩ් ස්ටුඩියෝ දියත් කළ හැකිය, අපගේ විකේතන ශ්‍රිතයට සමාන ආදාන පරාමිති ලබා ගන්නා ශ්‍රිතයක් එහි ලියන්න සහ ගොනුවකට ලියන්න, ඉන්පසු සම්පාදකය විසින් කරන කේතය පිටපත් කර ඇලවිය හැකිය. උත්පාදනය කරන්න.

UC Browser කණ්ඩායමේ අපේ මිතුරන්ද කේතය එකතු කිරීමේ පහසුව ගැන සැලකිලිමත් විය. සෑම කාර්යයකම ආරම්භයේදීම අප සතුව කසළ කේතයක් ඇති බව මතක තබා ගනිමු, එය පහසුවෙන් වෙනත් ඕනෑම දෙයක් සමඟ ප්‍රතිස්ථාපනය කළ හැකිය. ඉතා පහසුයි 🙂 කෙසේ වෙතත්, ඉලක්ක ශ්‍රිතයේ ආරම්භයේදී සියලුම පරාමිති ගොනුවකට සුරකින කේතය සඳහා ප්‍රමාණවත් ඉඩක් නොමැත. මට එය කොටස් වලට බෙදීමට සහ අසල්වැසි කාර්යයන්ගෙන් කුණු කුට්ටි භාවිතා කිරීමට සිදු විය. මුළු කොටස් හතරක් තිබුණා.

පළමු කොටස:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ARM ගෘහ නිර්මාණ ශිල්පය තුළ, පළමු ශ්‍රිත පරාමිති හතර R0-R3 රෙජිස්ටර් හරහා යවනු ලැබේ, ඉතිරිය තිබේ නම්, තොගය හරහා යවනු ලැබේ. LR ලේඛනය ආපසු පැමිණීමේ ලිපිනය දරයි. මේ සියල්ල සුරැකිය යුතු අතර, අපි එහි පරාමිතීන් ඉවත් කිරීමෙන් පසුව කාර්යය ක්රියා කළ හැකිය. ක්‍රියාවලියේදී අප භාවිතා කරන සියලුම රෙජිස්ටර් සුරැකීමටද අපට අවශ්‍ය වේ, එබැවින් අපි PUSH.W {R0-R10,LR} කරන්නෙමු. R7 වලදී අපට stack එක හරහා ශ්‍රිතයට යවන ලද පරාමිති ලැයිස්තුවේ ලිපිනය ලැබේ.

කාර්යය භාවිතා කිරීම fopen අපි ගොනුව විවෘත කරමු /data/local/tmp/aes "ab" ආකාරයෙන්
එනම් එකතු කිරීම සඳහා. R0 හි අපි ගොනු නාමයේ ලිපිනය පූරණය කරමු, R1 හි - මාදිලිය දැක්වෙන රේඛාවේ ලිපිනය. මෙහි කුණු කේතය අවසන් වේ, එබැවින් අපි ඊළඟ කාර්යයට යමු. එය දිගටම ක්‍රියා කිරීම සඳහා, අපි මුලදී ශ්‍රිතයේ සැබෑ කේතයට සංක්‍රමණය කර, කුණු කසළ මඟ හරිමින්, කසළ වෙනුවට අපි පැච් එක අඛණ්ඩව එකතු කරමු.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ඇමතීම fopen.

ශ්රිතයේ පළමු පරාමිති තුන AES වර්ගය ඇත int. අපි මුලදි Stack එකට Registers save කරපු නිසා අපිට Function එක සරලව pass කරන්න පුළුවන් fwrite තොගයේ ඔවුන්ගේ ලිපින.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

ඊළඟට අපට දත්ත ප්‍රමාණය අඩංගු ව්‍යුහ තුනක් සහ යතුර සඳහා දත්ත වෙත දර්ශකයක්, ආරම්භක දෛශිකය සහ සංකේතනය කළ දත්ත ඇත.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

අවසානයේදී, ගොනුව වසා, රෙජිස්ටර් නැවත යථා තත්ත්වයට පත් කර පාලනය සැබෑ කාර්යයට මාරු කරන්න AES.

අපි පැච් කරන ලද පුස්තකාලයක් සහිත APK එකක් එකතු කර, එය අත්සන් කර, එය උපාංගයට/ඉමුලේටරයට උඩුගත කර, එය දියත් කරන්නෙමු. අපගේ ඩම්ප් නිර්මාණය වෙමින් පවතින බවත්, එහි බොහෝ දත්ත ලියා ඇති බවත් අපට පෙනේ. බ්‍රවුසරය ගමනාගමනය සඳහා පමණක් සංකේතනය භාවිතා කරයි, සහ සියලු සංකේතනය ප්‍රශ්නගත කාර්යය හරහා යයි. නමුත් කිසියම් හේතුවක් නිසා අවශ්ය දත්ත නොමැති අතර, අවශ්ය ඉල්ලීම තදබදය තුළ නොපෙනේ. UC බ්‍රව්සරය අවශ්‍ය ඉල්ලීම සිදු කරන තෙක් බලා නොසිටීම සඳහා, කලින් ලැබුණු සේවාදායකයෙන් සංකේතනය කළ ප්‍රතිචාරය ලබාගෙන නැවත යෙදුම පැච් කරමු: ප්‍රධාන ක්‍රියාකාරකමේ onCreate වෙත විකේතනය එක් කරන්න.

    const/16 v1, 0x62
new-array v1, v1, [B
fill-array-data v1, :encrypted_data
const/16 v0, 0x1f
invoke-static {v0, v1}, Lcom/uc/browser/core/d/c/g;->j(I[B)[B
move-result-object v1
array-length v2, v1
invoke-static {v2}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;
move-result-object v2
const-string v0, "ololo"
invoke-static {v0, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

අපි එකලස් කිරීම, අත්සන් කිරීම, ස්ථාපනය කිරීම, දියත් කිරීම. ක්‍රමය ශුන්‍ය ලෙස ආපසු ලබා දුන් නිසා අපට NullPointerException එකක් ලැබේ.

කේතය තවදුරටත් විශ්ලේෂණය කිරීමේදී, රසවත් රේඛා විකේතනය කරන ශ්‍රිතයක් සොයා ගන්නා ලදී: "META-INF/" සහ ".RSA". යෙදුම එහි සහතිකය සත්‍යාපනය කරන බවක් පෙනේ. නැතහොත් එයින් යතුරු පවා ජනනය කරයි. සහතිකය සමඟ සිදු වන දේ සමඟ කටයුතු කිරීමට මට ඇත්තටම අවශ්‍ය නැත, එබැවින් අපි එය නිවැරදි සහතිකය ලිස්සා දමමු. "META-INF/" වෙනුවට "BLABLINF/" ලැබෙන පරිදි, APK හි එම නම සහිත ෆෝල්ඩරයක් සාදා එහි ලේනු බ්‍රවුසර සහතිකය එක් කරන්න.

අපි එකලස් කිරීම, අත්සන් කිරීම, ස්ථාපනය කිරීම, දියත් කිරීම. බිංගෝ! යතුර අප සතුව ඇත!

MitM

යතුරට සමාන යතුරක් සහ ආරම්භක දෛශිකයක් අපට ලැබුණි. CBC මාදිලියේ සේවාදායක ප්‍රතිචාරය විකේතනය කිරීමට උත්සාහ කරමු.

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

අපි සංරක්ෂිත URL එක දකිමු, MD5 ට සමාන දෙයක්, "extract_unzipsize" සහ අංකයක්. අපි පරීක්ෂා කරමු: ලේඛනාගාරයේ MD5 එක සමාන වේ, ඇසුරුම් නොකළ පුස්තකාලයේ ප්රමාණය සමාන වේ. අපි මේ library එක patch කරලා browser එකට දෙන්නයි හදන්නේ. අපගේ පැච් කළ පුස්තකාලය පූරණය වී ඇති බව පෙන්වීමට, අපි “PWNED!” යන පාඨය සහිත කෙටි පණිවුඩයක් සෑදීමේ අභිප්‍රාය දියත් කරන්නෙමු. අපි සේවාදායකයෙන් ප්‍රතිචාර දෙකක් ප්‍රතිස්ථාපනය කරන්නෙමු: puds.ucweb.com/upgrade/index.xhtml සහ සංරක්ෂිතය බාගත කිරීමට. මුලින්ම අපි MD5 ආදේශ කරමු (අසුරන ලද පසු ප්රමාණය වෙනස් නොවේ), දෙවනුව අපි පැච් කළ පුස්තකාලය සමඟ සංරක්ෂිතය ලබා දෙන්නෙමු.

බ්රවුසරය සංරක්ෂිතය කිහිප වතාවක් බාගත කිරීමට උත්සාහ කරයි, පසුව එය දෝෂයක් ලබා දෙයි. පෙනෙන විදිහට දෙයක්
ඔහු කැමති නෑ. මෙම අඳුරු ආකෘතිය විශ්ලේෂණය කිරීමේ ප්‍රති result ලයක් ලෙස, සේවාදායකයා ලේඛනාගාරයේ ප්‍රමාණය ද සම්ප්‍රේෂණය කරන බව පෙනී ගියේය:

UC බ්‍රව්සරයේ දුර්වලතා සොයමින්

එය LEB128 හි සංකේතනය කර ඇත. පැච් එකෙන් පසු, පුස්තකාලය සහිත ලේඛනාගාරයේ ප්‍රමාණය ටිකක් වෙනස් විය, එබැවින් බ්‍රව්සරය සංරක්ෂිතය වංක ලෙස බාගත කර ඇති බව සලකන අතර උත්සාහ කිහිපයකින් පසුව එය දෝෂයක් ඇති කළේය.

අපි ලේඛනාගාරයේ ප්රමාණය සකස් කරමු ... සහ - ජයග්රහණය! 🙂 ප්‍රතිඵලය වීඩියෝවේ ඇත.

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

ප්රතිවිපාක සහ සංවර්ධක ප්රතික්රියාව

එලෙසම, හැකර්වරුන්ට අනිෂ්ට පුස්තකාල බෙදා හැරීමට සහ ක්‍රියාත්මක කිරීමට UC බ්‍රව්සරයේ අනාරක්ෂිත විශේෂාංගය භාවිතා කළ හැකිය. මෙම පුස්තකාල බ්‍රවුසරයේ සන්දර්භය තුළ ක්‍රියා කරනු ඇත, එබැවින් ඔවුන්ට එහි සියලුම පද්ධති අවසර ලැබෙනු ඇත. එහි ප්රතිඵලයක් වශයෙන්, phishing windows ප්රදර්ශනය කිරීමේ හැකියාව මෙන්ම, දත්ත ගබඩාවේ ගබඩා කර ඇති පිවිසුම්, මුරපද සහ කුකීස් ඇතුළු තැඹිලි පැහැති චීන ලේනුන්ගේ වැඩ කරන ගොනු වෙත ප්රවේශය.

අපි UC බ්‍රව්සරයේ සංවර්ධකයින් අමතා අප සොයාගත් ගැටලුව පිළිබඳව ඔවුන්ව දැනුවත් කළෙමු, අවදානම සහ එහි භයානකකම පෙන්වා දීමට උත්සාහ කළ නමුත් ඔවුන් අප සමඟ කිසිවක් සාකච්ඡා කළේ නැත. මේ අතර, බ්‍රවුසරය පැහැදිලිව පෙනෙන පරිදි එහි භයානක අංගය දිගටම පෙන්වීය. නමුත් අපි අවදානම පිළිබඳ විස්තර හෙළි කළ පසු, එය පෙර මෙන් නොසලකා හැරීමට තවදුරටත් නොහැකි විය. මාර්තු 27 විය
UC බ්‍රව්සරයේ නව අනුවාදයක් 12.10.9.1193 නිකුත් කරන ලදී, එය HTTPS හරහා සේවාදායකයට ප්‍රවේශ විය: puds.ucweb.com/upgrade/index.xhtml.

ඊට අමතරව, “fix” කිරීමෙන් පසුව සහ මෙම ලිපිය ලියන කාලය දක්වා, බ්‍රවුසරයක PDF එකක් විවෘත කිරීමට උත්සාහ කිරීමේ ප්‍රතිඵලයක් ලෙස “අපොයි, යමක් වැරදී ඇත!” යන පාඨය සහිත දෝෂ පණිවිඩයක් ඇති විය. PDF එකක් විවෘත කිරීමට උත්සාහ කිරීමේදී සේවාදායකය වෙත ඉල්ලීමක් සිදු නොකළ නමුත් බ්‍රවුසරය දියත් කරන විට ඉල්ලීමක් කරන ලදී, එය Google Play නීති උල්ලංඝනය කරමින් ක්‍රියාත්මක කළ හැකි කේතය බාගත කිරීමේ අඛණ්ඩ හැකියාව පිළිබඳව ඉඟි කරයි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න