in reply to Re: Forge CRCs
in thread Forge CRCs
You don't have to append to the end to get whatever CRC you want, either. By changing any 4 consecutive bytes, you can set the internal state of the CRC register however you like, as the code below shows. In certain conditions, you can do it with non-consecutive bytes, but it usually takes a little bit of a brute force search.
Once again, you could optimize the "for (1..8)" loops with a lookup table (that's the ordinary way of calculating CRCs). It's easier to see what's happening this way, though.
# the usual crc32 polynomial my $crc_poly = 0xedb88320; my $crc_size = 32; my $initial_str = "foo bar"; my $final_str = "baz blat"; my $desired_crc = 0x12345678; my $magic = forward_crc($initial_str, 0xffffffff) ^ reverse_crc("\0\0\0\0".$final_str, $desired_crc^0xffffffff); my $forged_str = $initial_str . pack("V",$magic) . $final_str; use String::CRC32; printf "%x\n", crc32($forged_str); # calculate an ordinary crc of $string, # given the initial register contents sub forward_crc { my ($str, $reg) = @_; foreach (split //, $str) { $reg ^= ord; for (1..8) { $reg = ($reg & 1) ? ($reg >> 1) ^ $crc_poly : $reg >> 1; } } return $reg; } # forward_crc # given the final register contents, calculate # what the register state was before $str sub reverse_crc { my ($str, $reg) = @_; my $poly = ($crc_poly << 1) ^ 1; my $highbit = 1 << ($crc_size - 1); foreach (reverse split //, $str) { for (1..8) { $reg = ($reg & $highbit) ? ($reg << 1) ^ $poly : $reg << 1; } $reg ^= ord; } return $reg; } # reverse_crc
|
|---|