Skip to content

findmyevil

7h30th3r0n3 edited this page Nov 16, 2025 · 2 revisions

🧲 FindMyEvil Advertiser

A multi‑tag Apple Find My (OpenHaystack) advertiser.
Broadcasts valid or lab‑generated FindMy advert keys with realistic Apple Manufacturer Data,
rotating MAC addresses, SD‑stored keys, dynamic intervals, and multi‑slot tag cycling.
Fully compatible with OpenHaystack, FindMy (biemster), and Apple’s offline finding protocol.

Can be used standalone on any esp32.

Setup of keys at the end


⚠️ Legal & Ethical Notice

Use only with keys you own and control.
This module does not break Apple encryption and does not reveal identities.
It merely broadcasts public BLE frames that real Find My devices would emit.


💡 What This Module Does

Capabilities

  • Broadcasts valid FindMy-compliant raw BLE advertisements.
  • Supports two modes:
    • FindMy mode (SD keys) → load 28‑byte adv_keys from /evil/FindMyEvil_keys.txt
    • LAB mode → generate pseudo‑P224 keys for testing
  • Maintains up to 20 simultaneous tags
  • Auto‑rotates MAC addresses derived deterministically from adv_key
  • Multi‑tag slot scheduler (round‑robin)
  • Adjustable BLE advertising interval (200–10000 ms)
  • Dynamic key rotation (LAB mode only)
  • UI with:
    • ON/OFF state
    • Battery display
    • Interval, Slot time, Mode, Tag count
    • Current tag preview (MAC + first 8 bytes of key)
  • SD card persistence for long‑term tracking experiments
  • Optimized non‑blocking advertising control

🚀 Quick Start (Device UI Flow)

1. Launch the module

Inside the main menu, choose FindMyEvil Advertiser.

The screen shows:

  • Interval
  • Slot duration
  • Mode (unset)
  • Tag count
  • Key/MAC preview (empty until tags exist)

2. Controls

Key Action
SPACE Toggle TX ON/OFF
B Dim screen / standby / restore
N Add new LAB tag (FindMy mode disables)
R Rotate adv_key of current tag (LAB only)
+ / - Increase/decrease advertising interval
Backspace or Enter Exit module

3. Choosing the mode (first activation)

When pressing SPACE for the first time:

  • Device asks: Use keys from SD?
    • YES → Load /evil/FindMyEvil_keys.txt
    • NO → LAB mode (auto‑generate keys)

If SD file is empty / invalid → fallback to LAB mode.

4. Starting transmission

After choosing a mode:

  • First tag is created/loaded
  • Press SPACE → TX ON
  • Advertising begins immediately (Apple Manufacturer Data)

5. Multi‑tag cycling

If more than one tag:

  • Device cycles every fmSlotMs (default 100ms)
  • Each tag gets its own MAC + raw advertisement

🧩 FindMy-Compatible Raw Advertisement (Apple Offline Finding)

The module constructs a 31‑byte Apple Manufacturer Frame:

[0]   0x1E              Length
[1]   0xFF              Type: Manufacturer Specific
[2]   0x4C 0x00         Apple Company ID
[4]   0x12              Offline Finding type
[5]   0x19              Payload length (25)
[6]   State byte (0x00)
[7-28] 22 bytes of adv_key[6..27]
[29] adv_key[0] >> 6
[30] Hint/counter (0x00)

Total: 31 bytes, identical structure to genuine FindMy broadcasts.

MAC Derivation

mac[0] = (adv_key[0] & 0x3F) | 0xC0   # static random
mac[1..5] = adv_key[1..5]

Matches Apple’s approach for AirTags / FindMy beacons.


🗂️ SD Card Structure

/evil/FindMyEvil_keys.txt

Each line = 28‑byte HEX key, any separators allowed.

Example valid formats:

DE AD BE EF 00 11 22 33 [...] DE F0
DEADBEEF00112233[...]DEF0
de ad be ef 00 [...]

Up to 20 keys are parsed.

On load, each line produces:

  • adv_key[]
  • derived MAC[]
  • tag entry in fmTags[]

🖥️ On-Device UI Overview

Header

  • Title: FindMyEvil
  • TX state: ON/OFF
  • Battery percentage

Body (Top)

  • Interval (ms)
  • Slot time (ms)
  • Mode (FindMy Keys / LAB Random)
  • Tag count

Body (Bottom)

  • First 8 bytes of adv_key
  • Corresponding MAC
  • Keybinds legend

🔧 Key Generation (Full Pipeline)

See included README block below, which is reproduced in full.

Summary

  1. Generate .keys via FindMy tools
  2. Convert adv_key (Base64 → 28 bytes HEX)
  3. Store in /evil/FindMyEvil_keys.txt
  4. Device broadcasts them as real FindMy beacons
  5. Apple’s network picks them up
  6. Use request_reports.py to download reports
  7. Parse reports.db for positions


FindMy DIY Setup (Key Generation + Location Retrieval)

The following section is the complete Find My DIY Setup documentation that accompanies this module: This guide walks you through setting up the full Find My DIY stack:

  1. Generate Find My / OpenHaystack-compatible keys (.keys files).
  2. Convert Base64 keys to HEX for SD firmware (EvilCardputer / ESP32).
  3. Run an Anisette server (emulating an Apple device) via Docker.
  4. Query the Apple Find My network using request_reports.py with your iCloud account.
  5. Read and process results from the reports.db SQLite database.

