UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಪರಿಚಯ

ಮಾರ್ಚ್ ಕೊನೆಯಲ್ಲಿ ನಾವು ವರದಿ ಮಾಡಿದೆ, ಅವರು UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ಪರಿಶೀಲಿಸದ ಕೋಡ್ ಅನ್ನು ಲೋಡ್ ಮಾಡಲು ಮತ್ತು ರನ್ ಮಾಡಲು ಗುಪ್ತ ಸಾಮರ್ಥ್ಯವನ್ನು ಕಂಡುಹಿಡಿದಿದ್ದಾರೆ. ಈ ಡೌನ್‌ಲೋಡ್ ಹೇಗೆ ಸಂಭವಿಸುತ್ತದೆ ಮತ್ತು ಹ್ಯಾಕರ್‌ಗಳು ಅದನ್ನು ತಮ್ಮ ಸ್ವಂತ ಉದ್ದೇಶಗಳಿಗಾಗಿ ಹೇಗೆ ಬಳಸಬಹುದು ಎಂಬುದನ್ನು ಇಂದು ನಾವು ವಿವರವಾಗಿ ನೋಡುತ್ತೇವೆ.

ಕೆಲವು ಸಮಯದ ಹಿಂದೆ, UC ಬ್ರೌಸರ್ ಅನ್ನು ಬಹಳ ಆಕ್ರಮಣಕಾರಿಯಾಗಿ ಪ್ರಚಾರ ಮಾಡಲಾಯಿತು ಮತ್ತು ವಿತರಿಸಲಾಯಿತು: ಇದು ಮಾಲ್‌ವೇರ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ಬಳಕೆದಾರರ ಸಾಧನಗಳಲ್ಲಿ ಸ್ಥಾಪಿಸಲ್ಪಟ್ಟಿದೆ, ವೀಡಿಯೊ ಫೈಲ್‌ಗಳ ಸೋಗಿನಲ್ಲಿ ವಿವಿಧ ಸೈಟ್‌ಗಳಿಂದ ವಿತರಿಸಲಾಗಿದೆ (ಅಂದರೆ, ಬಳಕೆದಾರರು ತಾವು ಡೌನ್‌ಲೋಡ್ ಮಾಡುತ್ತಿದ್ದಾರೆ ಎಂದು ಭಾವಿಸಿದ್ದರು, ಉದಾಹರಣೆಗೆ, ಅಶ್ಲೀಲ ವೀಡಿಯೊ, ಆದರೆ ಬದಲಿಗೆ ಈ ಬ್ರೌಸರ್‌ನೊಂದಿಗೆ APK ಅನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿದೆ), ಬ್ರೌಸರ್ ಹಳೆಯದು, ದುರ್ಬಲವಾಗಿದೆ ಮತ್ತು ಅಂತಹ ವಿಷಯಗಳ ಸಂದೇಶಗಳೊಂದಿಗೆ ಭಯಾನಕ ಬ್ಯಾನರ್‌ಗಳನ್ನು ಬಳಸಿದೆ. VK ಯಲ್ಲಿನ ಅಧಿಕೃತ ಯುಸಿ ಬ್ರೌಸರ್ ಗುಂಪಿನಲ್ಲಿ ಇದೆ ಥೀಮ್, ಇದರಲ್ಲಿ ಬಳಕೆದಾರರು ಅನ್ಯಾಯದ ಜಾಹೀರಾತಿನ ಬಗ್ಗೆ ದೂರು ನೀಡಬಹುದು, ಅಲ್ಲಿ ಹಲವು ಉದಾಹರಣೆಗಳಿವೆ. 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 ಬ್ರೌಸರ್‌ನ ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು ನಿರ್ಧರಿಸಿದ್ದೇವೆ: ಸ್ಥಳೀಯ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸಿಕೊಂಡು PDF ಅನ್ನು ತೆರೆಯುವ ಸಾಮರ್ಥ್ಯ, ಇದು APK ಯಲ್ಲಿಲ್ಲ ಮತ್ತು ಅಗತ್ಯವಿದ್ದರೆ ಇಂಟರ್ನೆಟ್‌ನಿಂದ ಡೌನ್‌ಲೋಡ್ ಮಾಡುತ್ತದೆ. ಸೈದ್ಧಾಂತಿಕವಾಗಿ, ಯುಸಿ ಬ್ರೌಸರ್ ಬಳಕೆದಾರರ ಸಂವಹನವಿಲ್ಲದೆ ಏನನ್ನಾದರೂ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಒತ್ತಾಯಿಸಬಹುದು ಎಂದು ಗಮನಿಸಬೇಕಾದ ಅಂಶವಾಗಿದೆ - ಬ್ರೌಸರ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿದ ನಂತರ ಕಾರ್ಯಗತಗೊಳಿಸಿದ ವಿನಂತಿಗೆ ನೀವು ಉತ್ತಮವಾಗಿ ರೂಪುಗೊಂಡ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಒದಗಿಸಿದರೆ. ಆದರೆ ಇದನ್ನು ಮಾಡಲು, ನಾವು ಸರ್ವರ್‌ನೊಂದಿಗಿನ ಪರಸ್ಪರ ಕ್ರಿಯೆಯ ಪ್ರೋಟೋಕಾಲ್ ಅನ್ನು ಹೆಚ್ಚು ವಿವರವಾಗಿ ಅಧ್ಯಯನ ಮಾಡಬೇಕಾಗಿದೆ, ಆದ್ದರಿಂದ ತಡೆಹಿಡಿಯಲಾದ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಸಂಪಾದಿಸಲು ಮತ್ತು PDF ನೊಂದಿಗೆ ಕೆಲಸ ಮಾಡಲು ಲೈಬ್ರರಿಯನ್ನು ಬದಲಾಯಿಸಲು ಸುಲಭವಾಗುತ್ತದೆ ಎಂದು ನಾವು ನಿರ್ಧರಿಸಿದ್ದೇವೆ.

