SourceInsight4093:
SourceInsight是比较强大的软件,如果觉得这个软件有用,请购买正版,发布这个纯属娱乐。
关于SourceInsight
Source Insight不仅是一个强大的程序编辑器,而且是面向项目开发的程序编辑器和代码浏览器,它拥有内置的对C/C++, C#和Java等程序的分析。能分析源代码并在工作的同时动态维护它自己的符号数据库,并自动显示有用的上下文信息。运行截图如下图所示:
##过程
先使用查壳工具PEID查壳,然后通过试运行sourceinsight查看会提示什么,然后决定使用什么方法来破解,一般来讲,输入注册码不正确跳出提示框,这样可以通过查找字符串进而找到关键算法,通过下面尝试,这样方法确实可行,但是并不能完全破解,只能绕过一个判断。商业软件毕竟是别的软件不一样的,sourceinsight有在线检查黑名单制度,而且相较于之前版本,黑名单检测地方在不断增多,找到黑名单检测处并且一一注释才能够最终完成破解。
###1.查壳
先用PEID查壳,发现没有加壳,但是入口地址和偏移与之后在IDA里面看到的不一样,这是win7下的ASLR技术,ASLR技术是对缓冲区溢出的安全保护技术,对堆栈、共享库等映射随机化,这样提高安全,但是不利于我们分析,IDA动态调试的时候不能返回,相对OD显得不那么方便,但是IDA反汇编出来的地址就是没有随机化的地址,是最原始程序的地址,而OD是随机化的,所以通过参考IDA,并且尝试关闭win7下的ASLR服务,这样就可以使用OD进行动态调试,使用IDA反汇编查看源码,这样可以快随方便的找到关键判断,加速破解进度。下图为查壳结果:无壳
###2.关闭ASLR
如果想使用OD动态调试,那么必须要关闭ASLR服务,因为每次调试的断点,注释会随着动态地址变化而消逝,所以必须要关闭ASLR服务。下图为没关闭ASLR服务之前的OD加载地址与IDA加载地址效果图:可以明显看到OD的地址漂移。
网上下载ASLR关闭工具进行关闭是不行的,后来Google上找到一篇帖子,介绍了方法,通过win+R,regedit,HKEY_LOCAL_MACHINE->SYSTEM->CurrentControlSet->Control->Session
Manager->Memory Management,右键,新建一个dword变量,命名为MoveImages,将其值置为0,重启电脑即可。如下图为修改注册表中的数值:
关闭ASLR后效果如下图,这样可以通过IDA找到关键处,OD动态调试辅助进行破解。
###3.运行程序寻找突破口
下图为未破解之前截图:
第一个选项是导入注册码,第二选项是试用30天,第三个选项是导入license,如果不选的话,会直接退出程序。尝试输入错误的注册码看会提示是什么,
跳出一串字符如上图,然后通过IDA查找字符串,Shift+F12打开字符串界面,按下ctrl+f,然后输入上面提及的字符中not correct,搜索结果如下图:
第二条记录是刚刚输入不正确注册码跳出的界面的提示,双击进入,下图所示,可以看到,字符串和上面输入错的字符跳出来的提示语是一样的。可以看到第一句The serial number you entered is not correct. A serial number for下面有DATA XREF,后面跟了一个函数,鼠标放在上面会出现函数入口指令,双击进入
下图所示,双击进入的地方,这个地址就是这串字符压入栈的地方:
IDA最强大的一面就是反汇编,接下来就是体现其强大的一面,按F5会将这段汇编指令尽量按照源码反汇编出来,按下F5以后效果如下图所示:
可以看到上面的一个关键if判断,满足条件,就会进入到下一个if判断,两个if都满足的话,说明这个序列号是3.x版本的,第二个if如果不满足,则会进入else,见下图:
可以明显看到,第67行,第二个if判断没有成立进入到这里就会显示上面提到的注册不成功的提示,而sub_40A8E0这个函数就是实现显示提示的功能,IDA查看sub_40A8E0这个函数非常方便,双击这个函数就会自动跳到这个函数,如下图,想要再回到之前的函数,点击左上角返回键即可。
上面代码可以看到是输出一串字符的,结合上面截图中的代码分析,传入的参数a1是序列号错误的提示字符串,代码中有调用其他的函数,就不一一展开说明。
回到上上图中的代码中,只要代码不进入if判断,把显示提示序列号错误的字符跳过,那么很可能找到判断序列号是否正确的关键判断。(注:上上图中代码还有一部分没有截图展示出来,都是和这个if平行的判断,跳过了这个if,可以进入到下面的判断,下面判断中用到了替换查表的方法判断,表是代码中原有存在的,查看代码可以看文章末尾附录)
通过上面的分析,关键call就是sub_50C8E0(&MultiByteStr,dword_66BAE8 + 1544, dword_66BAE8 + 1548, dword_66BAE8 + 1540, 1)这个函数,双击这个函数进入函数主体,下图可以看到函数中所有的代码:
接下来分析这段代码
1 | int __cdecl sub_50C8E0(char *a1, int a2, int a3, int a4, int a5)//a1为输入的序列号,如果任一判断不成立return 0,那么之前的判断会直接跳到序列号失败的那个call |
总结以上代码,首先是判断序列号的合法性,必须满足如下格式(其中X表示未知字符):
S(0-9)(T|B|S|U)X-X(R|G|D|F)XX-XXXX-XXXX
其中第二位,根据版本要求必须是4,第三位中T 表示 试用版,B表示Beta版,S表示Standard版,U未知。因此按照本软件的要求,序列号格式应该如下:
S4SX-X(R|G|D|F)XX-XXXX-XXXX
可以看到是do-while循环四次来做的,而当中最关键的是byte_5F6E68[]这个预先存于内存中的表取值,双击byte_5F6E68[],可以看到表中的值,下图展示了一部分当中的值,
最后四个字节可以算出来,可以尝试穷举(直接遍历 byte_5F6E68[]中的字符即可),通过这样的方法来计算出最后四个字节,但是由于时间有限,没有尝试这种方法,直接利用OD单步调试算出,然后重新运行程序,输入序列号,如下图所示:call的50C0B0这个函数,计算最后四位
进入到50C0B0这个函数,如下图:
过程中没有做过多的指令分析,程序运行起来,第一次输入S4SV-UFWT-ZPR6-XXXX,鼠标选中循环之外的第一条语句,如上图橙色框。选中之后直接按F4运行到这一句,然后看下面堆栈区,就计算出来最后四位,这样重新运行程序,然后就可以输入正确的序列号,跳过这一条验证, 计算结果如下图所示:
图中已标出计算结果,寄存器EAX也有计算结果,寄存器EBP中存的是前15位,可以看到前十五S4SV-UFWT-ZPR6计算出来的最后四位是F336。下次输入S4SV-UFWT-ZPR6-F336即可跳过这个判断。输入序列号,
过程中跳过了以上的判断,但是,没有激活成功,效果如下图所示:
这时遇到瓶颈了,在很长一段时间里,无法取得进展。IDA动态调试不是很方便,所以一直使用OD进行动态调试,进行寻找突破口。在经过一段时间寻找之后,在OD动态调试到以下函数时候,下图所示:
可以明显在堆栈区看到我键入的信息,并且能看到一个文件夹,但是当我打开文件夹时,里面不存在这个文件。无法找到这个文件,在经过很多次调试之后还是无果。只是键入序列号的话,无法激活,这时候,程序一直运行在一段地址之内,无法跳出,而屏幕上也一直显示正在激活请稍后,
但是就像文章开头分析一样,还有可以选使用试用30天和导入license的选项,导入license是需要选择文件夹的,这是伏笔。选择试用试一下,选择试用之后,C:\ProgramData\Source Insight\4.0这个文件夹下多了一个文件,si4.lic文件,这时候打开文件分析,格式大致如下:
清晰看到,之前填的用户名,组织,邮箱,时间在里面,下面signature字眼很关键,说明这里使用了数据签名,然后可能在某处存在进行核对,如果正确的话就激活成功。将系统状态还原至还未试用的版本,通过多次调试,查阅资料之后,发现程序使用的Windows Cryptography APIs进行签名:在调试的时候发现调用了这个系统API,系统API怎么计算的具体怎么计算没有跟踪。OD动态跟踪之后,系统调用API如下图所示:
通过网上查阅,“签名”和“签名验证”是通过公钥体系来实现的,所以程序中一定存在公钥,在不断寻找之后,在地址0063F648处,发现了公钥,如下图所示:
找到公钥之后,只要找到什么地方对公钥试用,以及签名最后在哪里比对,可能最终完成破解,继续选择键入序列号, 这时候程序依然处于上面那一段地址内循环,此时放弃了键入序列号破解程序的想法。文中一开始提到的三个方法,只剩最后一个导入license没用了,在使用试用版本发现si4.lic文件中格式之后,自己造了一个license文件,放入C:\ProgramData\Source
Insight\4.0文件夹中,然后选择导入license,如下图:
选择license文件导入,导入之后,先会进入判断序列号是否正确的断点,序列号是通过之前计算出来的,所以不会有问题。如下图:
在检查完序列号之后,会一一对license文件中所有值进行一一计算验证,一路继续F7F8调试,在调试很久之后,发现很关键的字眼,如下图:
上图中两个Asc码很显眼,可能接下来的重要数据就在这里,继续调试。再往下发现一处正在读入license中签名的值,如下图:
再往下是继续将si4中数据进行读入并进行存储,这里只截取其中两处展示,如下图:
将除签名之外所有的数据读入:
将signature存在堆栈:
再往下调试,出现了非常非常非常重要的函数,经过对license文件的计算,这个函数的返回值决定了是否能成功激活,如下图:
进入函数主体进行分析,如下图:
可以明显看到导入公钥了,这里计算非常关键,此时借助IDA反汇编查看代码,分析思路然后再次回到OD去调试尝试,这样两个工具相结合加快了破解的进展。
图中展示借用公钥计算,然后返回结果,总共可以返回的结果有472、473、474、475、472、200.代码贴出如下:
1 | int __cdecl sub_50C3D0(BYTE *pbData, DWORD dwDataLen, BYTE *pbSignature, DWORD dwSigLen) |
经过多次尝试,发现只有当返回值为200(十六进制为0xC8)的时候,软件这时候被激活,但是过程想要让它直接运行到使其直接返回C8是有困难的,所以这里直接将值改为0xC8。如下图:
运行结果可以看到已经激活,结果如下图:
点击确定之后,在help->about Source Insight中,可以看到已经激活的信息,并且激活的信息也与license中一致。
###4.后续
程序破解完了会有黑名单检测,如下图
上图中会在C:\Users\liyuf\AppData\Local\Source
Insight\4.0中出现一个.dat文件,这个文件记录了你是黑名单,然后再打开Source Insight会发现下图所示:
细心点可以发现,这与之前键入注册码提示的错误不一样的地方是,没有下两行的选项了,为了应对黑名单检测,总共需要修改四处地方:
1)
0050E393 85C0 TEST EAX, EAX
==>
0050E393 31C0 XOR EAX, EAX
2)
0050E645 85C0 TEST EAX, EAX
==>
0050E645 31C0 XOR EAX, EAX
3)
0050DF68 76 69 JBE SHORT 0050DFD3
==>
0050DF68 EB 69 JMP SHORT 0050DFD3
4)
0050F1BB 85C0 TEST EAX, EAX
==>
0050F1BB 31C0 XOR EAX, EAX
修改完之后保存:
再次打开程序,界面如下:
###附录
附上sub_50F5A0()函数代码:
1 | int __cdecl sub_50F5A0(int a1, int a2, int a3) |
参考链接:
https://www.52pojie.cn/thread-713308-1-4.html