<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Architecting Life &#187; Crack</title>
	<atom:link href="http://xujiwei.com/blog/tags/crack/feed/" rel="self" type="application/rss+xml" />
	<link>http://xujiwei.com/blog</link>
	<description>Just do it</description>
	<lastBuildDate>Thu, 05 Apr 2012 17:19:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>[ASM] 是男人就下100层，交出序列号来</title>
		<link>http://xujiwei.com/blog/get-serial-of-shinanrenjiuxia100cen/</link>
		<comments>http://xujiwei.com/blog/get-serial-of-shinanrenjiuxia100cen/#comments</comments>
		<pubDate>Sat, 17 Jun 2006 05:07:40 +0000</pubDate>
		<dc:creator>Xu Jiwei</dc:creator>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[ASM]]></category>
		<category><![CDATA[Crack]]></category>

		<guid isPermaLink="false">http://tmp.xujiwei.com/blog/?p=113</guid>
		<description><![CDATA[<a href="http://xujiwei.com/blog/get-serial-of-shinanrenjiuxia100cen/" title="[ASM] 是男人就下100层，交出序列号来"></a>某天（前天：），看了两个小时高数（具体不详：）之后，想放松一下，找到《是男人就下100层》，打开，玩了两把，突然发现今天怎么看那个“注册”的按钮特别不爽，OK，Crack it！ 常规步骤，用PEid侦壳，用VC4.x写的，这样方便了，脱壳都不用。接着祭出用户级调试法宝——Ollydbg，加载《是男人就下100层》，万事俱备，踏上征途！ 按F9运行程序，等程序窗口出来，点一下任务栏上按钮，结果竟然中断了，CPU窗口一看，原来是一条INT3指令，麻烦的东西，NOP掉。继续F9运行，好，这下可以把程序窗口调到前面了。切换到程序窗口，点注册，出现填写用户名和序列号的窗口。用户名填HotHeart，序列号填一个123456，确定，当然不会成功，要不我就可以去买彩票了^_^。弹出一个错误提示框，内容是日文的……意思大概是序列号无效。既然有提示框，那就好办，回到Ollydbg，下断点bp MessageBoxA，再次换到程序窗口点确定。YES！顺利中断，切回Ollydbg看看代码： ; 获取对话框中控件文本 00407A78  PUSH 100 00407A7D  LEA EAX,DWORD PTR SS:[EBP-204] 00407A83  PUSH EAX 00407A84  PUSH 3EB 00407A89  MOV EAX,DWORD PTR SS:[EBP+8] 00407A8C  PUSH EAX 00407A8D  CALL DWORD PTR DS:[&#60;&#38;USER32.GetDlgItemText&#62;] 00407A93  LEA EAX,DWORD PTR SS:[EBP-204] 00407A99  PUSH EAX 00407A9A  CALL 是男人就.00407C5F 00407A9F  ADD ESP,4 00407AA2  TEST EAX,EAX 00407AA4  JNZ 是男人就.00407AE1 ; 从资源中载入字符串，是注册失败的提示信息 00407AAA  PUSH 100 00407AAF  LEA EAX,DWORD PTR SS:[EBP-104] &#8230;<p class="read-more"><a href="http://xujiwei.com/blog/get-serial-of-shinanrenjiuxia100cen/">Read more &#187;</a>]]></description>
			<content:encoded><![CDATA[<a href="http://xujiwei.com/blog/get-serial-of-shinanrenjiuxia100cen/" title="[ASM] 是男人就下100层，交出序列号来"></a><div class="post-content">

某天（前天：），看了两个小时高数（具体不详：）之后，想放松一下，找到《是男人就下100层》，打开，玩了两把，突然发现今天怎么看那个“注册”的按钮特别不爽，OK，Crack it！

常规步骤，用PEid侦壳，用VC4.x写的，这样方便了，脱壳都不用。接着祭出用户级调试法宝——Ollydbg，加载《是男人就下100层》，万事俱备，踏上征途！

按F9运行程序，等程序窗口出来，点一下任务栏上按钮，结果竟然中断了，CPU窗口一看，原来是一条INT3指令，麻烦的东西，NOP掉。继续F9运行，好，这下可以把程序窗口调到前面了。切换到程序窗口，点注册，出现填写用户名和序列号的窗口。用户名填HotHeart，序列号填一个123456，确定，当然不会成功，要不我就可以去买彩票了^_^。弹出一个错误提示框，内容是日文的……意思大概是序列号无效。既然有提示框，那就好办，回到Ollydbg，下断点bp MessageBoxA，再次换到程序窗口点确定。YES！顺利中断，切回Ollydbg看看代码：

<span style="color: #008000;">; 获取对话框中控件文本</span>

00407A78  <span style="color: #0000d0;">PUSH</span> 100

00407A7D  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-204]

00407A83  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407A84  <span style="color: #0000d0;">PUSH</span> 3EB

00407A89  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407A8C  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407A8D  <span style="color: #0000d0;">CALL</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[&lt;&amp;USER32.GetDlgItemText&gt;]

00407A93  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-204]

00407A99  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407A9A  <span style="color: #0000d0;">CALL</span> 是男人就.00407C5F

00407A9F  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407AA2  <span style="color: #0000d0;">TEST</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span>

00407AA4  <span style="color: #0000d0;">JNZ</span> 是男人就.00407AE1

<span style="color: #008000;">; 从资源中载入字符串，是注册失败的提示信息</span>

00407AAA  <span style="color: #0000d0;">PUSH</span> 100

00407AAF  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-104]

00407AB5  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407AB6  <span style="color: #0000d0;">PUSH</span> 4

00407AB8  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[40E200]

00407ABD  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407ABE  <span style="color: #0000d0;">CALL</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[&lt;&amp;USER32.LoadStringA&gt;]

<span style="color: #008000;">; 下面就是弹出出错提示框的代码了</span>

00407AC4  <span style="color: #0000d0;">PUSH</span> 10

00407AC6  <span style="color: #0000d0;">PUSH</span> 是男人就.0040D270

00407ACB  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-104]

00407AD1  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407AD2  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407AD5  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407AD6  <span style="color: #0000d0;">CALL</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[&lt;&amp;USER32.MessageBoxA&gt;]

00407ADC  <span style="color: #0000d0;">JMP</span> 是男人就.00407B22

看到407AD6这里调用了MessageBoxA，往上看，很舒服地看到这一句：

00407AA4  <span style="color: #0000d0;">JNZ</span> 是男人就.00407AE1

一个很值得注意的跳转，是不是关键跳转呢，把JNZ改成JZ，再试试，点确定，出错提示是没有了，不过那个注册按钮还是在的，也就是说这句不是关键跳转，没有涉及到序列号的部分。再往上看，发现看在这个跳转之前有获取对话框中数据：

00407A8D  <span style="color: #0000d0;">CALL</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[&lt;&amp;USER32.GetDlgItemText&gt;]

那么在这里中断看看它得到了什么。F2下断点，切到程序窗口，输入用户名和序列号，确定，预料之中断下来。接着F8单步运行，再来一个YES！它得到的是123456，也就是我填的序列号，接着把序列号所在的地址存到EAX中，再将EAX压入堆栈，紧接着又一个call，嗯，这个call很值得怀疑，跟进！下面就是整个call的函数的代码了，有点长：）

00407C5F  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EBP</span> <span style="color: #008000;">; C函数标准开头</span>

00407C60  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EBP</span>,<span style="color: #ff0000;">ESP</span>

00407C62  <span style="color: #0000d0;">SUB</span> <span style="color: #ff0000;">ESP</span>,4   <span style="color: #008000;">; 局部变量，分析后面的代码可知是用来作计数器的</span>

00407C65  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EBX</span> <span style="color: #008000;">; 保护寄存器</span>

00407C66  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">ESI</span>

00407C67  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EDI</span>

从代码开始可明显看出这是一个标准的C函数，接着往下看。碰到堆栈操作，这值得注意，因为call过来时有压入过一个参数，指向序列号起始地址：

00407C68  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]  <span style="color: #008000;">; 这句之后EAX指向序列号</span>

