导语:恶意软件是如何从网络浏览器中获取凭证的呢?目前,最热门的方法是MiTB(Man-in-The-Browser 浏览器中间者)攻击,它被称为inline hooking为人们所熟知(有时也称为detours)。

恶意软件是如何从网络浏览器中获取凭证的呢?目前,最热门的方法是MiTB(Man-in-The-Browser 浏览器中间者)攻击,它被称为inline hooking为人们所熟知(有时也称为detours)。inline hooks是非常通用的,而且在恶意软件中非常常见。通过使用inline hooks,恶意软件可以成为任何进程的puppetmaster,并且恶意软件作者可以操纵它来实现任何他们想实现的东西。下面让我们来看看是怎么实现的。

如何将代码插入目标程序中?

inline hooking的第一步是让代码在目标进程中运行。这个过程被称为注入。

一般情况下有几种常见的注入方法。例如,我们使用VirtualAllocEx,在0x0D000000的Firefox中创建一个内存区域。然后,CreateRemoteThread将被用于开始执行0x0D000000区域的Firefox,以便设置hooks,并处理初始化。(实际的注入过程本身就是一个很复杂的主题,超出了本文的范围。)下面是我们注入的代码块。随着继续注入,高亮显示的区域将变得更加清晰。

图片1.png 

inline hook有四个部分:the hook、恶意代码(这里的恶意代码全由NOPs组成)、被损坏字节的执行和回复。

什么是Windows API?

Windows API是一组函数和数据结构,Windows程序可以使用它来请求Windows执行一些命令,比如打开文件、显示消息,等等。Windows程序所执行的所有命令几乎都涉及到调用各种API函数。总的来说,Windows提供的所有API功能都称为“Windows API”。

图片2.png 

The hook

hook,有时被称为trampoline,类似于一个交通主管把交通改道到另一个位置。示例如下,我们将从ws2_32库中hook send()函数。下图是ws2_32!中最初的几条指令,像正常情况下一样发送函数。为了放置hook,我们需要覆盖函数中的一些现有指令。图中的绿色框突出显示了我们将要覆盖的字节。

图片3.png 

由于hook占用5个字节,因此将有5个字节被覆盖,jmp指令跳转到0x0D000000的代码中。(还有其他放置hook的方法,如使用push addr与ret指令组合)。下面是放置了hook之后的同一个send()函数:

图片4.png 

 

恶意代码

既然,执行流程被重定向到我们的注入代码中,必须保存寄存器,以确保当我们返回执行send()函数时不会崩溃。在32位进程中,我们可以使用pusha指令保存所有寄存器。当恶意代码完成执行时,popad指令将把所有寄存器恢复到send()函数被最初执行调用时所处的状态。既然我们已经控制了send()函数,可以实现很多有趣的指令。其中一件就是我们可以查看是否发送了POST请求,并将该数据发送回我们的命令和控制,希望它包含登录凭证。

被损坏字节的执行和回复

在对恶意代码做了一些修改之后,我们必须确保我们的进程能够跳转回与之hook的原函数。

首先,我们使用popad指令来恢复所有的寄存器。在设置hook时损坏了5个字节,由于这些原始指令仍然需要运行,所以在hook的进程中这5个字节被复制到恶意代码的末尾,以便在寄存器恢复后无缝地运行。最后,我们安全地跳回到send函数+0x05(hook的长度)。

图片5.png 

 

总结

回顾上述所有的操作方法,然后把所有步骤按顺序整合到一张图片里。按照箭头的指示,可以看到,Firefox中一个正常的、没有被hook的send()函数的执行流程:

图片6.png 

注入detour之后,执行流程如下:

图片7.png 

 

需要hook API调用的情况

大家能随便想到一种情况需要hook所有可以想象到的API调用。下面列出了几个:

l. urlmon !URLDownloadToFile——用于拦截下载的文件。Shifu在每一个进程中都hook这个函数,以防止新出的恶意软件下载文件。
2. ws2_32!send——用于从未加密的流量中捕获POST凭证。
3. GetHostByName——Shifu hook这个函数是为了忽略它的命令和控制站点的流量。
4. ws2_32!recv——用于从未加密的流量中捕获传入的数据包数据。
5. Advapi32!CryptEncrypt——在它被加密之前用于捕获数据,因为它在输出send()函数时不是纯文本
6. Advapi32!CryptDecrypt——用于解密来自recv()函数的加密数据。
7. User32!GetMessage——Shifu在这里使用hook来拦截鼠标点击信息,以获得虚拟键盘点击的图片。
8. Kernel32!ExitProcess——有助于防止进程关闭(绕过游戏反作弊程序)

检测

下面是一个伪代码简单的解决方案,但如果攻击者是一个硬茬,则不太有效。下面的代码将检查api ExitProcess的序言是否从0xE9开始(opcode JMP)

FARPROC Address = GetProcAddress(GetModuleHandle("kernel32.dll"),"ExitProcess");
if (*(BYTE*)Address == 0xE9)
{
 printf("Api hookedn");//Do your thing
}
源链接

Hacking more

...