相关文章推荐
打酱油的小刀  ·  Azure API Management ...·  7 月前    · 
重情义的卤蛋  ·  java.util.concurrent.t ...·  1 年前    · 
风流倜傥的杨桃  ·  python ...·  1 年前    · 

C语言CRC-32 MPEG-2格式校验函数

CRC-32校验产生4个字节长度的数据校验码,通过计算得到的校验码和获得的校验码比较,用于验证获得的数据的正确性。基本的CRC-32校验算法实现,参考: C语言标准CRC-32校验函数

不同应用规范通过对输入数据前处理和输出数据后处理的方式不同,又产生了不同的应用规范校验函数,这里介绍MPEG-2格式的CRC-32校验函数。 MPEG-2格式对输入数据,只有预置值为0XFFFF(当做最初的余数)的前处理。

生成多项式为x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
由于反向算法更适合于有输入字节倒位序和输出整体数据倒位序的情况,这里只介绍正向算法。

正向算法是符合标准CRC-32的计算理论,从左向右计算,也即计算过程中移位时,向左移出。几种正向算法的实现如下:

CRC-32 MPEG-2格式校验函数一(8位输入数据格式,64位装载计算):

#include <stdio.h>
#include <stdlib.h>
uint32_t PY_CRC_32_MPEG_2(uint8_t *di, uint32_t len)
    uint64_t crc_poly = 0x104C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 33 effective bits. Computed total data shall be compensated 32-bit '0' before CRC computing.
	uint8_t *datain;
	uint64_t cdata = 0; //Computed total data
    uint64_t data_t = 0; //Process data of CRC computing
	uint16_t index_t = 63;  ///bit shifting index for initial '1' searching
	uint16_t index = 63;    //bit shifting index for CRC computing
	uint8_t rec = 0; //bit number needed to be compensated for next CRC computing
    uint32_t cn=(len+4)/4;
    uint32_t cr=(len+4)%4;
	uint32_t j;
	datain = malloc(len+4);
	for(j=0;j<len;j++)
		datain[j]=di[j];
        datain[len]=0; datain[len+1]=0; datain[len+2]=0; datain[len+3]=0;//Compensate 32-bit '0' for input data
        datain[0] ^= 0xff; datain[1] ^= 0xff; datain[2] ^= 0xff; datain[3] ^= 0xff;
    if(len<=4)   //Mount data for only one segment
    	 for(j=0;j<=(len+3);j++)
    		 cdata = (cdata<<8);
    		 cdata = cdata|datain[j];
    	 cn = 1;
    	 if(cr==0)
    		 cr = 8;
             cn--;
         else if(cr==1)
             cr = 5;
         else if(cr==2)
             cr = 6;
         else if(cr==3)
             cr = 7;
         else;
    	 for(j=0;j<cr;j++)
    		 cdata = (cdata<<8);
    		 cdata = cdata|datain[j];
 		cn--;
 		while(index_t>0)
 			if( (cdata>>index_t)&1 )
 				index = index_t;
 				index_t = 0;
 				data_t |= (cdata>>(index-32));
 					data_t = data_t ^ crc_poly;
 	            while((index!=0x5555)&&(index!=0xaaaa))
	 	    		for(uint8_t n=1;n<33;n++)
	 	    			if ((data_t>>(32-n))&1) {rec = n;break;}
	 	    			if (n==32) rec=33;
 	    			if((index-32)<rec)
 	    				data_t = data_t<<(index-32);
 	    				data_t |=  (uint64_t)((cdata<<(64-(index-32)))>>(64-(index-32)));
 	    				index = 0x5555;
 	        			for(uint8_t i=1;i<=rec;i++)
 	        				data_t = (data_t<<1)|((cdata>>(index-32-i))&1) ;
 	        			if(rec!= 33)
 	        				data_t = data_t ^ crc_poly;
 	        				index -= rec;
 	        				data_t = 0;
 	        				index_t = index-32-1;
 	        				index = 0xaaaa;
 				if(index==0x5555) break;
 				index_t--;
 				if(index_t<32) break;
 		if(cn>0) //next segment
  			cdata = data_t&0x00ffffffff;
 			for(uint8_t k=0;k<4;k++)
 	    		 cdata = (cdata<<8);
 	    		 cdata = cdata|datain[j++];
 	    	data_t = 0;
 	 		index_t = 63;  ///bit shifting index for initial '1' searching
 	 		index = 63;    //bit shifting index for CRC computing
 	 		rec = 0; //bit number needed to be compensated for next CRC computing
     while(cn>0);
     free(datain);
     return (uint32_t)data_t;

