苏紫方璇 发表于 2015-8-24 15:57

一款excel文件解析库的破解记录

本帖最后由 苏紫方璇 于 2015-8-24 16:10 编辑

【文章标题】: 一款excel文件解析库的破解记录
【文章作者】: 苏紫方璇
【软件名称】: LibXl 3.6.2
【下载地址】: 自己搜索下载
【使用工具】: OD,CE,VC
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【转载提示】: 本文原创于吾爱破解论坛的苏紫方璇, 转载请注明作者并保持文章的完整, 谢谢!
--------------------------------------------------------------------------------
首先介绍一下(抄袭官网)这个库

Direct reading and writing Excel files

LibXL is a library that can read and write Excel files. It doesn't require Microsoft Excel and .NET framework, combines an easy to use and powerful features. Library can be used to
Generate a new spreadsheet from scratch
Extract data from an existing spreadsheet
Edit an existing spreadsheet
LibXL can help your applications in exporting and extracting data to/from Excel files with minimum effort. Also it can be used as report engine. Library can be used in C, C++, C#, Delphi, Fortran and other languages. Supports Excel 97-2003 binary formats (xls) and Excel 2007-2013 xml formats (xlsx/xlsm). Supports Unicode and 64-bit platforms. There are a wrapper for .NET developers and separate Linux, Mac and iOS editions. See features of the library in demo.xls or demo.xlsx files.
想了解详细的可以去问一下度娘
--------------------------------------------------------------------------------------
【详细过程】
由于是分析dll文件,需要一个宿主进程来加载,所以我写了一个程序来加载此dll(代码如下,代码写的很烂,请轻喷{:1_910:})
#include <stdio.h>
#include <conio.h>
#include "include_c/libxl.h"
#include <tchar.h>

#pragma comment(lib,"libxl.lib")

