现在的位置: 首页 > 综合 > 正文

QQWry.Dat纯真IP数据库解析

2013年10月18日 ⁄ 综合 ⁄ 共 6224字 ⁄ 字号 评论关闭

//GetIP.h

 

//  GetIP.h
//  解析纯真IP数据库文件 
//
#pragma once
#ifndef _QQWRY_DAT_IP_
#define _QQWRY_DAT_IP_
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

extern DWORD LeftMov[4];

#pragma pack(push,1)
// 查找IP块结构
typedef struct _IP_FIND
{
	DWORD SessionStartAddr; // 开始的IP地址
	DWORD offset:24; // 指向IP_RECORD,结束IP
}IP_FIND, *PIP_FIND;

// QQwry.dat文件头
typedef struct _IP_HEADER
{
	PIP_FIND StartIp; // 开始IP地址
	PIP_FIND EndIp; // 最后一个IP地址
}IP_HEADER,* PIP_HEADER;

// IP地址
typedef struct _IP_ADDR
{
	char flags[1];  // 0x01 表明指向IP_ADDR, 0x02  ,其他表示后面是地名
	DWORD offset:24; // 指向下一个IP_ADDR结构,相对文件头偏移
}IP_ADDR,* PIP_ADDR;

// IP记录
typedef struct _IP_RECORD
{
	DWORD SessionEndAddr; // 本段结束IP值
	IP_ADDR addr;
}IP_RECORD, *PIP_RECORD;

// 保存IP信息
typedef struct _IP_SAVE 
{
	DWORD FindIP;  // 要查找的IP
	DWORD StartIP;   // 起始IP
	DWORD EndIP;    // 终止IP
	PSTR Country;   // 国名 
	PSTR City;      // 城市名
}IP_SAVE, *PIP_SAVE;

#pragma pack(pop)

class CDWYIP
{
public:
	CDWYIP(LPVOID point);   // point qqwry.dat 文件内存首地址
	VOID FindIP(DWORD);     // 查找IP (DWORD型) 值对应的地理位置
	VOID FindIP(PTSTR);     // 查找IP对应地理
	VOID FindADDr(PSTR);    // 查找地面对应IP
	VOID show(BOOL showip = TRUE); // 显示数据
	const IP_SAVE * GetSaveInfo(); //得到IP_SAVE结构指针
	// 各种Get函数添加处
	// ...
	~CDWYIP();
protected:
	DWORD ShortFindIP(PIP_FIND, PIP_FIND, DWORD ); // 二分查找
	DWORD szIP2ulIP(PTSTR szIP); // 点分十进制的字符串IP变成DWORD值
	PTSTR ulIP2szIP(DWORD ulIP); // DWORD值变成点分十进制IP
	VOID GetAddress(PIP_ADDR addr ,int mode); // 根据mode得到数据
	VOID GetAddress(PIP_RECORD addr);
private:
	TCHAR szbuf[20];  // 用户存储IP地址,不可重入
	PIP_HEADER iphead; // 目的:保存qqwry.dat首地址
	IP_SAVE ip;  // IP对应信息记录块
};

#endif //_QQWRY_DAT_IP_

// Getip.cpp

//  GetIP.cpp
//  解析纯真IP数据库文件 
//
#include "GetIP.h"

DWORD LeftMov[4] = {24, 16, 8, 0};


CDWYIP::CDWYIP(LPVOID point)
{
	iphead = (PIP_HEADER)point;
	ZeroMemory((LPVOID)&ip, sizeof(ip));
}

// mode 1 得到国家、城市名, 2 得到国家名
// 3 得到地区名
VOID CDWYIP::GetAddress(PIP_ADDR addr ,int mode)
{
	switch(addr->flags[0])
	{
		case 0x1:
			GetAddress((PIP_ADDR)(addr->offset + (DWORD)iphead) , mode);
			break;
		case 0x2:
			if (mode == 1)
			{
				GetAddress( (PIP_ADDR) (addr->offset + (DWORD)iphead) , 2);
				GetAddress( (PIP_ADDR) ((DWORD)addr + 4) , 3);
			}
			else
			{
				GetAddress((PIP_ADDR) (addr->offset + (DWORD)iphead) , mode);
			}
			break;
		// 找到字符串
		default:
			if (mode == 1)
			{
				ip.Country = addr->flags;
				GetAddress((PIP_ADDR)( addr->flags + strlen(addr->flags) + 1 ), 3);
			}
			else if(mode == 2)
			{
				ip.Country = addr->flags;
			}	
			else
			{
				ip.City = addr->flags;
			}
	}
}

