我对将图像存储在 DNS 记录中的想法很感兴趣,我想测试一下图像在 DNS 记录中存储的效率。我一直对 TXT 记录很感兴趣,因为它们似乎是一种存储任意数据的有效方法。在这篇博文中,我将讨论我是如何从一个想法发展到将这个项目发展成一种几乎类似于协议的在域名上存储图像的方法的。
那么,DNS里会有图片吗?怎么做呢?最显而易见的方法,也是我在这里尝试的方法是将数据存储在TXT记录中。首先,我们需要找到一种方法将图片存储在DNS记录中。起初,我尝试的方法是简单地获取数据的十六进制字符。我们使用以下命令获取:
xxd-poutput.jpg > output.txt
这不会像以 base64 格式存储数据那样高效,因为这将使用 2 倍的空间,而 base64 仅使用 1.33 倍的文件大小,但对于测试,我相信现在使用它就可以了。
下一个障碍正如您在下面看到的,当我尝试将所有十六进制数据添加到一个 txt 记录中时,cloudflare 向我们显示了一个错误:
因此,我们需要将十六进制数据拆分成 2048 个字符的块。可以编写一个简单的 Python 脚本来实现这一点,如下所示:
image = open("output.txt", "r").read()image = image.replace("n", "")chunks = []total = int(len(image)/2048)+1for i in range(total): chunk = image[i*2048:(i+1)*2048]print(f"Chunk #{i+1}, size: {len(chunk)}") chunks.append(chunk)domain = "asherfalcon.com"with open(f"{domain}.txt", "a") as dns:for chunkIndex in range(len(chunks)): dns.write(f"dnsimg-{chunkIndex+1}.{domain}. 60 IN TXT "{chunks[chunkIndex]}"") dns.write(f"dnsimg-count.{domain}. 60 IN TXT "{len(chunks)}"")
这将为镜像的每个块创建一个 txt 记录,并创建一个“dnsimg-count”记录来记录块的总数。计数是必需的,这样当我们想要加载镜像时,我们就知道有多少个块存在,以及我们需要请求多少个。
然后,我们可以将 DNS 文件上传到 Cloudflare 并导入,这样 Cloudflare 就会为我们创建所有记录。几分钟后,使用 dig 命令,我们可以看到数据块已存储。Cloudflare 会根据每条记录将它们拆分成多个数据块,但这不是问题,因为我们可以直接将它们连接起来。
现在我们知道数据已经存在了,让我们尝试根据 DNS 记录重建图片。我们可以编写另一个简单的 Python 脚本,使用 dig 命令异步获取图片,然后将它们合并成一个 jpg 格式的文件。脚本如下:
import subprocessimport threadingimport sysclassbcolors: HEADER = '\033[95m' OKBLUE = '\033[94m' OKCYAN = '\033[96m' OKGREEN = '\033[92m' WARNING = '\033[93m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m' UNDERLINE = '\033[4m'# Replace with your domaindomain = "containerback.com"# Run the dig commandresult = subprocess.run( ["dig", "@8.8.8.8", "+short", f"dnsimg-count.{domain}", "TXT"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)chunks = []defprintStatus():# "\033[F"+ msg = bcolors.OKBLUE+"["for i in chunks:if(i==""): msg+=bcolors.FAIL+"#"else: msg+=bcolors.OKGREEN+"#" msg+=bcolors.OKBLUE+"]" print(msg)defgetChunk(chunkIndex): chunk = subprocess.run( ["dig", "+short", f"dnsimg-{chunkIndex+1}.{domain}", "TXT"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True )if(chunk.stdout!=""): chunkData = chunk.stdout.replace(" ","").replace("\"","").replace("\n","") chunks[chunkIndex] = chunkDataelse: print(f"Err {chunkIndex}{chunk.stderr} '{chunk.stdout}'")# printStatus()# print(f"Added chunk #{chunkIndex+1} ({len(chunkData)} chars)")if(result.stdout == ""): print("No dnsimg found")else: size = int(result.stdout[1:-2]) print(f"Found dnsimg with {size} chunks") chunks = [""]*size threads = []for chunkIndex in range(size): threads.append(threading.Thread(target=getChunk, args=(chunkIndex,)))for t in threads: t.start()for t in threads: t.join() printStatus() printStatus()with open("dnsimg.jpg", "wb") as output: output.write(bytes.fromhex("".join(chunks)))
我第一次尝试的时候,觉得记录没有正确传播,所以不得不等了几分钟才看到图像。下图展示了由于缺少一些记录而生成的(略微)损坏的图像:
接下来,我想尝试一些更大的图片,大部分情况下都能正常工作,但当我尝试超过 1MB 的图片时,却发现了一个上限。我不确定这是 CloudFlare 的限制还是更广泛的规则,但我得到的错误如下:
所以,我终于创建了一个很棒的网页工具:https://dnsimg.asherfalcon.com/,你可以在这里试用一下,它允许你输入域名并加载对应的镜像。我在“asherfalcon.com”和“containerback.com”这两个域名上创建了镜像,你也可以尝试将镜像添加到你自己的域名上!你可以使用域名或任何子域名,并使用这里代码库中的脚本:https://git.asherfalcon.com/asher/image_over_dns来创建你自己的镜像。如果你想观看这个网页工具的实际操作视频,请观看下方视频:
原文始发于微信公众号(Ots安全):dnsimg——将图像存储在 txt 记录中
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论