【吾爱2013CM大赛解答】-- White Decrypt & CrackMe 解题思路和方法
题目:【吾爱2013CM大赛题目】-- White Decrypt & CrackMe分析文章(以发帖时间为序):
playboysen:【吾爱2013CM大赛解答】-- White Decrypt & CrackMe -- White 算法还原(复杂)
ja3klyTim9k:【吾爱2013CM大赛解答】 -- White Decrypt & CrackMe -- White
Thend:【吾爱2013CM大赛解答】-- White Decrypt & CrackMe -- White 算法详细分析+还原
题目要求很简单:找出合适的Name和Key组合,使得INFO显示“Something Is always Changing!”时,解题成功!
分析就不再重复了。贴段我的笔记来说明问题:
***************************************************************************************************************
Offset: 0123456789ABCDEF10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
Key: 44 6F 5F 59 6F 75 5F 4C 69 6B 65 5F 49 74 5F 4F 72 5F 4E 4F 54 5F 5F 3A 29 5F "Do_You_Like_It_Or_NOT__:)_"
Key Variation #1: 00401577
ALGO: ^= Key, i = strlen(Key)-1 ~ 0
44 2B 30 06 36 1A 2A 13 25 02 0E 3A 16 3D 2B 10 3D 2D 11 01 1B 0B 00 65 13 76
Name: 57 68 69 74 65 5F 43 72 61 63 6B 4D 65 5F 4A 55 53 54 5F 46 6F 72 5F 46 75 6E "White_CrackMe_JUST_For_Fun"
Name Variation #1: 0040159A
ALGO: ^= Name, i = strlen(Name)-1 ~ 0
57 3F 01 1D 11 3A 1C 31 13 02 08 26 28 3A 15 1F 06 07 0B 19 29 1D 2D 19 33 1B
.D]cBrC}B"OU.[yhg~x9caaot{ng !
Preset: 1F 44 5D 63 42 72 43 7D 42 22 4F 55 08 5B 79 68 67 7E 78 39 63 61 61 6F 74 7B 6E 67 20 21 00 00
at address 004160B0
Decoding #1, Key Variation #2: 00401644
for Preset: ALGO: ^= Key, i = 00 ~ 0A;
for Key: ALGO: Key ^= Key, i = 0A ~ strlen(Key)-0A if strlen(Key)-0A >= 0A
<------------------------------>
[omething AU.[yhg~x9caaot{ng !
Preset: 5B 6F 6D 65 74 68 69 6E 67 20 41 55 08 5B 79 68 67 7E 78 39 63 61 61 6F 74 7B 6E 67 20 21 00 00
<------>
Key: 44 2B 30 06 36 1A 2A 13 25 02 0E 34 22 1F 2B 10 3D 2D 11 01 1B 0B 00 65 13 76
Decoding #2, Name Variation #2: 00401668
for Preset: ALGO: ^= Name, i = 0A ~ 14
for Name: ALGO: Name &= Name, i = 14 ~ strlen(Name)-14 if strlen(Name)-14 >= 14
<------------------------------>
[omething Is always Jaaot{ng !
Preset: 5B 6F 6D 65 74 68 69 6E 67 20 49 73 20 61 6C 77 61 79 73 20 4A 61 61 6F 74 7B 6E 67 20 21 00 00
<----------------, ...
Name: 57 3F 01 1D 11 3A 1C 31 13 02 08 26 28 3A 15 1F 06 07 0B 19 29 1D 2D 19 33 1B
Name Variation #3: 00401695
ALGO: ^= Key, i = 00 ~ 0A
<------------------------------>
Name: 13 14 31 1B 27 20 36 22 36 00 06 26 28 3A 15 1F 06 07 0B 19 29 1D 2D 19 33 1B
Key Variation #3: 004016A9
ALGO: &= Name, i = 0A ~ 14 <------------------------------>
Key: 44 2B 30 06 36 1A 2A 13 25 02 06 24 20 1A 01 10 04 05 01 01 09 0B 00 65 13 76
Name Variation #4: 004016BE
ALGO: &= Key, i = 14 ~ 19 <--------------->
Name: 13 14 31 1B 27 20 36 22 36 00 06 26 28 3A 15 1F 06 07 0B 19 09 09 00 01 13 12
Decoding #3: 004016CF
ALGO: ^= Name, i = 14 ~ 19 <--------------->
[omething Is always Changing !
Preset/Answer:5B 6F 6D 65 74 68 69 6E 67 20 49 73 20 61 6C 77 61 79 73 20 43 68 61 6E 67 69 6E 67 20 21 00 00
***************************************************************************************************************
Conclusion
Related: KKKKKKKKKKKN NNNNNNNNNNK NK NK NK NK NK
Key status: CCCCCCCCCCVvvvvvvvvvVVVVVV
Offset: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
<-----------------------------<>----------------------------<>-------------->
^= Key ^= Name ^= Name(#4)
ALGO: 1) 00~09: ^= Key
2) 0A: ^= Key, ^= Name
3) 0B~13: ^= Name
4) 14: ^= Name, ^= Name & (Key & Name)
5) 15~19: ^= (Name & Key)
***************************************************************************************************************
前半部分是Name和Key的变换、答案的解码过程;重点在后半部分的分析总结,那些无关的运算完全可以无视:
[*]Key的00~09位是固定的,Preset和Answer决定了它不可变化。在08的机器上为"Do_You_Lik",在00的机器上为"LgWQg}WDac"。“xx的机器上”这种说法有点儿诡异!
[*]Key的0A位:对给定的Name,是确定的,没有太多变数。
[*]Key的0B~13位:因为正确的答案只受Name的影响,则Key是可自定义的,随便了。可以弄得有意义一点,比如:"_MistHill","_52PoJie_","_It_Or_NO"等等。
[*]Key的14位:这个比较讨厌,“与”运算使得结果有相当的不确定性:用Name、Preset和Answer三个条件对Key进行枚举,找出所有的可能;在当前Name下,可能得不到任何结果,还需要修改Name的对应位,重复这个枚举过程。
[*]Key的15~19位:与第14位类似,但少一个与第一次变换后Name的“异或”。
对Name来说,其00~0A位不对结果产生影响(只需调整Key),也是可自定义的。比如:"White_Crack","Weare52PoJi","Weare吾爱__"等等。当然得满足Name和Name的强制要求。
Key:
0123456789ABCDEF0123456789ABCDEF
Do_You_Lik
LgWQg}WDac
_MistHill
_52PoJie_
_It_Or_NO
Name:
0123456789ABCDEF0123456789ABCDEF
White_Crack
Weare52PoJi
Weare吾爱__
理解了这些就可以写程序了,用ODbgScript比较方便。本来只想简单地写一个,结果越整越复杂,搞得平安夜还在码字。{:1_937:}
脚本对给定的Name,枚举出有效的Key。在某个Name无解时,会自动调整Name。
因为Key的0B~13位是自定义的。对一个给定的合格Name,仅Key在这里的变化就有256的9次方,这个数是很大的。脚本不处理这种简单的罗列!关键在Key~Key的求解上。
结合脚本的输入参数,说一下Keygen使用。
mov szName, "White_CrackMe_JUST_For_Fun"
mov char_mallocPtrMinus1, 8, 1
mov dwCountLimitFor1419, 2
mov bFilterOn, 1
mov bOutputToFile, 0
先什么都不用改,直接跑一下脚本,看看你能得到什么结果。
变量szName可以指定任意Name,脚本会自动调整的。{:1_921:}
长度有要求:至少0x1A(26.)字符,最多0x27(39.)字符。设置最长字符数是为了简化问题(参见上面的Name Variation #2)。Key是要求解的,长度固定为0x1A可省去不少麻烦。
char_mallocPtrMinus1是为解决“xx的机器上”造成答案的差异,即VC运行库函数_malloc返回的指针-1那个字节的值。正常地,任何时候都不应该访问不属于自己请求的地址范围。不过,_malloc大多数情况是从Heap里分配空间,非法访问不易察觉。
我和ja3klyTim9k的这个值为0x00,其它人多为0x08。感谢playboysen在多个平台的测试!
dwCountLimitFor1419用来限制Key的14~19位各种有效组合的输出数量。脚本已经计算出了各位的有效值,完全的组合数同样巨大,没必要全部输出显示。
以题目的示例Name为例,各位的有效个数及取值如下:
位 个数 有效值
-- ---- ------
14 20 09 0B 0D 0F 19 1B 1D 1F 49 4B 4D 4F 59 5B 5D 5F 89 8B 8D 8F 99 9B 9D 9F C9 CB CD CF D9 DB DD DF
15 10 09 0B 29 2B 49 4B 69 6B 89 8B A9 AB C9 CB E9 EB
16 10 00 02 10 12 40 42 50 52 80 82 90 92 C0 C2 D0 D2
17 20 01 03 05 07 21 23 25 27 41 43 45 47 61 63 65 67 81 83 85 87 A1 A3 A5 A7 C1 C3 C5 C7 E1 E3 E5 E7
18 10 13 17 1B 1F 53 57 5B 5F 93 97 9B 9F D3 D7 DB DF
19 10 12 16 32 36 52 56 72 76 92 96 B2 B6 D2 D6 F2 F6
这6位的有效数据完全组合为0x40000000 (1,073,741,824)个,就其中的可打印字符组合保守地按1/3计算,也还有0x15555555 (357,913,941)个,保存为文件约有9GB。所以不要小看!
bFilterOn是一个开关,用于过滤那些不可能正确输入到题目编辑框的不可打印组合。只保留Key编码后字符范围在0x20~0x7E之间的组合。也会过滤掉Key为一些怪异的有效中文组合,题目能够通过。
Thend的帖子里有个还原得较好的C源码,可视为题目的命令行版本,稍微完善一下也可以作为验证程序。
其中有两处需要修改补充:1) Key第二次变换的条件及位数;2) 增加可能发生的Name的第二次变换。
我也写了一个验证脚本,奇怪的是脚本验证通过了,有极少数Key在题目里却显示错误答案。后来才发现它是用_sprintf函数来复制对话框的Name和Key,很奇怪的用法。
而这些出问题的Key包含字符'%',这就带来不确定性,要处理的话很麻烦,干脆过滤掉了事。算是一个陷阱吧!
bOutputToFile也是一个开关,决定是否将结果输出到文件,方便验证程序使用。
以下为一些输出示例。
Name:
White_CrackMe_JUST_For_Fun
Keys:
Do_You_Like_MistHill!*(/pf
Do_You_Like_MistHill!*(/pb
Do_You_Like_MistHill!*(/tb
Do_You_Like_MistHill!*(/tf
Do_You_Like_MistHill!*(-rd
Do_You_Like_MistHill!*(-r`
Do_You_Like_MistHill!*(-v`
Do_You_Like_MistHill!*(-vd
Do_You_Like_MistHill!**-rd
Do_You_Like_MistHill!**-r`
Do_You_Like_MistHill!**-v`
Do_You_Like_MistHill!**-vd
Do_You_Like_MistHill!**/pf
Do_You_Like_MistHill!**/pb
Do_You_Like_MistHill!**/tb
Do_You_Like_MistHill!**/tf
...
Name:
White_CrackMe_JUST_For_Fun
Keys:
Do_You_Like_52PoJie_Do=>!W
Do_You_Like_52PoJie_Do=>!S
Do_You_Like_52PoJie_Do=<#U
Do_You_Like_52PoJie_Do=<#Q
Do_You_Like_52PoJie_Do=<'Q
Do_You_Like_52PoJie_Do=<'U
Do_You_Like_52PoJie_Do?<#U
Do_You_Like_52PoJie_Do?<#Q
Do_You_Like_52PoJie_Do?<'Q
Do_You_Like_52PoJie_Do?<'U
Do_You_Like_52PoJie_Do?>!W
Do_You_Like_52PoJie_Do?>!S
Do_You_Like_52PoJie_Dm?<#U
Do_You_Like_52PoJie_Dm?<#Q
...
Name:
White_CrackMe_JUST_For_Fun
Keys:
Do_You_Like_It_Or_NOT__8/Y
Do_You_Like_It_Or_NOT__8/]
Do_You_Like_It_Or_NOT__8+]
Do_You_Like_It_Or_NOT__8+Y
Do_You_Like_It_Or_NOT__:-[ ; 我更喜欢这个
Do_You_Like_It_Or_NOT__:-_
Do_You_Like_It_Or_NOT__:)_ ; 题目示例Key
Do_You_Like_It_Or_NOT__:)[
Do_You_Like_It_Or_NOT_M*=K
Do_You_Like_It_Or_NOT_M*=O
Do_You_Like_It_Or_NOT_M*9O
Do_You_Like_It_Or_NOT_M*9K
...
Name:
Weare52PoJiOg]HWQV]Ddmml?-
Keys:
Do_You_LikNtfBX_cBGGFMLOXK
Do_You_LikNtfBX_cBGGFMLOXJ
Do_You_LikNtfBX_cBGGFMLO\O
Do_You_LikNtfBX_cBGGFMLO\N
Do_You_LikNtfBX_cBGGFMLMZI
Do_You_LikNtfBX_cBGGFMLMZH
Do_You_LikNtfBX_cBGGFMLM^M
Do_You_LikNtfBX_cBGGFMLM^L
Do_You_LikNtfBX_cBGGFMMNYJ
...
Name:
Weare吾爱__yQk~ag`krR[[ZI[
Keys:
Do_You_LikmWEa{|@addenol{h
Do_You_LikmWEa{|@addenol{i
Do_You_LikmWEa{|@addenonyj
Do_You_LikmWEa{|@addenonyk
Do_You_LikmWEa{|@addenon}n
Do_You_LikmWEa{|@addenon}o
Do_You_LikmWEa{|@addennmzi
Do_You_LikmWEa{|@addennmzh
...
最后一个,Name里有中文,题目会崩溃;而Key里含有中文却不会。不知道原因。
感谢White提供这个有趣的游戏!
祝各位圣诞快乐!
MistHill的每篇文章都值得好好研读,分析得不错。 本帖最后由 MistHill 于 2013-12-26 17:59 编辑
还是说一下吧!
这个CM暴露出的问题,是每个写程序的人都可能碰到、而且经常犯的错误,吸取经验和教训总是有益的。从某种程度上讲,我觉得比分析和解答CM自身更有意义!
前面提到Name里的中文字符会造成目标崩溃,仔细看下来后发现,原因不是中文引起的,西文同样可能使目标崩溃。
在程序对话框的编辑框里随便输入点儿字符串会“搞死”程序,这无论如何是说不过去的,看来程序有很严重的Bug。
这次问题出在Key和Name的第二次变换那两个循环:
0040161F|. 8B7424 20 MOV ESI, pKey(After Variation #1)
00401623|. 83C9 FF OR ECX, 0xFFFFFFFF
00401626|. 8BFE MOV EDI, ESI pKey
00401628|. 83C4 08 ADD ESP, 0x8
0040162B|. F2:AE REPNE SCAS BYTE PTR ES:
0040162D|. 8B5424 1C MOV EDX, pName(After Variation #1)
00401631|. F7D1 NOT ECX
00401633|. 49 DEC ECX ECX=strlen(pKey)
00401634|. 8BFA MOV EDI, EDX pName
00401636|. 8BD9 MOV EBX, ECX EBX=strlen(pKey)
00401638|. 83C9 FF OR ECX, 0xFFFFFFFF
0040163B|. F2:AE REPNE SCAS BYTE PTR ES:
0040163D|. F7D1 NOT ECX
0040163F|. 49 DEC ECX ECX=strlen(pName)
00401640|. 894C24 18 MOV , ECX ECX->, save to local variable
00401644|> 8A0C30 / MOV CL, ESI=pKey, EAX=0 Init.
00401647|. 300C28 | XOR , CL EBP=pPreset, Decoding #1 with Key
0040164A|. 83F8 0A | CMP EAX, 0xA
0040164D|. 75 13 | JNZ SHORT 00401662
0040164F|. 8D7B F6 | LEA EDI, EDI=strlen(pKey)-0A, EDI: unsigned int
00401652|. 3BF8 | CMP EDI, EAX
00401654|. 72 0C | JB SHORT 00401662 <- *** BUG!
00401656|> 8A0C06 |/MOV CL, <- Memory access violation if strlen(pKey) < 0A
00401659|. 304C06 01 ||XOR , CL <- write
0040165D|. 40 ||INC EAX
0040165E|. 3BC7 ||CMP EAX, EDI <- *** Never stop!
00401660|. 76 F4 |\JBE SHORT 00401656
00401662|> 40 | INC EAX
00401663|. 83F8 0A | CMP EAX, 0xA
00401666|. 76 DC \ JBE SHORT 00401644
00401668|. 8B4C24 18 MOV ECX, ECX<-strlen(pName)
0040166C|. B8 0A000000 MOV EAX, 0xA EAX=0A Init.
00401671|> 8A1C10 / MOV BL, EDX=pName
00401674|. 301C28 | XOR , BL EBP=pPreset, Decoding #2 with Name
00401677|. 83F8 14 | CMP EAX, 0x14
0040167A|. 75 13 | JNZ SHORT 0040168F
0040167C|. 8D79 EC | LEA EDI, EDI=strlen(pName)-14, EDI: unsigned int
0040167F|. 3BF8 | CMP EDI, EAX
00401681|. 72 0C | JB SHORT 0040168F <- *** BUG!
00401683|> 8A1C02 |/MOV BL, <- Memory access violation if strlen(pName) < 14
00401686|. 205C02 01 ||AND , BL <- write
0040168A|. 40 ||INC EAX
0040168B|. 3BC7 ||CMP EAX, EDI <- *** Never stop!
0040168D|. 76 F4 |\JBE SHORT 00401683
0040168F|> 40 | INC EAX
00401690|. 83F8 14 | CMP EAX, 0x14
00401693|. 76 DC \ JBE SHORT 00401671
00401695|. 8BCE MOV ECX, ESI在00401644和00401671处的外层循环是分别用Key和Name解码预设值得到答案;现在我们重点关注00401656和00401683两处内层循环。
搞这么个Key和Name的第二次变换无非是想增加一点解Key的难度。实际上也没啥作用,我在Keygen的脚本中写有一个针对Key第二次变换的逆过程,后来发现调用这个子过程与否对获得正确结果没太大影响,为节省运行时间就将那个调用注释掉了。
进入这两个循环的条件是:strlen(pKey)-0A >= 0和strlen(pName)-14 >= 0;换言之,即strlen(pKey) >= 0A和strlen(pName) >= 14。
“换言之”是我的第一反应,看起来strlen(pKey)=01~09,strlen(pName)=01~13都不会进入循环。可事实却完全不是我们想象的那样。
比如strlen(pKey)=09或strlen(pName)=13时,09-0A或13-14都等于-1,在32位系统里表示为0xFFFFFFFF。进入循环的条件就变成:FFFFFFFF与0A或14比较,紧接着的那条JB指令(00401654和00401681)就出问题了,这是一定要进循环的!
而结束循环的条件是:EAX++ > FFFFFFFF(0040165E和0040168B)。将永远不可能退出循环滴!于是它会读写4G内存空间的每一个地址,直到出现“内存访问冲突”,操作系统忍无可忍、不得不终止这个失控的进程。
由于Key和Name的第一次变换算法为两相邻字符进行异或,只要两个相邻字符相同,就得到一个字符串结尾NULL。在中文字符串的情况下不易察觉:比如“吾爱破解”中的“破”字,其两字节内码为0xC60 xC6,同样得到一个NULL字符。
下面这张表可用于对比测试:
0123456789ABCDEF0123456789
<--------> Key 紧邻字符相同崩溃区
<-----------------> Name 紧邻字符相同崩溃区
Name: White_CrackMe_JUST_For_Fun 标准输入
Key: Do_You_Like_It_Or_NOT__:)_
会造成崩溃的Name:
White_CrackMe_JUST__or_Fun strlen(pName)=13
White_CrackMe_JUSTFFor_Fun strlen(pName)=13
WWite_CrackMe_JUST_For_Fun strlen(pName)=01
会造成崩溃的Key:
Do_You_Liie_It_Or_NOT__:)_ strlen(pKey)=09
Do_You_Lkke_It_Or_NOT__:)_ strlen(pKey)=09
DD_You_Like_It_Or_NOT__:)_ strlen(pKey)=01
oo_You_Like_It_Or_NOT__:)_ strlen(pKey)=01显然,写程序的人用错了数据类型声明,没有达到预期的设想。编译器只是忠实地将源代码变成机器指令。
先将目标这两处:
0040165472 0C JB SHORT 00401662
0040168172 0C JB SHORT 0040168F改为:
004016547C 0C JL SHORT 00401662
004016817C 0C JL SHORT 0040168F再试试,就不会出问题了。不要忽视这一个字节的差异:JB用于无符号数,而JL用于有符号数!
模仿题目写了一个命令行的东西,数据声明部分如下:
void __cdecl sub_4015E0(char *pKey, char *pName, int DisplayMode)
{
char *pPreset;
unsigned int i;
/* Correct data type declaration: */
int nKeyLength;
int nNameLength;
/* Wrong data type declaration: */
// unsigned int nKeyLength;
// unsigned int nNameLength;
...数据声明分别为int和unsigned int时,生成的代码对比如下:
正确(int): #错误(unsigned int):
004015238A0C30 / MOV CL, #004015238A0C30 / MOV CL,
00401526300C28 | XOR , CL #00401526300C28 | XOR , CL
0040152983F8 0A | CMP EAX, 0xA #0040152983F8 0A | CMP EAX, 0xA
0040152C75 16 | JNZ SHORT 00401544 #0040152C75 13 | JNZ SHORT 00401541
0040152E8D4B F6 | LEA ECX, #0040152E8D7B F6 | LEA EDI,
004015313BC8 | CMP ECX, EAX #004015313BF8 | CMP EDI, EAX
004015337C 0F | JL SHORT 00401544 #0040153372 0C | JB SHORT 00401541
004015358D7B F6 | LEA EDI, #004015358A0C06 |/MOV CL,
004015388A0C06 |/MOV CL, #00401538304C06 01 ||XOR , CL
0040153B304C06 01 ||XOR , CL#0040153C40 ||INC EAX
0040153F40 ||INC EAX #0040153D3BC7 ||CMP EAX, EDI
004015403BC7 ||CMP EAX, EDI #0040153F76 F4 |\JBE SHORT 00401535
0040154276 F4 |\JBE SHORT 00401538 #0040154140 | INC EAX
0040154440 | INC EAX #0040154283F8 0A | CMP EAX, 0xA
0040154583F8 0A | CMP EAX, 0xA #0040154576 DC \ JBE SHORT 00401523
0040154876 D9 \ JBE SHORT 00401523 #004015478B4C24 14 MOV ECX,
0040154A8B4C24 14 MOV ECX, #0040154BB8 0A000000 MOV EAX, 0xA
0040154EB8 0A000000 MOV EAX, 0xA #004015508A1C10 / MOV BL,
004015538A1C10 / MOV BL, #00401553301C28 | XOR , BL
00401556301C28 | XOR , BL #0040155683F8 14 | CMP EAX, 0x14
0040155983F8 14 | CMP EAX, 0x14 #0040155975 13 | JNZ SHORT 0040156E
0040155C75 16 | JNZ SHORT 00401574 #0040155B8D79 EC | LEA EDI,
0040155E8D79 EC | LEA EDI, #0040155E3BF8 | CMP EDI, EAX
004015613BF8 | CMP EDI, EAX #0040156072 0C | JB SHORT 0040156E
004015637C 0F | JL SHORT 00401574 #004015628A1C02 |/MOV BL,
004015658D79 EC | LEA EDI, #00401565205C02 01 ||AND , BL
004015688A1C02 |/MOV BL, #0040156940 ||INC EAX
0040156B205C02 01 ||AND , BL#0040156A3BC7 ||CMP EAX, EDI
0040156F40 ||INC EAX #0040156C76 F4 |\JBE SHORT 00401562
004015703BC7 ||CMP EAX, EDI #0040156E40 | INC EAX
0040157276 F4 |\JBE SHORT 00401568 #0040156F83F8 14 | CMP EAX, 0x14
0040157440 | INC EAX #0040157276 DC \ JBE SHORT 00401550
0040157583F8 14 | CMP EAX, 0x14
0040157876 D9 \ JBE SHORT 00401553从对比可以看到:1) JL和JB的差异;2) 右边的错误代码与目标代码几乎完全一致!
下面说说附件里的东西。
Date Time SizeName
-----------------------------------------------
2013-12-25 18:23:00 5968WDC Verifier.c
2013-12-25 22:41:47 16384WDC Verifier.exe在命令提示符下不带参数运行会显示用法:
A Verification Program for "White Decrypt & CrackMe"
By MistHill, 25/12/2013
SYNTAX:
"WDC Verifier.exe" "Name" "Key"
or
"WDC Verifier.exe" "Log file created by my ODbgScript T228419.Keygen.osc"
You can get the script at:
http://www.52pojie.cn/thread-230338-1-1.html第一种用法类似题目的命令行版本,即输入Name和Key参数会显示结果,自己检查与标准答案是否匹配。
运行实例:
"WDC Verifier.exe" "White_CrackMe_JUST_For_Fun" "Do_You_Like吾爱破解_V__^As"
INFO:
Something Is always Changing !
"WDC Verifier.exe" "White_CrackMe_JUST_For_Fun" "Do_You_Like吾爱破解_V__\O]"
INFO:
Something Is always Changing !
"WDC Verifier.exe" "Weare_ChildBjPEZ\[PII@@AR@" "Do_You_LikeMMwb}{|wn%,,->,"
INFO:
Something Is always changing !
"WDC Verifier.exe" "Weare吾爱__yQk~ag`krR[[ZI[" "Do_You_LikmWEa{|@addenol{h"
INFO:
Something Is always Changing !因为已经修正了已知Bug,所以不会崩溃,也能正确处理字符'%'。
但受命令提示符传递给程序main函数的命令行参数的影响,通常Name和Key字符串必须用西文字符'"'封闭。在Name或Key存在'"'字符的情况下,见以下示例:
Name: Weare_ChildBjPEZ\[PII@@AR@
Key1: Do_You_LikeMCQD[]ZQH*##"1#
Key2: Do_You_LikeMCQD[]ZQH+""#0"
"WDC Verifier.exe" "Weare_ChildBjPEZ\ZQH*##""1#"
INFO:
Something Is always changing !
"WDC Verifier.exe" "Weare_ChildBjPEZ\ZQH+\"\"#0\"
INFO:
Something Is always changing !即在只有一个'"'的情况下,多加一个'"'字符;在有多个'"'的情况下,不使用'"'进行封闭,其中的'"'字符前加脱字符'\'。
上面例子中,有几个答案是不正确的,注意'c'和'C'的区别。这是最早调试脚本时的记录,现在一时找不到适合的样本。
总之,这时使用命令行是很麻烦的。对这个感兴趣的可参阅:Everyone quotes command line arguments the wrong way[http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx]。
还是把Name和Key放到文件比较方便,第二种用法:
只需一个参数,为Key的记录文件,其格式用Keygen脚本生成一个就清楚了。
文件里包含一个Name和多个Key,进行批量自动验证。合格的Key后面会显示'V'字符,而无效的Key会以'X'字符表示。
mark 下次看!
页:
[1]