Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Samsung Smart Tag #65

Open
trep-kalkyl opened this issue Oct 18, 2024 · 10 comments
Open

Implement Samsung Smart Tag #65

trep-kalkyl opened this issue Oct 18, 2024 · 10 comments

Comments

@trep-kalkyl
Copy link

Hi everyone,

Have you seen this repo?
Samsung SmartTag Hack

Samsung holds a significant market share in the tracker space, and this could be interesting for anyone looking into.

@trep-kalkyl
Copy link
Author

https://arxiv.org/pdf/2210.14702

@biemster
Copy link
Owner

I remember seeing that repo yes, but besides from the very impressive rom dump there is no more info there (as you already mentioned there). The paper on the other hand has a lot of info, and I did not see that one yet. I'll have a look soon.

@biemster
Copy link
Owner

@KieronQuinn does your work on the Samsung tags also include creating fake tags, or is it focused on using official tags on non-samsung androids?

@KieronQuinn
Copy link

@KieronQuinn does your work on the Samsung tags also include creating fake tags, or is it focused on using official tags on non-samsung androids?

Only official tags on non-Samsung. I'm not sure a similar setup to Open Haystack is even possible with Samsung's network, the Bluetooth communication is a lot more complex and would need replicating.

@KieronQuinn
Copy link

KieronQuinn commented Nov 29, 2024

