冰凌汇编

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 46|回复: 0
收起左侧

[Delphi] 解决vb6和delphi7在win10下输入中文乱码问题

[复制链接]
testbbb 发表于 2022-7-18 23:22:25
最近遇到一个问题,在win10下,部分vb6或者delphi7写的使用A函数控件的程序,TextBox输入中文总是乱码,而复制粘贴则正常。
在网上查找发现,目前通用的办法是删除美式键盘即可解决。
测试一下确实如此,但是,删除后会改变切换输入法的习惯,为了极个别老古董程序改习惯还是不太舒服的。于是就大致看了一下问题所在。
在网上搜索发现,输入法最后会发送一个WM_IME_CHAR的消息,其中包含了输入的文本。
既然是多字节的A类控件,断SendMessageA即可在输入汉字后触发断点。
程序断在user32中,向上查找发现部分流程。

代码如下:
[Asm] 纯文本查看 复制代码
76801D16   .  33C0          xor eax,eax
76801D18   .  50            push eax
76801D19   .  50            push eax
76801D1A   .  68 00080000   push 0x800
76801D1F   .  51            push ecx
76801D20   .  3945 14       cmp dword ptr ss:[ebp+0x14],eax
76801D23   .  0F84 DE000000 je user32.76801E07
76801D29   .  8B35 F4128576 mov esi,dword ptr ds:[0x768512F4]        ;  imm32.ImmGetCompositionStringA
76801D2F   .  8BCE          mov ecx,esi
76801D31   .  FF15 4C408576 call dword ptr ds:[0x7685404C]           ;  user32.767EEEA0
76801D37   .  FFD6          call esi
76801D39   .  8BF0          mov esi,eax
76801D3B   .  85F6          test esi,esi
76801D3D   .  0F84 64010000 je user32.76801EA7
76801D43   .  8D4E 01       lea ecx,dword ptr ds:[esi+0x1]
76801D46   .  51            push ecx                                 ; /dwBytes = 0x0
76801D47   .  6A 08         push 0x8                                 ; |dwFlags = HEAP_ZERO_MEMORY
76801D49   .  FF35 F0198576 push dword ptr ds:[0x768519F0]           ; |hHeap = 00430000
76801D4F   .  FF15 60378576 call dword ptr ds:[<&ntdll.RtlAllocateHe>; \RtlAllocateHeap
76801D55   .  894424 1C     mov dword ptr ss:[esp+0x1C],eax
76801D59   .  85C0          test eax,eax
76801D5B   .  0F84 46010000 je user32.76801EA7
76801D61   .  56            push esi
76801D62   .  8B35 F4128576 mov esi,dword ptr ds:[0x768512F4]        ;  imm32.ImmGetCompositionStringA
76801D68   .  8BCE          mov ecx,esi
76801D6A   .  50            push eax
76801D6B   .  68 00080000   push 0x800
76801D70   .  FF7424 30     push dword ptr ss:[esp+0x30]
76801D74   .  FF15 4C408576 call dword ptr ds:[0x7685404C]           ;  user32.767EEEA0
76801D7A   .  FFD6          call esi
76801D7C   .  8B4424 1C     mov eax,dword ptr ss:[esp+0x1C]
76801D80   .  8A08          mov cl,byte ptr ds:[eax]
76801D82   .  84C9          test cl,cl
76801D84   .  0F84 0A010000 je user32.76801E94
76801D8A   .  8B7C24 14     mov edi,dword ptr ss:[esp+0x14]
76801D8E   .  33F6          xor esi,esi
76801D90   .  46            inc esi
76801D91   .  8BD8          mov ebx,eax
76801D93   >  64:A1 1800000>mov eax,dword ptr fs:[0x18]
76801D99   .  8B90 DC0F0000 mov edx,dword ptr ds:[eax+0xFDC]
76801D9F   .  85D2          test edx,edx
76801DA1   .  79 02         jns short user32.76801DA5
76801DA3   .  03C2          add eax,edx
76801DA5   >  0FB780 980800>movzx eax,word ptr ds:[eax+0x898]
76801DAC   .  8D53 01       lea edx,dword ptr ds:[ebx+0x1]
76801DAF   .  51            push ecx
76801DB0   .  50            push eax
76801DB1   .  895424 30     mov dword ptr ss:[esp+0x30],edx
76801DB5   .  FF15 78338576 call dword ptr ds:[<&api-ms-win-core-loc>;  KernelBa.IsDBCSLeadByteEx
76801DBB   .  85C0          test eax,eax
76801DBD   .  74 29         je short user32.76801DE8
76801DBF   .  8B4424 28     mov eax,dword ptr ss:[esp+0x28]
76801DC3   .  8A00          mov al,byte ptr ds:[eax]
76801DC5   .  84C0          test al,al
76801DC7   .  74 1C         je short user32.76801DE5
76801DC9   .  0FB60B        movzx ecx,byte ptr ds:[ebx]
76801DCC   .  56            push esi                                 ; /lParam = 0x2BF1E94
76801DCD   .  C1E1 08       shl ecx,0x8                              ; |
76801DD0   .  0FB6C0        movzx eax,al                             ; |
76801DD3   .  0BC8          or ecx,eax                               ; |
76801DD5   .  51            push ecx                                 ; |wParam = 0x0
76801DD6   .  68 86020000   push 0x286                               ; |Message = WM_IME_CHAR
76801DDB   .  57            push edi                                 ; |hWnd = 0x767CDDB0
76801DDC   .  E8 DF02FDFF   call user32.SendMessageA                 ; \SendMessageA
76801DE1   .  8B5C24 28     mov ebx,dword ptr ss:[esp+0x28]
76801DE5   >  43            inc ebx
76801DE6   .  EB 14         jmp short user32.76801DFC
76801DE8   >  0FB603        movzx eax,byte ptr ds:[ebx]
76801DEB   .  56            push esi                                 ; /lParam = 0x2BF1E94
76801DEC   .  50            push eax                                 ; |wParam = 0x0
76801DED   .  68 86020000   push 0x286                               ; |Message = WM_IME_CHAR
76801DF2   .  57            push edi                                 ; |hWnd = 0x767CDDB0
76801DF3   .  E8 C802FDFF   call user32.SendMessageA                 ; \SendMessageA     <<============断在这里
76801DF8   .  8B5C24 28     mov ebx,dword ptr ss:[esp+0x28]
76801DFC   >  8A0B          mov cl,byte ptr ds:[ebx]
76801DFE   .  84C9          test cl,cl
76801E00   .^ 75 91         jnz short user32.76801D93

系统调用ImmGetCompositionStringA获取输入法输入的字符,这里正常没错,之后通过程序TEB定位到程序的代码页,
使用IsDBCSLeadByteEx确定是否是中文,是就走第一个send,发送多字节,不是就走第二个(即断下位置),发送单字节。
问题就出现在这里了,获取到的代码页为1252,并非中文的936,导致IsDBCSLeadByteEx认为不是中文,走了第二个send。
之后测试在程序断在入口点时,将1252改为936,程序正常输入中文了。

代码页定位:TEB-->0xFDC(WowTebOffset),加上偏移后得到TEB64-->(0x800+0x98)Win32ClientInfo.CodePage( win32k!tagCLIENTINFO结构体)

最后,改下pe文件或者整个dll加载进去,把代码页改了齐活。
冰凌汇编免责声明
以上内容均来自网友转发或原创,如存在侵权请发送到站方邮件9003554@qq.com处理。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|站点统计|Archiver|小黑屋|RSS|冰凌汇编 ( 滇ICP备2022002049号 滇公网安备 53032102000029号)|网站地图

GMT+8, 2022-10-6 21:29 , Processed in 0.140137 second(s), 8 queries , Redis On.

冰凌汇编 - 建立于2021年12月20日

Powered by Discuz! © 2001-2022 Comsenz Inc.

快速回复 返回顶部 返回列表