int main()
{
      int i = 0;
      const char *b;
      const TCHAR *c;
      BookHandle book = xlCreateBook();
      if (book)
      {
                if (xlBookLoad(book, _T("example.xls")))
                {
                        SheetHandle sheet = xlBookGetSheet(book, 0);
                        if (sheet)
                        {
                              for (i = 0; i < 350; i++)
                              {
                                        if (xlSheetWriteStr(sheet, i, 0, _T("11111"), 0) == 0)
                                        {
                                                b = xlBookErrorMessage(book);
                                                printf("%d行%d列写入错误:%s\n", i+1,1,b);
                                                break;
                                        }
                                        if (xlSheetWriteStr(sheet, i, 1, _T("222222"), 0) == 0)
                                        {
                                                b = xlBookErrorMessage(book);
                                                printf("%d行%d列写入错误:%s\n", i + 1,2, b);
                                                break;
                                        }
                                        if (xlSheetWriteStr(sheet, i, 2, _T("333333"), 0) == 0)
                                        {
                                                b = xlBookErrorMessage(book);
                                                printf("%d行%d列写入错误:%s\n", i + 1, 3, b);
                                                break;
                                        }
                                        if (xlSheetWriteStr(sheet, i, 3, _T("444444"), 0) == 0)
                                        {
                                                b = xlBookErrorMessage(book);
                                                printf("%d行%d列写入错误:%s\n", i + 1, 4, b);
                                                break;
                                        }
                                        if (xlSheetWriteStr(sheet, i, 4, _T("555555"), 0) == 0)
                                        {
                                                b = xlBookErrorMessage(book);
                                                printf("%d行%d列写入错误:%s\n", i + 1, 5, b);
                                                break;
                                        }

                              }
                              
                        }

                        if (xlBookSave(book, _T("example.xlsx"))) printf("\nFile example.xls has been modified.\n");
                        for (i = 0; i < 350; i++)
                        {
                              c = xlSheetReadStr(sheet, i, 0, 0);
                              if (c==NULL)
                              {
                                        b = xlBookErrorMessage(book);
                                        printf("%d行%d列读取错误:%s\n", i + 1, 1, b);
                                        break;
                              }
                              else
                              {
                                        if (_tcscmp(c, _T("11111")) != 0)
                                        {
                                                printf("%d行%d列校验错误:%ws\n", i + 1, 1,c);
                                                break;
                                        }
                              }
                              c = xlSheetReadStr(sheet, i, 1, 0);
                              if (c == NULL)
                              {
                                        b = xlBookErrorMessage(book);
                                        printf("%d行%d列读取错误:%s\n", i + 1, 1, b);
                                        break;
                              }
                              else
                              {
                                        if (_tcscmp(c, _T("222222")) != 0)
                                        {
                                                printf("%d行%d列校验错误:%ws\n", i + 1, 1, c);
                                                break;
                                        }
                              }
                              c = xlSheetReadStr(sheet, i, 2, 0);
                              if (c == NULL)
                              {
                                        b = xlBookErrorMessage(book);
                                        printf("%d行%d列读取错误:%s\n", i + 1, 1, b);
                                        break;
                              }
                              else
                              {
                                        if (_tcscmp(c, _T("333333")) != 0)
                                        {
                                                printf("%d行%d列校验错误:%ws\n", i + 1, 1, c);
                                                break;
                                        }
                              }
                              c = xlSheetReadStr(sheet, i, 3, 0);
                              if (c == NULL)
                              {
                                        b = xlBookErrorMessage(book);
                                        printf("%d行%d列读取错误:%s\n", i + 1, 1, b);
                                        break;
                              }
                              else
                              {
                                        if (_tcscmp(c, _T("444444")) != 0)
                                        {
                                                printf("%d行%d列校验错误:%ws\n", i + 1, 1, c);
                                                break;
                                        }
                              }
                              c = xlSheetReadStr(sheet, i, 4, 0);
                              if (c == NULL)
                              {
                                        b = xlBookErrorMessage(book);
                                        printf("%d行%d列读取错误:%s\n", i + 1, 1, b);
                                        break;
                              }
                              else
                              {
                                        if (_tcscmp(c, _T("555555")) != 0)
                                        {
                                                printf("%d行%d列校验错误:%ws\n", i + 1, 1, c);
                                                break;
                                        }
                              }

                        }
                }
                xlBookRelease(book);
      }

      printf("\nPress any key to exit...");
      _getch();

      return 0;
}

经过测试未注册版有几个限制
1、表格的第一行会加上标识,并且无法操作第一行
2、读写行数有限制
3、写入时会出现Buy me!字样


od加载自己的exe,然后转到dll里面,查找字符串“can't write row 0 in trial version”
在所有找到的地方下断,然后运行程序

程序断在了这里

往上边看,如果上边的两个跳转任意一个跳走,就不会触发这个地方,所以这里应该就是关键跳,那么改跳转不就行了么。这当然可以,但是刚才找了N多地方,一个一个的改觉得不大好,
所以要找关键点
1007D071|.80B8 98090000>cmp byte ptr ds:,0x0
这里有一处比较,如果不等于0就触发限制。
所以要找一下哪个地方改写了这个内存地址的值。这里选用内存写入断点

操作方法(大牛请无视):鼠标点击那条指令,然后在中间的ds:上按右键,数据窗口跟随
然后在下边数据窗口的第一个字节处,按右键,断点,内存写入。
断点下好后,继续运行程序,程序会在这里断下。

这里首先给内存地址写入0,过了个call之后又写入1。结合上边的判断,应该始终让这个地址保持为0,所以应该将所有改写这个地址的指令全部修改为0即可。
这个可以使用查找二进制串,也可以使用查找所有命令来进行操作。我试了一下,所有的改写都是同一个指令,所以,这里使用“查找所有命令”来操作。
查找结果

将这四个指令
mov byte ptr ds:,0x1
全部改为
mov byte ptr ds:,0x0
保存到可执行文件。
重新运行程序
程序提示发现了buy me
打开excel文件,果然在25行发现了不同的数据。


