输入法注入及防护分析

news/2025/1/24 7:18:49/

 一 .输入法原理:

输入法的ime文件实质是个dll文件,导出windows的imm输入法管理器调用的一些回调函数。

初始化:

DllMain里注册窗口类

1. ImeInquire里告诉imm输入法的me消息窗口的类名

2. imm根据这个类名创建ime消息窗口

3. 消息窗口的回调函数被调用, 消息是wm_create

至此, 用户就可以开始使用输入法了,之后顺序是:

1. 用户按下一个键

2. ImeProcessKey返回true, 表示输入法想处理这个键

3. ImeToAsciiEx被调用

4. 此函数创建一些ime消息, 如开始/结束输入法编辑, 设置comp串, cand串, 显示comp窗口, 显示状态栏窗口, 提交等

5. 相应的窗口被创建, 显示,

6. 如果当前的应用程序是懂输入法的, 它自己也会显示comp串, 前提是你的ImeToAsciiEx需要告诉它comp串是什么

 

 

 

二.输入法注入原理总结:

输入法ime文件实现功能 :

1.导出imm输入法管理器要求的几个必须的函数

2.导出一个初始化和一个释放空间的函数.初始化函数用于设置目标dll的路径及回调函数的参数信息。释放空间函数用于重置回调函数参数及恢复dll加载的参数。

3.在dllmain里通过LoadLibrary加载注入的目标dll 

3.(可选)可以通过GetProcAddress回调目标dll实现的某个回调函数,函数声明格式固定。

 

安装卸载输入法ime的主程序实现功能:

1.通过ImmInstallIME安装已经实现的输入法文件。

2.如果安装失败,通过GetKeyboardLayoutList得到输入法列表,判断是否已经安装,给错误提示.

3.安装成功的话,调用ime文件的导出的初始化函数,实现对目标dll的初始化.

4.可以通过FindWindowsEx遍历窗口或者只给顶层窗口,实现对所有窗口或者顶层窗口发送

WM_INPUTLANGCHANGEREQUEST消息,激活输入法。

 

目标dll:

1.导出回调函数供输入法ime文件调用

2.自己实现任意功能。

3火星文输入法外挂中是RegisterWindowMessage注册消息钩子与主程序通信。然后inline hook前五个字节,hook imm32.lib的ImmGetCompositionStringA和ImmGetCompositionStringW函数,实现对输入文字的修改.

 

 

 

三. 目前考虑的防护方式:

关于主防拦截:

1.输入法安装主要通过ImmInstallIME()函数,在驱动中过滤这个函数,实现对输入法安装拦截.

2.输入法安装后需要通过发送WM_INPUTLANGCHANGEREQUEST消息在指定窗口中激活输入法。在驱动中通过过滤NtUserGetMessage,拦截消息处理。

3.输入法安装需修改两处注册表值,在驱动中检测对这两处注册表值得更改。

 

关于加载输入法后的检测自保:

1.通过过滤NtImeSetValue函数得到输入的按键信息,检测已经安装的输入法。

2.通过过滤WM_IME_COMPOSITION消息得到CompositionString,在消息的INPUTCONTEXT 中得到按键的输入的字符。

3.输入法加载后一般会在输入法中加载目标dll注入到目标进程中,可以过滤loadlibrary等函数做一般的dll注入的检测。

4.过滤imexxx函数即输入法调用实现的相关内核中的函数检测输入法的功能调用

 

 

四. 第三代输入法注入样本:

以前的输入法注入是通过在伪造的输入法中加载恶意的dll,需要伪造输入法文件,恶意dll和安装输入法的控制程序。

在 http://blogs.avg.com/news-threats/ime-injection-evolution/ ;

这个avg的样本中所述的第三代输入法注入样本是hook 了ZwQueryValueKey函数。

原理如下:

1.用户在每次激活输入法时,系统会调用ImmLoadLayout激活载入键盘布局文件,即输入法文件,参数为文件的路径。

系统在ImmLoadLayout通过ZwQueryValueKey读注册表查询ime file name及路径,由于恶意软件hook了ZwQueryValueKey函数,返回任意文件名,

这个任意文件就是恶意代码文件。

2.恶意软件向explorer 进程发送 WM_INPUTLANGCHANGEREQUEST 消息激活输入法。Explorer进程会调用 ImmLoadIME,在这个函数中,会调用loadlibrary装载

ImmGetImeInfoEx返回的一个dll文件,这个dll文件就是第1步中的任意文件。

通过这两步,这个恶意dll文件即被explore进程装载

这种不需要安装输入法文件的输入法注入方式不用调用ImmInstallIME()安装输入法,故隐蔽性更好。

 

故对输入法注入的防护需要对ImmLoadLayout()函数的过滤监控.

 

五.参考资料:

1.泄露win2k源码(win2k\private\ntos\w32\ntuser\imm),reactos的win32k.sys代码(ReactOS-0.3.15-REL-src\ntoskrnl\ex\win32k.c)

过程如下:

安装时ImmInstallIME(ime路径,输入法名字)

该部分代码在imm32.dll中,我逆向xp的代码和泄露源码基本一样。

LoadVersionInof(判断imm版本号)-->GetImeLayout(获取当前键盘布局,如果有重名的,做冲突或升级处理)?AssignNewLayout(根据最大的ime handl计算一个新的id号给新输入法)

?WriteImeLayout(在注册表中新建一个键项,设置imefile,layout file,layout text值)->LoadKeyboardLayout(调用win32k.sys的 NtUserLoadKeyboardLayoutEx)

然后,在win32k.sys中,经过逆向,处理过程如下

遍历列表在链表中增加新输入法元素->_xxxInternalActivateKeyboardLayout(向本线程发送WM_INPUTLANGCHANGEREQUEST消息激活输入法)-> LoadKeyboardLayoutFile()->ReadLayoutFile(通过ZwCreateSection,

ZwMapViewOfSection内存添加目标的输入法dll文件)

 

 

typedef struct {  //属性信息,没句柄,没路径

  DWORD dwPrivateDataSize;

  DWORD fdwProperty;

  DWORD fdwConverstionCaps;

  DWORD fdwSentenceCaps;

  DWORD fdwUICaps;

  DWORD fdwSCSCaps;

  DWORD fdwSelectCaps;

} IMEINFO;

 

typedef struct tagIMEINFOEX {  //有句柄,有路径,只有它包含路径,区分标识一个路径,全局的存在驱动里

    HKL                 hkl;                                                         //0

    IMEINFO             ImeInfo;                                                     //4

    WCHAR               wszUIClass[IM_UI_CLASS_SIZE];                              //size=16  32

    DWORD               fdwInitConvMode;    // Check this later                    //64

    BOOL                fInitOpen;          // Check this later                     //68

    BOOL                fLoadFlag;                                                  //72

    DWORD               dwProdVersion;                                             //76

    DWORD               dwImeWinVersion;                                           //80

    WCHAR               wszImeDescription[IM_DESC_SIZE];  //size=50  84

    WCHAR               wszImeFile[IM_FILE_SIZE];  //size=80  184 只有文件名,路径默认system32

} IMEINFOEX, *PIMEINFOEX;                           //184+80*2=0x158

 

 

