CRC32: Дополнить файл для получения контрольной суммы FFFFFFFF - VB

Узнай цену своей работы

Формулировка задачи:

Привет! Имеется произвольный бинарный файл. Цель: дополнить его как можно меньшим кол-вом байт, чтобы его КС по CRC32 стала = FFFFFFFF. Можете для меня такое сочинить? P.S. Долгое время пользуюсь модулем подсчета CRC32 от Catstail, который меня не подводил. Настало время чего то более сложного. Т.к. не математик, сам такого боюсь не сделаю.

Решение задачи: «CRC32: Дополнить файл для получения контрольной суммы FFFFFFFF»

textual
Листинг программы
Option Explicit
 
Const poly As Long = &HEDB88320
 
Public Declare Function Mul Lib "msvbvm60.dll" Alias "_allmul" (ByVal dw1 As Long, ByVal Reserved As Long, ByVal dw3 As Long, ByVal Reserved As Long) As Long
 
Dim Tab_CRC(255)    As Long
Dim pTable(255)     As Long
 
Sub Make_CRC_32_Table()
    Dim bx&, cx&, eax&
    
    For bx = 0& To 255&
        eax = bx
        For cx = 0& To 7&
            If (eax And 1) Then
                eax = ((eax And &HFFFFFFFE) \ 2&) And &H7FFFFFFF    'eax >> 1
                eax = eax Xor poly
            Else
                eax = ((eax And &HFFFFFFFE) \ 2&) And &H7FFFFFFF
            End If
        Next
        Tab_CRC(bx) = eax
        pTable(((eax And &HFF000000) \ &H1000000) And &HFF) = bx
    Next
End Sub
 
Sub SplitInto4bytes(Src As Long, bit3 As Byte, bit2 As Byte, bit1 As Byte, bit0 As Byte)
    bit3 = ((Src And &HFF000000) \ &H1000000) And &HFF
    bit2 = ((Src And &HFF0000) \ &H10000) And &HFF
    bit1 = ((Src And &HFF00) \ &H100) And &HFF
    bit0 = Src And &HFF
End Sub
 
Public Sub RecoverCRC()
    
    Dim oldCRC&, newCRC&, ChkCRC&, a(3) As Byte, b(3) As Byte, c(3) As Byte, d(3) As Byte, e(3) As Byte, f(3) As Byte, r(3) As Byte, i&
    Dim InitStri$, NewStri$, PatchAddr&, ForwardCRC&, BackwardCRC&, AddBytes$
    
    ' Исходные данные
    InitStri = "Some Data"
    
    ' Указать адрес для добавочных (или заменяемых) байтов (считаем с нуля).
    PatchAddr = Len(InitStri) 'Len(InitStri) - пишем в конец
    
    If PatchAddr > Len(InitStri) Then Err.Raise 14
    
    Make_CRC_32_Table
    
    ' Какую КС нужно получить
    newCRC = &H12345678
    oldCRC = CalcCRC(InitStri)
    
    Debug.Print "Initial CRC: " & Hex(oldCRC)
    Debug.Print "New CRC:     " & Hex(newCRC)
    
    ForwardCRC = CalcCRC(Left$(InitStri, PatchAddr)) Xor -1
    BackwardCRC = newCRC Xor -1
    
    If (PatchAddr + 4) < Len(InitStri) Then BackwardCRC = CalcCRCReverse(Right$(InitStri, Len(InitStri) - (PatchAddr + 4)), BackwardCRC)
    
    SplitInto4bytes ForwardCRC, a(3), a(2), a(1), a(0)
    SplitInto4bytes BackwardCRC, f(3), f(2), f(1), f(0)
    
    e(3) = f(3):                            SplitInto4bytes Tab_CRC(pTable(e(3))), e(3), e(2), e(1), e(0)
    d(3) = f(2) Xor e(2):                   SplitInto4bytes Tab_CRC(pTable(d(3))), d(3), d(2), d(1), d(0)
    c(3) = f(1) Xor e(1) Xor d(2):          SplitInto4bytes Tab_CRC(pTable(c(3))), c(3), c(2), c(1), c(0)
    b(3) = f(0) Xor e(0) Xor d(1) Xor c(2): SplitInto4bytes Tab_CRC(pTable(b(3))), b(3), b(2), b(1), b(0)
    
    r(3) = pTable(b(3)) Xor a(0)
    r(2) = pTable(c(3)) Xor b(0) Xor a(1)
    r(1) = pTable(d(3)) Xor c(0) Xor b(1) Xor a(2)
    r(0) = pTable(e(3)) Xor d(0) Xor c(1) Xor b(2) Xor a(3)
    
    AddBytes = Chr$(r(3)) & Chr$(r(2)) & Chr$(r(1)) & Chr$(r(0))
    
    ' Вставляем корректирующие байты в исходную строку
    NewStri = InitStri
    If PatchAddr - Len(InitStri) + 4 > 0 Then NewStri = NewStri & Space$(PatchAddr - Len(InitStri) + 4)
    Mid(NewStri, PatchAddr + 1) = Chr$(r(3)) & Chr$(r(2)) & Chr$(r(1)) & Chr$(r(0))
    
    ' Контрольная проверка КС
    ChkCRC = CalcCRC(NewStri)
    
    ' Если КС не совпадает
    If ChkCRC <> newCRC Then Err.Raise 17
    
    Debug.Print "Check CRC:   " & Hex(ChkCRC)
    Debug.Print "Исходная строка: " & InitStri
    Debug.Print "Новая строка:    " & NewStri
    Debug.Print "Адрес для вставки: " & PatchAddr
    Debug.Print "Корректирующие байты: " & Hex(Mul(r(3), 0, &H1000000, 0) Or Mul(r(2), 0, &H10000, 0) Or Mul(r(1), 0, &H100, 0) Or r(0))
    End
End Sub
 
Public Function CalcCRC(Stri As String) As Long
    Dim CRC&, i&, m&, n&
 
    If Tab_CRC(1) = 0 Then Make_CRC_32_Table
 
    CRC = -1
 
    For i = 1& To Len(Stri)
        m = Asc(Mid$(Stri, i, 1&))
        n = (CRC Xor m) And &HFF&
        CRC = (Tab_CRC(n) Xor (((CRC And &HFFFFFF00) \ &H100) And &HFFFFFF)) And -1  ' Tab ^ (crc >> 8)
    Next
 
    CalcCRC = -(CRC + 1&)
End Function
 
Public Function CalcCRCReverse(Stri As String, Optional nextValue As Long = -1) As Long
    Dim CRC&, i&, m&, n&, prevValueL&, prevValueH&, b3 As Byte
 
    If Tab_CRC(1) = 0 Then Make_CRC_32_Table
 
    CRC = nextValue
 
    For i = Len(Stri) To 1 Step -1
        m = Asc(Mid$(Stri, i, 1&))
        b3 = ((CRC And &HFF000000) \ &H1000000) And &HFF
        prevValueL = (pTable(b3) Xor m) And &HFF
        prevValueH = Mul(CRC Xor Tab_CRC(pTable(b3)), 0, &H100, 0)  ' << 8
        CRC = prevValueH Or prevValueL
    Next
    
    CalcCRCReverse = CRC
End Function

Оцени полезность:

15   голосов , оценка 3.933 из 5
Похожие ответы