Jump to content

PHP5 CRC32()


netbookpros

Recommended Posts

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.

 

Link to comment
Share on other sites

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.

 

 

Link to comment
Share on other sites

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);

Link to comment
Share on other sites

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!  :confused:

 

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;
} 
}
?>

 

Link to comment
Share on other sites

  • 2 weeks later...

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);
?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.