typedef struct tagIMEDPI {    //immuser.h  //有句柄,有函数,没路径,区分标识dll文件,全局链表的存在imm32.dll

    struct tagIMEDPI   *pNext;

    HANDLE              hInst;

    HKL                 hKL;

    IMEINFO             ImeInfo;

    DWORD               dwCodePage;

    WCHAR               wszUIClass[IM_UI_CLASS_SIZE];

    DWORD               cLock;

    DWORD               dwFlag;

 

    struct _tagImeFunctions {

        union {PFNINQUIREA       a; PFNINQUIREW       w; PVOID t;} ImeInquire;

        union {PFNCONVLISTA      a; PFNCONVLISTW      w; PVOID t;} ImeConversionList;

        union {PFNREGWORDA       a; PFNREGWORDW       w; PVOID t;} ImeRegisterWord;

        union {PFNUNREGWORDA     a; PFNUNREGWORDW     w; PVOID t;} ImeUnregisterWord;

        union {PFNGETREGWORDSTYA a; PFNGETREGWORDSTYW w; PVOID t;} ImeGetRegisterWordStyle;

        union {PFNENUMREGWORDA   a; PFNENUMREGWORDW   w; PVOID t;} ImeEnumRegisterWord;

        PFNCONFIGURE                                                 ImeConfigure;

        PFNDESTROY                                                 ImeDestroy;

        PFNESCAPE                                                  ImeEscape;

        PFNPROCESSKEY                                              ImeProcessKey;

        PFNSELECT                                                  ImeSelect;

        PFNSETACTIVEC                                              ImeSetActiveContext;

        PFNTOASCEX                                                 ImeToAsciiEx;

        PFNNOTIFY                                                  NotifyIME;

        PFNSETCOMPSTR                                              ImeSetCompositionString;

        PFNGETIMEMENUITEMS                                         ImeGetImeMenuItems;

    } pfn;

 

} IMEDPI, *PIMEDPI;

 

HKEY_CURRENT_USER\keyboard layout\preload 当前

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts]

 

 

typedef struct tagIMELAYOUT {  //暂时不用看

    HKL     hImeKL;

    WCHAR   szKeyName[HEX_ASCII_SIZE];

    WCHAR   szImeName[IM_FILE_SIZE];

} IMELAYOUT, *PIMELAYOUT;

 

 

kd> dd f88e94a0

f88e94a0  e0010804 00000008 8e050338 0011da50

f88e94b0  0007f670 746af7ca 0011da50 0007f930

f88e94c0  746b0577 000a71d0 000000f5 0011da50

f88e94d0  00000000 0011e798 746b059b 7c939d8a

f88e94e0  00000009 000a7624 00000042 7d5c44a9

f88e94f0  0007f9bc 00010094 00000001 0007f694

f88e9500  77d18830 76313c0c 76316020 76313c1a

f88e9510  ffffffff 7d5c4513 77d18734 00010094

kd> dd

f88e9520  00000014 01010056 00000000 746b6adb

f88e9530  00000000 0007f7bc 7c8328f4 0007f7e4

f88e9540  001d8a20 00000010 0007f7e4 e0010804

f88e9550  7c811726 0007f65c 77d1882a 00000000

f88e9560  000cc0d8 e0010804 001200a5 0011da10

f88e9570  7c9378b0 746b6adb 00000000 00161468

f88e9580  0007fd94 00161480 0007f7a0 7c93795c

f88e9590  00161480 00000000 000e7b20 00000008

kd> dd f88e94a0+158-a0

f88e9558  77d1882a 00000000 000cc0d8 e0010804

f88e9568  001200a5 0011da10 7c9378b0 746b6adb

f88e9578  00000000 00161468 0007fd94 00161480

f88e9588  0007f7a0 7c93795c 00161480 00000000

f88e9598  000e7b20 00000008 7c937790 746b6adb

f88e95a8  00000000 00000020 0007f7d4 000c87a0

f88e95b8  7ffdd000 0007f79c 00090000 7c930202

f88e95c8  0000000c 000908c8 00090000 00129308

kd> p

win32k!NtUserGetImeInfoEx+0x7a:

bf914b49 898588feffff    mov     dword ptr [ebp-178h],eax

kd> dd f88e94a0

f88e94a0  e0010804 0006e0e8 7c92cfd0 00000000

f88e94b0  0006e214 7c92e900 7c930208 00000000

f88e94c0  01109b28 0006e030 00070000 7c930202

f88e94d0  00000016 00070aa8 00070000 010f9a98

f88e94e0  0006e008 0000001e 00000000 00050001

f88e94f0  00040000 62fc5168 51658f93 00206cd5

f88e9500  002e0035 00200030 00007248 00000000

f88e9510  00000000 7c92cfd0 7c9350f2 00000024

kd> dd f88e94a0+158-a0

f88e9558  00690077 0070006e 002e0079 006d0069

f88e9568  00000065 000706e8 0006e0dc 00070000

f88e9578  7c930202 00000005 00070778 00070000

f88e9588  01109848 0006e0b4 7c930202 0006e2f8