ಆದ್ದರಿಂದ, ಬಳಕೆದಾರರು ನೇರವಾಗಿ ಬ್ರೌಸರ್‌ನಲ್ಲಿ PDF ಅನ್ನು ತೆರೆಯಲು ಬಯಸಿದಾಗ, ಕೆಳಗಿನ ವಿನಂತಿಗಳನ್ನು ಟ್ರಾಫಿಕ್‌ನಲ್ಲಿ ಕಾಣಬಹುದು:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಮೊದಲು ಪೋಸ್ಟ್ ವಿನಂತಿ ಇದೆ puds.ucweb.com/upgrade/index.xhtml, ನಂತರ
PDF ಮತ್ತು ಕಚೇರಿ ಸ್ವರೂಪಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಲೈಬ್ರರಿಯೊಂದಿಗೆ ಆರ್ಕೈವ್ ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ. ಮೊದಲ ವಿನಂತಿಯು ಸಿಸ್ಟಮ್ ಬಗ್ಗೆ ಮಾಹಿತಿಯನ್ನು ರವಾನಿಸುತ್ತದೆ ಎಂದು ಭಾವಿಸುವುದು ತಾರ್ಕಿಕವಾಗಿದೆ (ಕನಿಷ್ಠ ಅಗತ್ಯವಿರುವ ಲೈಬ್ರರಿಯನ್ನು ಒದಗಿಸಲು ಆರ್ಕಿಟೆಕ್ಚರ್), ಮತ್ತು ಅದಕ್ಕೆ ಪ್ರತಿಕ್ರಿಯೆಯಾಗಿ ಬ್ರೌಸರ್ ಡೌನ್‌ಲೋಡ್ ಮಾಡಬೇಕಾದ ಲೈಬ್ರರಿಯ ಬಗ್ಗೆ ಕೆಲವು ಮಾಹಿತಿಯನ್ನು ಪಡೆಯುತ್ತದೆ: ವಿಳಾಸ ಮತ್ತು, ಪ್ರಾಯಶಃ , ಬೇರೆ ಏನಾದರೂ. ಸಮಸ್ಯೆಯೆಂದರೆ ಈ ವಿನಂತಿಯನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದೆ.

ವಿನಂತಿ ತುಣುಕು

ಉತ್ತರ ತುಣುಕು

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಲೈಬ್ರರಿಯನ್ನು ZIP ನಲ್ಲಿ ಪ್ಯಾಕ್ ಮಾಡಲಾಗಿದೆ ಮತ್ತು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿಲ್ಲ.

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಟ್ರಾಫಿಕ್ ಡೀಕ್ರಿಪ್ಶನ್ ಕೋಡ್ ಅನ್ನು ಹುಡುಕಿ

ಸರ್ವರ್ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸೋಣ. ವರ್ಗ ಕೋಡ್ ಅನ್ನು ನೋಡೋಣ com.uc.deployment.UpgradeDeployService: ವಿಧಾನದಿಂದ ಆನ್ ಸ್ಟಾರ್ಟ್ ಕಮಾಂಡ್ ಗೆ ಹೋಗಿ 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. ನಮಗೆ ಬೇಕಾದಂತೆ ಧ್ವನಿಸುತ್ತದೆ. ರೇಖೆಗಳ ಮೂಲಕ ನಿರ್ಣಯಿಸುವುದು ("ಅಪ್_ಡಿಕ್ರಿಪ್ಟ್", ಉದಾಹರಣೆಗೆ), ಸರ್ವರ್ನ ಪ್ರತಿಕ್ರಿಯೆಯನ್ನು ಡೀಕ್ರಿಪ್ಟ್ ಮಾಡುವ ವಿಧಾನವನ್ನು ಇಲ್ಲಿ ಕರೆಯಬೇಕು.
ವಿಧಾನಕ್ಕೆ ಹೋಗೋಣ 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, ಇದು ವಾಸ್ತವವಾಗಿ a .so ಅಲ್ಲ, ಆದರೆ a .jar. ನಾವು ಆಸಕ್ತಿ ಹೊಂದಿರುವ ವಿಧಾನವನ್ನು ಈ ಕೆಳಗಿನಂತೆ ಅಳವಡಿಸಲಾಗಿದೆ:

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 ಎಂದರೆ ಡೀಕ್ರಿಪ್ಶನ್, ವಿಧಾನದಲ್ಲಿರುವಂತೆ ಅಂತಿಮ ಸಿಸ್ಟಮ್ ವರ್ಗ javax.crypto.Cipher. ಮತ್ತು ಇದೆಲ್ಲವನ್ನೂ 10601 ಸಂಖ್ಯೆಯೊಂದಿಗೆ ನಿರ್ದಿಷ್ಟ ರೂಟರ್‌ಗೆ ವರ್ಗಾಯಿಸಲಾಗುತ್ತದೆ - ಇದು ಸ್ಪಷ್ಟವಾಗಿ ಕಮಾಂಡ್ ಸಂಖ್ಯೆ.

ಪರಿವರ್ತನೆಗಳ ಮುಂದಿನ ಸರಣಿಯ ನಂತರ ನಾವು ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸುವ ವರ್ಗವನ್ನು ಕಂಡುಕೊಳ್ಳುತ್ತೇವೆ ಐರೌಟರ್ ಕಾಂಪೊನೆಂಟ್ ಮತ್ತು ವಿಧಾನ 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.

