发表于 2024-5-5 10:02

申请会员ID:FishSeeWater【申请通过】

1、申 请 I D:FishSeeWater
2、个人邮箱:FishSeeWater@gmail.com   
3、原创技术文章:
《PE Fix bug SQLiteMaestro~ 自己动手,丰衣足食》   ( https://bbs.kanxue.com/thread-125916.htm )
【文章标题】: PE Fix bug SQLiteMaestro
【文章作者】: FishSeeWater
【作者邮箱】: FishSeeWater@gmail.com
【软件名称】: SQLiteMaestro
【保护方式】: Asprotect
【使用工具】: OllyICE,Dede,IDA
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
          SQlite3数据库的美大家有目共睹,最近我也爱上了她,一直想找个支持SQLite数据库的管理工具,最后发现SQLiteMaestro后感觉很棒,
在作者的官方主页上看到其支持好多数据库.这个软件不支持中文路径下的数据库,在新版修复了这个问题,但在使用过程中,发现其对中文支持还是有问题,
无法向数据库中插入中文,同时在检索时,也不能有中文的限定.这另我比较郁闷,~.而且作者也好长时间没有作出新的更新.找其它软件,没有发现更好的,呵呵,
自己动手丰衣足食吧~:) .
主程序版本 10.5.01

运行程序后,会发现如下图所示的问题.
软件是用Delphi7写ASProtect保护的,脱壳与破解过程略~.把处理好的程序扔到IDA中加工后,发现可读性不高.请出DEDE加工,生成MAP文件,
再用IDA脚本loadmap.idc(感谢jackozoo) 导入到IDA中.再生成MAP文件.用OD LoadMapex导入.
(为什么要先导入IDA中再生成MAP呢,在IDA导入map时,会把相关的参考调用都标识出来,这样用IDA生成的MAP可读性更好)
上述问题的出现估计是编码转换的原因, win下的编码转换API是WideCharToMultiByte 运行程序后,
在SQLedit中写下 select 语句 "select * from table01 where filed01 like '%媒%';"
下断点 BPX WideCharToMultiByte 后 ,点击 Execute Select only .这时会发现断点刚下的时候,程序就不断的中断.只有换个方法,在DEDE中找到这个模块的消息入口,
下断点后回到程序,然后再点击Execute Select only 程序顺利断下,这时再下 API断点.观察API的参数有没有上面的SQL语句.
遗憾的是整个过程中并没有发现SQL语句做参数的调用.难道思路不对?折腾了一上午也没找到关键点,在IDA中消遣.发现有个 Utf8Encode 函数,这时突然想起,难道Delphi
的这个函数不是调用的winapi?马上打开Delphi2010(我装的是2010),查看了一下这个函数,明明就是调用的API嘛,为什么会断不下来呢?又难道是Delphi7函数没有调用?
打开D7的目录,找到System.pas文件, 一看果然是D7的Utf8Encode函数是自己实现的.怪不得断不下来呢.那就在OD中直接下断 Utf8Encode 哈哈,不几次F9就发
现 "select * from table01 where filed01 like '%媒%'".
   分析过程如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
