spi滤包技术之2解

    以前我写过一篇讲spi滤包的文章,所以对于spi的细节,这里就不多讲了,不了解的可以看一下我以前那篇《关于spi滤包技术的研究》。后来我发现,其实对spi中间层的修改,其实质就是对注册表的修改。所有spi的dll,其路径都存放在注册表中。因此,用自定义的中间层插入系统spi列表,其实质也就是改动了注册表。
    基于这个原因,于是我们想到了更为直接的方法(当然,不是我想到的):直接修改注册表。我们先找到注册表中存放spi之dll路径的地方:
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/WinSock2/Parameters/Protocol_Catalog9/Catalog_Entries
这里就存放有这些dll的路径。然后,我们只要将这些路径都改为自定义的dll的路径,然后在自定义的dll里面执行了自己的代码后,再加载原先那些spi的dll,岂不是就可以达到插入中间层同样的效果了?
    以上就是我所谓的“spi滤包技术之2解”的大体思路了。从技术上讲,无非就是修改注册表,技术含量不高,但是,这也算是从另一个角度去思考,得到了解决问题的另一种方法。所谓“条条道路通罗马”,在这里又一次得到了证明。
    好,废话不多讲了,说干就干。下面我们就通过代码来具体说明吧!代码同样分两部分:安装部分和dll部分。

1,安装部分:

#include "stdafx.h"
#include "stdio.h"
#include "ws2spi.h"
#include "windows.h"
#pragma comment(lib,"ws2_32.lib")

#define SPI_REG_KEY "System//CurrentControlSet//Services//WinSock2//Parameters//Protocol_Catalog9//Catalog_Entries"
#define SAVE_REG_KEY "System//CurrentControlSet//Services//WinSock2//Parameters//SPIDLL"
#define KEY_VALUE_LEN MAX_PATH+sizeof(WSAPROTOCOL_INFOW)


void usage()
{
printf("***********************************/n");
printf("*        Made by ffantasyYD       */n");
printf("*           QQ:76889713           */n");
    printf("*     email:ffantasyYD@163.com    */n");
printf("***********************************/n");
printf("This program have 1 parameter: InstallFilter (/install or /remove)/n");
printf("If you select '/install',you will install the filter;/n");
printf("and if you select '/remove',you will remove the filter that you have installed./n");
}

void install()
{
HKEY hKey,hSubKey,hSaveKey;
ULONG index=0,size=KEY_VALUE_LEN;
WSAPROTOCOL_INFOW protoInfo={0};
char dllPath[MAX_PATH]={0},name[128]={0},keyValue[KEY_VALUE_LEN]={0},
     copyDllPath[MAX_PATH]={0};

//检查是否已安装: if(::RegOpenKey(HKEY_LOCAL_MACHINE,SAVE_REG_KEY,&hSaveKey)==ERROR_SUCCESS)
{
printf("The filter has been installed!/n");
return;
}
::RegCloseKey(hSaveKey);

::GetCurrentDirectory(MAX_PATH,dllPath);
strcat(dllPath,"//PacketFilter.dll");
//这里设置dll拷贝至的路径:
memcpy(copyDllPath,"c://mmty.dll",strlen("c://mmty.dll"));
CopyFile(dllPath,copyDllPath,0);

::RegOpenKey(HKEY_LOCAL_MACHINE,SPI_REG_KEY,&hKey);
while(::RegEnumKey(hKey,index,name,128)==ERROR_SUCCESS)
{
::RegOpenKey(hKey,name,&hSubKey);
::RegQueryValueEx(hSubKey,"PackedCatalogItem",0,NULL,(BYTE *)keyValue,&size);
//printf("%s/n",keyValue);

memcpy(&protoInfo,keyValue+MAX_PATH,sizeof(WSAPROTOCOL_INFOW));
if((protoInfo.ProtocolChain.ChainLen==1)&&((protoInfo.iProtocol==6)||(protoInfo.iProtocol==17)))
{
char entryId[128]={0};

sprintf(entryId,"%u",protoInfo.dwCatalogEntryId);
::RegCreateKey(HKEY_LOCAL_MACHINE,SAVE_REG_KEY,&hSaveKey);
::RegSetValueEx(hSaveKey,entryId,0,REG_SZ,(BYTE *)keyValue,MAX_PATH);

memset(keyValue,0,MAX_PATH);
memcpy(keyValue,copyDllPath,MAX_PATH);
::RegSetValueEx(hSubKey,"PackedCatalogItem",0,REG_BINARY,(BYTE *)keyValue,KEY_VALUE_LEN);
}

index++;
}

printf("Install successful!/n");
return;
}