ರಫ್ತು ಮಾಡಿದ ಕಾರ್ಯಗಳಲ್ಲಿ ಅಂತಹ ಯಾವುದೇ ಕಾರ್ಯವಿಲ್ಲ, ಅಂದರೆ ನೀವು ಕರೆಗಾಗಿ ನೋಡಬೇಕಾಗಿದೆ ನೋಂದಣಿ ಸ್ಥಳೀಯರು.
ಫಂಕ್ಷನ್‌ಗೆ ಹೋಗೋಣ JNI_Onload ಮತ್ತು ನಾವು ಈ ಚಿತ್ರವನ್ನು ನೋಡುತ್ತೇವೆ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಇಲ್ಲಿ ಏನು ನಡೆಯುತ್ತಿದೆ? ಮೊದಲ ನೋಟದಲ್ಲಿ, ಕಾರ್ಯದ ಪ್ರಾರಂಭ ಮತ್ತು ಅಂತ್ಯವು ARM ಆರ್ಕಿಟೆಕ್ಚರ್‌ಗೆ ವಿಶಿಷ್ಟವಾಗಿದೆ. ಸ್ಟಾಕ್‌ನಲ್ಲಿನ ಮೊದಲ ಸೂಚನೆಯು ಕಾರ್ಯವು ಅದರ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಬಳಸುವ ರೆಜಿಸ್ಟರ್‌ಗಳ ವಿಷಯಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ (ಈ ಸಂದರ್ಭದಲ್ಲಿ, R0, R1 ಮತ್ತು R2), ಹಾಗೆಯೇ LR ರಿಜಿಸ್ಟರ್‌ನ ವಿಷಯಗಳು, ಇದು ಕಾರ್ಯದಿಂದ ಹಿಂತಿರುಗುವ ವಿಳಾಸವನ್ನು ಹೊಂದಿರುತ್ತದೆ. . ಕೊನೆಯ ಸೂಚನೆಯು ಉಳಿಸಿದ ರೆಜಿಸ್ಟರ್‌ಗಳನ್ನು ಮರುಸ್ಥಾಪಿಸುತ್ತದೆ, ಮತ್ತು ರಿಟರ್ನ್ ವಿಳಾಸವನ್ನು ತಕ್ಷಣವೇ ಪಿಸಿ ರಿಜಿಸ್ಟರ್‌ನಲ್ಲಿ ಇರಿಸಲಾಗುತ್ತದೆ - ಹೀಗಾಗಿ ಕಾರ್ಯದಿಂದ ಹಿಂತಿರುಗುತ್ತದೆ. ಆದರೆ ನೀವು ಹತ್ತಿರದಿಂದ ನೋಡಿದರೆ, ಅಂತಿಮ ಸೂಚನೆಯು ಸ್ಟಾಕ್‌ನಲ್ಲಿ ಸಂಗ್ರಹವಾಗಿರುವ ರಿಟರ್ನ್ ವಿಳಾಸವನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ ಎಂದು ನೀವು ಗಮನಿಸಬಹುದು. ನಂತರ ಅದು ಹೇಗಿರುತ್ತದೆ ಎಂದು ಲೆಕ್ಕಾಚಾರ ಮಾಡೋಣ
ಕೋಡ್ ಮರಣದಂಡನೆ. ನಿರ್ದಿಷ್ಟ ವಿಳಾಸ 1xB0 ಅನ್ನು R130 ಗೆ ಲೋಡ್ ಮಾಡಲಾಗಿದೆ, 5 ಅನ್ನು ಅದರಿಂದ ಕಳೆಯಲಾಗುತ್ತದೆ, ನಂತರ ಅದನ್ನು R0 ಗೆ ವರ್ಗಾಯಿಸಲಾಗುತ್ತದೆ ಮತ್ತು 0x10 ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತದೆ. ಇದು 0xB13B ಆಗಿ ಹೊರಹೊಮ್ಮುತ್ತದೆ. ಹೀಗಾಗಿ, ಕೊನೆಯ ಸೂಚನೆಯು ಸಾಮಾನ್ಯ ಫಂಕ್ಷನ್ ರಿಟರ್ನ್ ಎಂದು IDA ಭಾವಿಸುತ್ತದೆ, ಆದರೆ ವಾಸ್ತವವಾಗಿ ಇದು ಲೆಕ್ಕಹಾಕಿದ ವಿಳಾಸ 0xB13B ಗೆ ಹೋಗುತ್ತದೆ.

ARM ಪ್ರೊಸೆಸರ್‌ಗಳು ಎರಡು ವಿಧಾನಗಳು ಮತ್ತು ಎರಡು ಸೆಟ್ ಸೂಚನೆಗಳನ್ನು ಹೊಂದಿವೆ ಎಂಬುದನ್ನು ಇಲ್ಲಿ ನೆನಪಿಸಿಕೊಳ್ಳುವುದು ಯೋಗ್ಯವಾಗಿದೆ: ARM ಮತ್ತು Thumb. ವಿಳಾಸದ ಕನಿಷ್ಠ ಮಹತ್ವದ ಬಿಟ್ ಪ್ರೊಸೆಸರ್‌ಗೆ ಯಾವ ಸೂಚನಾ ಸೆಟ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತಿದೆ ಎಂದು ಹೇಳುತ್ತದೆ. ಅಂದರೆ, ವಿಳಾಸವು ವಾಸ್ತವವಾಗಿ 0xB13A ಆಗಿದೆ, ಮತ್ತು ಕನಿಷ್ಠ ಮಹತ್ವದ ಬಿಟ್‌ನಲ್ಲಿ ಒಂದು ಥಂಬ್ ಮೋಡ್ ಅನ್ನು ಸೂಚಿಸುತ್ತದೆ.

ಇದೇ ರೀತಿಯ "ಅಡಾಪ್ಟರ್" ಅನ್ನು ಈ ಲೈಬ್ರರಿಯಲ್ಲಿ ಪ್ರತಿ ಕಾರ್ಯದ ಪ್ರಾರಂಭಕ್ಕೆ ಸೇರಿಸಲಾಗಿದೆ ಮತ್ತು
ಕಸದ ಕೋಡ್. ನಾವು ಅವುಗಳ ಮೇಲೆ ಹೆಚ್ಚು ವಿವರವಾಗಿ ವಾಸಿಸುವುದಿಲ್ಲ - ನಾವು ನೆನಪಿಸಿಕೊಳ್ಳುತ್ತೇವೆ
ಬಹುತೇಕ ಎಲ್ಲಾ ಕಾರ್ಯಗಳ ನಿಜವಾದ ಆರಂಭವು ಸ್ವಲ್ಪ ದೂರದಲ್ಲಿದೆ.

ಕೋಡ್ ಸ್ಪಷ್ಟವಾಗಿ 0xB13A ಗೆ ನೆಗೆಯುವುದಿಲ್ಲವಾದ್ದರಿಂದ, ಕೋಡ್ ಈ ಸ್ಥಳದಲ್ಲಿದೆ ಎಂದು IDA ಸ್ವತಃ ಗುರುತಿಸಲಿಲ್ಲ. ಅದೇ ಕಾರಣಕ್ಕಾಗಿ, ಇದು ಲೈಬ್ರರಿಯಲ್ಲಿರುವ ಹೆಚ್ಚಿನ ಕೋಡ್ ಅನ್ನು ಕೋಡ್ ಎಂದು ಗುರುತಿಸುವುದಿಲ್ಲ, ಇದು ವಿಶ್ಲೇಷಣೆಯನ್ನು ಸ್ವಲ್ಪ ಕಷ್ಟಕರವಾಗಿಸುತ್ತದೆ. ಇದು ಕೋಡ್ ಎಂದು ನಾವು IDA ಗೆ ಹೇಳುತ್ತೇವೆ ಮತ್ತು ಇದು ಹೀಗಾಗುತ್ತದೆ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಟೇಬಲ್ ಸ್ಪಷ್ಟವಾಗಿ 0xB144 ನಲ್ಲಿ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ. sub_494C ಯಲ್ಲಿ ಏನಿದೆ?

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

