Python Sample SQLite
It is possible to access SQLite files in Truxton without first exporting them to your local system. Almost always, you will have to export the SQLite file from Truxton to a temporary folder and run your scripts on it. This is because it is not worth modifying the Python code to open the SQLite file in Truxton's storage. It is just easier to export the file from Truxton, run your code on it, delete the exported file, continue on with life.
When your holdings get large, the performance hit of exporting all those files becomes worth the effort to modify the Python script. When you get there, here's how to query SQLite files directly from Truxton.
APSW
Since the Python DB-API only supports establishing a connection to a SQLite database by providing a file name, we have to create our own filesystem to read from the file in Truxton. SQLite has the concept of virtual filesystems but DB-API doesn't support it. However, another SQLite library called APSW does. Install it using pip:
pip install apsw
You can verify that it is working by running the following script:
import sys
import apsw
import apsw.ext
def main() -> None:
print(" Using APSW file", apsw.__file__)
print(" APSW version", apsw.apsw_version())
print("SQLite header version", apsw.SQLITE_VERSION_NUMBER)
print(" SQLite lib version", apsw.sqlite_lib_version())
print(" Using amalgamation", apsw.using_amalgamation)
return None
if __name__ == "__main__":
sys.exit(main())
SQLite in Truxton
Here's a script to query a SQLite database that is stored in Truxton.
Instead of opening a file by name, we open it using the file's identifier.
This corresponds to the ID column of the [File] table.
import sys
import os
import apsw
from pathlib import Path
sys.path.append('C:/Program Files/Truxton/SDK')
import truxton
def main() -> None:
truxton_virtual_filesystem = TruxtonVFS()
truxton_virtual_filesystem.Truxton = truxton.create()
# Open the SQLite file using it's id
database = apsw.Connection( "65d9d912-7328-d2e7-d511-f909000000c6", flags = SQLITE_OPEN_READONLY, vfs = "truxton")
for row in database.execute("SELECT Z_UUID FROM Z_METADATA"):
print(row)
database.close()
return None
SQLITE_OPEN_READONLY = 0x00000001
class TruxtonVFS(apsw.VFS):
Truxton = None
def __init__(self, vfsname="truxton", basevfs=""):
self.vfs_name = vfsname
self.base_vfs = basevfs
super().__init__(self.vfs_name, self.base_vfs)
def xOpen(self, fname, flags):
# fname is of type apsw.URIFilename object
truxton_guid = os.path.basename(fname.filename())
opened_file = self.Truxton.getfileid(truxton_guid)
return TruxtonVFSFile(f = opened_file, name = truxton_guid, flags = flags)
def xAccess(self, pathname, flags):
return False
def xDelete(self, filename, syncdir):
pass
class TruxtonVFSFile(apsw.VFSFile):
def __init__(self, f: truxton.TruxtonFileIO, name, flags):
"""
Truxton VFS File object
Args:
* f: TruxtonFileIO object returned by Truxton.getfileid
* name: name of the file
* flags: SQLite open flags
"""
self.f = f
self.flags = flags
self.name = name
self.mode = "rb"
def xRead(self, amount, offset) -> bytes:
self.f.seek(offset)
data = self.f.read(amount)
return data
def xFileControl(self, *args):
return True
def xDeviceCharacteristics(self):
return 4096
def xCheckReservedLock(self):
return False
def xLock(self, level):
pass
def xUnlock(self, level):
pass
def xSectorSize(self):
return self.f.block_size
def xClose(self):
self.f.close()
pass
def xFileSize(self):
pos = self.f.tell()
self.f.seek(0, 2)
size = self.f.tell()
self.f.seek(pos)
return size
def xSync(self, flags):
pass
def xTruncate(self, newsize):
pass
def xWrite(self, data, offset):
pass
if __name__ == "__main__":
sys.exit(main())
Exploiting All SQLite Files in Truxton
Using enumeration, we can find all files of a particular type and query them without ever having to write to a file.
This is the AllSpeedTestDatabases.py sample found here.
import sys
import os
import apsw
import sqlite3
from pathlib import Path
sys.path.append('C:/Program Files/Truxton/SDK')
import truxton
# Notice that we keep the database parameter typeless
# This is so we can use the same function with an APSW Connection or a splite3 cursor.
# The exploitation code doesn't know nor care which SQLite technology is used.
def exploit_speed_test_database( database ) -> None:
for row in database.execute("SELECT [ZDATE],[ZLATITUDE],[ZLONGITUDE],[ZALTITUDE],[ZWIFISSID] FROM [ZSPEEDTESTRESULT]"):
# Your exploitation code goes here
print(row)
return None
def process_file(file_information: truxton.TruxtonFileIO) -> None:
# Separate the opening of the SQLite file from the exploitation of it.
# Open the SQLite database
database = apsw.Connection( file_information.id, flags = SQLITE_OPEN_READONLY, vfs = "truxton")
# Exploit the SQLite database
exploit_speed_test_database( database )
database.close()
return None
def search_files(media: truxton.TruxtonMedia) -> None:
files_in_media = truxton_virtual_filesystem.Truxton.newenumerator()
files_in_media.scope = truxton.Type_Media
files_in_media.scopeid = media.id
files_in_media.target = truxton.Type_File
files_in_media.filetype = truxton.Type_Speedtest_Database
for file_information in files_in_media:
process_file(file_information)
return None
def search_media(media: truxton.TruxtonMedia) -> None:
search_files(media)
return None
def search_investigation(investigation: truxton.TruxtonInvestigation) -> None:
investigation_media = truxton_virtual_filesystem.Truxton.newenumerator()
investigation_media.scope = truxton.Type_Investigation
investigation_media.scopeid = investigation.id
investigation_media.target = truxton.Type_Media
for media in investigation_media:
search_media(media)
return None
SQLITE_OPEN_READONLY = 0x00000001
class TruxtonVFS(apsw.VFS):
Truxton = None
def __init__(self, vfsname="truxton", basevfs=""):
self.vfs_name = vfsname
self.base_vfs = basevfs
super().__init__(self.vfs_name, self.base_vfs)
def xOpen(self, fname, flags):
# fname is of type apsw.URIFilename object
truxton_guid = os.path.basename(fname.filename())
opened_file = self.Truxton.getfileid(truxton_guid)
return TruxtonVFSFile(f = opened_file, name = truxton_guid, flags = flags)
def xAccess(self, pathname, flags):
return False
def xDelete(self, filename, syncdir):
pass
class TruxtonVFSFile(apsw.VFSFile):
def __init__(self, f: truxton.TruxtonFileIO, name, flags):
"""
Truxton VFS File object
Args:
* f: TruxtonFileIO object returned by Truxton.getfileid
* name: name of the file
* flags: SQLite open flags
"""
self.f = f
self.flags = flags
self.name = name
self.mode = "rb"
def xRead(self, amount, offset) -> bytes:
self.f.seek(offset)
data = self.f.read(amount)
return data
def xFileControl(self, *args):
return True
def xDeviceCharacteristics(self):
return 4096
def xCheckReservedLock(self):
return False
def xLock(self, level):
pass
def xUnlock(self, level):
pass
def xSectorSize(self):
return self.f.block_size
def xClose(self):
self.f.close()
pass
def xFileSize(self):
pos = self.f.tell()
self.f.seek(0, 2)
size = self.f.tell()
self.f.seek(pos)
return size
def xSync(self, flags):
pass
def xTruncate(self, newsize):
pass
def xWrite(self, data, offset):
pass
# Global Variables
truxton_virtual_filesystem = TruxtonVFS()
truxton_virtual_filesystem.Truxton = truxton.create()
def main() -> None:
investigations = truxton_virtual_filesystem.Truxton.newenumerator()
investigations.target = truxton.Type_Investigation
for investigation in investigations:
search_investigation(investigation)
return None
if __name__ == "__main__":
sys.exit(main())