void remove()
{
HKEY hKey,hSubKey,hSaveKey;
ULONG index=0,size=KEY_VALUE_LEN;
WSAPROTOCOL_INFOW protoInfo={0};
char dllPath[MAX_PATH]={0},name[128]={0},keyValue[KEY_VALUE_LEN]={0};

//检查是否已安装:
if(::RegOpenKey(HKEY_LOCAL_MACHINE,SAVE_REG_KEY,&hSaveKey)!=ERROR_SUCCESS)
{
printf("The filter hasn't been installed!/n");
return;
}

::RegOpenKey(HKEY_LOCAL_MACHINE,SPI_REG_KEY,&hKey);
while(::RegEnumKey(hKey,index,name,128)==ERROR_SUCCESS)
{
::RegOpenKey(hKey,name,&hSubKey);
::RegQueryValueEx(hSubKey,"PackedCatalogItem",0,NULL,(BYTE *)keyValue,&size);

memcpy(&protoInfo,keyValue+MAX_PATH,sizeof(WSAPROTOCOL_INFOW));
if((protoInfo.ProtocolChain.ChainLen==1)&&((protoInfo.iProtocol==6)||(protoInfo.iProtocol==17)))
{
char entryId[128]={0};
ULONG sizeOfPath=MAX_PATH;
sprintf(entryId,"%u",protoInfo.dwCatalogEntryId);
//printf("%s/n",entryId);

::RegQueryValueEx(hSaveKey,entryId,0,NULL,(BYTE *)dllPath,&sizeOfPath);

memset(keyValue,0,MAX_PATH);
memcpy(keyValue,dllPath,MAX_PATH);
::RegSetValueEx(hSubKey,"PackedCatalogItem",0,REG_BINARY,(BYTE *)keyValue,KEY_VALUE_LEN);
}
index++;
}
//删除拷贝至c盘下的dll:
DeleteFile("c://mmty.dll");

::RegCloseKey(hKey);
::RegOpenKey(HKEY_LOCAL_MACHINE,"System//CurrentControlSet//Services//WinSock2//Parameters",&hKey);
::RegDeleteKey(hKey,"SPIDLL");
printf("Remove successful!/n");
return;
}

int main(int argc, char* argv[])
{
usage();
if(argc!=2)
{
return 0;
}
printf("Start............../n");

if(strcmp(argv[1],"/install")==0)
{
install();
return 0;
}
if(strcmp(argv[1],"/remove")==0)
{
remove();
return 0;
}

printf("The parameter error!/n");
return 0;
}

2,DLL部分:

#include "StdAfx.h"
#include "ws2spi.h"
#include "windows.h"
#include "stdio.h"
#pragma comment (lib,"ws2_32.lib")

#define SAVE_REG_KEY "System//CurrentControlSet//Services//WinSock2//Parameters//SPIDLL"

WSPPROC_TABLE sourceProcTable;

int WSPAPI WSPConnect (SOCKET s,                          
                       const struct sockaddr FAR * name,  
                       int namelen,                       
                       LPWSABUF lpCallerData,             
                       LPWSABUF lpCalleeData,             
                       LPQOS lpSQOS,                      
                       LPQOS lpGQOS,                      
                       LPINT lpErrno)
{
sockaddr_in addr_in={0};
FILE *pf=fopen("c://spiLog.txt","a");
char *ip;

memcpy(&addr_in,name,sizeof(sockaddr));
ip=inet_ntoa(addr_in.sin_addr);
fprintf(pf,"Connect to %s/n",ip);

fclose(pf);
return sourceProcTable.lpWSPConnect(s,name,namelen,lpCallerData,lpCalleeData,lpSQOS,lpGQOS,lpErrno);
}

