ikki_CrackMe变形SHA和变形BlowFish逆向分析(四)----BlowFish算法
大家好,我们又见面了,这次我们继续分析这个CrackMe,这次分析最后一道工程BlowFish算法。首先当然还是先来看看下面的BlowFish函数的初始化部分了。函数参考原型如下:
------------Procedure BlowFish_Init(var sBox_Key:MyArray;---------------------------------------
var pBox_Key:array of DWORD;
var Name_64:array of DWORD);
00411DE4 LEA EAX,DWORD PTR SS:[EBP-114]
00411DEA PUSH EAX ; var SHA1_Init_En[1..5] of DWORD;
00411DEB LEA ECX,DWORD PTR SS:[EBP-11AC]
00411DF1 PUSH ECX ; var BlowFish_Init:array[1..1024] of DWORD;
00411DF2 CALL CRACKME_.004112A8 ; CALL BlowFish_Init;
-----------------------CALL BlowFish_Init-------------------------------------------------------
00412410 PUSH EBP
00412411 MOV EBP,ESP
00412413 SUB ESP,0F0
00412419 PUSH EBX
0041241A PUSH ESI
0041241B PUSH EDI
0041241C LEA EDI,DWORD PTR SS:[EBP-F0]
00412422 MOV ECX,3C
00412427 MOV EAX,CCCCCCCC ; 又是程序惯例初始化,不管他。
0041242C REP STOS DWORD PTR ES:[EDI]
0041242E MOV DWORD PTR SS:[EBP-8],0 ; var i:DWORD = 0;
00412435 JMP SHORT CRACKME_.00412440
下面一大段循环没什么好说的,就是将全局上的BlowFish的sBox转存到局部变量中sBox_Key。用高级语言表达如下:
for i := 0 to 3 do
begin
for j := 0 to $FF do
begin
sBox_Key[i,j] := sBox[i,j]; //将全局的sBox连续填充转到局部变量sBox_Key中。
end;
end;
00412437 /MOV EAX,DWORD PTR SS:[EBP-8] ; i := i + 1;
0041243A |ADD EAX,1
0041243D |MOV DWORD PTR SS:[EBP-8],EAX
00412440 CMP DWORD PTR SS:[EBP-8],4 ; For i := 0 to 4 do
00412444 |JGE SHORT CRACKME_.0041248B
00412446 |MOV DWORD PTR SS:[EBP-14],0 ; var j:DWORD = 0;
0041244D |JMP SHORT CRACKME_.00412458
0041244F |/MOV EAX,DWORD PTR SS:[EBP-14] ; j := j + 1;
00412452 ||ADD EAX,1
00412455 ||MOV DWORD PTR SS:[EBP-14],EAX
00412458 | CMP DWORD PTR SS:[EBP-14],100 ; For j := 0 to $100 do
0041245F ||JGE SHORT CRACKME_.00412489
00412461 ||MOV EAX,DWORD PTR SS:[EBP-8] ; k := i shl $A;
00412464 ||SHL EAX,0A
00412467 ||MOV ECX,DWORD PTR SS:[EBP-8] ; k := i shl $A;
0041246A ||SHL ECX,0A
0041246D ||MOV EDX,DWORD PTR SS:[EBP+8]
00412470 ||LEA ECX,DWORD PTR DS:[EDX+ECX+80] ; sBox_Key[k + j] := sBox[k + j];
00412477 ||MOV EDX,DWORD PTR SS:[EBP-14]
0041247A ||MOV ESI,DWORD PTR SS:[EBP-14]
0041247D ||MOV EAX,DWORD PTR DS:[EAX+ESI*4+4281B0>
00412484 ||MOV DWORD PTR DS:[ECX+EDX*4],EAX
00412487 |\JMP SHORT CRACKME_.0041244F
00412489 \JMP SHORT CRACKME_.00412437
这里开始加密pBox,转成pBox_Key。高级语言表达如下:
For i := 0 to $1F do //加密连续填充pBox_Key
begin
k := 4 - (i mod 5);
pBox_Key[i] := Name_64[k] xor pBox[i];
end;
0041248B MOV DWORD PTR SS:[EBP-8],0
00412492 JMP SHORT CRACKME_.0041249D
00412494 /MOV EAX,DWORD PTR SS:[EBP-8]
00412497 |ADD EAX,1
0041249A |MOV DWORD PTR SS:[EBP-8],EAX
0041249D CMP DWORD PTR SS:[EBP-8],20
004124A1 |JGE SHORT CRACKME_.004124D0
004124A3 |MOV EAX,DWORD PTR SS:[EBP-8] ; j := 4 - (i mod 5);
004124A6 |CDQ
004124A7 |MOV ECX,5
004124AC |IDIV ECX
004124AE |MOV EAX,4
004124B3 |SUB EAX,EDX
004124B5 |MOV ECX,DWORD PTR SS:[EBP-8] ; pBox_Key[i] := Name_64_Key[j] xor pBox[i];
004124B8 |MOV EDX,DWORD PTR SS:[EBP+C]
004124BB |MOV ECX,DWORD PTR DS:[ECX*4+428130]
004124C2 |XOR ECX,DWORD PTR DS:[EDX+EAX*4]
004124C5 |MOV EDX,DWORD PTR SS:[EBP-8]
004124C8 |MOV EAX,DWORD PTR SS:[EBP+8]
004124CB |MOV DWORD PTR DS:[EAX+EDX*4],ECX
004124CE \JMP SHORT CRACKME_.00412494
这里加密两个全0的消息(xL, xR)再次对pBox_Key进行加密,高级语言表达如下:
xL := 0;
xR := 0;
j := 0;
For i := 0 to $F do //第二次加密填充pBox_Key
begin
BlowFish_En_Init(xL,xR,pBox_Key,sBox_Key);
pBox_key[j] := xL;
pBox_Key[j + 1] := xR;
j := j + 2;
end;
004124D0 MOV DWORD PTR SS:[EBP-20],0 ; xL := 0;
004124D7 MOV DWORD PTR SS:[EBP-2C],0 ; xR := 0;
004124DE MOV DWORD PTR SS:[EBP-20],0
004124E5 MOV DWORD PTR SS:[EBP-2C],0
004124EC MOV DWORD PTR SS:[EBP-8],0 ; i := 0;
004124F3 JMP SHORT CRACKME_.004124FE
004124F5 /MOV EAX,DWORD PTR SS:[EBP-8]
004124F8 |ADD EAX,2
004124FB |MOV DWORD PTR SS:[EBP-8],EAX
004124FE CMP DWORD PTR SS:[EBP-8],20
00412502 |JGE SHORT CRACKME_.00412533
这个函数其实是BlowFish的加密函数,不过这个加密函数的这个CrackMe对注册码加密的函数运算顺序不同,而且只是用来作中间运算,现在先不分析他,稍后再分析。
Procedure BlowFish_En_Init(var xL, xR:DWORD; var pBox_Key:array of DWORD; var sBox_Key:MyArray);
00412504 |LEA EAX,DWORD PTR SS:[EBP-2C]
00412507 |PUSH EAX ; Push XR
00412508 |LEA ECX,DWORD PTR SS:[EBP-20]
0041250B |PUSH ECX ; Push xL
0041250C |MOV EDX,DWORD PTR SS:[EBP+8]
0041250F |PUSH EDX ; push pBox_key
00412510 |CALL CRACKME_.00411591 ; CALL BlowFish_En_Init
00412515 |ADD ESP,0C
将加密后的xL和xR连续填充pBox_Key。
00412518 |MOV EAX,DWORD PTR SS:[EBP-8]
0041251B |MOV ECX,DWORD PTR SS:[EBP+8]
0041251E |MOV EDX,DWORD PTR SS:[EBP-20]
00412521 |MOV DWORD PTR DS:[ECX+EAX*4],EDX ; pBox[j] := xL;
00412524 |MOV EAX,DWORD PTR SS:[EBP-8]
00412527 |MOV ECX,DWORD PTR SS:[EBP+8]
0041252A |MOV EDX,DWORD PTR SS:[EBP-2C]
0041252D |MOV DWORD PTR DS:[ECX+EAX*4+4],EDX ; pBox[j + 1] := xR;
00412531 \JMP SHORT CRACKME_.004124F5
到这里,程序开始对sBox_Key进行连续加密填充。这段代码用高级语言表达如下:
For i := 0 to 3 do //连续加密填充sBox_Key
begin
k := 0;
For j := 0 to $7F do
begin
BlowFish_En_Init(xL,xR,pBox_Key,sBox_Key);
sBox_Key[i,k] := xL;
sBox_key[i,k + 1] := xR;
k := k + 2;
end;
end;
00412533 MOV DWORD PTR SS:[EBP-8],0 ; i := 0;
0041253A JMP SHORT CRACKME_.00412545
0041253C /MOV EAX,DWORD PTR SS:[EBP-8]
0041253F |ADD EAX,1
00412542 |MOV DWORD PTR SS:[EBP-8],EAX
00412545 CMP DWORD PTR SS:[EBP-8],4
00412549 |JGE SHORT CRACKME_.004125B1
0041254B |MOV DWORD PTR SS:[EBP-14],0 ; j := 0;
00412552 |JMP SHORT CRACKME_.0041255D
00412554 |/MOV EAX,DWORD PTR SS:[EBP-14]
00412557 ||ADD EAX,2
0041255A ||MOV DWORD PTR SS:[EBP-14],EAX
0041255D | CMP DWORD PTR SS:[EBP-14],100
00412564 ||JGE SHORT CRACKME_.004125AF
Procedure BlowFish_En_Init(var xL, xR:DWORD; var pBox_Key:array of DWORD; var sBox_Key:MyArray);
00412566 ||LEA EAX,DWORD PTR SS:[EBP-2C]
00412569 ||PUSH EAX ; push xR
0041256A ||LEA ECX,DWORD PTR SS:[EBP-20]
0041256D ||PUSH ECX ; push xL
0041256E ||MOV EDX,DWORD PTR SS:[EBP+8]
00412571 ||PUSH EDX ; push pBox_Key
00412572 ||CALL CRACKME_.00411591 ; CALL BlowFish_En_Init
00412577 ||ADD ESP,0C
sBox_Key[i,k] := xL;
0041257A ||MOV EAX,DWORD PTR SS:[EBP-8]
0041257D ||SHL EAX,0A
00412580 ||MOV ECX,DWORD PTR SS:[EBP+8]
00412583 ||LEA EDX,DWORD PTR DS:[ECX+EAX+80]
0041258A ||MOV EAX,DWORD PTR SS:[EBP-14]
0041258D ||MOV ECX,DWORD PTR SS:[EBP-20]
00412590 ||MOV DWORD PTR DS:[EDX+EAX*4],ECX
sBox_Key[i,k] := xR;
00412593 ||MOV EAX,DWORD PTR SS:[EBP-8]
00412596 ||SHL EAX,0A
00412599 ||MOV ECX,DWORD PTR SS:[EBP+8]
0041259C ||LEA EDX,DWORD PTR DS:[ECX+EAX+80]
004125A3 ||MOV EAX,DWORD PTR SS:[EBP-14]
004125A6 ||MOV ECX,DWORD PTR SS:[EBP-2C]
004125A9 ||MOV DWORD PTR DS:[EDX+EAX*4+4],ECX
004125AD |\JMP SHORT CRACKME_.00412554
004125AF \JMP SHORT CRACKME_.0041253C
到这里以后不管他们了。
004125B1 PUSH EDX
004125B2 MOV ECX,EBP
004125B4 PUSH EAX
004125B5 LEA EDX,DWORD PTR DS:[4125D6]
004125BB CALL CRACKME_.004111D1
004125C0 POP EAX
004125C1 POP EDX
004125C2 POP EDI
004125C3 POP ESI
004125C4 POP EBX
004125C5 ADD ESP,0F0
004125CB CMP EBP,ESP
004125CD CALL CRACKME_.004113FC
004125D2 MOV ESP,EBP
004125D4 POP EBP
004125D5 RETN
根据上面的分析,我们已经可以用高级语言写出功能相像的代码出来了(附源码):
Procedure BlowFish_Init(var sBox_Key:MyArray; var pBox_Key:array of DWORD; Name_64:array of DWORD);
var
i, j, k, xL, xR:DWORD;
begin
for i := 0 to 3 do //初始化sBox_Key
begin
for j := 0 to $FF do
begin
sBox_Key[i,j] := sBox[i,j];
end;
end;
For i := 0 to $1F do //加密填充pBox_Key
begin
k := 4 - (i mod 5);
pBox_Key[i] := Name_64[k] xor pBox[i];
end;
xL := 0;
xR := 0;
j := 0;
For i := 0 to $F do //第二次加密填充pBox_Key
begin
BlowFish_En_Init(xL,xR,pBox_Key,sBox_Key);
pBox_key[j] := xL;
pBox_Key[j + 1] := xR;
j := j + 2;
end;
For i := 0 to 3 do //连续加密填充sBox_Key
begin
k := 0;
For j := 0 to $7F do
begin
BlowFish_En_Init(xL,xR,pBox_Key,sBox_Key);
sBox_Key[i,k] := xL;
sBox_key[i,k + 1] := xR;
k := k + 2;
end;
end;
end;
---------------------Procedure BlowFish_En_Init(var xL, xR:DWORD;-------------------------------
var pBox_Key:array of DWORD;
var sBox_Key:MyArray);
00412566 ||LEA EAX,DWORD PTR SS:[EBP-2C]
00412569 ||PUSH EAX ; push xR
0041256A ||LEA ECX,DWORD PTR SS:[EBP-20]
0041256D ||PUSH ECX ; push xL
0041256E ||MOV EDX,DWORD PTR SS:[EBP+8]
00412571 ||PUSH EDX ; push pBox_Key
00412572 ||CALL CRACKME_.00411591 ; CALL BlowFish_En_Init
--------------------CALL BlowFish_En_Init-------------------------------------------------------
00412110 PUSH EBP
00412111 MOV EBP,ESP
00412113 SUB ESP,0F0
00412119 PUSH EBX
0041211A PUSH ESI
0041211B PUSH EDI
0041211C LEA EDI,DWORD PTR SS:[EBP-F0]
00412122 MOV ECX,3C
00412127 MOV EAX,CCCCCCCC
0041212C REP STOS DWORD PTR ES:[EDI]
0041212E MOV EAX,DWORD PTR SS:[EBP+C]
00412131 MOV ECX,DWORD PTR DS:[EAX]
00412133 MOV DWORD PTR SS:[EBP-8],ECX
00412136 MOV EAX,DWORD PTR SS:[EBP+10]
00412139 MOV ECX,DWORD PTR DS:[EAX]
0041213B MOV DWORD PTR SS:[EBP-14],ECX
0041213E MOV WORD PTR SS:[EBP-2C],0 ; var i:DWORD = 0;
00412144 JMP SHORT CRACKME_.00412152
下面的一段循环用高级语言表达如下:
For i := 0 to $1D do
begin
xL := xL xor pBox_Key[i];
xR := xR xor BlowFish_Func(xl,sBox_Key);
tmp := xL;
xL := xR;
xR := tmp;
end;
00412146 /MOV AX,WORD PTR SS:[EBP-2C]
0041214A |ADD AX,1
0041214E |MOV WORD PTR SS:[EBP-2C],AX
00412152 MOVSX EAX,WORD PTR SS:[EBP-2C]
00412156 |CMP EAX,1E
00412159 |JGE SHORT CRACKME_.00412195
xL := xL xor pBox_Key[0];
0041215B |MOVSX EAX,WORD PTR SS:[EBP-2C] ; eax := i
0041215F |MOV ECX,DWORD PTR SS:[EBP+8] ; ecx := pBox_Key;
00412162 |MOV EDX,DWORD PTR SS:[EBP-8] ; edx := xL;
00412165 |XOR EDX,DWORD PTR DS:[ECX+EAX*4] ; xL := xL xor pBox_Key[i];
00412168 |MOV DWORD PTR SS:[EBP-8],EDX
BlowFish加密的中间运算函数。函数原型参考如下:
Function BlowFish_Func(tmp:DWORD; sBox_Key:MyArray):DWORD;
0041216B |MOV EAX,DWORD PTR SS:[EBP-8]
0041216E |PUSH EAX ; /Arg2
0041216F |MOV ECX,DWORD PTR SS:[EBP+8] ; |
00412172 |PUSH ECX ; |Arg1
00412173 |CALL CRACKME_.00412220 ; \CRACKME_.00412220
00412178 |ADD ESP,8
tmp := xL;
xL := xR;
xR := tmp;
0041217B |XOR EAX,DWORD PTR SS:[EBP-14]
0041217E |MOV DWORD PTR SS:[EBP-14],EAX
00412181 |MOV EAX,DWORD PTR SS:[EBP-8]
00412184 |MOV DWORD PTR SS:[EBP-20],EAX
00412187 |MOV EAX,DWORD PTR SS:[EBP-14]
0041218A |MOV DWORD PTR SS:[EBP-8],EAX
0041218D |MOV EAX,DWORD PTR SS:[EBP-20]
00412190 |MOV DWORD PTR SS:[EBP-14],EAX
00412193 \JMP SHORT CRACKME_.00412146
这里再一次转换位置。
tmp := xL;
xL := xR;
xR := tmp;
00412195 MOV EAX,DWORD PTR SS:[EBP-8]
00412198 MOV DWORD PTR SS:[EBP-20],EAX
0041219B MOV EAX,DWORD PTR SS:[EBP-14]
0041219E MOV DWORD PTR SS:[EBP-8],EAX
004121A1 MOV EAX,DWORD PTR SS:[EBP-20]
004121A4 MOV DWORD PTR SS:[EBP-14],EAX
xL := xL xor pBox_key[$1E];
004121A7 MOV EAX,DWORD PTR SS:[EBP+8]
004121AA MOV ECX,DWORD PTR SS:[EBP-14]
004121AD XOR ECX,DWORD PTR DS:[EAX+78]
004121B0 MOV DWORD PTR SS:[EBP-14],ECX
xR := xR xor pBox_Key[$1F];
004121B3 MOV EAX,DWORD PTR SS:[EBP+8]
004121B6 MOV ECX,DWORD PTR SS:[EBP-8]
004121B9 XOR ECX,DWORD PTR DS:[EAX+7C]
004121BC MOV DWORD PTR SS:[EBP-8],ECX
到这里就没什么写了,只是保存运算结果。
004121BF MOV EAX,DWORD PTR SS:[EBP+C]
004121C2 MOV ECX,DWORD PTR SS:[EBP-8]
004121C5 MOV DWORD PTR DS:[EAX],ECX
004121C7 MOV EAX,DWORD PTR SS:[EBP+10]
004121CA MOV ECX,DWORD PTR SS:[EBP-14]
004121CD MOV DWORD PTR DS:[EAX],ECX
004121CF POP EDI
004121D0 POP ESI
004121D1 POP EBX
004121D2 ADD ESP,0F0
004121D8 CMP EBP,ESP
004121DA CALL CRACKME_.004113FC
004121DF MOV ESP,EBP
004121E1 POP EBP
004121E2 RETN
到这里,我们又分析出一个函数的过程了。过程如下:
Procedure BlowFish_En_Init(var xL, xR:DWORD; var pBox_Key:array of DWORD; var sBox_Key:MyArray);
var
i, tmp:DWORD;
begin
For i := 0 to $1D do
begin
xL := xL xor pBox_Key[i];
xR := xR xor BlowFish_Func(xl,sBox_Key);
tmp := xL;
xL := xR;
xR := tmp;
end;
tmp := xL;
xL := xR;
xR := tmp;
xR := xR xor pBox_Key[$1E];
xL := xL xor pBox_Key[$1F];
end;
现在我们接着分析BlowFish_Func函数,这个是BlowFish加解密函数要用到的中间函数。加密和解密都用他,所以我在这里分析一次,下面的加密函数中就略过不分析了。这个函数参考原型如下:
----------------Function BlowFish_Func(tmp:DWORD; sBox_Key:MyArray):DWORD;----------------------
0041216B |MOV EAX,DWORD PTR SS:[EBP-8]
0041216E |PUSH EAX ; /Arg2
0041216F |MOV ECX,DWORD PTR SS:[EBP+8] ; |
00412172 |PUSH ECX ; |Arg1
00412173 |CALL CRACKME_.00412220 ; \CRACKME_.00412220
------------------CALL BlowFish_Func------------------------------------------------------------
00412220 push ebp
00412221 mov ebp,esp
00412223 sub esp,0F0
00412229 push ebx
0041222A push esi
0041222B push edi
0041222C lea edi,dword ptr ss:[ebp-F0]
00412232 mov ecx,3C
00412237 mov eax,CCCCCCCC
0041223C rep stos dword ptr es:[edi]
下面一大段代码是将xL转换成Byte类型,高级语言表达如下:
a := Byte(xL and $000000FF);
b := Byte((xL and $0000FF00) shr 8);
c := Byte((xL and $00FF0000) shr $10);
d := Byte((xL and $FF000000) shr $18);
0041223E movzx eax,word ptr ss:[ebp+C]
00412242 and eax,0FF
00412247 mov word ptr ss:[ebp-2C],ax
0041224B mov eax,dword ptr ss:[ebp+C]
0041224E shr eax,8
00412251 mov dword ptr ss:[ebp+C],eax
00412254 movzx eax,word ptr ss:[ebp+C]
00412258 and eax,0FF
0041225D mov word ptr ss:[ebp-20],ax
00412261 mov eax,dword ptr ss:[ebp+C]
00412264 shr eax,8
00412267 mov dword ptr ss:[ebp+C],eax
0041226A movzx eax,word ptr ss:[ebp+C]
0041226E and eax,0FF
00412273 mov word ptr ss:[ebp-14],ax
00412277 mov eax,dword ptr ss:[ebp+C]
0041227A shr eax,8
0041227D mov dword ptr ss:[ebp+C],eax
00412280 movzx eax,word ptr ss:[ebp+C]
00412284 and eax,0FF
00412289 mov word ptr ss:[ebp-8],ax
开始加密:高级语言表达如下:
xL := (sBox_Key[2, a] - sBox_Key[1, c]) xor (sBox_Key[0, b] + sBox_Key[3, d]);
最后返回xL(Result := xL);
0041228D movzx eax,word ptr ss:[ebp-2C]
00412291 movzx ecx,word ptr ss:[ebp-14]
00412295 mov edx,dword ptr ss:[ebp+8]
00412298 mov esi,dword ptr ss:[ebp+8]
0041229B mov eax,dword ptr ds:[edx+eax*4+8>
004122A2 sub eax,dword ptr ds:[esi+ecx*4+4>
004122A9 movzx ecx,word ptr ss:[ebp-20]
004122AD movzx edx,word ptr ss:[ebp-8]
004122B1 mov esi,dword ptr ss:[ebp+8]
004122B4 mov ecx,dword ptr ds:[esi+ecx*4+8>
004122BB mov esi,dword ptr ss:[ebp+8]
004122BE add ecx,dword ptr ds:[esi+edx*4+C>
004122C5 xor eax,ecx
004122C7 pop edi
004122C8 pop esi
004122C9 pop ebx
004122CA mov esp,ebp
004122CC pop ebp
004122CD retn
到此,我们又得到一个函数:源码如下:
Function BlowFish_Func(xL:DWORD; sBox_Key:MyArray):DWORD;
var
a, b, c, d:Byte;
begin
a := Byte(xL and $000000FF);
b := Byte((xL and $0000FF00) shr 8);
c := Byte((xL and $00FF0000) shr $10);
d := Byte((xL and $FF000000) shr $18);
Result := (sBox_Key[2, a] - sBox_Key[1, c]) xor (sBox_Key[0, b] + sBox_Key[3, d]);
end;
最后,我们终于来到最关键处了,BlowFish加密算法上,其实这个加密算法和上面的BlowFish加密算法操作是一样的,只是上面的操作方法是从0~$1F依次循环加密的,而这个是反过来,从$1F~0依次循环加密的,因为这样,所以这个算法我就不细分析了。
这里开始对Sn1和Sn2进行BlowFish_En加密。参考函数原型如下:
------procedure BlowFish_En(var BlowFish_Init_En:array of DWORD; var Sn1, Sn2:DWORD);------------
00411E3E LEA EAX,DWORD PTR SS:[EBP-120]
00411E44 PUSH EAX ; var Sn2:DWORD;
00411E45 LEA ECX,DWORD PTR SS:[EBP-124]
00411E4B PUSH ECX ; var Sn1:DWORD;
00411E4C LEA EDX,DWORD PTR SS:[EBP-11AC]
00411E52 PUSH EDX ; var BlowFish_Init_En:array[1..1024] of DWORD;
00411E53 CALL CRACKME_.004114D3 ; CALL BlowFish_En;
------------------------CALL BlowFish_En--------------------------------------------------------
00412300 push ebp
00412301 mov ebp,esp
00412303 sub esp,0F0
00412309 push ebx
0041230A push esi
0041230B push edi
0041230C lea edi,dword ptr ss:[ebp-F0]
00412312 mov ecx,3C
00412317 mov eax,CCCCCCCC
0041231C rep stos dword ptr es:[edi]
0041231E mov eax,dword ptr ss:[ebp+C]
00412321 mov ecx,dword ptr ds:[eax]
00412323 mov dword ptr ss:[ebp-8],ecx ; var xL;
00412326 mov eax,dword ptr ss:[ebp+10]
00412329 mov ecx,dword ptr ds:[eax]
0041232B mov dword ptr ss:[ebp-14],ecx ; var xR;
0041232E mov word ptr ss:[ebp-2C],1F ; i := $1F;
00412334 jmp short CRACKME_.00412342
For i := $1F downto 2 do
begin
xL := xL xor pBox_Key[i];
xR := xR xor BlowFish_Func(xl, sBox_Key);
tmp := xL;
xL := xR;
xR := tmp;
end;
00412336 /mov ax,word ptr ss:[ebp-2C]
0041233A |sub ax,1
0041233E |mov word ptr ss:[ebp-2C],ax
00412342 movsx eax,word ptr ss:[ebp-2C]
00412346 |cmp eax,1
00412349 |jle short CRACKME_.00412385
xL := xL xor pBox_Key[i];
0041234B |movsx eax,word ptr ss:[ebp-2C]
0041234F |mov ecx,dword ptr ss:[ebp+8]
00412352 |mov edx,dword ptr ss:[ebp-8]
00412355 |xor edx,dword ptr ds:[ecx+eax*4]
00412358 |mov dword ptr ss:[ebp-8],edx
这个Call BlowFish_Func和上面的一模一样,所以这里不分析了,大家可以看前面的分析。
xR := xR xor BlowFish_Func(xl, sBox_Key);
0041235B |mov eax,dword ptr ss:[ebp-8]
0041235E |push eax ; /Arg2
0041235F |mov ecx,dword ptr ss:[ebp+8] ; |
00412362 |push ecx ; |Arg1
00412363 |call CRACKME_.00412220 ; \CRACKME_.00412220
00412368 |add esp,8
0041236B |xor eax,dword ptr ss:[ebp-14]
0041236E |mov dword ptr ss:[ebp-14],eax
tmp := xL;
xL := xR;
xR := tmp;
00412371 |mov eax,dword ptr ss:[ebp-8]
00412374 |mov dword ptr ss:[ebp-20],eax
00412377 |mov eax,dword ptr ss:[ebp-14]
0041237A |mov dword ptr ss:[ebp-8],eax
0041237D |mov eax,dword ptr ss:[ebp-20]
00412380 |mov dword ptr ss:[ebp-14],eax
00412383 \jmp short CRACKME_.00412336
tmp := xL;
xL := xR;
xR := tmp;
00412385 mov eax,dword ptr ss:[ebp-8]
00412388 mov dword ptr ss:[ebp-20],eax
0041238B mov eax,dword ptr ss:[ebp-14]
0041238E mov dword ptr ss:[ebp-8],eax
00412391 mov eax,dword ptr ss:[ebp-20]
00412394 mov dword ptr ss:[ebp-14],eax
xR := xR xor pBox_Key[1];
00412397 mov eax,dword ptr ss:[ebp+8]
0041239A mov ecx,dword ptr ss:[ebp-14]
0041239D xor ecx,dword ptr ds:[eax+4]
004123A0 mov dword ptr ss:[ebp-14],ecx
xL := xL xor pBox_Key[0];
004123A3 mov eax,dword ptr ss:[ebp+8]
004123A6 mov ecx,dword ptr ss:[ebp-8]
004123A9 xor ecx,dword ptr ds:[eax]
004123AB mov dword ptr ss:[ebp-8],ecx
保存结果运算结果。
004123AE mov eax,dword ptr ss:[ebp+C]
004123B1 mov ecx,dword ptr ss:[ebp-8]
004123B4 mov dword ptr ds:[eax],ecx
004123B6 mov eax,dword ptr ss:[ebp+10]
004123B9 mov ecx,dword ptr ss:[ebp-14]
004123BC mov dword ptr ds:[eax],ecx
004123BE pop edi
004123BF pop esi
004123C0 pop ebx
004123C1 add esp,0F0
004123C7 cmp ebp,esp
004123C9 call CRACKME_.004113FC
004123CE mov esp,ebp
004123D0 pop ebp
004123D1 retn
到这里后,这个CrackMe总算是分析完毕了。附上BlowFish的加密函数源码和解密函数源码作为最后的结束。
BlowFish_En加密函数:
Procedure BlowFish_En(var xL, xR:DWORD; var pBox_Key:array of DWORD; var sBox_Key:MyArray);
var
i, tmp:DWORD;
begin
For i := $1F downto 2 do
begin
xL := xL xor pBox_Key[i];
xR := xR xor BlowFish_Func(xl, sBox_Key);
tmp := xL;
xL := xR;
xR := tmp;
end;
tmp := xL;
xL := xR;
xR := tmp;
xR := xR xor pBox_Key[1];
xL := xL xor pBox_Key[0];
end;
BlowFish_De解密函数,BlowFish的解密函数也很简单,只须将加密函数倒转过来使用就行了。
BlowFish_De解密函数:
Procedure BlowFish_De(var xL, xR:DWORD; pBox_Key:array of DWORD; sBox_key:MyArray);
var
i, tmp:DWORD;
begin
xL := xL xor pBox_Key[0];
xR := xR xor pBox_Key[1];
tmp := xL;
xL := xR;
xR := tmp;
For i := 2 to $1F do
begin
tmp := xL;
xL := xR;
xR := tmp;
xR := xR xor BlowFish_Func(xL,sBox_Key);
xL := xL xor pBox_Key[i];
end;
end;
到这里,终于写完了,因为是边分析边写的(分析和写笔记共用了一个星期),可能写的比较乱,大家就将就点吧。希望对大家有点帮助。呵呵。
|
|