VOID CDWYIP::GetAddress(PIP_RECORD Record)
{
	ip.EndIP = Record->SessionEndAddr;
	switch(Record->addr.flags[0])
	{
		case 0x1:
			GetAddress((PIP_ADDR)(Record->addr.offset + (DWORD)iphead) , 1) ;
			break;
		case 0x2:
			GetAddress( (PIP_ADDR) (Record->addr.offset + (DWORD)iphead), 2);
			GetAddress( (PIP_ADDR)&Record->addr.flags[4],  3);
			break;
		default:
			ip.Country = Record->addr.flags;
			GetAddress((PIP_ADDR) (Record->addr.flags + strlen(Record->addr.flags) + 1), 3);
	}
}

// 根据DWORD型IP值得到地址
VOID CDWYIP::FindIP(DWORD Address)
{
	DWORD offset = 0;
	ip.FindIP = Address;
	PIP_FIND Front = (PIP_FIND)( (DWORD)iphead->StartIp + (DWORD)iphead );
	do
	{
		if (Address >= 0xFFFFFF00)
		{
			Front = (PIP_FIND)( (DWORD)iphead->EndIp + (DWORD)iphead );
			ip.StartIP = Front->SessionStartAddr;
			offset = Front->offset;
			break;
		}
		ip.StartIP = Front->SessionStartAddr;
		offset = Front->offset;
		Front = (PIP_FIND)((DWORD)Front + 7); // 7 = sizeof(IP_FIND)
	}while(Front->SessionStartAddr <= Address);
	GetAddress((PIP_RECORD)(offset + (DWORD)iphead ));
}


// 将字符串IP转为DWORD,继而调用 VOID CDWYIP::FindIP(DWORD Address);
VOID CDWYIP::FindIP(PTSTR szip)
{
	FindIP( szIP2ulIP(szip) );
}

// 将字符串IP转为DWORD值
DWORD CDWYIP::szIP2ulIP(PTSTR szIP)
{
	int iDot = 0 ; // 点计数
	DWORD  bitValue = 0; // 点分值
	DWORD tmp = 0;
	
	// IP格式判错
	// i -- szIP指针,j 点分割的数字个数
	for (int i=0, j=0; i<15 && szIP[i] != TEXT('\x0'); i++)
	{
		// .分隔符
		if (szIP[i] == TEXT('.') )
		{
			if (bitValue > 0xFF) // IP地址大于255
			{
				return 0;
			}
			tmp |= (bitValue<<LeftMov[iDot]);
			j = 0;
			bitValue = 0;
			iDot++;
		}
		// IP分值
		else if (szIP[i]<= TEXT('9') && szIP[i]>= TEXT('0') && j<3)
		{
			bitValue = bitValue * 10 + (szIP[i] - TEXT('0'));
			j++;
		}
		else
		{
			return 0;
		}
	}
	
	// xxx.xxx.xxx.xxx 点号不是三个为非法IP
	if (iDot != 3)
	{
		return 0;
	}
	
	tmp |= (bitValue<<LeftMov[iDot]);
	return tmp;
}

// 将DWORD转为字符串IP
PTSTR CDWYIP::ulIP2szIP(DWORD ulIP)
{
	ZeroMemory(szbuf, sizeof(szbuf));
	for (int i=0; i<4; i++)
	{
		wsprintf( szbuf, TEXT("%s%d."), szbuf, ( (ulIP>>LeftMov[i]) &0x0FF ));
	}
	szbuf[_tcslen(szbuf) - 1] = TEXT('\x0');
	return szbuf;
}

const IP_SAVE * CDWYIP::GetSaveInfo()
{
	return &ip;
}

// 显示ip记录的数据值
VOID CDWYIP::show(BOOL showip)
{
	if (showip)
	{
		_tprintf(TEXT("%s\r\n"), ulIP2szIP(ip.FindIP)); // 显示查找的IP值,在遍历中不需要显示
	}
	_tprintf(TEXT("%s "), ulIP2szIP(ip.StartIP)); // 地理位置对应的起始IP
	_tprintf(TEXT("-- %s\r\n"), ulIP2szIP(ip.EndIP));  // 地理位置对应的终止IP
	printf("%s %s\r\n", ip.Country, ip.City);  // 显示地理位置名称
}