Got a moment to spare so some more detail on the above:

  • The vast majority of calls to Samsung's API can be done on an account with no FME (find my everything) phone registered. Most of SmartThings' Tag functionality is actually functional on non-Samsung devices, with little modification. The FMD (Samsung's find my device) app has far more OneUI-specific calls, which is what I've needed to replace.
    • Registering a phone and uploading locations for other people's Tags require a certificate that has to have been generated on a real Samsung device. It uses the on-device attestation (SAK) to verify this. While I was able to extract a generated certificate and sign my own requests, the certificate could be revoked at any point so it would be pointless to share.
    • Registering a Tag does not require this certificate, nor does sending location updates for your own Tags
    • Setting and changing the offline location encryption PIN requires a Samsung FME phone on the account, but only its ID, so it can be spoofed. Simply having an old Samsung phone signed in to the account is enough to enable this functionality (it doesn't even need to be on)
  • There are signs that Samsung maybe intended for Tags to be available on non-Samsung phones (the biggest of which is the enum which differentiates between Samsung phone or tablet for who reported a location update also including entries for non-Samsung phone and non-Samsung tablet)
  • All BLE calls are encrypted, but the SmartThings app exposes a service (when given the right permissions) to access the Tag from another app. SmartThings then handles all the encryption and Bluetooth calls for you. I haven't needed to reverse the BLE encryption for this reason.
  • It's possible to use UWB with the Tags, but only with lower-level access to the UWB service (Shizuku allows this). The AndroidX implementation is not currently compatible (I wonder if this is what the delay is with Google's Find Device app too?)
  • As with other implementations, everything non-owner devices need most of the time is in the service data advertisement, but the BLE service has calls to ring and enable UWB locating for non-owners too. Unsure if these are also encrypted, I've not yet checked since Samsung's unknown tag scanner doesn't seem to work at all on my Pixels.

Like I said on the linked ticket, I plan to include extensive API documentation with my app once it's released. The app won't require root, but will come in the form of a modified SmartThings APK and a companion app (with the option of using the official SmartThings build and Xposed for rooted users)

@biemster
Copy link
Owner

I'm very much looking forward to the docs! My focus is on the BLE advertisement, I'll try to get that info from the paper linked a couple comments up.

@KieronQuinn
Copy link

I do have a list of characteristic IDs and what they're for, as well as the output of an endpoint which gives a list of "commands" that can be made on them if that'd be useful to you. I think it includes which are encrypted too.

@biemster
Copy link
Owner

I do have a list of characteristic IDs and what they're for, as well as the output of an endpoint which gives a list of "commands" that can be made on them if that'd be useful to you. I think it includes which are encrypted too.

Am I understanding correctly that the FD5A uuid in the advertisement is all a lost tag needs to transmit?

@KieronQuinn
Copy link

KieronQuinn commented Dec 1, 2024

I do have a list of characteristic IDs and what they're for, as well as the output of an endpoint which gives a list of "commands" that can be made on them if that'd be useful to you. I think it includes which are encrypted too.

Am I understanding correctly that the FD5A uuid in the advertisement is all a lost tag needs to transmit?

As far as I've been able to find, the only difference between tags that are connected to a device (not lost) and not (potentially lost) is a single flag in the advertisement data on that service: the tag state. Here's two decoded service datas:

Tag connected to phone:

TagData(
	version=1, 
	advertisingType=0, 
	tagState=5, 
	privacyId=*removed*, 
	regionId=11, 
	batteryLevel=3, 
	uwbFlag=1, 
	encryptionFlag=0, 
	motionDetection=0, 
	activityTrackingMode=false, 
	signature=*removed*, 
	reserved=[0, 0], 
	agingCounter=154849
)

Tag not connected to phone:

TagData(
	version=1, 
	advertisingType=0, 
	tagState=4, 
	privacyId=*removed*, 
	regionId=11, 
	batteryLevel=3, 
	uwbFlag=1, 
	encryptionFlag=0, 
	motionDetection=0, 
	activityTrackingMode=false, 
	signature=*removed*, 
	reserved=[0, 0], 
	agingCounter=154849
)

And here's the Kotlin code for decoding these items:

val version = (serviceData[0].toInt() and 0xF0) shr 4
val tagStateAndAdvertisementType = serviceData[0].toInt() and 15
val tagState = tagStateAndAdvertisementType and 7
val advertisementType = tagStateAndAdvertisementType shr 3 and 1
val agingCounter = serviceData[1].toInt() and 0xFF or
		((serviceData[2].toInt() and 0xFF) shl 8) or
		((serviceData[3].toInt() and 0xFF) shl 16)
val privacyId = ByteArray(8).apply {
	serviceData.copyInto(this, startIndex = 4, endIndex = 12)
}.toHexString()
val regionId = (serviceData[12].toInt() and 0xF0) shr 4
val flags = serviceData[12].toInt() and 15
val uwbFlag = flags shr 2 and 1
val encryptionFlag = flags shr 3 and 1
val batteryLevel = flags and 3
val motionDetection = 1 and ((serviceData[13].toInt() and 0xFF) shr 7)
val reserved = ByteArray(2).apply {
	serviceData.copyInto(this, startIndex = 14, endIndex = 16)
}
val activityTrackingMode = (serviceData[15].toInt() and 1) != 0
val signature = ByteArray(4).apply {
	serviceData.copyInto(this, startIndex = 16, endIndex = 20)
}

I'm just checking now to see if there's an enum in the SmartThings APK for what the tag states correspond to, but obviously 5 is connected and 4 is disconnected.

Edit: There doesn't seem to be one, it's always checking against just integers. Most likely it's been optimised out of the APK.

@KieronQuinn
Copy link

KieronQuinn commented Dec 1, 2024

Here's the full list of characteristics for a SmartTag2 from the https://client.smartthings.com/miniature/configure?profileId=*removed* endpoint: characteristics.json

And my own table of them that was built before I found that endpoint, based on what they were used for in the APK:

eedd5e73-6aa8-4673-8219-398a489da87c (Encryption/Auth Service)

Characteristic Modes Configuration Use
50f98bfd-158c-4efa-add4-0a70c2f5df5d R, W   Cipher
a12be31c-5b38-4773-9b9d-3d5735233a7c I, W 0x2902 Nonce
4ebe81f6-b952-465e-9ece-5ca39d4e8955 I, W 0x2902 Encrypted Nonce

0000fd5a-0000-1000-8000-00805f9b34f (Control Service)

Characteristic Modes Configuration Use
dee30001-182d-5496-b1ad-14f216324184 I, R, W 0x2902 Alarm
dee30002-182d-5496-b1ad-14f216324184 N, R, W 0x2902 Audio Volume
dee30003-182d-5496-b1ad-14f216324184 I, W 0x2902 Tag Button
dee30004-182d-5496-b1ad-14f216324184 I, R, W 0x2902 Battery
dee30005-182d-5496-b1ad-14f216324184 I, W 0x2902 Time
dee30006-182d-5496-b1ad-14f216324184 W   Factory Reset
dee30007-182d-5496-b1ad-14f216324184 R, W   E2E Encryption flag
dee30008-182d-5496-b1ad-14f216324184 R, W   UWB Ranging flag
dee30009-182d-5496-b1ad-14f216324184 I, W 0x2902 UWB Parameter
dee3000a-182d-5496-b1ad-14f216324184 R, W   Ringtone
dee3000b-182d-5496-b1ad-14f216324184 R   Firmware Version
dee3000c-182d-5496-b1ad-14f216324184 I, R, WNR 0x2902 Firmware Transfer
dee3000d-182d-5496-b1ad-14f216324184 R, W   Bond
dee3000e-182d-5496-b1ad-14f216324184 R   Spec Version
dee3000f-182d-5496-b1ad-14f216324184 I, W 0x2902 Bond
dee3001a-182d-5496-b1ad-14f216324184 I, W 0x2902 Private ID Pool Size
dee3001d-182d-5496-b1ad-14f216324184 I, R, W 0x2902 Activity Tracker
dee30025-182d-5496-b1ad-14f216324184 R, W   TxPower
dee3001f-182d-5496-b1ad-14f216324184 N, R, W 0x2902 Button Sound Volume
dee30030-182d-5496-b1ad-14f216324184 I, W 0x2902 Debug Flag
dee3001b-182d-5496-b1ad-14f216324184 R, W   Lost Message URL
dee3001c-182d-5496-b1ad-14f216324184 I, R 0x2902 Motion Detection
dee30041-182d-5496-b1ad-14f216324184 N, W 0x2902 Pet Activity

a0e78d39-75b5-4182-8fdc-c4b7365c9062 (?)

Characteristic Modes Configuration Use
040c6507-f08a-f7c2-abea-6382ee250230 N, WNR 0x2902 ?
cb91b0d6-3080-dbfb-876b-407db045e52b I, R, W 0x2902 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants