Skip to content

Commit 0304f69

Browse files
authored
Add files via upload
1 parent 2a24161 commit 0304f69

File tree

3 files changed

+265
-0
lines changed

3 files changed

+265
-0
lines changed

scripts/emulate_card.sh

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/bin/bash
2+
# Script to emulate an NFC card
3+
4+
source ./scripts/card_utils.sh
5+
6+
# Check if UID was passed
7+
if [ $# -lt 1 ]; then
8+
echo "[!] Usage: $0 <card_uid>"
9+
exit 1
10+
fi
11+
12+
CARD_UID="$1"
13+
CARD_FILE=$(get_card_path "$CARD_UID")
14+
15+
# Verify card exists
16+
if [ ! -f "$CARD_FILE" ]; then
17+
echo "[!] Card not found: $CARD_UID"
18+
echo "[!] Available cards:"
19+
list_saved_cards
20+
exit 1
21+
fi
22+
23+
echo "[*] Preparing to emulate card: $CARD_UID"
24+
echo "[*] Card file: $CARD_FILE"
25+
26+
# Create a temporary JSON settings file for the Android app
27+
TEMP_SETTINGS=$(mktemp)
28+
cat > "$TEMP_SETTINGS" << EOF
29+
{
30+
"uid": "$CARD_UID",
31+
"card_path": "$CARD_FILE",
32+
"auto_response": true
33+
}
34+
EOF
35+
36+
# Copy settings to a location accessible by the app
37+
ANDROID_STORAGE_PATH="/storage/emulated/0/Android/data/com.nfcclone.app/files"
38+
mkdir -p "$ANDROID_STORAGE_PATH"
39+
cp "$TEMP_SETTINGS" "$ANDROID_STORAGE_PATH/current_card.json"
40+
rm "$TEMP_SETTINGS"
41+
42+
# Start the NFC Emulator app
43+
if am start -n com.nfcclone.app/.MainActivity --ez "start_emulation" true; then
44+
echo "[+] NFC emulation service started"
45+
# Notify user
46+
termux-notification --title "NFC Emulation Active" --content "Emulating card: $CARD_UID" --priority high --ongoing
47+
termux-toast "Card emulation started for UID: $CARD_UID"
48+
else
49+
echo "[!] Failed to start NFC emulation service"
50+
echo "[!] Check if the NFC Clone app is installed correctly"
51+
exit 1
52+
fi
53+
54+
echo "[*] Press Ctrl+C to stop emulation"
55+
# Wait for user to cancel
56+
trap 'echo "[*] Stopping emulation"; am broadcast -a com.nfcclone.app.STOP_EMULATION; termux-notification-remove nfc_emulation; echo "[+] Emulation stopped"' INT TERM
57+
read -r -d '' _ </dev/tty

scripts/read_card.py

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env python3
2+
import nfc
3+
import os
4+
import json
5+
import sys
6+
import base64
7+
import time
8+
import binascii
9+
from utils import load_config, get_card_path
10+
11+
def on_connect(tag):
12+
"""Process tag when detected and save its data"""
13+
if tag is None:
14+
print("[!] No tag detected")
15+
return False
16+
17+
try:
18+
# Extract UID
19+
uid = binascii.hexlify(tag.identifier).decode().upper()
20+
21+
# Get tag type info
22+
tag_info = {
23+
"UID": uid,
24+
"Type": str(tag),
25+
"Technologies": [tech for tech in dir(tag) if not tech.startswith('_') and tech != 'identifier'],
26+
"Timestamp": int(time.time()),
27+
}
28+
29+
# Extract NDEF data if available
30+
if hasattr(tag, 'ndef') and tag.ndef:
31+
ndef_records = []
32+
for record in tag.ndef.records:
33+
record_data = {
34+
"type": binascii.hexlify(record.type).decode(),
35+
"name": record.name,
36+
"data": base64.b64encode(record.data).decode('ascii')
37+
}
38+
if hasattr(record, 'text'):
39+
record_data["text"] = record.text
40+
ndef_records.append(record_data)
41+
tag_info["NDEF"] = ndef_records
42+
43+
# For MIFARE Classic, try to read sectors
44+
if hasattr(tag, 'mifare'):
45+
sectors_data = {}
46+
for sector in range(16): # Standard MIFARE Classic has 16 sectors
47+
try:
48+
blocks = tag.mifare.read_blocks(sector * 4, 4)
49+
sectors_data[f"sector_{sector}"] = binascii.hexlify(blocks).decode()
50+
except Exception as e:
51+
sectors_data[f"sector_{sector}"] = f"Error: {str(e)}"
52+
tag_info["MIFARE_Data"] = sectors_data
53+
54+
# Save the card data
55+
config = load_config()
56+
card_file = get_card_path(uid)
57+
os.makedirs(os.path.dirname(card_file), exist_ok=True)
58+
59+
# Save raw dump for advanced analysis
60+
tag_info["RawData"] = {
61+
"Identifier": binascii.hexlify(tag.identifier).decode(),
62+
}
63+
64+
# Add raw dumps of any available data
65+
if hasattr(tag, 'dump'):
66+
raw_dump = tag.dump()
67+
tag_info["RawData"]["Dump"] = raw_dump
68+
69+
# Add custom response template
70+
tag_info["custom_response"] = "9000" # Default success response
71+
72+
with open(card_file, 'w') as f:
73+
json.dump(tag_info, f, indent=4)
74+
75+
print(f"[+] Card saved: {uid}")
76+
print(f"[+] File: {card_file}")
77+
return True
78+
79+
except Exception as e:
80+
print(f"[!] Error processing tag: {str(e)}")
81+
return False
82+
83+
def main():
84+
"""Main function to read an NFC card"""
85+
try:
86+
config = load_config()
87+
reader = config.get('nfc_reader', 'usb')
88+
89+
print("[*] Connecting to NFC reader...")
90+
with nfc.ContactlessFrontend(reader) as clf:
91+
print("[*] Place card on reader...")
92+
93+
# Try to read for up to 30 seconds
94+
clf.connect(rdwr={'on-connect': on_connect, 'beep-on-connect': True})
95+
96+
except KeyboardInterrupt:
97+
print("\n[*] Reading cancelled")
98+
return 1
99+
except Exception as e:
100+
print(f"[!] Error: {str(e)}")
101+
return 1
102+
103+
return 0
104+
105+
if __name__ == "__main__":
106+
sys.exit(main())

scripts/utils.py

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/usr/bin/env python3
2+
import json
3+
import os
4+
import sys
5+
import binascii
6+
7+
def load_config():
8+
"""Load configuration from config.json"""
9+
try:
10+
with open('config.json', 'r') as f:
11+
return json.load(f)
12+
except (FileNotFoundError, json.JSONDecodeError) as e:
13+
print(f"[!] Error loading config: {str(e)}")
14+
return {"card_data_dir": "./cards", "nfc_reader": "usb"}
15+
16+
def get_card_path(uid):
17+
"""Get the path for a card file based on its UID"""
18+
config = load_config()
19+
card_data_dir = config.get('card_data_dir', './cards')
20+
return os.path.join(card_data_dir, f"card_{uid}.json")
21+
22+
def list_saved_cards():
23+
"""List all saved cards"""
24+
config = load_config()
25+
card_data_dir = config.get('card_data_dir', './cards')
26+
27+
if not os.path.exists(card_data_dir):
28+
print(f"[!] Card directory not found: {card_data_dir}")
29+
return []
30+
31+
card_files = [f for f in os.listdir(card_data_dir) if f.startswith('card_') and f.endswith('.json')]
32+
33+
cards = []
34+
for card_file in card_files:
35+
try:
36+
with open(os.path.join(card_data_dir, card_file), 'r') as f:
37+
card_data = json.load(f)
38+
uid = card_data.get('UID', 'Unknown')
39+
card_type = card_data.get('Type', 'Unknown')
40+
timestamp = card_data.get('Timestamp', 0)
41+
42+
cards.append({
43+
'uid': uid,
44+
'type': card_type,
45+
'timestamp': timestamp,
46+
'file': card_file
47+
})
48+
except Exception as e:
49+
print(f"[!] Error reading card file {card_file}: {str(e)}")
50+
51+
return cards
52+
53+
def parse_hex_string(hex_string):
54+
"""Convert a hex string to byte array"""
55+
try:
56+
return binascii.unhexlify(hex_string)
57+
except binascii.Error as e:
58+
print(f"[!] Invalid hex string: {str(e)}")
59+
return None
60+
61+
def analyze_card(uid):
62+
"""Analyze a saved card and print detailed information"""
63+
card_path = get_card_path(uid)
64+
65+
if not os.path.exists(card_path):
66+
print(f"[!] Card not found: {uid}")
67+
return False
68+
69+
try:
70+
with open(card_path, 'r') as f:
71+
card_data = json.load(f)
72+
73+
print(f"\n[*] Card Analysis: {uid}")
74+
print("-" * 50)
75+
print(f"Type: {card_data.get('Type', 'Unknown')}")
76+
77+
if 'Technologies' in card_data:
78+
print("\nSupported Technologies:")
79+
for tech in card_data['Technologies']:
80+
print(f"- {tech}")
81+
82+
if 'NDEF' in card_data:
83+
print("\nNDEF Records:")
84+
for i, record in enumerate(card_data['NDEF']):
85+
print(f"\nRecord {i+1}:")
86+
print(f" Type: {record.get('type', 'Unknown')}")
87+
if 'text' in record:
88+
print(f" Text: {record['text']}")
89+
90+
if 'MIFARE_Data' in card_data:
91+
print("\nMIFARE Sectors:")
92+
for sector, data in card_data['MIFARE_Data'].items():
93+
if not data.startswith('Error'):
94+
print(f" {sector}: {data[:20]}...")
95+
else:
96+
print(f" {sector}: {data}")
97+
98+
return True
99+
100+
except Exception as e:
101+
print(f"[!] Error analyzing card: {str(e)}")
102+
return False

0 commit comments

Comments
 (0)