I found a code to reverse CRC32 but I don't know how it works, because im not that good in programming, I just started. I just want to compare 2 files, the old and the new one, then in the new fix the CRC32 adding 4 bytes at the end of the file, so the 2 files will have the same CRC32. Here is the code, is in C#:
public class Crc32
{
public const uint poly = 0xedb88320;
public const uint startxor = 0xffffffff;
static uint[] table = null;
static uint[] revtable = null;
public void FixChecksum(byte[] bytes, int length, int fixpos, uint wantcrc)
{
if (fixpos + 4 > length) return;
uint crc = startxor;
for (int i = 0; i < fixpos; i++) {
crc = (crc >> 8) ^ table[(crc ^ bytes[i]) & 0xff];
}
Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 4);
crc = wantcrc ^ startxor;
for (int i = length - 1; i >= fixpos; i--) {
crc = (crc << 8) ^ revtable[crc >> (3 * 8)] ^ bytes[i];
}
Array.Copy(BitConverter.GetBytes(crc), 0, bytes, fixpos, 4);
}
public Crc32()
{
if (Crc32.table == null) {
uint[] table = new uint[256];
uint[] revtable = new uint[256];
uint fwd, rev;
for (int i = 0; i < table.Length; i++) {
fwd = (uint)i;
rev = (uint)(i) << (3 * 8);
for (int j = 8; j > 0; j--) {
if ((fwd & 1) == 1) {
fwd = (uint)((fwd >> 1) ^ poly);
} else {
fwd >>= 1;
}
if ((rev & 0x80000000) != 0) {
rev = ((rev ^ poly) << 1) | 1;
} else {
rev <<= 1;
}
}
table[i] = fwd;
revtable[i] = rev;
}
Crc32.table = table;
Crc32.revtable = revtable;
}
}
}
Here's some PHP code that will also do what you're looking for I spent a great deal of time trying to do this for legitimate purposes so I hope it helps someone
Functions like this could be used to:
To test crc32 strings online you can use: http://www.lammertbies.nl/comm/info/crc-calculation.html
See http://www.reversing.be/article.php?story=20061209172953555 from where this was adapted from as I'm not the original author, the original spent a great deal of time on his essay, and it helped in no small way
Here's PHP code which can be used to modify a given file as follows:
<?php
//Calculate the original file's CRC32
$DesiredCRC32 = hexdec(hash_file('crc32b','originalcleanfile.ext'));
//Calculate the newfile's current CRC
$CurrentIncorrectCRC32 = hexdec(hash_file('crc32b','newupdatedfile.ext'));
//Generate a 4 byte string that, if appended to the newfile will result in the original CRC32
echo modCRC($DesiredCRC32,$CurrentIncorrectCRC32);
// I should note that the original guy that posted this has some incorrect calcs on his page
// but if you read carefully and understand the math, you can pick up where it's incorrect
// and learn a thing or two (I beleive last time I tested this code it was accurate)
// if you wanted to do something via the CLI you could use something like:
parse_str(implode('&', array_slice($argv, 1)), $_GET);
// and grab the files w/
$file1 = $_GET['a'];
//... etc.
//then you could run it via something like this:
//c:\php\php -f somefile.php a=c:\original.txt b=c:\new.txt c=c:\newwithcrc.txt
public static function modCRC($ExistingCRC, $DesiredCRC){
$crc32lookup = array(
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
);
//More Description:
//Want to append bytes: X Y Z W
//Take for register a3 a2 a1 a0 (a is the 'already calculated' crc for string)
//Note that a3 is the most significant byte and a0 the least.
// f is the wanted new CRC byte string, and xyzw is the modification pad
/*
I'll show it a little different way:
a0 + X =(1) points to b3 b2 b1 b0 in table
a1 + b0 + Y =(2) points to c3 c2 c1 c0 in table
a2 + b1 + c0 + Z =(3) points to d3 d2 d1 d0 in table
a3 + b2 + c1 + d0 + W =(4) points to e4 e3 e2 e1 in table
b3 + c2 + d1 + e0 =f0
c3 + d2 + e1 =f1
d3 + e2 =f2
e3 =f3
(1) (2) (3) (4)
(figure 4)
This is reversed in the same way as the 16bit version. I shall give an example with real values. For the table values use the CRC-32 table in the appendix.
Take for CRC register before, a3 a2 a1 a0 -> AB CD EF 66
Take for CRC register after, f3 f2 f1 f0 -> 56 33 14 78 (wanted value)
Here we go:
First byte of entries entry value
e3=f3 =56 -> 35h=(4) 56B3C423 for e3 e2 e1 e0
d3=f2+e2 =33+B3 =E6 -> 4Fh=(3) E6635C01 for d3 d2 d1 d0
c3=f1+e1+d2 =14+C4+63 =B3 -> F8h=(2) B3667A2E for c3 c2 c1 c0
b3=f0+e0+d1+c2=78+23+5C+66=61 -> DEh=(1) 616BFFD3 for b3 b2 b1 b0
Now we have all needed values, then
X=(1)+ a0= DE+66=B8
Y=(2)+ b0+a1= F8+D3+EF=C4
Z=(3)+ c0+b1+a2= 4F+2E+FF+CD=53
W=(4)+d0+c1+b2+a3=35+01+7A+6B+AB=8E
(final computation)
*/
$ExistingCRC = ~$ExistingCRC;
$DesiredCRC = ~$DesiredCRC;
//a3a2a1a0
$a3 = (($ExistingCRC & 0xFF000000) >> 24) & 0x000000FF;
$a2 = ($ExistingCRC & 0x00FF0000) >> 16;
$a1 = ($ExistingCRC & 0x0000FF00) >> 8;
$a0 = ($ExistingCRC & 0x000000FF);
//f3f2f1f0
$f3 = (($DesiredCRC & 0xFF000000) >> 24) & 0x000000FF;
$f2 = ($DesiredCRC & 0x00FF0000) >> 16;
$f1 = ($DesiredCRC & 0x0000FF00) >> 8;
$f0 = ($DesiredCRC & 0x000000FF);
//echo "Existing CRC:" . dechex($ExistingCRC) . " DesiredCRC:" . dechex($DesiredCRC) . "<BR>";
//echo "a3:" . dechex($a3) . " a2:" . dechex($a2) . " a1:" . dechex($a1) . " a0:" . dechex($a0) . "<br>";
//echo "f3:" . dechex($f3) . " f2:" . dechex($f2) . " f1:" . dechex($f1) . " f0:" . dechex($f0) . "<br>";
//capture e3/e2/e1/e0/(4) values
for ($i = 0; $i < 256; $i++)
{
if (($crc32lookup[$i] & 0xFF000000 ) == ($DesiredCRC & 0xFF000000)){
$e3 = (($crc32lookup[$i] & 0xFF000000) >> 24) & 0x000000FF;
$e2 = ($crc32lookup[$i] & 0x00FF0000) >> 16;
$e1 = ($crc32lookup[$i] & 0x0000FF00) >> 8;
$e0 = ($crc32lookup[$i] & 0x000000FF);
$four = $i;
break;
}
}
//echo "e3:" . dechex($e3) . " e2:" . dechex($e2) . " e1:" . dechex($e1) . " e0:" . dechex($e0) . "<br>";
//$d3=f2+e2 =33+B3 =E6 -> 4Fh=(3) E6635C01 for d3 d2 d1 d0
$d3 = $f2^$e2; //lookup $d3 and assign the values for d2/d1/d0/(3)
for ($i = 0; $i < 256; $i++)
{
if (($crc32lookup[$i] & 0xFF000000 ) == ($d3 << 24)){
$d2 = ($crc32lookup[$i] & 0x00FF0000) >> 16;
$d1 = ($crc32lookup[$i] & 0x0000FF00) >> 8;
$d0 = ($crc32lookup[$i] & 0x000000FF);
$three = $i;
break;
}
}
//echo "d3:" . dechex($d3) . " d2:" . dechex($d2) . " d1:" . dechex($d1) . " d0:" . dechex($d0) . "<br>";
//c3=f1+e1+d2 =14+C4+63 =B3 -> F8h=(2) B3667A2E for c3 c2 c1 c0
$c3 = $f1^$e1^$d2;
for ($i = 0; $i < 256; $i++)
{
if (($crc32lookup[$i] & 0xFF000000 ) == ($c3 << 24)){
$c2 = ($crc32lookup[$i] & 0x00FF0000) >> 16;
$c1 = ($crc32lookup[$i] & 0x0000FF00) >> 8;
$c0 = ($crc32lookup[$i] & 0x000000FF);
$two = $i;
break;
}
}
//echo "c3:" . dechex($c3) . " c2:" . dechex($c2) . " c1:" . dechex($c1) . " c0:" . dechex($c0) . "<br>";
//b3=f0+e0+d1+c2=78+23+5C+66=61 -> DEh=(1) 616BFFD3 for b3 b2 b1 b0
$b3 = $f0^$e0^$d1^$c2;
for ($i = 0; $i < 256; $i++)
{
if (($crc32lookup[$i] & 0xFF000000 ) == ($b3 << 24)){
$b2 = ($crc32lookup[$i] & 0x00FF0000) >> 16;
$b1 = ($crc32lookup[$i] & 0x0000FF00) >> 8;
$b0 = ($crc32lookup[$i] & 0x000000FF);
$one = $i;
break;
}
}
/*
Now we have all needed values, then
X=(1)+ a0= DE+66=B8
Y=(2)+ b0+a1= F8+D3+EF=C4
Z=(3)+ c0+b1+a2= 4F+2E+FF+CD=53
W=(4)+d0+c1+b2+a3=35+01+7A+6B+AB=8E
(final computation)
*/
$X = $one ^ $a0;
$Y = $two ^ $b0^$a1;
$Z = $three ^ $c0^$b1^$a2;
$W = $four ^ $d0 ^ $c1 ^ $b2^$a3;
//echo "Four:" . dechex($four) . " Three:" .dechex($three)." Two:".dechex($two)."One:" .dechex($one) . "<br>";
//echo "X:" . dechex($X) . " Y:" . dechex($Y) . " Z:" . dechex($Z) . " W:" . dechex($W) . "<br>";
return chr($X) . chr($Y) . chr($Z) . chr($W);
}
?>
Would you like to know how it works, or how to use it?
If it's the later, than from the code signature:
public void FixChecksum(byte[] bytes, int length, int fixpos, uint wantcrc)
It seems that you put the contents of your second file to an array (with additional 4 bytes at the end for the fix), and pass it as the bytes
parameter. You pass the lengths of this array as the length
parameter, you pass the offset to the place to insert the fix to, (in this case length - 4) as fixpos
parameter, and you put your desired CRC as wantcrc
parameter, you can obtain this value, by calculating CRC of the first file.
FixChecksum
method appears to write the 4 bytes fix in the array you have provided at the offset you have provided. After you've made the call to FixChecksum
you just need to write the results to your second file.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.