LR ರಿಜಿಸ್ಟರ್ನಲ್ಲಿ ಈ ಕಾರ್ಯವನ್ನು ಕರೆಯುವಾಗ, ನಾವು ಹಿಂದೆ ತಿಳಿಸಿದ ಟೇಬಲ್ನ ವಿಳಾಸವನ್ನು ಪಡೆಯುತ್ತೇವೆ (0xB144). R0 ನಲ್ಲಿ - ಈ ಕೋಷ್ಟಕದಲ್ಲಿ ಸೂಚ್ಯಂಕ. ಅಂದರೆ, ಮೌಲ್ಯವನ್ನು ಟೇಬಲ್ನಿಂದ ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತದೆ, LR ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ ಮತ್ತು ಫಲಿತಾಂಶವಾಗಿದೆ
ಹೋಗಬೇಕಾದ ವಿಳಾಸ. ಅದನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡಲು ಪ್ರಯತ್ನಿಸೋಣ: 0xB144 + [0xB144 + 8* 4] = 0xB144 + 0x120 = 0xB264. ನಾವು ಸ್ವೀಕರಿಸಿದ ವಿಳಾಸಕ್ಕೆ ಹೋಗುತ್ತೇವೆ ಮತ್ತು ಅಕ್ಷರಶಃ ಒಂದೆರಡು ಉಪಯುಕ್ತ ಸೂಚನೆಗಳನ್ನು ನೋಡಿ ಮತ್ತು ಮತ್ತೆ 0xB140 ಗೆ ಹೋಗಿ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಈಗ ಟೇಬಲ್‌ನಿಂದ 0x20 ಸೂಚ್ಯಂಕದೊಂದಿಗೆ ಆಫ್‌ಸೆಟ್‌ನಲ್ಲಿ ಪರಿವರ್ತನೆ ಇರುತ್ತದೆ.

ಟೇಬಲ್ನ ಗಾತ್ರದಿಂದ ನಿರ್ಣಯಿಸುವುದು, ಕೋಡ್ನಲ್ಲಿ ಅಂತಹ ಅನೇಕ ಪರಿವರ್ತನೆಗಳು ಇರುತ್ತವೆ. ವಿಳಾಸಗಳನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಲೆಕ್ಕಾಚಾರ ಮಾಡದೆಯೇ ಇದನ್ನು ಹೇಗಾದರೂ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಭಾಯಿಸಲು ಸಾಧ್ಯವೇ ಎಂಬ ಪ್ರಶ್ನೆ ಉದ್ಭವಿಸುತ್ತದೆ. ಮತ್ತು ಸ್ಕ್ರಿಪ್ಟ್‌ಗಳು ಮತ್ತು ಐಡಿಎಯಲ್ಲಿ ಕೋಡ್ ಅನ್ನು ಪ್ಯಾಚ್ ಮಾಡುವ ಸಾಮರ್ಥ್ಯವು ನಮ್ಮ ಸಹಾಯಕ್ಕೆ ಬರುತ್ತದೆ:

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 ನಂತರದ ಸೂಚನೆಗಳು ಹೆಚ್ಚು ಅರ್ಥವನ್ನು ತೋರುತ್ತಿಲ್ಲ, ಇದು ಕೆಲವು ರೀತಿಯ ಸ್ಥಳಾಂತರದಂತಿದೆ. ಉಪ_4964 ಅನ್ನು ನೋಡೋಣ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಮತ್ತು ವಾಸ್ತವವಾಗಿ, ಇಲ್ಲಿ LR ನಲ್ಲಿ ಇರುವ ವಿಳಾಸದಲ್ಲಿ dword ತೆಗೆದುಕೊಳ್ಳಲಾಗುತ್ತದೆ, ಈ ವಿಳಾಸಕ್ಕೆ ಸೇರಿಸಲಾಗುತ್ತದೆ, ಅದರ ನಂತರ ಫಲಿತಾಂಶದ ವಿಳಾಸದಲ್ಲಿನ ಮೌಲ್ಯವನ್ನು ತೆಗೆದುಕೊಂಡು ಸ್ಟಾಕ್ನಲ್ಲಿ ಹಾಕಲಾಗುತ್ತದೆ. ಅಲ್ಲದೆ, 4 ಅನ್ನು LR ಗೆ ಸೇರಿಸಲಾಗುತ್ತದೆ ಆದ್ದರಿಂದ ಕಾರ್ಯದಿಂದ ಹಿಂತಿರುಗಿದ ನಂತರ, ಇದೇ ಆಫ್‌ಸೆಟ್ ಅನ್ನು ಬಿಟ್ಟುಬಿಡಲಾಗುತ್ತದೆ. ಅದರ ನಂತರ 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 ನಿಂದ ವಿಳಾಸಕ್ಕೆ ಆಫ್ಸೆಟ್ ಅನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತೇವೆ, ಅದನ್ನು LR ಗೆ ಸೇರಿಸಿ ಮತ್ತು ಅಲ್ಲಿಗೆ ಹೋಗುತ್ತೇವೆ. 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 ಬ್ರೌಸರ್ನ ಡೆವಲಪರ್ಗಳು ನಮಗೆ ಮತ್ತೊಂದು ಆಶ್ಚರ್ಯವನ್ನು ಸಿದ್ಧಪಡಿಸಿದ್ದಾರೆ.

