揭秘星号密码查看器实现原理(第二篇)

2018年4月9日17:03:56 发表评论 4,747

揭秘星号密码查看器实现原理(第二篇)

相隔一个月,第二篇文章终于开始写了,鬼知道这一个月我干了什么。再上一篇文章中,用了SendMessage()和PostMessage()这两个API实现了星号密码查看器的功能,但是在测试中却发现,有些控件读不出来,猜测可能是SendMessage()消息在外部无法读取的原因,后来在网上看到一篇对星号密码查看器的分析帖子,就仿照其代码做了些修改,下面记录一下。其原理还是使用消息机制,但是这次使用了注入代码的方式,将我们的代码注入到指定进程中,在内部实现密码的读取。

0x01 基本原理

依然获取鼠标所在位置的控件进程句柄和控件句柄,然后使用VirtualAllocEx()函数在进程中开空间,将我们的读取密码框程序的代码使用WriteProcessMemory()注入到进程中,然后使用CreateRemoteThread()函数运行我们注入的代码函数,然后使用ReadProcessMemory()将读取到的密码拷贝到本地。

说白了,一堆API的调用。

0x02 定义注入代码

在注入代码中仍然是使用消息来获取密码——“SendMessage(hwnd, WM_GETTEXT, 255, long(buffer)) ”,我们需要定义个函数,然后函数里需要放我们的参数,包括读取的控件句柄,要发送的消息,缓冲区。因为的以线程的方式进行调用,所以我们定义成结构体的形式,代码如下:

Injectbegin()函数就是我们的注入函数,看不懂的建议看看8086汇编代码。

0x03 定义注入程序

注入程序我们需要拿到被注入进程的进程id,我们首先要对上面的结构体进行初始化,因为要用到SendMessage(),所以我们要在user32模块中使用GetModuleHandle("user32")和 GetProcAddress(hmod, _T("SendMessageA"))拿到SendMessage的函数地址,保存到结构体中,然后再进程中开辟两块空间,一块放结构体参数,一块放我们的注入代码。

代码注入成功后就可以使用CreateRemoteThread()函数调用远程Call,调用完成后密码就保存到了buffer缓冲区,我们只要使用ReadProcessMemory()函数读取进程的结构体复制到本地的结构体中就拿到了密码。具体代码如下:

需要注意的是,记得再注入完成后将空间释放掉。

0x04 完整的MFC程序

MFC程序包:

备注:代码是VS2017编译的,低版本会报错,可新建程序拷贝其中的代码。

0x05结束语

在次声明:本文中的注入程序代码部分参考自某论坛中的一篇星号密码查看器逆向分析修改得到,非本人原创。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: