010editor算法分析
本帖最后由 溯__ 于 2018-1-26 21:11 编辑1.定位到注册算法入口
跟着序号①②③④看:
00DD57DE .PUSH 0x9
00DD57E0 .CALL 010Edito.0040A82B
00DD57E5 .MOV ECX,DWORD PTR DS:
00DD57EB .MOV EBX,EAX //ebx接收函数0040A82B的返回值
00DD57ED .PUSH 0x4389
00DD57F2 .PUSH 0x9
00DD57F4 .CALL 010Edito.00409CA0// ④所以此时查看函数00409CA0,这个函数内部jmp到013BE220
00DD57F9 .MOV ECX,DWORD PTR DS:
00DD57FF .MOV EDI,EAX//edi接收函数00409CA0返回值③
00DD5801 .CMP EBX,0xE7
00DD5807 .JE 010Edito.00DD5900 //ebx是函数0040A82B的返回值,默认情况是0xE7 ,所以此处会跳转
00DD580D .CMP DWORD PTR DS:,0x0
00DD5811 .JE 010Edito.00DD5900
..........................................
00DD5900 >CMP EDI,0xDB // 比较edi和0xDB的值②
00DD5906 JNZ 010Edito.00DD5A38// 此处不能跳转,EDI = 0xDB,edi是函数00409CA0的返回值..........................................其间无长跳转
00DD599F .CALL DWORD PTR DS:[<&Qt5Core.??YQS>;Qt5Core.?append@QString@@QAEAAV1@PBD@Z
00DD59A5 >PUSH 010Edito.0231D3A4 ;ASCII " Thank you for purchasing 010 Editor!"①
00DD59AA .LEA ECX,DWORD PTR SS:
00DD59AD .CALL DWORD PTR DS:[<&Qt5Core.??YQS>;Qt5Core.?append@QString@@QAEAAV1@PBD@Z
接下来:
定位到013BE220,发现返回0xDB的在Case 2D of switch 013BE243,所以需要函数0040A82B返回0x2D,
查看函数0040A82B,这个函数内部jmp到013BD900,接着查看地址013BD900处
地址013BD900也就是注册验证的核心地方了,可以在里面直接返回0x2D爆破,当然这里分析一下其算法
013BE220 PUSH EBP
013BE221 MOV EBP,ESP
013BE223 PUSH ESI
013BE224 MOV ESI,ECX
013BE226 CMP DWORD PTR DS:,0x0
013BE22A|.JE SHORT 010Edito.013BE236
013BE22C|.MOV EAX,0x113
013BE231|.POP ESI
013BE232|.POP EBP
013BE233|.RETN 0x8
013BE236|>PUSH EDI
013BE237|.PUSH
013BE23A|.MOV EDI,
013BE23D|.PUSH EDI
013BE23E|.CALL 010Edito.0040A82B
013BE243|.CMP EAX,0x2D ;Switch (cases 2D..E7)
.....................................
013BE2EF|>POP EDI ;Case 2D of switch 013BE243
013BE2F0|.MOV EAX,0xDB
013BE2F5|.POP ESI
013BE2F6|.POP EBP
013BE2F7\.RETN 0x8
这里先写明013BD900(也就是函数0040A82B)的参数情况
参数一:0x9
参数二: 0x4389
2.“处理用户名函数”之前对注册号的判断
函数中在013BD99D之前是获取注册码和一些检测工作
013BD96D MOV ECX,EDI
013BD96F PUSH EAX ;局部变量地址
013BD970 CALL 010Edito.00409B74 ;获取注册码
下面是注册码和局部变量的对应关系
注册码KEY[]
12 3456 7887 6543210011
0123 45 6 7 8 9
0019CFF890 FA 01 6C E0 4E 2C 03 01 00 00 00 12 34 56 78
0019D00887 65 43 21 00 11 6D 6B 08 06 86 05 C6 4C 89 6B
0019D01800 00 00 00 6C D0 19 00 89 5A 88 01 FF FF FF FF
ebp-> 0019D02878 D0 19 00
ebp-0x24KEY
ebp-0x23KEY
ebp-0x22KEY
ebp-0x21KEY
ebp-0x20KEY
ebp-0x1FKEY
ebp-0x1EKEY
ebp-0x1DKEY
ebp-0x1CKEY
ebp-0x1BKEY
接着会判断KEY:
KEY == 0x9C
013BD99D MOV BL,BYTE PTR SS: ;BL = KEY
013BD9A0 MOV BH,BYTE PTR SS: ;BH = KEY
013BD9A3 CMP BL,0x9C ;判断KEY 是否为0x9C
013BD9A6 JNZ SHORT 010Edito.013BDA18
013BD9A8 MOV AL,BYTE PTR SS: ;情况1:KEY = 9C
013BD9AB XOR AL,BYTE PTR SS: ;al = KEY xor KEY
013BD9AE MOV BYTE PTR SS:,AL ;BYTE ptr = KEY xor KEY
013BD9B1 MOV AL,BYTE PTR SS:
013BD9B4 XOR AL,BYTE PTR SS: ; al = KEY xor KEY
013BD9B7 PUSH DWORD PTR SS: ; push KEY xor KEY作为0040764E的参数
013BD9BA MOVZX ECX,AL
013BD9BD MOV EAX,0x100
013BD9C2 IMUL CX,AX ; cx = (KEY xor KEY)*0x100
013BD9C6 MOV AL,BYTE PTR SS: ; al = KEY
013BD9C9 XOR AL,BH ; al = KEY xor KEY
013BD9CB MOVZX EAX,AL
013BD9CE ADD CX,AX ; cx = ((KEY xor KEY)*0x100) + (KEY xor KEY)
013BD9D1 MOVZX ESI,CX ; esi = ((KEY xor KEY)*0x100) + (KEY xor KEY)
013BD9D4 CALL 010Edito.0040764E
013BCDF0/>PUSH EBP ((((KEY xor KEY) xor 0x18) + 0x3D)xor 0xA7)
013BCDF1|.MOV EBP,ESP
013BCDF3|.MOV EAX, ;arg1 = KEY xor KEY
013BCDF6|.XOR AL,0x18
013BCDF8|.ADD AL,0x3D
013BCDFA|.XOR AL,0xA7
013BCDFC|.POP EBP
013BCDFD\.RETN
013BD9D9 .0FB6C0 MOVZX EAX,AL ;eax = ((((KEY xor KEY) xor 0x18) + 0x3D)xor 0xA7)
013BD9DC .56 PUSH ESI ;esi = ((KEY xor KEY)*0x100) + (KEY xor KEY)
013BD9DD .8947 1C MOV DWORD PTR DS:,EAX
013BD9E0 .E8 EDA904FF CALL 010Edito.004083D2
013BCD60/>PUSH EBP
013BCD61|.MOV EBP,ESP
013BCD63|.MOV EAX,
013BCD66|.MOV ECX,0xB ecx = 0xB
013BCD6B|.XOR EAX,0x7892
013BCD70|.ADD EAX,0x4D30
013BCD75|.XOR EAX,0x3421eax=((((KEY xor KEY)*0x100) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421
013BCD7A|.MOVZX EAX,AX
013BCD7D|.CDQ
013BCD7E|.IDIV ECX
013BCD80|.TEST EDX,EDXecx/eax的余数
013BCD82|.JE SHORT 010Edito.013BCD86 如果余数不为0,就跳出,否则清零eax
013BCD84|.XOR EAX,EAX
013BCD86|>POP EBP
013BCD87\.RETN
013BD9E5 MOV ECX,DWORD PTR DS: ;ECX = ((((KEY xor KEY) xor 0x18) + 0x3D)xor 0xA7)
013BD9E8 ADD ESP,0x8
013BD9EB MOVZX EAX,AX ; EAX= ((((KEY xor KEY)*0x100) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421
013BD9EE MOV DWORD PTR DS:,EAX
013BD9F1 TEST ECX,ECX ;如果ecx = 0,就结束
013BD9F3 JE 010Edito.013BDBB5
013BD9F9 TEST EAX,EAX ;如果eax = 0,就结束
013BD9FB JE 010Edito.013BDBB5
013BDA01 CMP EAX,0x3E8 ;如果eax > 0x3E8,就结束
013BDA06 JA 010Edito.013BDBB5
013BDA0C CMP ECX,0x2 ;如果小于 CF = 1 否则为0
013BDA0F SBB ESI,ESI ; -CF
013BDA11 AND ESI,ECX
013BDA13 JMP 010Edito.013BDACB
结果:DWORD PTR DS: = ((((KEY xor KEY) xor 0x18) + 0x3D)xor 0xA7)
DWORD PTR DS: = (((((KEY xor KEY)*0x100) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421)/0xB
对应的C代码
case 0x9C:
{
DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421;
DWORD ECX = (((KEY[ 0 ] ^ KEY[ 6 ]) ^ 0x18) + 0x3D) ^ 0xA7;
if (EAX % 0xB != 0)
{
EAX = 0;//error
}
if (EAX == 0 || EAX > 0x3E8)
{
return;//error
}
if(ECX == 0)
{
return;//error
}
if (ECX < 0x2)
{
// ECX == 1,ESI=1
ESI = ECX;
}
else
{
ESI = 0;
}
// 这里ECX如果大于0x2 ESI=0否则=ECX=1,至于ECX的值是多少,在后面可以看到
EDI0x20 = EAX/0xB;
break;
}
KEY == 0xFC
013BDA18 >80FB FC CMP BL,0xFC //如果KEY != 0x9C
013BDA1B .75 1F JNZ SHORT 010Edito.013BDA3C //如果KEY == 0xFC
013BDA1D .C747 1C FF000000 MOV DWORD PTR DS:,0xFF ;Case FC of switch 013BD9A3
013BDA24 .BE FF000000 MOV ESI,0xFF
013BDA29 .C747 20 01000000 MOV DWORD PTR DS:,0x1
013BDA30 .C747 30 01000000 MOV DWORD PTR DS:,0x1
013BDA37 .E9 8F000000 JMP 010Edito.013BDACB
结果:DWORD PTR DS: = 0xFF
DWORD PTR DS: = 0x1
// 后面判断,如果是0xFC,是不会返回0x2D,这里就略去
KEY == 0xAC
013BDA3C >CMP BL,0xAC //如果KEY != 0xFC
013BDA3F .JNZ 010Edito.013BDBB5
013BDA45 .MOV AL,BYTE PTR SS: ;KEY = 0xAC
013BDA48 .XOR AL,BYTE PTR SS: ;al = KEY xor KEY
013BDA4B .MOVZX ECX,AL ;ecx =KEY xor KEY
013BDA4E .MOV EAX,0x100
013BDA53 .IMUL CX,AX ;ecx = (KEY xor KEY)*0x100
013BDA57 .MOV AL,BYTE PTR SS: ;al = KEY
013BDA5A .XOR AL,BH ; al = KEY xor KEY
013BDA5C .MOV DWORD PTR DS:,0x2
013BDA63 .MOVZX EAX,AL
013BDA66 .ADD CX,AX ;cx = (KEY xor KEY) << 2)+(KEY xor KEY)
013BDA69 .MOVZX EAX,CX;eax = (KEY xor KEY) << 2)+(KEY xor KEY)
013BDA6C .PUSH EAX
013BDA6D .CALL 010Edito.004083D2
013BCD60/>PUSH EBP
013BCD61|.MOV EBP,ESP
013BCD63|.MOV EAX,;eax = (KEY xor KEY) << 2)+(KEY xor KEY)
013BCD66|.MOV ECX,0xB ecx = 0xB
013BCD6B|.XOR EAX,0x7892
013BCD70|.ADD EAX,0x4D30
013BCD75|.XOR EAX,0x3421eax= ((((KEY xor KEY)<<2) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421
013BCD7A|.MOVZX EAX,AX
013BCD7D|.CDQ
013BCD7E|.IDIV ECX eax = (((((KEY xor KEY)*0x100) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421)/0xB
013BCD80|.TEST EDX,EDXeax/ecx的余数
013BCD82|.JE SHORT 010Edito.013BCD86 如果余数不为0,就跳出,否则清零eax
013BCD84|.XOR EAX,EAX
013BCD86|>POP EBP
013BCD87\.RETN
013BDA72 .MOVZX EAX,AX
013BDA75 .ADD ESP,0x4
013BDA78 .MOV DWORD PTR DS:,EAX
013BDA7B .TEST EAX,EAX
013BDA7D .JE 010Edito.013BDBB5;等于0就返回
013BDA83 .CMP EAX,0x3E8 ;eax= ((((KEY xor KEY)<<2) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421
013BDA88 .JA 010Edito.013BDBB5;大于0x3E8就返回
013BDA8E MOVZX EDX,BYTE PTR SS: ;edx = KEY
013BDA92 MOVZX ECX,BYTE PTR SS: ;ecx = KEY
013BDA96 MOVZX EAX,BH;EAX = KEY
013BDA99 XOR EDX,EAX;edx = KEY xor KEY
013BDA9B MOVZX EAX,BYTE PTR SS: ;eax = KEY
013BDA9F XOR ECX,EAXecx = KEY xor KEY
013BDAA1 SHL EDX,0x8; edx = (KEY xor KEY) << 8
013BDAA4 MOVZX EAX,BYTE PTR SS:;eax = KEY
013BDAA8 ADD EDX,ECX ; EDX = ((KEY xor KEY) << 8)+(KEY xor KEY)
013BDAAA MOVZX ECX,BYTE PTR SS: ;ECX = KEY
013BDAAE SHL EDX,0x8 ; EDX = (((KEY xor KEY) << 8)+(KEY xor KEY))<<0x8
013BDAB1 XOR ECX,EAX ; ECX = KEY xor KEY;
013BDAB3 ADD EDX,ECX ; EDX = ((((KEY xor KEY) << 8)+(KEY xor KEY))<<0x8)+(KEY xor KEY)
013BDAB5 PUSH 010Edito.005B8C27
013BDABA PUSH EDX ;
013BDABB CALL 010Edito.0040A790
013BCCD0 PUSH EBP
013BCCD1 MOV EBP,ESP
013BCCD3 MOV ECX, ; ;ECX = ((((KEY xor KEY) << 8)+(KEY xor KEY))<<0x8)+(KEY xor KEY)
013BCCD6 MOV EAX,0xF0F0F0F1 ;eax = 0xF0F0F0F1
013BCCDB XOR ECX, ;ecx = (((((KEY xor KEY) << 8)+(KEY xor KEY))<<0x8)+(KEY xor KEY))xor 005B8C27
013BCCDE XOR ECX,0x22C078;ecx = ((((((KEY xor KEY) << 8)+(KEY xor KEY))<<8) + (KEYxor KEY))xor 005B8C27) xor 0x22c078
013BCCE4 SUB ECX,0x2C175 ;ecx = (((((((KEY xor KEY) << 8)+(KEY xor KEY))<<8) + (KEYxor KEY))xor 005B8C27) xor 0x22c078) - 0x2C175
013BCCEA XOR ECX,0xFFE53167;
013BCCF0 AND ECX,0xFFFFFF;ecx=(((((((((KEY xor KEY) << 8)+(KEY xor KEY))<<8) + (KEYxor KEY))xor 005B8C27) xor 0x22c078) - 0x2C175) xor 0xFFE53167) and 0xFFFFFF // ECX<0xFFFFFF
013BCCF6 MUL ECX ; EDX:EAX = 0xF0F0F0F1*ecxedx*0x100000000+eax = 0xF0F0F0F1*ecx ;EDX = ECX
013BCCF8 SHR EDX,0x4 ;
013BCCFB MOV EAX,EDX;
013BCCFD SHL EAX,0x4;
013BCD00 ADD EAX,EDX;
013BCD02 SUB ECX,EAX ;
013BCD04 MOV EAX,0x0 ;eax = 0
013BCD09 CMOVE EAX,EDX;zf = 1时移动
013BCD0C POP EBP
013BCD0D RETN
013BDAC0 .83C4 08 ADD ESP,0x8
013BDAC3 .8945 F0 MOV DWORD PTR SS:,EAX
013BDAC6 .8947 34 MOV DWORD PTR DS:,EAX
013BDAC9 .8BF0 MOV ESI,EAX
结果:
DWORD PTR SS: = EAX
DWORD PTR DS: = (((((KEY xor KEY)*0x100) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421)/0xB
case 0xAC:
{
DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421;
if(EAX % 0xB != 0)
{
EAX = 0;//error
}
if(EAX == 0 || EAX > 0x3E8)
{
return;//error
}
DWORD ECX = (((((((((KEY[ 9 ] ^ KEY[ 5 ]) << 8) + (KEY[ 4 ] ^ KEY[ 5 ])) << 8) + (KEY[ 6 ] ^ KEY[ 0 ])) ^ 0x05B8C27) ^ 0x22c078) - 0x2C175) ^ 0xFFE53167) & 0xFFFFFF;
EAX = 0xF0F0F0F1;
DWORD EDX = 0;
伪代码:EDX:EAX = EAX*ECX;
EDX = EDX >> 0x4;
EAX = (EDX << 0x4) + EDX;
ECX = ECX - EAX;
if (ECX == 0)// ECX = EAX
{
EAX = EDX;//right
}
else
{
EAX = 0;//error
}
EDI0x20 = ((((((KEY[ 1 ] ^ KEY[ 7 ]) << 2) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421)/0xB;
ESI = EAX;
break;
}
3.“处理用户名函数”
实际上面就是准备了ESI和EDI0x20 (DWORD PTR DS:)
“处理用户名函数”的参数为:
参数一:用户名字符串首地址
参数二:如果类型是0xFC就是0,否则是1,用于判断类型
参数三:上面获取的ESI
参数四:上面获取的EDI0x20
调用处
013BDACB >LEA EAX,DWORD PTR SS:
013BDACE .PUSH EAX
013BDACF .LEA ECX,DWORD PTR DS:
013BDAD2 CALL DWORD PTR DS:[<&Qt5Core.?toUt>;013BDAD8 .PUSH DWORD PTR DS: ;之前值已经获取((((KEY xor KEY)<<2) + (KEY xor KEY)) xor 0x7892)+0x4d30) xor 0x3421
013BDADB .XOR EAX,EAX ;
013BDADD .MOV DWORD PTR SS:,0x0
013BDAE4 .CMP BL,0xFC
013BDAE7 .LEA ECX,DWORD PTR SS:
013BDAEA .PUSH ESI ;ESI
013BDAEB .SETNE AL ;如果BL != 0xFC, AL = 1
013BDAEE .PUSH EAX ;
013BDAEF .CALL DWORD PTR DS:[<&Qt5Core.?data>;Qt5Core.?data@QByteArray@@QAEPADXZ// 这个函数没有参数,传出用户名
013BDAF5 .PUSH EAX ;传入的是用户名
013BDAF6 .CALL 010Edito.00402E50 ;处理用户名
函数中
013BCE60/> USH EBP
013BCE61|. MOV EBP,ESP
013BCE63|. SUB ESP,0x10
013BCE66|. MOV EDX, ;EDX = 用户名
013BCE69|. XOR ECX,ECX ;ECX = 0
013BCE6B|. PUSH ESI ;保存ESI
013BCE6C|. MOV ESI,EDX ;esi = 用户名
013BCE6E|. MOV ,ECX ; = 0
013BCE71|. PUSH EDI ;保存EDI
013BCE72|. LEA EDI,DWORD PTR DS: ;edi = 用户名地址+1,用于下面的判断
013BCE75|> MOV AL,BYTE PTR DS: ;al=pStr
013BCE77|. INC ESI ;pStr = pStr+1
013BCE78|. TEST AL,AL ;判断是否到达字符串结尾
013BCE7A|.^JNZ SHORT 010Edito.013BCE75
013BCE7C|. SUB ESI,EDI ;以上为获取字符串长度,<ESI = 用户名长度>
013BCE7E|. XOR EDI,EDI ; EDI = 0
013BCE80|. TEST ESI,ESI ;判断字符串是否为空
013BCE82|. JLE 010Edito.013BCF78 ; 长度<=0就跳出
013BCE88|. PUSH EBX; 保存EBX
013BCE89|. MOV EBX,;EBX = Arg_EDI0x20
013BCE8C|. MOV ,ECX ; = 0
013BCE8F|. MOV ,ECX ; = 0
013BCE92|. MOV ECX,; ECX = Arg_esi
013BCE95|. SHL EBX,0x4;EBX = Arg_EDI0x20<<0x4
013BCE98|. SUB EBX,; EBX = (Arg_EDI0x20<<0x4)-Arg_EDI0x20
013BCE9B|. SHL ECX,0x4;ECX = Arg_esi << 0x4
013BCE9E|. ADD ECX,;ECX = Arg_esi << 0x4 + Arg_esi
013BCEA1|. MOV ,ECX ; LOCAL.2 = Arg_esi << 0x4 + Arg_esi
013BCEA4|> MOVZX EAX,BYTE PTR DS: ;EAX = 用户名
013BCEA8|. PUSH EAX ; /c
013BCEA9|. CALL DWORD PTR DS:[<&MSVCR120.toupper>]; // 将字符转化为大写字母
013BCEAF|. MOV EDX,EAX ;将转化后的放到 EDX = 大写字母char
013BCEB1|. ADD ESP,0x4
013BCEB4|. MOV ECX,DWORD PTR DS:;将大写字母作为索引从0x2E64148中取内容
013BCEBB|. ADD ECX, ;ECX = +DWORD PTR DS:
013BCEBE|. CMP ,0x0 ;判断是哪种类型的注册
013BCEC2|. JE SHORT 010Edito.013BCF0E ;如果是0xFC类型就跳到下面一段处理
013BCEC4|. LEA EAX,DWORD PTR DS: ;EAX = char+0xD
013BCEC7|. AND EAX,0xFF; EAX= (char+0xD) AND 0xFF;
013BCECC|. XOR ECX,DWORD PTR DS:
; ECX = (+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]
013BCED3|.LEA EAX,DWORD PTR DS: ; EAX = char+0x2F
013BCED6|.AND EAX,0xFF ;EAX = (char+0x2F) and 0xFF
013BCEDB|.IMUL ECX,DWORD PTR DS:
;ECX = ((+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148]
013BCEE3|.MOV EAX,;EAX =
013BCEE6|.MOVZX EAX,AL; EAX =&0xFF
013BCEE9|.ADD ECX,DWORD PTR DS:;
ECX =
(((+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:(*+0x2E64148)
013BCEF0|.MOVZX EAX,BL ;EAX = EBX
013BCEF3|.ADD ECX,DWORD PTR DS:
ECX =
(((+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:(*+0x2E64148)
+DWORD PTR DS:
013BCEFA|.MOV EAX, ;EAX =
013BCEFD|.MOVZX EAX,AL
013BCF00|.ADD ECX,DWORD PTR DS:
ECX =
(((+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:(*+0x2E64148)
+DWORD PTR DS:
+ DWORD PTR DS:[*4+0x2E64148]
013BCF07|.8BC1 |MOV EAX,ECX
EAX =
(((+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:(*+0x2E64148)
+DWORD PTR DS:
+ DWORD PTR DS:[*4+0x2E64148]
013BCF09|.8945 FC |MOV ,EAX
=
(((+DWORD PTR DS: ) xor DWORD PTR DS:[((char+0xD) AND 0xFF)*4+0x2E64148]) * DWORD PTR DS:[((char+0x2F) and 0xFF)*4+0x2E64148])
+DWORD PTR DS:(*+0x2E64148)
+DWORD PTR DS:
+ DWORD PTR DS:[*4+0x2E64148]
013BCF0C|.EB 48 |JMP SHORT 010Edito.013BCF56
如果是0xFC类型就跳到这里ECX = +DWORD PTR DS:
013BCF0E|>LEA EAX,DWORD PTR DS:;eax = char+0x3f
013BCF11|.AND EAX,0xFF ; eax = (char + 0x3f) and 0xff
013BCF16|.XOR ECX,DWORD PTR DS:
;ecx =(+DWORD PTR DS:) xor(WORD PTR DS:[((char + 0x3f) and 0xff)*4+0x2E64148])
013BCF1D|.LEA EAX,DWORD PTR DS:
013BCF20|.AND EAX,0xFF ;eax = (char +0x17) and 0xff
013BCF25|.IMUL ECX,DWORD PTR DS:
;ecx = ((+DWORD PTR DS:) xor(WORD PTR DS:[((char + 0x3f) and 0xff)*4+0x2E64148])) *(DWORD PTR DS:[((char +0x17) and 0xff)*4+0x2E64148])
013BCF2D|.MOV EAX,
013BCF30|.MOVZX EAX,AL ;EAX =
013BCF33|.ADD ECX,DWORD PTR DS: ;
013BCF3A|.MOVZX EAX,BL ; EAX = ebx;
013BCF3D|.ADD ECX,DWORD PTR DS:
013BCF44|.MOV EAX,
013BCF47|.MOVZX EAX,AL ; eax =
013BCF4A|.ADD ECX,DWORD PTR DS:
013BCF51|.MOV EAX,ECX
013BCF53|.MOV ,ECX
// 循环递增
013BCF56|>|ADD ,0x13
013BCF5A|.|INC EDI
013BCF5B|.|ADD ,0x9
013BCF5F|.|ADD EBX,0xD
013BCF62|.|ADD ,0x7
013BCF66|.|MOV EDX, ;EDX = 用户名首地址
013BCF69|.|CMP EDI,ESI
013BCF6B|.^ \JL 010Edito.013BCEA4--->循环,
013BCF71|.POP EBX
013BCF72|.POP EDI
013BCF73|.POP ESI
013BCF74|.MOV ESP,EBP
013BCF76|.POP EBP
013BCF77|.RETN
// 长度小于0
013BCF78|>POP EDI
013BCF79|.MOV EAX,ECX
013BCF7B|.POP ESI
013BCF7C|.MOV ESP,EBP
013BCF7E|.POP EBP
013BCF7F\.RETN
很明显这里面涉及到一个整形数组
DWORD LOCAL3 = 0;
DWORD LOCAL4 = 0;
DWORD LOCAL2 = (ESI*17)&0xFF; // 用于设置注册天数
DWORD LOCAL1 = 0;
DWORD EBX = EDI0x20*15; 用于设置注册人数
INT NameLength = strlen(Name);
int i = 0;
char EAX[ 4 ] = {0};
DWORDBUF[ 256 ] = { 0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821, 0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60, 0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA, 0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B, 0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971, 0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08, 0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E, 0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F, 0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9, 0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99, 0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A, 0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C, 0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A, 0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851, 0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF, 0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60, 0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2, 0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72, 0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C, 0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D, 0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423, 0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B, 0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1, 0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2, 0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C, 0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC, 0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E, 0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F, 0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E, 0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5, 0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03, 0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };
while (NameLength)
{
char nameChar = toupper(Name[ i ]);
if (KEY != 0xFC)
{
LOCAL1 =
(((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0xD)]) * BUF[ (nameChar + 0x2F)])
+ BUF[ LOCAL2 ]
+ BUF[ EBX ]
+ BUF[ LOCAL3 ];
}
Else//这一情况无用
{
LOCAL1 =
(((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0x3F)]) * BUF[ (nameChar + 0x17)])
+ BUF[ LOCAL2 ]
+ BUF[ EBX ]
+ BUF[ LOCAL4 ];
}
*(DWORD*)EAX = LOCAL1;
EBX += 0xD;
LOCAL3 += 0x13;
LOCAL2 += 0x9;
LOCAL4 += 0x7;
i++;
NameLength--;
}
4.根据“处理用户名函数”返回值获得更多信息
在上面的函数返回之后,会对返回值进行判断,并且解开上面讲到的一些疑问
这里从结果0x2D往上找
这一段放到notepad中一高亮显示,首先就发现Case FC是跳不到正确处的,所以上面的关于FC的操作都可不用做
013BDAF6 .CALL 010Edito.00402E50 ;处理用户名
013BDAFB .MOV EDX,EAX
013BDAFD .ADD ESP,0x10
013BDB00 .CMP BYTE PTR SS:,DL ;KEY和返回值比较
013BDB03 .JNZ 010Edito.013BDB8A ;应该相等
013BDB09 .MOV ECX,EDX
013BDB0B .SHR ECX,0x8
013BDB0E .CMP BH,CL;返回值>>0x8 和 KEY比较
013BDB10 .JNZ SHORT 010Edito.013BDB8A;应该相等
013BDB12 .MOV ECX,EDX
013BDB14 .SHR ECX,0x10
013BDB17 .CMP BYTE PTR SS:,CL;返回值>>0x10 和 KEY比较
013BDB1A .JNZ SHORT 010Edito.013BDB8A;应该相等
013BDB1C .SHR EAX,0x18
013BDB1F .CMP BYTE PTR SS:,AL;返回值>>0x18 和 KEY比较
013BDB22 .JNZ SHORT 010Edito.013BDB8A;应该相等
013BDB24 .CMP BL,0x9C ;Switch (cases 9C..FC)
013BDB27 .JNZ SHORT 010Edito.013BDB38
013BDB29 .MOV EAX,DWORD PTR SS: ;Case 9C of switch 013BDB24
013BDB2C .CMP EAX,DWORD PTR DS:
013BDB2F .JBE SHORT 010Edito.013BDB83 // <= 跳到正确③
013BDB31 .MOV ESI,0x4E
013BDB36 .JMP SHORT 010Edito.013BDB8F
013BDB38 >CMP BL,0xFC ;
013BDB3B .JNZ SHORT 010Edito.013BDB6B
013BDB3D .MOVZX ECX,BYTE PTR SS: ;Case FC of switch 013BDB24
013BDB41 .MOVZX EAX,BYTE PTR SS:
013BDB45 .SHL ECX,0x8
013BDB48 .ADD ECX,EAX
013BDB4A .MOVZX EAX,BYTE PTR SS:
013BDB4E .SHL ECX,0x8
013BDB51 .PUSH EDX
013BDB52 .ADD ECX,EAX
013BDB54 .PUSH ECX
013BDB55 .CALL 010Edito.0040A790
013BDB5A .ADD ESP,0x8
013BDB5D .TEST EAX,EAX
013BDB5F .JE SHORT 010Edito.013BDB8A
013BDB61 .MOV DWORD PTR DS:,EAX
013BDB64 .MOV ESI,0x93
013BDB69 .JMP SHORT 010Edito.013BDB8F
013BDB6B >CMP BL,0xAC
013BDB6E .JNZ SHORT 010Edito.013BDB8A
013BDB70 .MOV EAX,DWORD PTR SS: ;Case AC of switch 013BDB24
013BDB73 .TEST EAX,EAX
013BDB75 .JE SHORT 010Edito.013BDB8A
013BDB77 .CMP DWORD PTR SS:,EAX
013BDB7A .JBE SHORT 010Edito.013BDB83 //<=跳到正确③
013BDB7C .MOV ESI,0x4E
013BDB81 .JMP SHORT 010Edito.013BDB8F
013BDB83 >MOV ESI,0x2D// 正确答案②
013BDB88 .JMP SHORT 010Edito.013BDB8F
013BDB8A >MOV ESI,0xE7 ;Default case of switch 013BDB24
013BDB8F >LEA ECX,DWORD PTR SS:
013BDB92 .MOV DWORD PTR SS:,-0x1
013BDB99 .CALL DWORD PTR DS:[<&Qt5Core.??1QB>;Qt5Core.??1QByteArray@@QAE@XZ
013BDB9F .MOV EAX,ESI// 获得返回值①
013BDBA1 .MOV ECX,DWORD PTR SS:
013BDBA4 .MOV DWORD PTR FS:,ECX
013BDBAB .POP ECX
013BDBAC .POP EDI
013BDBAD .POP ESI
013BDBAE .POP EBX
013BDBAF .MOV ESP,EBP
013BDBB1 .POP EBP
013BDBB2 .RETN 0x8
对应c
if (EAX == KEY &&
EAX == KEY&&
EAX == KEY&&
EAX == KEY)
{
switch (KEY)
{
case 0x9c:
/*if ([ EBP + 0x8 ] <= [ EDI + 0x1C ])
{
RIGHT
}*/
break;
case 0xfc:
break;
case 0xac:
/*if ([ EBP - 0x10 ] >= [ EBP + 0xC ])
{
RIGHT
}*/
break;
}
其次会发现在跳转之前有判断
case 0x9c:
/*if ([ EBP + 0x8 ] <= [ EDI + 0x1C ]) {
RIGHT
}*/
在case 0xAC之后有判断
case 0xac:
/*if ([ EBP - 0x10 ] >= [ EBP + 0xC ]){
RIGHT
}*/
对于0x9c(版本号授权)
[ EBP + 0x8 ] <= [ EDI + 0x1C ]这个条件表示:
[ EBP + 0x8 ]是注册验证函数参数1 ,值为 9(这个表示版本号), [ EDI + 0x1C ]根据前面可知是((((KEY xor KEY) xor 0x18) + 0x3D)xor 0xA7),
所以((((KEY xor KEY) xor 0x18) + 0x3D)xor 0xA7)>=9
结合上面的分析
DWORD ECX = (((KEY[ 0 ] ^ KEY[ 6 ]) ^ 0x18) + 0x3D) ^ 0xA7;
if (ECX < 0x2)
{
// ECX == 1,ESI=1
ESI = ECX;
}
else
{
ESI = 0;
}
可以知道ESI = 0
void CkeygenDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
char szName[ 64 ] = { 0 };
DWORD EDI0x20 = 1;// 0~1000,是0xB的倍数 // 表示人数
DWORD EBX = EDI0x20*15;
DWORD LOCAL3 = 0;
DWORD LOCAL2 = 0; //LOCAL2 = ESI*17
DWORD LOCAL1 = 0;
INT NameLength;
int i = 0;
BYTE KEY[ 10 ] = { 0 };
KEY[ 3 ] = 0x9C;
BYTE EAX[ 4 ] = { 0 };
DWORDBUF[ 256 ] = { 0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821, 0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60, 0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA, 0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B, 0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971, 0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08, 0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E, 0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F, 0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9, 0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99, 0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A, 0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C, 0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A, 0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851, 0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF, 0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60, 0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2, 0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72, 0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C, 0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D, 0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423, 0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B, 0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1, 0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2, 0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C, 0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC, 0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E, 0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F, 0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E, 0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5, 0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03, 0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };
UpdateData(TRUE);
WideCharToMultiByte(CP_ACP , 0 ,
m_user.GetBuffer() , -1 ,
szName , 64 ,
NULL , NULL);
NameLength = strlen(szName);
while(NameLength)
{
char nameChar = toupper(szName[ i ]);
LOCAL1 =
(((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0xD) ]) * BUF[ (nameChar + 0x2F) ])
+ BUF[ LOCAL2 ]
+ BUF[ EBX ]
+ BUF[ LOCAL3 ];
*(DWORD*)EAX = LOCAL1;
EBX += 0xD;
LOCAL3 += 0x13;
LOCAL2 += 0x9;
i++;
NameLength--;
}
KEY[ 4 ] = EAX[ 0 ];
KEY[ 5 ] = EAX[ 1 ];
KEY[ 6 ] = EAX[ 2 ];
KEY[ 7 ] = EAX[ 3 ];
//DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421 = EDI0x20;
//DWORD ECX = (((KEY[ 0 ] ^ KEY[ 6 ]) ^ 0x18) + 0x3D) ^ 0xA7 = 版本号;版本号此时应大于9
WORD tmp = ((EDI0x20*11) ^ 0x3421 - 0x4d30) ^ 0x7892;
KEY[ 1 ] = (HIBYTE(tmp)) ^ KEY[ 7 ];
KEY[ 2 ] = (LOBYTE(tmp)) ^ KEY[ 5 ];
KEY[ 0 ] = (((10 ^ 0xa7) - 0x3d) ^ 0x18) ^ KEY[ 6 ];//这里取版本号10
char reg[ 200 ] = { 0 };
sprintf_s(reg , 200 , "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" , KEY[ 0 ] , KEY[ 1 ] , KEY[ 2 ] , KEY[ 3 ] , KEY[ 4 ] , KEY[ 5 ] , KEY[ 6 ] , KEY[ 7 ] , 0 , 0);
m_reg = CString(reg);
UpdateData(FALSE);
}
对于0xac(天数授权)
[ EBP - 0x10 ] >= [ EBP + 0xC ]这个条件表示
[ EBP + 0xc ]是注册验证函数参数2 ,值为 0x4389, [ EBP -0x10 ]根据前面的条件是,0xac注册最后的EAX,说明最后ecx == eax,eax被赋值为edx
就是这段
if (ECX == 0)// ECX = EAX
{
EAX = EDX;//right
}
else
{
EAX = 0;//error
}
具体的需要结合上面的代码来看
由此可以算出 最后的eax的可能值,也是esi的可能值,
unsigned int num_ecx = 0xFFFFFF;
unsigned int num_eax = 0;
unsigned int num_edx = 0;
while(1)
{
__asm {
MOV ECX , num_ecx;
MOV EAX , 0XF0F0F0F1;
MUL ECX;
SHR EDX , 0x4 ;
MOV EAX , EDX;
SHL EAX , 0x4;
ADD EAX , EDX;
MOV num_eax , EAX;
MOV num_edx , EDX;
}
if (num_eax == num_ecx)
{
printf("%x_%x\n", num_ecx, num_edx);
}
num_ecx--;
}
从算出的结果取出一个(不要从最前面取,从中间取),用在注册机的0xAC情况中,用于表示天数
注意下面特别标注的地方
一些可用的值
ff7711_f0701
ff7700_f0700
ff76ef_f06ff
ff76de_f06fe
ff76cd_f06fd
ff76bc_f06fc
ff76ab_f06fb
ff769a_f06fa
void CkeygenDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
char szName[ 64 ] = { 0 };
DWORD EDI0x20 = 1;// 0~1000,是0xB的倍数,表示人数
DWORD EBX = EDI0x20*15;
DWORD LOCAL3 = 0;
DWORD ESI = 0xf054c;// 这个就是算出的num_edx,与注册天数有关
DWORD LOCAL2 = (17*ESI)&0xFF;//遍历出来的,ESI = EAX = EDX
DWORD LOCAL1 = 0;
INT NameLength;
int i = 0;
BYTE KEY[ 10 ] = { 0 };
BYTE EAX[ 4 ] = { 0 };
DWORDBUF[ 256 ] = { 0x39CB44B8, 0x23754F67, 0x5F017211, 0x3EBB24DA, 0x351707C6, 0x63F9774B, 0x17827288, 0x0FE74821, 0x5B5F670F, 0x48315AE8, 0x785B7769, 0x2B7A1547, 0x38D11292, 0x42A11B32, 0x35332244, 0x77437B60, 0x1EAB3B10, 0x53810000, 0x1D0212AE, 0x6F0377A8, 0x43C03092, 0x2D3C0A8E, 0x62950CBF, 0x30F06FFA, 0x34F710E0, 0x28F417FB, 0x350D2F95, 0x5A361D5A, 0x15CC060B, 0x0AFD13CC, 0x28603BCF, 0x3371066B, 0x30CD14E4, 0x175D3A67, 0x6DD66A13, 0x2D3409F9, 0x581E7B82, 0x76526B99, 0x5C8D5188, 0x2C857971, 0x15F51FC0, 0x68CC0D11, 0x49F55E5C, 0x275E4364, 0x2D1E0DBC, 0x4CEE7CE3, 0x32555840, 0x112E2E08, 0x6978065A, 0x72921406, 0x314578E7, 0x175621B7, 0x40771DBF, 0x3FC238D6, 0x4A31128A, 0x2DAD036E, 0x41A069D6, 0x25400192, 0x00DD4667, 0x6AFC1F4F, 0x571040CE, 0x62FE66DF, 0x41DB4B3E, 0x3582231F, 0x55F6079A, 0x1CA70644, 0x1B1643D2, 0x3F7228C9, 0x5F141070, 0x3E1474AB, 0x444B256E, 0x537050D9, 0x0F42094B, 0x2FD820E6, 0x778B2E5E, 0x71176D02, 0x7FEA7A69, 0x5BB54628, 0x19BA6C71, 0x39763A99, 0x178D54CD, 0x01246E88, 0x3313537E, 0x2B8E2D17, 0x2A3D10BE, 0x59D10582, 0x37A163DB, 0x30D6489A, 0x6A215C46, 0x0E1C7A76, 0x1FC760E7, 0x79B80C65, 0x27F459B4, 0x799A7326, 0x50BA1782, 0x2A116D5C, 0x63866E1B, 0x3F920E3C, 0x55023490, 0x55B56089, 0x2C391FD1, 0x2F8035C2, 0x64FD2B7A, 0x4CE8759A, 0x518504F0, 0x799501A8, 0x3F5B2CAD, 0x38E60160, 0x637641D8, 0x33352A42, 0x51A22C19, 0x085C5851, 0x032917AB, 0x2B770AC7, 0x30AC77B3, 0x2BEC1907, 0x035202D0, 0x0FA933D3, 0x61255DF3, 0x22AD06BF, 0x58B86971, 0x5FCA0DE5, 0x700D6456, 0x56A973DB, 0x5AB759FD, 0x330E0BE2, 0x5B3C0DDD, 0x495D3C60, 0x53BD59A6, 0x4C5E6D91, 0x49D9318D, 0x103D5079, 0x61CE42E3, 0x7ED5121D, 0x14E160ED, 0x212D4EF2, 0x270133F0, 0x62435A96, 0x1FA75E8B, 0x6F092FBE, 0x4A000D49, 0x57AE1C70, 0x004E2477, 0x561E7E72, 0x468C0033, 0x5DCC2402, 0x78507AC6, 0x58AF24C7, 0x0DF62D34, 0x358A4708, 0x3CFB1E11, 0x2B71451C, 0x77A75295, 0x56890721, 0x0FEF75F3, 0x120F24F1, 0x01990AE7, 0x339C4452, 0x27A15B8E, 0x0BA7276D, 0x60DC1B7B, 0x4F4B7F82, 0x67DB7007, 0x4F4A57D9, 0x621252E8, 0x20532CFC, 0x6A390306, 0x18800423, 0x19F3778A, 0x462316F0, 0x56AE0937, 0x43C2675C, 0x65CA45FD, 0x0D604FF2, 0x0BFD22CB, 0x3AFE643B, 0x3BF67FA6, 0x44623579, 0x184031F8, 0x32174F97, 0x4C6A092A, 0x5FB50261, 0x01650174, 0x33634AF1, 0x712D18F4, 0x6E997169, 0x5DAB7AFE, 0x7C2B2EE8, 0x6EDB75B4, 0x5F836FB6, 0x3C2A6DD6, 0x292D05C2, 0x052244DB, 0x149A5F4F, 0x5D486540, 0x331D15EA, 0x4F456920, 0x483A699F, 0x3B450F05, 0x3B207C6C, 0x749D70FE, 0x417461F6, 0x62B031F1, 0x2750577B, 0x29131533, 0x588C3808, 0x1AEF3456, 0x0F3C00EC, 0x7DA74742, 0x4B797A6C, 0x5EBB3287, 0x786558B8, 0x00ED4FF2, 0x6269691E, 0x24A2255F, 0x62C11F7E, 0x2F8A7DCD, 0x643B17FE, 0x778318B8, 0x253B60FE, 0x34BB63A3, 0x5B03214F, 0x5F1571F4, 0x1A316E9F, 0x7ACF2704, 0x28896838, 0x18614677, 0x1BF569EB, 0x0BA85EC9, 0x6ACA6B46, 0x1E43422A, 0x514D5F0E, 0x413E018C, 0x307626E9, 0x01ED1DFA, 0x49F46F5A, 0x461B642B, 0x7D7007F2, 0x13652657, 0x6B160BC5, 0x65E04849, 0x1F526E1C, 0x5A0251B6, 0x2BD73F69, 0x2DBF7ACD, 0x51E63E80, 0x5CF2670F, 0x21CD0A03, 0x5CFF0261, 0x33AE061E, 0x3BB6345F, 0x5D814A75, 0x257B5DF4, 0x0A5C2C5B, 0x16A45527, 0x16F23945 };
UpdateData(TRUE);
WideCharToMultiByte(CP_ACP , 0 ,
m_usersec.GetBuffer() , -1 ,
szName , 64 ,
NULL , NULL);
NameLength = strlen(szName);
while(NameLength)
{
char nameChar = toupper(szName[ i ]);
LOCAL1 =
(((LOCAL1 + BUF[ nameChar ]) ^ BUF[ (nameChar + 0xD) ]) * BUF[ (nameChar + 0x2F) ])
+ BUF[ LOCAL2 ]
+ BUF[ EBX ]
+ BUF[ LOCAL3 ];
*(DWORD*)EAX = LOCAL1;
EBX += 0xD;
LOCAL3 += 0x13;
LOCAL2 += 0x9;
i++;
NameLength--;
}
KEY[ 3 ] = 0xAC;
KEY[ 4 ] = EAX[ 0 ];
KEY[ 5 ] = EAX[ 1 ];
KEY[ 6 ] = EAX[ 2 ];
KEY[ 7 ] = EAX[ 3 ];
//DWORD EAX = (((((KEY[ 1 ] ^ KEY[ 7 ]) * 0x100) + (KEY[ 2 ] ^ KEY[ 5 ])) ^ 0x7892) + 0x4d30) ^ 0x3421 = EDI0x20;
/*ecx=(((((((((KEY xor KEY) << 8)+(KEY xor KEY))<<8) + (KEYxor KEY))xor 005B8C27) xor 0x22c078) - 0x2C175) xor 0xFFE53167) and 0xFFFFFF ;*/
WORD tmp = ((EDI0x20*11) ^ 0x3421 - 0x4d30) ^ 0x7892;
KEY[ 1 ] = (HIBYTE(tmp)) ^ KEY[ 7 ];
KEY[ 2 ] = (LOBYTE(tmp)) ^ KEY[ 5 ];
DWORD tmp2 = (((0xff5a0c ^ 0xFFE53167) + 0x2C175) ^ 0x22c078) ^ 0x05B8C27;// 这就是算出的e num_ecx
KEY[ 0 ] = (tmp2 & 0xFF) ^ KEY[ 6 ];
DWORD tmp3 = (tmp2 - (tmp2 & 0xFF)) >> 0x8;
KEY[ 8 ] = (tmp3 & 0xFF) ^ KEY[ 4 ];
KEY[ 9 ] = ((tmp3 - (tmp3 & 0xFF)) >> 0x8) ^ KEY[ 5 ];
char reg[ 200 ] = { 0 };
sprintf_s(reg , 200 , "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X" , KEY[ 0 ] , KEY[ 1 ] , KEY[ 2 ] , KEY[ 3 ] , KEY[ 4 ] , KEY[ 5 ] , KEY[ 6 ] , KEY[ 7 ] , KEY , KEY);
m_regsec = CString(reg);
UpdateData(FALSE);
}
页:
[1]