把excel文件清空,使用od载入程序,
查找字符串“Buy me”,同理,全部下断,然后运行

程序断下后,把字符串“Buy me”改为其他的字符串,这里我改成“suziha”

然后ctrl+f9运行到返回
下面使用ce(cheatengine)查找字符串“suziha”

在od的数据窗口按右键,转到,输入刚才ce找到的地址,并下内存访问断点。然后运行程序
程序断在了这个位置

然后返回到上层(Ctrl+f9)

这里没发现什么,继续返回

这里上边可以看到有N多跳转,怎么看呢,在段首下断,然后单步看下流程即可
1007D5BB|. /75 2F         jnz short libxl.1007D5EC
1007D5BD|> |E8 35872800   call libxl.10305CF7                      ;Default case of switch 1007D4AB
1007D5C2|. |99            cdq
1007D5C3|. |B9 FF7F0000   mov ecx,0x7FFF
1007D5C8|. |F7F9          idiv ecx
1007D5CA|. |81FA 587F0000 cmp edx,0x7F58
1007D5D0   |7E 1A         jle short libxl.1007D5EC               ;跳
1007D5D2|. |8B46 20       mov eax,dword ptr ds:
1007D5D5|. |83B8 100A0000>cmp dword ptr ds:,0x8         ;异常
1007D5DC|. |72 1C         jb short libxl.1007D5FA
1007D5DE|. |8B88 FC090000 mov ecx,dword ptr ds:
1007D5E4|. |6A 00         push 0x0
1007D5E6|. |51            push ecx
1007D5E7|. |EB 22         jmp short libxl.1007D60B
1007D5E9|> |8B75 08       mov esi,
1007D5EC|> \8B4E 20       mov ecx,dword ptr ds:
1007D5EF|.6A 00         push 0x0
1007D5F1|.57            push edi                                 ;libxltes.??_C@_1O@HCLCEMEK@?$AA3?$AA3?$AA3?$AA3?$AA3?$AA3?$AA?$AA@?$AAc?$AAt?$AAo?$AAo?$AAl?$AAs?$AA?2?$AAc?$AAr?$AAt?$AA?2?$AAc?$AAr?$AAt?$AAw?$AA3?$AA2?$AA?2?$AAc?$AAo?$AAn?$AAv?$AAe?$AAr?$AAt@AAh@$AAD?$AA?$CC@?$AAy?$AAt@
1007D5F2|.81C1 1C040000 add ecx,0x41C
1007D5F8|.EB 17         jmp short libxl.1007D611               ;正常
1007D5FA|>8D88 FC090000 lea ecx,dword ptr ds:
1007D600|.6A 00         push 0x0
1007D602|.51            push ecx
1007D603|.EB 06         jmp short libxl.1007D60B
1007D605|>8B55 14       mov edx,                        ;libxltes.??_C@_1O@HCLCEMEK@?$AA3?$AA3?$AA3?$AA3?$AA3?$AA3?$AA?$AA@?$AAc?$AAt?$AAo?$AAo?$AAl?$AAs?$AA?2?$AAc?$AAr?$AAt?$AA?2?$AAc?$AAr?$AAt?$AAw?$AA3?$AA2?$AA?2?$AAc?$AAo?$AAn?$AAv?$AAe?$AAr?$AAt@AAh@$AAD?$AA?$CC@?$AAy?$AAt@
1007D608|.6A 00         push 0x0
1007D60A|.52            push edx
1007D60B|>8D88 1C040000 lea ecx,dword ptr ds:
1007D611|>E8 CAEEF9FF   call libxl.1001C4E0                      ;<<
1007D616|.8B5D 08       mov ebx,
1007D619|.8B8B 04030000 mov ecx,dword ptr ds:
1007D61F|.2B8B 00030000 sub ecx,dword ptr ds:
经过分析,1007D5D0这个跳转就是关键跳,直接把他改成jmp就可以了,但是注意,程序调用的是宽字节(W结尾)的函数,所对应的多字节(A结尾)的函数也要改,我用上边的那个除法作为特征码进行查找。
找到这个地方1007B8B1 把他也给改成jmp即可。


