11.4.10 处理用户名
跳转到402AC4,你会发现这里的代码并不那么简单,还有不少代码需要我们进一步分析。代码首先对户名字符串执行了某种数值运算处理:对字符串中的每一个字符进行48求模,然后将这个模用于对该字符执行左移位操作。这里的左移位操作中有一个值得关注的细节,那就是它是在一个专用的、而且有点复杂的函数内实现的。这里是移位函数的代码列表:
这段代码好像是一个64位的左移操作。CL寄存器中是要左移的位数,EDX:EAX中存放的是要完成移位的数。在整个64位左移位的操作中,函数使用了SHLD指令。SHLD指令并不是真正的64位移位指令,因为它不左移EAX,它只是把EAX用作位的“源”移位到EDX中(用EAX的高位来填补EDX左移位后空出来的位)。这就是为什么函数在左移的位数少于32位的情况下(译注:大于等于32位的话EAX中的所有位就都补到EDX中了),还需要在EAX上使用一个SHL指令对EAX进行移位。
在这个64位左移位函数返回之后,程序即进入下面的代码:
图11.16给出了这段代码的数学解释。本质上,Defender是在为用户名准备一个独一无二的64位整数:它取出用户名中的每个字符,然后将它加到这个64位整数中的某个位置上去。
函数继而对输入的序列号做了与处理用户名类似的转化,只是这次转化要稍微简单一些。这次,它只是将这个16位的十六进制数直接转化成64位整数。得到这个整数后,程序就将从用户名和序列号转化来的两个64位数压栈,然后调用401EBC处的函数。此时,你一定希望在401EBC处的代码是你可以轻松理解的某种验证逻辑。若果真是这样的话,破解Defender就指日可待了!