日期:2014-05-16  浏览次数:20596 次

QQWry.Dat纯真IP数据库解析

//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)