netbookpros Posted May 27, 2011 Share Posted May 27, 2011 I need to produce 4 byte CRC32 checksums for UDP packets sent to an rcon tool for an online game. The (brief) specification for formatting these UDP packets is here: http://www.battleye.com/downloads/BERConProtocol.txt I have been converting the results of the CRC32() to hex and inserting it successfully in the correct part of the packet. The checksum result however is different from one that I packet captured from a working rcon tool. I have tried various methods of converting the int that CRC32 produces but have been unsuccessful in producing the correct checksum. For reference below is the captured correct packet from the working tool. All data is the same as the packets my tool produces except for the checksum. The checksum is bytes 3,4,5 & 6. and is formed (to my understanding) by performing a CRC32 check on the subsequent bytes. (From Smartsniff) 00000000 42 45 D5 C3 FB ED FF 00 61 62 63 64 65 31 32 BE...... abcde12 If anyone has a working CRC32 class that could reproduce the successful hash above or has any pointers in the correct direction I would be very thankful. Quote Link to comment Share on other sites More sharing options...
PFMaBiSmAd Posted May 27, 2011 Share Posted May 27, 2011 Did you read this note in the crc32 documentation - Because PHP's integer type is signed, and many crc32 checksums will result in negative integers, you need to use the "%u" formatter of sprintf() or printf() to get the string representation of the unsigned crc32 checksum. Quote Link to comment Share on other sites More sharing options...
netbookpros Posted May 27, 2011 Author Share Posted May 27, 2011 I have been using sprintf() but it is still producing incorrect checksums. Could this be because I am running x64 win7? EDIT: I'm fairly inexperienced so this could be down to a really silly mistake or misunderstanding. I won't take it to heart if you tell me I've done something stupid! $str = (chr(0xFF).chr(0x00).chr(0x61).chr(0x62).chr(0x63).chr(0x64).chr(0x65).chr(0x31).chr(0x32)); // String Including the LEAD two chars (FF 00) [i have tried it without these.] $crcint = crc32($str); $crc2 = sprintf("%u", $crcint);; $crcstr = dechex($crcint); //Below code is an inefficient way of turning the result of dechex into formatted hex e.g 0xFF $x = ('0x'); $a = substr($crcstr, 0, 2); $a = $x.$a; $b = substr($crcstr, 2, 4); $b = $x.$b; $c = substr($crcstr, 4, 6); $c = $x.$c; $d = substr($crcstr, 6, ; $d = $x.$d; //Then each character is inserted into the final message $msg = chr(0x42).chr(0x45).chr($a).chr($b).chr($c).chr($d).chr(0xFF).chr(0x00).chr(0x61).chr(0x62).chr(0x63).chr(0x64).chr(0x65).chr(0x31).chr(0x32); Quote Link to comment Share on other sites More sharing options...
netbookpros Posted May 27, 2011 Author Share Posted May 27, 2011 Ok I've now revised my code and used some other peoples functions to fix a few things. It now produces the hex checksum: DF C3 FB ED The target checksum is: D5 C3 FB ED So close! Anyone any ideas why it would be getting this only slightly wrong? A larger sample of the revised code below: <?php function connect (){ $this->security = new security(); $this->connection = fsockopen("udp://$this->server_ip", $this->server_port, &$errno, &$errstr, 5); stream_set_timeout($this->connection, 5); if (!$this->connection){ echo ("Connection Failed: $errno, $errstr"); } else{ $str = (chr(0xFF).chr(0x00).chr(0x61).chr(0x62).chr(0x63).chr(0x64).chr(0x65).chr(0x31).chr(0x32)); $crcunsign = $this->computeUnsignedCRC32($str); $crcstr = $this->dec_to_hex($crcunsign); $x = ('0x'); $a = substr($crcstr, 0, 2); $a = $x.$a; $b = substr($crcstr, 2, 2); $b = $x.$b; $c = substr($crcstr, 4, 2); $c = $x.$c; $d = substr($crcstr, 6, 2); $d = $x.$d; echo ($d.$c.$b.$a); $msg = chr(0x42).chr(0x45).chr($d).chr($c).chr($b).chr($a).chr(0xFF).chr(0x00).chr(0x61).chr(0x62).chr(0x63).chr(0x64).chr(0x65).chr(0x31).chr(0x32); fwrite($this->connection,$msg); $this->listen(); } } function listen(){ $last_message = fread($this->connection,16); } function send($data){ } function computeUnsignedCRC32($str){ sscanf(crc32($str), "%u", $var); return $var; } function dec_to_hex($dec) { $sign = ""; // suppress errors if( $dec < 0){ $sign = "-"; $dec = abs($dec); } $hex = Array( 0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f' ); do { $h = $hex[($dec%16)] . $h; $dec /= 16; } while( $dec >= 1 ); return $sign . $h; } } ?> Quote Link to comment Share on other sites More sharing options...
netbookpros Posted May 27, 2011 Author Share Posted May 27, 2011 Ok further update. Tested on a 32bit server and managed to produce the correct checksum, confirming that it is due to my OS being 64bit. Any ideas on a fix for this problem? Quote Link to comment Share on other sites More sharing options...
netbookpros Posted June 5, 2011 Author Share Posted June 5, 2011 OK problem Solved: For the reference of anyone who stumbles across this. The correct way to do it is as follows. Should work on both 32 and 64 bit. Adding zero to the result of the checksum fixed it for me. <?php sscanf(crc32($str), "%u", $crc); $crchex = dechex($crc + 0); ?> Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.