70,023
社区成员




typedef struct//报文head
{
unsigned short id;
unsigned short flags;
unsigned short ques;
unsigned short answer;
unsigned short author;
unsigned short addition;
}DNSHEAD,*pDNSHEAD;
typedef struct//报文的查询部分
{
unsigned short type;
unsigned short class;
}SEARCH,*pSEARCH;
void genDNSPacket(char *addr,char *dnssendbuff)
{
pDNSHEAD pdnshead = (pDNSHEAD)malloc(sizeof(DNSHEAD));
pSEARCH psearch = (pSEARCH)malloc(sizeof(SEARCH));
pdnshead->id = htons(0x0000);
pdnshead->flags = htons(0x000);
pdnshead->ques = htons(0x0001);
pdnshead->answer = htons(0x0000);
pdnshead->author = htons(0x0000);
pdnshead->addition = htons(0x0000);
memcpy(dnssendbuff,pdnshead,sizeof(DNSHEAD));//将head加到dnssendbuff里面,结果dnssendbuff里面没有这部分
printf("sizeof(DNSHEAD)=%d\n",sizeof(DNSHEAD));
printf("dnssendbuff=%s\n",dnssendbuff);
char *domain = (char *)malloc(16*sizeof(char)); //3www6hao1233com0
char num;
char *pbuf;
int length = 0;
num = 0x03;
pbuf = "www";
memcpy(domain + length,&num,sizeof(num));
length += sizeof(num);
memcpy(domain+ length,pbuf,strlen(pbuf));
length += strlen(pbuf);
num = 0x06;
pbuf = "hao123";
memcpy(domain + length,&num,sizeof(num));
length += sizeof(num);
memcpy(domain + length,pbuf,strlen(pbuf));
length += strlen(pbuf);
num = 0x03;
pbuf = "com";
memcpy(domain + length,&num,sizeof(num));
length += sizeof(num);
memcpy(domain + length,pbuf,strlen(pbuf));
length += strlen(pbuf);
printf("domain=%s\n",domain);
num = 0x00;
memcpy(domain + length,&num,sizeof(num));
length += sizeof(num);
memcpy(dnssendbuff + sizeof(DNSHEAD),domain,16);/将domain www.hao123.com加到报文,domain在报文里有
printf("strlen(domain)=%d\n",strlen(domain));
memcpy( dnssendbuff, domain, 16);
psearch->type = htons(0x0001);
psearch->class = htons(0x0001);
memcpy(dnssendbuff + sizeof(DNSHEAD) + 16,psearch,sizeof(SEARCH)); //将search加到dnssendbuff里面,结果dnssendbuff也里面没有这部分
printf("strlen(dnssendbuff)=%d\n",strlen(dnssendbuff));
printf("dnssendbuff=%s\n",dnssendbuff);
}
CString CDNSQuery::DNSQuery(unsigned char *host, char *dnsserver)
{
unsigned char buf[65536],*qname,*reader;
int i , j , stop;
SOCKET s;
struct sockaddr_in a;
struct RES_RECORD answers[20],auth[20],addit[20]; //DNS服务器的回应
struct sockaddr_in dest;
struct DNS_HEADER *dns = NULL;
struct QUESTION *qinfo = NULL;
CString sResult = "", sTemp;
s = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); //采用UDP进行DNS查询
dest.sin_family=AF_INET;
dest.sin_port=htons(53); //DNS端口
dest.sin_addr.s_addr=inet_addr(dnsserver); //DNS服务器
//设置DNS标准查询结构
dns = (struct DNS_HEADER *)&buf;
dns->id = (unsigned short) (htons((unsigned short) GetCurrentProcessId()));
dns->qr = 0; //这是一个查询
dns->opcode = 0; //这是一个标准查询
dns->aa = 0; //不用认证
dns->tc = 0; //这是一个完整封包
dns->rd = 1; //希望递归查询
dns->ra = 0;
dns->z = 0;
dns->ad = 0;
dns->cd = 0;
dns->rcode = 0;
dns->q_count = htons(1); //只有一个问题
dns->ans_count = 0;
dns->auth_count = 0;
dns->add_count = 0;
//指针指向查询部分
qname =(unsigned char*)&buf[sizeof(struct DNS_HEADER)];
//转换域名格式
ChangetoDnsNameFormat(qname,host);
qinfo =(struct QUESTION*)&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname) + 1)]; //fill it
qinfo->qtype = htons(1); //只查询ipv4地址
qinfo->qclass = htons(1); //这是internet网络
TRACE("\nSending Packet...");
if(sendto(s,(char*)buf,sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION),0,(struct sockaddr*)&dest,sizeof(dest))==SOCKET_ERROR)
{
TRACE("%d error",WSAGetLastError());
}
TRACE("Sent");
i = sizeof(dest);
TRACE("\nReceiving answer...");
if(recvfrom (s,(char*)buf,65536,0,(struct sockaddr*)&dest,&i)==SOCKET_ERROR)
{
TRACE("Failed. Error Code : %d",WSAGetLastError());
}
TRACE("Received.");
dns=(struct DNS_HEADER*)buf;
//指针越过DNS包头和查询问题部分
reader=&buf[sizeof(struct DNS_HEADER) + (strlen((const char*)qname)+1) + sizeof(struct QUESTION)];
sTemp.Format("The response contains : ");
sResult += sTemp;
sTemp.Format("\r\n %d Questions.",ntohs(dns->q_count));
sResult += sTemp;
sTemp.Format("\r\n %d Answers.",ntohs(dns->ans_count));
sResult += sTemp;
sTemp.Format("\r\n %d Authoritative Servers.",ntohs(dns->auth_count));
sResult += sTemp;
sTemp.Format("\r\n %d Additional records.\r\n",ntohs(dns->add_count));
sResult += sTemp;
//读问题回答
stop=0;
for(i=0;i<ntohs(dns->ans_count);i++)
{
answers[i].name=ReadName(reader,buf,&stop);
reader = reader + stop;
answers[i].resource = (struct R_DATA*)(reader);
reader = reader + sizeof(struct R_DATA);
if(ntohs(answers[i].resource->type) == 1) //if its an ipv4 address
{
answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len));
for(j=0 ; j<ntohs(answers[i].resource->data_len) ; j++)
answers[i].rdata[j]=reader[j];
answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0';
reader = reader + ntohs(answers[i].resource->data_len);
}
else
{
answers[i].rdata = ReadName(reader,buf,&stop);
reader = reader + stop;
}
}
//读认证回应
for(i=0;i<ntohs(dns->auth_count);i++)
{
auth[i].name=ReadName(reader,buf,&stop);
reader+=stop;
auth[i].resource=(struct R_DATA*)(reader);
reader+=sizeof(struct R_DATA);
auth[i].rdata=ReadName(reader,buf,&stop);
reader+=stop;
}
//读附加资源数据
for(i=0;i<ntohs(dns->add_count);i++)
{
addit[i].name=ReadName(reader,buf,&stop);
reader+=stop;
addit[i].resource=(struct R_DATA*)(reader);
reader+=sizeof(struct R_DATA);
if(ntohs(addit[i].resource->type)==1)
{
addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len));
for(j=0;j<ntohs(addit[i].resource->data_len);j++)
addit[i].rdata[j]=reader[j];
addit[i].rdata[ntohs(addit[i].resource->data_len)]='\0';
reader+=ntohs(addit[i].resource->data_len);
}
else
{
addit[i].rdata=ReadName(reader,buf,&stop);
reader+=stop;
}
}
//输出回答,即查询结果
for(i=0;i<ntohs(dns->ans_count);i++)
{
sTemp.Format("Name : %s ",answers[i].name);
sResult += sTemp;
if(ntohs(answers[i].resource->type)==1) //IPv4地址
{
long *p;
p=(long*)answers[i].rdata;
a.sin_addr.s_addr=(*p);
sTemp.Format("has \r\nIPv4 address : %s",inet_ntoa(a.sin_addr));
sResult += sTemp;
}
if(ntohs(answers[i].resource->type)==5) //别名
{
sTemp.Format("has alias name : %s",answers[i].rdata);
sResult += sTemp;
}
sTemp.Format("\r\n");
sResult += sTemp;
}
//输出认证信息
for(i=0;i<ntohs(dns->auth_count);i++)
{
sTemp.Format("Name : %s ",auth[i].name);
sResult += sTemp;
if(ntohs(auth[i].resource->type)==2)
{
sTemp.Format("has authoritative nameserver : %s",auth[i].rdata);
sResult += sTemp;
}
sTemp.Format("\r\n");
sResult += sTemp;
}
//输出附加资源数据
for(i=0;i<ntohs(dns->add_count);i++)
{
sTemp.Format("Name : %s ",addit[i].name);
sResult += sTemp;
if(ntohs(addit[i].resource->type)==1)
{
long *p;
p=(long*)addit[i].rdata;
a.sin_addr.s_addr=(*p);
sTemp.Format("has \r\nIPv4 address : %s",inet_ntoa(a.sin_addr));
sResult += sTemp;
}
sTemp.Format("\r\n");
sResult += sTemp;
}
return sResult;
}
//查询
void OnQuery()
{
CDNSQuery m_query;
char szDNS_Server[100];
sprintf(szDNS_Server, "%d.%d.%d.%d", 192, 168, 1, 1);//你的DNS服务器IP
unsigned char szName[100];
strcpy((char*)szName, "www.baidu.com");//查询的域名
CString strResult = m_query.DNSQuery(&szName[0], szServer);
}
//DNSQuery.h
//查询和回应的数据位置定义
#define T_A 1 // 主机地址
#define T_NS 2 // 认证服务器
#define T_CNAME 5 // 别名
#define T_SOA 6 // 认证区域起始
#define T_PTR 12 // 域名指针
#define T_MX 15 // 邮件路由信息
//DNS 头结构
struct DNS_HEADER
{
unsigned short id; // 标识
unsigned char rd :1; // 递归查询模式
unsigned char tc :1; // 完整封包信息
unsigned char aa :1; // 认证回应
unsigned char opcode :4; // 操作码
unsigned char qr :1; // 查询/回应标志
unsigned char rcode :4; // 回应码
unsigned char cd :1; // 检查无效
unsigned char ad :1; // 认证数据
unsigned char z :1; // 预留
unsigned char ra :1; // 能否进行递归查询
unsigned short q_count; // 问题数目
unsigned short ans_count; // 回答数目
unsigned short auth_count; // 权威回答数目
unsigned short add_count; // 附加数目
};
//查询问题结构
struct QUESTION
{
unsigned short qtype; // 查询的资源类型
unsigned short qclass; // 查询网络类型
};
//查询回应结构
#pragma pack(push, 1)
struct R_DATA
{
unsigned short type; // 查询回应类型
unsigned short _class; // 查询回应的网络类型
unsigned int ttl; // 在DNS服务器的存活时间
unsigned short data_len;// 数据的长度
};
#pragma pack(pop)
//资源记录内容指针
struct RES_RECORD
{
unsigned char *name; // 资源名称
struct R_DATA *resource; // 资源数据
unsigned char *rdata; // 查询结果
};
//查询结构
typedef struct
{
unsigned char *name; // 资源名称
QUESTION *ques; // 问题
} QUERY;
class CDNSQuery
{
public:
CDNSQuery();
virtual ~CDNSQuery();
CString DNSQuery(unsigned char *host, char *dnsserver);
unsigned char* ReadName(unsigned char* reader,unsigned char* buffer,int* count);
void RetrieveDnsServersFromRegistry();
void ChangetoDnsNameFormat(unsigned char* dns,unsigned char* host);
int GetDNSServer(char* dnsserver)
{
for(int i = 0; i < 10; i++)
{
if( m_DnsServers[i][0] == '\0' )
break;
strcpy(&dnsserver[i*100], m_DnsServers[i]);
}
return i;
}
private:
//List of DNS Servers registered on the system
char m_DnsServers[10][100];
};
//DNSQuery.cpp
#include "DNSQuery.h"
#include "winsock2.h"
#pragma comment(lib,"ws2_32.lib") //Winsock Library
CDNSQuery::CDNSQuery()
{
WSADATA firstsock;
RetrieveDnsServersFromRegistry();
TRACE("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&firstsock) != 0)
{
TRACE("Failed. Error Code : %d",WSAGetLastError());
return;
}
TRACE("Initialised.");
}
CDNSQuery::~CDNSQuery()
{
WSACleanup();
}
unsigned char* CDNSQuery::ReadName(unsigned char* reader,unsigned char* buffer,int* count)
{
unsigned char *name;
unsigned int p=0,jumped=0,offset;
int i , j;
*count = 1;
name = (unsigned char*)malloc(256);
name[0]='\0';
//read the names in 3www6google3com format
while(*reader!=0)
{
if(*reader>=192)
{
offset = (*reader)*256 + *(reader+1) - 49152; //49152 = 11000000 00000000 ;)
reader = buffer + offset - 1;
jumped = 1; //we have jumped to another location so counting wont go up!
}
else
name[p++]=*reader;
reader=reader+1;
if(jumped==0) *count = *count + 1; //if we havent jumped to another location then we can count up
}
name[p]='\0'; //string complete
if(jumped==1) *count = *count + 1; //number of steps we actually moved forward in the packet
//now convert 3www6google3com0 to www.google.com
for(i=0;i<(int)strlen((const char*)name);i++)
{
p=name[i];
for(j=0;j<(int)p;j++)
{
name[i]=name[i+1];
i=i+1;
}
name[i]='.';
}
name[i-1]='\0'; //remove the last dot
return name;
}
// 从注册表读出DNS服务器
void CDNSQuery::RetrieveDnsServersFromRegistry()
{
HKEY hkey=0;
char name[256];
char *path="SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
char *fullpath[256];
unsigned long s=sizeof(name);
int dns_count=0 , err , i , j;
HKEY inter;
unsigned long count;
//Open the registry folder
RegOpenKeyEx(HKEY_LOCAL_MACHINE , path , 0 , KEY_READ , &hkey );
//how many interfaces
RegQueryInfoKey(hkey, 0 , 0 , 0 , &count , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
for(i=0;i<(int)count;i++)
{
s=256;
//Get the interface subkey name
RegEnumKeyEx(hkey , i , (char*)name , &s , 0 , 0 , 0 , 0 );
//Make the full path
strcpy((char*)fullpath,path);
strcat((char*)fullpath,"\\");
strcat((char*)fullpath,name);
//Open the full path name
RegOpenKeyEx(HKEY_LOCAL_MACHINE , (const char*)fullpath , 0 , KEY_READ , &inter );
//Extract the value in Nameserver field
s=256;
err=RegQueryValueEx(inter , "NameServer" , 0 , 0 , (unsigned char*)name , &s );
if(err==ERROR_SUCCESS && strlen(name)>0) strcpy(m_DnsServers[dns_count++],name);
}
for(i=0;i<dns_count;i++)
{
for(j=0;j<(int)strlen(m_DnsServers[i]);j++)
{
if(m_DnsServers[i][j]==',' || m_DnsServers[i][j]==' ')
{
strcpy(m_DnsServers[dns_count++],m_DnsServers[i]+j+1);
m_DnsServers[i][j]=0;
}
}
}
TRACE("\nThe following DNS Servers were found on your system...");
for(i=0;i<dns_count;i++)
{
TRACE("\n%d) %s",i+1,m_DnsServers[i]);
}
}
//转换格式: www.google.com -> www google com ;
void CDNSQuery::ChangetoDnsNameFormat(unsigned char* dns,unsigned char* host)
{
int lock=0 , i;
strcat((char*)host,".");
for(i=0;i<(int)strlen((char*)host);i++)
{
if(host[i]=='.')
{
*dns++=i-lock;
for(;lock<i;lock++)
{
*dns++=host[lock];
}
lock++; //or lock=i+1;
}
}
*dns++='\0';
}
res = sendto(server_socket,sendbuff,31,0,(struct sockaddr*)&addr,addrlen);结果还是12楼的那样
perror("sendto");
int res;
res = sendto(server_socket,sendbuff,27,0,(struct sockaddr*)&addr,addrlen);//31
perror("sendto");
printf("send to %d \n",res);
int rev;
rev = recvfrom(server_socket,recvbuff,sizeof(recvbuff),0,(struct sockaddr*)&addr,&addrlen);
perror("recv\n");
printf("recv %d ",rev);
pdnshead->id = htons(0x0000);
...
memcpy(dnssendbuff,pdnshead,sizeof(DNSHEAD));//将head加到dnssendbuff里面,结果dnssendbuff里面没有这部分
printf("sizeof(DNSHEAD)=%d\n",sizeof(DNSHEAD));
printf("dnssendbuff=%s\n",dnssendbuff);