CRC-32 MPEG-2格式校验函数二(8位输入数据格式):

#include <stdio.h>
#include <stdlib.h>
uint32_t PY_CRC_32_S_MPEG_2(uint8_t *di, uint32_t len)
    uint32_t crc_poly = 0x04C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 16 effective bits without X^32. Computed total data shall be compensated 32-bit '0' before CRC computing.
	uint32_t clen = len+4;
	uint8_t cdata[clen] ;
	memcpy(cdata, di, len); cdata[len]=0; cdata[len+1]=0; cdata[len+2]=0; cdata[len+3]=0;
	cdata[0] ^= 0xff; cdata[1] ^= 0xff; cdata[2] ^= 0xff; cdata[3] ^= 0xff;
	uint32_t data_t =  (((uint32_t)cdata[0]) << 24) +  (((uint32_t)cdata[1]) << 16) + (((uint32_t)cdata[2]) << 8) + cdata[3]; //CRC register
    for (uint32_t i = 4; i < clen; i++)
        for (uint8_t j = 0; j <= 7; j++)
            if(data_t&0x80000000)
            	data_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ^ crc_poly;
            	data_t = ( (data_t<<1) | ( (cdata[i]>>(7-j))&0x01) ) ;
    return data_t;

CRC-32 MPEG-2格式校验函数三(32位输入数据格式):

uint32_t PY_CRC_32_T32_MPEG_2(uint32_t *di, uint32_t len)
	uint32_t crc_poly = 0x04C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 32 effective bits without X^32.
	//uint32_t data_t = 0; //CRC register
	uint32_t data_t = 0xffffffff; //CRC register
	uint32_t cdata[len];
	for(uint32_t j=0;j<len;j++)
		cdata[j] = (di[j]>>24) | ((di[j]&0x00ff0000)>>8) |  ((di[j]&0x0000ff00)<<8) | (di[j]<<24) ;
	//cdata[0] ^= 0xffffffff;
    for(uint32_t i = 0; i < len; i++)
    	data_t ^= cdata[i]; //32-bit data
        for (uint8_t j = 0; j < 32; j++)
            if (data_t & 0x80000000)
            	data_t = (data_t << 1) ^ crc_poly;
            	data_t <<= 1;
    return (data_t);

CRC-32 MPEG-2格式校验函数四(8位输入数据格式):

uint32_t PY_CRC_32_T8_MPEG_2(uint8_t *di, uint32_t len)
	uint32_t crc_poly = 0x04C11DB7;  //X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+1 total 32 effective bits without X^32.
	uint32_t data_t = 0; //CRC register
	uint32_t clen = len+4;
	uint8_t cdata[clen] ;
	memcpy(cdata, di, len); cdata[len]=0; cdata[len+1]=0; cdata[len+2]=0; cdata[len+3]=0;
	cdata[0] ^= 0xff; cdata[1] ^= 0xff; cdata[2] ^= 0xff; cdata[3] ^= 0xff;
    for(uint32_t i = 0; i < len; i++)
    	data_t ^= cdata[i]<<24; //8-bit data
        for (uint8_t j = 0; j < 8; j++)
            if (data_t & 0x80000000)
            	data_t = (data_t << 1) ^ crc_poly;
            	data_t <<= 1;
    return (data_t);

4种算法结果相同:
在这里插入图片描述