ಜಾವಾ ಕೋಡ್‌ನಲ್ಲಿ ರೂಪುಗೊಂಡ ರಚನೆಯಿಂದ ನಿಯತಾಂಕಗಳನ್ನು ಸ್ವೀಕರಿಸಿದ ನಂತರ, ನಾವು ಪಡೆಯುತ್ತೇವೆ
ವಿಳಾಸ 0x4D070 ನಲ್ಲಿ ಕಾರ್ಯಕ್ಕೆ. ಮತ್ತು ಇಲ್ಲಿ ಮತ್ತೊಂದು ರೀತಿಯ ಕೋಡ್ ಅಸ್ಪಷ್ಟತೆ ನಮಗೆ ಕಾಯುತ್ತಿದೆ.

ನಾವು R7 ಮತ್ತು R4 ನಲ್ಲಿ ಎರಡು ಸೂಚ್ಯಂಕಗಳನ್ನು ಇರಿಸಿದ್ದೇವೆ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ನಾವು ಮೊದಲ ಸೂಚ್ಯಂಕವನ್ನು R11 ಗೆ ಬದಲಾಯಿಸುತ್ತೇವೆ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಟೇಬಲ್‌ನಿಂದ ವಿಳಾಸವನ್ನು ಪಡೆಯಲು, ಸೂಚ್ಯಂಕವನ್ನು ಬಳಸಿ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಮೊದಲ ವಿಳಾಸಕ್ಕೆ ಹೋದ ನಂತರ, ಎರಡನೇ ಸೂಚ್ಯಂಕವನ್ನು ಬಳಸಲಾಗುತ್ತದೆ, ಅದು R4 ನಲ್ಲಿದೆ. ಕೋಷ್ಟಕದಲ್ಲಿ 230 ಅಂಶಗಳಿವೆ.

ಅದಕ್ಕೆ ಏನು ಮಾಡಬೇಕು? ಇದು ಸ್ವಿಚ್ ಎಂದು ನೀವು IDA ಗೆ ಹೇಳಬಹುದು: ಸಂಪಾದಿಸಿ -> ಇತರೆ -> ಸ್ವಿಚ್ ಭಾಷಾವೈಶಿಷ್ಟ್ಯವನ್ನು ಸೂಚಿಸಿ.

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಪರಿಣಾಮವಾಗಿ ಕೋಡ್ ಭಯಾನಕವಾಗಿದೆ. ಆದರೆ, ಅದರ ಕಾಡಿನ ಮೂಲಕ ನಿಮ್ಮ ದಾರಿಯಲ್ಲಿ, ನಮಗೆ ಈಗಾಗಲೇ ಪರಿಚಿತವಾಗಿರುವ ಕಾರ್ಯಕ್ಕೆ ಕರೆಯನ್ನು ನೀವು ಗಮನಿಸಬಹುದು ಉಪ_6115C:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

3 ರಲ್ಲಿ RC4 ಅಲ್ಗಾರಿದಮ್ ಬಳಸಿ ಡೀಕ್ರಿಪ್ಶನ್ ಇರುವ ಸ್ವಿಚ್ ಇತ್ತು. ಮತ್ತು ಈ ಸಂದರ್ಭದಲ್ಲಿ, ಕಾರ್ಯಕ್ಕೆ ರವಾನಿಸಲಾದ ರಚನೆಯು ರವಾನಿಸಲಾದ ನಿಯತಾಂಕಗಳಿಂದ ತುಂಬಿರುತ್ತದೆ doCommandNative. ನಾವು ಅಲ್ಲಿ ಏನನ್ನು ಹೊಂದಿದ್ದೇವೆ ಎಂಬುದನ್ನು ನೆನಪಿಸಿಕೊಳ್ಳೋಣ ಮ್ಯಾಜಿಕ್ ಇಂಟ್ ಮೌಲ್ಯದೊಂದಿಗೆ 16. ನಾವು ಅನುಗುಣವಾದ ಪ್ರಕರಣವನ್ನು ನೋಡುತ್ತೇವೆ - ಮತ್ತು ಹಲವಾರು ಪರಿವರ್ತನೆಗಳ ನಂತರ ಅಲ್ಗಾರಿದಮ್ ಅನ್ನು ಗುರುತಿಸಬಹುದಾದ ಕೋಡ್ ಅನ್ನು ನಾವು ಕಂಡುಕೊಳ್ಳುತ್ತೇವೆ.

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಇದು AES!

ಅಲ್ಗಾರಿದಮ್ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ, ಅದರ ನಿಯತಾಂಕಗಳನ್ನು ಪಡೆಯುವುದು ಮಾತ್ರ ಉಳಿದಿದೆ: ಮೋಡ್, ಕೀ ಮತ್ತು, ಪ್ರಾಯಶಃ, ಇನಿಶಿಯಲೈಸೇಶನ್ ವೆಕ್ಟರ್ (ಅದರ ಉಪಸ್ಥಿತಿಯು ಎಇಎಸ್ ಅಲ್ಗಾರಿದಮ್ನ ಆಪರೇಟಿಂಗ್ ಮೋಡ್ ಅನ್ನು ಅವಲಂಬಿಸಿರುತ್ತದೆ). ಅವರೊಂದಿಗೆ ರಚನೆಯು ಕಾರ್ಯದ ಕರೆಗೆ ಮುಂಚಿತವಾಗಿ ಎಲ್ಲೋ ರಚನೆಯಾಗಬೇಕು ಉಪ_6115C, ಆದರೆ ಕೋಡ್‌ನ ಈ ಭಾಗವು ವಿಶೇಷವಾಗಿ ಅಸ್ಪಷ್ಟವಾಗಿದೆ, ಆದ್ದರಿಂದ ಕೋಡ್ ಅನ್ನು ಪ್ಯಾಚ್ ಮಾಡುವ ಕಲ್ಪನೆಯು ಉದ್ಭವಿಸುತ್ತದೆ ಇದರಿಂದ ಡೀಕ್ರಿಪ್ಶನ್ ಕಾರ್ಯದ ಎಲ್ಲಾ ನಿಯತಾಂಕಗಳನ್ನು ಫೈಲ್‌ಗೆ ಎಸೆಯಲಾಗುತ್ತದೆ.

ಪ್ಯಾಚ್

