『壹』 如何計算checksum
checksum的演算法沒有必然的,不同人的演算法不一定一樣。
最簡單的:全部位元組直接相加,按最大位元組數取模。
比較通用的:CRC,這個比較復雜,需要上網找專業的資料學習,或者網上應該有演算法代碼。
總之,checksum應該要通信雙方協議好演算法,才可以進行校驗。
『貳』 如何計算TCP的CHECKSUM
如何計算UDP/TCP檢驗和checksum
一、下面的圖是一個UDP的檢驗和所需要用到的所有信息,包括三個部分:
UDP偽首部
2.UDP首部
3.UDP的數據部分(切記不要遺漏該部分,否則就~吐血了~)
首先解釋下偽首部的概念,偽首部包含IP首部一些欄位。其目的是讓UDP兩次檢查數據是否已經正確到達目的地,只是單純為了做校驗用的。
還有一個概念十分重要,那就是16位UDP總長度,請注意該長度不是報文的總長度,而只是UDP(包括UDP頭和數據部分)的總長度(之前就是因為這個概念沒弄清楚,走了不少彎路,吐血~~)。
二、計算檢驗和(checksum)的過程很關鍵,主要分為以下幾個步驟:
把偽首部添加到UDP上;
2.計算初始時是需要將檢驗和欄位添零的;
3.把所有位劃分為16位(2位元組)的字
4.把所有16位的字相加,如果遇到進位,則將高於16位元組的進位部分的值加到最低位上,舉例,0xBB5E+0xFCED=0x1 B84B,則將1放到最低位,得到結果是0xB84C
5.將所有字相加得到的結果應該為一個16位的數,將該數取反則可以得到檢驗和checksum。
三、事實勝於雄辯,還是舉個例子來分析一下吧,該例子計算的是一個TCP的檢驗和(和UDP的演算法一致)
TCP計算檢驗和的報文結構如下所示:
抓包工具抓了一個TCP 的syn報文做研究,呵呵,下面就是整個報文:
首先將檢驗和部分添零;
2.然後將TCP偽首部部分,TCP首部部分,數據部分都劃分成16位的一個個16進制數;
3.將這些數逐個相加,記得溢出的部分加到最低位上,這是循環加法:
0xc0a8+ 0x0166+……+0x0402=0x9b49
4.最後將得到的結果取反,則可以得到檢驗和位0x64B6
按照上述步驟進行計算就可以得到檢驗和為0x64B6,大家也可以試試看
IP數據報只檢驗IP數據報的首部,但UDP檢驗的是把首部和數據部分一起都檢驗。
『叄』 java checksum的校驗方式
public class CRC {
/**
* CRC-CCITT(Kermit)驗證模式
* @param str
* @return
*/
public String CRC_CCITT_Kermit(String str) {
int j, b, rrrc, c, i;
String tmpBalance;
int k;
rrrc = 0;
tmpBalance = str;
int tmpInt, CharInt;
String tmpChar, tmpStr;
tmpStr = "";
int High;
int Low;
for (j = 1; j <= 3; j++) {
if (Character.isDigit(tmpBalance.charAt(2 * j - 2))) {
High = Integer.parseInt(tmpBalance.charAt(2 * j - 2) + "");
} else {
High = 0;
}
if (Character.isDigit(tmpBalance.charAt(2 * j - 1))) {
Low = Integer.parseInt(tmpBalance.charAt(2 * j - 1) + "");
} else {
Low = 0;
}
High = (High & 0xff) << 4;
High = High | Low;
k = High;
for (i = 1; i <= 8; i++) {
c = rrrc & 1;
rrrc = rrrc >> 1;
if ((k & 1) != 0) {
rrrc = rrrc | 0x8000;
}
if (c != 0) {
rrrc = rrrc ^ 0x8408;
}
k = k >> 1;
}
}
for (i = 1; i <= 16; i++) {
c = rrrc & 1;
rrrc = rrrc >> 1;
if (c != 0) {
rrrc = rrrc ^ 0x8408;
}
}
c = rrrc >> 8;
b = rrrc << 8;
rrrc = c | b;
tmpInt = rrrc;
tmpStr = "";
for (i = 1; i <= 4; i++) {
tmpChar = "";
CharInt = tmpInt % 16;
if (CharInt > 9) {
switch (CharInt) {
case 10:
tmpChar = "A";
break;
case 11:
tmpChar = "B";
break;
case 12:
tmpChar = "C";
break;
case 13:
tmpChar = "D";
break;
case 14:
tmpChar = "E";
break;
case 15:
tmpChar = "F";
break;
}
} else {
tmpChar = Integer.toString(CharInt);
}
tmpInt = tmpInt / 16;
tmpStr = tmpChar + tmpStr;
}
System.out.println("tmpStr:" + tmpStr);
return tmpStr;
}
/**
* CRC-CCITT(XModem)
* CRC-CCITT(0xFFFF)
* CRC-CCITT(0x1D0F)
* 校驗模式
* @param flag< XModem(flag=1) 0xFFFF(flag=2) 0x1D0F(flag=3)>
* @param str
* @return
*/
public String CRC_CCITT( int flag,String str) {
int crc = 0x00; // initial value
int polynomial = 0x1021;
byte[] bytes=str.getBytes();
switch(flag){
case 1:
crc=0x00;
break;
case 2:
crc=0xFFFF;
break;
case 3:
crc=0x1D0F;
break;
}
for (int index = 0 ; index< bytes.length; index++) {
byte b = bytes[index];
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7-i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
if (c15 ^ bit) crc ^= polynomial;
}
}
crc &= 0xffff;
str = Integer.toHexString(crc);
return str;
}
『肆』 checksum的編程實現
/// <summary>
/// 獲取校驗和,ASCII編碼
/// </summary>
/// <param name="s"></param>
/// <param checkSum="s"></param>
#region 獲取校驗和,ASCII編碼
/// <summary>
/// 獲取校驗和,ASCII編碼
/// </summary>
/// <param name="s"></param>
/// <param checkSum="s"></param>
private bool GetCheckSum( string s , out string checkSum )
{
checkSum = "";
if ( 0 == s.Length )
return false;
int sIndex = s.IndexOf( '$' ) + 1;
int eIndex = s.IndexOf( "**" );
string str = "";
if ( sIndex < 1 || eIndex < 1 )
str = s;
else
str = s.Substring( sIndex , eIndex - sIndex );
byte [] cs = Encoding.ASCII.GetBytes( str );
//核心部分
for ( int i = 0 ; i < cs.Length - 1 ; i++ )
{
cs [i + 1] = (byte) ( cs [i] ^ cs [i + 1] );
}
checkSum = cs [cs.Length - 1].ToString( "x2" ).ToUpper();
//checkSum = Convert.ToString( cs [cs.Length - 1] , 16 ).ToUpper();
return true;
}
『伍』 md5 checksum與md5是一樣嗎
兩個不是一概念。。
checksum是一個概念,一串數據或者一個文件的校驗碼,叫做checksum。
如果一個文件的checksum與原本的checksum不一樣的話,說明這個文件已經被改過了(被植入病毒或者廣告)。
從這個角度來理解的話,checksum的計算方法有多種多樣。
md5是一個加解密演算法,可以用在各方各面,如口令加密/文件加密等等。
md5 checksum,就是採用MD5方式的checksum的計算方法。
不知道這樣解釋是否夠明白。
『陸』 Checksum計算
XOR:異或
可以用交換結合律
每8個bit一組進行xor運算,最後結果8位就是要的校驗碼
41h xor 41h = 00h
02h xor 03h = 01h
41h xor 01h = 40h
16進制 40h = 10進制64 = ascii 的 @
『柒』 校驗和怎麼計算
檢驗和(checksum),在數據處理和數據通信領域中,用於校驗目的地一組數據項的和。它通常是以十六進制為數製表示的形式。如果校驗和的數值超過十六進制的FF,也就是255. 就要求其補碼作為校驗和。通常用來在通信中,尤其是遠距離通信中保證數據的完整性和准確性。
這些數據項可以是數字或在計算檢驗的過程中看作數字的其它字元串。校驗和(checksum)是指傳輸位數的累加,當傳輸結束時,接收者可以根據這個數值判斷是否接到了所有的數據。如果數值匹配,那麼說明傳送已經完成。TCP和UDP傳輸層都提供了一個校驗和與驗證總數是否匹配的服務功能。[1]
它通常是以十六進制為數製表示的形式
發送方生成檢驗和
1.將發送的進行檢驗和運算的數據分成若干個16位的位串,每個位串看成一個二進制數,這里並不管字元串代表什麼,是整數、浮點數還是點陣圖都無所謂。
2.將IP、UDP或TCP的PDU首部中的檢驗和欄位置為0,該欄位也參與檢驗和運算。
3.對這些16位的二進制數進行1的補碼和(one'scomplementsum)運算,累加的結果再取反碼即生成了檢驗碼。將檢驗碼放入檢驗和欄位中。
其中1的補碼和運算,即帶循環進位(end round carry)的加法,最高位有進位應循環進到最低位。反碼即二進制各位取反,如0111的反碼為1000。
接收方校驗檢驗和
1.接收方將接收的數據(包括檢驗和欄位)按發送方的同樣的方法進行1的補碼和運算,累加的結果再取反碼。
2.校驗,如果上步的結果為0,表示傳輸正確;否則,說明傳輸有差錯。
『捌』 16進制校驗和怎麼算
先把16進制轉成2進制:就是每位數轉換成4為2進制數!
6=0110 A=1010
再連起來,是01101010=106(10進制的)!
如果你不知道那些0和1是怎麼換來的我還可以告訴你!
『玖』 edid 的CHECKSUM怎麼算
1. EDID標准里對CheckSum的解釋是:The Checksum Byte (at address 7Fh) shall contain a value such that a checksum of the entire
128-byte BASE EDID equals 00h.
2. 也就是說,EDID里每隔127位 後面會跟隨一個 CheckSum值,這個十六進制值於前面127個十六進制值的 總和 等於十六進制XX00(其中XX為任意值)。
按十進制來說,就是讓這128個數的 總和 等於256的整數倍。
3. 通過CheckSum值,電腦就可以判斷檢測到的EDID在傳輸過程中有沒有發生錯誤。
『拾』 checksum文件 效驗怎麼算
校驗和(Checksum)
PE的可選映像頭(IMAGE_OPTION_HEADER)裡面,有一個Checksum欄位,是該文件的校驗和,一般EXE文件可以使0,但一些重要的和系統DLL及驅動文件必須有一個校驗和.
Windows 提供了一個API函數MapFileAndCheckSum 測試文件的Checksum,它位於IMAGEHLP.DLL鏈接庫里,其原型:
ULONG MapFileAndCheckSum
{
LPSTR FileName, // 文件名
LPDWORD HeaderSum, // 指向PE文件頭的CheckSum
LPDWORD new_checksum // 指向新計算出的Checksum
}
程序一旦運行後,new_checksum 地址處將放當前的文件的校驗和,old_checksum地址指向PE文件的checksum欄位
安全的方法是將此值放在注冊表裡,需要時比較.
內存映像校驗
磁碟文件完整性校驗可以抵抗解密者直接修改文件,但對內存補丁卻沒有效果,必須對內存關鍵的代碼進行校驗.
1 對整個代碼進行校驗
每個程序至少有一個代碼區塊和數據區塊,數據區塊屬性可讀寫,程序運行時全局變數通常會放在這里,這些數據會動態變化,因此校驗這部分是沒什麼意義,而代碼段只讀,存放的是程序代碼,在程序中數據數不會變的,因此用這部分進行內存校驗是可行的.
具體實現方法:
(1) 從內存中映像中得到PE相關數據,如代碼塊的RVA和內存大小
(2) 根據得到代碼區塊的RVA值和內存大小,計算出內存數據的CRC-32值
(3) 讀取自身文件先前存儲的CRC-32值(PE文件頭前一個欄位),這個值是通過軟體寫進去的.
(4) 比較兩個CRC-32值.
這樣比較內存的代碼段校驗,只要內存的數據被修改,就能發現。
BOOL CodeSectionCRC32()
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_SECTION_HEADER pSection = NULL;
DWORD ImageBase,OriginalCRC32;
ImageBase = (DWORD)GetMoleHandle(NULL); // 取基址
pDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
pNtHeader = (PIMAGE_NT_HEADER32)((DWORD)pDosHeader + pDosHeader -> e_lfanew);
// 定位到PE文件頭前4個位元組值,並讀取存儲在這里的CRC -32值
OriginalCRC32 = *((DWORD*)(DWORD)pNtHeader - 4);
pSecHeader = IMAGE_FIRST_SECTION(pNtHeader); // 得到第一個區塊的地址
//假設第一個區塊就是代碼區塊
if(OriginalCRC32 == CRC32((BYTE*)ImageBase + pSecHeader -> VirtualAddress)
// 為了方便加殼
// 上一句也可為if(OriginalCRC32 == CRC32((BYTE *)0x401000, 0x36AE)
return TRUE;
else
return FALSE;
}