SOCKET WSPAPI WSPSocket(
int af,                              
int type,                            
int protocol,                        
LPWSAPROTOCOL_INFOW lpProtocolInfo,  
GROUP g,                             
DWORD dwFlags,                       
LPINT lpErrno
)
{
FILE *pf=fopen("c://spiLog.txt","a");
fprintf(pf,"Start socket!/n");
fclose(pf);

return sourceProcTable.lpWSPSocket(
af, type, protocol, lpProtocolInfo, g, dwFlags, lpErrno);
}

int WSPAPI WSPSendTo (
  SOCKET s,                                                
  LPWSABUF lpBuffers,                                      
  DWORD dwBufferCount,                                     
  LPDWORD lpNumberOfBytesSent,                             
  DWORD dwFlags,                                           
  const struct sockaddr FAR * lpTo,                        
  int iTolen,                                              
  LPWSAOVERLAPPED lpOverlapped,                            
  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,  
  LPWSATHREADID lpThreadId,                                
  LPINT lpErrno                                            
)
{
sockaddr_in addr_in={0};
FILE *pf=fopen("c://spiLog.txt","a");
char *ip;

memcpy(&addr_in,lpTo,sizeof(sockaddr));
ip=inet_ntoa(addr_in.sin_addr);
fprintf(pf,"Send to %s/n",ip);

fclose(pf);
return sourceProcTable.lpWSPSendTo(s,lpBuffers,dwBufferCount,lpNumberOfBytesSent,dwFlags,lpTo,iTolen,lpOverlapped,
                               lpCompletionRoutine,lpThreadId,lpErrno);
}

BOOL WINAPI DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
 )
{
// FILE *pf=fopen("start.txt","w");
// fprintf(pf,"Start:/n");
// fclose(pf);
    return TRUE;
}

int WSPAPI WSPStartup(WORD  wVersionRequested,
  LPWSPDATA  lpWSPData,
  LPWSAPROTOCOL_INFOW  lpProtocolInfo,
  WSPUPCALLTABLE  upcallTable,
  LPWSPPROC_TABLE  lpProcTable)
{
HKEY hSaveKey;
HMODULE hSourceDll=NULL;
LPWSPSTARTUP lpWspStartup=NULL;
char entryId[128]={0},dllPath[MAX_PATH]={0},expandDllPath[MAX_PATH]={0};
ULONG size=MAX_PATH,uEntryId=0;
int chainLen=lpProtocolInfo->ProtocolChain.ChainLen;

if(chainLen<=1)
{
uEntryId=lpProtocolInfo->dwCatalogEntryId;
}
else
{
uEntryId=lpProtocolInfo->ProtocolChain.ChainEntries[chainLen-1];
}
::RegOpenKey(HKEY_LOCAL_MACHINE,SAVE_REG_KEY,&hSaveKey);
sprintf(entryId,"%u",uEntryId);
::RegQueryValueEx(hSaveKey,entryId,0,NULL,(BYTE *)dllPath,&size);
ExpandEnvironmentStrings(dllPath,expandDllPath,MAX_PATH);

hSourceDll=::LoadLibrary(expandDllPath);
lpWspStartup=(LPWSPSTARTUP)::GetProcAddress(hSourceDll,"WSPStartup");
lpWspStartup(wVersionRequested,lpWSPData,lpProtocolInfo,upcallTable,lpProcTable);

sourceProcTable=*lpProcTable;

lpProcTable->lpWSPSendTo=WSPSendTo;
lpProcTable->lpWSPConnect=WSPConnect;
lpProcTable->lpWSPSocket=WSPSocket;

return 0;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值