ಅಸೆಂಬ್ಲಿ ಭಾಷೆಯಲ್ಲಿ ಎಲ್ಲಾ ಪ್ಯಾಚ್ ಕೋಡ್ ಅನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಬರೆಯದಿರಲು, ನೀವು Android ಸ್ಟುಡಿಯೊವನ್ನು ಪ್ರಾರಂಭಿಸಬಹುದು, ನಮ್ಮ ಡೀಕ್ರಿಪ್ಶನ್ ಕಾರ್ಯದಂತೆಯೇ ಅದೇ ಇನ್‌ಪುಟ್ ನಿಯತಾಂಕಗಳನ್ನು ಸ್ವೀಕರಿಸುವ ಮತ್ತು ಫೈಲ್‌ಗೆ ಬರೆಯುವ ಕಾರ್ಯವನ್ನು ಬರೆಯಬಹುದು, ನಂತರ ಕಂಪೈಲರ್ ಮಾಡುವ ಕೋಡ್ ಅನ್ನು ನಕಲಿಸಿ-ಅಂಟಿಸಿ. ಉತ್ಪಾದಿಸುತ್ತವೆ.

UC ಬ್ರೌಸರ್ ತಂಡದ ನಮ್ಮ ಸ್ನೇಹಿತರು ಸಹ ಕೋಡ್ ಸೇರಿಸುವ ಅನುಕೂಲವನ್ನು ನೋಡಿಕೊಂಡರು. ಪ್ರತಿ ಕಾರ್ಯದ ಪ್ರಾರಂಭದಲ್ಲಿ ನಾವು ಕಸದ ಕೋಡ್ ಅನ್ನು ಹೊಂದಿದ್ದೇವೆ ಅದನ್ನು ಸುಲಭವಾಗಿ ಇತರರೊಂದಿಗೆ ಬದಲಾಯಿಸಬಹುದು. ತುಂಬಾ ಅನುಕೂಲಕರ 🙂 ಆದಾಗ್ಯೂ, ಗುರಿ ಕಾರ್ಯದ ಆರಂಭದಲ್ಲಿ ಫೈಲ್‌ಗೆ ಎಲ್ಲಾ ನಿಯತಾಂಕಗಳನ್ನು ಉಳಿಸುವ ಕೋಡ್‌ಗೆ ಸಾಕಷ್ಟು ಸ್ಥಳವಿಲ್ಲ. ನಾನು ಅದನ್ನು ಭಾಗಗಳಾಗಿ ವಿಭಜಿಸಬೇಕಾಗಿತ್ತು ಮತ್ತು ನೆರೆಯ ಕಾರ್ಯಗಳಿಂದ ಕಸದ ಬ್ಲಾಕ್ಗಳನ್ನು ಬಳಸಬೇಕಾಗಿತ್ತು. ಒಟ್ಟು ನಾಲ್ಕು ಭಾಗಗಳಿದ್ದವು.

ಮೊದಲ ಭಾಗ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ARM ಆರ್ಕಿಟೆಕ್ಚರ್‌ನಲ್ಲಿ, ಮೊದಲ ನಾಲ್ಕು ಕಾರ್ಯ ನಿಯತಾಂಕಗಳನ್ನು R0-R3 ರೆಜಿಸ್ಟರ್‌ಗಳ ಮೂಲಕ ರವಾನಿಸಲಾಗುತ್ತದೆ, ಉಳಿದವು ಯಾವುದಾದರೂ ಇದ್ದರೆ, ಸ್ಟಾಕ್ ಮೂಲಕ ರವಾನಿಸಲಾಗುತ್ತದೆ. LR ರಿಜಿಸ್ಟರ್ ರಿಟರ್ನ್ ವಿಳಾಸವನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಇದೆಲ್ಲವನ್ನೂ ಉಳಿಸಬೇಕಾಗಿದೆ ಆದ್ದರಿಂದ ನಾವು ಅದರ ನಿಯತಾಂಕಗಳನ್ನು ಡಂಪ್ ಮಾಡಿದ ನಂತರ ಕಾರ್ಯವು ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ಪ್ರಕ್ರಿಯೆಯಲ್ಲಿ ನಾವು ಬಳಸುವ ಎಲ್ಲಾ ರೆಜಿಸ್ಟರ್‌ಗಳನ್ನು ಸಹ ನಾವು ಉಳಿಸಬೇಕಾಗಿದೆ, ಆದ್ದರಿಂದ ನಾವು PUSH.W {R0-R10,LR} ಅನ್ನು ಮಾಡುತ್ತೇವೆ. R7 ನಲ್ಲಿ ನಾವು ಸ್ಟಾಕ್ ಮೂಲಕ ಕಾರ್ಯಕ್ಕೆ ರವಾನಿಸಲಾದ ನಿಯತಾಂಕಗಳ ಪಟ್ಟಿಯ ವಿಳಾಸವನ್ನು ಪಡೆಯುತ್ತೇವೆ.

ಕಾರ್ಯವನ್ನು ಬಳಸುವುದು ಫೋಪೆನ್ ಫೈಲ್ ಅನ್ನು ತೆರೆಯೋಣ /data/local/tmp/aes "ab" ಮೋಡ್‌ನಲ್ಲಿ
ಅಂದರೆ ಸೇರ್ಪಡೆಗಾಗಿ. R0 ನಲ್ಲಿ ನಾವು ಫೈಲ್ ಹೆಸರಿನ ವಿಳಾಸವನ್ನು ಲೋಡ್ ಮಾಡುತ್ತೇವೆ, R1 ನಲ್ಲಿ - ಮೋಡ್ ಅನ್ನು ಸೂಚಿಸುವ ಸಾಲಿನ ವಿಳಾಸ. ಮತ್ತು ಇಲ್ಲಿ ಕಸದ ಕೋಡ್ ಕೊನೆಗೊಳ್ಳುತ್ತದೆ, ಆದ್ದರಿಂದ ನಾವು ಮುಂದಿನ ಕಾರ್ಯಕ್ಕೆ ಮುಂದುವರಿಯುತ್ತೇವೆ. ಅದು ಕೆಲಸ ಮಾಡುವುದನ್ನು ಮುಂದುವರಿಸಲು, ನಾವು ಆರಂಭದಲ್ಲಿ ಕಾರ್ಯದ ನೈಜ ಕೋಡ್‌ಗೆ ಪರಿವರ್ತನೆಯನ್ನು ಹಾಕುತ್ತೇವೆ, ಕಸವನ್ನು ಬೈಪಾಸ್ ಮಾಡುತ್ತೇವೆ ಮತ್ತು ಕಸದ ಬದಲಿಗೆ ನಾವು ಪ್ಯಾಚ್‌ನ ಮುಂದುವರಿಕೆಯನ್ನು ಸೇರಿಸುತ್ತೇವೆ.

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಕರೆ ಮಾಡಲಾಗುತ್ತಿದೆ ಫೋಪೆನ್.

