第一次写分析文章,第一是分享自己的分析过程,还有一个就是对自己做这道题的一个总结吧。。。
首先打开main函数,发现fgets获取输入,FILE*结构体就是stdin,OD动态跟发现也是我输入的字符串,所以确认这就是输入点
这是最基本的判断,接下来调用了一个thiscall的函数,传了局部变量的一个指针,这里猜测这个局部变量是一个类
进去之后使用了指针后面偏移0x200C和0x2008的DWORD数据,把它赋值为GetTickCount的返回值,然后发现又调用了一个子函数
跟进那个子函数,还有第一个dword是虚表
第一步,这个函数把[1026](把this看成dword*)往后1024个DWORD赋值为了0-1023
然后bit_proc_toTickCount根据之前用GetTickCount存储在这个class里面的值做了一些位处理,姑且算他是伪随机生成器,然后进行一个数组打乱的算法,用OD看一下也的确是乱着的0-1023
最后,倒序复制[1026]后1024个dword到[2]后的1024个dword
初步分析这个类的结构如下
调用完刚才的函数之后(八成就是构造函数了),又调用了一个函数,传入了输入作为参数
这个就是遍历输入字符串,然后根据下标转换成数字,比方说输入“123...”,第一次循环得到的就是1,第二次20,第三次300...
然后把这个v跟着this传到另外一个函数里面去
接下来看critical_401580的内容,顺便看了看xref发现这个函数只有一处引用
这个循环呢仔细看看其实也不难分析,比方说进来一个1234,实际会是4,30,200,1000这样进来(注意这样的话实际在控制台的输入是4321,当然不够八位这里不考虑就举个栗子),他会把4放在[0],3放在[1],2放在[2],1放在[3],而且下标永远不能超过结构体偏移为4的那个整形,如果位数大于了那个数,就会把它++。比方说rec是2,输入1234,循环到2的时候,i>=rec(我们姑且先把+4命名为rec),会把[2]清0,然后rec++。
这里要注意的是,这个存储的方式不是用单个数组。比方说[0],真正用到的是arr1[arr2[0]]来存放,因为arr2里面的值永远在0-1023之间,所以不会越过下标,可以把它理解为两次映射,这可能是作者的一种混淆方式。
实际调用这个函数的时候,传进来的v会是x x0 x00 x000 x0000。。。x是1-9的数字
所以如果不溢出的话,如果我输入192837465
这个类就会按如下方式保存
arr1[arr2[0]] 1
arr1[arr2[1]] 9
arr1[arr2[2]] 2
arr1[arr2[3]] 8
......
溢出的话就不一定是x00...的形式了,因为那样的话要对0x100000000取模,现在暂时不考虑溢出的情况,但不排除溢出的可能性,因为最多能有20位。不过就算溢出,也会使得这个类保存某个数,只不过这个数不直接是输入的数了
接下来再看看这个make_e_smaller_than_10
如注释所写,他会把所有0到rec-1的数都弄得小于10,如果大了,就把多出来的部分/10放在后面,然后自己%10,如果rec要爆了,就把它++
现在就可以有灵感了,这个类很有可能是一个表示大数的类,表示方法如下
arr1[arr2[i]]存储第i位数字
如数字4567,7就存在[0]处,6在[1],以此类推,其中,rec是数字的位数
那么前面的那个函数,
就是把那个大数加上参数v,因为这样有可能会使个别数字大于等于10,所以调用make_e_smaller_than_10
好的回到main继续分析
看下multiplty2这个函数(当然现在分析到这里的时候还不知道是multiply。。因为我这个已经分析好了,所以就重命名了,,算剧透一波了。。。。)
这里又出现了一个constructor3,其实里面内容和constructor基本一样,只不过这个函数会直接把rec清0
接着分析这4个函数,在循环里面的
一个一个来,第一个发现这个hexray瞎**给我反编译,所以自己看asm。。。
分析一下发现很简单,他就是使this所存储的数等于cc3所存储的数,相当于一个赋值
那么这4个函数都分析完了,那么来看看这个multiply2为什么是乘吧。。。
嗯。。所以这玩意就是乘,至于返回值,就是基本上就会返回0,不正常的情况下(rec>=1024了,明显不会有那么大的数。。。)才会返回1
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!