• 标 题:键盘记录2003算法分析  
  • 作 者:FTBirthday
  • 时 间:2003/08/17 04:23pm
  • 链 接:http://bbs.pediy.com

键盘记录2003算法分析
目标:键盘记录2003
作者:LFTBirthday
类型:明码比较,无壳。
工具:olly

0041F87B   E8 D4DF0100      CALL <JMP.&MFC42.#3098>                      ; 读入第一个输入框的姓名MFC42.#3098
0041F880   80BD 68FFFFFF 00 CMP BYTE PTR SS:[EBP-98],0                   ; [EBP-98]处存放FTBirthday,判断是否为空
0041F887   75 18            JNZ SHORT FTBirthd.0041F8A1                  ; 不为空则继续ORT FT
0041F889   6A 40            PUSH 40
0041F88B   68 0CEE4000      PUSH FTBirthd.0040EE0C                       ; ASCII "Attention!"
0041F890   68 F4ED4000      PUSH FTBirthd.0040EDF4                       ; ASCII "Please enter your name!"
0041F895   8BCF             MOV ECX,EDI
0041F897   E8 BEDF0100      CALL <JMP.&MFC42.#4224>
0041F89C   E9 FA000000      JMP FTBirthd.0041F99B
0041F8A1   56               PUSH ESI                                     ; ESI入栈ES
0041F8A2   6A 0A            PUSH 0A                                      ; 0A入栈 0
0041F8A4   5E               POP ESI                                      ; OA给ESI,ESI=0000000A
0041F8A5   8D45 E8          LEA EAX,DWORD PTR SS:[EBP-18]                ; 把[EBP-18]=0012E508的有效值(=内存地址)给EAX
0041F8A8   56               PUSH ESI
0041F8A9   50               PUSH EAX
0041F8AA   68 DAD60000      PUSH 0D6DA
0041F8AF   8BCF             MOV ECX,EDI
0041F8B1   E8 9EDF0100      CALL <JMP.&MFC42.#3098>                      ; 读入注册码第一部分,EAX为位数,12E508处存放注册码第一部分四位
0041F8B6   8D45 D0          LEA EAX,DWORD PTR SS:[EBP-30]                ; 把[EBP-30]=0012E4F0的有效值(=内存地址)给EAX
0041F8B9   56               PUSH ESI
0041F8BA   50               PUSH EAX
0041F8BB   68 DBD60000      PUSH 0D6DB
0041F8C0   8BCF             MOV ECX,EDI
0041F8C2   E8 8DDF0100      CALL <JMP.&MFC42.#3098>                      ; 读入注册码第二部分,EAX为位数,12E4F0处存放注册码第二部分四位
0041F8C7   8D45 DC          LEA EAX,DWORD PTR SS:[EBP-24]                ; 把[EBP-24]=0012E4FC的有效值(=内存地址)给EAX
0041F8CA   56               PUSH ESI
0041F8CB   50               PUSH EAX
0041F8CC   68 DCD60000      PUSH 0D6DC
0041F8D1   8BCF             MOV ECX,EDI
0041F8D3   E8 7CDF0100      CALL <JMP.&MFC42.#3098>                      ; 读入注册码第三部分,EAX为位数,0012E4FC处存放注册码第三部分四位
0041F8D8   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]                 ; 把[EBP-C]=0012E514的有效值(=内存地址)给EAX
0041F8DB   56               PUSH ESI
0041F8DC   50               PUSH EAX
0041F8DD   68 DDD60000      PUSH 0D6DD
0041F8E2   8BCF             MOV ECX,EDI
0041F8E4   E8 6BDF0100      CALL <JMP.&MFC42.#3098>                      ; 读入注册码第四部分,EAX为位数,12E514处存放注册码第四部分四位
0041F8E9   8D45 E8          LEA EAX,DWORD PTR SS:[EBP-18]                ; EAX 0012E508 ASCII "1111"
0041F8EC   50               PUSH EAX
0041F8ED   8D45 9C          LEA EAX,DWORD PTR SS:[EBP-64]                ; EAX 0012E4BC
0041F8F0   50               PUSH EAX
0041F8F1   FF15 40114000    CALL DWORD PTR DS:[<&KERNEL32.lstrcpyA>]     ; kernel32.lstrcpyA
0041F8F7   8B35 48114000    MOV ESI,DWORD PTR DS:[<&KERNEL32.lstrcatA>]  ; kernel32.lstrcatA
0041F8FD   8D45 D0          LEA EAX,DWORD PTR SS:[EBP-30]                ; EAX 0012E4F0 ASCII "2222"
0041F900   50               PUSH EAX
0041F901   8D45 9C          LEA EAX,DWORD PTR SS:[EBP-64]                ; EAX 0012E4BC ASCII "1111"
0041F904   50               PUSH EAX
0041F905   FFD6             CALL ESI                                     ; EAX 0012E4BC ASCII "11112222"
0041F907   8D45 DC          LEA EAX,DWORD PTR SS:[EBP-24]                ; EAX 0012E4FC ASCII "3333"
0041F90A   50               PUSH EAX
0041F90B   8D45 9C          LEA EAX,DWORD PTR SS:[EBP-64]                ; EAX 0012E4BC ASCII "11112222"
0041F90E   50               PUSH EAX
0041F90F   FFD6             CALL ESI                                     ; EAX 0012E4BC ASCII "111122223333"
0041F911   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]                 ; EAX 0012E514 ASCII "4444"
0041F914   50               PUSH EAX
0041F915   8D45 9C          LEA EAX,DWORD PTR SS:[EBP-64]                ; EAX 0012E4BC ASCII "1111222233334444"
0041F918   50               PUSH EAX
0041F919   FFD6             CALL ESI                                     ; EAX 0012E4BC ASCII "1111222233334444"
0041F91B   8D85 34FFFFFF    LEA EAX,DWORD PTR SS:[EBP-CC]                ; EAX 0012E454
0041F921   50               PUSH EAX
0041F922   8D85 68FFFFFF    LEA EAX,DWORD PTR SS:[EBP-98]                ; EAX 0012E488 ASCII "FTBirthday"
0041F928   68 00434000      PUSH FTBirthd.00404300                       ; 参数1 ASCII "_r <@~=nj/2[l5,^"
0041F92D   50               PUSH EAX                                     ; 参数2,用户名X
0041F92E   E8 61FEFFFF      CALL FTBirthd.0041F794                       ; 关键CALL,EAX 0012E454 ASCII "ANXKAKKKLLQPVRTR"
0041F933   83C4 0C          ADD ESP,0C
0041F936   8D45 9C          LEA EAX,DWORD PTR SS:[EBP-64]                ; EAX 0012E4BC ASCII "1111222233334444"
0041F939   50               PUSH EAX
0041F93A   8D85 34FFFFFF    LEA EAX,DWORD PTR SS:[EBP-CC]                ; EAX 0012E454 ASCII "ANXKAKKKLLQPVRTR"
0041F940   50               PUSH EAX
0041F941   FF15 20114000    CALL DWORD PTR DS:[<&KERNEL32.lstrcmpiA>]    ; kernel32.lstrcmpiA
0041F947   5E               POP ESI
0041F948   85C0             TEST EAX,EAX                                 ; 将由用户名处理得到的注册码和输入的注册码比较
0041F94A   6A 40            PUSH 40
0041F94C   75 31            JNZ SHORT FTBirthd.0041F97F
0041F94E   68 E4ED4000      PUSH FTBirthd.0040EDE4                       ; ASCII "Registration"
0041F953   68 A0ED4000      PUSH FTBirthd.0040EDA0                       ; ASCII "Registration succeeded. Thank you for choosing Perfect Keylogger!"
0041F958   8BCF             MOV ECX,EDI
0041F95A   E8 FBDE0100      CALL <JMP.&MFC42.#4224>
0041F95F   8D85 68FFFFFF    LEA EAX,DWORD PTR SS:[EBP-98]
0041F965   8D4F 64          LEA ECX,DWORD PTR DS:[EDI+64]
0041F968   50               PUSH EAX
0041F969   E8 24DA0100      CALL <JMP.&MFC42.#860>
0041F96E   8D45 9C          LEA EAX,DWORD PTR SS:[EBP-64]
0041F971   8D4F 60          LEA ECX,DWORD PTR DS:[EDI+60]
0041F974   50               PUSH EAX
0041F975   E8 18DA0100      CALL <JMP.&MFC42.#860>
0041F97A   6A 01            PUSH 1
0041F97C   58               POP EAX
0041F97D   EB 1E            JMP SHORT FTBirthd.0041F99D
0041F97F   68 8CED4000      PUSH FTBirthd.0040ED8C                       ; ASCII "Registration error"
0041F984   68 38ED4000      PUSH FTBirthd.0040ED38                       ; ASCII "Registration code or user name is invalid. Please check all fields and try again!"
0041F989   8BCF             MOV ECX,EDI
0041F98B   E8 CADE0100      CALL <JMP.&MFC42.#4224>
0041F990   68 2C010000      PUSH 12C
0041F995   FF15 38114000    CALL DWORD PTR DS:[<&KERNEL32.Sleep>]        ; kernel32.Sleep
0041F99B   33C0             XOR EAX,EAX
0041F99D   5F               POP EDI
0041F99E   C9               LEAVE
0041F99F   C3               RETN

