逆向分析某office插件

这篇具有很好参考价值的文章主要介绍了逆向分析某office插件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

注:本文仅用于技术研究与探讨,不提供任何成品和补丁程序

收集信息

今天要逆向的是XX格子这款部分功能付费的Office插件。先安装好后打开看看,看它都有啥可以调教的功能,发现了一个VIP窗口,那这就有意思了,狠狠的开破。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

随后我们点击加入会员,点击离线登录,弹出如下窗口:

ffcell离线注册机,安全,软件工程,Powered by 金山文档

关键信息都已经取得了,那就开始进入分析环节。

因为现在微软加载项都是以vsto进行部署的,所以我们先打开目录下的vsto文件,看看它调用了哪些DLL库,vsto文件关键节选如下:

  <dependency>
    <dependentAssembly dependencyType="install" codebase="FFCell.dll.manifest" size="25452">
      <assemblyIdentity name="FFCell.dll" version="2.0.0.0" publicKeyToken="b0c5e50cded54578" language="neutral" processorArchitecture="msil" type="win32" />
      <hash>
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>HswFQTT/AEBRt6Esc2Qlgpkx1Nc=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>

不难发现其首先带调用的是FFCell.dll这个库,那我们直接开干,拖入exeinfope查壳,发现其为.NET程序并且加了混淆,如下图所示:

ffcell离线注册机,安全,软件工程,Powered by 金山文档

可以发现其为IntelliLock加密,无所谓,我会出手,but技术水平有限,就不手工脱壳了,直接拖入NET Reactor Slayer脱壳机,可以直接一键脱掉。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

脱壳机

开始分析

基本代码分析

脱壳完毕后直接拖入dnSpy开始分析,我们直接搜索“绑定”,发现找不到,于是把函数名看看,发现关于软件注册的函数并没有在这个模块里面,那我们重新猜想,把目录里面的DLL都拿来分析了下,发现除了本体FFCell.dll外,还有若干个DLL也同样加了壳,猜测这几个DLL可能也是作者原创的DLL,再次执行上述的脱壳大法后拖入dnspy分析,可以在Newmem.dll这个文件中找到关于软件注册的函数,函数名也是如此,那我们就不难推断其实这个DLL专门就是管软件注册的事情的

ffcell离线注册机,安全,软件工程,Powered by 金山文档

关于软件注册的函数

随后我们再次搜索关键字符串“绑定”,可以发现出现了结果

ffcell离线注册机,安全,软件工程,Powered by 金山文档

在多个函数中均出现了关键字符串,那无所谓我们一个个看,经过分析,发现这几个函数分别对应不同的注册方式,分别有离线和在线两种。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

首先先进行离线注册的分析,可在代码中发现确定绑定的按钮如下:

this.Button1.TabIndex = 0;
this.Button1.Text = "确定绑定";
this.Button1.UseVisualStyleBackColor = true;
this.LinkLabel1.AutoSize = true;

那我们就Button1对应的事件,长这样子:

internal virtual Button Button1
{
    get
    {
        return this.button_0;
    }
    set
    {
        EventHandler value2 = new EventHandler(this.method_2);
        if (this.button_0 != null)
        {
            this.button_0.Click -= value2;
        }
        this.button_0 = value;
        if (this.button_0 != null)
        {
            this.button_0.Click += value2;
        }
    }
}

可以看出好像method_2方法是点击这个按钮后的,无所谓是不是总之我们先跟进去看看就是,节选如下:

