Skip to content

11b. Naughty/Nice List with Blockchain Investigation Part 2

Introduction

Tinsel Upatree in Santa's Office

Howdy Santa! Just guarding the Naughty/Nice list on your desk.

Santa, I don't know if you've heard, but something is very, very wrong...

We tabulated the latest score of the Naughty/Nice Blockchain.

Jack Frost is the nicest being in the world! Jack Frost!?!

As you know, we only really start checking the Naughty/Nice totals as we get closer to the holidays.

Out of nowhere, Jack Frost has this crazy score... positive 4,294,935,958 nice points!

No one has EVER gotten a score that high! No one knows how it happened.

Most of us recall Jack having a NEGATIVE score only a few days ago...

Worse still, his huge positive score seems to have happened way back in March.

Our first thought was that he somehow changed the blockchain - but, as you know, that isn't possible.

We ran a validation of the blockchain and it all checks out.

Even the smallest change to any block should make it invalid.

Blockchains are huge, so we cut a one minute chunk from when Jack's big score registered back in March.

You can get a slice of the Naughty/Nice blockchain on your desk.

You can get some tools to help you here.

Tangle Coalbox, in the Speaker UNPreparedness room. has been talking with attendees about the issue.

Tangle Coalbox in the Speaker UNPreparedness room

Now, the REAL question is, how else can this be abused? Do you think someone could try and cheat the Naughty/Nice Blockchain with this?

If you have control over to bytes in a file, it's easy to create MD5 hash collisions.

Problem is: there's that nonce that he would have to know ahead of time.

A blockchain works by "chaining" blocks together - so there's no way that Jack could change it without it messing up the chain...

Maybe if you look at the block that seems like it got changed, it might help.

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.

That's about all the help I can give you, kid, but Prof. Petabyte may have more.

Objective

Hints

Solution

The following files should be retrieved to complete this objective:

Find the altered block

After studying the code in the naughty_nice.py file and reading the documentation at the start of the file, the following code was developed to find the altered block that had the SHA256 hash of 58a3b9335a6ceb0234c12d35a0564c4ef0e90152d0eb2ce2082383b38028a90f.

#!/usr/bin/python3

from naughty_nice import Chain
from naughty_nice import Block
from Crypto.Hash import MD5, SHA256

# Create new method that will calculate the SHA256 hash of a given block
# This is based on this method starting at line 233 in naughty_nice.py
#    def full_hash(self):
#        hash_obj = MD5.new()
#        hash_obj.update(self.block_data_signed())
#        return hash_obj.hexdigest()

def full_hash_sha256(self):
    # create new SHA256 object
    hash_obj = SHA256.new()
    # hash the data part of the block
    hash_obj.update(self.block_data_signed())
    # return the has value
    return hash_obj.hexdigest()

# add new method to Block class
setattr(Block, 'full_hash_sha256', full_hash_sha256)

# load blockchain
bc = Chain(load=True, filename='blockchain.dat')

for i in range((129996 - 128449)):
    my_hash = bc.blocks[i].full_hash_sha256()
    if my_hash == "58a3b9335a6ceb0234c12d35a0564c4ef0e90152d0eb2ce2082383b38028a90f":
        print("The block at", i + 128449, "( array element",i,") has a SHA256 hash of", my_hash)

The code is here 11b-get-block.py

found the block

The next step was to get all of the details for the block. The following lines were added to the code above:

        # print details of the block
        print(bc.blocks[i])
        # dump a copy of the block so that it can be analysed.
        bc.save_a_block(i, "block_"+str(i)+".bin")
        print("Created", "block_"+str(i)+".bin")
        # Extract any documents that are part of the block
        print("Extract Documents")
        for doc_num in range(bc.blocks[i].doc_count):
            bc.blocks[i].dump_doc(doc_num)

The code is here 11b-block-details.py

The output was as follows (a lot of the binary data has been removed for clarity):

~/HolidayHack/2020/OfficialNaughtyNiceBlockchainEducationPack> ./11b-block-details.py
The block at 129459 ( array element 1010 ) has a SHA256 hash of 58a3b9335a6ceb0234c12d35a0564c4ef0e90152d0eb2ce2082383b38028a90f
Chain Index: 129459
              Nonce: a9447e5771c704f4
                PID: 0000000000012fd1
                RID: 000000000000020f
     Document Count: 2
              Score: ffffffff (4294967295)
               Sign: 1 (Nice)
         Data item: 1
               Data Type: ff (Binary blob)
             Data Length: 0000006c
                    Data: b'ea465340303a6079d3df2762be68467c27f046d3a7ff4e92dfe1def7407f2a7b73e1b759b8b919451e37518d22d987296fcb0f188dd60388bf20350f2a91c29d0348614dc0bceef2bcadd4cc3f251ba8f9fbaf171a06df1e1fd8649396ab86f9d5118cc8d8204b4ffe8d8f09'
         Data item: 2
               Data Type: 05 (PDF)
             Data Length: 00009f57
                    Data: b'255044462d312e330a2525c1cec7c521