009B7DA0 /$push    ebp                                    ;Sql Create
009B7DA1 |.mov   ebp, esp
009B7DA3 |.push    0
..........
009B7DCA |.jnz   short <SQLiteMa.loc_9B7DED>
009B7DCC |.lea   edx, dword ptr ss:
009B7DCF |.mov   eax, esi
009B7DD1 |.call    <SQLiteMa.System::UTF8Encode(System::Wid>
009B7DD6 |.mov   edx, dword ptr ss:
009B7DD9 |.lea   eax, dword ptr ss:
009B7DDC |.call    <SQLiteMa.System_@WStrFromLStr>// 这一句纯属多余的,估计在原程序中是两个变量的赋值 WideString=AnsiString
009B7DE1.mov   edx, dword ptr ss:      // 也就是因为这一句导致已经UTF-8编码的字串,转换成坏串了.
009B7DE4 |.mov   eax, ebx
009B7DE6 |.mov   ecx, dword ptr ds:
009B7DE8 |.call    dword ptr ds:   ;<SQLiteMa.sub_E03F24> // 这个CALL把上面的"宽"坏串(SQL语句)写入一个TString
009B7DEB |.jmp   short <SQLiteMa.loc_9B7DF6>                  // 对象中,在以后的代码中解析SQL语法.
..........                                                            // 注意,这个CALL由于是个虚函数,通过多次跟踪,发现其调用了两个
009B7E0B |.lea   eax,                                  // 函数 <SQLiteMa.sub_E03F24> 和 <SQLiteMa.sub_00E03C60>
009B7E0E |.call    <SQLiteMa.System_@WStrClr>                     // 这两个函数都要跟进去检查一下.
009B7E13 \.retn
009B7E14.^ jmp   <SQLiteMa.System_@HandleFinally_>      ;loc_9B7E14
009B7E19.^ jmp   short <SQLiteMa.loc_9B7E03>

//===========<SQLiteMa.sub_E03F24>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
00E03F24 /.push    ebp                                    ;sub_E03F24
00E03F25 |.mov   ebp, esp
00E03F27 |.xor   ecx, ecx
.........
00E03F65 |.lea   eax, dword ptr ss:
00E03F68 |.mov   edx, esi
00E03F6A |.call    <SQLiteMa.System_@LStrFromWStr>//这一句是将"宽"坏串(SQL语句)反转回Ansi串,错上加错,这里也需要处理.
00E03F6F |.mov   eax, dword ptr ss:
00E03F72 |.lea   edx, dword ptr ss:
..........
00E03F92   lea   eax, dword ptr ss:
00E03F95   mov   edx, esi
00E03F97   call    <SQLiteMa.System_@LStrFromWStr>//这一句是将"宽"坏串(SQL语句)反转回Ansi串,错上加错. 改下面一句,忽略其
00E03F9C   mov   edx, dword ptr ss:
00E03F9F |.pop   eax
00E03FA0 |.mov   ecx, dword ptr ds:
00E03FA2 |.call    dword ptr ds:;Classes::TStrings::SetTextStr(System::AnsiString)// 将SQL语句存入TString中,后解析执行.
.........
00E03FBA |.call    <SQLiteMa.System_@LStrArrayClr>
00E03FBF \.retn

//===========<SQLiteMa.sub_00E03C60>


1
2
3
4
5
6
7
8
9
10
11
12
00E03C60 /.push    ebp
00E03C61 |.mov   ebp, esp
00E03C63 |.push    0
........
00E03C82 |.lea   eax, dword ptr ss:
00E03C85 |.mov   edx, esi
00E03C87 |.call    <SQLiteMa.System_@LStrFromWStr>//这一句是将"宽"坏串(SQL语句)反转回Ansi串,错上加错. 改下面一句,忽略其
00E03C8C   mov   edx, dword ptr ss:
00E03C8F |.pop   eax
......
00E03CA5 |.call    <SQLiteMa.System_@LStrClr>
00E03CAA \.retn


/////////////////////////////////////
补丁方法:
两步:


1
2
3
4
5
1.在CALL之前要传入正确的SQL语句

009B7DE1.mov   edx, dword ptr ss:
改成
009B7DE1.mov   edx, dword ptr ss:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   
2.在CALL里,就不要再反转成AnsiString了. 有3处
(1)将 函数<SQLiteMa.sub_E03F24>
00E03F6F |.mov   eax, dword ptr ss:
改成
00E03F6F   mov   eax, esi
00E03F71   nop
(2)将 函数<SQLiteMa.sub_E03F24>
00E03F9C   mov   edx, dword ptr ss:
改成
00E03F9C   mov   edx, esi
00E03F9E   nop
(3)将 函数<SQLiteMa.sub_00E03C60>
00E03C8C   mov   edx, dword ptr ss:
改成
00E03C8C   mov   edx, esi
00E03C8E   nop

OK收工.
经过修正后,的效果~:
-------------------------------------------------------------------------
【经验总结】

      修补这个程序费了两天的时间,大部分时间都浪费在一开始的下断上,思路不对出路不通啊~ 最后发现这个UTF8Encode这个函数时,有很大的运气成份.
看来做任何一件事的时间付出度都是一定的:)
      分析Delphi的程序真的很头痛,一点都不如C/C++来的直接~多亏了Dede的帮忙. 看雪真是个大宝库呀,工具教程一应俱全~:)

      在这一过程中发现D7的UTF8Encode实现上有个漏洞,只处理到三字节码, U-00000800 - U-0000FFFF 高出这一部分的都没有处理,看来用D7同学真的是要升级了~:)
      这个程序的数据库驱动用的是开源的项目ZEOSDBO(怪不得支持这么多数据库呢),这个项目非常棒, 但在字符编码上存在不少问题,用的同学注意编码~.

      笔记是后来整理的,在跟踪的过程中有不清楚的地方 留言共同交流~:).

Hmily 发表于 2024-5-6 12:14

I D:FishSeeWater
邮箱:FishSeeWater@gmail.com   

申请通过,欢迎光临吾爱破解论坛,期待吾爱破解有你更加精彩,ID和密码自己通过邮件密码找回功能修改,请即时登陆并修改密码!
登陆后请在一周内在此帖报道,否则将删除ID信息。

FishSeeWater 发表于 2024-5-7 20:49

新人报道,请多关照:)
页: [1]
查看完整版本: 申请会员ID:FishSeeWater【申请通过】