好友
阅读权限 100
听众
最后登录 1970-1-1
苏紫方璇
发表于 2015-8-24 15:57
本帖最后由 苏紫方璇 于 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:})
[C++] 纯文本查看 复制代码
#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:[eax+0x998],0x0
这里有一处比较,如果[eax+0x998]不等于0就触发限制。
所以要找一下哪个地方改写了这个内存地址的值。这里选用内存写入断点
操作方法(大牛请无视):鼠标点击那条指令,然后在中间的ds:[00xxxxxx]上按右键,数据窗口跟随
然后在下边数据窗口的第一个字节处,按右键,断点,内存写入。
断点下好后,继续运行程序,程序会在这里断下。
这里首先给内存地址写入0,过了个call之后又写入1。结合上边的判断,应该始终让这个地址保持为0,所以应该将所有改写这个地址的指令全部修改为0即可。
这个可以使用查找二进制串,也可以使用查找所有命令来进行操作。我试了一下,所有的改写都是同一个指令,所以,这里使用“查找所有命令”来操作。
查找结果
将这四个指令
mov byte ptr ds:[ecx+0x998],0x1
全部改为
mov byte ptr ds:[ecx+0x998],0x0
保存到可执行文件。
重新运行程序
程序提示发现了buy me
打开excel文件,果然在25行发现了不同的数据。
把excel文件清空,使用od载入程序,
查找字符串“Buy me”,同理,全部下断,然后运行
程序断下后,把字符串“Buy me”改为其他的字符串,这里我改成“suziha”
然后ctrl+f9运行到返回
下面使用ce(cheatengine)查找字符串“suziha”
在od的数据窗口按右键,转到,输入刚才ce找到的地址,并下内存访问断点。然后运行程序
程序断在了这个位置
然后返回到上层(Ctrl+f9)
这里没发现什么,继续返回
这里上边可以看到有N多跳转,怎么看呢,在段首下断,然后单步看下流程即可
[Asm] 纯文本查看 复制代码
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:[esi+0x20]
1007D5D5 |. |83B8 100A0000>cmp dword ptr ds:[eax+0xA10],0x8 ; 异常
1007D5DC |. |72 1C jb short libxl.1007D5FA
1007D5DE |. |8B88 FC090000 mov ecx,dword ptr ds:[eax+0x9FC]
1007D5E4 |. |6A 00 push 0x0
1007D5E6 |. |51 push ecx
1007D5E7 |. |EB 22 jmp short libxl.1007D60B
1007D5E9 |> |8B75 08 mov esi,[arg.1]
1007D5EC |> \8B4E 20 mov ecx,dword ptr ds:[esi+0x20]
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:[eax+0x9FC]
1007D600 |. 6A 00 push 0x0
1007D602 |. 51 push ecx
1007D603 |. EB 06 jmp short libxl.1007D60B
1007D605 |> 8B55 14 mov edx,[arg.4] ; 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:[eax+0x41C]
1007D611 |> E8 CAEEF9FF call libxl.1001C4E0 ; <<
1007D616 |. 8B5D 08 mov ebx,[arg.1]
1007D619 |. 8B8B 04030000 mov ecx,dword ptr ds:[ebx+0x304]
1007D61F |. 2B8B 00030000 sub ecx,dword ptr ds:[ebx+0x300]
经过分析,1007D5D0这个跳转就是关键跳,直接把他改成jmp就可以了,但是注意,程序调用的是宽字节(W结尾)的函数,所对应的多字节(A结尾)的函数也要改,我用上边的那个除法作为特征码进行查找。
找到这个地方1007B8B1 把他也给改成jmp即可。
注意:这个我仅仅测试了普通的读写功能,其他功能以及未测试的xlsx文件的读写可能存在不可预料的情况,若出现此类情况,请自行处理。
另外:我只做了32位_cdecl的dll的破解,若需求64位、.Net以及stdcall的也请自行破解,net我不清楚,其他的应该与此类似(特别是stdcall)。
最后:以上是本人的一点拙见,如果有什么错误和不足之处,还请各位批评指出,如果各位觉得学到了什么,还请不要吝啬手中的热心和CB,感谢大家的支持。
源码及破解后的文件(需要例子和资料的请登录官网自行下载)
libxltest.7z
(1.16 MB, 下载次数: 74)
应@smile1110 的要求,附件云盘链接: http://pan.baidu.com/s/1eQyI1eM 密码: qt4w (如果失效就请下附件吧)
--------------------------------------------------------------------------------
吾爱破解论坛
2015年08月24日
免费评分
查看全部评分