00407C6B  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407C6D  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+7]    <span style="color: #008000;">; 得到序列号第8位</span>

00407C70  <span style="color: #0000d0;">TEST</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span> <span style="color: #008000;">; 判断是否为0</span>

00407C72  <span style="color: #0000d0;">JE</span> 是男人就.00407C7F    <span style="color: #008000;">; 是刚跳转</span>

00407C78  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; EAX清零</span>

00407C7A  <span style="color: #0000d0;">JMP</span> 是男人就.00407DC4    <span style="color: #008000;">; 这里跳到函数结尾</span>

00407C7F  <span style="color: #0000d0;">MOV</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-4],0    <span style="color: #008000;">; 计数器清零</span>

00407C86  <span style="color: #0000d0;">JMP</span> 是男人就.00407C8E

上面的代码的作用是得到序列号第8位，并判断是否为0，学过C的人都知道在C里字符串是以0表示结束的，那么就知道这里三句是用来判断用户输入的序列号是否大于7位的了，如果大于7位，就会将EAX清零并跳到函数结束的地方，而前面已经知道，在调用这个函数之后，如果返回值为0则序列号验证失败，所以序列号是7位或7位以内的。我填的123456，是6位，所以没有跳到函数结束，接着往下分析：

00407C8B  <span style="color: #0000d0;">INC</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-4]    <span style="color: #008000;">; 计数器加1</span>

00407C8E  <span style="color: #0000d0;">CMP</span> <span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-4],7  <span style="color: #008000;">; 判断计数器是否大于7</span>

00407C92  <span style="color: #0000d0;">JGE</span> 是男人就.00407CC3       <span style="color: #008000;">; 大于等于就</span>

00407C98  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>-4] <span style="color: #008000;">; 取计数器值到EAX</span>

00407C9B  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8] <span style="color: #008000;">; 取序列号地址到ECX</span>

00407C9E  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+<span style="color: #ff0000;">ECX</span>] <span style="color: #008000;">; 取序列号第N位到AL，N为计数器值</span>

00407CA1  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; 压入堆栈，调用处理函数</span>

00407CA2  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9  <span style="color: #008000;">; 将1位序列号从ASCII转换成二进制值</span>

00407CA7  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4   <span style="color: #008000;">; 恢复堆栈</span>

00407CAA  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span> <span style="color: #008000;">; ECX清零</span>

00407CAC  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span> <span style="color: #008000;">; 将处理过的1位序列号存到CL</span>

00407CAE  <span style="color: #0000d0;">CMP</span> <span style="color: #ff0000;">ECX</span>,24  <span style="color: #008000;">; 判断是否大于0&#215;24</span>

00407CB1  <span style="color: #0000d0;">JLE</span> 是男人就.00407CBE  <span style="color: #008000;">; 大于就出错了</span>

00407CB7  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; 大于0&#215;24，跳到函数结束，返回0</span>

00407CB9  <span style="color: #0000d0;">JMP</span> 是男人就.00407DC4

00407CBE  <span style="color: #0000d0;">JMP</span> 是男人就.00407C8B  <span style="color: #008000;">; 继续处理下一位</span>

很清楚的，上面这段代码是用来判断序列号中每一位是否符合要求，是什么要求呢，看到在每取得1位序列号之后有一句call：

00407CA2  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

这个调用得看看，F7跟进：

00407DC9  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EBP</span>

00407DCA  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EBP</span>,<span style="color: #ff0000;">ESP</span>

00407DCC  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EBX</span>

00407DCD  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">ESI</span>

