【文章标题】: GIFMovieGear4.2注册码算法分析+注册机
【文章作者】: VIDEN
【作者QQ号】: 38352959
【作者邮箱】: viden@live.cn
【操作系统】: Windows 7
【生产日期】: 20100712
【软件名称】: GIFMovieGear4.2
【软件介绍】: 一个gif格式图片制作软件
【加壳方式】: PECompact 2.x -> Jeremy Collake
【保护方式】: 注册码
【编写语言】: Microsoft Visual C++ 7.0
【使用工具】: OD+PEID+UNPECompact_2.x_by_mirz(脱壳机)
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!第一次分析程序注册码算法,写的第一个KeyGen。不足之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
GIFMovieGear4.2该程序原本带破解补丁,没注册机,心想原来只是爆破,从没分析过算法。心血来潮挑战一下。
PEID查壳PECompact 2.x -> Jeremy Collake,脱壳机搞定。脱壳后查壳Microsoft Visual C++ 7.0。
运行程序,找到注册位置输入姓名111111,注册码222222。提交后弹出出错信息。
OD载入,字符串参考,没找到出错信息。接着查找二进制字符串FF25,查看输入表函数。发现USER32.GetWindowTextA和USER32.GetDlgItemTextA,都给他硬件访问断点,概率大点。运行程序,找到注册位置填入假注册信息,提交,断在USER32.GetWindowTextA。这样另一个断点就没用了。
断在此处,F8向下运行
00433C1A . 50 PUSH EAX ; |hWnd = 00160554 (class='Edit',parent=001704F6)
00433C1B . FFD3 CALL EBX ; \GetWindowTextA
00433C1D . 6A 64 PUSH 64 ; /Count = 64 (100.)
00433C1F . 8D8424 C80000>LEA EAX,DWORD PTR SS:[ESP+C8] ; |
00433C26 . 50 PUSH EAX ; |Buffer
00433C27 . 68 50040000 PUSH 450 ; |/ControlID = 450 (1104.)
00433C2C . 57 PUSH EDI ; ||hWnd
00433C2D . FFD6 CALL ESI ; |\GetDlgItem
00433C2F . 50 PUSH EAX ; |hWnd
00433C30 . FFD3 CALL EBX ; \GetWindowTextA
00433C32 . 8D8C24 C40000>LEA ECX,DWORD PTR SS:[ESP+C4]
00433C39 . 51 PUSH ECX
00433C3A . 8D5424 64 LEA EDX,DWORD PTR SS:[ESP+64]
00433C3E . 52 PUSH EDX ;运行到此处,看堆栈出现假的注册信息
00433C3F . E8 FCFBFFFF CALL unpacked.00433840 ;开始验证,F7进去
到此处,下面这段是检验用户名前四个字符是否为"mg37",一般没人会乱猜一个注册码前四位是"mg37吧"?呵呵,直接跳走
00433840 /$ 53 PUSH EBX
00433841 |. 55 PUSH EBP
00433842 |. 8B6C24 10 MOV EBP,DWORD PTR SS:[ESP+10]
00433846 |. 807D 00 6D CMP BYTE PTR SS:[EBP],6D
0043384A |. 56 PUSH ESI
0043384B |. 57 PUSH EDI
0043384C |. 0F85 AD000000 JNZ unpacked.004338FF ;从这就跳走,继续往下
00433852 |. 807D 01 67 CMP BYTE PTR SS:[EBP+1],67
00433856 |. 0F85 A3000000 JNZ unpacked.004338FF
0043385C |. 807D 02 33 CMP BYTE PTR SS:[EBP+2],33
00433860 |. 0F85 99000000 JNZ unpacked.004338FF
00433866 |. 807D 03 37 CMP BYTE PTR SS:[EBP+3],37
0043386A |. 0F85 8F000000 JNZ unpacked.004338FF
跳到此处
004338FF |> 8B5C24 14 MOV EBX,DWORD PTR SS:[ESP+14]
00433903 |> 55 PUSH EBP
00433904 |. 53 PUSH EBX
00433905 |. E8 16FCFFFF CALL unpacked.00433520 ;F7进去
到此处
00433520 /$ 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4]
00433524 |. 8D9424 38FFFF>LEA EDX,DWORD PTR SS:[ESP-C8]
0043352B |. 81EC D8000000 SUB ESP,0D8
00433531 |. 2BD0 SUB EDX,EAX
00433533 |> 8A08 /MOV CL,BYTE PTR DS:[EAX]
00433535 |. 880C02 |MOV BYTE PTR DS:[EDX+EAX],CL
00433538 |. 40 |INC EAX
00433539 |. 84C9 |TEST CL,CL
0043353B |.^ 75 F6 \JNZ SHORT unpacked.00433533
0043353D |. 53 PUSH EBX
0043353E |. 55 PUSH EBP
0043353F |. 56 PUSH ESI
00433540 |. 57 PUSH EDI
00433541 |. 8D4424 20 LEA EAX,DWORD PTR SS:[ESP+20]
00433545 |. 50 PUSH EAX ; /StringOrChar
00433546 |. FF15 1CF34700 CALL DWORD PTR DS:[<&user32.CharUpperA>] ; \CharUpperA ;CharUpperA函数将用户名全部转换为大写
0043354C |. 8A4424 20 MOV AL,BYTE PTR SS:[ESP+20]
00433550 |. 84C0 TEST AL,AL
00433552 |. 8D7424 20 LEA ESI,DWORD PTR SS:[ESP+20]
00433556 |. 8D7C24 20 LEA EDI,DWORD PTR SS:[ESP+20]
0043355A |. 74 26 JE SHORT unpacked.00433582
0043355C |. 8D6424 00 LEA ESP,DWORD PTR SS:[ESP]
00433560 |> 0FBE0E /MOVSX ECX,BYTE PTR DS:[ESI]
00433563 |. 51 |PUSH ECX
00433564 |. 68 78F44800 |PUSH unpacked.0048F478 ; hkrwqv2958dwntqrgnscfsxazpyk ;这里是程序自带的一个字符串,先全部转换为大写,把这个字符串记为①,用它经过换算生成注册码的
00433569 |. E8 B2C00300 |CALL unpacked.0046F620 ;F7进去
0043356E |. 83C4 08 |ADD ESP,8
00433571 |. 85C0 |TEST EAX,EAX
00433573 |. 74 05 |JE SHORT unpacked.0043357A
00433575 |. 8A16 |MOV DL,BYTE PTR DS:[ESI]
00433577 |. 8817 |MOV BYTE PTR DS:[EDI],DL
00433579 |. 47 |INC EDI
0043357A |> 8A46 01 |MOV AL,BYTE PTR DS:[ESI+1]
0043357D |. 46 |INC ESI
0043357E |. 84C0 |TEST AL,AL
00433580 |.^ 75 DE \JNZ SHORT unpacked.00433560
进去后到这,这个CAll的调用目的是检查全部为大写的用户名的每个字符,是否包含在字符串①里面,若存在,返回EAX为该字符在字符串①中的地址,若不存在EAX置0
0046F620 |$ 33C0 XOR EAX,EAX
0046F622 |. 8A4424 08 MOV AL,BYTE PTR SS:[ESP+8]
0046F626 |. 53 PUSH EBX
0046F627 |. 8BD8 MOV EBX,EAX
0046F629 |. C1E0 08 SHL EAX,8
0046F62C |. 8B5424 08 MOV EDX,DWORD PTR SS:[ESP+8]
0046F630 |. F7C2 03000000 TEST EDX,3
0046F636 |. 74 15 JE SHORT unpacked.0046F64D
0046F638 |> 8A0A /MOV CL,BYTE PTR DS:[EDX]
0046F63A |. 83C2 01 |ADD EDX,1
0046F63D |. 38D9 |CMP CL,BL
0046F63F |.^ 74 CF |JE SHORT unpacked.0046F610
0046F641 |. 84C9 |TEST CL,CL
0046F643 |. 74 51 |JE SHORT unpacked.0046F696
0046F645 |. F7C2 03000000 |TEST EDX,3
0046F64B |.^ 75 EB \JNZ SHORT unpacked.0046F638
0046F64D |> 0BD8 OR EBX,EAX
0046F64F |. 57 PUSH EDI
0046F650 |. 8BC3 MOV EAX,EBX
0046F652 |. C1E3 10 SHL EBX,10
0046F655 |. 56 PUSH ESI
0046F656 |. 0BD8 OR EBX,EAX
0046F658 |> 8B0A /MOV ECX,DWORD PTR DS:[EDX] ;运行到这,看到EBX的值,就知道从这向上这段代码的作用了
0046F65A |. BF FFFEFE7E |MOV EDI,7EFEFEFF
0046F65F |. 8BC1 |MOV EAX,ECX
0046F661 |. 8BF7 |MOV ESI,EDI
0046F663 |. 33CB |XOR ECX,EBX
0046F665 |. 03F0 |ADD ESI,EAX
0046F667 |. 03F9 |ADD EDI,ECX
0046F669 |. 83F1 FF |XOR ECX,FFFFFFFF
0046F66C |. 83F0 FF |XOR EAX,FFFFFFFF
0046F66F |. 33CF |XOR ECX,EDI
0046F671 |. 33C6 |XOR EAX,ESI
0046F673 |. 83C2 04 |ADD EDX,4
0046F676 |. 81E1 00010181 |AND ECX,81010100
0046F67C |. 75 1C |JNZ SHORT unpacked.0046F69A
0046F67E |. 25 00010181 |AND EAX,81010100
0046F683 |.^ 74 D3 |JE SHORT unpacked.0046F658
0046F685 |. 25 00010101 |AND EAX,1010100
0046F68A |. 75 08 |JNZ SHORT unpacked.0046F694
0046F68C |. 81E6 00000080 |AND ESI,80000000
0046F692 |.^ 75 C4 \JNZ SHORT unpacked.0046F658
0046F694 |> 5E POP ESI
0046F695 |. 5F POP EDI
0046F696 |> 5B POP EBX
0046F697 |. 33C0 XOR EAX,EAX
0046F699 |. C3 RETN ;不存在时从这里返回,明显EAX被置0
0046F69A |> \8B42 FC MOV EAX,DWORD PTR DS:[EDX-4]
0046F69D |. 38D8 CMP AL,BL
0046F69F |. 74 36 JE SHORT unpacked.0046F6D7
0046F6A1 |. 84C0 TEST AL,AL
0046F6A3 |.^ 74 EF JE SHORT unpacked.0046F694
0046F6A5 |. 38DC CMP AH,BL
0046F6A7 |. 74 27 JE SHORT unpacked.0046F6D0
0046F6A9 |. 84E4 TEST AH,AH
0046F6AB |.^ 74 E7 JE SHORT unpacked.0046F694
0046F6AD |. C1E8 10 SHR EAX,10
0046F6B0 |. 38D8 CMP AL,BL
0046F6B2 |. 74 15 JE SHORT unpacked.0046F6C9
0046F6B4 |. 84C0 TEST AL,AL
0046F6B6 |.^ 74 DC JE SHORT unpacked.0046F694
0046F6B8 |. 38DC CMP AH,BL
0046F6BA |. 74 06 JE SHORT unpacked.0046F6C2
0046F6BC |. 84E4 TEST AH,AH
0046F6BE |.^ 74 D4 JE SHORT unpacked.0046F694
0046F6C0 |.^ EB 96 JMP SHORT unpacked.0046F658
0046F6C2 |> 5E POP ESI
0046F6C3 |. 5F POP EDI
0046F6C4 |. 8D42 FF LEA EAX,DWORD PTR DS:[EDX-1]
0046F6C7 |. 5B POP EBX
0046F6C8 |. C3 RETN ;第一个
0046F6C9 |> 8D42 FE LEA EAX,DWORD PTR DS:[EDX-2]
0046F6CC |. 5E POP ESI
0046F6CD |. 5F POP EDI
0046F6CE |. 5B POP EBX
0046F6CF |. C3 RETN ;第二个
0046F6D0 |> 8D42 FD LEA EAX,DWORD PTR DS:[EDX-3]
0046F6D3 |. 5E POP ESI
0046F6D4 |. 5F POP EDI
0046F6D5 |. 5B POP EBX
0046F6D6 |. C3 RETN ;第三个
0046F6D7 |> 8D42 FC LEA EAX,DWORD PTR DS:[EDX-4]
0046F6DA |. 5E POP ESI
0046F6DB |. 5F POP EDI
0046F6DC |. 5B POP EBX
0046F6DD \. C3 RETN ;第四个;若存在就从这4个RETN中返回,虽然有4个,但是目的是为了返回匹配字符在字符串①中的地址
返回后回到这里,看这个循环,目的是将用户名里在字符串①里存在的字符保存下来,组成一组新的字符串,这里记为②
00433560 |> /0FBE0E /MOVSX ECX,BYTE PTR DS:[ESI]
00433563 |. |51 |PUSH ECX
00433564 |. |68 78F44800 |PUSH unpacked.0048F478 ; hkrwqv2958dwntqrgnscfsxazpyk
00433569 |. |E8 B2C00300 |CALL unpacked.0046F620
0043356E |. |83C4 08 |ADD ESP,8 ;返回后回到这里
00433571 |. |85C0 |TEST EAX,EAX ;测试EAX的值,若为0则跳走,若不为0,则将存在的那个字符保存下来
00433573 |. |74 05 |JE SHORT unpacked.0043357A
00433575 |. |8A16 |MOV DL,BYTE PTR DS:[ESI]
00433577 |. |8817 |MOV BYTE PTR DS:[EDI],DL ;在这里把字符保存下来
00433579 |. |47 |INC EDI
0043357A |> |8A46 01 |MOV AL,BYTE PTR DS:[ESI+1]
0043357D |. |46 |INC ESI
0043357E |. |84C0 |TEST AL,AL
00433580 |.^\75 DE \JNZ SHORT unpacked.00433560 ;循环,直到用户名所有字符全部检查完毕
继续向下看
00433582 |> \8D4424 20 LEA EAX,DWORD PTR SS:[ESP+20]
00433586 |. C607 00 MOV BYTE PTR DS:[EDI],0 ;这里,是在新字符串②末尾添加一个00
00433589 |. 8D50 01 LEA EDX,DWORD PTR DS:[EAX+1]
0043358C |. 8D6424 00 LEA ESP,DWORD PTR SS:[ESP]
00433590 |> 8A08 /MOV CL,BYTE PTR DS:[EAX]
00433592 |. 40 |INC EAX
00433593 |. 84C9 |TEST CL,CL
00433595 |.^ 75 F9 \JNZ SHORT unpacked.00433590
00433597 |. 2BC2 SUB EAX,EDX ;上面的小循环到这里是算出新字符串②的个数
00433599 |. 83F8 18 CMP EAX,18
0043359C |. 7D 1E JGE SHORT unpacked.004335BC ;字符串②个数大于24就跳走,虽然跳走不会挂,但是一般输入的用户名都会比较短,不会弄个24位以上吧,呵呵,继续往下看
0043359E |. B9 18000000 MOV ECX,18
004335A3 |. 2BC8 SUB ECX,EAX ;这里24减去②的长度
004335A5 |. 8D7C04 20 LEA EDI,DWORD PTR SS:[ESP+EAX+20]
004335A9 |. 8BC1 MOV EAX,ECX
004335AB |. C1E9 02 SHR ECX,2 ;得到的差逻辑右移2位,可以认为得到的差去除以4,得到结果给ECX
004335AE |. BE 78F44800 MOV ESI,unpacked.0048F478 ; hkrwqv2958dwntqrgnscfsxazpyk
004335B3 |. F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] ;到这里,把这个字符串从左向右4个字符为一组,分成7组。取前ECX组字符,我们记做③吧,剩下的7-ECX组字符我们记为④。这里是把③接在了②的后面,保存下来。
004335B5 |. 8BC8 MOV ECX,EAX ;这里ECX就是24减去②的长度的结果
004335B7 |. 83E1 03 AND ECX,3 ;这里把ECX换算成二进制,取最低2位的值给ECX
004335BA |. F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ;到这里,取④字符串的前ECX个字符接在②③的后面。不知道我这样说大家觉得乱不乱。。。。这样就组成了一组新的字符串,我们记为⑤吧
004335BC |> B8 78F44800 MOV EAX,unpacked.0048F478 ; hkrwqv2958dwntqrgnscfsxazpyk
004335C1 |. C64424 39 00 MOV BYTE PTR SS:[ESP+39],0
004335C6 |. C68424 840000>MOV BYTE PTR SS:[ESP+84],0
004335CE |. 33ED XOR EBP,EBP ;注意此时的EBP为0,下面会用到
004335D0 |. 8D48 01 LEA ECX,DWORD PTR DS:[EAX+1]
004335D3 |> 8A10 /MOV DL,BYTE PTR DS:[EAX]
004335D5 |. 40 |INC EAX
004335D6 |. 84D2 |TEST DL,DL
004335D8 |.^ 75 F9 \JNZ SHORT unpacked.004335D3
004335DA |. 2BC1 SUB EAX,ECX ;这句加上上面的小循环是算字符串①的字符数
004335DC |. 894424 10 MOV DWORD PTR SS:[ESP+10],EAX
004335E0 |. B8 01000000 MOV EAX,1
004335E5 |. 2D 78F44800 SUB EAX,unpacked.0048F478 ; ASCII "HKRWQV2958DWNTQRGNSCFSXAZPYK" 这里用1减去字符串首的地址这里把结果记做a,下面用到
004335EA |. 894424 18 MOV DWORD PTR SS:[ESP+18],EAX ;保存起来
004335EE |. 33DB XOR EBX,EBX
004335F0 |. B8 78F44800 MOV EAX,unpacked.0048F478 ; hkrwqv2958dwntqrgnscfsxazpyk
004335F5 |. 48 DEC EAX ;字符串①首地址减去1,这里把结果记做b,下面用到
004335F6 |. 894424 14 MOV DWORD PTR SS:[ESP+14],EAX ;保存起来
004335FA |. 8D4424 20 LEA EAX,DWORD PTR SS:[ESP+20] ;取新字符串⑤的首地址给EAX
004335FE |. 48 DEC EAX ;也减去1
004335FF |. 8DBC24 840000>LEA EDI,DWORD PTR SS:[ESP+84]
00433606 |. 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX
0043360A |. EB 04 JMP SHORT unpacked.00433610 ;进下面这个循环,关键时候到了,这个循环是算注册码的地方
0043360C |> 8B4424 1C /MOV EAX,DWORD PTR SS:[ESP+1C]
00433610 |> 0FBE4C18 01 MOVSX ECX,BYTE PTR DS:[EAX+EBX+1] ;字符串⑤的一个字符给ECX
00433615 |. 8D73 01 |LEA ESI,DWORD PTR DS:[EBX+1]
00433618 |. 51 |PUSH ECX
00433619 |. 68 78F44800 |PUSH unpacked.0048F478 ; hkrwqv2958dwntqrgnscfsxazpyk
0043361E |. E8 FDBF0300 |CALL unpacked.0046F620 ;这里跟上面00433569地址的那个一样,自己向上看,不多解释了
00433623 |. 8B5424 20 |MOV EDX,DWORD PTR SS:[ESP+20] ;取a的值给EDX,a是什么向上看
00433627 |. 8BC8 |MOV ECX,EAX ;上面那个CALL返回的EAX给ECX
00433629 |. 03CA |ADD ECX,EDX ;实际结果是字符串①里,第ECX个字符与字符串⑤的那个字符匹配
0043362B |. 8D41 FF |LEA EAX,DWORD PTR DS:[ECX-1] ;ECX-1
0043362E |. 0FAFC1 |IMUL EAX,ECX ;ECX*(ECX-1)
00433631 |. 03C5 |ADD EAX,EBP ;ECX*(ECX-1)+EBP 上面提到初始EBP为0
00433633 |. 99 |CDQ ;EDX置0
00433634 |. F77C24 18 |IDIV DWORD PTR SS:[ESP+18] ;(ECX*(ECX-1)+EBP)/28,商给EAX,余数给EDX
00433638 |. 83C4 08 |ADD ESP,8
0043363B |. B9 06000000 |MOV ECX,6 ;ECX=6,目的是生成的注册码每6个之间用'-'符号隔开
00433640 |. 42 |INC EDX ;余数+1
00433641 |. 8BEA |MOV EBP,EDX ;余数+1给EBP
00433643 |. 8B5424 14 |MOV EDX,DWORD PTR SS:[ESP+14] ;取b给EDX,b是什么请向上看
00433647 |. 8A042A |MOV AL,BYTE PTR DS:[EDX+EBP] ;取字符串①中第EBP个字符作为注册码!!!!注册码出现!
0043364A |. 8807 |MOV BYTE PTR DS:[EDI],AL ;找了个地存起来了
0043364C |. 8BC6 |MOV EAX,ESI ;这里的ESI是来计数用的
0043364E |. 99 |CDQ
0043364F |. F7F9 |IDIV ECX
00433651 |. 47 |INC EDI
00433652 |. 85D2 |TEST EDX,EDX
00433654 |. 75 09 |JNZ SHORT unpacked.0043365F
00433656 |. 83FB 17 |CMP EBX,17
00433659 |. 7D 04 |JGE SHORT unpacked.0043365F
0043365B |. C607 2D |MOV BYTE PTR DS:[EDI],2D ;这里到上面是注册码每6个用'-'隔开
0043365E |. 47 |INC EDI
0043365F |> 8BDE |MOV EBX,ESI
00433661 |. 83FB 18 |CMP EBX,18
00433664 |.^ 7C A6 \JL SHORT unpacked.0043360C ;循环生成注册码。注册码为24个,6个为一组,共四组
00433666 |. 8B8424 F00000>MOV EAX,DWORD PTR SS:[ESP+F0] ;到这是取我们输入得注册码给EAX
0043366D |. C607 00 MOV BYTE PTR DS:[EDI],0
00433670 |. 8DB424 840000>LEA ESI,DWORD PTR SS:[ESP+84] ;取计算出的真实注册码给ESI,大家应该都想到了,下面就是比较了
00433677 |> 8A10 /MOV DL,BYTE PTR DS:[EAX] ; (初始 cpu 选择)
00433679 |. 8A1E |MOV BL,BYTE PTR DS:[ESI]
0043367B |. 8ACA |MOV CL,DL
0043367D |. 3AD3 |CMP DL,BL
0043367F |. 75 1E |JNZ SHORT unpacked.0043369F ;这里!可以将这里改为JMP 0043369B来实现爆破!!!
00433681 |. 84C9 |TEST CL,CL
00433683 |. 74 16 |JE SHORT unpacked.0043369B
00433685 |. 8A50 01 |MOV DL,BYTE PTR DS:[EAX+1]
00433688 |. 8A5E 01 |MOV BL,BYTE PTR DS:[ESI+1]
0043368B |. 8ACA |MOV CL,DL
0043368D |. 3AD3 |CMP DL,BL
0043368F |. 75 0E |JNZ SHORT unpacked.0043369F
00433691 |. 83C0 02 |ADD EAX,2
00433694 |. 83C6 02 |ADD ESI,2
00433697 |. 84C9 |TEST CL,CL
00433699 |.^ 75 DC \JNZ SHORT unpacked.00433677
0043369B |> 33C0 XOR EAX,EAX ;这里如果注册码正确,则EAX置0,然后直接跳下去
0043369D |. EB 05 JMP SHORT unpacked.004336A4
0043369F |> 1BC0 SBB EAX,EAX
004336A1 |. 83D8 FF SBB EAX,-1 ;这里注册码不正确,EAX置1,然后测试EAX的值
004336A4 |> 85C0 TEST EAX,EAX
004336A6 |. 5F POP EDI
004336A7 |. 5E POP ESI
004336A8 |. 5D POP EBP
004336A9 |. 5B POP EBX
004336AA |. 75 0C JNZ SHORT unpacked.004336B8 ;这个程序是以EAX的值来判断是否正确,这里正确EAX为1,错误EAX为0。
004336AC |. B8 01000000 MOV EAX,1
004336B1 |. 81C4 D8000000 ADD ESP,0D8
004336B7 |. C3 RETN
004336B8 |> 33C0 XOR EAX,EAX
004336BA |. 81C4 D8000000 ADD ESP,0D8
004336C0 \. C3 RETN ;分析还没结束,F8单步向下运行
返回到此处
00433C44 . 83C4 08 ADD ESP,8
00433C47 . 85C0 TEST EAX,EAX ;这里测试EAX的值
00433C49 . 0F84 B6000000 JE unpacked.00433D05 ;当注册码正确,EAX为1时,下面就将注册信息写入注册表,否则跳走出错
00433C4F . 8D4424 10 LEA EAX,DWORD PTR SS:[ESP+10]
00433C53 . 50 PUSH EAX ; /pDisposition
00433C54 . 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10] ; |
00433C58 . 51 PUSH ECX ; |pHandle
00433C59 . 6A 00 PUSH 0 ; |pSecurity = NULL
00433C5B . 68 3F000F00 PUSH 0F003F ; |Access = KEY_ALL_ACCESS
00433C60 . 6A 00 PUSH 0 ; |Options = REG_OPTION_NON_VOLATILE
00433C62 . 68 85F64700 PUSH unpacked.0047F685 ; |Class = ""
00433C67 . 6A 00 PUSH 0 ; |Reserved = 0
00433C69 . 68 84E44800 PUSH unpacked.0048E484 ; |software\gamani\gifmoviegear\2.0
00433C6E . 68 02000080 PUSH 80000002 ; |hKey = HKEY_LOCAL_MACHINE
00433C73 . FF15 0CF04700 CALL DWORD PTR DS:[<&ADVAPI32.RegCreateKeyExA>; \RegCreateKeyExA
00433C79 . 8D4424 60 LEA EAX,DWORD PTR SS:[ESP+60]
00433C7D . 8D50 01 LEA EDX,DWORD PTR DS:[EAX+1]
00433C80 > 8A08 MOV CL,BYTE PTR DS:[EAX]
00433C82 . 40 INC EAX
00433C83 . 84C9 TEST CL,CL
00433C85 .^ 75 F9 JNZ SHORT unpacked.00433C80
00433C87 . 8B35 00F04700 MOV ESI,DWORD PTR DS:[<&ADVAPI32.RegSetValueE>; ADVAPI32.RegSetValueExA
00433C8D . 2BC2 SUB EAX,EDX
00433C8F . 40 INC EAX
00433C90 . 50 PUSH EAX ; /BufSize
00433C91 . 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] ; |
00433C95 . 8D5424 64 LEA EDX,DWORD PTR SS:[ESP+64] ; |
00433C99 . 52 PUSH EDX ; |Buffer
00433C9A . 6A 01 PUSH 1 ; |ValueType = REG_SZ
00433C9C . 6A 00 PUSH 0 ; |Reserved = 0
00433C9E . 68 C8F34800 PUSH unpacked.0048F3C8 ; |regname3
00433CA3 . 50 PUSH EAX ; |hKey
00433CA4 . FFD6 CALL ESI ; \RegSetValueExA
00433CA6 . 8D8424 C40000>LEA EAX,DWORD PTR SS:[ESP+C4]
00433CAD . 8D48 01 LEA ECX,DWORD PTR DS:[EAX+1]
00433CB0 > 8A10 MOV DL,BYTE PTR DS:[EAX]
00433CB2 . 40 INC EAX
00433CB3 . 84D2 TEST DL,DL
00433CB5 .^ 75 F9 JNZ SHORT unpacked.00433CB0
00433CB7 . 8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C]
00433CBB . 2BC1 SUB EAX,ECX
00433CBD . 40 INC EAX
00433CBE . 50 PUSH EAX
00433CBF . 8D8C24 C80000>LEA ECX,DWORD PTR SS:[ESP+C8]
00433CC6 . 51 PUSH ECX
00433CC7 . 6A 01 PUSH 1
00433CC9 . 6A 00 PUSH 0
00433CCB . 68 D4F34800 PUSH unpacked.0048F3D4 ; regcode3
00433CD0 . 52 PUSH EDX
00433CD1 . FFD6 CALL ESI
00433CD3 . 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]
00433CD7 . 50 PUSH EAX ; /hKey
00433CD8 . FF15 18F04700 CALL DWORD PTR DS:[<&ADVAPI32.RegCloseKey>] ; \RegCloseKey
00433CDE . 68 E0F34800 PUSH unpacked.0048F3E0 ; /software\loani\mg4
00433CE3 . 68 02000080 PUSH 80000002 ; |hKey = HKEY_LOCAL_MACHINE
00433CE8 . FF15 14F04700 CALL DWORD PTR DS:[<&ADVAPI32.RegDeleteKeyA>] ; \RegDeleteKeyA
00433CEE . 6A 01 PUSH 1 ; /Result = 1
00433CF0 . 57 PUSH EDI ; |hWnd
00433CF1 . FF15 A4F34700 CALL DWORD PTR DS:[<&user32.EndDialog>] ; \EndDialog
00433CF7 . 5F POP EDI
00433CF8 . 5E POP ESI
00433CF9 . 33C0 XOR EAX,EAX
00433CFB . 5B POP EBX
00433CFC . 81C4 1C010000 ADD ESP,11C
00433D02 . C2 1000 RETN 10
程序开始时也会读取注册表进行验证。
至此注册码分析完毕。第一次分析,不知道大家看着乱不乱。。。。呵呵,让大家见笑了。
总结一下算法过程:
主要字符串"HKRWQV2958DWNTQRGNSCFSXAZPYK",记为①。
1.先将用户名转换为大写。
2.检验用户名的每个字符在字符串"HKRWQV2958DWNTQRGNSCFSXAZPYK"里是否存在,并把存在的保存下来。记为②。
3.(24-②的长度)/4=C,把字符串"HKRWQV2958DWNTQRGNSCFSXAZPYK"每4个分为一组,共7组。取前C组字符,记为③。剩下的7-C组记为④。把③接在②后面。
4.24-②的长度,转换为二进制,取最低2位的值N,取④前N个字符,接在②③后面,组成一组新的字符串⑤。
5.初始EBP=0,用⑤每个字符与字符串"HKRWQV2958DWNTQRGNSCFSXAZPYK"每个比较,设为第M个匹配。EBP=(M*(M-1)+EBP)/28+1。
6.找出字符串"HKRWQV2958DWNTQRGNSCFSXAZPYK"第EBP个字符即为注册码。每得到6个字符用'-'隔开。重复5,6步。
另外贴上第一个注册机代码,VB写的,毕竟学的还不是很专业,不足之处敬请诸位大侠赐教!
2个文本框,(t1,t2),一个按钮(默认),已测试可以正常使用。
Private Sub Command1_Click()
t2.Text = ""
Dim s As String
Dim c(77) As String
Dim i As Integer
Dim j As Integer
Dim t As Integer
Dim p As Integer
Dim temp As Integer
Dim r(26) As String
s = "HKRWQV2958DWNTQRGNSCFSXAZPYK"
t = 0
'If Len(t1.Text) > 23 Then
'MsgBox "姓名要小于24位"
't1.SetFocus
'Command1.Value = False
'End If
If Len(t1.Text) = 0 Then
MsgBox "姓名不能为空"
t1.SetFocus
Else
For i = 0 To Len(t1.Text) - 1
c(i) = Mid(t1.Text, i + 1, 1)
If Asc(c(i)) > 96 And Asc(c(i)) < 123 Then
c(i) = Chr(Asc(c(i)) - 32)
End If
Next i
For i = 0 To Len(t1.Text) - 1
For j = 0 To 27
If Asc(c(i)) = Asc(Mid(s, j + 1, 1)) Then
c(t) = c(i)
t = t + 1
GoTo nn:
End If
Next j
nn:
Next i
temp = t
For p = 0 To Int((24 - t) / 4) - 1
j = 4 * p + 1
For i = 0 To 3
c(t) = Mid(s, j + i, 1)
t = t + 1
Next i
Next p
For i = 0 To (24 - temp) And &H3 - 1
c(t) = Mid(s, j + 4 + i, 1)
t = t + 1
Next i
temp = 0
For i = 0 To 23
For j = 0 To 27
If Asc(c(i)) = Asc(Mid(s, j + 1, 1)) Then
temp = ((j + 1) * j + temp) Mod 28 + 1
r(i) = Mid(s, temp, 1)
GoTo nnn:
End If
Next j
nnn:
Next i
For i = 0 To 23
t2.Text = t2.Text + r(i)
If (i + 1) Mod 6 = 0 And i <> 23 Then
t2.Text = t2.Text + "-"
End If
Next i
End If
End Sub
Private Sub Form_Load()
On Error Resume Next
End Sub
[课程]Android-CTF解题方法汇总!