简易网络程序反HOOK技术

文章作者:MagicBear QQ130012321
信息来源:邪恶八进制信息安全团队( www.eviloctal.com

最近在搞一个网络程序,出后不久被破解,于是弄了一些反HOOK的技术
经测试WPE,IPSniffer,XSniffer等等著名Sniffer均告失效

检测内容:
1. 子程序地址是否在DLL空间内
2. 检查本机是否有运行RAW SOCKET类Sniffer
3. 检查GetFuncAddress返回地址是否与从IAT表获取地址相同
4. 检查地址开头是否有JMP
5. 对程序地址进行CRC校验,防止修改主程序及DLL内地址而使保护失效

P.S 需要主程序配合校验
主要是主程序调用,然后同时在DLL内备份一份并做CRC校验备份,主程序在每次发送前都调用DLL校验一次,对网络用量大的可能-0-...........欢迎丟鸡旦

//  LvKrnl.cpp : Defines the entry point for the DLL application.
//

#include 
" stdafx.h "
#include 
< winsock2.h >

#define  MAX_PACK_LEN 65535
#define  MAX_HOSTNAME_LAN 255
#pragma  comment (lib , "ws2_32.lib")

DWORD GetFunctionAddress( HMODULE phModule,
char *  pProcName )
{
        
if (!phModule)
                
return        0;
        PIMAGE_DOS_HEADER        pimDH        
=        (PIMAGE_DOS_HEADER)phModule;
        PIMAGE_NT_HEADERS        pimNH        
=        (PIMAGE_NT_HEADERS)((char*)phModule+pimDH->e_lfanew);
        PIMAGE_EXPORT_DIRECTORY        pimED        
=        (PIMAGE_EXPORT_DIRECTORY)((DWORD)phModule+pimNH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
        DWORD        pExportSize        
=        pimNH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
        DWORD        pResult        
=        0;

       
        
if ((DWORD)pProcName < 0x10000)
        
{
                
if ((DWORD)pProcName        >=        pimED->NumberOfFunctions+pimED->Base || (DWORD)pProcName < pimED->Base)
                        
return        0;
                pResult        
=        (DWORD)phModule+((DWORD*)((DWORD)phModule+pimED->AddressOfFunctions))[(DWORD)pProcName-pimED->Base];
        }
else
        
{
                DWORD
*        pAddressOfNames        =        (DWORD*)((DWORD)phModule+pimED->AddressOfNames);
                
for (int i=0;i<pimED->NumberOfNames;i++)
                
{
                        
char*        pExportName        =        (char*)(pAddressOfNames[i]+(DWORD)phModule);
                        
if (strcmp(pProcName,pExportName) == 0)
                        
{
                                WORD
*        pAddressOfNameOrdinals        =        (WORD*)((DWORD)phModule+pimED->AddressOfNameOrdinals);
                                pResult                
=        (DWORD)phModule+((DWORD*)((DWORD)phModule+pimED->AddressOfFunctions))[pAddressOfNameOrdinals[i]];
                                
break;
                        }

                }

        }

        
if  (pResult != 0 && pResult        >=        (DWORD)pimED        &&        pResult <        (DWORD)pimED+pExportSize)
        
{
                
char*        pDirectStr        =        (char*)pResult;
                
bool        pstrok        =        false;
                
while (*pDirectStr)
                
{
                        
if (*pDirectStr == '.')
                        
{
                                pstrok        
=        true;
                                
break;
                        }

                        pDirectStr
++;
                }

                
if (!pstrok)
                        
return        0;
                
char        pdllname[MAX_PATH];
                
int                pnamelen        =        pDirectStr-(char*)pResult;
                
if (pnamelen <= 0)
                        
return        0;
                memcpy(pdllname,(
char*)pResult,pnamelen);
                pdllname[pnamelen] 
= 0;
                HMODULE        phexmodule        
=        GetModuleHandle(pdllname);
                pResult        
=        GetFunctionAddress(phexmodule,pDirectStr+1);
        }


        
return pResult;
}


BOOL RawSnifferCheck()
{
    SOCKET SockRaw,Sock;
    WSADATA wsaData;
    
int ret=0;
    
struct sockaddr_in sAddr,addr;
    
char RecvBuf[MAX_PACK_LEN];
    
char FAR name[MAX_HOSTNAME_LAN];

    
struct hostent FAR * pHostent;
    
char *Buf;
    
int settimeout=100;//这里我们设置了一秒钟超时
    WSAStartup(MAKEWORD(2,2),&wsaData);
    
//建立一条RawSocket
    SockRaw=socket(AF_INET,SOCK_RAW,IPPROTO_IP);
    
//再建立一条UDP
    Sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    memset(
&sAddr,0,sizeof(sAddr));
    memset(
&addr,0,sizeof(addr));
    sAddr.sin_family
=AF_INET;
    sAddr.sin_port
=htons(35257);
    addr.sin_family
=AF_INET;

    addr.sin_port
=htons(35258);
    
//把IP地址指向本机
    addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    memset(RecvBuf,
0sizeof(RecvBuf));
    gethostname(name, MAX_HOSTNAME_LAN);
    pHostent
=gethostbyname(name);

    
//取得自己的IP地址
    memcpy(&sAddr.sin_addr.S_un.S_addr, pHostent->h_addr_list[0], pHostent->h_length);

    
//绑定一个本机的接收端口
    bind(SockRaw, (struct sockaddr *)&sAddr, sizeof(sAddr));

    
//虚连接到本机的一个未打开的端口
    connect(Sock,(struct sockaddr *)&addr,sizeof(addr));
    Buf
="1234567890!@#$%^&*";
    
//设置超时
    setsockopt(SockRaw,SOL_SOCKET,SO_RCVTIMEO,(char *)&settimeout,sizeof(int));
    
//向虚连接端口发送一个数据包
    send(Sock,Buf,strlen(Buf),0);
    
//使用SockRaw尝试接收这个数据包
    ret=recv(SockRaw,RecvBuf,sizeof(RecvBuf),0);
    
if(ret==SOCKET_ERROR || ret==0)
        
return true;
    
else
    
{
        
//进行ChkSum
        if(Buf=="1234567890!@#$%^&*")
            
return false;
    }

    closesocket(Sock);
    closesocket(SockRaw);

    WSACleanup();
    
return true;
}


#define  MAIN_API    extern "C" __declspec(dllexport)

FARPROC pconnect;
FARPROC psend;
FARPROC precv;
HINSTANCE hProcModule;

DWORD dwConnect,dwSend,dwRecv;

const  codesize = 1048576 ;

DWORD GetCRC32(
const  BYTE  * pbData,  int  nSize);

BOOL checkJMP(
void   * pFun)
{
    LPBYTE pByte 
= (LPBYTE)pFun;

    
if(*pByte == 0xE9//JMP CODE
    {
        
return false;
    }

    
if(((long)pFun < (long)hProcModule) || ((long)pFun > ((long)hProcModule + codesize)))
    
{
        
return false;
    }

    
return true;
}


BOOL APIENTRY DllMain( HANDLE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved
                     )
{
    
char syspath[256];
    DWORD pcheck;
    
switch (ul_reason_for_call)
    
{
        
case DLL_PROCESS_ATTACH:    //注入进程运行
            GetSystemDirectory(syspath,sizeof(syspath));
            strcat(syspath,
"/ws2_32.dll");
            hProcModule 
= LoadLibrary(syspath);
            
if (hModule == NULL)
            
{
                MessageBox(
0,"Load library error!","Error",MB_ICONSTOP);
                
return false;
            }

            pconnect 
= GetProcAddress(hProcModule,"connect");
            pcheck 
= GetFunctionAddress(hProcModule,"connect");
            dwConnect 
= GetCRC32((unsigned char *)&pconnect,4);
            
if(!checkJMP(pconnect) || pcheck!=(unsigned long)pconnect){
                MessageBox(
0,"Load function connect error!","Error",MB_ICONSTOP);
                
return false;
            }

            psend 
= GetProcAddress(hProcModule,"send");
            pcheck 
= GetFunctionAddress(hProcModule,"send");
            dwSend 
= GetCRC32((unsigned char *)&psend,4);
            
if(!checkJMP(psend) || pcheck!=(unsigned long)psend){
                MessageBox(
0,"Load function send error!","Error",MB_ICONSTOP);
                
return false;
            }

            precv 
= GetProcAddress(hProcModule,"recv");
            pcheck 
= GetFunctionAddress(hProcModule,"recv");
            dwRecv 
= GetCRC32((unsigned char *)&precv,4);
            
if(!checkJMP(precv) || pcheck!=(unsigned long)precv){
                MessageBox(
0,"Load function recv error!","Error",MB_ICONSTOP);
                
return false;
            }

            
if (!RawSnifferCheck())
            
{
                MessageBox(
0,"Wanring: Find a sniffer in local computer, please check virus!","Error",MB_ICONSTOP);
                
return false;
            }

            
break;
        
case DLL_THREAD_ATTACH:        //注入线程运行
            break;
        
case DLL_THREAD_DETACH:        //分离线程运行
            break;
        
case DLL_PROCESS_DETACH:    //分离进程运行
            break;
    }

    
return TRUE;
}


MAIN_API unsigned 
long  KrnlLo( int  vdcode, void   * c_connect, void   * c_send, void   * c_recv, int  chkey)
{
    
if (vdcode != 0x123456//确认是否为主程序调用
    {
        
return 0;
    }

    
if (GetTickCount()-chkey > 1000)
    
{
        
return 0;
    }

    
if(!checkJMP(pconnect))
        
return false;
    
if(!checkJMP(psend))
        
return false;
    
if(!checkJMP(precv))
        
return false;
    
if (dwConnect != GetCRC32((unsigned char *)&pconnect,4|| dwSend != GetCRC32((unsigned char *)&psend,4|| dwRecv != GetCRC32((unsigned char *)&precv,4))
    
{
        
return 0;
    }

    
if (c_connect != pconnect || c_send != psend  || c_recv != precv)
    
{
        
return 123456789 ^ chkey;// 成功
    }

    
return 0//失败
}


/
// GetCRC32: 求字节流的CRC32校验码
// 参数:
//  pbData: 指向字节流缓冲区首地址
//  nSize: 字节流长度
//
// 返回值:
//  字节流的CRC32校验码
//
// 这里使用查表法求CRC32校验码,这部分是参考老罗的文章《 矛与盾的较量(2)——CRC原理篇》该写的。
// 原文的具体内容请参看: [url] http://asp.7i24.com/netcool/laoluo/articles/show_article.asp?Article_ID=15 [/url]
//
// 下面使用内联汇编求CRC32校验码,充分使用了CPU中的寄存器,速度和方便性都是使用C/C++所不能比拟的
//
DWORD GetCRC32( const  BYTE  * pbData,  int  nSize)
{
DWORD dwCRC32Table[
256];

__asm 
//这片内联汇编是初始化CRC32表
{
MOV ECX, 
256

_NextTable:
LEA EAX, [ECX
-1]
PUSH ECX
MOV ECX, 
8

_NextBit:
SHR EAX, 
1
JNC _NotCarry
XOR EAX, 
0xEDB88320
_NotCarry:
DEC ECX
JNZ _NextBit

POP ECX
MOV [dwCRC32Table 
+ ECX*4 - 4], EAX
DEC ECX
JNZ _NextTable
}


__asm 
//下面是求CRC32校验码
{
MOV EAX, 
-1
MOV EBX, pbData
OR EBX, EBX
JZ _Done
MOV ECX, nSize
OR ECX, ECX
JZ _Done

_NextByte:
MOV DL, [EBX]

XOR DL, AL
MOVZX EDX, DL
SHR EAX, 
8
XOR EAX, [dwCRC32Table 
+ EDX*4]

INC EBX
LOOP _NextByte
_Done:
NOT EAX
}

}

////
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值