CRC32碰撞的實現
昨天晚上開始學習CRC32,發現這個HASH實際上應該很容易得出碰撞,下面給出一種生成碰撞的演算法
用CRC32對長度為N的資料效驗,初始效驗值為0xFFFFFFFF,經過N輪以後得到的值取反作為效驗值
生成碰撞的關鍵就是能夠找到4個位元組使得效驗值經過他們後得到一個已知的數
設:
在經過很多輪後效驗值為ABCD,接著要效驗的資料是abcd,效驗後的結果為WXYZ,其中4輪的查表索引值為mnop
(單個字母都表示一個位元組)
因此關鍵就是由ABCD+WXYZ推出abcd
定義4個函式F(x),G(x),H(x),I(x)分別表示以x為索引查表,取出來的DWORD的從高位到低位的4個位元組
CRC32效驗abcd的過程可以表示為:
R0:A,B,C,D <m=D^d>
R1:F(m),A^G(m),B^H(m),C^I(m) <n=c^C^I(m)>
R2:F(n),F(m)^G(n),A^G(m)^H(n),B^H(m)^I(n) <o=b^B^H(m)^I(n)>
R3:F(o),F(n)^G(o),F(m)^G(n)^H(o),A^G(m)^H(n)^I(o) <p=a^A^G(m)^H(n)^I(o)>
R4:F(p),F(o)^G(p),F(n)^G(o)^H(p),F(m)^G(n)^H(o)^I(p)
到R4這個得到的4個值就是效驗和WXYZ,總結一下這個過程:
-------------------------
<1>
W=F(p);
X=F(o)^G(p);
Y=F(n)^G(o)^H(p);
Z=F(m)^G(n)^H(o)^I(p);
<2>
m=d^D;
n=c^C^I(m);
o=b^B^H(m)^I(n);
p=a^A^G(m)^H(n)^I(o);
-------------------------
以上兩個方程表示了ABCD,abcd,WXYZ之間的關係,而mnop是中間變數
要解出abcd並不困難,設F(x)反函式為RF(x),得:
-----------------------
~<1>
p=RF(W);
o=RF(X^G(p));
n=RF(Y^G(o)^H(p));
m=RF(Z^G(n)^H(o)^I(p));
~<2>
d=m^D;
c=n^C^I(m);
b=o^B^H(m)^I(n);
a=p^A^G(m)^H(n)^I(o);
-----------------------
這裡假設要驗證的資料在記憶體中的分佈是:d,c,b,a (這是為了方便處理小端模式)
這樣就可以得到一組資料值,不過這裡關鍵的問題是RF(x)是否存在,下面這個函式可以證明y=F(x)是個一一對映:
void TestRF()
{
BYTE i,j;
DWORD flag;
for(i=0;i<=0xFF;i++)
{
flag=0;
for(j=0;j<=0xFF;j++)
{
if(HIBYTE(HIWORD(CRC32_tab[j])) == i)
{
flag=1;
printf("%X gets!\r\n",i);
break;
}
if(j==0xFF)break;
}
if(!flag)printf("%X can't get RF\r\n",i);
if(i==0xFF)break;
}
}
檢測的結果是所有的0~255都是RF(x)的定義域,這說明RF(x)是完全存在的,上述演算法完全可行!
程式設計實現~<1> ~<2>的結果:
BYTE RF(BYTE x)
{
BYTE j;
for(j=0;j<=0xFF;j++)
{
if(HIBYTE(HIWORD(CRC32_tab[j])) == x)break;
}
return j;
}
BYTE F(BYTE x)
{
return HIBYTE(HIWORD(CRC32_tab[x]));
}
BYTE G(BYTE x)
{
return LOBYTE(HIWORD(CRC32_tab[x]));
}
BYTE H(BYTE x)
{
return HIBYTE(LOWORD(CRC32_tab[x]));
}
BYTE I(BYTE x)
{
return LOBYTE(LOWORD(CRC32_tab[x]));
}
#define MakeLong(a,b) MAKELONG(b,a)
#define MakeWord(a,b) MAKEWORD(b,a)
DWORD rCRC32(DWORD WXYZ,DWORD ABCD)
{
BYTE p,o,n,m,a,b,c,d,W,X,Y,Z,A,B,C,D;
W=HIBYTE(HIWORD(WXYZ));
X=LOBYTE(HIWORD(WXYZ));
Y=HIBYTE(LOWORD(WXYZ));
Z=LOBYTE(LOWORD(WXYZ));
A=HIBYTE(HIWORD(ABCD));
B=LOBYTE(HIWORD(ABCD));
C=HIBYTE(LOWORD(ABCD));
D=LOBYTE(LOWORD(ABCD));
p=RF(W);
o=RF(X^G(p));
n=RF(Y^G(o)^H(p));
m=RF(Z^G(n)^H(o)^I(p));
d=m^D;
c=n^C^I(m);
b=o^B^H(m)^I(n);
a=p^A^G(m)^H(n)^I(o);
return MakeLong(MakeWord(a,b),MakeWord(c,d));
}
DWORD RCRC32(DWORD WXYZ,DWORD abcd)
{
BYTE p,o,n,m,a,b,c,d,W,X,Y,Z,A,B,C,D;
W=HIBYTE(HIWORD(WXYZ));
X=LOBYTE(HIWORD(WXYZ));
Y=HIBYTE(LOWORD(WXYZ));
Z=LOBYTE(LOWORD(WXYZ));
a=HIBYTE(HIWORD(abcd));
b=LOBYTE(HIWORD(abcd));
c=HIBYTE(LOWORD(abcd));
d=LOBYTE(LOWORD(abcd));
p=RF(W);
o=RF(X^G(p));
n=RF(Y^G(o)^H(p));
m=RF(Z^G(n)^H(o)^I(p));
D=m^d;
C=n^c^I(m);
B=o^b^H(m)^I(n);
A=p^a^G(m)^H(n)^I(o);
return MakeLong(MakeWord(A,B),MakeWord(C,D));
}
DWORD CRC32(DWORD ABCD,DWORD abcd)
{
BYTE p,o,n,m,a,b,c,d,W,X,Y,Z,A,B,C,D;
A=HIBYTE(HIWORD(ABCD));
B=LOBYTE(HIWORD(ABCD));
C=HIBYTE(LOWORD(ABCD));
D=LOBYTE(LOWORD(ABCD));
a=HIBYTE(HIWORD(abcd));
b=LOBYTE(HIWORD(abcd));
c=HIBYTE(LOWORD(abcd));
d=LOBYTE(LOWORD(abcd));
m=d^D;
n=c^C^I(m);
o=b^B^H(m)^I(n);
p=a^A^G(m)^H(n)^I(o);
W=F(p);
X=F(o)^G(p);
Y=F(n)^G(o)^H(p);
Z=F(m)^G(n)^H(o)^I(p);
return MakeLong(MakeWord(W,X),MakeWord(Y,Z));
}
這個尋找一個碰撞變得非常簡單,首先選取任意的一段資料,做CRC32效驗,結果就是ABCD
透過計算方程組<1><2>後得到abcd,將abcd和原來的資料連線就是碰撞的結果!
例如,"DonQuixote[CCG][iPB]"這個字串的CRC32是0x8A0C90C9,下面這段程式碼可以算出它的碰撞來:
int main(int argc, char* argv[])
{
DWORD x=rCRC32(~0x8A0C90C9,~CRC((BYTE*)"ipb",3));
char str[5];
memcpy(str,&x,4);
str[4]=0;
printf("x=%X\r\nstring=%s\r\n",x,str);
return 0;
}
這裡給出一些結果:
DonQuixote[CCG][iPB]
123Dp0
ccg_G
ipbkw
他們都得到相同的CRC32效驗和=0x8A0C90C9
(看雪有個工具可以驗證此結果,地址是http://www.pediy.com/tools/Cryptography/Hash/DAMN%20Hash%20Calculat
or%20.zip)
但是這麼做必須修改最後一個DWORD,有時我們可能在修改中間某個位置的DWORD,這也是可以實現的
只要根據WXYZ,abcd計算出ABCD就可以了:
-------------------------
(mnop的計算和~<1>~<2>一樣)
~<2'>
D=m^d;
C=n^c^I(m);
B=o^b^H(m)^I(n);
A=p^a^G(m)^H(n)^I(o);
-------------------------
這樣可以把資料反著"效驗"回去,到了中間某個位置再來放修改值
****************************************************************************************8
現在想到的一些應用:
這種尋找碰撞的演算法可以應用到anti-debug上,大多數效驗都是把驗證值放在效驗段外面
透過計算~<2'>和~<2>可以連著效驗值一起計算,構造出資料滿足:CRC(***A***)=A
另外windows的系統檔案也是CRC32效驗的,這樣就可以寫出一種病毒感染系統檔案後得到的效驗值和原來的一樣
更好的用處的做成RootKit這樣的後門,這樣會更加難以被發現
據說TCP/IP的資料包也是CRC32效驗,那麼也許可以寫出病毒混亂一個資料包後使它的效驗和不變
......
by DonQuixote[CCG][iPB]
2004/12/20
相關文章
- 用JS實現方塊碰撞2021-12-06JS
- Three.js中實現對InstanceMesh的碰撞檢測2023-09-20JS
- Unity射擊遊戲例項—物理碰撞的實現2020-12-21Unity遊戲
- 原生js實現一個DIV的碰撞反彈運動2018-06-28JS
- 科技互動沙盤實現傳統與科技的碰撞2023-03-03
- 計算 CRC32 的逆函式2020-03-22函式
- JavaScript 遊戲開發:手把手實現碰撞物理引擎2021-02-26JavaScript遊戲開發
- 使用 Rust + WebAssembly 編寫 crc322018-07-13RustWeb
- flutter與unity的碰撞--opengl紋理共享實現flutter與unity介面的融合2021-07-18FlutterUnity
- PHP 每日一函式 — 字串函式 crc32 ()2020-05-04PHP函式字串
- ccf碰撞的小球(100分)2020-09-27
- 雜湊碰撞2024-10-22
- 碰撞檢測2024-06-17
- UE4的移動碰撞2019-04-10
- MD5碰撞的演化之路2020-08-19
- RFID的防碰撞是什麼2024-07-17
- ORA,全球文化與科技的碰撞2022-05-22
- 成理信安協會反序列化01-利用fastcoll實現md5碰撞2020-10-10AST
- 策略模式、策略模式與Spring的碰撞2020-06-30模式Spring
- 公有云和開源的商業碰撞2019-02-16
- python如何檢測pygame中的碰撞2021-09-11PythonGAM
- 雲原生與邊緣計算的碰撞——邊緣原生應用實踐2020-05-09
- 密碼學系列之:碰撞抵禦和碰撞攻擊collision attack2021-06-03密碼學
- JS寫的不咋地的碰撞檢測2019-01-14JS
- unity3d碰撞2024-07-23Unity3D
- 虛擬現實 VR 碰撞 3D 視覺化,圖撲打造一體化管控平臺2023-01-04VR3D視覺化
- AIGC遇上低程式碼的碰撞與融合2023-05-05AIGC
- a標籤href與onclick之間的碰撞2023-02-03
- PHP 陣列的雜湊碰撞攻擊2021-04-08PHP陣列
- 學習 PixiJS — 碰撞檢測2019-02-25JS
- js小球重力和碰撞效果2018-05-29JS
- MD5碰撞試驗2024-10-30
- CCF-CSP 20180302:小球碰撞2020-11-27
- mpvue: vuejs和小程式碰撞出來的火花2018-05-21VueJS
- 淺談DOTA2中的碰撞體積2020-03-10
- 【SQL】晨光咖啡館,過濾聚合的微妙碰撞2024-07-15SQL
- 遊戲性與文化的碰撞 實際上是《太閣立志傳5》的人文野望2019-12-05遊戲
- 中保研:中國各車型碰撞測試 日系車表現最好2019-10-29
- Open Source 103:開源與雲的商業碰撞2019-01-16