00407DCE  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EDI</span>

00407DCF  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span>

00407DD1  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]    <span style="color: #008000;">; 取参数，即1位序列号</span>

00407DD4  <span style="color: #0000d0;">CMP</span> <span style="color: #ff0000;">EAX</span>,61

00407DD7  <span style="color: #0000d0;">JL</span> 是男人就.00407DE8

<span style="color: #008000;">; 判断是否大于0&#215;61，如果对ASCII码表熟悉的话可以知道0&#215;61对应的是a</span>

<span style="color: #008000;">; 小于则跳转，好，上面那个判断应该不是用来判断这个字符是否为小写字母了</span>

<span style="color: #008000;">; 不是则跳到后面继续处理，是则进行下面的处理过程</span>

00407DDD  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; EAX清零</span>

00407DDF  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]    <span style="color: #008000;">; 取字符</span>

00407DE2  <span style="color: #0000d0;">SUB</span> <span style="color: #ff0000;">EAX</span>,20     <span style="color: #008000;">; 减0&#215;20，变大写字母</span>

00407DE5  <span style="color: #0000d0;">MOV</span> <span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8],<span style="color: #ff0000;">AL</span> <span style="color: #008000;">; 保存</span>

<span style="color: #008000;">; 不管是否为小字字母，经过上面的判断和处理都会变成大写字母，继续进行处理</span>

00407DE8  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; EAX清零</span>

00407DEA  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]    <span style="color: #008000;">; 取字符</span>

00407DED  <span style="color: #0000d0;">CMP</span> <span style="color: #ff0000;">EAX</span>,41

00407DF0  <span style="color: #0000d0;">JL</span> 是男人就.00407E01

<span style="color: #008000;">; 判断是否大于，0&#215;41对应的ASCII字符为A</span>

<span style="color: #008000;">; 小于则跳转，说明这里是判断字符是否为大写字母</span>

<span style="color: #008000;">; 不是则跳到后面继续处理，是则进行下面的处理过程</span>

00407DF6  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; EAX清零</span>

00407DF8  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]    <span style="color: #008000;">; 取字符</span>

00407DFB  <span style="color: #0000d0;">SUB</span> <span style="color: #ff0000;">EAX</span>,7      <span style="color: #008000;">; 减去7</span>

00407DFE  <span style="color: #0000d0;">MOV</span> <span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8],<span style="color: #ff0000;">AL</span> <span style="color: #008000;">; 保存</span>

<span style="color: #008000;">; 如果不是大写字母就跳到这里了，当然如果是大写字母的话</span>

<span style="color: #008000;">; 经过上面的处理过程同样要进行下面的处理过程</span>

00407E01  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; EAX清零</span>

00407E03  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]    <span style="color: #008000;">; 取字符</span>

00407E06  <span style="color: #0000d0;">SUB</span> <span style="color: #ff0000;">EAX</span>,30     <span style="color: #008000;">; 减去0&#215;30</span>

00407E09  <span style="color: #0000d0;">JMP</span> 是男人就.00407E0E  <span style="color: #008000;">; 函数结束</span>

00407E0E  <span style="color: #0000d0;">POP</span> <span style="color: #ff0000;">EDI</span>

00407E0F  <span style="color: #0000d0;">POP</span> <span style="color: #ff0000;">ESI</span>

00407E10  <span style="color: #0000d0;">POP</span> <span style="color: #ff0000;">EBX</span>

00407E11  <span style="color: #0000d0;">LEAVE</span>

00407E12  <span style="color: #0000d0;">RETN</span>

连贯起来看可以知道这个处理函数的过程是这样的：

char是否为小写字母 -&gt; 是则减去0&#215;20变成大写字母，不是则保持不变 -&gt; char是否为大写字母 -&gt; 是则减去7，不是则保持不变 -&gt; char减0&#215;30

