During the competition, my team got 1st place and i got 1st blood in this challenge. I've been facing some CRC32 challenge that required me to do cracking, but this one is not usual. It requires me to do some preprocessing before cracking using crchack.
Analyzing the Code
Given source code below
#!/usr/bin/python3import base64# polynomial = ????crc_32_tab = [0x00000000,0xd1a61e95,0x05d75b55,0xd47145c0,0x0baeb6aa,0xda08a83f,0x0e79edff,0xdfdff36a,0x175d6d54,0xc6fb73c1,0x128a3601,0xc32c2894,0x1cf3dbfe,0xcd55c56b,0x192480ab,0xc8829e3e,0x2ebadaa8,0xff1cc43d,0x2b6d81fd,0xfacb9f68,0x25146c02,0xf4b27297,0x20c33757,0xf16529c2,0x39e7b7fc,0xe841a969,0x3c30eca9,0xed96f23c,0x32490156,0xe3ef1fc3,0x379e5a03,0xe6384496,0x5d75b550,0x8cd3abc5,0x58a2ee05,0x8904f090,0x56db03fa,0x877d1d6f,0x530c58af,0x82aa463a,0x4a28d804,0x9b8ec691,0x4fff8351,0x9e599dc4,0x41866eae,0x9020703b,0x445135fb,0x95f72b6e,0x73cf6ff8,0xa269716d,0x761834ad,0xa7be2a38,0x7861d952,0xa9c7c7c7,0x7db68207,0xac109c92,0x649202ac,0xb5341c39,0x614559f9,0xb0e3476c,0x6f3cb406,0xbe9aaa93,0x6aebef53,0xbb4df1c6,0xbaeb6aa0,0x6b4d7435,0xbf3c31f5,0x6e9a2f60,0xb145dc0a,0x60e3c29f,0xb492875f,0x653499ca,0xadb607f4,0x7c101961,0xa8615ca1,0x79c74234,0xa618b15e,0x77beafcb,0xa3cfea0b,0x7269f49e,0x9451b008,0x45f7ae9d,0x9186eb5d,0x4020f5c8,0x9fff06a2,0x4e591837,0x9a285df7,0x4b8e4362,0x830cdd5c,0x52aac3c9,0x86db8609,0x577d989c,0x88a26bf6,0x59047563,0x8d7530a3,0x5cd32e36,0xe79edff0,0x3638c165,0xe24984a5,0x33ef9a30,0xec30695a,0x3d9677cf,0xe9e7320f,0x38412c9a,0xf0c3b2a4,0x2165ac31,0xf514e9f1,0x24b2f764,0xfb6d040e,0x2acb1a9b,0xfeba5f5b,0x2f1c41ce,0xc9240558,0x18821bcd,0xccf35e0d,0x1d554098,0xc28ab3f2,0x132cad67,0xc75de8a7,0x16fbf632,0xde79680c,0x0fdf7699,0xdbae3359,0x0a082dcc,0xd5d7dea6,0x0471c033,0xd00085f3,0x01a69b66,0xd34db33f,0x02ebadaa,0xd69ae86a,0x073cf6ff,0xd8e30595,0x09451b00,0xdd345ec0,0x0c924055,0xc410de6b,0x15b6c0fe,0xc1c7853e,0x10619bab,0xcfbe68c1,0x1e187654,0xca693394,0x1bcf2d01,0xfdf76997,0x2c517702,0xf82032c2,0x29862c57,0xf659df3d,0x27ffc1a8,0xf38e8468,0x22289afd,0xeaaa04c3,0x3b0c1a56,0xef7d5f96,0x3edb4103,0xe104b269,0x30a2acfc,0xe4d3e93c,0x3575f7a9,0x8e38066f,0x5f9e18fa,0x8bef5d3a,0x5a4943af,0x8596b0c5,0x5430ae50,0x8041eb90,0x51e7f505,0x99656b3b,0x48c375ae,0x9cb2306e,0x4d142efb,0x92cbdd91,0x436dc304,0x971c86c4,0x46ba9851,0xa082dcc7,0x7124c252,0xa5558792,0x74f39907,0xab2c6a6d,0x7a8a74f8,0xaefb3138,0x7f5d2fad,0xb7dfb193,0x6679af06,0xb208eac6,0x63aef453,0xbc710739,0x6dd719ac,0xb9a65c6c,0x680042f9,0x69a6d99f,0xb800c70a,0x6c7182ca,0xbdd79c5f,0x62086f35,0xb3ae71a0,0x67df3460,0xb6792af5,0x7efbb4cb,0xaf5daa5e,0x7b2cef9e,0xaa8af10b,0x75550261,0xa4f31cf4,0x70825934,0xa12447a1,0x471c0337,0x96ba1da2,0x42cb5862,0x936d46f7,0x4cb2b59d,0x9d14ab08,0x4965eec8,0x98c3f05d,0x50416e63,0x81e770f6,0x55963536,0x84302ba3,0x5befd8c9,0x8a49c65c,0x5e38839c,0x8f9e9d09,0x34d36ccf,0xe575725a,0x3104379a,0xe0a2290f,0x3f7dda65,0xeedbc4f0,0x3aaa8130,0xeb0c9fa5,0x238e019b,0xf2281f0e,0x26595ace,0xf7ff445b,0x2820b731,0xf986a9a4,0x2df7ec64,0xfc51f2f1,0x1a69b667,0xcbcfa8f2,0x1fbeed32,0xce18f3a7,0x11c700cd,0xc0611e58,0x14105b98,0xc5b6450d,0x0d34db33,0xdc92c5a6,0x08e38066,0xd9459ef3,0x069a6d99,0xd73c730c,0x034d36cc,0xd2eb2859]defcrc32(data): crc =0xfffffffffor byte in data: crc = crc_32_tab[(crc ^ byte) &0xff]^ (crc >>8) crc = crc ^0xffffffffreturn crc &0xffffffffFLAG =open('flag.txt', 'r').read()if__name__=='__main__':try:print('Enter your credential >> ', end='') cred = base64.b64decode(input()) username, level ='',''for line instr(cred, 'utf-8').splitlines(): s = line.split(':')iflen(s)==2:if s[0]=='username': username = s[1]elif s[0]=='level': level = s[1]if username =='':print('Invalid credential!')exit(1)if username =='nino': crc =crc32(cred)if crc !=0xCAFEBABE:print('You are not my waifu!')exit(1)print()print(f'hi {username}, please choose :^)')print('1. do nothing')print('2. read flag')print('>> ', end='') choice =int(input())if choice ==1:print('You just did nothing...')elif choice ==2:if username !='nino':print('Only my waifu can read the flag!')else:print(FLAG)exceptExceptionas e:print(e)exit(1)
It can be seen that the code above implements the crc32 hash, but the crc32 table is different from the general one. The purpose of this question is clear, the point is to find collisions/get a hash value with a predetermined prefix. We found a tool to get collisions on crc32, namely crchack . However, crchack needs several parameters to get collisions in crc32 implementations that do not use default values, for example the default value for the polynomial.
Cracking CRC32
To get the polynomial we use the naive method, namely bruteforce because 32 bits is not too much. Here's the code for bruteforce
A valid value was obtained, which is 0xd34db33f
#include<stdio.h>intmain () {long i;int j;long tmp,v;for (i =0; i <4294967296; i++){ v =1;for (j =8; j >0; --j){ v = (v &1) ? (v >>1) ^ i : (v >>1); } tmp = v;if((tmp&0xffffffff)==0xd1a61e95){// 0xd34db33fprintf("%lx%lx\n",i,tmp); } }return0; }
After getting the polynomial value we realized that the problem implemented crc forward while crchack implemented crc reverse.