EQEmulator Forums

EQEmulator Forums (https://www.eqemulator.org/forums/index.php)
-   Development::Tools (https://www.eqemulator.org/forums/forumdisplay.php?f=593)
-   -   CRC32 Checksum How to in Player Profile (https://www.eqemulator.org/forums/showthread.php?t=25190)

cybernine186 05-07-2008 06:31 PM

CRC32 Checksum How to in Player Profile
 
I have developed a tool for viewing/editing the player profile in the character_ table. The viewing and editing works for int values only (Which almost every value seems to be a numeric value) but I am having trouble trying to figure out how the CRC32 check works. So far from my research the CRC32's value runs off the sizeof value. I am using PHP and it has build in capabilities for CRC32 and sizeof. Can anyone help me or point me in the right direction of being able to recreate the checksum in the player profile in the database or is the checksum totally worthless to the EQ client?

Theeper 05-07-2008 08:46 PM

Take a look at crc32.cpp. You'll need the data from "int32 CRC32Table[256]" at the top. Also the function "SetEQChecksum()" is passed a reference to the profile and it creates the checksum and then copies it into the profile.

I don't know if the checksum is actually used by the server, but it is set.

I wrote a C++ app a while back to display the profile using the profile struct from the server code. I started to make it write the profile back to the DB but was unsure of what type of problems it could create. I got lazy and never finished it.

I do know that some events cause the server to save the profile like a change in coin, zoning and inventory changes. Spells don't seem to cause the server to save the profile.

You'll need to unpack() the data with PHP unless you're just doing a string replace on the binary data. AndMetal wrote a nice PHP script to unpack the profile here.

cybernine186 05-07-2008 10:56 PM

I am using substr_replace in php to just replace the data that is changed instead of repacking the entire blob. Just seems to make more since to me that way. So far everything in the editor works perfectly, all char info, money, features, colors, languages, skills, etc. Just mostly the basics no LDON stuff yet. But that still doesn't tell me what the CRC32 checksum uses for the actual checksum. It has to be part or all of the info in the profile but what. I ant a C++ expert so any help is appreciated.

AndMetal 05-08-2008 12:29 AM

I'll give you a hint: don't worry about the checksum.

I tried messing with it a little bit, until I discovered there wasn't any real reason to. This is what I came up with:

From my PHP-based utility:
Code:

  73 /*
  74 SetEQChecksum taken from crc32.cpp source code, translated to PHP
  75
  76 Original source:
  77 void CRC32::SetEQChecksum(uchar* in_data, int32 in_length)
  78 {
  79        unsigned long data;
  80    unsigned long check = 0xffffffff;
  81
  82        assert(in_length >= 4 && in_data);
  83
  84    for(int32 i=4; i<in_length; i++)
  85    {
  86        data = in_data[i];
  87        data = data ^ (check);
  88        data = data & 0x000000ff;
  89        check = check >> 8;
  90        data = CRC32Table[data];
  91        check = check ^ data;
  92    }
  93
  94    memcpy(in_data, (char*)&check, 4);
  95 }
  96 */
  97 function SetEQChecksum($in_data) {
  98        $in_length = strlen($in_data);
  99        $check = 0xffffffff;
  100        for ($i=4; $i<in_length; $i++) {
  101                $data = $in_data[$i];
  102                $data = $data XOR ($check);
  103                $data = $data & 0x000000ff;
  104                $check = $check >> 8;
  105                $data = $CRC32Table[$data];
  106                $check = $check XOR $data;
  107        };
  108        return $check;
  109 };

Plus the CRC32Table:
Code:

  380 $CRC32Table = array(
  381        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
  382        0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
  383        0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
  384        0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
  385        0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
  386        0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  387        0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
  388        0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
  389        0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
  390        0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
  391        0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
  392        0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  393        0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
  394        0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
  395        0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
  396        0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
  397
  398        0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
  399        0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  400        0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
  401        0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
  402        0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
  403        0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
  404        0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
  405        0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  406        0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
  407        0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
  408        0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
  409        0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
  410        0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
  411        0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  412        0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
  413        0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
  414
  415        0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
  416        0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
  417        0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
  418        0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  419        0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
  420        0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
  421        0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
  422        0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
  423        0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
  424        0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  425        0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
  426        0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
  427        0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
  428        0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
  429        0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
  430        0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  431
  432        0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
  433        0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
  434        0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
  435        0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
  436        0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
  437        0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  438        0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
  439        0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
  440        0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
  441        0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
  442        0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
  443        0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  444        0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
  445        0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
  446        0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
  447        0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  448 );

Unfortunately, it just ANDs the entire thing to all binary 1's. I didn't really try anything else after that, but I'm sure it's pretty straightforward to figure out, it will just take some debugging.

Btw, if you're looking for a somewhat basic way to just look at the profile blob, I put together a script to break it down:
PHP Code:

<html>

<head>

<?php

// Database Info
$db_user "eqemu";            // Username
$db_pass "password";    // Password
$db_host "localhost";        // Hostname/IP Address
$db_name "peq";            // Database Name
$db mysql_connect($db_host,$db_user,$db_pass) or die(mysql_error());
mysql_select_db($db_name);
// include "../includes/constants.php";

// Default settings for output
$field "profile";
$line_size 16;
$limit 20;        // Max lines to display per page. 0 to show all
$offset 0;        // Usually won't change from 0, but can be used to set an offset starting point (in rows)

// Set values to defaults if not passed in $_GET
if (!isset($_GET[field]) || ($_GET[field] == "")) $_GET[field] = $field;
if (!isset(
$_GET[line_size]) || ($_GET[line_size] == "")) $_GET[line_size] = $line_size;
if (!isset(
$_GET[limit]) || ($_GET[limit] == "")) $_GET[limit] = $limit;
if (!isset(
$_GET[offset]) || ($_GET[offset] == "")) $_GET[offset] = $offset;

?>

<title></title>

<style type="text/css">
td 
{
    text-align: center;
    /* width: 5px; */
}
</style>

</head>

<body>

<form name="NoID" method="GET" action="">Enter ID: <input type="text" name="id" size="2" value="<?php echo $_GET['id']?>"><button type="submit">Go</button>&nbsp;<button type="reset">Reset</button><br>
<input type="radio" name="field" value="profile"<?php if ($_GET[field] == "profile") echo " checked"?>>Profile</input> <input type="radio" name="field" value="extprofile"<?php if ($_GET[field] == "extprofile") echo " checked"?>>Extended Profile</input><br>
Characters per line: <input type="text" name="line_size" size="2" value="<?php echo $_GET[line_size]?>"><br>
Lines per page: <input type="text" name="limit" size="3" value="<?php echo $_GET[limit]?>"><br>
Start: <input type="text" name="offset" size="3" value="<?php echo $_GET[offset]?>"><br>
</form>

<?php

if ($_GET['id']) {

    
flush(); ob_flush();

    
$query "SELECT " $_GET[field] . " FROM character_ WHERE id='" $_GET['id'] . "' ";
    
$result mysql_query($query,$db);
    
$db_row mysql_fetch_array($result);
    
$total_chars strlen($db_row[$_GET[field]]);
    
$total_chars_len strlen($total_chars);

?>

<table border="1">
<form method="GET" action="">
<caption align="top" style="text-align:left">
<a href="?id=<?php echo $_GET['id']?>&line_size=<?php echo $_GET[line_size]?>&limit=<?php echo $_GET[limit]?>&offset=<?php if ($_GET[offset] - ($_GET[line_size] * $_GET[limit]) >= 0) {echo $_GET[offset] - ($_GET[line_size] * $_GET[limit]);};?>">&lt;&lt;Prev</a>
<a href="?id=<?php echo $_GET['id']?>&line_size=<?php echo $_GET[line_size]?>&limit=<?php echo $_GET[limit]?>&offset=<?php echo $_GET[offset] + ($_GET[line_size] * $_GET[limit]);?>">Next&gt;&gt;</a>
</caption>
</form>
<tr><td align="center">Row</td><td colspan="<?php echo $_GET[line_size]?>">Val</td><td colspan="<?php echo $_GET[line_size]?>">Char</td></tr>
<?php

    
if ($_GET[limit] == 0$_GET[limit] = ($total_chars $_GET[line_size]) - 1;
    for (
$row $_GET[offset]; $row <= ((($_GET[line_size] * $_GET[limit]) + $_GET[offset]) - 1) && $row <= $total_chars$row += $_GET[line_size]) {

?>
<tr><td align="right"><?php echo str_pad($row,$total_chars_len,0,STR_PAD_LEFT)?></td><?php
        
//Output for HEX
        
for ($char $row$char <= ($row + ($_GET[line_size] - 1)); $char++) {
?>
<td title="<?php echo str_pad($char,$total_chars_len,0,STR_PAD_LEFT)?>"><?php echo strtoupper(str_pad(dechex(ord($db_row[$_GET[field]][$char])),2,0,STR_PAD_LEFT))?></td><?php
        
};
        
        
// Output for Characters
        
for ($char $row$char <= ($row + ($_GET[line_size] - 1)); $char++) {
?>
<td title="<?php echo str_pad($char,$total_chars_len,0,STR_PAD_LEFT)?>"><?php
            $char_dec_val 
ord($db_row[$_GET[field]][$char]);
            echo 
"";
            if ((
$char_dec_val >= 33) && ($char_dec_val <= 126)) {echo $db_row[$_GET[field]][$char];}
            elseif (
$char_dec_val == 32) {echo "&nbsp;";};
?></td><?php
        
};
?>
</tr>
<?php
        flush
(); ob_flush();
    };
?>
</table>

<?php
};
?>

</body>

</html>

I'll eventually include it with the other stuff, but that's for another day.

Anyways, hope this points you in the right direction.


All times are GMT -4. The time now is 09:27 AM.

Powered by vBulletin®, Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.