Skip to content

Objective 11b - Naughty/Nice List with Blockchain Investigation Part 2

Objective

Objective 11b


Tinsel Upatree tells you the following after you solve Objective 11a:

Wow, it really was all about abusing the pseudo-random sequence! I've been thinking, do you think someone could try and cheat the Naughty/Nice Blockchain with this same technique? I remember you told us about how if you have control over to bytes in a file, it's easy to create MD5 hash collisions. But the nonce would have to be known ahead of time. We know that the blockchain works by "chaining" blocks together. There's no way you know who could change it without messing up the chain, right Santa? I'm going to look closer to spot if any of the blocks have been changed. If Jack was able to change the block AND the document without changing the hash... that would require a very UNIque hash COLLision. Apparently Jack was able to change just 4 bytes in the block to completely change everything about it. It's like some sort of evil game to him. I think I need to review my (Human Behavior Naughty/Niceness)[https://www.youtube.com/watch?v=7rLMl88p-ec] curriculum again.

Walk-through

The terminal challenge for this objective is the "Snowball fight" that is offered by Tangle Coalbox in the UNPreparedness room. This is the same terminal challenge as objective 11a.

Solving this terminal challenge provide additional hints for this objective. To view the hints or the walk-through for this terminal challenge, use the menu on the left.

To start this objective, go to Santa's Office and Download the blockchain data and OfficialNaughtyNiceBlockchainEducationPack.zip.

There is a talk that may be helpful for this challenge.

To solve this challenge you need to read the blockchain, blockchain.dat, and find the block that Jack has altered. You know the SHA256 for this block is58a3b9335a6ceb0234c12d35a0564c4e f0e90152d0eb2ce2082383b38028a90f. You need to iterate through the blocks until you find a block that has the correct SHA256 hash. Once you find this block, dump the documents attached to the block and the block itself into separate files. From the hints, we know Jack has altered a total of 4 Bytes in the block. From analyses of these files, we can find the 4 bytes that Jack has altered.

You then need to modify these four bytes to their original value and save the new block. Calculate the SHA256 of this new block to solve the objective.

Finding the modified block

Extract OfficialNaughtyNiceBlockchainEducationPack.zip to a new folder. Update the Block() class in the naughty_nice.py script by adding the following:

#new function to calculate Hash of the block
def hash_block(self):
    hash_obj = MD5.new()
    hash_obj.update(self.block_data())
    return hash_obj.hexdigest()

#new function to calculate SHA256 Hash of the block
def hash_SHA256_block(self):
    hash_obj = SHA256.new()
    hash_obj.update(self.block_data())
    return hash_obj.hexdigest()

The above functions will calculate the MD5 and SHA256 hash of a block.

Update the main in naughty_nice.py as follow:

if __name__ == '__main__':
# Note: This is how you would load and verify a blockchain contained in a file called blockchain.dat

 with open('official_public.pem', 'rb') as fh:
     official_public_key = RSA.importKey(fh.read())
 c2 = Chain(load=True, filename='blockchain.dat')
 print('C2: Block chain verify: %s' % (c2.verify_chain(official_public_key)))
 print (len(c2.blocks))

 i=0
 targetBlock_SHA256 ="58a3b9335a6ceb0234c12d35a0564c4ef0e90152d0eb2ce2082383b38028a90f"
 for i in range(len(c2.blocks)):
     if (c2.blocks[i].full_hash_SHA256() ==targetBlock_SHA256):
            print("Matched Blocked",i,":")
            print(c2.blocks[i])
            print("Block [",c2.blocks[i].index,"].index:",c2.blocks[i].index)
            print("Block [",c2.blocks[i].index,"].hash:",c2.blocks[i].hash)
            print("Block [",c2.blocks[i].index,"] Calculated Hash (MD5)", c2.blocks[i].hash_block())
            print("Block [",c2.blocks[i].index,"] Calculated Hash (SHA256)", c2.blocks[i].hash_SHA256_block())
            print("Block [",c2.blocks[i].index,"].previous_hash", c2.blocks[i].previous_hash)
            print("Block [",c2.blocks[i].index,"] signed Hash(MD5)", c2.blocks[i].full_hash())
            print("Block [",c2.blocks[i].index,"] signed Hash (SHA256)", c2.blocks[i].full_hash_SHA256())
            print("===========")
            print(c2.blocks[i])
            print("===========")

         for y in range (1,c2.blocks[i].doc_count+1):
             c2.blocks[i].dump_doc(y)
         # save a block before and after for comparison
         c2.save_a_block(i-1)
         c2.save_a_block(i)
         c2.save_a_block(i+1)


         # save a block before and after for comparison
         print(c2.blocks[i-1])
         print(c2.blocks[i])
         print(c2.blocks[i+1])

 hash_md5 =  MD5.new()
 hash_sha256 = SHA256.new()
 with open("block1010.dat", "rb") as f:
     for chunk in iter(lambda: f.read(4096), b""):
         hash_md5.update(chunk)
         hash_sha256.update(chunk)
 print("block1010.dat(md5):",hash_md5.hexdigest())
 print("block1010.dat(sha256):",hash_sha256.hexdigest())

