- 预备知识
- 一、相关实验
- 二、异或运算
- 实验目的
- 实验环境
- 实验步骤一
- 实验步骤二
- 实验步骤三
本实验要求您已经认真学习和完成了《CTF REVERSE练习之算法分析1》。
二、异或运算异或运算是一种数学运算,英文为Exclusive OR,常常缩写成XOR。异或运算针对二进制0和1而言,其数学符号为⊕,异或运算的法则如下:
0⊕0=0 1⊕0=1 0⊕1=1 1⊕1=0
除了二进制以外,异或运算可以扩展到任意数据类型。因为我们所接触的任何数据都可以使用二进制来表示,所以可以对二进制里面的所有位上的数据都进行两两的异或 *** 作,如15的二进制表示为1111,而100的二进制表示为1100100,因此15⊕100的计算过程如下:
异或运算的性质:
1)A ⊕ B = B ⊕ A 2)A ⊕ A = 0 3)A ⊕ 0 = A 4)A ⊕ B ⊕ A = 0 ⊕ B = B
在编程语言中,通常使用^符号来表示异或运算,比如C和Python都使用这一符号。
实验目的1)掌握异或运算的特性。
2)掌握IDA的基本 *** 作,学会使用IDA进行静态分析。
3)学会编写简单的注册机(Keygen)程序。
服务器:Windows XP,IP地址:随机分配
辅助工具:PEiD,IDA
题目描述:
主机C:Reverse5目录下有一个CrackMe5.exe程序,运行这个程序的时候会提示输入用户名和注册码进行注册,当输入正确的用户名和注册码时,会d出成功提示的消息框,请对CrackMe5.exe程序进行逆向分析和调试,尝试编写一个注册机程序。
考察意图:
这个CrackMe程序要求输入一个用户名以及注册码进行注册,注册码通过用户名经过一定的算法变换得到,主要考察逆向分析中简单的算法分析过程,以及如何通过IDA提取关键数据。
通过API交叉引用快速定位关键代码:
运行这个程序后要求输入一个用户名和注册码进行注册,当注册失败的时候,程序将d出一个消息框提示不正确,如图所示:
那么我们可以通过IDA的交叉引用功能来定位这一块的代码。使用IDA载入CrackMe5.exe程序,待分析结束后,通过imports TAB页面找到MessageBoxA,双击来到反汇编视图,在MessageBoxA按下X按键对其进行交叉引用查找,经过一个一个进行分析,我们发现sub_401490就是我们所要找的关键函数,我们通过F5得到这个函数的伪代码。通过对伪代码添加注释,以及对变量进行重命名 *** 作,我们得到如下的代码片段:
由于IDA Hex-Rays Decompiler插件的原因,上述伪代码中计算字符串长度的地方仍然存在一些问题。
通过上面的伪代码的分析,我们发现只do while循环这里的代码的功能不是很清楚。程序要求用户名和注册码的长度必须相等,且长度必须大于0且小于等于33。
分析关键算法:
通过实验步骤一的分析,我们发现一个do while循环对字符串进行了处理,代码如下:
v1 = 0; do { if ( ((unsigned __int8)*(&szUsername + v1) ^ (unsigned __int8)byte_423678[v1]) != *(&szPassword + v1) ) break; ++v1; }while ( v1 < _dwNameLen ); if ( v1 != _dwNameLen ) { // 错误 } else { // 正确 }
仔细分析上面循环过程中的代码,其中*(&szUsername + v1)实际上相当于szUsername[v1],相应的,*(&szPassword + v1)实际上相当于szPassword[v1],因此这里if语句的条件判断可以简化为:szUsername[v1] ^ byte_423678[v1] == szPassword[v1],根据异或运算的性质,上述条件可以转换为:szPassword [v1] ^ byte_423678[v1] == szUsername [v1],也就是不断的从注册码中取出一个字符,和byte_423678中对应下标的字符进行异或运算,看是否和用户名中对应的字符一致,需要全部匹配才表明注册是成功的。
在IDA中双击byte_423678,切换到IDA View视图,就可以看到内容了,如图所示:
我们需要把byte_423678的内容提取出来,为:
1,2,3,4,1,5,1,5,1,3,6,5,4,8,5,3,1,2,3,4,5,3,5,7,2,3,2,4,8,2,5,6,4。
这就是我们找到的XOR密钥数组。
编写注册机:
现在我们已经将程序的注册算法分析清楚了,下面就可以编写一个注册机了。程序的注册算法为:将用户名的每一个字符与XOR密钥数组中的对应下标的字符进行异或运算,产生注册码字符串对应的字符。用户名的长度不能超过33个字符。
我们编写这样一段Python脚本即可:(代码位于C:Reverse5Keygen.py)
def crack(username): key = [1, 2, 3, 4, 1, 5, 1, 5, 1, 3, 6, 5, 4, 8, 5, 3, 1, 2, 3, 4, 5, 3, 5, 7, 2, 3, 2, 4, 8, 2, 5, 6, 4] pwd = [] for i in xrange(0, len(username)): pwd.append(chr(ord(username[i]) ^ key[i])) return "".join(pwd) if __name__ == "__main__": while True: username = raw_input("input username:") serial = crack(username) print "serial: %s" % serial
我们输入用户名Wins0n,就可以得到注册码为Vkmw1k,输入程序可以成功注册,如图所示:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)