ಕಾರ್ಯದ ಮೊದಲ ಮೂರು ನಿಯತಾಂಕಗಳು ಏಸ್ ಪ್ರಕಾರವನ್ನು ಹೊಂದಿವೆ ಇಂಟ್. ನಾವು ಆರಂಭದಲ್ಲಿ ರೆಜಿಸ್ಟರ್‌ಗಳನ್ನು ಸ್ಟಾಕ್‌ಗೆ ಉಳಿಸಿರುವುದರಿಂದ, ನಾವು ಕಾರ್ಯವನ್ನು ಸರಳವಾಗಿ ರವಾನಿಸಬಹುದು ಬರೆಯಿರಿ ಸ್ಟಾಕ್‌ನಲ್ಲಿ ಅವರ ವಿಳಾಸಗಳು.

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಮುಂದೆ ನಾವು ಮೂರು ರಚನೆಗಳನ್ನು ಹೊಂದಿದ್ದೇವೆ ಅದು ಡೇಟಾ ಗಾತ್ರ ಮತ್ತು ಕೀ, ಇನಿಶಿಯಲೈಸೇಶನ್ ವೆಕ್ಟರ್ ಮತ್ತು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಡೇಟಾಗೆ ಪಾಯಿಂಟರ್ ಅನ್ನು ಹೊಂದಿರುತ್ತದೆ.

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಕೊನೆಯಲ್ಲಿ, ಫೈಲ್ ಅನ್ನು ಮುಚ್ಚಿ, ರೆಜಿಸ್ಟರ್ಗಳನ್ನು ಮರುಸ್ಥಾಪಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಣವನ್ನು ನೈಜ ಕಾರ್ಯಕ್ಕೆ ವರ್ಗಾಯಿಸಿ ಏಸ್.

ನಾವು ಪ್ಯಾಚ್ ಮಾಡಿದ ಲೈಬ್ರರಿಯೊಂದಿಗೆ 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 ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ನಾವು MD5, "extract_unzipsize" ಮತ್ತು ಸಂಖ್ಯೆಯನ್ನು ಹೋಲುವ ಆರ್ಕೈವ್ URL ಅನ್ನು ನೋಡುತ್ತೇವೆ. ನಾವು ಪರಿಶೀಲಿಸುತ್ತೇವೆ: ಆರ್ಕೈವ್ನ MD5 ಒಂದೇ ಆಗಿರುತ್ತದೆ, ಅನ್ಪ್ಯಾಕ್ ಮಾಡಲಾದ ಲೈಬ್ರರಿಯ ಗಾತ್ರವು ಒಂದೇ ಆಗಿರುತ್ತದೆ. ನಾವು ಈ ಲೈಬ್ರರಿಯನ್ನು ಪ್ಯಾಚ್ ಮಾಡಲು ಮತ್ತು ಅದನ್ನು ಬ್ರೌಸರ್‌ಗೆ ನೀಡಲು ಪ್ರಯತ್ನಿಸುತ್ತಿದ್ದೇವೆ. ನಮ್ಮ ಪ್ಯಾಚ್ ಮಾಡಿದ ಲೈಬ್ರರಿ ಲೋಡ್ ಆಗಿದೆ ಎಂದು ತೋರಿಸಲು, "PWNED!" ಪಠ್ಯದೊಂದಿಗೆ SMS ಅನ್ನು ರಚಿಸಲು ನಾವು ಉದ್ದೇಶವನ್ನು ಪ್ರಾರಂಭಿಸುತ್ತೇವೆ. ನಾವು ಸರ್ವರ್‌ನಿಂದ ಎರಡು ಪ್ರತಿಕ್ರಿಯೆಗಳನ್ನು ಬದಲಾಯಿಸುತ್ತೇವೆ: puds.ucweb.com/upgrade/index.xhtml ಮತ್ತು ಆರ್ಕೈವ್ ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು. ಮೊದಲನೆಯದರಲ್ಲಿ ನಾವು MD5 ಅನ್ನು ಬದಲಾಯಿಸುತ್ತೇವೆ (ಅನ್ಪ್ಯಾಕ್ ಮಾಡಿದ ನಂತರ ಗಾತ್ರವು ಬದಲಾಗುವುದಿಲ್ಲ), ಎರಡನೆಯದರಲ್ಲಿ ನಾವು ಆರ್ಕೈವ್ ಅನ್ನು ಪ್ಯಾಚ್ ಮಾಡಿದ ಲೈಬ್ರರಿಯೊಂದಿಗೆ ನೀಡುತ್ತೇವೆ.

ಬ್ರೌಸರ್ ಹಲವಾರು ಬಾರಿ ಆರ್ಕೈವ್ ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ, ಅದರ ನಂತರ ಅದು ದೋಷವನ್ನು ನೀಡುತ್ತದೆ. ಸ್ಪಷ್ಟವಾಗಿ ಏನೋ
ಅವನಿಗೆ ಇಷ್ಟವಿಲ್ಲ. ಈ ಮರ್ಕಿ ಸ್ವರೂಪವನ್ನು ವಿಶ್ಲೇಷಿಸಿದ ಪರಿಣಾಮವಾಗಿ, ಸರ್ವರ್ ಆರ್ಕೈವ್‌ನ ಗಾತ್ರವನ್ನು ಸಹ ರವಾನಿಸುತ್ತದೆ:

UC ಬ್ರೌಸರ್‌ನಲ್ಲಿ ದೋಷಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ

