首页
社区
课程
招聘
[原创]HappyTown的第12个CrackMe分析_MD5
发表于: 2006-5-19 12:03 6949

[原创]HappyTown的第12个CrackMe分析_MD5

2006-5-19 12:03
6949

原CrackMe:
http://bbs.pediy.com/showthread.php?s=&threadid=25862

没人贴,我来贴吧~~先看标准的MD5加密算法,网络有大把,自己去COPY.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Label3: TLabel;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  MD5Count = array[0..1] of DWORD;
  MD5State = array[0..3] of DWORD;
  MD5Block = array[0..15] of DWORD;
  MD5CBits = array[0..7] of Byte;
  MD5Digest = array[0..15] of Byte;
  MD5Buffer = array[0..63] of Byte;
  MD5Context = record
    State: MD5State;
    Count: MD5Count;
    Buffer: MD5Buffer;
  end;

procedure MD5Init(var Context: MD5Context);
//四个32位变量初始化子程序
procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
//MD5模块更新操作
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
//MD5算法最终结束部分

function MD5String(M: string): MD5Digest;
function MD5File(N: string): MD5Digest;
function MD5Print(D: MD5Digest): string;
function MD5Match(D1, D2: MD5Digest): Boolean;

function RivestStr(Str: string): string;
//字符串加密函数
function RivestFile(FileName: string): string;
//文件加密函数

var
  Form1: TForm1;
  PADDING: MD5Buffer = (
//填充64位Buffer
    $80, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00,
    $00, $00, $00, $00, $00, $00, $00, $00);

implementation

{$R *.dfm}
//定义四个MD5基本的按位操作函数,四个非线性函数
//F(X,Y,Z)=(X&Y)|((~X)&Z)
function F(x, y, z: DWORD): DWORD;
begin
  Result := (x and y) or ((not x) and z);
end;

//G(X,Y,Z)=(X&Z)|(Y&(~Z))
function G(x, y, z: DWORD): DWORD;
begin
  Result := (x and z) or (y and (not z));
end;

//H(X,Y,Z)=X^Y^Z
function H(x, y, z: DWORD): DWORD;
begin
  Result := x xor y xor z;
end;

//I(X,Y,Z)=Y^(X|(~Z))
function I(x, y, z: DWORD): DWORD;
begin
  Result := y xor (x or (not z));
end;

//shl x n位
procedure rot(var x: DWORD; n: BYTE);
begin
  x := (x shl n) or (x shr (32 - n));
end;

