一款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日
@苏紫方璇
本人用的是C++ 编程的
我下载后使用后,发现输出的xls格式文档的文件 第一行输出的是淡红色,并且只有第一行的第一个(A1)能输出, A2之后的都是空的.
前面的 4个mov byte ptr ,0x1
还有2个 move byte ptr ,0x1 也是访问该地址!
Hmily 发表于 2015-8-25 17:53
我意思普通用户咋使用?不可能也弄个exe来加载?
这回懂了,普通用户还真得弄个exe来加载,不过一般普通用户也用不着这东西,有excel就够了。这个算是编程接口,功能就是不借助excel组件来实现解析xls文件。算是编程用的东西吧。 苏紫方璇 发表于 2015-8-24 16:12
免CB通道
链接: http://pan.baidu.com/s/1eQyI1eM 密码: qt4w
我也破解完毕了
最后我发现值得深究的地方 其试用版检测赋值语句在 102bXXXX之中某个地方,然后每次检测都与其一个偏移值比较,若是找到那个地方把其数值赋值为eax数值即可完全注册,也就是该软件本身的正版验证机制原理
附件要钱 1金币 买不起 smile1110 发表于 2015-8-24 16:03
附件要钱 1金币 买不起
俺刚看完这篇文章,也想试试,不过你都领完100金币奖励了!!!! smile1110 发表于 2015-8-24 16:03
附件要钱 1金币 买不起
免CB通道
链接: http://pan.baidu.com/s/1eQyI1eM 密码: qt4w 哇塞,楼主,我看好你哦。可惜我看不明白{:301_986:} smile1110 发表于 2015-8-24 16:38
我也破解完毕了
我一直不知道这个从哪里注册正版,你说的那个地方我看见了,但是没仔细分析过 苏紫方璇 发表于 2015-8-24 16:44
我一直不知道这个从哪里注册正版,你说的那个地方我看见了,但是没仔细分析过
俺也想要点金币奖励,这个软件是不是悬赏呢? smile1110 发表于 2015-8-24 16:12
俺刚看完这篇文章,也想试试,不过你都领完100金币奖励了!!!!
大哥,俺也破解了,分俺10金币好吗 大哥,俺也破解了,分俺10金币好吗