-
-
为单词大爆炸2.0增加NeoSpeech TTS 发音,兼谈增加代码段保存出现“无法定位数据”的解决
-
发表于:
2006-8-29 19:12
15938
-
为单词大爆炸2.0增加NeoSpeech TTS 发音,兼谈增加代码段保存出现“无法定位数据”的解决
单词大爆炸2.0采用sapi4的TTS,不能调用NeoSpeech TTS,因此做个补钉,提高发音质量。
这是Delphi编写的
思路:先编写一个调用sapi5的DLL,主程序中传入要读的单词或句子,由DLL调用sapi5发音。由于原来也为奇迹智能英语增加TTS接口,奇迹智能是VB编写的,单词为UNICODE,而单词大爆炸的单词为ascii。因此在DLL文件中做了两个接口,一个是unicode用的speak,一个是ascii用的speaka.
然后,屏蔽原软件中的TTS发音,加入自己的DLL调用。
首先要确定程序可TTS调用的代码在那里,用dreaman的OllyHTML插件中的“获取特定操作相关的过程列表”脚本,对过程进行跟踪:即比较按下发音按钮前后过程的差别,就可以大致确定TTS调用代码位置,然后,一步一步跟踪,就可以找到了。
0045B792 . 8B55 E8 mov edx, [ebp-18]
0045B795 . 8BC3 mov eax, ebx
0045B797 . E8 B4CDFAFF call 00408550 跟踪到这里,执行后,eax返回单词地址,这个可是有用的啊!
0045B79C 8B7D F0 mov edi, [ebp-10] 在这里,将程序跳转到自己的DLL调用位置:改为 jmp 005682AD
0045B7A1 83C7 06 add edi, 6
0045B7A2 . 85FF test edi, edi
继续跟踪TTS调用代码
0045B836 . 8B45 D8 mov eax, [ebp-28]
0045B839 . E8 7686FAFF call 00403EB4 跟踪到这个,执行后,eax返回单词地址
0045B83E mov [ebp-C],eax 单词地址放入[ebp-C],用于下面代码中进行TTS发音,改为nop后,TTS就不发音了
0045B841 . 33C0 xor eax, eax
....
0045B87F . 50 push eax
0045B880 . 8B00 mov eax, [eax]
0045B882 FF50 1C call [eax+1C] 调用msttssyn.dll进行发声,由于已将0045B83E mov [ebp-C],eax改为nop,无单词传入,便不发声了
下面是加入自己的DLL调用
00568290 . 74 74 6... ascii "ttd.dll" 自己的DLL文件名
00568298 00 db 00
00568299 00 db 00
0056829A 00 db 00
0056829B . 73 70 ... ascii "speaka" 发声函数名
005682A6 00 db 00 用于存放speaka函数的地址
005682AD 53 push ebx 从0045B79C跳来,保存现场
005682AE 50 push eax EAX中的单词的址,保存现场
005682AF 8B1D A6825600mov ebx, [5682A6] 取speaka地址
005682B5 90 nop
005682B6 90 nop
005682B7 83FB 00 cmp ebx, 0 speaka地址是否已有了?
005682BA 75 2A jnz short 005682E6 已有,直接调用
005682BC . 68 90825600 push 00568290 speaka地址为空,则要调用LoadLibraryA,传送DLL文件名地址:ttd.dll
005682C1 . E8 26E2E9FF call <jmp.&kernel32.LoadLibraryA> LoadLibraryA
005682C6 . 83F8 00 cmp eax, 0
005682C9 . 74 22 je short 005682ED DLL是否调用成功?
005682CB . 68 9B825600 push 0056829B 成功,传函数名地址 speaka
005682D0 . 50 push eax 传DLL hModule
005682D1 E8 8EE1E9FF call <jmp.&kernel32.GetProcAddress> 取speaka
005682D6 A3 A6825600 mov [5682A6], eax 将地址保存
005682DB 83F8 00 cmp eax, 0
005682DE 74 0D je short 005682ED speaka是否有效
005682E0 8B1D A6825600mov ebx, [5682A6] 有效,将地址放在ebx
005682E6 58 pop eax 弹出单词地址
005682E7 50 push eax 传单词地址
005682E8 FFD3 call ebx 调用speaka进行发音
005682EA EB 02 jmp short 005682EE
005682EC 90 nop
005682ED 58 pop eax
005682EE 5B pop ebx
005682EF 8B7D F0 mov edi, [ebp-10] 恢复0045B79C 0045B7A1 处修改为JMP 005682AD的代码
005682F2 83C7 06 add edi, 6
005682F5 ^ E9 A834EFFF jmp 0045B7A2 跳回原程序处
修改完代码后,将代码保存时,却发生“在可执行文件中无法定位数据”的问题,这个问题也必须解决才行。
一、打开PE Explorer,载入调试程序
二、修改CODE段的RAW SIZE 见下图:
1.切换到Section headers
2.选中CODE段
3.按下Section Editor
4.解锁
5.将Size of Raw Data修改大一些,如将167200改为167400,这样修改后文件空间就增大了。
6.将CODE段设置为可写。因为程序中,要将取到的speaka的地址放在CODE段中的[5682A6]中,因此要让CODE段可写才行。当然也可以增加一个data段,用来存放地址,就可以不用修改这个属性了。
保存!
现在就可以在OD中增加代码并保存了。但注意的是,这样修改后,在最后的空白处还是不能保存的,但前面可保存空间已足够了
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课