苏紫方璇 发表于 2021-8-30 15:43

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

本帖最后由 苏紫方璇 于 2021-8-30 22:35 编辑

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

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:,eax
76801D23   .0F84 DE000000 je user32.76801E07
76801D29   .8B35 F4128576 mov esi,dword ptr ds:      ;imm32.ImmGetCompositionStringA
76801D2F   .8BCE          mov ecx,esi
76801D31   .FF15 4C408576 call dword ptr ds:         ;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:
76801D46   .51            push ecx                                 ; /dwBytes = 0x0
76801D47   .6A 08         push 0x8                                 ; |dwFlags = HEAP_ZERO_MEMORY
76801D49   .FF35 F0198576 push dword ptr ds:         ; |hHeap = 00430000
76801D4F   .FF15 60378576 call dword ptr ds:[<&ntdll.RtlAllocateHe>; \RtlAllocateHeap
76801D55   .894424 1C   mov dword ptr ss:,eax
76801D59   .85C0          test eax,eax
76801D5B   .0F84 46010000 je user32.76801EA7
76801D61   .56            push esi
76801D62   .8B35 F4128576 mov esi,dword ptr ds:      ;imm32.ImmGetCompositionStringA
76801D68   .8BCE          mov ecx,esi
76801D6A   .50            push eax
76801D6B   .68 00080000   push 0x800
76801D70   .FF7424 30   push dword ptr ss:
76801D74   .FF15 4C408576 call dword ptr ds:         ;user32.767EEEA0
76801D7A   .FFD6          call esi
76801D7C   .8B4424 1C   mov eax,dword ptr ss:
76801D80   .8A08          mov cl,byte ptr ds:
76801D82   .84C9          test cl,cl
76801D84   .0F84 0A010000 je user32.76801E94
76801D8A   .8B7C24 14   mov edi,dword ptr ss:
76801D8E   .33F6          xor esi,esi
76801D90   .46            inc esi
76801D91   .8BD8          mov ebx,eax
76801D93   >64:A1 1800000>mov eax,dword ptr fs:
76801D99   .8B90 DC0F0000 mov edx,dword ptr ds:
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:
76801DAC   .8D53 01       lea edx,dword ptr ds:
76801DAF   .51            push ecx
76801DB0   .50            push eax
76801DB1   .895424 30   mov dword ptr ss:,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:
76801DC3   .8A00          mov al,byte ptr ds:
76801DC5   .84C0          test al,al
76801DC7   .74 1C         je short user32.76801DE5
76801DC9   .0FB60B      movzx ecx,byte ptr ds:
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:
76801DE5   >43            inc ebx
76801DE6   .EB 14         jmp short user32.76801DFC
76801DE8   >0FB603      movzx eax,byte ptr ds:
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:
76801DFC   >8A0B          mov cl,byte ptr ds:
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加载进去,把代码页改了齐活。

苏紫方璇 发表于 2021-8-30 17:54

flyingdancex 发表于 2021-8-30 16:57
意思是要改系统user32.dll文件里的IsDBCSLeadByteEx,还是,唉~!还是没看明白...

改代码页就可以了,之所以没出成品,因为我无法定位修改的位置,不同的系统位置不一样

白鱼啊 发表于 2022-4-19 16:23

antclt 发表于 2021-8-30 16:12

看半天意思明白了但还是解决不了...

flyingdancex 发表于 2021-8-30 16:57

意思是要改系统user32.dll文件里的IsDBCSLeadByteEx,还是,唉~!还是没看明白...

bjxiaoyao 发表于 2021-8-30 18:13

学习了,原来系统问题还可以这样分析,这才是从根源上解决问题。虽然最难,但是最彻底。

阿迪服饰 发表于 2021-8-30 20:03

可以很强大

阿迪服饰 发表于 2021-8-30 20:03

可以很强

suadzh 发表于 2021-8-30 22:05

苏紫方璇YYDS

lovehfs 发表于 2021-8-30 22:33

值得试一下

Sky_M 发表于 2021-8-31 09:18

虽然没用,先留着以后用
页: [1] 2 3 4
查看完整版本: 解决vb6和delphi7在win10下输入中文乱码问题