private void method_2(object sender, EventArgs e)
    {
        int num;
        int num4;
        object obj;
        try
        {
            IL_01:
            ProjectData.ClearProjectError();
            num = -2;
            IL_0A:
            int num2 = 2;
            string machineName = Environment.MachineName;
            IL_13:
            num2 = 3;
            string computerNo = VipRegV2Helper.GetComputerNo(machineName);
            IL_1E:
            num2 = 4;
            string text = this.TextBox1.Text;
            IL_2D:
            num2 = 5;
            if (Operators.CompareString(text, "授权码", false) != 0)
            {
                goto IL_4B;
            }
            IL_42:
            num2 = 6;
            text = "";
            IL_4B:
            num2 = 8;
            if (Operators.CompareString(text, "", false) != 0)
            {
                goto IL_7B;
            }
            IL_5F:
            num2 = 9;
            Interaction.MsgBox("授权码不能为空", MsgBoxStyle.OkOnly, "提示");
            IL_76:
            goto IL_2E3;
            IL_7B:
            num2 = 12;
            string left = this.TextBox3.Text.Trim();
            IL_91:
            num2 = 13;
            if (Operators.CompareString(left, this.VerfyImage1.code, false) == 0)
            {
                goto IL_CC;
            }
            IL_B0:
            num2 = 14;
            Interaction.MsgBox("验证码错误", MsgBoxStyle.OkOnly, "提示");
            IL_C7:
            goto IL_2E3;
            IL_CC:
            num2 = 17;
            string str = "";
            IL_D6:
            num2 = 18;
            if (VipRegV2Helper.CheckAccessCode(text, computerNo, ref str))
            {
                goto IL_11A;
            }
            IL_E9:
            num2 = 19;
            Interaction.MsgBox("授权码错误,原因:" + str, MsgBoxStyle.OkOnly, "提示");
            IL_106:
            num2 = 20;
            this.VerfyImage1.Gen();
            IL_115:
            goto IL_2E3;
            IL_11A:
            num2 = 23;
            DateTime expireDateFromAccessCode = VipRegV2Helper.GetExpireDateFromAccessCode(text);
            IL_125:
            num2 = 24;
            if (DateTime.Compare(expireDateFromAccessCode, DateTime.Now) < 0)
            {
                goto IL_1BF;
            }
            IL_13F:
            num2 = 31;
            string userNameFromAccessCode = VipRegV2Helper.GetUserNameFromAccessCode(text);
            IL_14B:
            num2 = 32;
            LoginHelper.SetLocalLogin(userNameFromAccessCode, "----");
            IL_15C:
            num2 = 33;
            VipOfflineHelper.SetLocalExpireDate(expireDateFromAccessCode);
            IL_166:
            num2 = 34;
            VipRegHelper.g_isReg = true;
            IL_170:
            num2 = 35;
            VipRegHelper.GetVipUility().SetVipValid(true);
            IL_180:
            num2 = 36;
            Interaction.MsgBox("离线绑定成功!绑定至" + expireDateFromAccessCode.ToString("yyyy年MM月dd日") + "\r\n\r\n到期后可继续申请绑定。", MsgBoxStyle.OkOnly, "离线绑定成功");
            IL_1AF:
            num2 = 37;
            this.DialogResult = DialogResult.OK;
            IL_1BA:
            goto IL_2E3;
            IL_1BF:
            num2 = 26;
            IL_1C3:
            num2 = 27;
            Interaction.MsgBox("授权码中绑定的日期已经过期", MsgBoxStyle.OkOnly, "提示");
            IL_1DA:
            num2 = 28;
            this.VerfyImage1.Gen();
            IL_1E9:
            goto IL_2E3;
            IL_1EE:
            int num3 = num4 + 1;
            num4 = 0;
            @switch(ICSharpCode.Decompiler.ILAst.ILLabel[], num3);
            IL_296:
            goto IL_2D8;
            IL_298:
            num4 = num2;
            if (num <= -2)
            {
                goto IL_1EE;
            }
            @switch(ICSharpCode.Decompiler.ILAst.ILLabel[], num);
            IL_2B4:;
        }

不难看出这个函数其实就是判断看用户输入的注册码是否正确,但是还存在部分没有脱壳脱干净的代码,不过无伤大雅,已经不影响我们对代码的判读了。其实就是先根据电脑名称算一个机器码出来,然后与用户输入的注册码进行对比,对比上了就说明输入正确,予以注册,否则就弹错误窗口,期间还有注册码格式的检查过程等。其中,关键的函数是

if (VipRegV2Helper.CheckAccessCode(text, computerNo, ref str))
{
    goto IL_11A;
}

这个CheckAccessCode函数就是我们要找的关键了,跟进看看:

ffcell离线注册机,安全,软件工程,Powered by 金山文档

不难发现就是判断注册码输对了没,然后返回一个bool类型,如果是true就说明对了,可以注册,是false就说明不对,不让注册,那我们思路就非常清楚了,可以在函数的返回处下断进行调试。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

此处下断直接强行改变量为true,这下不得不给我狠狠注册了

ffcell离线注册机,安全,软件工程,Powered by 金山文档

随后程序带着true跳出CheckAccessCode函数,返回到method_2函数,因为改成true了所以现在要判断注册多长时间,因为我刚才的注册码是胡乱敲的,怎么可能包含注册有效时间在里面,所以我们还要在我们再改一处,当程序来到这里的时候我们可以修改expireDateFromAccessCode变量的值,如下图所示:

ffcell离线注册机,安全,软件工程,Powered by 金山文档

直接把到期日期设置为2099年1月1日,随后我们继续运行程序,可以看到我们梦寐以求的窗口弹出来了:

ffcell离线注册机,安全,软件工程,Powered by 金山文档

至此,我们就成功拿到了会员身份,但是还是有局限。

  1. 全程需要断网运行,否则软件一旦联网就发现你这个会员身份是假的,就给你覆盖掉了,又成为了非会员身份。

  1. 每次用这个插件都要先用dnspy调试下断改变量,老麻烦了

那首先我们先解决第二个问题,那既然每次都要用,那我们为什么不直接输入正确的注册码呢,那我们就对注册码的算法来一波狠狠的扒皮。

授权码算法分析

通过对多个函数的分析,为了方便读者阅读,特画出超强理解的流程图,保证你一看就懂。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

注册表分析

如果觉得上面注册码算法过于困难,还是有点看不懂,没有关系,其实我们还可以利用注册表法来直接把到期时间改了,不难发现SetLocalExpireDate函数就是拿来把到期日期写进电脑系统的注册表的,其代码如下:

public static void SetLocalExpireDate(DateTime dt)
{
    Simple3Des simple3Des = new Simple3Des("为防止泄露密钥已隐藏");
    string v = simple3Des.EncryptData(dt.ToString());
    RegistryHelper.SetValue("FFCELL_VIPOFFLINE_SETTING", "OfflineExpireFlag", v);
}

可以很清楚的发现这是三轮的DES加密,密钥也直接写死在代码中了,为防止泄露,在本文中就隐藏掉了,我们拿到密钥后自己把授权到期日期一加密手动写进注册表就直接达到了授权到2099年的目的了。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

再提一嘴,除了加密授权到期的日期外,如果用的是联网登录账号,那么你的账号和密码也是用这个算法来加密存储在注册表里面的。

通信协议分析

联网验证也没关系,我们只需要分析一下通信内容即可,先找到判断是否为VIP的联网通信函数

public static bool GetVipInfo(ref string info, ref VipUser vip1)
    {
        string localUserName = LoginHelper.GetLocalUserName();
        string localEnpwd = LoginHelper.GetLocalEnpwd();
        bool result;
        if (Operators.CompareString(localUserName, "", false) == 0 | Operators.CompareString(localEnpwd, "", false) == 0)
        {
            result = false;
        }
        else
        {
            try
            {
                Login login = new Login();
                string vipInfo = login.GetVipInfo(localUserName);
                if (vipInfo == null)
                {
                    info = "无法连接服务器,请检查网络或联系我们!\r\n" + Information.Err().Description;
                    result = false;
                }
                else if (vipInfo.IndexOf("RegOK") > 0)
                {
                    string text = "#@x#";
                    info = "";
                    int num = vipInfo.LastIndexOf(")");
                    string text2 = vipInfo.Substring(checked(num + 1));
                    string[] array = Regex.Split(text2, text);
                    if (array.Length != 5)
                    {
                        result = false;
                    }
                    else
                    {
                        if (Operators.CompareString(array[0].ToLower(), "t", false) == 0)
                        {
                            vip1.isValid = true;
                        }
                        else
                        {
                            vip1.isValid = false;
                        }
                        vip1.userName = array[1];
                        vip1.expireDate = array[2];
                        vip1.lastPc = array[3];
                        vip1.vipscore = array[4];
                        if (Operators.CompareString(vip1.vipscore, "", false) == 0)
                        {
                            vip1.vipscore = "0";
                        }
                        result = true;
                    }
                }
                else
                {
                    info = vipInfo;
                    result = false;
                }
            }
            catch (Exception ex)
            {
                info = "执行过程出现异常:" + ex.Message;
                result = false;
            }
        }
        return result;
    }

注意上述代码的第34行,如果从服务器接收的值是t就是会员,是其他值就不是会员,那我们使用Fiddler抓包看看

请求:

POST /vip/VipRegV2/VipRegVer2.aspx HTTP/1.0

接收:

(RegOK:1)f#@x#UserName#@x#2023/2/18 23:51:32#@x##@x#0

可以看到接收的内容中有f,我们猜测这可能就是和是否为会员相关的值,我们使用fiddler的拦截功能将数据包拦下,修改成t后再放行此数据包 ,可以看见已经成为会员了。

ffcell离线注册机,安全,软件工程,Powered by 金山文档

接收内容的最后那个0猜测就是会员等级,也可以随意修改的。

总结

至此,这个软件就分析的差不多了,还有其他的一些小功能在此就不再赘述了,本文起到一个抛砖引玉的作用,读者可以参考本文自行分析其余的功能模块,若想获得VIP权限,有如下几种方法。

  1. 每次使用软件时用dnSpy调试,修改局部变量, 在内存中改成VIP;

  1. 分析授权码算法,自行编写注册机进行授权;

  1. 直接拿密钥写注册表;

  1. 拦截通讯数据包,抓包改包,欺骗软件自己已经是VIP了。

上述1~3条方法建议配合断网使用,否则可能会失效,不过也可以通过hook方法屏蔽掉它的联网功能,此处不再赘述。文章来源地址https://www.toymoban.com/news/detail-582539.html

到了这里,关于逆向分析某office插件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 逆向分析某office插件

    注:本文仅用于技术研究与探讨,不提供任何成品和补丁程序 今天要逆向的是XX格子这款部分功能付费的Office插件。先安装好后打开看看,看它都有啥可以调教的功能,发现了一个VIP窗口,那这就有意思了,狠狠的开破。 随后我们点击加入会员,点击离线登录,弹出如下窗口

    2024年02月17日
    浏览(29)
  • 跨平台Office文档预览原生插件,非腾讯X5,支持离线,稳定高可用

    2023年3月13日,腾讯发布了调整公告:关于腾讯浏览服务内核SDK-内核文档能力调整公告,公告里面明确说明了: 2023年4月13日零时起,内核文档能力正式下线 。为了脱离腾讯X5,实现真正的文档预览与编辑,于是有了这篇文章。 前面写了多篇关于 跨平台文件在线预览解决方案

    2024年02月02日
    浏览(30)
  • 75.网游逆向分析与插件开发-背包的获取-背包结构与指针的逆向分析

    内容参考于:易道云信息技术研究院VIP课 上一个内容:物品名称与物品编号的映射关系分析-CSDN博客 通过上一个内容已经可以通过物品的id得到一个名字,知道了它的算法,它的算法自己封装好了,我们直接用就好,接下来要用到物品的指针了,所以接下来分析物品的指针怎

    2024年01月21日
    浏览(28)
  • 61.网游逆向分析与插件开发-游戏增加自动化助手接口-游戏红字公告功能的逆向分析

    内容来源于: 易道云信息技术研究院VIP课 上一节内容:游戏公告功能的逆向分析与测试-CSDN博客 码云地址(master分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:63e04cc40f649d10ba2f4fa313ca65cc78f46516 代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-游戏红字公告功能的逆

    2024年01月23日
    浏览(35)
  • 73.网游逆向分析与插件开发-背包的获取-物品数据的初步数据分析

    内容参考于: 易道云信息技术研究院VIP课 上一个内容:72.网游逆向分析与插件开发-背包的获取-项目需求与需求拆解-CSDN博客 然后首先找切入点: 通过药物来当切入点,药物比较好使用,然后鼠标放到药物上它有名字、种类、说明、数量等,除了数量我们都改不了,所以毫

    2024年01月18日
    浏览(40)
  • 80.网游逆向分析与插件开发-背包的获取-自动化助手显示物品数据

    内容参考于: 易道云信息技术研究院VIP课 上一个内容:升级Notice类获得背包基址-CSDN博客 码云地址(ui显示角色数据 分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:3be017de38c50653b1d98bae6eb6db0fcff7bd54 代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-自动化助手显示物

    2024年01月25日
    浏览(36)
  • 66.网游逆向分析与插件开发-角色数据的获取-角色类的数据分析与C++还原

    内容来源于: 易道云信息技术研究院VIP课 上一个内容:65.网游逆向分析与插件开发-角色数据的获取-项目需求与需求拆解-CSDN博客 ReClass.NET工具下载,它下方链接里的 逆向工具.zip 里的reclass目录下:注意它分x64、x32版本,启动是用管理员权限启动否则附加时有些进程附加不上

    2024年02月03日
    浏览(35)
  • 71.网游逆向分析与插件开发-角色数据的获取-修复角色名与等级显示问题

    内容参考于: 易道云信息技术研究院VIP课 上一个内容:自动化助手UI显示角色数据-CSDN博客 码云地址(ui显示角色数据 分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:0049452c079867779f639c4bfab9bd1cd0c68932 代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-修复角色名与等

    2024年01月16日
    浏览(35)
  • 70.网游逆向分析与插件开发-角色数据的获取-自动化助手UI显示角色数据

    内容参考于: 易道云信息技术研究院VIP课 上一个内容:利用技能点属性分析角色数据基址-CSDN博客 码云地址(ui显示角色数据 分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:367aa71f60b9c10ff47ca913a96d2a2ede76b389 代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-自动化助

    2024年01月18日
    浏览(32)
  • 64.网游逆向分析与插件开发-游戏增加自动化助手接口-优化自动助手与游戏焦点的切换

    内容来源于: 易道云信息技术研究院VIP课 上一个内容:自动化助手UI与游戏菜单的对接-CSDN博客 码云地址(master分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:617ac3477ef18273fb9cc281be3c04052304b965 代码下载地址,在 SRO_EX 目录下,文件名为:SRO_Ex-优化自动助手与游戏焦

    2024年01月15日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包