再联系数字和字母的ASCII码值，9为0&#215;39，A为0&#215;41，0&#215;41-0&#215;39=7，OK，可以知道这个函数是把1位序列号变成二进制值，字符0到9对应数值0到9，字母全部转换成大写字母，并且字母A对应10，B对应11，后面依次类推。

弄明白了字符到数字的函数，继续看序列号验证的代码，可以看到在得到二进制值之后，又来了一句：

00407CB1  <span style="color: #0000d0;">JLE</span> 是男人就.00407CBE  <span style="color: #008000;">; 大于就出错了</span>

00407CB7  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; 大于0&#215;24，跳到函数结束，返回0</span>

00407CB9  <span style="color: #0000d0;">JMP</span> 是男人就.00407DC4

00407CBE  <span style="color: #0000d0;">JMP</span> 是男人就.00407C8B  <span style="color: #008000;">; 继续处理下一位</span>

0&#215;24转换成十进制就是36，刚好是10个数字加26个字母，也就是说序列号只允许数字与字母，并且要7位，否则就通不过这个验证了。弄明白了这个，继续往下看：

00407CC3  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407CC6  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+5]  <span style="color: #008000;">; 取序列号第6位</span>

00407CC9  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407CCA  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9      <span style="color: #008000;">; 转换成数值</span>

00407CCF  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407CD2  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">EBX</span>

00407CD4  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">BL</span>,<span style="color: #ff0000;">AL</span> <span style="color: #008000;">; 序列号第6位值保存到EBX</span>

00407CD6  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407CD9  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+2]  <span style="color: #008000;">; 取序列号第3位</span>

00407CDC  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407CDD  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9      <span style="color: #008000;">; 转换成数值</span>

00407CE2  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407CE5  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407CE7  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span> <span style="color: #008000;">; 序列号第3位值保存到ECX</span>

00407CE9  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">ESI</span>,24   <span style="color: #008000;">; ESI=0&#215;24</span>

00407CEE  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">ECX</span>+<span style="color: #ff0000;">EBX</span>*2+1D] <span style="color: #008000;">; EAX=ECX+EBX*2+1D</span>

00407CF2  <span style="color: #0000d0;">CDQ</span> <span style="color: #008000;">; 扩展成64位</span>

00407CF3  <span style="color: #0000d0;">IDIV</span> <span style="color: #ff0000;">ESI</span> <span style="color: #008000;">; 除以0&#215;24</span>

00407CF5  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">EDX</span> <span style="color: #008000;">; EDX为余数，存到EBX</span>

00407CF7  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407CFA  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>]  <span style="color: #008000;">; 取序列号第1位</span>

00407CFC  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407CFD  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9    <span style="color: #008000;">; 转换成数值</span>

00407D02  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407D05  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407D07  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span> <span style="color: #008000;">; 序列号第1位值存到ECX</span>

00407D09  <span style="color: #0000d0;">CMP</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">ECX</span> <span style="color: #008000;">; EBX=ECX?</span>

00407D0B  <span style="color: #0000d0;">JNZ</span> 是男人就.00407DBD  <span style="color: #008000;">; 不等，验证失败，跳到函数结束</span>

<span style="color: #008000;">; 头有些大了，用心看发现这里在判断序列号是否符合规则</span>

<span style="color: #008000;">; (第3位+第6位*2+0x1D)%0&#215;24==第1位</span>

<span style="color: #008000;">; 跟着又是两段代码类似的，不难发现也是判断，不过规则有小小的不同</span>

<span style="color: #008000;">; 下面这段的判断规则是</span>

<span style="color: #008000;">; (第2位+第5位*2+0x1D)%0&#215;24==第7位</span>

00407D11  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407D14  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+4]

00407D17  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407D18  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

00407D1D  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407D20  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">EBX</span>

00407D22  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">BL</span>,<span style="color: #ff0000;">AL</span>

00407D24  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407D27  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+1]

00407D2A  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407D2B  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

00407D30  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407D33  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407D35  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span>

