|
#*******************************************************************************# |
|
# BinaryCookieReader: Written By Satishb3 (http://www.securitylearn.net) # |
|
# # |
|
# For any bug fixes contact me: satishb3@securitylearn.net # |
|
# # |
|
# Usage: Python BinaryCookieReader.py Cookie.Binarycookies-FilePath # |
|
# # |
|
# Safari browser and iOS applications store the persistent cookies in a binary # |
|
# file names Cookies.binarycookies.BinaryCookieReader is used to dump all the # |
|
# cookies from the binary Cookies.binarycookies file. # |
|
# # |
|
#*******************************************************************************# |
|
|
|
import sys |
|
from struct import unpack |
|
from StringIO import StringIO |
|
from time import strftime, gmtime |
|
|
|
if len(sys.argv)!=2: |
|
print "\nUsage: Python BinaryCookieReader.py [Full path to Cookies.binarycookies file] \n" |
|
print "Example: Python BinaryCookieReader.py C:\Cookies.binarycookies" |
|
sys.exit(0) |
|
|
|
FilePath=sys.argv[1] |
|
|
|
try: |
|
binary_file=open(FilePath,'rb') |
|
except IOError as e: |
|
print 'File Not Found :'+ FilePath |
|
sys.exit(0) |
|
|
|
file_header=binary_file.read(4) #File Magic String:cook |
|
|
|
if str(file_header)!='cook': |
|
print "Not a Cookies.binarycookie file" |
|
sys.exit(0) |
|
|
|
num_pages=unpack('>i',binary_file.read(4))[0] #Number of pages in the binary file: 4 bytes |
|
|
|
page_sizes=[] |
|
for np in range(num_pages): |
|
page_sizes.append(unpack('>i',binary_file.read(4))[0]) #Each page size: 4 bytes*number of pages |
|
|
|
pages=[] |
|
for ps in page_sizes: |
|
pages.append(binary_file.read(ps)) #Grab individual pages and each page will contain >= one cookie |
|
|
|
|
|
print "#*************************************************************************#" |
|
print "# BinaryCookieReader: developed by Satishb3: http://www.securitylearn.net #" |
|
print "#*************************************************************************#" |
|
|
|
for page in pages: |
|
page=StringIO(page) #Converts the string to a file. So that we can use read/write operations easily. |
|
page.read(4) #page header: 4 bytes: Always 00000100 |
|
num_cookies=unpack('<i',page.read(4))[0] #Number of cookies in each page, first 4 bytes after the page header in every page. |
|
|
|
cookie_offsets=[] |
|
for nc in range(num_cookies): |
|
cookie_offsets.append(unpack('<i',page.read(4))[0]) #Every page contains >= one cookie. Fetch cookie starting point from page starting byte |
|
|
|
page.read(4) #end of page header: Always 00000000 |
|
|
|
cookie='' |
|
for offset in cookie_offsets: |
|
page.seek(offset) #Move the page pointer to the cookie starting point |
|
cookiesize=unpack('<i',page.read(4))[0] #fetch cookie size |
|
cookie=StringIO(page.read(cookiesize)) #read the complete cookie |
|
|
|
cookie.read(4) #unknown |
|
|
|
flags=unpack('<i',cookie.read(4))[0] #Cookie flags: 1=secure, 4=httponly, 5=secure+httponly |
|
cookie_flags='' |
|
if flags==0: |
|
cookie_flags='' |
|
elif flags==1: |
|
cookie_flags='Secure' |
|
elif flags==4: |
|
cookie_flags='HttpOnly' |
|
elif flags==5: |
|
cookie_flags='Secure; HttpOnly' |
|
else: |
|
cookie_flags='Unknown' |
|
|
|
cookie.read(4) #unknown |
|
|
|
urloffset=unpack('<i',cookie.read(4))[0] #cookie domain offset from cookie starting point |
|
nameoffset=unpack('<i',cookie.read(4))[0] #cookie name offset from cookie starting point |
|
pathoffset=unpack('<i',cookie.read(4))[0] #cookie path offset from cookie starting point |
|
valueoffset=unpack('<i',cookie.read(4))[0] #cookie value offset from cookie starting point |
|
|
|
endofcookie=cookie.read(8) #end of cookie |
|
|
|
expiry_date_epoch= unpack('<d',cookie.read(8))[0]+978307200 #Expiry date is in Mac epoch format: Starts from 1/Jan/2001 |
|
expiry_date=strftime("%a, %d %b %Y ",gmtime(expiry_date_epoch))[:-1] #978307200 is unix epoch of 1/Jan/2001 //[:-1] strips the last space |
|
|
|
create_date_epoch=unpack('<d',cookie.read(8))[0]+978307200 #Cookies creation time |
|
create_date=strftime("%a, %d %b %Y ",gmtime(create_date_epoch))[:-1] |
|
#print create_date |
|
|
|
cookie.seek(urloffset-4) #fetch domaain value from url offset |
|
url='' |
|
u=cookie.read(1) |
|
while unpack('<b',u)[0]!=0: |
|
url=url+str(u) |
|
u=cookie.read(1) |
|
|
|
cookie.seek(nameoffset-4) #fetch cookie name from name offset |
|
name='' |
|
n=cookie.read(1) |
|
while unpack('<b',n)[0]!=0: |
|
name=name+str(n) |
|
n=cookie.read(1) |
|
|
|
cookie.seek(pathoffset-4) #fetch cookie path from path offset |
|
path='' |
|
pa=cookie.read(1) |
|
while unpack('<b',pa)[0]!=0: |
|
path=path+str(pa) |
|
pa=cookie.read(1) |
|
|
|
cookie.seek(valueoffset-4) #fetch cookie value from value offset |
|
value='' |
|
va=cookie.read(1) |
|
while unpack('<b',va)[0]!=0: |
|
value=value+str(va) |
|
va=cookie.read(1) |
|
|
|
print 'Cookie : '+name+'='+value+'; domain='+url+'; path='+path+'; '+'expires='+expiry_date+'; '+cookie_flags |
|
|
|
binary_file.close() |
sdvas