通过在线CRC工具对照验证成功:
在这里插入图片描述

–End–

CRC笔记 CRC-32/MPEG-2 简介及C语言实现一、CRC-32 MPEG-2算法简介二、CRC-32/MPEG-2算法基本信息三、CRC-32/MPEG-2算法C语言实现1、查表法计算CRC-32/MPEG-22、直接计算法计算CRC-32/MPEG-23、测试程序[参考资料] 一、CRC-32 MPEG-2算法简介 Class: attested ISO/IEC 13818-1:2000 — ITU-T Recommendation H.222.0 (February 2000) STM32采用的CRC校验模块使用的校验算法与主流CRC32校验算法不同。 下面是一个CRC在线校验网站: http://www.ip33.com/crc.html 主流32校验算法包括CRC-32CRC-32/MPEG-2两种,而STM32采用的校验算法与这两种都不同,尽管形式上很像CRC-32/MPEG-2,但STM3232为逐位计算的,而主流算法都是按字...
本课程为《x86/x64软件逆向分析》系列课程之“提高篇”,在“入门篇”的基础上,补充了更多深入和复杂的逆向分析内容。本课程可以作为逆向工程师的参考教程,也可以作为对软件逆向分析充满兴趣的朋友们的“提高”教程。 如果你看到某个exe程序能够实现某种特殊的功能,但你却不知道如何实现,这时候,你通过反汇编、反编译和动态跟踪等方法分析出其具体的实现过程,进而“参考”这个过程自己实现这个特殊的功能,这种行为就是逆向工程。逆向不仅仅是反编译,而且还要推倒出设计,并且能够文档化,从而使软件得以更好的维护。 在工作中,发现现用软件中有BUG,但软件开发商已经不存在了,怎么办?掌握软件逆向分析技术,给它“修”一下。 传说中的神秘的“黑客”、“大神”,无非是掌握了你还没掌握的某些技能而已,知道了你所不知道的某些特殊知识而已。掌握《x86/x64软件逆向分析》,你离这些神秘的“黑客”、“大神”只有一步之遥。 “天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣!” 逆向分析,如同玩猜谜游戏,当你看到一个个谜底慢慢浮现的时候,只有身在其中的人,才能享受其中的刺激和乐趣。作为看客,永远无缘体验这份乐趣。
三、CRC-32/MPEG-2算法C语言实现 1、查表法计算CRC-32/MPEG-2 2、直接计算法计算CRC-32/MPEG-2 3、测试程序 [参考资料] 一、CRC-32 MPEG-2算法简介 Class: attested ISO/IEC 13818-1:2000 — ITU-T Recommendation H.222.0 (February 2000) I Definition: Width, Poly, I 1.CRC32的几种分类:http://www.ip33.com/crc.html 2.CRC32算法在C#中的一种实现方法“:https://www.cnblogs.com/Kconnie/p/3538194.html 3.全套CRC校验 C的实现 4.C#  CRC32校验CRC-32/MPEG-2算法的实现: //1EA90DFF string ...
uint32_t crc32_mpeg_2(uint8_t *data, uint16_t length) { uint8_t i; uint32_t crc = 0xffffffff; // Initial value while(length--) { crc ^= (uint32_t)(*data++) << 24;// crc ^=(uint32_t)(*data)<<24; data++; for (i = 0; i < 8; ++i) { if ( crc & 0x80000000 ) crc = (crc << 1) ^ 0x04C11DB7; else crc <<= 1; } } return crc; }转为python
def crc32_mpeg_2(data: bytes) -> int: crc = 0xFFFFFFFF # Initial value for byte in data: crc ^= (byte << 24) # crc ^=(uint32_t)(*data)<<24; data++; for i in range(8): if crc & 0x80000000: crc = (crc << 1) ^ 0x04C11DB7 else: crc <<= 1 return crc 其中,参数`data`是一个bytes类型的数据,返回值是一个整数表示计算得到的CRC32校验值。