Closed amaduain closed 1 year ago
Hi,
I don't think I have stumbled upon something called bypassing so I'm not sure what the purpose of this function is. The way I have developed the library is by reverse engineering the mobile app. What is bypassing used for? Is there a way for you to use it in the mobile app? If there is a way in the app, what are the steps I need to take to use bypassing. Sadly, I have no access to the API documentation which makes it a bit harder to develop against :)
No problems, thanks for your input!
Thanks a lot for the answer, the application I'm using is Connect Alarm, and there is an option called bypass that disables one of the sensor, to avoid false positives. Which application are you reversing? Maybe I can take a look too. Anyway, feel free to close it, if I found anything I will tell you. Best regards!
Hi, I'm using Connect Alarm as well, but the reason I have not implemented it might be that I can't see that option in my alarm system. If I click Devices and select a sensor (a "Contact" for example), the only option that is available for me is "Rename". Can you see other options here? Please let me know if you figure it out.
In my case, some sensors can by bypassed and renamed:
Also, any good source / training for reverse engineering apps?
It's probably a setting in the alarm panel itself or simply that my sensors doesn't have that feature.
If you are comfortable with Python and know how to setup a reverse proxy with a Let's Encrypt certificate you can try my dummy API server that I've built.
The way I have developed this library is by implementing a Python Flask application that responds to the API requests that the Connect Alarm app sends.
The workflow is something like this:
visonicalarm
library that sends that same information to the real API server and now I can see what the response from the real server looks like.Initially I tried using applications like Proxyman and Burp Suite, but this approach didn't work since the Connect Alarm app require a valid SSL certificate for its connections.
I hope this made it a bit more clear and let me know if you would like to try my Python Flask API server to find out which endpoint the Bypass button calls on the API server.
I don't think I have any good training material for you more than the apps I mentioned earlier and perhaps to check out my Python server script and simply learn by doing :)
Thanks a lot for the hints! I have no problem with python or let's encrypt I use them on other projects, can you share your api server? Once I got the info I will share it with you of course! I'm using your actual libraries on the Home Assistant (I got a script to translate from your scripts to MQTT).
No problems! :) You can get the server script here:
Get up and running in a few steps.
Great to hear that the library is being used!
Happy hunting π
Thanks for the heads up, it was nice to have a way to reverse engineer the app, super cool.
So, what I did is create the certs for the flask server, once you have them you can skip the reverse proxy if you have a local dns (I got Pihole) and route it to the fake server. So in the server code you can add this:
import ssl ... ... if __name__ == '__main__': context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) context.load_cert_chain("fullchain2.pem","privkey2.pem") app.run(host='0.0.0.0', port=443, ssl_context=context)
After that I was able to emulate the zone bypassing:
URL : /rest_api/9.0/set_bypass_zone
Action: Post
Enable bypassing payload json:
{ "zone": 5, "set": true }
Disable bypassing json:
{ "zone": 5, "set": false }
Zone id has to be one that you have defined on the panel :-D
Don't know if you plan to add it to your code, if so, let me know if you need anything else.
Thanks! It has been very helpful in developing the library. But I would call it an "ugly hack" rather than "super cool" π
Also, thanks for the tip on using the certificate with Flask, I didn't know you could do that. I will definitely use this approach in the future, since I seem to be using the Flask server a lot in different projects. Much appreciated! ππ»
Sure, I'm already working on adding this to the library, so I will need some help testing it soon π
One thing that would be nice if you could check is what the output of the following call is on your system. It will print the raw output from the API server for the get_panel_info
endpoint:
print(alarm.api.get_panel_info())
What I'm interested in is the value of the bypass_mode
key value pair on your system. On my alarm system it is set to 'bypass_mode': 'no_bypass'
, which is probably why I can't see this option in the app. I suspect this would make it possible to trick the app to show the Bypass button for some dummy sensors.
There you go: { "serial": "XXXXXXXXX", "model": "XXXXXXX", "manufacturer": "DSC", "current_user": "master_user", "state_sets": { "all": [ { "name": "AWAY", "settable": true, "options": [ "NOENTRY" ], "statuses": [ "EXIT", "ENTRY", "HOLD" ], "transitions": [ "DISARM", "STAY" ] }, { "name": "NIGHT", "settable": true, "options": [], "statuses": [ "EXIT", "ENTRY", "HOLD" ], "transitions": [ "DISARM", "AWAY", "STAY" ] }, { "name": "STAY", "settable": true, "options": [ "NOENTRY", "NOEXIT" ], "statuses": [ "EXIT", "ENTRY", "HOLD" ], "transitions": [ "DISARM", "AWAY", "NIGHT" ] }, { "name": "DISARM", "settable": true, "options": [], "statuses": [], "transitions": [ "DISARM", "STAY", "NIGHT", "AWAY" ] }, { "name": "PROGRAMMING", "settable": false, "options": [], "statuses": [], "transitions": [] } ] }, "partitions": [ { "id": 1, "active": true, "exit_delay_time": 45, "state_set": "all", "name": "ParticiΓ³n 1" }, { "id": 2, "active": false, "exit_delay_time": 120, "state_set": "all", "name": "ParticiΓ³n 2" }, { "id": -1, "active": true, "exit_delay_time": 0, "state_set": "all", "name": "ALL" } ],
El mar, 13 dic 2022 a las 18:22, mikael @.***>) escribiΓ³:
Thanks! It has been very helpful in developing the library. But I would call it an "ugly hack" rather than "super cool" π
Also, thanks for the tip on using the certificate with Flask, I didn't know you could do that. I will definitely use this approach in the future, since I seem to be using the Flask server a lot in different projects. Much appreciated! ππ»
Sure, I'm already working on adding this to the library, so I will need some help testing it soon π
One thing that would be nice if you could check is what the output of the following call is on your system. It will print the raw output from the API server for the get_panel_info endpoint:
print(alarm.api.get_panel_info())
What I'm interested in is the value of the bypass_mode key value pair on your system. On my alarm system it is set to 'bypass_mode': 'no_bypass', which is probably why I can't see this option in the app. I suspect this would make it possible to trick the app to show the Bypass button for some dummy sensors.
β Reply to this email directly, view it on GitHub https://github.com/bitcanon/visonicalarm/issues/16#issuecomment-1349151970, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC5Z7SBCI7FBZ7MKH2LTPGLWNCWFFANCNFSM6AAAAAARXC3RPE . You are receiving this because you authored the thread.Message ID: @.***>
Thanks for the output, sadly I wasn't able to get the Bypass button appear in the app.
But, to the good news. I have pushed the code for set_bypass_zone()
to GitHub now so you should be able to call:
alarm.set_bypass_zone(5, True)
My guess is that the API will return a token that we can poll to check if the operation succeeded.
I haven't pushed the changes to PyPI yet so you have to clone the GitHub repository and try it that way to see if it works first.
Let me know how it goes or if any weird messages appear (most likely) π
I will test it tomorrow and let you know. For your testing I can sanitize the whole data set and send it to you. Seems there is relationship between the panel, and the devices. It didn't allow me to bypass till I add all data.
On Tue, Dec 13, 2022, 21:22 mikael @.***> wrote:
Thanks for the output, sadly I wasn't able to get the Bypass button appear in the app.
But, to the good news. I have pushed the code for set_bypass_zone() to GitHub now so you should be able to call:
alarm.set_bypass_zone(5, True)
My guess is that the API will return a token that we can poll to check if the operation succeeded.
I haven't pushed the changes to PyPI yet so you have to clone the GitHub repository and try it that way to see if it works first.
Let me know how it goes or if any weird messages appear (most likely) π
β Reply to this email directly, view it on GitHub https://github.com/bitcanon/visonicalarm/issues/16#issuecomment-1349637155, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC5Z7SGAYY7KLJCEGNGD2Q3WNDLJHANCNFSM6AAAAAARXC3RPE . You are receiving this because you authored the thread.Message ID: @.***>
You can find your server.py with the valid payloads for bypassing here: https://github.com/amaduain/visonic_findings/blob/main/server.py
Thanks for the output, sadly I wasn't able to get the Bypass button appear in the app.
But, to the good news. I have pushed the code for
set_bypass_zone()
to GitHub now so you should be able to call:alarm.set_bypass_zone(5, True)
My guess is that the API will return a token that we can poll to check if the operation succeeded.
I haven't pushed the changes to PyPI yet so you have to clone the GitHub repository and try it that way to see if it works first.
Let me know how it goes or if any weird messages appear (most likely) π
Yep, the return is something like:
{
"process_token": "d32aa971-4ed4-4674-8dd0-ea6b5263f10b"
}
You can find your server.py with the valid payloads for bypassing here: https://github.com/amaduain/visonic_findings/blob/main/server.py
Thanks, with your code I could figure out that each device that support bypassing also has a trait called bypass:
{
...
"traits": {
"rssi": {},
"bypass": {
"enabled": false
},
"soak": {
"enabled": false
},
"rarely_used": {
"enabled": false
}
},
...
},
This attribute will have to be added to the Device class.
I will test it tomorrow and let you know. For your testing I can sanitize the whole data set and send it to you. Seems there is relationship between the panel, and the devices. It didn't allow me to bypass till I add all data.
I have now added support for bypassing a device in the GitHub repository, so you should now be able to check the bypass status of a device like so:
print("Gettings Devices...")
for device in alarm.get_devices():
print(f"Device: {device.id} - Bypassed: {device.bypass}")
Output:
Gettings Devices...
<output truncated>
Device: 1234004 - Bypassed: False
Device: 1234005 - Bypassed: True
Device: 1234006 - Bypassed: False
<output truncated>
And like previously mentioned, bypass a device with:
alarm.set_bypass_zone(5, True)
If your testing goes smoothly I can push to PyPI as well π
Nice, I have been testing in my system today and it is working. Only issue I had it was with the GSM device, which is not reporting the signal so the get_devices was failing on line 181 alarm.py so I added a check as a workaround:
elif device['device_type'] == 'GSM':
if 'signal_level' in device['traits'].keys():
signal_level=device['traits']['signal_level']['level']
else:
signal_level=0
contact_device = GSMDevice(
device_number=device['device_number'],
device_type=device['device_type'],
enrollment_id=device['enrollment_id'],
id=device['id'],
name=device['name'],
partitions=device['partitions'],
preenroll=device['preenroll'],
removable=device['removable'],
renamable=device['renamable'],
subtype=device['subtype'],
warnings=device['warnings'],
zone_type=device['zone_type'],
signal_level=signal_level
)
If you have time maybe you can check the inputs before assign them, traits seems to be quite tricky.
Shall you close this issue?
Nice, I have been testing in my system today and it is working. Only issue I had it was with the GSM device, which is not reporting the signal so the get_devices was failing on line 181 alarm.py so I added a check as a workaround:
elif device['device_type'] == 'GSM': if 'signal_level' in device['traits'].keys(): signal_level=device['traits']['signal_level']['level'] else: signal_level=0 contact_device = GSMDevice( device_number=device['device_number'], device_type=device['device_type'], enrollment_id=device['enrollment_id'], id=device['id'], name=device['name'], partitions=device['partitions'], preenroll=device['preenroll'], removable=device['removable'], renamable=device['renamable'], subtype=device['subtype'], warnings=device['warnings'], zone_type=device['zone_type'], signal_level=signal_level )
If you have time maybe you can check the inputs before assign them, traits seems to be quite tricky.
Shall you close this issue?
Great, thanks for all of your help and support! Much appreciated π
Version 3.10.0 of the library is now available for installation via PyPI/pip
, and I also fixed the bug you found regarding the signal_level
trait (created issue #18 for this). Traits sure are quite tricky to predict since they seem to be different on different systems.
I will close the issue for now. The new version seem to be working fine, let me know otherwise.
I know this is a closed issue but found the info here really helpful in understanding the rest api. There are a few endpoints we could add to the api (which I will do a PR for soon) but wanted to a) thanks for the effort on this and b) contribute some enhancement I did on your server.py script. This gist server.py
Instead of having to modify it with each endpoint you discover, it is actually forwarding the request to the true endpoint servers, getting the response, and passing back to the client. This is then very easy to now use the app to see the resp api request and response. Hope it helps!
Hi, thanks a lot for your improvement to the server.py script. I have already given it a go and it will make development much easier in the future. Great work and thanks again!ππ»
Hi all, thanks for the great work, I was guessing if you already thought on supporting bypassing, I've been trying to find the api for bypassing, but so far no luck. Do you have any details on the api?
Thanks!