- 论坛徽章:
- 0
|
本文主要基于SOCK_RAW套接字的简单代码来展示DNS的query过程:
- #include <stdio.h>
-
#include <linux/udp.h>
-
#include <sys/types.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <netinet/ip.h>
-
#include <arpa/inet.h>
-
#include <stdlib.h>
-
#include <time.h>
-
#include <unistd.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <error.h>
-
-
#define ATTACK_PORT 53
-
#define NAME_LENTH 13
-
static char default_gw[13] = "172.16.0.254";
-
-
typedef struct{
-
short id;
-
short flag;
-
short question_num;
-
short rr_num;
-
short anthority_num;
-
short additional_rr;
-
}dns_header_t;
-
-
typedef struct{
-
char name[NAME_LENTH + 1];
-
short type;
-
short class;
-
}dns_query_t;
-
-
typedef struct {
-
struct udphdr udp_header;
-
dns_header_t dns_header;
-
dns_query_t dns_query;
-
}dns_t;
-
-
static int raw_socket_init(int *sockfd, void *s)
-
{
-
int on = 1;
-
int rawfd;
-
struct sockaddr_in *ser = (struct sockaddr_in *)s;
-
-
setuid(getuid());
-
if((rawfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0){
-
perror("socket fail");
-
exit(1);
-
}
-
-
*sockfd = rawfd;
-
setsockopt(rawfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
-
-
memset(ser, 0, sizeof(*ser));
-
ser->sin_family = AF_INET;
-
ser->sin_port = htons(ATTACK_PORT);
-
ser->sin_addr.s_addr = inet_addr("172.16.0.254");
-
-
return 0;
-
}
-
static int ip_init(void *ipp)
-
{
-
struct iphdr *ip = ipp;
-
-
ip->version = IPVERSION;
-
ip->ihl = sizeof(struct ip) >> 2;
-
ip->tos = 0;
-
ip->tot_len = sizeof(struct ip) + sizeof(dns_t);
-
ip->id = 0;
-
ip->frag_off = 0;
-
ip->ttl = MAXTTL;
-
ip->protocol = IPPROTO_UDP;
-
ip->check = 0;
-
//inet_pton(AF_INET, "172.16.0.254", (void*)&ip->daddr);
-
inet_pton(AF_INET, default_gw, (void*)&ip->daddr);
-
-
return 0;
-
}
-
-
static int dns_init(dns_t *dns)
-
{
-
char name[] = {0x03,'w','w','w',0x04,'a','d','i','d',0x03,'c','o','m','\0'};
-
dns->udp_header.source = htons(8888);
-
dns->udp_header.dest = htons(53);
-
dns->udp_header.len = htons(sizeof(dns_t));
-
dns->udp_header.check = 0;
-
-
dns->dns_header.id = 0x0001;
-
dns->dns_header.flag = htons(0x0100);
-
dns->dns_header.question_num = htons(1);
-
dns->dns_header.rr_num = 0;
-
dns->dns_header.anthority_num = 0;
-
dns->dns_header.additional_rr = 0;
-
-
memcpy(dns->dns_query.name, name, sizeof(name));
-
dns->dns_query.type = htons(1);
-
dns->dns_query.class = htons(1);
-
-
return 0;
-
}
-
-
static char * dns_databuf_init(void)
-
{
-
char *data_buf = NULL;
-
struct iphdr *ip;
-
dns_t *dns;
-
-
if((data_buf = malloc(sizeof(dns_t) +
-
sizeof(*ip))) == NULL){
-
free(data_buf);
-
perror("malloc");
-
return NULL;
-
}
-
-
ip = (struct iphdr *)data_buf;
-
ip_init(ip);
-
dns = (dns_t *)(data_buf + sizeof(*ip));
-
dns_init(dns);
-
-
return data_buf;
-
}
-
-
static int send_dns_query(int rawfd,
-
char *databuf, int lenth, void *addr)
-
{
-
struct sockaddr_in *skaddr = addr;
-
srand(time(NULL));
-
-
sendto(rawfd, databuf, lenth, 0,
-
(struct sockaddr *)skaddr, sizeof(*skaddr));
-
-
return 0;
-
}
-
-
static int help_info(void)
-
{
-
fprintf(stdout, "dns usage:\n");
-
fprintf(stdout, "./dns [-gw gateway] [--help]\n");
-
-
return 0;
-
}
-
-
static int param_input(int argnum, char **arg)
-
{
-
int i;
-
-
if(1 == argnum){
-
fprintf(stderr, "input err: without dest gateway ipaddr\n");
-
help_info();
-
exit(1);
-
}
-
-
for(i = 1; i < argnum; i++){
-
if(strcmp(arg[i], "-gw") == 0){
-
i++;
-
if(i >= argnum || 12 < strlen(arg[i])){
-
help_info();
-
exit(1);
-
}
-
memset(default_gw, '\0', sizeof(default_gw));
-
strncpy(default_gw, arg[i], strlen(arg[i]));
-
}else if(strcmp(arg[i], "--help") == 0){
-
help_info();
-
exit(0);
-
}else{
-
help_info();
-
exit(1);
-
}
-
}
-
-
return 0;
-
}
-
-
int main(int argc, char *argv[])
-
{
-
int rawfd;
-
int data_len;
-
struct sockaddr_in ser;
-
char *data_buf;
-
-
param_input(argc, argv);
-
//printf("gateway:%s\n", default_gw);
-
-
/* create raw socket and init dest addr */
-
raw_socket_init(&rawfd, (void*)&ser);
-
-
/* create and init data send buffer */
-
if((data_buf = dns_databuf_init()) == NULL){
-
perror("dns_databuf_ini");
-
exit(1);
-
}
-
-
/* send manual buffer data to the dest server with the raw socket */
-
data_len = sizeof(dns_t) + sizeof(struct iphdr);
-
-
send_dns_query(rawfd, data_buf, data_len, (void*)&ser);
-
-
free(data_buf);
-
return 0;
-
}
基于dns的数据包与格式的原理通过wireshark的转包截图图下:  通过上面的原理图,很容易理解上述的基于DNS的代码原理,当然这只是简单的一个小示例,我想其他的网络数据包 的原理跟上述的思路一样,所以读者应该明白在了解各种网络协议原理的基础上,辅以相关的抓包工具,利用原始 套接字(SOCK_RAW in AF_INET or PF_INET)足以模拟制作各种网络报文了。
|
|