00407D37  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">ESI</span>,24

00407D3C  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">ECX</span>+<span style="color: #ff0000;">EBX</span>*2+1D]

00407D40  <span style="color: #0000d0;">CDQ</span>

00407D41  <span style="color: #0000d0;">IDIV</span> <span style="color: #ff0000;">ESI</span>

00407D43  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">EDX</span>

00407D45  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407D48  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+6]

00407D4B  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407D4C  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

00407D51  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407D54  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407D56  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span>

00407D58  <span style="color: #0000d0;">CMP</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">ECX</span>

00407D5A  <span style="color: #0000d0;">JNZ</span> 是男人就.00407DBD

<span style="color: #008000;">; 下面这段的判断规则是</span>

<span style="color: #008000;">; (第1位+第7位*2+0x1D)%0&#215;24==第4位</span>

00407D60  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407D63  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+6]

00407D66  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407D67  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

00407D6C  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407D6F  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">EBX</span>

00407D71  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">BL</span>,<span style="color: #ff0000;">AL</span>

00407D73  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407D76  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>]

00407D78  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407D79  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

00407D7E  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407D81  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407D83  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span>

00407D85  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">ESI</span>,24

00407D8A  <span style="color: #0000d0;">LEA</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">ECX</span>+<span style="color: #ff0000;">EBX</span>*2+1D]

00407D8E  <span style="color: #0000d0;">CDQ</span>

00407D8F  <span style="color: #0000d0;">IDIV</span> <span style="color: #ff0000;">ESI</span>

00407D91  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">EDX</span>

00407D93  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff00ff;">DWORD</span> PTR <span style="color: #ff0000;">SS</span>:[<span style="color: #ff0000;">EBP</span>+8]

00407D96  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">AL</span>,<span style="color: #ff00ff;">BYTE</span> PTR <span style="color: #ff0000;">DS</span>:[<span style="color: #ff0000;">EAX</span>+3]

00407D99  <span style="color: #0000d0;">PUSH</span> <span style="color: #ff0000;">EAX</span>

00407D9A  <span style="color: #0000d0;">CALL</span> 是男人就.00407DC9

00407D9F  <span style="color: #0000d0;">ADD</span> <span style="color: #ff0000;">ESP</span>,4

00407DA2  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">ECX</span>,<span style="color: #ff0000;">ECX</span>

00407DA4  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">CL</span>,<span style="color: #ff0000;">AL</span>

00407DA6  <span style="color: #0000d0;">CMP</span> <span style="color: #ff0000;">EBX</span>,<span style="color: #ff0000;">ECX</span>

00407DA8  <span style="color: #0000d0;">JNZ</span> 是男人就.00407DBD

上面这三段就是序列号验证的主要部分了，写个示意表达式，用b1~b7表示序列号第1至7位转换后的数值，T为临时变量：

T = b3 + b6*2 + 1D

b1 = T mod 24 ?

T = b2 + b5*2 + 1D

b7 = T mod 24 ?

T = b1 + b7*2 + 1D

b4 = T mod 24 ?

如果三次判断均通过，那么整个序列号验证函数就回返回1，表示验证通过：

00407DAE  <span style="color: #0000d0;">MOV</span> <span style="color: #ff0000;">EAX</span>,1   <span style="color: #008000;">; EAX=1</span>

00407DB3  <span style="color: #0000d0;">JMP</span> 是男人就.00407DC4  <span style="color: #008000;">; 跳到返回</span>

00407DB8  <span style="color: #0000d0;">JMP</span> 是男人就.00407DC4

00407DBD  <span style="color: #0000d0;">XOR</span> <span style="color: #ff0000;">EAX</span>,<span style="color: #ff0000;">EAX</span> <span style="color: #008000;">; 任何验证的情况下均返回0</span>

00407DBF  <span style="color: #0000d0;">JMP</span> 是男人就.00407DC4

