代码注入技术之Shellcode注入

来源:岁月联盟 编辑:猪蛋儿 时间:2020-01-29

代码注入是指在应用程序中注入任意外部代码的行为,有两种类型的代码注入
1.注入易受攻击的程序;
2.注入不易受攻击的程序;
如果代码注入是在易受攻击的应用程序中完成的,则可以通过利用在处理无效数据时发生的漏洞来实现。在这种情况下,代码注入的程度就取决于应用程序中的错误,我们也将其称为“漏洞”。但问题在于,应用程序应该具有可以被利用来获得代码执行的漏洞。
本系列针对第二种情况,即不希望或不需要该应用程序具有漏洞。正如所预料的那样,这为应用程序提供了一个非常广泛的领域,同时也为滥用操作系统提供了机会。
恶意软件通常使用此方法,因为执行代码注入之前不需要满足任何条件,并且操作系统本身也完全支持该方法。所有主要的操作系统都提供ABI和API,以与其他进程进行交互,控制它们后,在其他程序的进程空间中读写内存。
通过CreateRemoteThread API进行代码注入
CreateRemoteThread是Win32 API提供的用于在另一个进程中创建线程的函数。在另一个应用程序中创建线程之前,必须满足两个条件:
1.试图在另一个进程中创建线程的进程必须具有创建线程的权限,简单地说,这意味着与受害进程(目标是指我们要在其中创建线程的进程)具有相同或更高的权限。
2.两个进程(目标进程和攻击者进程)必须驻留在同一个会话中,如果会话标识符不匹配,将不会创建线程。
如果上述任何一个条件不满足,则操作系统本身将拒绝代码注入过程。
但这不并是Windows OS体系结构中的安全漏洞,而是由操作系统提供的功能。由于我们无法修改具有比我们更高的权限的进程,因此不会跨越安全边界。
算法
为了通过CreateRemoteThread API实现代码注入,我们必须遵循以下算法:
1.选择一个进程作为受害者进程;
2.使用带有参数PROCESS_ALL_ACCESS的OpenProcess函数获得对进程的访问权限,以便能够执行所需的操作;
3.如果OpenProcess失败,请退出;
4.使用VirtualAllocEx函数在受害者进程的进程空间中分配内存;
5.如果VirtualAllocEx失败,请退出;
6.将shellcode写入VirtualAllocEx分配的内存位置;
7.如果Shellcode写入失败或只有部分写入Shellcode,请退出;
8.编写完shellcode后,请使用必要的参数调用CreateRemoteThread,将shellcode的地址指向LPTHREAD_START_ROUTINE。
运行环境
就本文的示例而言,必须具备以下环境设置:
1.Visual Studio 2019;
2.Windows 10 RS6(x64);
注意:可以从我的github存储库访问代码。
代码注入
访问远程进程
要对任何进程执行内存操作,我们必须能够访问它。可以使用函数OpenProcess来获得它,该函数的原型为:

它包含三个参数:
1.dwDesiredAccess:它根据受害者进程的安全令牌进行检查,不过你可以指定一些所需的访问值,但是指定PROCESS_ALL_ACCESS包含该进程的所有可能的访问权限。
2.bInheritHandle:这是一个布尔值,指示该进程创建的进程是否将继承此句柄。
3.dwProcessId:这是受害者进程的进程标识符;
这个进程返回其他进程的句柄(成功时),其他API函数可以使用它来操作受害进程的内存。如果失败,则返回NULL。
为Shellcode分配空间
一旦获得了受害进程的句柄,我们就可以在受害进程内存中为shell代码分配空间,这是通过使用VirtualAllocEx API调用实现的。
VirtualAllocEx的原型为:

它包含五个参数:
1.hProcess:处理要在其中分配内存的进程;
2.lpAddress:指向受害者进程内存中指定地址的指针,如果将参数指定为NULL,则该函数自动选择要分配给的内存页;
3.dwSize:要分配的内存区域的大小,它是以字节为单位指定的。
4.flAllocationType:指定要分配的内存类型,该参数必须包含以下三个值之一:MEM_COMMIT,MEM_RESERVE,MEM_RESET,MEM_RESET_UNDO。
5.flProtect:指定分配的内存保护。出于我们的目的,由于它将包含要执行的代码,并且希望其具有可读性和可写性,因此将其设置为PAGE_EXECUTE_READWRITE。
该函数在成功时返回分配的基地址,而在失败时返回NULL。至此,我们已经成功地在受害进程中分配了可执行内存。
在远程进程中编写Shellcode
现在,我们需要在分配的区域中编写我们的shellcode。为此,我们有一个称为WriteProcessMemory的函数。
WriteProcessMemory是一种由调用者将数据写入指定进程的内存区域的函数,需要注意的是,整个内存区域必须是可写的,否则该函数将会失败,这就是为什么我们将内存分配为可写的,以及可读和可执行的原因。
WriteProcessMemory的原型为:

WriteProcessMemory具有五个参数:
1.hProcess:处理要向其中写入数据的进程;
2.lpBaseAddress:我们要在其中写入数据的地址(以指针的形式);
3.lpBuffer:指向必须写入的数据的指针,该指针必须是const指针。

[1] [2]  下一页