⚠️ Legal disclaimer:

  • Use only your own Apple ID and your own devices.
  • Respect privacy and local regulations.
  • Never share your private keys, Apple ID, password, or .keys files publicly.

1. Requirements

Hardware

  • A computer running Linux (tested on Debian/Kali/Ubuntu) or macOS.
  • (Optional) BLE devices (ESP32, M5, EvilCardputer) broadcasting the generated keys.

Software

For Debian/Ubuntu/Kali:

sudo apt update
sudo apt install -y \
  python3 python3-venv python3-pip \
  git sqlite3 docker.io curl

sudo systemctl enable --now docker

On macOS: install Homebrew, then install python3, git, sqlite3, and Docker Desktop.


2. Folder Setup

Work in a dedicated directory:

mkdir FindMyLab
cd FindMyLab

2.1 Clone the FindMy repository

git clone https://github.com/biemster/FindMy
cd FindMy

Expected structure:

FindMy/
  ├─ ESP32/
  ├─ BlueZ/
  ├─ generate_keys.py
  ├─ request_reports.py
  ├─ pypush_gsa_icloud.py
  ├─ auth.json        (created later)
  ├─ *.keys           (created later)
  └─ reports.db       (created later)

2.2 Create a Python virtual environment

python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip

Install dependencies:

pip install requests pbkdf2 pycryptodome

Re-activate the venv in new sessions:

cd FindMy
source .venv/bin/activate

3. Create the SQLite Database

sqlite3 reports.db "CREATE TABLE reports (
  id_short TEXT,
  timestamp INTEGER,
  datePublished INTEGER,
  payload TEXT,
  id TEXT,
  statusCode INTEGER,
  PRIMARY KEY(id_short, timestamp)
);"

Verify:

sqlite3 reports.db '.tables'
# Should show: reports

4. Install and Run the Anisette Server (Docker)

git clone https://github.com/Dadoum/anisette-v3-server
cd anisette-v3-server
docker build -t anisette-server .
docker run -d --name anisette -p 6969:6969 anisette-server

Check if it’s running:

docker ps

You should see a container exposing port 6969.

Test it:

curl http://localhost:6969

You should see JSON output with fields like X-Apple-I-Client-Time and X-Apple-I-Locale.


5. Generate Find My Keys

python3 generate_keys.py

You’ll get .keys files such as:

tag01.keys
tag02.keys

Example content:

Private key: FAKEPRIVATEKEYBASE64EXAMPLE==
Advertisement key: FAKEADVB64KEYEXAMPLE==
Hashed adv key: FAKEHASHEDKEY1234567890=
  • Private key: for decryption.
  • Advertisement key: broadcast key (base64 → 28 bytes adv_key for firmware).
  • Hashed adv key: short ID used in database and logs.

6 Convert Base64 → HEX (for SD usage on Evil / ESP32 firmware)

Example:

Advertisement key: FAKEADVB64KEYEXAMPLE==

➤ Step 1. Decode Base64 to raw bytes (28 bytes)

python3 - <<'PY'
import base64
b64 = "FAKEADVB64KEYEXAMPLE=="
raw = base64.b64decode(b64 + '==')
print(" ".join(f"{x:02X}" for x in raw))
print(f"Length: {len(raw)} bytes")
PY

Example output (fake data):

DE AD BE EF 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 12 34 56 78 9A BC DE F0
Length: 28 bytes

➤ Step 2. Place this HEX key into your SD card file

Create /evil/FindMyEvil_keys.txt on your SD card:

DE AD BE EF 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 12 34 56 78 9A BC DE F0

or compact form:

DEADBEEF00112233445566778899AABBCCDDEEFF123456789ABCDEFA0

➤ Step 3. Firmware side

Console output example:

[FM-TX] SD tag #0 KEY=DEADBEEF... MAC=C0:11:22:33:44:55

7. Fetch Reports from the Find My Network

python3 request_reports.py

Output example:

pyprovision is not installed, querying http://localhost:6969 for an anisette server
200: 3 reports received.
found: ['tag01']
missing: ['tag02']

If sqlite3.OperationalError: no such table: reports, recreate the table.


8. Read and Process Reports

sqlite3 reports.db "SELECT id_short, datetime(timestamp, 'unixepoch'), substr(payload,1,80) FROM reports;"

Or export:

sqlite3 reports.db "SELECT payload FROM reports;" > reports.json

Python helper:

#!/usr/bin/env python3
import sqlite3, json

conn = sqlite3.connect("reports.db")
cur = conn.cursor()
for (payload,) in cur.execute("SELECT payload FROM reports ORDER BY timestamp DESC"):
    try:
        data = json.loads(payload)
    except:
        continue
    lat, lon = data.get("lat"), data.get("lon")
    print(f"{data.get('id_short')}{lat}, {lon}")
conn.close()

9. Generate a map with FindMyMap python script

You can now use the reports.db and something.keys to generate a maps with last position.


✅ Summary

Step Description
1 Clone FindMy + anisette-v3-server
2 Setup Python virtualenv
3 Create SQLite reports.db
4 Build and run Docker anisette server
5 Generate .keys files
6 Convert Base64 → HEX for SD
7 Run request_reports.py to query iCloud
8 View positions in reports.db
9 Generate the map with FindMyMap python script

Result: Full DIY Find My pipeline → key generation → BLE broadcast → Apple network pickup → local decryption → SQLite storage → map visualization.

Clone this wiki locally