f88e9598  7c92e900 7c930208 ffffffff 7c930202

f88e95a8  7c93017b 7c9301bb 80000005 7c92d950

f88e95b8  7f6f31f8 7c80f8d8 0010000e 7c80f3ac

f88e95c8  7c92fe2a 00000008 0007ec18 00000000

kd> du f88e94a0+158-a0

f88e9558  "winpy.ime"

 

 

bf914b3c 6a00            push    0  下断 

bf914b3e e8f9eceeff      call    win32k!_GetProcessWindowStation (bf80383c)

bf914b43 50              push    eax

bf914b44 e8ba2c0100      call    win32k!GetImeInfoEx (bf927803)

bf914b49 898588feffff    mov     dword ptr [ebp-178h],eax ss:0010:f88e949 下断

 

 

08040804 

 

 

--写于2013-11-3


http://www.ppmy.cn/news/577404.html

相关文章

病毒扫描策略配置

Linux下的病毒扫描 ClamAV(Clam AntiVirus)是Unix/Linux系统下免费开源的防毒软件,它是专为邮件服务器网关上电子邮件的扫描而设计,提供电子邮件的病毒扫描。ClamAV提供了灵活的可伸缩监控程序、命令行扫描程序和用于更新病毒数据库的工具,更重要的是它的核心代码可用于各…

常子骎的笔记

1. Nmap的基本 Nmap ip 6 ip Nmap -A 开启操作系统识别和版本识别功能 – T(0-6档) 设置扫描的速度 一般设置T4 过快容易被发现 -v 显示信息的级别,-vv显示更详细的信息 192.168.1.1/24 扫描C段 192.168.11 -254 上 nmap -A -T…

macOS FreeBSD 如何刷新 DNS 缓存

macOS FreeBSD 如何刷新 DNS 缓存 全文:如何刷新 DNS 缓存 (macOS, Linux, Windows) Unix Linux Windows 如何刷新 DNS 缓存 (macOS, FreeBSD, RHEL, CentOS, Debian, Ubuntu, Windows) 请访问原文链接:https://sysin.org/blog/how-to-flush-dns-cach…

180420 逆向-DDCTF_WP(Re)

Reverse Baby MIPS IDA打开发现几个字符串结构都很清晰,提供16个变量,然后进行16次方程校验 但是运行会发现在中间就因为段错误而异常 尝试许久以后发现几个不太对劲的指令,突兀出现的 t, t , sp, 跳转等等的机器码都为EB02开头&#xff…

关于木马免杀的一些方法

一、免杀简述 ​ 理论上讲,免杀⼀定是出现在杀毒软件之后的。⽽通过杀毒软件的发展史不难知 道,第⼀款杀毒软件 kill 1.0是Wish公司1987年推出的,也就是说免杀技术⾄少是在 1989年以后才发展起来的。 ​ 1989年:第⼀款杀毒软件M…

76%都存在漏洞?!Docker镜像安全扫描应该这样做

在之前的文章《从自身漏洞与架构缺陷,谈Docker安全建设》中,我们介绍了Docker存在的安全问题、整套Docker应用架构的安全基线以及安全规则,重头戏是Docker安全规则的各种思路和方案。 本文作为“续集”,考虑到镜像安全问题的普遍性…

利用AI+大数据的方式分析恶意样本(十六)

有关静态分析的三篇论文以及一篇恶意代码可视化的论文阅读 文章目录 有关静态分析的三篇论文以及一篇恶意代码可视化的论文阅读基于两维二进制程序特征和深度神经网络的恶意代码检测 15年发表modelfeature字节熵直方图导入函数表PE元数据信息 labelNetworkbayesian校准评估和数…

杀毒软件 防火墙 PHPIDS打造php网站服务器三位一体宙斯盾安防

张智翔 杀毒软件防火墙 PHPIDS打造php网站服务器三位一体宙斯盾安防  只要要发布信息到外网,就不可避免的碰到入侵与嗅探,环眼扫去,安全事故层出不穷,尤其php在web服务器这一块的巨大市场,如何打造安全体系呢&#x…