0x1前言:
因本人最近创业,公司刚成立,需要联系一些没有制作过网站、App等的公司法人代表来增加自己的客户,于是想到了企业名录这样的一个软件,后来百度了一下,较为有名的有卓迅和百分百的软件,后来也就选了百分百吧,发现收费800,让我这个刚开始的创业狗有些心疼,于是就有了今天的这篇文章,不足之处,还望各为指点迷津,毕竟第一逆向.NET的软件。
0x2主程序:
1、百分百客户综合采集软件8.3(启动程序.exe)【MD5: D4F99FB54F24E7E3AAEB363E7CD2471F】
2、/Plug/bfbqf.AppMain.dll【MD5: F79795D12DFC61038B6BCA7F1821E482】
3、/Plug/bfbqf.AppLogin.dll【MD5: D60205FE302D8F5D947965C8C3C97D51】
4、/Plug/bfbqf.AppObject.dll【MD5: 1109D47D611D277EE32FB8FED43E2B4E】
5、/Plug/bfbqf.PublicLib.dll【MD5: 836F482D6E1F83FE890B97AA4D94B484】
0x3侦查:
-0x3-01工具:
1、ProcessMonitor
2、PEID
3、ScanId
-0x3-02
软件采用.NET编写
于是利用ScanId看看它有没有加什么混淆,然而并没有发现什么
于是运行它,在ProcessMonitor上看它的一些进程信息
如此一来,可以大致地分析出,该软件主要是调用bfbqf.AppMain.dll、bfbqf.AppLogin.dll、bfbqf.AppObject.dll、bfbqf.PublicLib.dll来实现主要的功能,不过,我们有必要也反编译一下exe的程序,毕竟是可执行程序嘛。
0x04反编译:
-0x04-01工具:
1、dnSpy
-0x04-02过程:
可以看到所有的函数都是检查的功能,如果要K掉更新什么的,直接可以在函数体内入手,但这不是我们今天的主题,下面开始分析今天的主角——Dll。
--0x04-02-01bfbqf.AppLogin.dll
看文件名的话,经验告诉我,先分析bfbqf.AppLogin.dll会比较好一点。
该Dll存在5个程序集,我们进入bfbqf.AppLogin的程序集里面去愁一愁。
定位到private bool Login(string UserName, string Password)和public bool Login(string UserName, string Password, out UserCenter.TUserInfo UserInfo)的函数,这里需要注意的是这两个函数的参数不一样,第二个函数会把返回值传给UserCenter.TUserInfo UserInfo
可以清楚地看到,一句关键的赋值比较“bool flag2 = this.OutUserInfo.UserType == UserCenter.UserTypeEnum.Test;”它的意思就是把this.OutUserInfo.UserType赋值给flag2并且与UserCenter.UserTypeEnum.Test做比较,知道了这个,我们来看一看UserCenter.UserTypeEnum存放了哪些东西。
可以大致地判断出,程序的用户会有三个状态,分别是Test(测试用户)、User(普通用户)和VIP(收费用户),如此一来,我们的目的,就是要让我们的变成VIP。再来看一看OutUserInfo.UserType存放了一些什么东西吧。
可以看出它存放了很多关于用户的一些Flag,其中最为主要的就是UserType,它最终会指向Public enum UserTypeEnum,然后返回其中的值(Test、User、VIP),也就是说,最终影响用户状态的就是它,也就是public bool Login(string UserName, string Password, out UserCenter.TUserInfo UserInfo)的第三个参数,知道了这些,我们在该函数体内下一个断点,来动态调试它看看。然而可惜的是发现并没有断下来,于是进入到另一个Login函数,也就是private bool Login(string UserName, string Password)。
发现这里有一个接口,而这个接口成功地亮瞎了我的眼,不知道大家有没有发现,这两个函数,往下面都是大同小异的,主要就是用flagN来接收返回值,不管怎样,我们现在这个函数体内下一个断点运行看一看。
已经成功断下来了,我的UserName和PassWord已经获取到了。发现在这里才开始调用public bool Login(string UserName, string Password, out UserCenter.TUserInfo UserInfo)的,F11进去瞅瞅,看看我们在上面的猜想是否正确。
这一句的意思就是把UserName、PassWord、HardDeviceUtils.GetDeviceCode().Replace(" ", "")、DateTime.Now.Ticks,填写到{0}、{1}、{2}、{3}中,然后调用UserCenter.GetURLText()函数把Format到的数据当作参数以POST的方式提交给Login.php,最后把返回值给text,后面的两个参数大概就是和硬盘以及时间有关系的了,这里必须得一步一步地分析,我们F11跟进去瞅瞅。
首先GetDeviceCOde(),然会HardDeviceUtils.GetHardDiskID(),应该是硬盘ID,继续F11。
这里已经是属于RWXComLibrary.APISdk.Utils了,我们就不用理会了,因为我看不懂,也懒得看懂它,反正就是一路F10,最后要看到返回值。
可以清楚地看到,最后返回给我的硬盘ID是5VMB24HJ。然后继续F11,继续分析咯。
同上,不必理会,因为反正也看不懂,不过最后还是得留意它的返回值。一路F11之后,会进入到public static string Concat(string str0, string str1)函数,这里是关键点,看不懂也得看!
具体的意思我已经在上面的代码中给出了注释,来看一下最终的返回值吧。
成功返回出一个接口,我们直接在浏览器里面访问一下,看看回显结果是啥样子的。
OK,差不多已经分析出来了,把这一串Json赋值给text。
我们继续F10单步往下走,看看它验证的过程是什么样子的。
这里请注意UserType,它存在login_Json.data里面,而后面的login_Json.msg返回的是“Success”,然后可以拿刚才获取到的Json来对比一下,也就是取msg和UserType的值。
我们继续F10单步往下走,程序会回到private bool Login(string UserName, string Password)的位置,而text最终返回为Success,我刚开始的时候想,直接把text赋值为Success不就得了?然而并没有什么卵用,不信你们试试看,不然我也不会写这篇文章了。我们继续往下看。
后面又通过flag3接收Success,之后又有一个关键的比较bool flag4 = this.OutUserInfo.UserType == UserCenter.UserTypeEnum.Test和bool flag5 = this.OutUserInfo.UserType == UserCenter.UserTypeEnum.User;
这里大家应该都能明白了吧?总之,最后不是UserCenter.UserTypeEnum.VIP,就给你弹个框,然后就限制你的操作行为,看了很心疼。
这里因为限制上上传图片的数量,就只能传刚开始的图片了。
既然如此,知道了它是如何判断你的UserType的,那么就好办了,不是访问接口之后会返回一个Json吗?然后再读取里面的msg和UserType吗?那好的很啊,我们现在把这一串Json撸下来,然后把里面的UserType手动改成VIP,然后再搭建本地服务器,不就过了它的网络验证了吗?不就完事儿了吗?不就通关了吗?
{"msg":"Success","data":{"uid":"f2eeb691-c292-11e6-bcbf-002590e21c76","UserName":"howsk","LoginTime":"2016\/12\/15 14:51:47","UserType":"VIP","ExpTime":"2016\/12\/16 14:51:47","SubscribeStatus":"0","VerifyCode":"urvpckwrpt","LoginUID":"f782f923897e9414829f0e917111fea3","AgentID":"125135"}}
好了,环境搭建好了,现在我们来开始动手修改吧!(限制了上传图片的数量,只能贴代码了)
然而很遗憾,发现根本没有什么卵用,依然是熟悉的画面,依然是同一个弹框,初恋般的感觉。
不过没有关系,我们大致地分析出来了它的检查原理,这里忘记了还有其它几个Dll,我这里就不卖关子了,我们直接到bfbqf.PublicLib.dll里面看一看吧。在UserCenter里面又发现了一处Login的函数,通过上面的讲解,我们继续下断点,最后得出的结论是,修改这里的接口为本地链接方可达到破解的目的。
放在本地的一个目的就可以改变任意用户名,任意密码,全部都是任意的,然后所有的限制功能也可以用了。
0x05总结:
1、作者并没有对软件进行混淆之类的保护。
2、在整个逆向过程中,可以发现,在这个接口上,根本没有再次验证硬盘ID和时间,这也说明了接口中的Login.php需要的参数没有做严格的要求和验证。
3、作者在对服务器交互的时候并没有采用Token或者Session来做验证,从而恶意者可以投机取巧。
*注:
1、该文章首发52破解论坛,其它地方看到此文章,均属盗版。
2、该文章仅供参考和学习,切勿用于非法和商业用途,否则一切后果与本人无关。
3、最后祝自己公司开业大吉,生意兴隆。
--官方论坛
www.52pojie.cn
--推荐给朋友
公众微信号:吾爱破解论坛
或搜微信号:pojie_52