libyal / libesedb

Library and tools to access the Extensible Storage Engine (ESE) Database File (EDB) format.
GNU Lesser General Public License v3.0
341 stars 91 forks source link

pyesesb get_value_data returns unexpected data #70

Open segevrl opened 4 months ago

segevrl commented 4 months ago

I'm trying to build a parser for the BITS database in Windows 10 using pyesedb. https://cloud.google.com/blog/topics/threat-intelligence/attacker-use-of-windows-background-intelligent-transfer-service/

I created a BITS job named "persistence", like the one in the Mandiant article above:

bitsadmin /create persistence
bitsadmin /addfile persistence http://127.0.0.1/invalid.exe c:\windows\i.exe
bitsadmin /SetNotifyCmdLine persistence c:\windows\malware.exe NULL
bitsadmin /resume persistence

I exported the qmgr.db database after that: qmgr.zip I examined the database using this tool: https://github.com/wfraser/EseView, which uses Microsoft's ESENT Managed Interop library: image

This is the 'Blob' column in the second row of the 'Jobs' table, as exported by this tool: Picture1

With pyesedb, I can get the GUID from this row, and it's the same. However, I don't get the same data from the 'Blob' column:

>>> import pyesedb
>>> db = pyesedb.file()
>>> db.open_file_object(open(".\\qmgr.db", "rb"))
>>> list(map(lambda table: table.name, db.tables))
['MSysObjects', 'MSysObjectsShadow', 'MSysObjids', 'MSysLocales', 'Jobs', 'Files']
>>>
>>> jobs_table = db.get_table_by_name("Jobs")
>>> list(map(lambda column: column.name, jobs_table.columns))
['Id', 'Blob']
>>>
>>> second_record_guid_bytes = jobs_table.records[1].get_value_data(0)
>>> uuid.UUID(bytes_le=second_record_guid_bytes)
UUID('54206de4-be77-4608-84e0-872f864acf50')
>>>
>>> second_record_blob = jobs_table.records[1].get_value_data(1)
>>> second_record_blob
b'\x17\x00\x00\x80\x00\x00\x00\x80'

I get these bytes instead: b'\x17\x00\x00\x80\x00\x00\x00\x80' What could be the reason for this? Am I missing something? Thanks!

joachimmetz commented 4 months ago

Is this a long value?

segevrl commented 4 months ago

The type of the 'Blob' column is JET_coltypLongBinary

joachimmetz commented 4 months ago

yes then you are getting a reference to a long key

segevrl commented 4 months ago

Should I call get_value_data_as_long_value in this case? It gives me an error:

>>> jobs_table.records[1].get_value_data_as_long_value(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: pyesedb_record_get_value_data_as_long_value: unable to retrieve long value: 1. libesedb_record_get_long_value_data_segments_list: unsupport long value key size: 8.  libesedb_record_get_long_value: unable retrieve value data.