Skip to content

Instantly share code, notes, and snippets.

@Lense
Last active July 12, 2018 22:01
Show Gist options
  • Save Lense/0a5cc18f902f855b1a82 to your computer and use it in GitHub Desktop.
Save Lense/0a5cc18f902f855b1a82 to your computer and use it in GitHub Desktop.
CSAW quals 2015 forensics 400: Sharpturn

First thing I did was figure out that it was a git repo, search Google for how to extract the code, and run git archive master | tar x -C code. It asks for 2 prime factors of a number which doesn't have exactly 2 prime factors, from which it can be assumed that something was wrong with the code.

Running git fsck (after more Google searching) showed 3 hashes not matching up, which means that the hash of the file contents (plus header metadata) didn't match the filename. I then read https://git-scm.com/book/en/v2/Git-Internals-Git-Objects (side-note: the Pro Git book is a fantastic introduction to and reference for git). 3 Files are corrupted: sharp.cpp in each of the 3 commits (see git log).

Then I tool a leap of faith and assumed that a single byte was wrong (corrupted, hence the SATA controller comment) in each blob, and wrote a script to brute force it. It worked for first one, and then doom had to remind me to propagate the changes: the first commit has an error, and that same error occurs in the 2 next commits. So commit 1 has 1 error, commit 2 has 2 errors, and commit 3 has 3 errors.

(http://rpis.ec)

#!/usr/bin/env python2
import hashlib
import os
import subprocess
import zlib
"""
Run this from the objects directory.
"""
# Find bad hashes
fsck = subprocess.check_output("git fsck; exit 0", shell=True)
badHashes = [line[line.rindex(' ') + 1:] for line in \
filter(lambda x: x.startswith("missing blob "), fsck.split('\n'))]
# Sort them in order of commit (cheat a little by assuming they grow in size)
badHashes.sort(key=lambda h: os.stat(h[:2] + '/' + h[2:]).st_size)
replacements = list()
for h in badHashes:
print("Fixing " + h)
filename = h[:2] + '/' + h[2:]
with open(filename, "r") as f:
# git blobs are stored with zlib compression
fContents = zlib.decompress(f.read())
# Propagate fixes from previous blobs
for r in replacements:
if r[0]+r[2] in fContents:
i = fContents.index(r[2]) - 1
fContents = fContents[:i] + r[1] + fContents[i+1:]
# Find error
for i in range(len(fContents)):
for c in range(256):
if hashlib.sha1(fContents[:i] + chr(c) + fContents[i+1:]).hexdigest() == h:
print("Found error in " + h)
replacements.append((fContents[i-10:i+1], chr(c), fContents[i+1:i+10]))
# Save fix
with open(filename, "w") as f:
f.write(zlib.compress(fContents[:i] + chr(c) + fContents[i+1:]))
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment