2015-10-01 86 views
2

我移植以下從拆解的x86二進制C代碼時:整蠱整數溢出移植C到C#

(unsigned __int16) ~ (_WORD) crc32^length * ~crc32; 

這是我在C#中移植的代碼:

(uint) (~(ushort) crc32)^length * ~crc32) 

而且下面有表與一些計算值。

Expected | Actual (C#) 
-----------+------------ 
0x1082B9CB | 0x6082B9CB 
0x30389AF7 | 0x20389AF7 
0xD0EF1CD6 | 0xE0EF1CD6 

正如你所看到的,最後三個字節是正確的。只是第一個字節幾乎沒有移位,但我看不出任何模式與其他模式的區別。

任何想法如何解決我的C#代碼,所以它給予預期的輸出?


示例值(C#語法):

uint crc32 = 0x7601A9C5; 
int length = 17; 

他們應該評估爲0xD0EF1CD6,但給0xE0EF1CD6代替。


編輯: 我可能忘了提及一件重要的事情。輸出以十六進制符號的底層原始字節表示。

工作的代碼示例:https://ideone.com/Z8eONJ

Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(checksum))); 
+2

你能舉出'crc32'和''長度'應該使你的期望值的例子值嗎? – vcsjones

+3

看起來你的演員陣容倒退了。 '_WORD - > uint','__int16-> ushort' –

+0

@RobertMcKee:我認爲__int16和ushort在C#中是相等的?這不正確嗎?我添加了示例值,所以如果您認爲它有幫助,請添加答案。 – stil

回答

0

的問題是與CRC32實現。看來,我反彙編的二進制文件並沒有否定返回值,這在大多數CRC32實現中通常是這種情況。

public static class Crc32 
{ 
    private static readonly uint[] _table = 
    { 
     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 
     0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 
     ... 
    }; 

    public static uint ComputeChecksum(byte[] bytes) 
    { 
     var crc = 0xffffffff; 
     for (var i = 0; i < bytes.Length; i++) 
     { 
      var t = bytes[i]; 
      var index = (byte) ((crc & 0xff)^t); 
      crc = (crc >> 8)^_table[index]; 
     } 
     return ~crc; // or maybe return crc; 
    } 
} 

因此,代碼:

(uint) (~(ushort) crc32)^length * ~crc32) 

簡化爲:

(uint) ((ushort) crc32)^length * crc32) 

現在它返回預期的輸出。 花了我比我願意承認的更長的時間...