The above code will do the following:

  1. Load the blockchain 'blockchain.dat'.
  2. Keep iterating through the blocks until you find the block with the SHA256 '58a3b9335a6ceb0234c12d35a0564c4ef0e90152d0eb2ce2082383b38028a90f'
  3. Once found, write the block, the previous, and proceeding blocks to files.
  4. Dump all the attachments for the matched block.

Run naughty_nice.py to find the altered block. Partial results are shown below:


Objective 11b

Objective 11b


Finding the modified "bytes"

From the above screenshot, you can see the altered block is the block 129459 which has the correct SHA256 Hash. This block has two attachments. This block shows that the individual was 1 (Nice) with the maximum score for FFFFFFFF.

A good assumption is that Jack is likely "naughty", which means one of the changed bytes is the nice/naughty "sign".

One of the attachments to block 129459 is a ".pdf" file (Virustotal). This attachment corroborates the story that Jack is very nice. So if our first assumption is correct, Jack somehow must have changed the whole content of the PDF file.

PDF files are documents that have tree structures. Here is an example of what a logical structure of a typical document looks like.


Objective 11b


Open the PDF file in a text editor and examine the objects. You can see that there are two trees in the document. One tree starts at object 2 and the other at object 3. The current catalogue points to object 2 (tree).


Objective 11b


Change this byte from 2 to 3 to point to object 3 (tree).


Objective 11b


Reopening the PDF file reveals the content of the PDF has changed to a different document. This document portrays Jack as being naughty.

Here Original PDF attached to the blockchain and Fixed PDF.

Changing the bytes back

To figure this out on your own, read the hints, review the slides, watch the talk for this objective. You need a basic understanding of Hash collision and specifically UNICOL.

One of the most useful slides that explain what UNICOL is doing is the following:


Objective 11b


UNICOL is adding 1 to the 10th CHAR of the PREFIX and removing 1 from the 10th CHAR of the 2nd Block. This keeps the MD5 hash of the original and new blocks to be identical.

It just happens that both the modified bytes are on the 10th Byte of the 64K Blocks.

To undo what UNICOL does, we need to subtract 1 from the PREFIX and add one to the 10th CHAR of the second block.

Open the block1010.dat in a hexeditor and change the 4 bytes back. Here is a screenshot that shows the changing of the first two bytes. The sign "nice" is changed to "naughty". The corresponding 10th CHAR of the second block is also changed.


Objective 11b


Here is a screenshot that shows the changing of the second two bytes. The catalogue is changed from object 2 to 3. The corresponding 10th CHAR of the second block is also changed.


Objective 11b


Save the modified block as "blockchain.dat_2"

Finding the SHA256 of the "original block"

Once you fix the modified bytes, you save the block as "block1010.dat_2". Add this code to the end of naughty_nice.py to calculate the SHA256 of the "original" block.

hash_md5 =  MD5.new()
hash_sha256 = SHA256.new()
with open("block1010_2.dat", "rb") as f:
    for chunk in iter(lambda: f.read(4096), b""):
        hash_md5.update(chunk)
        hash_sha256.update(chunk)
print("block1010.dat_2:",hash_md5.hexdigest())
print("block1010.dat_2(sha256):",hash_sha256.hexdigest())

Here is a screenshot that shows the MD5 and SHA256 of the two blocks. You can see they both have the same MD5 hash but different SHA256 hashes.


Objective 11b


The updated naughty_nice.py code can be downloaded here.

After you solve the challenge, you need to go to Santa's office (as "Santa") and talk to the different elves. Here is what happens if you go to the office without the "Santa" skin.


Objective 11b


Change to Santa and go back to finish the game.


Objective 11b



Objective 11b


Eve Snowshoes: What a fantabulous job! Congratulations! What a fantabulous job! Congratulations! You MUST let us know how you did it! Feel free to show off your skills with some swag - only for our victors!


Santa: Thank you for foiling Jack’s foul plot! He sent that magical portrait so he could become me and destroy the holidays! Due to your incredible work, you have set everything right and saved the holiday season! Congratulations on a job well done! Ho Ho Ho!

Answer

The SHA256 of the original block is:

fff054f33c2134e0230efb29dad515064ac97aa8c68d33c58c01213a0d408afb