Warning etc etc, use with caution... Might contain bugs :)
#!/usr/bin/python3.5
import sys
if len(sys.argv) <2:
print( "usage:" )
print(" " + sys.argv[0] + " [.PCK file]", "[Folder-prefix]" )
print( " " )
exit()
import os
from binascii import crc32
from struct import unpack
#get unpack file
src_file_path = sys.argv[1]
#read file length
src_file_size = os.path.getsize(src_file_path)
#read file
b = bytearray(open(src_file_path, 'rb').read())
# crude bytearray to String converter
def toStr(b):
return "".join(["%c"%i for i in b]).strip("\x00")
# convert 4 bytes to int
def word2int(w):
return unpack("<I", w)[0]
# crude filetable parser
def getHeader(b, datastart):
beginstart=b.find(63) #"?"
filename = toStr(b[0:beginstart]).replace("\\","/")
beginstart+=1
beginlength=b.find(63,beginstart) #"?"
start = int(b[beginstart:beginlength],16) + datastart + 4
beginlength+=1
length = int(b[beginlength:beginlength+10],16)
return {
"filename": filename,
"start" : start,
"length" : length,
}
#crude way to create nonexisting directories
def checkCreateDir(filename):
if not os.path.exists(os.path.dirname(filename)):
try:
os.makedirs(os.path.dirname(filename))
except OSError as exc: # Guard against race condition
if exc.errno != errno.EEXIST:
raise
def save(filename, data):
checkCreateDir(prefix + "/" + filename) #create missing directories
print ("writing %s\t (%d bytes)"%(filename,len(data)))
open(prefix + "/" + filename, 'wb').write(data)
## Start decoding
print("Unknown byte 0:\t"+ str(b[0]))
print("Unknown byte 1:\t"+ str(b[1]))
print("Unknown byte 2:\t"+ str(b[2]))
print("Unknown byte 3:\t"+ str(b[3]))
prefix = sys.argv[2] if len(sys.argv)>=3 else "."
headerstart_token = bytearray((int(62), int(0x0d), int(0x0a)))
headerstart = b.find(headerstart_token,0)+3
pos=headerstart
datastart_token = bytearray((int(0x0d), int(0x0a), int(0x0d), int(0x0a)))
datastart = b.find(datastart_token,0)
print("header end: \t"+ str(datastart))
nHeaders = b.count(int(13),4,datastart)
print("# files \t: "+str(nHeaders))
# crude way to parse the directory table
files = []
print ("found %i files\n"%nHeaders)
token = bytearray((int(0x0d), int(0x0a)))
for i in range(nHeaders):
pos2=b.find(token,pos)
h = getHeader(b[pos:pos2], datastart)
files.append(h)
print(h)
pos = int(pos2)+2
for h in files:
bFile = b[h["start"]:h["start"]+h["length"]]
#write stripped file
save(h["filename"],bFile)
print("Done!")
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
The unpacker is also here https://github.com/Damme/LandLord/blob/master/unpack_pck.py
But I unpacked fw v2.66 with the code from this page, it works great!
$ python --version
Python 3.7.10
$ db504_v2.66_extracted % python ../../unpacker.py ../db504_v2.66_30-10-2017.pck
Unknown byte 0: 197
Unknown byte 1: 24
Unknown byte 2: 200
Unknown byte 3: 67
header end: 2418
# files : 50
found 50 files
{'filename': 'db504 v2.66 30-10-2017.bin', 'start': 2422, 'length': 363076}
{'filename': 'web_files/debugPage.html', 'start': 365498, 'length': 23187}
{'filename': 'web_files/dummy.html', 'start': 388685, 'length': 2}
{'filename': 'web_files/index.htm', 'start': 388687, 'length': 13929}
{'filename': 'web_files/index.html', 'start': 402616, 'length': 13929}
{'filename': 'web_files/log.html', 'start': 416545, 'length': 4116}
{'filename': 'web_files/manifest.json', 'start': 420661, 'length': 667}
{'filename': 'web_files/css/style.css', 'start': 421328, 'length': 10653}
{'filename': 'web_files/css/styleLog.css', 'start': 431981, 'length': 13279}
{'filename': 'web_files/img/android-icon-1x.png', 'start': 445260, 'length': 1663}
{'filename': 'web_files/img/android-icon-2x.png', 'start': 446923, 'length': 2349}
{'filename': 'web_files/img/android-icon-3x.png', 'start': 449272, 'length': 3098}
{'filename': 'web_files/img/android-icon-4x.png', 'start': 452370, 'length': 4108}
{'filename': 'web_files/img/back-highlight.png', 'start': 456478, 'length': 1344}
{'filename': 'web_files/img/back.png', 'start': 457822, 'length': 1345}
{'filename': 'web_files/img/close.png', 'start': 459167, 'length': 1038}
{'filename': 'web_files/img/ios-icon-58@2x.png', 'start': 460205, 'length': 1661}
{'filename': 'web_files/img/ios-icon-60@2x.png', 'start': 461866, 'length': 2864}
{'filename': 'web_files/img/ios-icon-60@3x.png', 'start': 464730, 'length': 3897}
{'filename': 'web_files/img/ios-icon-76.png', 'start': 468627, 'length': 2097}
{'filename': 'web_files/img/ios-icon-76@2x.png', 'start': 470724, 'length': 17439}
{'filename': 'web_files/img/lock.png', 'start': 488163, 'length': 1321}
{'filename': 'web_files/img/logo.png', 'start': 489484, 'length': 2530}
{'filename': 'web_files/img/menu-highlight.png', 'start': 492014, 'length': 1090}
{'filename': 'web_files/img/menu.png', 'start': 493104, 'length': 1084}
{'filename': 'web_files/img/minus-highlight.png', 'start': 494188, 'length': 1035}
{'filename': 'web_files/img/minus.png', 'start': 495223, 'length': 1041}
{'filename': 'web_files/img/plus-highlight.png', 'start': 496264, 'length': 1150}
{'filename': 'web_files/img/plus.png', 'start': 497414, 'length': 1142}
{'filename': 'web_files/js/app.js.gz', 'start': 498556, 'length': 5517}
{'filename': 'web_files/js/lib.js.gz', 'start': 504073, 'length': 87122}
{'filename': 'web_files/locale/da.js', 'start': 591195, 'length': 3869}
{'filename': 'web_files/locale/de.js', 'start': 595064, 'length': 4019}
{'filename': 'web_files/locale/en.js', 'start': 599083, 'length': 3759}
{'filename': 'web_files/locale/es.js', 'start': 602842, 'length': 4118}
{'filename': 'web_files/locale/fi.js', 'start': 606960, 'length': 4022}
{'filename': 'web_files/locale/fr.js', 'start': 610982, 'length': 4231}
{'filename': 'web_files/locale/it.js', 'start': 615213, 'length': 3870}
{'filename': 'web_files/locale/nb.js', 'start': 619083, 'length': 3777}
{'filename': 'web_files/locale/nl.js', 'start': 622860, 'length': 3854}
{'filename': 'web_files/locale/pt.js', 'start': 626714, 'length': 4101}
{'filename': 'web_files/locale/sv.js', 'start': 630815, 'length': 3870}
{'filename': 'wifi/1iuinst1.bin', 'start': 634685, 'length': 9612}
{'filename': 'wifi/2iuinst2.bin', 'start': 644297, 'length': 4}
{'filename': 'wifi/3iudata.bin', 'start': 644301, 'length': 400}
{'filename': 'wifi/4ffinst1.bin', 'start': 644701, 'length': 65388}
{'filename': 'wifi/5ffinst2.bin', 'start': 710089, 'length': 30128}
{'filename': 'wifi/6ffdata.bin', 'start': 740217, 'length': 58464}
{'filename': 'wifi/wifiFwVersion.txt', 'start': 798681, 'length': 6}
{'filename': 'wire/Boundary 0.7.bin', 'start': 798687, 'length': 229376}
writing db504 v2.66 30-10-2017.bin (363076 bytes)
writing web_files/debugPage.html (23187 bytes)
writing web_files/dummy.html (2 bytes)
writing web_files/index.htm (13929 bytes)
writing web_files/index.html (13929 bytes)
writing web_files/log.html (4116 bytes)
writing web_files/manifest.json (667 bytes)
writing web_files/css/style.css (10653 bytes)
writing web_files/css/styleLog.css (13279 bytes)
writing web_files/img/android-icon-1x.png (1663 bytes)
writing web_files/img/android-icon-2x.png (2349 bytes)
writing web_files/img/android-icon-3x.png (3098 bytes)
writing web_files/img/android-icon-4x.png (4108 bytes)
writing web_files/img/back-highlight.png (1344 bytes)
writing web_files/img/back.png (1345 bytes)
writing web_files/img/close.png (1038 bytes)
writing web_files/img/ios-icon-58@2x.png (1661 bytes)
writing web_files/img/ios-icon-60@2x.png (2864 bytes)
writing web_files/img/ios-icon-60@3x.png (3897 bytes)
writing web_files/img/ios-icon-76.png (2097 bytes)
writing web_files/img/ios-icon-76@2x.png (17439 bytes)
writing web_files/img/lock.png (1321 bytes)
writing web_files/img/logo.png (2530 bytes)
writing web_files/img/menu-highlight.png (1090 bytes)
writing web_files/img/menu.png (1084 bytes)
writing web_files/img/minus-highlight.png (1035 bytes)
writing web_files/img/minus.png (1041 bytes)
writing web_files/img/plus-highlight.png (1150 bytes)
writing web_files/img/plus.png (1142 bytes)
writing web_files/js/app.js.gz (5517 bytes)
writing web_files/js/lib.js.gz (87122 bytes)
writing web_files/locale/da.js (3869 bytes)
writing web_files/locale/de.js (4019 bytes)
writing web_files/locale/en.js (3759 bytes)
writing web_files/locale/es.js (4118 bytes)
writing web_files/locale/fi.js (4022 bytes)
writing web_files/locale/fr.js (4231 bytes)
writing web_files/locale/it.js (3870 bytes)
writing web_files/locale/nb.js (3777 bytes)
writing web_files/locale/nl.js (3854 bytes)
writing web_files/locale/pt.js (4101 bytes)
writing web_files/locale/sv.js (3870 bytes)
writing wifi/1iuinst1.bin (9612 bytes)
writing wifi/2iuinst2.bin (4 bytes)
writing wifi/3iudata.bin (400 bytes)
writing wifi/4ffinst1.bin (65388 bytes)
writing wifi/5ffinst2.bin (30128 bytes)
writing wifi/6ffdata.bin (58464 bytes)
writing wifi/wifiFwVersion.txt (6 bytes)
writing wire/Boundary 0.7.bin (229376 bytes)
Done!
Are you sure? yes | no
Thanks for this, have extracted db510-v3.26.pck and looked like it went fine:
Unknown byte 0: 242
Unknown byte 1: 202
Unknown byte 2: 19
Unknown byte 3: 105
header end: 234
# files : 4
found 4 files
{'start': 238, 'filename': 'db510 v3.26 22-12-2017.bin', 'length': 195844}
{'start': 196082, 'filename': 'wifi_firmware/wififw v0.12.bin', 'length': 523520}
{'start': 719602, 'filename': 'wire_firmware/Boundary 2.0.bin', 'length': 32768}
{'start': 752370, 'filename': 'wire_firmware/Boundary BL 1.1.bin', 'length': 32768}
writing db510 v3.26 22-12-2017.bin (195844 bytes)
writing wifi_firmware/wififw v0.12.bin (523520 bytes)
writing wire_firmware/Boundary 2.0.bin (32768 bytes)
writing wire_firmware/Boundary BL 1.1.bin (32768 bytes)
So looks good. Is there any way of reversing the .bin or as it's a compiled ARM binary I'm guessing that's a no?
Anywhere have the original source for the stock firmware (Is it under GPL has anyone done an information request from Worx by any chance)?
Are you sure? yes | no
Hi Daniel,
I've just used your unpacker with the latest Firmware available for my 2017 Worx WR101SI.
It unpacks without problems, but if i scan the binary for strings, there isn't a single one that makes sense as well as no known headers.
Do you know if the kind of obfuscate their binarys?
Are you sure? yes | no
Hello,
I have tested the script . Here came the following error :
Unknown byte 0: 17
Unknown byte 1: 38
Unknown byte 2: 172
Unknown byte 3: 156
header end: 2418
Traceback (most recent call last):
File "unpack_pck.py", line 61, in
nHeaders = b.count(int(13),4,datastart)
TypeError: Type int doesn't support the buffer API
Greetings
Are you sure? yes | no
Hmm, I am no python guru, what version do you run? It works in my Python 3.5.2
Are you sure? yes | no
I just tried python 2 and got same error. This is written for python 3.
Are you sure? yes | no