00407DC4  <span style="color: #0000d0;">POP</span> <span style="color: #ff0000;">EDI</span>

00407DC5  <span style="color: #0000d0;">POP</span> <span style="color: #ff0000;">ESI</span>

00407DC6  <span style="color: #0000d0;">POP</span> <span style="color: #ff0000;">EBX</span>

00407DC7  <span style="color: #0000d0;">LEAVE</span>

00407DC8  <span style="color: #0000d0;">RETN</span>

到这里就差不多了，序列号验证函数已经分析完成，它的验证规则也知道了，接着是写注册机了，不过我一开始没想到怎么随机产生一个序列号，只好把正确的序列号全列出来了，看了一下，有4万多个……我用C写了个列序列号的程序，用的穷举法，列出每一个序列号，判断是否可用，如果可用就打印出来，程序清单如下：

<span style="color: #0000d0;">#include</span> &lt;stdio.h&gt;

<span style="color: #0000d0;">int</span> main()

{

<span style="color: #0000d0;">char</span> bin2char(<span style="color: #0000d0;">int</span> bin);

<span style="color: #0000d0;">int</span> tmp,b1,b2,b3,b4,b5,b6,b7;

<span style="color: #ff0000;">printf</span>(<span style="color: #808080;">&#8220;register codes:\n&#8221;</span>);

<span style="color: #0000d0;">for</span>(b1=0;b1&lt;36;b1++)

<span style="color: #0000d0;">for</span>(b2=0;b2&lt;36;b2++)

<span style="color: #0000d0;">for</span>(b3=0;b3&lt;36;b3++)

<span style="color: #0000d0;">for</span>(b4=0;b4&lt;36;b4++)

<span style="color: #0000d0;">for</span>(b5=0;b5&lt;36;b5++)

<span style="color: #0000d0;">for</span>(b6=0;b6&lt;36;b6++)

<span style="color: #0000d0;">for</span>(b7=0;b7&lt;36;b7++)

{

tmp = b3 + b6*2 + 0x1D;

<span style="color: #0000d0;">if</span> (b1!=tmp%0&#215;24) <span style="color: #0000d0;">break</span>;

tmp = b2 + b5*2 + 0x1D;

<span style="color: #0000d0;">if</span> (b7!=tmp%0&#215;24) <span style="color: #0000d0;">break</span>;

tmp = b1 + b7*2 + 0x1D;

<span style="color: #0000d0;">if</span> (b4!=tmp%0&#215;24) <span style="color: #0000d0;">break</span>;

<span style="color: #ff0000;">printf</span>(<span style="color: #808080;">&#8220;%c%c%c%c%c%c%c\n&#8221;</span>,

bin2char(b1),bin2char(b2),bin2char(b3),bin2char(b4),bin2char(b5),bin2char(b6),bin2char(b7));

}

}

<span style="color: #0000d0;">char</span> bin2char(<span style="color: #0000d0;">int</span> bin)

{

<span style="color: #0000d0;">if</span>(bin&lt;10) <span style="color: #0000d0;">return</span>(bin+0&#215;30);

<span style="color: #0000d0;">else</span> <span style="color: #0000d0;">return</span>(bin-10+0&#215;41);

}

函数bin2char是序列号验证过程中字符转数值的逆过程。

是男人就下100层的破解就到此结束了，后来我又看了一下序列号的规律，发现第7位总是为0，而第4位决定第1位，而第3位与第6位，第2位与第5位分别为一组。这样，随机产生b2,b3,b4就可以生成一个序列号了。另外，也可用暴力破解的方式，在序列号验证函数中直接将EXA=1并返回，这样不论什么序列号都能通过验证了：）

OK，大功告成。写的有些啰嗦，第一次写破解的文章，有错误也是难免的，欢迎指正^_^，vipxjw#163.com。

</div>
]]></content:encoded>
			<wfw:commentRss>http://xujiwei.com/blog/get-serial-of-shinanrenjiuxia100cen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

