密码输入框显示明文问题分析
现场环境
wine版本: wine10.14
系统版本:debian12
问题描述
- 密码输入框显示明文,如下图:

分析流程
window下实现密码框通常设置window窗口ES_PASSWORD风格实现或者在wm_create中发送EM_SETPASSWORDCHAR消息设置window的edit为密码框
使用spy++发现wine下窗口风格与window下不一致,缺少ES_PASSWORD风格
查看msg/edit/win中逻辑,完成window下的demo,确认wine下的多行
ES_MULTILINE风格不支持加密,该应用加密逻辑大致如下:- 该应用使用的是
wingding.ttf中的字母l设置密码为黑圆圈。 - 在WM_CREATE中发送消息类似SendMessage(hPwd, EM_SETPASSWORDCHAR, ‘*’, 0),由于用的是
l字母所有这里发送的消息字符就是l - wingding这个字体wine中会自带,目前将window下的这个字体拷贝到容器中输入字符就会变化,目前原因还需要调研????
- 在设置密码为黑圆圈的时候有两种方案,1:将WCHAR消息进行拦截,在这进行修改,2:类似步骤2,在wm_create中发送一次EM_SETPASSWORDCHAR消息即可设置
- wine下收到EM_SETPASSWORDCHAR消息的时候,会在
EDIT_EM_SetPasswordChar函数进程处理,目前就是这里出问题,在wine中当edit窗口中风格有ES_MULTILINE直接返回,不会设置edit为密码窗口 - EDIT_EM_SetPasswordChar修改后还需要修改排版函数,不然输入的字符变成
wingding.ttf对应的符号,不是密码中的字符,所以需要修改EDIT_UpdateUniscribeData_linedef函数
- 该应用使用的是
查看wine下的user32/edit.c中的EDIT_EM_SetPasswordChar函数
1 | static void EDIT_EM_SetPasswordChar(EDITSTATE *es, WCHAR c) |
需要将EDIT_UpdateUniscribeData函数的EDIT_UpdateUniscribeData_linedef函数进行处理,第一个函数是处理单行的,第二个函数是处理编辑框多行风格的。在单行风格中有处理wine密码风格,让其显示密码型号,多行中没有,需要增加该逻辑,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49static SCRIPT_STRING_ANALYSIS EDIT_UpdateUniscribeData_linedef(EDITSTATE *es, HDC dc, LINEDEF *line_def)
{
if (!line_def)
return NULL;
if (line_def->net_length && !line_def->ssa)
{
int index = line_def->index;
HFONT old_font = NULL;
HDC udc = dc;
SCRIPT_TABDEF tabdef;
HRESULT hr;
if (!udc)
udc = NtUserGetDC(es->hwndSelf);
if (es->font)
old_font = SelectObject(udc, es->font);
tabdef.cTabStops = es->tabs_count;
tabdef.iScale = GdiGetCharDimensions(udc, NULL, NULL);
tabdef.pTabStops = es->tabs;
tabdef.iTabOrigin = 0;
if (es->style & ES_PASSWORD)
hr = ScriptStringAnalyse(udc, &es->password_char, line_def->net_length,
(1.5*line_def->net_length+16), -1,
SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_TAB|SSA_PASSWORD, -1,
NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa);
else
hr = ScriptStringAnalyse(udc, &es->text[index], line_def->net_length,
(1.5*line_def->net_length+16), -1,
SSA_LINK|SSA_FALLBACK|SSA_GLYPHS|SSA_TAB, -1,
NULL, NULL, NULL, &tabdef, NULL, &line_def->ssa);
if (FAILED(hr))
{
WARN("ScriptStringAnalyse failed (%lx)\n",hr);
line_def->ssa = NULL;
}
if (es->font)
SelectObject(udc, old_font);
if (udc != dc)
NtUserReleaseDC( es->hwndSelf, udc );
}
return line_def->ssa;
}修改后成功显示黑圆圈
