飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2624|回复: 6

菜鸟学习《加密与解密》BlowFish笔记

[复制链接]
  • TA的每日心情

    2024-4-11 22:10
  • 签到天数: 53 天

    [LV.5]常住居民I

    发表于 2005-9-10 21:19:49 | 显示全部楼层 |阅读模式
    【破文作者】   rdsnow[BCG][PYG][D.4s]

    【作者主页】   http://rdsnow.ys168.com

    【 E-mail 】   rdsnow@163.com

    【 作者QQ 】   83757177

    【文章题目】   菜鸟学习《加密与解密》BlowFish笔记

    破解平台】   Win9x/NT/2000/XP/XP SP2

    ----------------------------------------------------------------------------------------------
    【文章简介】

    这两天跟踪某个软件,其中使用了变了形的BlowFish,虽然可以找到注册码的保存地址做出内存注册机,但是写不出算法注册机,心里很不平衡。以前从来没有接触过密码学知识,就从这个对称算法开始吧!

    ----------------------------------------------------------------------------------------------
    【破解过程】

    BlowFish是个64位分组的算法。输入64信息,运算后输出64位密文。

    刚开始当然要找个简单的。找来找去,最后拿《加密与解密》光盘上的夜月的BlowFish's crackme KeyGen分析了。这个keygen对ID(待加密数据)进行了两次BlowFish的计算。

    通过跟踪发现,对某个消息加密的过程,分两步进行:

    1、密钥预处理过程:
    6A 12           PUSH 12                                    ; /Arg2 = 00000012    压入密钥长度12
    68 00304000     PUSH BFKEYGEN.00403000                     ; |Arg1 = 00403000    压入密钥地址
    E8 50FEFFFF     CALL BFKEYGEN.004010C8                     ; \BFKEYGEN.004010C8  密钥预处理

    2、对信息加密过程:
    68 CD404000     PUSH BFKEYGEN.004040CD                     ; /Arg2 = 004040CD    被加密信息的地址1
    68 D1404000     PUSH BFKEYGEN.004040D1                     ; |Arg1 = 004040D1    被加密信息的地址2
    E8 E5FDFFFF     CALL BFKEYGEN.0040106C                     ; \BFKEYGEN.0040106C  BlowFish的核心函数BF_EN加密函数

    先来认识一下BlowFish的两个盒,所谓盒子,我想就是两个数组:

    PBOX盒:unsigned long PBOX[18],有18个元素的一维数组

    unsigned long PBOX[4,256],总共有1024个元素的二维数组

    这两个盒子里已经保存了一些固定的数值:

    PBOX    dd 0243f6a88h, 085a308d3h, 013198a2eh, 003707344h, 0a4093822h, 0299f31d0h
            dd 0082efa98h, 0ec4e6c89h, 0452821e6h, 038d01377h, 0be5466cfh, 034e90c6ch
            dd 0c0ac29b7h, 0c97c50ddh, 03f84d5b5h, 0b5470917h, 09216d5d9h, 08979fb1bh

    SBOX1   dd 0d1310ba6h, 098dfb5ach, 02ffd72dbh, 0d01adfb7h, 0b8e1afedh, 06a267e96h
            dd 0ba7c9045h, 0f12c7f99h, 024a19947h, 0b3916cf7h, 00801f2e2h, 0858efc16h
            dd 0636920d8h, 071574e69h, 0a458fea3h, …………(因为很多所以就省略了)

    SBOX2   ………………

    SBOX3   ………………

    SBOX4   ………………

    MD5编码过程中只要用到4个常数,而BlowFish却要用到这么多常数。现在很多的算法search工具,就是通过搜索SBOX来判断程序使用了什么算法的。

    ★★★★★★★★★★★★过程1、密钥的预处理★★★★★★★★★★★★

    6A 12           PUSH 12                                    ; /Arg2 = 00000012    压入密钥长度12
    68 00304000     PUSH BFKEYGEN.00403000                     ; |Arg1 = 00403000    压入密钥地址
    E8 50FEFFFF     CALL BFKEYGEN.004010C8                     ; \BFKEYGEN.004010C8  密钥预处理

    跟进CALL BFKEYGEN.004010C8

    004010C8  /$  55              PUSH EBP
    004010C9  |.  8BEC            MOV EBP,ESP
    004010CB  |.  83C4 F4         ADD ESP,-0C
    004010CE  |.  53              PUSH EBX
    004010CF  |.  57              PUSH EDI
    004010D0  |.  56              PUSH ESI
    004010D1  |.  52              PUSH EDX
    004010D2  |.  51              PUSH ECX
    004010D3  |.  BE 3D304000     MOV ESI,BFKEYGEN.0040303D                  ;  KEY_PBOX地址(PBOX处理后放到这里)
    004010D8  |.  B8 1D414000     MOV EAX,BFKEYGEN.0040411D                  ;  SBOX地址
    004010DD  |.  8D4E 48         LEA ECX,DWORD PTR DS:[ESI+48]              ;  KEY_SBOX地址(SBOX处理后放到这里)
    004010E0  |>  BA 00010000     /MOV EDX,100                               ;  开始循环
    004010E5  |>  8B38            |/MOV EDI,DWORD PTR DS:[EAX]               ;  取SBOX内容
    004010E7  |.  83C0 04         ||ADD EAX,4
    004010EA  |.  8939            ||MOV DWORD PTR DS:[ECX],EDI               ;  填充到KEY_SBOX
    004010EC  |.  83C1 04         ||ADD ECX,4
    004010EF  |.  4A              ||DEC EDX
    004010F0  |.^ 75 F3           |\JNZ SHORT BFKEYGEN.004010E5
    004010F2  |.  3D 1D514000     |CMP EAX,BFKEYGEN.0040511D                 ;  判断有没有填充完毕
    004010F7  |.^ 7C E7           \JL SHORT BFKEYGEN.004010E0                ;  循环出口

    以上循环结束了,这个循环就是SBOX的1024个元素搬新家,搬到KEY_SBOX

    004010F9  |.  8B55 08         MOV EDX,DWORD PTR SS:[EBP+8]               ;  取用户密钥KEY的地址
    004010FC  |.  BF D5404000     MOV EDI,BFKEYGEN.004040D5
    00401101  |.  33C0            XOR EAX,EAX
    00401103  |.  2BFE            SUB EDI,ESI
    00401105  |.  C745 FC 1200000>MOV DWORD PTR SS:[EBP-4],12                ;  置循环次数为18(PBOX内有18个元素)
    0040110C  |>  33C9            /XOR ECX,ECX                               ;  进入循环
    0040110E  |.  C745 F8 0400000>|MOV DWORD PTR SS:[EBP-8],4
    00401115  |>  33DB            |/XOR EBX,EBX
    00401117  |.  8A1C02          ||MOV BL,BYTE PTR DS:[EDX+EAX]
    0040111A  |.  C1E1 08         ||SHL ECX,8
    0040111D  |.  0BCB            ||OR ECX,EBX
    0040111F  |.  40              ||INC EAX
    00401120  |.  3B45 0C         ||CMP EAX,DWORD PTR SS:[EBP+C]
    00401123  |.  7C 02           ||JL SHORT BFKEYGEN.00401127
    00401125  |.  33C0            ||XOR EAX,EAX
    00401127  |>  8B5D F8         ||MOV EBX,DWORD PTR SS:[EBP-8]
    0040112A  |.  4B              ||DEC EBX
    0040112B  |.  895D F8         ||MOV DWORD PTR SS:[EBP-8],EBX
    0040112E  |.^ 75 E5           |\JNZ SHORT BFKEYGEN.00401115              ;  这里嵌套了个小循环,作用是用KEY中依次取4个字符的ASC,如果KEY取完,就从KEY的头个字母继续取
    00401130  |.  8B1C3E          |MOV EBX,DWORD PTR DS:[ESI+EDI]
    00401133  |.  83C6 04         |ADD ESI,4
    00401136  |.  33D9            |XOR EBX,ECX                               ;  用取出的4个字符的ASC XOR PBOX
    00401138  |.  8B4D FC         |MOV ECX,DWORD PTR SS:[EBP-4]
    0040113B  |.  895E FC         |MOV DWORD PTR DS:[ESI-4],EBX              ;  用异或结果填充KEY_PBOX
    0040113E  |.  49              |DEC ECX                                   ;  计数器减1
    0040113F  |.  894D FC         |MOV DWORD PTR SS:[EBP-4],ECX
    00401142  |.^ 75 C8           \JNZ SHORT BFKEYGEN.0040110C               ;  循环出口

    上面循环作用是:依次取KEY的字符的ASC异或PBOX,KEY可以循环使用,结果保存在KEY_PBOX中。

    接下来要使用BlowFish的核心函数BF_EN来处理KEY_PBOX了,这个BF_EN函数就是后来用来加密输入信息的。被加密的64位信息被分成32位的两部分,XL和XR

    PUSH BFKEYGEN.004040CD                     ; /Arg2 = 004040CD    XR的地址
    PUSH BFKEYGEN.004040D1                     ; |Arg1 = 004040D1    XL的地址
    CALL BFKEYGEN.0040106C                     ; \BFKEYGEN.0040106C  BlowFish的核心函数BF_EN加密函数
    输出信息保存在[4040C5]和[4040D1]两个地址中。

    00401144  |.  BB 3D304000     MOV EBX,BFKEYGEN.0040303D                  ;  KEY_PBOX地址
    00401149  |.  33C0            XOR EAX,EAX
    0040114B  |.  A3 C5404000     MOV DWORD PTR DS:[4040C5],EAX              ;  [4040C5]保存了XR,先置0
    00401150  |.  A3 C9404000     MOV DWORD PTR DS:[4040C9],EAX              ;  [4040C9]保存了XL,先置0
    00401155  |.  8BF3            MOV ESI,EBX
    00401157  |.  BF 09000000     MOV EDI,9                                  ;  循环次数置9
    0040115C  |>  8D05 C5404000   /LEA EAX,DWORD PTR DS:[4040C5]             ;  进入循环
    00401162  |.  8D0D C9404000   |LEA ECX,DWORD PTR DS:[4040C9]
    00401168  |.  50              |PUSH EAX                                  ; /Arg2 => 004040C5
    00401169  |.  51              |PUSH ECX                                  ; |Arg1 => 004040C9
    0040116A  |.  E8 FDFEFFFF     |CALL BFKEYGEN.0040106C                    ; \核心加密函数:BF_EN
    0040116F  |.  A1 C9404000     |MOV EAX,DWORD PTR DS:[4040C9]
    00401174  |.  8B0D C5404000   |MOV ECX,DWORD PTR DS:[4040C5]             ;  取出BF_EN结果
    0040117A  |.  8906            |MOV DWORD PTR DS:[ESI],EAX
    0040117C  |.  894E 04         |MOV DWORD PTR DS:[ESI+4],ECX              ;  替换KEY_PBOX的数据
    0040117F  |.  83C6 08         |ADD ESI,8
    00401182  |.  4F              |DEC EDI
    00401183  |.^ 75 D7           \JNZ SHORT BFKEYGEN.0040115C               ;  循环出口

    这个循环大致是这样的:
    BF_EN (0x0000000000000000)    结果填入KEY_BOX[1]KEY_BOX[2]
    BF_EN(KEY_BOX[1]KEY_BOX[2])   结果填入KEY_BOX[3]KEY_BOX[4]
    BF_EN(KEY_BOX[3]KEY_BOX[4])   结果填入KEY_BOX[5]KEY_BOX[6]
    ……………………
    BF_EN(KEY_BOX[15]KEY_BOX[16]) 结果填入KEY_BOX[17]KEY_BOX[18]
    BF_EN(KEY_BOX[17]KEY_BOX[18]) 结果填入KEY_BOX[1]KEY_BOX[2]

    00401185  |.  8D73 4C         LEA ESI,DWORD PTR DS:[EBX+4C]              ; ESI-4是KEYSBOX的地址
    00401188  |.  C745 F4 0400000>MOV DWORD PTR SS:[EBP-C],4
    0040118F  |>  BF 80000000     /MOV EDI,80
    00401194  |>  8D0D C5404000   |/LEA ECX,DWORD PTR DS:[4040C5]            ; 这里循环前保存了对KEY_PBOX处理的结果
    0040119A  |.  8D15 C9404000   ||LEA EDX,DWORD PTR DS:[4040C9]            ; 这里循环前保存了对KEY_PBOX处理的结果
    004011A0  |.  51              ||PUSH ECX                                 ; /Arg2 => 004040C5
    004011A1  |.  52              ||PUSH EDX                                 ; |Arg1 => 004040C9
    004011A2  |.  E8 C5FEFFFF     ||CALL BFKEYGEN.0040106C                   ; \BFKEYGEN.0040106C
    004011A7  |.  8B0D C9404000   ||MOV ECX,DWORD PTR DS:[4040C9]
    004011AD  |.  8B15 C5404000   ||MOV EDX,DWORD PTR DS:[4040C5]
    004011B3  |.  894E FC         ||MOV DWORD PTR DS:[ESI-4],ECX
    004011B6  |.  8916            ||MOV DWORD PTR DS:[ESI],EDX
    004011B8  |.  83C6 08         ||ADD ESI,8
    004011BB  |.  4F              ||DEC EDI
    004011BC  |.^ 75 D6           |\JNZ SHORT BFKEYGEN.00401194
    004011BE  |.  FF4D F4         |DEC DWORD PTR SS:[EBP-C]
    004011C1  |.^ 75 CC           \JNZ SHORT BFKEYGEN.0040118F

    这个循环用了同样的方法处理KEY_SBOX,不同的是第一次不是处理一个全0的64位信息,而是上一个循环对KEY_PBOX[17]和KEY_PBOX[28]的结果。

    004011C3  |.  59              POP ECX
    004011C4  |.  5A              POP EDX
    004011C5  |.  5E              POP ESI
    004011C6  |.  5F              POP EDI
    004011C7  |.  5B              POP EBX
    004011C8  |.  C9              LEAVE
    004011C9  \.  C2 0800         RETN 8

    那个BF_EN函数到底做了什么呢,现在不跟了,到下面过程2再来看吧!



    ★★★★★★★★★★★★过程2、信息加密★★★★★★★★★★★★

    此时,已经完成了KEY_PBOX[18]和对KEY_SBOX[4,256]的处理,开始对信息编码。所用的就是初始化过程中用到的BF_EN函数。

    被加密的64位信息被分成32位的两部分,XL和XR

    PUSH BFKEYGEN.004040CD                     ; /Arg2 = 004040CD    XR的地址
    PUSH BFKEYGEN.004040D1                     ; |Arg1 = 004040D1    XL的地址
    CALL BFKEYGEN.0040106C                     ; \BFKEYGEN.0040106C  BlowFish的核心函数BF_EN加密函数

    输出信息保存在[4040C5]和[4040D1]两个地址中。

    0040106C  /$  55              PUSH EBP
    0040106D  |.  8BEC            MOV EBP,ESP
    0040106F  |.  83C4 FC         ADD ESP,-4
    00401072  |.  53              PUSH EBX
    00401073  |.  57              PUSH EDI
    00401074  |.  56              PUSH ESI
    00401075  |.  52              PUSH EDX
    00401076  |.  51              PUSH ECX
    00401077  |.  8B45 08         MOV EAX,DWORD PTR SS:[EBP+8]               ;  取XL的地址
    0040107A  |.  8B4D 0C         MOV ECX,DWORD PTR SS:[EBP+C]               ;  取XR的地址
    0040107D  |.  8B00            MOV EAX,DWORD PTR DS:[EAX]                 ;  取XL
    0040107F  |.  8B31            MOV ESI,DWORD PTR DS:[ECX]                 ;  取XR
    00401081  |.  BF 3D304000     MOV EDI,BFKEYGEN.0040303D                  ;  取KEY_PBOX的地址
    00401086  |.  C745 FC 1000000>MOV DWORD PTR SS:[EBP-4],10                ;  循环次数置16
    0040108D  |.  8BDF            MOV EBX,EDI
    0040108F  |>  3303            /XOR EAX,DWORD PTR DS:[EBX]                ;  XL = XL ^ KEY_PBOX[ i]
    00401091  |.  8BD0            |MOV EDX,EAX                               ;  保存异或结果
    00401093  |.  50              |PUSH EAX
    00401094  |.  E8 67FFFFFF     |CALL BFKEYGEN.00401000                    ;  XL = F(XL),F( )另外一个函数
    00401099  |.  8B4D FC         |MOV ECX,DWORD PTR SS:[EBP-4]              ;  取循环次数
    0040109C  |.  33C6            |XOR EAX,ESI                               ;  XL = XL ^ XR
    0040109E  |.  83C3 04         |ADD EBX,4
    004010A1  |.  49              |DEC ECX                                   ;  循环次数减1
    004010A2  |.  8BF2            |MOV ESI,EDX                               ;  上面保存的异或结果赋给XR
    004010A4  |.  894D FC         |MOV DWORD PTR SS:[EBP-4],ECX              ;  保存循环次数
    004010A7  |.^ 75 E6           \JNZ SHORT BFKEYGEN.0040108F               ;  循环出口
    004010A9  |.  8B4F 40         MOV ECX,DWORD PTR DS:[EDI+40]              ;  取KEY_PBOX[17]
    004010AC  |.  8B57 44         MOV EDX,DWORD PTR DS:[EDI+44]              ;  取KEY_PBOX[18]
    004010AF  |.  33C8            XOR ECX,EAX                                ;  XL ^ KEY_PBOX[18]
    004010B1  |.  33D6            XOR EDX,ESI                                ;  XR ^ KEY_PBOX[17]
    004010B3  |.  8915 C9404000   MOV DWORD PTR DS:[4040C9],EDX              ;  输出XL
    004010B9  |.  890D C5404000   MOV DWORD PTR DS:[4040C5],ECX              ;  输出XR
    004010BF  |.  59              POP ECX
    004010C0  |.  5A              POP EDX
    004010C1  |.  5E              POP ESI
    004010C2  |.  5F              POP EDI
    004010C3  |.  5B              POP EBX
    004010C4  |.  C9              LEAVE
    004010C5  \.  C2 0800         RETN 8

    进入F( )函数分析,F( )是用它来处理XL的,进去看看:

    00401000  /$  55              PUSH EBP
    00401001  |.  8BEC            MOV EBP,ESP
    00401003  |.  53              PUSH EBX
    00401004  |.  57              PUSH EDI
    00401005  |.  56              PUSH ESI
    00401006  |.  52              PUSH EDX
    00401007  |.  51              PUSH ECX
    00401008  |.  8B4D 08         MOV ECX,DWORD PTR SS:[EBP+8]
    0040100B  |.  8AC1            MOV AL,CL
    0040100D  |.  25 FF000000     AND EAX,0FF
    00401012  |.  C1E9 08         SHR ECX,8
    00401015  |.  8BD0            MOV EDX,EAX
    00401017  |.  8AC1            MOV AL,CL
    00401019  |.  BF 3D304000     MOV EDI,BFKEYGEN.0040303D
    0040101E  |.  25 FF000000     AND EAX,0FF
    00401023  |.  C1E9 08         SHR ECX,8
    00401026  |.  8BF0            MOV ESI,EAX
    00401028  |.  8BC1            MOV EAX,ECX
    0040102A  |.  C1E8 08         SHR EAX,8
    0040102D  |.  25 FF000000     AND EAX,0FF                                ;  a
    00401032  |.  81E1 FF000000   AND ECX,0FF                                ;  b
    00401038  |.  81E6 FFFF0000   AND ESI,0FFFF                              ;  c
    0040103E  |.  81E2 FFFF0000   AND EDX,0FFFF                              ;  d

    上面代码就是把XL分成4个8位的a、b、c、d

    00401044  |.  8B4487 48       MOV EAX,DWORD PTR DS:[EDI+EAX*4+48]        ;  取出KEY_SBOX[1,a]
    00401048  |.  8B9C8F 48040000 MOV EBX,DWORD PTR DS:[EDI+ECX*4+448]       ;  取出KEY_SBOX[2,b]
    0040104F  |.  8B8CB7 48080000 MOV ECX,DWORD PTR DS:[EDI+ESI*4+848]       ;  取出KEY_SBOX[3,c]
    00401056  |.  03C3            ADD EAX,EBX                                ;  KEY_SBOX[1,a]+KEY_SBOX[2,b]
    00401058  |.  33C1            XOR EAX,ECX                                ;  结果 ^ KEY_SBOX[3,c]
    0040105A  |.  8B8C97 480C0000 MOV ECX,DWORD PTR DS:[EDI+EDX*4+C48]       ;  取出KEY_SBOX[4,d]
    00401061  |.  03C1            ADD EAX,ECX                                ;  结果 ^ KEY_SBOX[4,d]
    00401063  |.  59              POP ECX
    00401064  |.  5A              POP EDX
    00401065  |.  5E              POP ESI
    00401066  |.  5F              POP EDI
    00401067  |.  5B              POP EBX
    00401068  |.  C9              LEAVE
    00401069  \.  C2 0400         RETN 4

    a、b、c、d作为二维数组的下标到KEY_SBOX里取元素来运算

    就是:(((KEY_SBOX[1,a]+KEY_SBOX[2,b]) ^ KEY_SBOX[3,c] ) + KEY_SBOX[4,d]

    但是写注册机时要注意高位溢出的问题

    信息解密时密钥预处理的过程与加密时完全相同,信息解密的过程就是把信息加密过程的key_pbox逆序使用即可。

    ----------------------------------------------------------------------------------------------
    【破解心得】

    共享软件为了不让破解者找到KEY,常常把密钥的预处理过程放到程序的其他地方,只要找到SBOX盒子所在的地址(Peid的插件就具有这个功能),下内存断点,就能来到密钥预处理的地方,从而找到KEY。

    对于算法,我是外行,第一次接触密码学知识,理解还是很肤浅,写的也没有什么新的东西,只是把我得学习过程跟大家分享一下。现在越来越多的程序使用变形代码来阻止写算法注册机了,真希望自己能够有所进步。

    ----------------------------------------------------------------------------------------------
    【破解声明】   我是一只小菜鸟,偶得一点心得,愿与大家分享:)

    【版权声明】   本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
    ----------------------------------------------------------------------------------------------
                                                                         文章写于2005-8-24 18:42:39
    PYG19周年生日快乐!
    zhupf 该用户已被删除
    发表于 2005-9-14 19:00:38 | 显示全部楼层
    提示: 作者被禁止或删除 内容自动屏蔽
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2019-11-22 21:56
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2005-9-24 11:57:57 | 显示全部楼层
    学习学习   。
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2018-7-26 08:15
  • 签到天数: 7 天

    [LV.3]偶尔看看II

    发表于 2005-11-16 20:38:24 | 显示全部楼层
    密码学还要学习啊~~~
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    11 小时前
  • 签到天数: 1883 天

    [LV.Master]伴坛终老

    发表于 2007-9-9 07:49:05 | 显示全部楼层
    暂时看不懂
    Down下来,慢慢看
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-9-9 14:14:29 | 显示全部楼层
    强烈支持了,继续努力研究。。。
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2007-9-9 18:36:36 | 显示全部楼层
    提示: 作者被禁止或删除 内容自动屏蔽
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表