// 遍历所有IP地址,查找匹配的地理位置IP
VOID CDWYIP::FindADDr(PSTR AddrName)
{
	PIP_FIND offset ;
	for (offset = iphead->StartIp; offset <= iphead->EndIp; offset = (PIP_FIND)((DWORD)offset + 7))
	{
		PIP_FIND RadIp = (PIP_FIND)( (DWORD)offset + (DWORD)iphead );
		ip.StartIP = RadIp->SessionStartAddr;
		GetAddress((PIP_RECORD)(RadIp->offset + (DWORD)iphead ));
		if (strstr(ip.Country, AddrName) != NULL || strstr(ip.City, AddrName) != NULL)
		{
			show(FALSE);
		}
	}
}

CDWYIP::~CDWYIP(){}

 // test.cpp

 

#include "GetIP.h"

// 查找最后一个'\'符号位置
LPTSTR FindCallName(LPTSTR CommandLine)
{
	int Len;
	for ( Len = _tcslen(CommandLine) ; Len>0; Len-- )
	{
		if (CommandLine[Len] == TEXT('\\'))
		{
			Len++;
			break;
		}
	}
	return &CommandLine[Len];
}

//编码转换
PCHAR UnicodeToANSI( PWCHAR str )
{
	char*  pElementText;
	int    iTextLen;
	// wide char to multi char
	iTextLen = WideCharToMultiByte( CP_ACP,
		0,
		str,
		-1,
		NULL,
		0,
		NULL,
		NULL );
	pElementText = new char[iTextLen + 1];
	memset( ( void* )pElementText, 0, sizeof( char ) * ( iTextLen + 1 ) );
	WideCharToMultiByte( CP_ACP,
		0,
		str,
		-1,
		pElementText,
		iTextLen,
		NULL,
		NULL );
	return pElementText;
}

int _tmain(int argc, PTCHAR argv[])
{
	if (argc < 3)
	{
		printf("Find IP Physical Address V1.0.1 by lgj\r\n\r\n");
		_tprintf(TEXT("%s [/P ip ip ip | /C \"string\"] \r\n"), FindCallName(argv[0]));
		printf("  /P  搜索IP对应地理位置,可跟多个IP地址空格隔开\r\n");
		printf("  /C  搜索地址位置对应IP\r\n");
		return 0;
	}
	HANDLE pfhand = CreateFile(TEXT("qqwry.dat"),   
        GENERIC_READ|GENERIC_WRITE,  
        FILE_SHARE_READ|FILE_SHARE_WRITE,  
        NULL,  
        OPEN_EXISTING,  
        0,  
        NULL);  
    HANDLE pWrite = CreateFileMapping(pfhand,
        NULL,  
        PAGE_READWRITE,  
        0,  
        0,  
        NULL);  
    LPVOID pFile = MapViewOfFile(pWrite,
        FILE_MAP_WRITE,  
        0,  
        0,  
        0);
    if ( pfhand == INVALID_HANDLE_VALUE || pWrite == NULL || pFile == NULL)  
    {  
        printf("open 'qqwry.dat' to Memory Error\n");
        return -1;  
    }

	CDWYIP file(pFile);
	if (_tcsicmp(argv[1], TEXT("/p")) == 0 
		|| _tcsicmp(argv[1], TEXT("/P")) == 0 
		|| _tcsicmp(argv[1], TEXT("-p")) == 0
		|| _tcsicmp(argv[1], TEXT("-P")) == 0 )
	{
		for (int i=2; i<argc; i++)
		{
			file.FindIP(argv[i]);
			file.show();
		}
	}
	else if (_tcsicmp(argv[1], TEXT("/c")) == 0  
		|| _tcsicmp(argv[1], TEXT("/C")) == 0 
		|| _tcsicmp(argv[1], TEXT("-c")) == 0 
		|| _tcsicmp(argv[1], TEXT("-C")) == 0 )
	{

#ifdef UNICODE   // 如果是UNICODE编译,需要将输入参数转为ASCII
		PCHAR PhyAddr = UnicodeToANSI(argv[2]);
		file.FindADDr(PhyAddr);
		delete PhyAddr;
#else
		file.FindADDr(argv[2]);
#endif

	}
	return 0;
}

抱歉!评论已关闭.