11b. Naughty/Nice List with Blockchain Investigation Part 2
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.
- Blockchain ... Chaining
- Block Investigation
- Imposter Block Event
- Unique Hash Collision
- Minimal Changes
- Blockchain Talk
The following files should be retrieved to complete this objective:
- The Naught/Nice Blockchain from Santa's desk - https://download.holidayhackchallenge.com/2020/blockchain.dat
- The suggested tools to help - https://download.holidayhackchallenge.com/2020/OfficialNaughtyNiceBlockchainEducationPack.zip
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
#!/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
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
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)
0x49had to be changed from a 1 (
0x31) to a 0 (
0x30) (see https://man7.org/linux/man-pages/man7/ascii.7.html)
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 (
0x89 needs to be changed. By experimentation it was found that the value of the byte needed to be changed from
./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:
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 (
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
Get SHA256 hash
Now generate sha256sum of block_1010.bin
With all of the objectives complete, let's return to Santa's office to see if the door with the padlock is now open.
Eve Snowshoes, Santa and Jack Frost are waiting on Santa's Balcony.
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!
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!
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.