... SNIP ... SNIP ... SNIP ...
ec8d21c07d86032d97df517106022db0c21c33c03402019a43'
               Date: 03/24
               Time: 13:21:41
       PreviousHash: 4a91947439046c2dbaa96db38e924665
  Data Hash to Sign: 347979fece8d403e06f89f8633b5231a
          Signature: b'MJIxJy2iFXJRCN1EwDsqO9NzE2Dq1qlvZuFFlljmQ03+erFpqqgSI1xhfAwlfmI2MqZWXA9RDTVw3+aWPq2S0CKuKvXkDOrX92cPUz5wEMYNfuxrpOFhrK2sks0yeQWPsHFEV4cl6jtkZ//OwdIznTuVgfuA8UDcnqCpzSV9Uu8ugZpAlUY43Y40ecJPFoI/xi+VU4xM0+9vjY0EmQijOj5k89/AbMAD2R3UbFNmmR61w7cVLrDhx3XwTdY2RCc3ovnUYmhgPNnduKIUA/zKbuu95FFi5M2r6c5Mt6F+c9EdLza24xX2J4l3YbmagR/AEBaF9EBMDZ1o5cMTMCtHfw=='

Created block_1010.bin
Extract Documents
Document dumped as: 129459.pdf
Document dumped as: 129459.bin

Recreate the original block

There was a lot of reading to do and the github repository at https://github.com/corkami/collisions was downloaded. The hashclash release v1.2b was downloaded and extracted.

The important points from the reading were:

  • "differences are always at the same offset" - slide 68
  • "tiny differences at fixed offsets We can’t change these offsets. (they depend on the hash function)" - slide 82
  • How to change the Page number in a pdf as per slide 194

11b-check-hash.py was written to check that the MD5 hash of the block remained the same as it was manipulated.

Fix Naught/Nice Sign

The first thing to fix was the byte that was set to 1 to say that Jack Frost was nice.

The changes were applied using hexedit to edit the file.

Based on the values that were dumped for the block:

              Nonce: a9447e5771c704f4
                PID: 0000000000012fd1
                RID: 000000000000020f
     Document Count: 2
              Score: ffffffff (4294967295)
               Sign: 1 (Nice)
         Data item: 1
               Data Type: ff (Binary blob)
it was possible to identify that the byte at offset 0x49 had to be changed from a 1 (0x31) to a 0 (0x30) (see https://man7.org/linux/man-pages/man7/ascii.7.html)

change sign byte

To determine where the offset might be hashclash-hashclash-static-release-v1.2b/scripts/poc_no.sh was run and the output of the resulting files diffed.

# diff <(xxd collision1.bin) <(xxd collision2.bin)
1c1
< 00000000: 850c f9f0 78f1 2cac ebd3 9dc7 ce1d 1e2f  ....x.,......../
---
> 00000000: 850c f9f0 78f1 2cac ebd4 9dc7 ce1d 1e2f  ....x.,......../
5c5
< 00000040: fc99 350a f58a a8ad 7309 9faa c154 d298  ..5.....s....T..
---
> 00000040: fc99 350a f58a a8ad 7308 9faa c154 d298  ..5.....s....T..

It was determined that the offset is 0x40. So to apply this to the block byte (0x49 + 0x40) 0x89 needs to be changed. By experimentation it was found that the value of the byte needed to be changed from 0xd6 to 0xd7.

byte changes

Running ./11b-check-hash.py confirms that the MD5 hashs is unaltered.

Fix PDF report

This is the original pdf which was extracted as 129459.pdf.

Following the details on slide 194, this file can be edited in hex to change the page number:

edit page number

And now the really report from Shinny Upatree is visible.

This same change needs to be made in the block file now and involves changing the byte at offset 0x109 from 2 (0x32) to 3 (0x33)

To check the offset, the following comparison was done.

# diff <(xxd collisions/scripts/pdf1.bin) <(xxd collisions/scripts/pdf2.bin)
5c5
< 00000040: 5f5f 2f50 6167 6573 2032 2030 2052 0a25  __/Pages 2 0 R.%
---
> 00000040: 5f5f 2f50 6167 6573 2033 2030 2052 0a25  __/Pages 3 0 R.%
9c9
< 00000080: 17a9 f823 ff5f 70be ce96 465a af13 7608  ...#._p...FZ..v.
---
> 00000080: 17a9 f823 ff5f 70be ce95 465a af13 7608  ...#._p...FZ..v.

Again the offset is 0x40. This implies that the byte 0x149 at has to be changed from 0x1C to 0x1B

byte changes

Get SHA256 hash

Now generate sha256sum of block_1010.bin sha256sum

Answer

fff054f33c2134e0230efb29dad515064ac97aa8c68d33c58c01213a0d408afb

Remarks

With all of the objectives complete, let's return to Santa's office to see if the door with the padlock is now open.

Santa's office no padlock

Eve Snowshoes, Santa and Jack Frost are waiting on Santa's Balcony.

The conclusion on Santa's Balcony

Eve Snowshoes

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!

Jack Frost

My plan was NEARLY perfect… but I never expected someone with your skills to come around and ruin my plan for ruining the holidays!

And now, they’re gonna put me in jail for my deeds.