ಇದನ್ನು LEB128 ರಲ್ಲಿ ಎನ್ಕೋಡ್ ಮಾಡಲಾಗಿದೆ. ಪ್ಯಾಚ್ ನಂತರ, ಲೈಬ್ರರಿಯೊಂದಿಗೆ ಆರ್ಕೈವ್ನ ಗಾತ್ರವು ಸ್ವಲ್ಪ ಬದಲಾಗಿದೆ, ಆದ್ದರಿಂದ ಆರ್ಕೈವ್ ಅನ್ನು ವಕ್ರವಾಗಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾಗಿದೆ ಎಂದು ಬ್ರೌಸರ್ ಪರಿಗಣಿಸಿದೆ ಮತ್ತು ಹಲವಾರು ಪ್ರಯತ್ನಗಳ ನಂತರ ಅದು ದೋಷವನ್ನು ಎಸೆದಿದೆ.

ನಾವು ಆರ್ಕೈವ್ನ ಗಾತ್ರವನ್ನು ಸರಿಹೊಂದಿಸುತ್ತೇವೆ ... ಮತ್ತು - ಗೆಲುವು! 🙂 ಫಲಿತಾಂಶವು ವೀಡಿಯೊದಲ್ಲಿದೆ.

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

ಪರಿಣಾಮಗಳು ಮತ್ತು ಡೆವಲಪರ್ ಪ್ರತಿಕ್ರಿಯೆ

ಅದೇ ರೀತಿಯಲ್ಲಿ, ಹ್ಯಾಕರ್‌ಗಳು ದುರುದ್ದೇಶಪೂರಿತ ಲೈಬ್ರರಿಗಳನ್ನು ವಿತರಿಸಲು ಮತ್ತು ಚಲಾಯಿಸಲು UC ಬ್ರೌಸರ್‌ನ ಅಸುರಕ್ಷಿತ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಬಹುದು. ಈ ಲೈಬ್ರರಿಗಳು ಬ್ರೌಸರ್‌ನ ಸಂದರ್ಭದಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತವೆ, ಆದ್ದರಿಂದ ಅವರು ಅದರ ಎಲ್ಲಾ ಸಿಸ್ಟಮ್ ಅನುಮತಿಗಳನ್ನು ಸ್ವೀಕರಿಸುತ್ತಾರೆ. ಪರಿಣಾಮವಾಗಿ, ಫಿಶಿಂಗ್ ವಿಂಡೋಗಳನ್ನು ಪ್ರದರ್ಶಿಸುವ ಸಾಮರ್ಥ್ಯ, ಹಾಗೆಯೇ ಲಾಗಿನ್‌ಗಳು, ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಡೇಟಾಬೇಸ್‌ನಲ್ಲಿ ಸಂಗ್ರಹವಾಗಿರುವ ಕುಕೀಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ಕಿತ್ತಳೆ ಚೈನೀಸ್ ಅಳಿಲುಗಳ ಕಾರ್ಯ ಫೈಲ್‌ಗಳಿಗೆ ಪ್ರವೇಶ.

ನಾವು UC ಬ್ರೌಸರ್‌ನ ಡೆವಲಪರ್‌ಗಳನ್ನು ಸಂಪರ್ಕಿಸಿದ್ದೇವೆ ಮತ್ತು ನಾವು ಕಂಡುಕೊಂಡ ಸಮಸ್ಯೆಯ ಬಗ್ಗೆ ಅವರಿಗೆ ತಿಳಿಸಿದ್ದೇವೆ, ದುರ್ಬಲತೆ ಮತ್ತು ಅದರ ಅಪಾಯವನ್ನು ಸೂಚಿಸಲು ಪ್ರಯತ್ನಿಸಿದ್ದೇವೆ, ಆದರೆ ಅವರು ನಮ್ಮೊಂದಿಗೆ ಏನನ್ನೂ ಚರ್ಚಿಸಲಿಲ್ಲ. ಏತನ್ಮಧ್ಯೆ, ಬ್ರೌಸರ್ ತನ್ನ ಅಪಾಯಕಾರಿ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸರಳ ದೃಷ್ಟಿಯಲ್ಲಿ ತೋರಿಸುವುದನ್ನು ಮುಂದುವರೆಸಿದೆ. ಆದರೆ ಒಮ್ಮೆ ನಾವು ದುರ್ಬಲತೆಯ ವಿವರಗಳನ್ನು ಬಹಿರಂಗಪಡಿಸಿದ್ದೇವೆ, ಅದನ್ನು ಮೊದಲಿನಂತೆ ನಿರ್ಲಕ್ಷಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮಾರ್ಚ್ 27 ಆಗಿತ್ತು
UC ಬ್ರೌಸರ್ 12.10.9.1193 ನ ಹೊಸ ಆವೃತ್ತಿಯನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲಾಯಿತು, ಇದು HTTPS ಮೂಲಕ ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿತು: puds.ucweb.com/upgrade/index.xhtml.

ಹೆಚ್ಚುವರಿಯಾಗಿ, "ಫಿಕ್ಸ್" ನಂತರ ಮತ್ತು ಈ ಲೇಖನವನ್ನು ಬರೆಯುವ ಸಮಯದವರೆಗೆ, ಬ್ರೌಸರ್‌ನಲ್ಲಿ PDF ಅನ್ನು ತೆರೆಯಲು ಪ್ರಯತ್ನಿಸುವಾಗ "ಓಹ್, ಏನೋ ತಪ್ಪಾಗಿದೆ!" ಎಂಬ ಪಠ್ಯದೊಂದಿಗೆ ದೋಷ ಸಂದೇಶಕ್ಕೆ ಕಾರಣವಾಗುತ್ತದೆ. PDF ಅನ್ನು ತೆರೆಯಲು ಪ್ರಯತ್ನಿಸುವಾಗ ಸರ್ವರ್‌ಗೆ ವಿನಂತಿಯನ್ನು ಮಾಡಲಾಗಿಲ್ಲ, ಆದರೆ ಬ್ರೌಸರ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಿದಾಗ ವಿನಂತಿಯನ್ನು ಮಾಡಲಾಯಿತು, ಇದು Google Play ನಿಯಮಗಳನ್ನು ಉಲ್ಲಂಘಿಸಿ ಕಾರ್ಯಗತಗೊಳಿಸಬಹುದಾದ ಕೋಡ್ ಅನ್ನು ಡೌನ್‌ಲೋಡ್ ಮಾಡುವ ನಿರಂತರ ಸಾಮರ್ಥ್ಯವನ್ನು ಸೂಚಿಸುತ್ತದೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