Excel催化剂开源第18波-工作表、工作薄保护破解

2021-08-19 15:04:12 浏览数 (1)

在各大插件中,破解工作表、工作薄密码的功能比比皆是,此篇开源确实有些炒冷饭凑文章的嫌疑,但换个角度,当时笔者开发过程中,找寻相关的代码,也还是花上一些的时间在百度里找了好久,原因如下: 1.大部分能够找到的代码都是VBA的代码 这说明在Excel高级开发群体中,特别是VSTO、COM加载项开发群体中,还是守口如瓶的,仿佛越是高级的开发者,越对自己掌握的“核心”技术保密,希望Excel催化剂这一系列的开源文章对此风气有所好转(在专业程序员圈子里,人家可以越是大神,越是不断地造轮子造福后来者和初级者,并且任性地开源)。 2.VSTO开发的确还是很冷门,没有进入专业开发者的视野中 对于工作表密码破解这些,肯定是OFFICE开发者的专业领域,就算国内不开源,找国外,也没找到多少,所以此篇简单开源,还是有此必要性的。

代码实现

工作表保护破解

在微软官方文档中,看到工作表保护在Excel2013上得到增强,着实吓一跳,以为是旧的破解代码肯定会失效。没想到还是一如既往地正常破解,包括现在Excel365仍然能够成功。

官方文档说明

此段代码是改造VBA的代码,用Excel对象的方法成功破解,速度还是秒级的,能够想出这种破解代码的人真的够神,或者是作者自己埋的后门了,不然怎么这么多次版本更新都没修复的bug。

代码语言:javascript复制
        public static void RemoveWorkSheetProtection()
        {
            Excel.Worksheet sheet = Globals.ThisAddIn.Application.ActiveSheet as Excel.Worksheet;

            sheet.Protect(DrawingObjects: Office.MsoTriState.msoTrue, Contents: Office.MsoTriState.msoTrue, Scenarios: Office.MsoTriState.msoTrue, AllowFiltering: Office.MsoTriState.msoTrue, AllowUsingPivotTables: Office.MsoTriState.msoTrue);
            sheet.Protect(DrawingObjects: Office.MsoTriState.msoTrue, Contents: Office.MsoTriState.msoTrue, Scenarios: Office.MsoTriState.msoTrue, AllowFiltering: Office.MsoTriState.msoTrue, AllowUsingPivotTables: Office.MsoTriState.msoTrue);
            sheet.Protect(DrawingObjects: Office.MsoTriState.msoTrue, Contents: Office.MsoTriState.msoTrue, Scenarios: Office.MsoTriState.msoTrue, AllowFiltering: Office.MsoTriState.msoTrue, AllowUsingPivotTables: Office.MsoTriState.msoTrue);
            sheet.Protect(DrawingObjects: Office.MsoTriState.msoTrue, Contents: Office.MsoTriState.msoTrue, Scenarios: Office.MsoTriState.msoTrue, AllowFiltering: Office.MsoTriState.msoTrue, AllowUsingPivotTables: Office.MsoTriState.msoTrue);
            sheet.Unprotect();
        }
工作薄保护密码破解

工作薄保护密码破解,用百度上流传的VBA方式未能破解成功,印象中还有一个问题是不懂得如何改写回.Net的C#代码,看到的是一大坨的VBA代码,也看不懂。

接着用自己想到的方法实现了,直接操作xml文件,将其中的保护工作薄节点给删除它,此方法同理也适用于前面的工作表保护。

代码语言:javascript复制
public static void RemoveWorkbookProctection()
        {
            if (Common.IsContineToRunQuery())
            {
                Excel.Workbook wkb = Common.ExcelApp.ActiveWorkbook;
                string actShtName = wkb.ActiveSheet.Name;
                string wkbOpenPwd = string.Empty;
                string wkbFullPath = wkb.FullName;

                if (Path.GetExtension(wkbFullPath).ToLower() == ".xls" || wkb.HasPassword)//当是xls时,转换成xlsx或xlsm
                {
                    if (wkb.HasVBProject)
                    {
                        wkbFullPath = Path.Combine(Path.GetDirectoryName(wkbFullPath), Path.GetFileNameWithoutExtension(wkbFullPath)   ".xlsm");
                        wkb.SaveAs(Filename: wkbFullPath, FileFormat: Excel.XlFileFormat.xlOpenXMLWorkbookMacroEnabled);
                    }
                    else
                    {
                        wkbFullPath = Path.Combine(Path.GetDirectoryName(wkbFullPath), Path.GetFileNameWithoutExtension(wkbFullPath)   ".xlsx");
                        wkb.SaveAs(Filename: wkbFullPath, FileFormat: Excel.XlFileFormat.xlOpenXMLWorkbook);
                    }

                }

                wkb.Close();

                FileInfo fileInfo = new FileInfo(wkbFullPath);
                ExcelPackage package;

                using (package = new ExcelPackage(fileInfo))
                {
                    var workbook = package.Workbook;
                    var wkbXml = workbook.WorkbookXml;
                    var protectNode = wkbXml.GetElementsByTagName("workbookProtection")[0];
                    protectNode.ParentNode.RemoveChild(protectNode);
                    package.Save();
                };

                Excel.Workbook wkbReOpen = Common.ExcelApp.Workbooks.Open(Filename: wkbFullPath);
                wkbReOpen.Worksheets[actShtName].Activate();
            }
        }

同样地,派出了EPPLUS类库来直接访问xlsx的xml文档,这里同样用了很巧妙的方式,如果是xls文件非07版格式时,就将其保存为07版格式。而非像其他VBA方法那样只是遍历工作表复制到新的工作薄中,这样可能会引起原文档中有宏代码或其他自定义文档信息等不能同步带过去。

核心代码如下:

代码语言:javascript复制
                using (package = new ExcelPackage(fileInfo))
                {
                    var workbook = package.Workbook;
                    var wkbXml = workbook.WorkbookXml;
                    var protectNode = wkbXml.GetElementsByTagName("workbookProtection")[0];
                    protectNode.ParentNode.RemoveChild(protectNode);
                    package.Save();
                };

结语

对广大Excel开发者来说,VBA的教程已经非常丰富了,但VSTO仍是十分欠缺,但其实也不完成是欠缺,只要合理使用搜索引擎和官方帮助文档,还是可以找到够用的知识点使用的。

此篇简单地实现广大开发者广为熟知的功能,代码换成了C#的形式,可在VSTO上实现此功能,希望此代码段在愿意学习、查找的人手中能被找到并复用起来。开源的态度Excel催化剂是极其拥护的,并以行动来证实了。

0 人点赞