My FAQ,最新最全的IT技术FAQ
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 未整理篇 | 技术讨论
  当前位置:> 看雪学院专区 > CrackMe
ikki_CrackMe变形SHA和变形BlowFish逆向分析(四)
作者:佚名 时间:2005-11-17 12:36 出处:pediy.com 责编:My FAQ
              摘要:ikki_CrackMe变形SHA和变形BlowFish逆向分析(四)
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:DWORDvar pBox_Key:array of DWORDvar 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:DWORDvar pBox_Key:array of DWORDvar 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:DWORDvar pBox_Key:array of DWORDvar 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 DWORDvar 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:DWORDvar pBox_Key:array of DWORDvar 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;

到这里,终于写完了,因为是边分析边写的(分析和写笔记共用了一个星期),可能写的比较乱,大家就将就点吧。希望对大家有点帮助。呵呵。

 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 myfaq.com.cn All rights reserved. www.myfaq.com.cn 版权所有