Sonar is using HTTP REST API to control Sonar backend service.
On my first reverse engineering session request destinated to port 10430. Based on previous GameSense-documentation and educated guess the port will be randomized every time the application starts.
Port changed to 10749 after restart - confirmed
C:\ProgramData\SteelSeries\GG contains some interesting files:
- coreProps.json
- GameSense address
- Two unknown endpoints (encrypted)
- encryptedAddress -> Wireshark + premaster secret log
- ggEncryptedAddress -> Wireshark + premaster secret log
- db/database.db
- Nothing useful
- apps/sonar/db/database.db
- Easy alternative to fetch KVP-settings / configs?
Used Wireshark with premaster secret log enabled and ...BOOM!
HTTP GET with TLS v1.2 to ggEncryptedAddress' /subApps responds with stuff we really need.
{
"subApps": {
"engine": {
"name": "engine",
"isEnabled": true,
"isReady": true,
"isRunning": true,
"shouldAutoStart": true,
"isWindowsSupported": true,
"isMacSupported": true,
"toggleViaSettings": false,
"metadata": {
"encryptedWebServerAddress": "127.0.0.1:12261",
"webServerAddress": "127.0.0.1:12260"
},
"secretMetadata": {
"encryptedWebServerAddressCertText": "REMOVED FOR REASONS"
}
},
"sonar": {
"name": "sonar",
"isEnabled": true,
"isReady": false,
"isRunning": true,
"shouldAutoStart": true,
"isWindowsSupported": true,
"isMacSupported": false,
"toggleViaSettings": true,
"metadata": {
"encryptedWebServerAddress": "",
"webServerAddress": "http://localhost:12268"
},
"secretMetadata": {
"encryptedWebServerAddressCertText": ""
}
},
"threeDAT": {
"name": "threeDAT",
"isEnabled": true,
"isReady": false,
"isRunning": false,
"shouldAutoStart": false,
"isWindowsSupported": true,
"isMacSupported": false,
"toggleViaSettings": false,
"metadata": {
"encryptedWebServerAddress": "",
"webServerAddress": ""
},
"secretMetadata": {
"encryptedWebServerAddressCertText": ""
}
}
}
}
Ok, subApps.sonar.metadata.webServerAddress
is what we need.
Certificate is self-signed and valid for a year. Based on certificate validity times I guess it is also regenerated every runtime.
Just to test it again, I ran
> curl https://127.0.0.1:6327/subApps -k
{"subApps": {"engine":{"name":"engine","isEnabled":true,"isReady":true,"isRunning":true,"shouldAutoStart":true,"isWindowsSupported":true,"isMacSupported":true,"toggleViaSettings":false,"metadata":{"encryptedWebServerAddress":"127.0.0.1:12261","webServerAddress":"127.0.0.1:12260"},"secretMetadata":{"encryptedWebServerAddressCertText":"REMOVED FO REASONS"}},"sonar":{"name":"sonar","isEnabled":true,"isReady":true,"isRunning":true,"shouldAutoStart":true,"isWindowsSupported":true,"isMacSupported":false,"toggleViaSettings":true,"metadata":{"encryptedWebServerAddress":"","webServerAddress":"http://localhost:12268"},"secretMetadata":{"encryptedWebServerAddressCertText":""}},"threeDAT":{"name":"threeDAT","isEnabled":true,"isReady":false,"isRunning":false,"shouldAutoStart":false,"isWindowsSupported":true,"isMacSupported":false,"toggleViaSettings":false,"metadata":{"encryptedWebServerAddress":"","webServerAddress":""},"secretMetadata":{"encryptedWebServerAddressCertText":""}}}}
So this is how we get the connection information.
Two subfolders have some raw captures from plain HTTP traffic between Sonar & backend (initializing/
and volumeSettings/
).
These examples can be used to do some basic volume controlling over API.
To capture more just run Wireshark with port filtering
tcp.port == ####
where ####
is port number from subApps.sonar.metadata.webServerAddress
.
Mute/unmute classic-mode Game-channel
curl -X PUT http://127.0.0.1:13108/volumeSettings/classic/game/Mute/true -H "Content-Length: 0" -H "Host: localhost:13108"
curl -X PUT http://127.0.0.1:13108/volumeSettings/classic/game/Mute/false -H "Content-Length: 0" -H "Host: localhost:13108"
Set classic-mode Game-channel volume to 100%
curl -X PUT http://127.0.0.1:13108/volumeSettings/classic/game/Volume/1.00 -H "Content-Length: 0" -H "Host: localhost:13108"
Seems like we are connecting to ggEncryptedAddress
and trusting the certificate there. (I am not 100% sure since code is using somekind of DI with C# and had literally 5 minutes to check out the Sonar's end.)
I started to reverse engineer this stuff for a plugin to Elgato Streamdeck.
Unfortunaly I am already using Elgato Wavelink, so the priority of this project has fallen really low.
I hope by releasing this information someone will see the effort to create the plugin!