注意:这个我仅仅测试了普通的读写功能,其他功能以及未测试的xlsx文件的读写可能存在不可预料的情况,若出现此类情况,请自行处理。
另外:我只做了32位_cdecl的dll的破解,若需求64位、.Net以及stdcall的也请自行破解,net我不清楚,其他的应该与此类似(特别是stdcall)。
最后:以上是本人的一点拙见,如果有什么错误和不足之处,还请各位批评指出,如果各位觉得学到了什么,还请不要吝啬手中的热心和CB,感谢大家的支持。
源码及破解后的文件(需要例子和资料的请登录官网自行下载)应@smile1110 的要求,附件云盘链接: http://pan.baidu.com/s/1eQyI1eM 密码: qt4w    (如果失效就请下附件吧)
--------------------------------------------------------------------------------

                                                         吾爱破解论坛
                                                       2015年08月24日


dxl102586342 发表于 2015-9-10 09:49

@苏紫方璇
本人用的是C++ 编程的
我下载后使用后,发现输出的xls格式文档的文件 第一行输出的是淡红色,并且只有第一行的第一个(A1)能输出, A2之后的都是空的.


前面的 4个mov byte ptr ,0x1
还有2个   move byte ptr ,0x1 也是访问该地址!

苏紫方璇 发表于 2015-8-25 18:00

Hmily 发表于 2015-8-25 17:53
我意思普通用户咋使用?不可能也弄个exe来加载?

这回懂了,普通用户还真得弄个exe来加载,不过一般普通用户也用不着这东西,有excel就够了。这个算是编程接口,功能就是不借助excel组件来实现解析xls文件。算是编程用的东西吧。

smile1110 发表于 2015-8-24 16:38

苏紫方璇 发表于 2015-8-24 16:12
免CB通道
链接: http://pan.baidu.com/s/1eQyI1eM 密码: qt4w

我也破解完毕了

   

最后我发现值得深究的地方 其试用版检测赋值语句在 102bXXXX之中某个地方,然后每次检测都与其一个偏移值比较,若是找到那个地方把其数值赋值为eax数值即可完全注册,也就是该软件本身的正版验证机制原理

smile1110 发表于 2015-8-24 16:03

附件要钱 1金币 买不起

smile1110 发表于 2015-8-24 16:12

smile1110 发表于 2015-8-24 16:03
附件要钱 1金币 买不起

俺刚看完这篇文章,也想试试,不过你都领完100金币奖励了!!!!

苏紫方璇 发表于 2015-8-24 16:12

smile1110 发表于 2015-8-24 16:03
附件要钱 1金币 买不起

免CB通道
链接: http://pan.baidu.com/s/1eQyI1eM 密码: qt4w

枫恋蓝点 发表于 2015-8-24 16:25

哇塞,楼主,我看好你哦。可惜我看不明白{:301_986:}

苏紫方璇 发表于 2015-8-24 16:44

smile1110 发表于 2015-8-24 16:38
我也破解完毕了

   


我一直不知道这个从哪里注册正版,你说的那个地方我看见了,但是没仔细分析过

smile1110 发表于 2015-8-24 16:49

苏紫方璇 发表于 2015-8-24 16:44
我一直不知道这个从哪里注册正版,你说的那个地方我看见了,但是没仔细分析过

俺也想要点金币奖励,这个软件是不是悬赏呢?

smile1110 发表于 2015-8-24 16:54

smile1110 发表于 2015-8-24 16:12
俺刚看完这篇文章,也想试试,不过你都领完100金币奖励了!!!!

大哥,俺也破解了,分俺10金币好吗

soarsoar77 发表于 2015-8-24 17:28

大哥,俺也破解了,分俺10金币好吗
页: [1] 2 3
查看完整版本: 一款excel文件解析库的破解记录