映射注入
2023-12-27 15:59:19 Author: moonsec(查看原文) 阅读量:11 收藏

本文所有代码回复2023-12-26获取。

简介

针对于各大安全厂商对私有内存的监控,就是我们之前使用VirtualAlloc/EX来申请的内存,最后执行shellcode如下图是RWX的内存区域,里面是我们的shellcode。

映射注入

由于各大安全厂商以及安全软件对分配私有内存有着高度监控,所以为了避免使用一些常见的API函数,比如VirtualAlloc/EX,VirtualProtect/Ex,映射注入使用Mapped内存类型,并使用不同的Win API函数,例如CreateFileMapping和MapViewOfFile。

需要注意的是VirtualProtect是无法更改更改映射内存的内存权限。

创建文件映射

这里需要用到如下函数:

CreateFileMapping

经微软介绍CreateFileMapping函数可以创建或打开命名或未命名的文件映射对象,该对象通过内存映射技术对文件内容的访问,它允许进程创建虚拟内存空间,映射到磁盘上文件的内容或另一个内存位置。该函数返回文件映射对象的句柄。

HANDLE CreateFileMappingA(  [in]           HANDLE                hFile,  [in, optional] LPSECURITY_ATTRIBUTES lpFileMappingAttributes,  [in]           DWORD                 flProtect,  [in]           DWORD                 dwMaximumSizeHigh,  [in]           DWORD                 dwMaximumSizeLow,  [in, optional] LPCSTR                lpName);

hFile 用于创建文件映射对象的文件的句柄,由于在实现中不需要从文件中创建文件映射因此可以使用INVALID_HANDLE_VALUE标志来代替,微软对INVALID_HANDLE_VALUE的解释是:

如果 hFile INVALID_HANDLE_VALUE,则调⽤进程还必须在dwMaximumSizeHigh和dwMaximumSizeLow参数中指定映射对象的大小,在这种情况下CreateFileMappingA创建指定大小的文件映射对象。设置此标志允许函数在不使用磁盘中的文件的情况下执行任务,而是在内存中创建文件映射对象,大小由dwMaximumSizeHigh和dwMaximumSizeLow参数来决定的。

flProtect参数表示指定文件映射对象的权限,这里我们设置为PAGE_EXECUTE_READWRITE权限即可,这里并不会立即创建RWX的内存区域,而是稍后进行创建,我们如果设置PAGE_READWRITE的话,后续shellcode将无法执行。

MapViewOfFile

MapViewOfFile函数会将文件映射的视图映射到调用进程的地址空间中,它获取文件映射对象的句柄和所需的访问权限,并返回指向进程地址空间中映射开头的指针。

LPVOID MapViewOfFile(  [in] HANDLE hFileMappingObject,  [in] DWORD  dwDesiredAccess,  [in] DWORD  dwFileOffsetHigh,  [in] DWORD  dwFileOffsetLow,  [in] SIZE_T dwNumberOfBytesToMap);

hFileMappingObject参数表示文件映射对象的句柄,也就是上面我们通过CreateFileMapping创建的文件映射,dwDesiredAccess参数表示文件映射的访问类型,这里我们将其设置为FILE_MAP_EXECUTE和FILE_MAP_WRITE标志来返回有效的可执行和可写的内存。

代码编写

首先通过CreateFileMapping函数创建一个文件映射句柄。

这里的第一个参数我们上面说过了给他一个INVALID_HANDLE_VALUE标志,不需要从文件中创建文件映射,还有就是四个和第五个参数指定的就是映射对象的大小,这里我们第五个参数指定shellcode的大小即可,并且第三个参数我们需要指定PAGE_EXECUTE_READWRITE表示我们需要RWX的内存区域,但不是立即创建,而是稍后创建。

hFile = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, NULL, shellcodeSize, NULL);

创建完成文件映射之后,接下来需要来将文件映射的视图映射到进程的地址空间中。

这里第一个参数是我们上面通过CreateFileMapping函数拿到的文件映射的句柄,第二个参数就是我们上面说过的,需要将其设置为FILE_MAP_EXECUTE和FILE_MAP_WRITE标志,来返回有效的可执行和可写的内存,最后一个参数就是shellcode的大小。

pMapAddress = MapViewOfFile(hFile, FILE_MAP_WRITE | FILE_MAP_EXECUTE, NULL, NULL, shellcodeSize);

这前两步我们可以理解为VirtualAlloc这一类的函数。

创建完成之后,我们拿到了创建好内存的地址,然后通过memcpy将shellcode复制到创建好的内存地址中。

copy shellcode到内存。

最后我们通过回调函数去执行即可,当然你也可以使用创建线程的方式,或者指针的方式都可以。

EnumChildWindows(NULL, (WNDENUMPROC)Address, NULL);

但是我们提前得把这块内存的地址给他带出来。

*ppAddress = Address;

UnmapviewOfFile

UnmapviewOfFile函数用于取消映射先前映射的内存,这个一般我们在执行完shellcode之后再去调用,而不是正在运行中,UnmapviewOfFile函数只需要取消映射的文件映射视图的基地址,也就是Address。

我们来一步一步来跟一下:

首先将文件映射的视图映射到调用进程的地址空间,然后copy shellcode。

copy shellcode。

最后通过回调函数执行。


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMjc0NTEzMw==&mid=2653588248&idx=1&sn=3c0a72c00fa0a4f1f84a510220e1d10b&chksm=80d296f0cdcfbd158d19d0595bbf5c69e80ac8f758279f3d22a99c336a0669e17eb36ec54ff5&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh