ソフトウェアセキュリティのCRC検出

CRCの紹介

fps ゲームなどの一部のゲームをプレイするとき、いくつかの特定の値を変更して一部の機能を実現したい場合、この時点で、アカウントまたはマシンコードさえも禁止される可能性があります。ゲーム内のデータを変更したため、受信機が「間違ったデータ」を受信したためです。受信機が受信したデータの精度を可能な限り向上させるためには、データを受信する前にデータの誤り検出を行う必要があり、このような検出をCRC検出と呼んでいます。

CRC は Cyclic Redundancy Check Code とも呼ばれます. 暗号化アルゴリズムのクラスに属し、データ検証によく使用されます. 一般に、プログラムが解凍されたかどうか、またはクラッキングを防止する目的を達成するために変更されたかどうかを検出するために使用されます. CRC 演算とは、実際にはデータ k に対して modulo 2 演算を実行して剰余 n を求め、n を k の後ろにつなぎ合わせて、巡回冗長検査符号の語長として k+n を生成することです。次に、k+n を被除数として受信機に送信し、剰余が 0 かどうかを modulo 2 で計算します。剰余が 0 でない場合、CRC はデータが変更されたことを検出します。簡単に言えば、検証対象データと生成多項式を巡回XOR処理することです。

PS:

1. 送信者と受信者は特定の除数に同意します。これは固定値であり、除数を生成多項式とも呼びます。

2. 剰余を計算する場合、被除数、つまりデータ k に 0 を追加する必要があり、追加される 0 の数は、生成多項式の長さ - 1 ゼロです。

3. 残りの長さは、ゼロ パディングの長さと一致している必要があります。

フローチャート:

Image

たくさんのことを言いましたが、理解するために例を挙げたほうがいいです

例 1: ここでのデータは 1110101 で、生成多項式は 101 であり、受信側に渡したいデータは 1110101 (データ) + 10 (剰余) = 111010110 です。

image-20230314201253238

これがCRCの計算原理です

CRC 計算の 2 つの方法

1. 直接計算法

ここでは、例を通して説明します。例 2:

image-20230314201309003

最初に、ここで生成された項目が 1101 であることがわかります。次に、計算の除数 (青色のフォントでマーク) はほとんどが 1101 で、場合によっては 0000 です。除数が 1101 の場合、被除数の最初の桁は 1 であり、最初の数字は 1 ではなく、0000 です。被除数と除数の最初の桁が 1 になると消去されるので、4 ビットの XOR は必要ないので、3 ビットの XOR に変更します。除数の 3 桁、被除数の最初の桁が 1 の場合、左に 1 ビット移動して、新しい 3 桁を除数の最後の 3 桁と XOR します (生成された項目); 桁が被除数からシフトアウトされた場合は 0、XOR 000 であり、完了するまでこの手順を繰り返します。(この例では、生成されたアイテムが n の場合、n-1 ビット XOR を取ります)

それから誰かが、それが終わるまでに何回繰り返す必要があるか尋ねますか?

処理回数=処理する桁数(被除数の桁数)=商の桁数(この問題の回数は6回)

たとえば、この質問の除数は最初は 100 で、1 ビット左にシフトして 001 を取得し、次に 101 と XOR して 100 を取得します。100 を左に 1 ビットシフトして 000 を取得し、次に 101 と XOR して101 を取得します。101 を 1 ビット左にシフトして 010 を取得し、次に 101 と XOR を取得します。 111 を取得します。 000 から 110 を取得します (000 との XOR 値は変更されません)。110 を 1 ビット左にシフトして 100 を取得し、101 と XOR して 001 を取得し、残りを正確に 6 回取得します。

サイバーセキュリティの学習に役立つ完全な情報セットを無料で受け取ることができます。
① サイバーセキュリティの学習と成長経路のマインド マップ
② 60 以上の古典的なサイバーセキュリティ ツールキット
③ 100 以上の SRC 分析レポート
④ サイバーセキュリティの攻撃と防御技術に関する 150 以上の電子ブック
⑤ 最も権威のある CISSP 認定試験ガイド + 問題バンク
⑥ 1800 ページを超える CTF 実践スキル マニュアル
⑦ ネットワーク セキュリティ企業からの最新のインタビューの質問のコレクション (回答を含む)
⑧ APP クライアント セキュリティ テスト ガイド (Android+IOS)

2.ドライブテーブル方式

駆動表法は、直接計算法ほど直感的ではありませんが、効率は直接計算法よりも高くなります。直接計算方法は、XOR によって上から下へ段階的に結果を取得することであることがわかっています. 計算プロセス中に、多くの XOR の生成項目があり、生成された項目は変更されません. したがって、事前に計算できますか?および前のいくつかのデータ 対応する生成された項目の合計と XOR はどうですか?

次に、0000 0000 ~ 1111 1111 の範囲で生成されたすべてのアイテムを計算し、それらをテーブルとして保存します. 計算するとき、データの最初のバイトをインデックス用に取得し、テーブル内の対応する生成アイテムの XOR 合計を見つけ、最初のバイトが削除されたデータと比較します。XOR で実行できます。