//定义四个分别用于四轮变换的函数
//函数FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<<s)
procedure FF(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, F(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

//函数GG(a,b,c,d,x,s,ac)表示a=b+((a+(G(b,c,d)+x+ac)<<<s)
procedure GG(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, G(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

//函数HH(a,b,c,d,x,s,ac)表示a=b+((a+(H(b,c,d)+x+ac)<<<s)
procedure HH(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, H(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

//函数II(a,b,c,d,x,s,ac)表示a=b+((a+(I(b,c,d)+x+ac)<<<s)
procedure II(var a: DWORD; b, c, d, x: DWORD; s: BYTE; ac: DWORD);
begin
  inc(a, I(b, c, d) + x + ac);
  rot(a, s);
  inc(a, b);
end;

//编码子函数
//将int转换为char,假定长度为4的倍数
procedure Encode(Source, Target: pointer; Count: longword);

var
  S: PByte;
  T: PDWORD;
  I: longword;
begin
  S := Source;
  T := Target;
  for I := 1 to Count div 4 do begin
    T^ := S^;
    inc(S);
    T^ := T^ or (S^ shl 8);
    inc(S);
    T^ := T^ or (S^ shl 16);
    inc(S);
    T^ := T^ or (S^ shl 24);
    inc(S);
    inc(T);
  end;
end;

//解码子函数
//将char转换为int,假定长度为4的倍数
procedure Decode(Source, Target: pointer; Count: longword);

var
  S: PDWORD;
  T: PByte;
  I: longword;
begin
  S := Source;
  T := Target;
  for I := 1 to Count do begin
    T^ := S^ and $ff;
    inc(T);
    T^ := (S^ shr 8) and $ff;
    inc(T);
    T^ := (S^ shr 16) and $ff;
    inc(T);
    T^ := (S^ shr 24) and $ff;
    inc(T);
    inc(S);
  end;
end;

//对输入数据作变换
procedure Transform(Buffer: pointer; var State: MD5State);

var
  a, b, c, d: DWORD;
  Block: MD5Block;
begin
  Encode(Buffer, @Block, 64);
  a := State[0];
  b := State[1];
  c := State[2];
  d := State[3];
//第一轮
  FF (a, b, c, d, Block[ 0],  7, $d76aa478);
  FF (d, a, b, c, Block[ 1], 12, $e8c7b756);
  FF (c, d, a, b, Block[ 2], 17, $242070db);
  FF (b, c, d, a, Block[ 3], 22, $c1bdceee);
  FF (a, b, c, d, Block[ 4],  7, $f57c0faf);
  FF (d, a, b, c, Block[ 5], 12, $4787c62a);
  FF (c, d, a, b, Block[ 6], 17, $a8304613);
  FF (b, c, d, a, Block[ 7], 22, $fd469501);
  FF (a, b, c, d, Block[ 8],  7, $698098d8);
  FF (d, a, b, c, Block[ 9], 12, $8b44f7af);
  FF (c, d, a, b, Block[10], 17, $ffff5bb1);
  FF (b, c, d, a, Block[11], 22, $895cd7be);
  FF (a, b, c, d, Block[12],  7, $6b901122);
  FF (d, a, b, c, Block[13], 12, $fd987193);
  FF (c, d, a, b, Block[14], 17, $a679438e);
  FF (b, c, d, a, Block[15], 22, $49b40821);
//第二轮
  GG (a, b, c, d, Block[ 1],  5, $f61e2562);
  GG (d, a, b, c, Block[ 6],  9, $c040b340);
  GG (c, d, a, b, Block[11], 14, $265e5a51);
  GG (b, c, d, a, Block[ 0], 20, $e9b6c7aa);
  GG (a, b, c, d, Block[ 5],  5, $d62f105d);
  GG (d, a, b, c, Block[10],  9,  $2441453);
  GG (c, d, a, b, Block[15], 14, $d8a1e681);
  GG (b, c, d, a, Block[ 4], 20, $e7d3fbc8);
  GG (a, b, c, d, Block[ 9],  5, $21e1cde6);
  GG (d, a, b, c, Block[14],  9, $c33707d6);
  GG (c, d, a, b, Block[ 3], 14, $f4d50d87);
  GG (b, c, d, a, Block[ 8], 20, $455a14ed);
  GG (a, b, c, d, Block[13],  5, $a9e3e905);
  GG (d, a, b, c, Block[ 2],  9, $fcefa3f8);
  GG (c, d, a, b, Block[ 7], 14, $676f02d9);
  GG (b, c, d, a, Block[12], 20, $8d2a4c8a);
//第三轮
  HH (a, b, c, d, Block[ 5],  4, $fffa3942);
  HH (d, a, b, c, Block[ 8], 11, $8771f681);
  HH (c, d, a, b, Block[11], 16, $6d9d6122);
  HH (b, c, d, a, Block[14], 23, $fde5380c);
  HH (a, b, c, d, Block[ 1],  4, $a4beea44);
  HH (d, a, b, c, Block[ 4], 11, $4bdecfa9);
  HH (c, d, a, b, Block[ 7], 16, $f6bb4b60);
  HH (b, c, d, a, Block[10], 23, $bebfbc70);
  HH (a, b, c, d, Block[13],  4, $289b7ec6);
  HH (d, a, b, c, Block[ 0], 11, $eaa127fa);
  HH (c, d, a, b, Block[ 3], 16, $d4ef3085);
  HH (b, c, d, a, Block[ 6], 23,  $4881d05);
  HH (a, b, c, d, Block[ 9],  4, $d9d4d039);
  HH (d, a, b, c, Block[12], 11, $e6db99e5);
  HH (c, d, a, b, Block[15], 16, $1fa27cf8);
  HH (b, c, d, a, Block[ 2], 23, $c4ac5665);
//第四轮
  II (a, b, c, d, Block[ 0],  6, $f4292244);
  II (d, a, b, c, Block[ 7], 10, $432aff97);
  II (c, d, a, b, Block[14], 15, $ab9423a7);
  II (b, c, d, a, Block[ 5], 21, $fc93a039);
  II (a, b, c, d, Block[12],  6, $655b59c3);
  II (d, a, b, c, Block[ 3], 10, $8f0ccc92);
  II (c, d, a, b, Block[10], 15, $ffeff47d);
  II (b, c, d, a, Block[ 1], 21, $85845dd1);
  II (a, b, c, d, Block[ 8],  6, $6fa87e4f);
  II (d, a, b, c, Block[15], 10, $fe2ce6e0);
  II (c, d, a, b, Block[ 6], 15, $a3014314);
  II (b, c, d, a, Block[13], 21, $4e0811a1);
  II (a, b, c, d, Block[ 4],  6, $f7537e82);
  II (d, a, b, c, Block[11], 10, $bd3af235);
  II (c, d, a, b, Block[ 2], 15, $2ad7d2bb);
  II (b, c, d, a, Block[ 9], 21, $eb86d391);
//将A,B,C,D分别加上a,b,c,d
  inc(State[0], a);
  inc(State[1], b);
  inc(State[2], c);
  inc(State[3], d);
end;

//四个32位变量初始化A,B,C,D(MD5参数)
procedure MD5Init(var Context: MD5Context);
begin
  with Context do begin
    State[0] := $67452301;
    State[1] := $efcdab89;
    State[2] := $98badcfe;
    State[3] := $10325476;
    Count[0] := 0;
    Count[1] := 0;
//用0填充64位Buffer
    ZeroMemory(@Buffer, SizeOf(MD5Buffer));
  end;
end;

//MD5模块更新操作,产生MD5消息摘要
operation, processing another message block, and updating the
context.
procedure MD5Update(var Context: MD5Context; Input: pChar; Length: longword);
var
  Index: longword;
  PartLen: longword;
  I: longword;
begin
  with Context do begin
//计算number of bytes mod 64
    Index := (Count[0] shr 3) and $3f;
//Update number of bits
    inc(Count[0], Length shl 3);
    if Count[0] < (Length shl 3) then inc(Count[1]);
    inc(Count[1], Length shr 29);
  end;
  PartLen := 64 - Index;
//变换操作
  if Length >= PartLen then begin
//输入Buffer剩余部分
    CopyMemory(@Context.Buffer[Index], Input, PartLen);
    Transform(@Context.Buffer, Context.State);
    I := PartLen;
    while I + 63 < Length do begin
      Transform(@Input[I], Context.State);
      inc(I, 64);
    end;
    Index := 0;
  end else I := 0;
  CopyMemory(@Context.Buffer[Index], @Input[I], Length - I);
end;

//MD5算法结束部分. 固定MD5消息摘要操作, 写入消息摘要以及将其余部分填充0操作.
procedure MD5Final(var Context: MD5Context; var Digest: MD5Digest);
//输出结果.A,B,C,D连续存放,共16个字节,128位。按十六进制依次输出这个16个字节。
var
  Bits: MD5CBits;
  Index: longword;
  PadLen: longword;
begin
  Decode(@Context.Count, @Bits, 2);
//Pad out to 56 mod 64
  Index := (Context.Count[0] shr 3) and $3f;
  if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index;
  MD5Update(Context, @PADDING, PadLen);
//扩展长度 (填充前)
  MD5Update(Context, @Bits, 8);
//将State值(A,B,C,D)存储于摘要中
  Decode(@Context.State, @Digest, 4);
//以0填充其余部分
  ZeroMemory(@Context, SizeOf(MD5Context));
end;

function MD5String(M: string): MD5Digest;
var
        Context: MD5Context;
begin
        MD5Init(Context);
        MD5Update(Context, pChar(M), length(M));
        MD5Final(Context, Result);
end;

function MD5File(N: string): MD5Digest;
var
        FileHandle: THandle;
        MapHandle: THandle;
        ViewPointer: pointer;
        Context: MD5Context;
begin
        MD5Init(Context);
        FileHandle := CreateFile(pChar(N), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
                nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
        if FileHandle <> INVALID_HANDLE_VALUE then try
                MapHandle := CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
                if MapHandle <> 0 then try
                        ViewPointer := MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
                        if ViewPointer <> nil then try
                                MD5Update(Context, ViewPointer, GetFileSize(FileHandle, nil));
                        finally
                                UnmapViewOfFile(ViewPointer);
                        end;
                finally
                        CloseHandle(MapHandle);
                end;
        finally
                CloseHandle(FileHandle);
        end;
        MD5Final(Context, Result);
end;

function MD5Print(D: MD5Digest): string;
var
        I: byte;
const
        Digits: array[0..15] of char =
                ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
begin
        Result := '';
        for I := 0 to 15 do Result := Result + Digits[(D[I] shr 4) and $0f] + Digits[D[I] and $0f];
end;

function MD5Match(D1, D2: MD5Digest): boolean;
var
        I: byte;
begin
        I := 0;
        Result := TRUE;
        while Result and (I < 16) do begin
                Result := D1[I] = D2[I];
                inc(I);
        end;
end;

function RivestStr(Str: string): string;
begin
  Result := MD5Print(MD5String(Str));
end;

function RivestFile(FileName: string): string;
begin
  Result := MD5Print(MD5File(FileName));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
//function RivestStr(Str: string): string;为字符串加密函数;
  if RivestStr(Edit1.Text)=Edit2.Text then
    ShowMessage('注册成功!')
  else
    ShowMessage('注册失败!');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Close;
end;

end.
调试分析,所有标注如下:
用户定义的注释
地址       反汇编                                    注释
004511B4   push    ebp                               Encode(Source, Target: pointer; Count: longword)调用开始
004511BA   mov     [ebp-C], ecx                      I: longword
004511BD   mov     [ebp-8], edx                      T: PDWORD
004511C0   mov     [ebp-4], eax                      S: PByte
004511C6   mov     [ebp-10], eax                     S := Source
004511CC   mov     [ebp-14], eax                     T := Target
004511D7   jbe     short 00451230                    for I := 1 to Count div 4 do begin
004511E3   mov     eax, [ebp-10]                     T^ := S^
004511EE   inc     dword ptr [ebp-10]                inc(S)
004511FD   or      [edx], eax                        T^ := T^ or (S^ shl 8)
004511FF   inc     dword ptr [ebp-10]                inc(S)
0045120E   or      [edx], eax                        T^ := T^ or (S^ shl 16)
00451210   inc     dword ptr [ebp-10]                inc(S)
0045121F   or      [edx], eax                        T^ := T^ or (S^ shl 24)
00451221   inc     dword ptr [ebp-10]                inc(S)
00451228   inc     dword ptr [ebp-18]                inc(T)
00451234   push    ebp                               Decode(Source, Target: pointer; Count: longword)调用开始
0045123A   mov     [ebp-C], ecx                      I: longword
0045123D   mov     [ebp-8], edx                      T: PByte
00451240   mov     [ebp-4], eax                      S: PDWORD
00451254   jbe     short 004512B1                    for I := 1 to Count do begin
00451265   and     al, 0FF                           T^ := S^ and $ff
0045126C   inc     dword ptr [ebp-14]                inc(T)
00451277   and     al, 0FF                           T^ := (S^ shr 8) and $ff
0045127E   inc     dword ptr [ebp-14]                inc(T)
00451289   and     al, 0FF                           T^ := (S^ shr 16) and $ff
00451290   inc     dword ptr [ebp-14]                inc(T)
0045129B   and     al, 0FF                           T^ := (S^ shr 24) and $ff
004512A2   inc     dword ptr [ebp-14]                inc(T)
004512A9   inc     dword ptr [ebp-18]                inc(S)
004512B8   push    ebp                               Transform(Buffer: pointer; var State: MD5State)调用开始
004512CF   call    004511B4                          Encode(Buffer, @Block, 64)
004512D9   mov     [ebp-C], eax                      a := State[0]
004512E2   mov     [ebp-10], eax                     b := State[1]
004512EB   mov     [ebp-14], eax                     c := State[2]
004512F4   mov     [ebp-18], eax                     d := State[3]
004512F7   mov     eax, [ebp-18]                     第一轮开始FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<<s)
004514C7   mov     eax, [ebp-18]                     第二轮开始GG(a,b,c,d,Mj,s,ti)表示a=b+((a+(G(b,c,d)+Mj+ti)<<<s)
00451697   mov     eax, [ebp-18]                     第三轮开始HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<<<s)
00451867   mov     eax, [ebp-18]                     第四轮开始II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<<<s)
00451A60   push    ebp                               MD5开始初始化
00451A67   mov     eax, [ebp-4]                      四个32位链接变量初始化
00451A6A   mov     dword ptr [eax], 67452301         A=0x01234567,State[0]
00451A73   mov     dword ptr [eax+4], EFCDAB89       B=0x89abcdef,State[1]
00451A7D   mov     dword ptr [eax+8], 98BADCFE       C=0xfedcba98,State[2]
00451A87   mov     dword ptr [eax+C], 10325476       D=0x76543210,State[3]
00451A93   mov     [eax+10], edx                     Count[0]=0
00451A9B   mov     [eax+14], edx                     Count[1]=0
00451AA9   call    0040665C                          ZeroMemory(@Buffer, SizeOf(MD5Buffer)),此处为0012F550开始,buffer=0x40
00451AB4   push    ebp                               MD5Update调用开始
00451AC7   mov     eax, [eax+10]                     Index := (Count[0] shr 3) and $3f
00451AD3   mov     eax, [ebp-C]                      inc(Count[0], Length shl 3)
00451AED   jnb     short 00451AF5                    if Count[0] < (Length shl 3) then inc(Count[1])
00451AF5   mov     eax, [ebp-C]                      inc(Count[1], Length shr 29)
00451B06   sub     eax, [ebp-10]                     PartLen := 64 - Index
00451B12   jb      short 00451B65                    if Length >= PartLen then begin
00451B24   call    00406654                          CopyMemory(@Context.Buffer[Index], Input, PartLen)
00451B32   call    004512B8                          Transform(@Context.Buffer, Context.State)
00451B4A   call    004512B8                          Transform(@Input[I], Context.State)
00451B4F   add     dword ptr [ebp-18], 40            inc(I, 64)
00451B5C   jb      short 00451B3F                    while I + 63 < Length do begin
00451B5E   xor     eax, eax                          Index := 0
00451B65   xor     eax, eax                          end else I := 0
00451B82   call    00406654                          CopyMemory(@Context.Buffer[Index], Input, PartLen)
00451B8C   push    ebp                               MD5Final调用开始
00451BA1   mov     ecx, 2                            Decode(@Context.Count, @Bits, 2)
00451BA6   call    00451234                          算法的主循环,循环的次数是消息中512位消息分组的数目
00451BAE   mov     eax, [eax+10]                     Index := (Context.Count[0] shr 3) and $3f
00451BBE   jnb     short 00451BCD                    if Index < 56 then PadLen := 56 - Index else PadLen := 120 - Index
00451BE3   call    00451AB4                          MD5Update(Context, @PADDING, PadLen)
00451BF3   call    00451AB4                          MD5Update(Context, @Bits, 8)
00451BFE   mov     ecx, 4                            Decode(@Context.State, @Digest, 4)
00451C03   call    00451234                          算法的主循环,循环的次数是消息中512位消息分组的数目
00451C10   call    0040665C                          ZeroMemory(@Context, SizeOf(MD5Context))
00451C41   call    00451A60                          MD5Init
00451C49   call    004040D0                          PartLen: longword
00451C52   call    004042D0                          Index: longword
00451C5D   call    00451AB4                          MD5Update
00451C68   call    00451B8C                          MD5Final
00451D78   call    00451C1C                          MD5(name)
00452019   lea     eax, [eax]                        (初始 CPU 选择)
0045201C   push    ebp                               点击确定
00452042   mov     eax, [eax+2F8]                    edtName : N.A.
00452048   call    00430348                          TControl.GetText(TControl):TCaption;
00452053   call    00451D50                          MD5(name)
0045206F   call    00430348                          TControl.GetText(TControl):TCaption;
00452085   call    0040421C                          LStrCmp;
比较后相等就注册成功.

MD5算法分析

在一些初始化处理后,MD5以512位分组来处理输入文本,每一分组又划分为16个32位子分组。算法的输出由四个32位分组组成,将它们级联

形成一个128位散列值。
首先填充消息使其长度恰好为一个比512位的倍数仅小64位的数。填充方法是附一个1在消息后面,后接所要求的多个0,然后在其后附上64

位的消息长度(填充前)。这两步的作用是使消息长度恰好是512位的整数倍(算法的其余部分要求如此),同时确保不同的消息在填充后

不相同。
四个32位变量初始化为:
A=0x01234567
B=0x89abcdef
C=0xfedcba98
D=0x76543210
它们称为链接变量(chaining variable)
接着进行算法的主循环,循环的次数是消息中512位消息分组的数目。
将上面四个变量复制到别外的变量中:A到a,B到b,C到c,D到d。
主循环有四轮(MD4只有三轮),每轮很相拟。第一轮进行16次操作。每次操作对a,b,c和d中的其中三个作一次非线性函数运算,然后将

所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a,b,c或d中之一。最后用该结果

取代a,b,c或d中之一。
以一下是每次操作中用到的四个非线性函数(每轮一个)。
F(X,Y,Z)=(X&Y)|((~X)&Z)
G(X,Y,Z)=(X&Z)|(Y&(~Z))
H(X,Y,Z)=X^Y^Z
I(X,Y,Z)=Y^(X|(~Z))
(&是与,|是或,~是非,^是异或)
这些函数是这样设计的:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。
函数F是按逐位方式操作:如果X,那么Y,否则Z。函数H是逐位奇偶操作符。
设Mj表示消息的第j个子分组(从0到15),<<<s表示循环左移s位,则四种操作为:
FF(a,b,c,d,Mj,s,ti)表示a=b+((a+(F(b,c,d)+Mj+ti)<<<s)
GG(a,b,c,d,Mj,s,ti)表示a=b+((a+(G(b,c,d)+Mj+ti)<<<s)
HH(a,b,c,d,Mj,s,ti)表示a=b+((a+(H(b,c,d)+Mj+ti)<<<s)
II(a,b,c,d,Mj,s,ti)表示a=b+((a+(I(b,c,d)+Mj+ti)<<<s)
这四轮(64步)是:
第一轮
FF(a,b,c,d,M0,7,0xd76aa478)
FF(d,a,b,c,M1,12,0xe8c7b756)
FF(c,d,a,b,M2,17,0x242070db)
FF(b,c,d,a,M3,22,0xc1bdceee)
FF(a,b,c,d,M4,7,0xf57c0faf)
FF(d,a,b,c,M5,12,0x4787c62a)
FF(c,d,a,b,M6,17,0xa8304613)
FF(b,c,d,a,M7,22,0xfd469501)
FF(a,b,c,d,M8,7,0x698098d8)
FF(d,a,b,c,M9,12,0x8b44f7af)
FF(c,d,a,b,M10,17,0xffff5bb1)
FF(b,c,d,a,M11,22,0x895cd7be)
FF(a,b,c,d,M12,7,0x6b901122)
FF(d,a,b,c,M13,12,0xfd987193)
FF(c,d,a,b,M14,17,0xa679438e)
FF(b,c,d,a,M15,22,0x49b40821)
第二轮
GG(a,b,c,d,M1,5,0xf61e2562)
GG(d,a,b,c,M6,9,0xc040b340)
GG(c,d,a,b,M11,14,0x265e5a51)
GG(b,c,d,a,M0,20,0xe9b6c7aa)
GG(a,b,c,d,M5,5,0xd62f105d)
GG(d,a,b,c,M10,9,0x02441453)
GG(c,d,a,b,M15,14,0xd8a1e681)
GG(b,c,d,a,M4,20,0xe7d3fbc8)
GG(a,b,c,d,M9,5,0x21e1cde6)
GG(d,a,b,c,M14,9,0xc33707d6)
GG(c,d,a,b,M3,14,0xf4d50d87)
GG(b,c,d,a,M8,20,0x455a14ed)
GG(a,b,c,d,M13,5,0xa9e3e905)
GG(d,a,b,c,M2,9,0xfcefa3f8)
GG(c,d,a,b,M7,14,0x676f02d9)
GG(b,c,d,a,M12,20,0x8d2a4c8a)
第三轮
HH(a,b,c,d,M5,4,0xfffa3942)
HH(d,a,b,c,M8,11,0x8771f681)
HH(c,d,a,b,M11,16,0x6d9d6122)
HH(b,c,d,a,M14,23,0xfde5380c)
HH(a,b,c,d,M1,4,0xa4beea44)
HH(d,a,b,c,M4,11,0x4bdecfa9)
HH(c,d,a,b,M7,16,0xf6bb4b60)
HH(b,c,d,a,M10,23,0xbebfbc70)
HH(a,b,c,d,M13,4,0x289b7ec6)
HH(d,a,b,c,M0,11,0xeaa127fa)
HH(c,d,a,b,M3,16,0xd4ef3085)
HH(b,c,d,a,M6,23,0x04881d05)
HH(a,b,c,d,M9,4,0xd9d4d039)
HH(d,a,b,c,M12,11,0xe6db99e5)
HH(c,d,a,b,M15,16,0x1fa27cf8)
HH(b,c,d,a,M2,23,0xc4ac5665)
第四轮
II(a,b,c,d,M0,6,0xf4292244)
II(d,a,b,c,M7,10,0x432aff97)
II(c,d,a,b,M14,15,0xab9423a7)
II(b,c,d,a,M5,21,0xfc93a039)
II(a,b,c,d,M12,6,0x655b59c3)
II(d,a,b,c,M3,10,0x8f0ccc92)
II(c,d,a,b,M10,15,0xffeff47d)
II(b,c,d,a,M1,21,0x85845dd1)
II(a,b,c,d,M8,6,0x6fa87e4f)
II(d,a,b,c,M15,10,0xfe2ce6e0)
II(c,d,a,b,M6,15,0xa3014314)
II(b,c,d,a,M13,21,0x4e0811a1)
II(a,b,c,d,M4,6,0xf7537e82)
II(d,a,b,c,M11,10,0xbd3af235)
II(c,d,a,b,M2,15,0x2ad7d2bb)
II(b,c,d,a,M9,21,0xeb86d391)
常数ti可以如下选择:
在第i步中,ti是4294967296*abs(sin(i))的整数部分,i的单位是弧度。
(2的32次方)
所有这些完成之后,将A,B,C,D分别加上a,b,c,d。然后用下一分组数据继续运行算法,最后的输出是A,B,C和D的级联。

MD5的安全性

MD5相对MD4所作的改进:
1.增加了第四轮.
2.每一步均有唯一的加法常数.
3.为减弱第二轮中函数G的对称性从(X&Y)|(X&Z)|(Y&Z)变为(X&Z)|(Y&(~Z))
4.第一步加上了上一步的结果,这将引起更快的雪崩效应.
5.改变了第二轮和第三轮中访问消息子分组的次序,使其更不相似.
6.近似优化了每一轮中的循环左移位移量以实现更快的雪崩效应.各轮的位移量互不相同.
网络资源多的很,COPY自己跟着调试就OK,仅供新手学习,共同进步.破解基本靠猜~调试一次不熟悉,多几次就OK啦.


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
2
欢迎你继续分析我的CrackMe密码学系列,以飨初学者。
2006-5-22 08:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
学习了,觉得还是很复杂啊,看来自己水平不够,唉
2006-5-24 23:08
0
游客
登录 | 注册 方可回帖
返回
//