‘壹’ 如何计算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;
}