Skip to content

Commit

Permalink
Update.
Browse files Browse the repository at this point in the history
  • Loading branch information
msuhanov committed Apr 15, 2022
1 parent 939b4ac commit 125729d
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 10 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
Version: 1.0.33

yarp-print: print deleted values correctly when dealing with truncated hives, print remnant value data (having no corresponding deleted key value).
RegistryRecover: handle remnant value data.

---

Version: 1.0.32

yarp-print: optimize the memory usage when dealing with deleted values and truncated hives.
Expand Down
2 changes: 1 addition & 1 deletion ReadMe
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ See the 'License' file.

5. Installation

# pip3 install https://github.com/msuhanov/yarp/archive/1.0.32.tar.gz
# pip3 install https://github.com/msuhanov/yarp/archive/1.0.33.tar.gz

6. Known issues

Expand Down
Binary file added hives_for_tests/RemnantData
Binary file not shown.
182 changes: 182 additions & 0 deletions test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@

hive_two_owners = path.join(HIVES_DIR, 'TwoOwnersHive')

hive_remnant_bytes = path.join(HIVES_DIR, 'RemnantData')

fragment_sqlite = path.join(HIVES_DIR, 'SqliteFragment')
fragment_sqlite_db = path.join(HIVES_DIR, 'SqliteFragment.sqlite')
fragment_invalid_parent = path.join(HIVES_DIR, 'InvalidParentFragment')
Expand Down Expand Up @@ -3213,3 +3215,183 @@ def test_layered_keys():
k = h.find_key('kEy')
assert k.flags_str() is None
f.close()

def test_remnant_bytes():
f = open(hive_remnant_bytes, 'rb')

hive = Registry.RegistryHive(f)

hive.walk_everywhere()

scanner = RegistryRecover.Scanner(hive, True, False, True)

hashes = [ '465d17740b0d7c443de4b4e0afcaa1c4', '995dd6585d84b3b766c272463a785fc3', '7f3c8904ea293c3aae69c745407c93cc', 'f02eb13db5b9fc92516e3a400b8b5777', 'aacdda7f3ce91cd5ab212f58756e2106', 'afb86dbf44f95c3f3e0b852ab8cdc2eb', 'd8d838d33ee4bc3a167281e8e944aee5', '319c4caa15d4513ee10503f90a8bc59c', 'e9b5bbac405dbfa2241f5f4bb7154980', '22e401881c635dee0324c3ab263324fe', 'b48781ea2beb38f46871755e93d0e102', '6079c357fa4b1d06b6b2fb1a9eff2e4a', 'c324946ce1884cae603d6f4aa055ac8c' ]

c = 0
for i in scanner.scan():
if type(i) is bytes:
c += 1
hashes.remove(md5(i).hexdigest())

assert len(hashes) == 0
assert c == 13

v = b'vk\x01\x00\x00\x00\x00\x80\x00\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\x009\x03\x00\x00p\x03\x00\x00'

c = 0
c_v = 0
for i in scanner.process_cell(v):
if type(i) is bytes:
c += 1
assert i == b'\x00\x00p\x03\x00\x00'
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 1 and c_v == 1

v = v[ : -6]

c = 0
c_v = 0
for i in scanner.process_cell(v):
if type(i) is bytes:
c += 1
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 0 and c_v == 1

c = 0
c_v = 0
l = [ b'aaaa', b'zzzz' ]
for i in scanner.process_cell(l[0] + v + l[1]):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 2 and len(l) == 0 and c_v == 1

c = 0
c_v = 0
l = [ b'aa' ]
for i in scanner.process_cell(l[0] + v):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 1 and len(l) == 0 and c_v == 1

c = 0
c_v = 0
l = [ b'aazz' ]
for i in scanner.process_cell(l[0] + v):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 1 and len(l) == 0 and c_v == 1

c = 0
c_v = 0
l = [ b'aazz' ]
for i in scanner.process_cell(l[0] + v + v):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 1 and len(l) == 0 and c_v == 2

c = 0
c_v = 0
l = [ b'aazz' ]
for i in scanner.process_cell(v + v + l[0]):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 1 and len(l) == 0 and c_v == 2

c = 0
c_v = 0
l = [ b'aazz', b'zzzz' ]
for i in scanner.process_cell(l[0] + v + v + l[1]):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 2 and len(l) == 0 and c_v == 2

c = 0
c_v = 0
l = [ b'aazz', b'zzzz', b'TEST1234' ]
for i in scanner.process_cell(l[0] + v + l[1] + v + l[2]):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 3 and len(l) == 0 and c_v == 2

c = 0
c_v = 0
l = [ b'aazz', b'12', b'T' ]
for i in scanner.process_cell(l[0] + v + l[1] + v + l[2]):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 3 and len(l) == 0 and c_v == 2

c = 0
c_v = 0
l = [ b'aazz', b'12', b'T' ]
for i in scanner.process_cell(l[0] + v + l[1] + v + l[2] + v):
if type(i) is bytes:
c += 1
if i in l:
l.remove(i)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 3 and len(l) == 1 and c_v == 2

c = 0
c_v = 0
l = [ b'aazz', b'12', b'TT' ]
for i in scanner.process_cell(l[0] + v + l[1] + v + l[2] + v + v):
if type(i) is bytes:
c += 1
assert i == l.pop(0)
else:
assert type(i) is Registry.RegistryValue
c_v += 1

assert c == 3 and len(l) == 0 and c_v == 4

f.close()
20 changes: 17 additions & 3 deletions yarp-print
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def process_normal_hive(hive):
print('Deleted keys and values (may contain reallocated data):')
print()

scanner = RegistryRecover.Scanner(hive)
scanner = RegistryRecover.Scanner(hive, yield_remnant_bytes = True)

for item in scanner.scan():
if type(item) is Registry.RegistryKey:
Expand All @@ -275,6 +275,13 @@ def process_normal_hive(hive):
if type(item) is Registry.RegistryValue:
print_deleted_value(item)

print('Possible value data or other remnant data (can include deleted registry structures, slack or even garbage):')
print()
for item in scanner.scan():
if type(item) is bytes and len(item) > 4 and len(item.rstrip(b'\x00')) > 4:
print(RegistryHelpers.HexDump(item))
print('---')

def process_truncated_hive(hive):
print('Primary file seems to be truncated, only available keys and values will be printed', file = sys.stderr)

Expand All @@ -299,18 +306,25 @@ def process_truncated_hive(hive):
print('Unallocated keys and values (may contain reallocated data):')
print()

scanner = RegistryRecover.Scanner(hive, False)
scanner = RegistryRecover.Scanner(hive, False, yield_remnant_bytes = True)

for item in scanner.scan():
if type(item) is Registry.RegistryKey:
print_deleted_key(item)

print('Unallocated values (all, may contain reallocated data):')
print()
for item in hive.scan():
for item in scanner.scan():
if type(item) is Registry.RegistryValue:
print_deleted_value(item)

print('Possible value data or other remnant data (can include deleted registry structures, slack or even garbage):')
print()
for item in scanner.scan():
if type(item) is bytes and len(item) > 4 and len(item.rstrip(b'\x00')) > 4:
print(RegistryHelpers.HexDump(item))
print('---')

args = parse_args()

if not os.path.isfile(args.primary_file):
Expand Down
Loading

0 comments on commit 125729d

Please sign in to comment.