【看雪论坛.腾讯公司2008软件安全竞赛】我的第二题分析过程及注册机
原文:https://www.pediy.com/kssd/pediy10/74166.html
标 题: 【看雪论坛.腾讯公司2008软件安全竞赛】第一阶段◇第二题分析及注册机
作 者: mstwugui
点击确定按钮后程序执行到403C00,读取name和key之后跳入401113
首先是调用403897校验403271至40389F是否有0xCC INT 3断点,如果有直接终止当前进程
接下来继续校验从403271开始的0x76E个字节,如果有代码改动则终止当前进程
接着开始name格式校验,长度为12的无重复小写字符串(不包含'z'),校验失败则显示"username?"对话框并回到返回函数
下一步是排序name, 将name的每个字节转变为他在原始name字符串从小到大排列后的位置
然后校验key的格式,长度至少为53并且每个字符都在0x30-0x33之间,校验失败则显示"key?"对话框并回到返回函数
接着调用401087计算根据key和排序过的name重新计算name,计算出来的结果为长度为24的字符串
如果上一步返回的字符串第n个字节不等于排序过的name的第n个字节(0<=n<12),或不等于第12+n个字节,则显示"wrong!"对话框并回到返回函数
否则显示"ok!"
关于401087也就是4022A0的算法粗看一下有些长,我也没有什么好办法,为了让自己省事一些,先把整个函数用C描述出来
现在我们可以开始分析key的格式,首先是注意到有一个长度为12的局部数组,而且代码中有很多a*4+b的定位操作,因此很显然为了覆盖到每一个字节并且不重叠,key的第一个字节应该是3
由于字符"ijkl"的触发条件都是value1==value2, value1和value2分别是从key[1]*4和key[2]*4在临时数组中的连续4个值的和,因此很显然key[1]和key[2]只能是0或1,并且这两个字节必须不同,考虑到后面的
如果key[1]是1,而key[0]是0话,那么在4<=offset<8的情况下,temp[0]-> temp[4]的原始值为 0x1E, temp[4]->temp[7]当中的4个字节有一个不为0x1E, 此时我们无法确保将value1的值转变为小于 value2, 这是因为我们先对value1需要用到的内存空间操作,随后才对value2需要用到的内存空间操作
因此key[1]应该是0,key[2]应该是[1]
接下来根据"ijkl"字符的触发条件,得到
回过头来我们继续看一下在value1不等于value2时对临时数组所做的调整
考虑到'a'和'e'的触发条件是修改后的value1==value2,因此此处修改应该只对偏移地址1,2,3起作用,所以得到
这里再进一步考虑key[1]和key[2]的值已经确定,因此得到
接下来根据a和e的触发条件得出
以及
再根据"bcd"的触发条件得出
最后根据"fgh"的触发条件得出
呵呵,都要结束了还没有谈到netwind大侠的h圈套,这个h确实看起来很像是个bug,但其实是有解的,只要我们把name中的第8大的字节放到第7大的字节之后这个问题也就迎刃而解了,仔细看一下源代码
这里其实有两次输出操作,if...else之后还有一个单独的if,因此这个h放在g后面就一帆风顺的通过了
从整个分析可以看出,name和key其实是独立的,并没有互相依赖,也就是说可以随意选取各一个合法的name和key都能得到ok!