テーブルフォーメーション

最後に、テーブルに行きます. ここでは、アルゴリズムを使用してテーブルを実現します, その原理を明確に理解できるように. ここでは、例としてCRC32テーブルの形成を取り上げます. まず, 生成されたアイテムが何であるかを理解する必要があります. CRC32のです。

Image

CRC とその生成多項式について詳しく知りたい場合は、http://www.ip33.com/crc.html にアクセスしてください。

#include <windows.h>
#include <stdio.h>

int main()
{
    DWORD crc;
    for (DWORD i = 0; i < 256; i++)//256个元素
    {
        crc = i;
        for (DWORD k = 0; k < 8; k++)//因为这里异或是从数据的高位开始,所以需要计算的数据左移8位,这里就需要计算8次
        {
            if (crc & 1)//判断最高位是否为1
                crc = (crc >> 1) ^ 0xEDB88320;//最高位为1,右移一位,然后与0xEDB88320异或   
            else
                crc = crc >> 1;//最高位为0时,不用异或,整体数据右移一位。相当于例子2中110与000异或值是不变的
        }
        printf ("0x%08x, ", crc);
        if (((i+1)%6) == NULL )
            printf ("\n");
    }
}

/*CRC32表
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
*/

注意这里用红色标识的右移,这里如果按照直接计算法来说不应该是要左移吗,为什么又右移了呢?

Image

注意看这个表的倒数第二个,CRC32,它的输入和输出都是需要进行反转的,也就是相当于逆向,我们就要将左移修改成右移

当然还会有人问它的多项式不应该是0x04C11DB7吗,怎么又变成了0xEDB88320了呢?

这是它是因为0xEDB88320是0x04C11DB7的反转。这个表的生成很简单,一般是用的是0xEDB88320这个反转多项式,假如用0x04C11DB7这个正常多项式则必须还要交换位,显然会很麻烦。

做一个CRC的检测程序

相信大家差不多能够理解CRC实现的大概过程了,前面主要是对CRC大致了解,而我们真正需要深入了解的是CRC32。CRC32常用于游戏以及一些 ARJ、LHA等压缩工具软件,那么接下来我们来写一个CRC32的检测程序。

#include <windows.h>
#include <stdio.h>
 
DWORD crc32_table[256];
 
void CRC32_Table()
{ 
    DWORD crc;
    //DWORD crc32_table[256];
    for (int i = 0; i < 256; i++)
    {
        crc = i;
        for (DWORD k = 0; k < 8; k++)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xEDB88320; 
            else
                crc >>= 1;
        }
        crc32_table[i] = crc; //生成并存储CRC32数据表
    }
}
 
//根据CRC32表计算CRC校验码
DWORD Check_CRC32(DWORD crc, PUCHAR Data, DWORD len)
{
    crc = 0xFFFFFFFF; //将CRC初始化为-1
    CRC32_Table();
    for (DWORD i = 0; i < len; i++)
    {
        crc = (crc >> 8) ^ crc32_table[(crc ^ Data[i]) & 0xff];
    }
    return ~crc;//输出的反转
}
 
int main()
{
    SetConsoleTitle("CRC32检测器");
    printf("开始检测"); 
    //初始内存校验值
    DWORD Original_CRC32 = Check_CRC32(0, (PUCHAR)0x400000, 0x112000);

    while (1)
    {
        //CRC循环校验实现实时检测
        DWORD Cycle_CRC32 = Check_CRC32(0, (PUCHAR)0x400000, 0x112000);//这里第二个参数是基址,第三个个参数是一个校验的范围,也就是程序主模块镜像大小。
 
        if (Cycle_CRC32 != Original_CRC32)
        {
            MessageBoxA(NULL, "已检测到您修改了代码!", "警告", MB_YESNO);
        }
        //为了防止频繁弹出信息框,这里使用的Sleep函数控制检测的周期,每5s弹出一次
        Sleep(5000);
    }
    getchar();
}

image-20230316204239892

这里初始化是因为待测数据的内容和长度是随机的,如果寄存器初始值为 0,那么待测字节是1字节的0x00,与待测字节是 N 字节的 0x00,计算出来的CRC32值都是0,那 CRC 值就没有意义了!所以寄存器用0xFFFFFFFF 进行初始化,就可以避免这个问题了

Image

我这里的文件大小对应的是主模块镜像大小

实践是否能成功

这里我们用CE进行数据的修改

Image

Image

这里我们先手动添加地址,然后再将数值进行更改,我这里是改成了11111,然后过了5秒就弹出了警告。可以看出这个检测程序成功了!

当然有些有点基础的人会问,CRC不是检测代码的吗,为什么这里你修改的是数值也可以检测呢?

因为CRC是在代码段中进行操作实现的,在内存中数据根代码没有实质性的区别。

おすすめ

転載: blog.csdn.net/qq_38154820/article/details/130226906