进入关键call看看
0041F795   8BEC             MOV EBP,ESP
0041F797   51               PUSH ECX
0041F798   51               PUSH ECX
0041F799   53               PUSH EBX
0041F79A   56               PUSH ESI
0041F79B   FF75 0C          PUSH DWORD PTR SS:[EBP+C]
0041F79E   8B35 B4104000    MOV ESI,DWORD PTR DS:[<&KERNEL32>; kernel32.lstrlenA
0041F7A4   FFD6             CALL ESI                         ; EAX 10注册码长度,EDX "_r <@~=nj/2[l5,^"
0041F7A6   FF75 08          PUSH DWORD PTR SS:[EBP+8]
0041F7A9   8BD8             MOV EBX,EAX                      ; EBX=10
0041F7AB   895D FC          MOV DWORD PTR SS:[EBP-4],EBX
0041F7AE   FFD6             CALL ESI                         ; EAX A用户名长度,EDX "FTBirthday"
0041F7B0   8BF0             MOV ESI,EAX                      ; ESI=A
0041F7B2   85F6             TEST ESI,ESI                     ; 判断用户名是否为空ESI
0041F7B4   8975 F8          MOV DWORD PTR SS:[EBP-8],ESI     ; [EBP-8]=0012E430=0A 00 00 00
0041F7B7   75 08            JNZ SHORT FTBirthd.0041F7C1      ; 不为零则跳,为空OVER
0041F7B9   8B45 10          MOV EAX,DWORD PTR SS:[EBP+10]
0041F7BC   8020 00          AND BYTE PTR DS:[EAX],0
0041F7BF   EB 4E            JMP SHORT FTBirthd.0041F80F
0041F7C1   57               PUSH EDI                         ; 一切正常,就到这里
0041F7C2   8B7D 10          MOV EDI,DWORD PTR SS:[EBP+10]
0041F7C5   FF75 0C          PUSH DWORD PTR SS:[EBP+C]
0041F7C8   57               PUSH EDI
0041F7C9   FF15 40114000    CALL DWORD PTR DS:[<&KERNEL32.ls>; 把"_r <@~=nj/2[l5,^"复制到EAX
0041F7CF   3BF3             CMP ESI,EBX                      ; 判断用户名长度是否大于注册码
0041F7D1   8975 0C          MOV DWORD PTR SS:[EBP+C],ESI     ; [EBP+C]=0A
0041F7D4   7F 03            JG SHORT FTBirthd.0041F7D9       ; 大于则跳HORT
0041F7D6   895D 0C          MOV DWORD PTR SS:[EBP+C],EBX     ; [EBP+C]=10
0041F7D9   33F6             XOR ESI,ESI                      ; ESI清零
0041F7DB   3975 0C          CMP DWORD PTR SS:[EBP+C],ESI     ; 判断有没有输入注册码
0041F7DE   7E 2C            JLE SHORT FTBirthd.0041F80C
0041F7E0   8BC6             MOV EAX,ESI                      ; 算法循环开始,EAX初值为0
0041F7E2   6A 19            PUSH 19
0041F7E4   99               CDQ                              ; EDX置零
0041F7E5   F77D FC          IDIV DWORD PTR SS:[EBP-4]        ; EAX idiv 注册码长度(EBP-4=10),商放入EAX,余数放入EDX
0041F7E8   8BC6             MOV EAX,ESI
0041F7EA   5B               POP EBX
0041F7EB   8D0C3A           LEA ECX,DWORD PTR DS:[EDX+EDI]   ; 字符串第[余数+1]位开始给ECX
0041F7EE   99               CDQ                              ; EDX置零
0041F7EF   F77D F8          IDIV DWORD PTR SS:[EBP-8]        ; EAX idiv 用户名长度(EBP-8=A),商放入EAX,余数放入EDX
0041F7F2   8B45 08          MOV EAX,DWORD PTR SS:[EBP+8]     ; "FTBirthday"给EAXR
0041F7F5   0FB60402         MOVZX EAX,BYTE PTR DS:[EDX+EAX]  ; 取用户名的第[余数+1]位
0041F7F9   0FB611           MOVZX EDX,BYTE PTR DS:[ECX]      ; 取ECX处字符串的第一位
0041F7FC   33C2             XOR EAX,EDX                      ; 异或,结果放入EAX
0041F7FE   99               CDQ                              ; EDX置零
0041F7FF   F7FB             IDIV EBX                         ; 异或结果idiv19,商放入EAX,余数放入EDX
0041F801   80C2 41          ADD DL,41                        ; 余数+41
0041F804   46               INC ESI                          ; 循环指针加1
0041F805   3B75 0C          CMP ESI,DWORD PTR SS:[EBP+C]     ; 比较循环是否结束,[EBP+C]=0012E444="10 00 00 00"
0041F808   8811             MOV BYTE PTR DS:[ECX],DL         ; DL即为注册码的下一位
0041F80A  ^7C D4            JL SHORT FTBirthd.0041F7E0       ; 小于则跳回继续
0041F80C   8BC7             MOV EAX,EDI                      ; 结束后把最终结果放入EAX
0041F80E   5F               POP EDI
0041F80F   5E               POP ESI
0041F810   5B               POP EBX
0041F811   C9               LEAVE
0041F812   C3               RETN

模拟算法验证

用户名"FTBirthday"       即"46 54 42 69 72 74 68 64 61 79" =A[i]
字符串"_r <@~=nj/2[l5,^" 即"5F 72 20 3C 40 7E 3D 6E 6A 2F 32 5B 31 35 2C 5E" =B[i]

初始ESI=0 EAX=0
注册码第一位={A[0 idiv A的余数] xor B[0 idiv 10的余数]}idiv 19的余数+41
           ={A[0] xor B[0]}idiv 19的余数+41
           ={46 xor 5F}idiv 19的余数+41
           =19 idiv 19的余数+41=0+41=41="A"

注册码第二位={A[1 idiv A的余数] xor B[1 idiv 10的余数]}idiv 19的余数+41
           ={A[1] xor B[1]}idiv 19的余数+41
           ={54 xor 72}idiv 19的余数+41
           =26 idiv 19的余数+41=D+41=4E="N"

注册码第三位={A[2 idiv A的余数] xor B[2 idiv 10的余数]}idiv 19的余数+41
           ={A[2] xor B[2]}idiv 19的余数+41
           ={42 xor 20}idiv 19的余数+41
           =62 idiv 19的余数+41=17+41=58="X"

注册码第四位={A[3 idiv A的余数] xor B[3 idiv 10的余数]}idiv 19的余数+41
           ={A[3] xor B[3]}idiv 19的余数+41
           ={69 xor 3C}idiv 19的余数+41
           =55 idiv 19的余数+41=A+41=4B="K"

………………

注册码第十一位={A[A idiv A的余数] xor B[A idiv 10的余数]}idiv 19的余数+41
           ={A[0] xor B[A]}idiv 19的余数+41
           ={46 xor 32}idiv 19的余数+41
           =74 idiv 19的余数+41=10+41=51="Q"

………………

注册码第十六位={A[F idiv A的余数] xor B[F idiv 10的余数]}idiv 19的余数+41
             ={A[5] xor B[F]}idiv 19的余数+41
             ={74 xor 5E}idiv 19的余数+41
             =2A idiv 19的余数+41=11+41=52="R"

所以示例注册码为
用户名:"FTBirthday"
注册码:"ANXK-AKKK-LLQP-VRTR"