//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; }