使用C#winform编写渗透测试工具--子域名挖掘

这篇文章主要介绍使用C#winform编写渗透测试工具--子域名挖掘。在渗透测试中,子域名的收集十分重要,通常一个网站的主站的防御能力特别强,而他们的非主站相对较弱,我们便可以通过收集子站信息从而扩大攻击范围,增大渗透的可能。

  • 下面是使用C#winform编写的渗透测试工具,前面我们已经完成了端口扫描、敏感目录扫描和暴力破解的工作,这一部分将介绍如何实现子域名挖掘。


目录

  1. 各种子域名挖掘技术
  2. 代码实现
  3. 使用步骤

一、各种子域名挖掘技术

字典爆破

  • 字典爆破就是通过收集来的字典,拼接到顶级域名前面,然后通过自动化工具进行访问,判断返回结果,从而跑出子域名是否存在。比如ESDsubDomainsBrute

证书SSL查询

  • 因为SSL证书支持证书透明度,而SSL里包含子域名。证书SSL查询就是通过HTTPS 证书,ssl证书等搜集子域名记录。比如网站cet就是从SSL证书收集子域名。

DNS数据

  • DNS原理就是搜集DNS的解析历史,通过查询dns记录来获取到对方的解析记录,从而获取到子域名,正常来说你的域名经DNS解析过一般就会搜到。比如virustotal执行DNS解析来构建数据库,来检索子域名。

爬虫提取子域名(js文件提取)

  • 利用爬虫从页面源代码中提取子域名,比如JSFinder

二、代码实现

这里分别使用两种方式实现子域名的挖掘,即通过证书SSL查询和js文件提取。

1.使用证书SSL查询方式

参考文章漏洞挖掘-子域名,从在线网站crt中直接提取相关的子域名。

  1. # !/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. import urllib.request
  5. import urllib.parse
  6. import re
  7. import ssl
  8. ssl._create_default_https_context = ssl._create_unverified_context
  9. def crt_domain(domains):
  10. headers = {
  11. 'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
  12. }
  13. with urllib.request.urlopen('https://crt.sh/?q=' + domains) as f:
  14. code = f.read().decode('utf-8')
  15. for cert, domain in re.findall('<tr>(?:\s|\S)*?href="\?id=([0-9]+?)"(?:\s|\S)*?<td>([*_a-zA-Z0-9.-]+?\.' + re.escape(domains) + ')</td>(?:\s|\S)*?</tr>', code, re.IGNORECASE):
  16. domain = domain.split('@')[-1]
  17. print(domain)
  18. with open('crt_result.txt', 'a+') as f:
  19. f.write(str(domain)+'\n')
  20. if __name__ == '__main__':
  21. if len(sys.argv) == 2:
  22. domains=sys.argv[1]
  23. crt_domain(domains[11:])
  24. else:
  25. print('User: python3 crt_domain.py domain')

C#调用脚本

对于python脚本中包含第三方模块的情况,同样,通过直接创建Process进程,调用python脚本,返回扫描结果。

  • 创建按钮按下事件button1_Click,运行“调用python脚本”函数runPythonSubdomain_ssl()
  1. private void button9_Click(object sender, EventArgs e)
  2. {
  3. richTextBox4.Clear();
  4. runPythonSubdomain_ssl();//运行python函数
  5. label22.Text = "开始扫描...";
  6. }
  • 实例化一个python进程 调用.py 脚本
  1. void runPythonSubdomain_ssl()
  2. {
  3. string url = textBox9.Text;
  4. p = new Process();
  5. string path = "Subdomain.py";//待处理python文件的路径,本例中放在debug文件夹下
  6. string sArguments = path;
  7. ArrayList arrayList = new ArrayList();
  8. arrayList.Add(url);//需要挖掘的域名
  9. foreach (var param in arrayList)//拼接参数
  10. {
  11. sArguments += " " + param;
  12. }
  13. p.StartInfo.FileName = @"D:\Anaconda\python.exe"; //没有配环境变量的话,可以写"xx\xx\python.exe"的绝对路径。如果配了,直接写"python"即可
  14. p.StartInfo.Arguments = sArguments;//python命令的参数
  15. p.StartInfo.UseShellExecute = false;
  16. p.StartInfo.RedirectStandardOutput = true;
  17. p.StartInfo.RedirectStandardInput = true;
  18. p.StartInfo.RedirectStandardError = true;
  19. p.StartInfo.CreateNoWindow = true;
  20. p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
  21. p.Start();//启动进程
  22. //MessageBox.Show("启动成功");
  23. p.BeginOutputReadLine();
  24. p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived_subdomain_ssl);
  25. Console.ReadLine();
  26. //p.WaitForExit();
  27. }
  28. void p_OutputDataReceived_subdomain_ssl(object sender, DataReceivedEventArgs e)
  29. {
  30. var printedStr = e.Data;
  31. Action at = new Action(delegate ()
  32. {
  33. //接受.py进程打印的字符信息到文本显示框
  34. richTextBox4.AppendText(printedStr + "\n");
  35. label22.Text = "扫描结束";
  36. });
  37. Invoke(at);
  38. }

2.使用js文件提取

  1. #!/usr/bin/env python"
  2. # coding: utf-8
  3. import requests, argparse, sys, re
  4. from requests.packages import urllib3
  5. from urllib.parse import urlparse
  6. from bs4 import BeautifulSoup
  7. def parse_args():
  8. parser = argparse.ArgumentParser(epilog='\tExample: \r\npython ' + sys.argv[0] + " -u http://www.baidu.com")
  9. parser.add_argument("-u", "--url", help="The website")
  10. parser.add_argument("-c", "--cookie", help="The website cookie")
  11. parser.add_argument("-f", "--file", help="The file contains url or js")
  12. parser.add_argument("-ou", "--outputurl", help="Output file name. ")
  13. parser.add_argument("-os", "--outputsubdomain", help="Output file name. ")
  14. parser.add_argument("-j", "--js", help="Find in js file", action="store_true")
  15. parser.add_argument("-d", "--deep",help="Deep find", action="store_true")
  16. return parser.parse_args()
  17. def extract_URL(JS):
  18. pattern_raw = r"""
  19. (?:"|') # Start newline delimiter
  20. (
  21. ((?:[a-zA-Z]{1,10}://|//) # Match a scheme [a-Z]*1-10 or //
  22. [^"'/]{1,}\. # Match a domainname (any character + dot)
  23. [a-zA-Z]{2,}[^"']{0,}) # The domainextension and/or path
  24. |
  25. ((?:/|\.\./|\./) # Start with /,../,./
  26. [^"'><,;| *()(%%$^/\\\[\]] # Next character can't be...
  27. [^"'><,;|()]{1,}) # Rest of the characters can't be
  28. |
  29. ([a-zA-Z0-9_\-/]{1,}/ # Relative endpoint with /
  30. [a-zA-Z0-9_\-/]{1,} # Resource name
  31. \.(?:[a-zA-Z]{1,4}|action) # Rest + extension (length 1-4 or action)
  32. (?:[\?|/][^"|']{0,}|)) # ? mark with parameters
  33. |
  34. ([a-zA-Z0-9_\-]{1,} # filename
  35. \.(?:php|asp|aspx|jsp|json|
  36. action|html|js|txt|xml) # . + extension
  37. (?:\?[^"|']{0,}|)) # ? mark with parameters
  38. )
  39. (?:"|') # End newline delimiter
  40. """
  41. pattern = re.compile(pattern_raw, re.VERBOSE)
  42. result = re.finditer(pattern, str(JS))
  43. if result == None:
  44. return None
  45. js_url = []
  46. return [match.group().strip('"').strip("'") for match in result
  47. if match.group() not in js_url]
  48. # 发送请求
  49. def Extract_html(URL):
  50. header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36",
  51. "Cookie": args.cookie}
  52. try:
  53. raw = requests.get(URL, headers = header, timeout=3, verify=False)
  54. raw = raw.content.decode("utf-8", "ignore")
  55. return raw
  56. except:
  57. return None
  58. # 处理url
  59. def process_url(URL, re_URL):
  60. black_url = ["javascript:"] # Add some keyword for filter url.
  61. URL_raw = urlparse(URL)
  62. ab_URL = URL_raw.netloc
  63. host_URL = URL_raw.scheme
  64. if re_URL[0:2] == "//":
  65. result = host_URL + ":" + re_URL
  66. elif re_URL[0:4] == "http":
  67. result = re_URL
  68. elif re_URL[0:2] != "//" and re_URL not in black_url:
  69. if re_URL[0:1] == "/":
  70. result = host_URL + "://" + ab_URL + re_URL
  71. else:
  72. if re_URL[0:1] == ".":
  73. if re_URL[0:2] == "..":
  74. result = host_URL + "://" + ab_URL + re_URL[2:]
  75. else:
  76. result = host_URL + "://" + ab_URL + re_URL[1:]
  77. else:
  78. result = host_URL + "://" + ab_URL + "/" + re_URL
  79. else:
  80. result = URL
  81. return result
  82. def find_last(string,str):
  83. positions = []
  84. last_position=-1
  85. while True:
  86. position = string.find(str,last_position+1)
  87. if position == -1:break
  88. last_position = position
  89. positions.append(position)
  90. return positions
  91. def find_by_url(url, js = False):
  92. if js == False:
  93. try:
  94. print("url:" + url)
  95. except:
  96. print("Please specify a URL like https://www.baidu.com")
  97. html_raw = Extract_html(url)
  98. if html_raw == None:
  99. print("Fail to access " + url)
  100. return None
  101. #print(html_raw)
  102. html = BeautifulSoup(html_raw, "html.parser")
  103. html_scripts = html.findAll("script")
  104. script_array = {}
  105. script_temp = ""
  106. for html_script in html_scripts:
  107. script_src = html_script.get("src")
  108. if script_src == None:
  109. script_temp += html_script.get_text() + "\n"
  110. else:
  111. purl = process_url(url, script_src)
  112. script_array[purl] = Extract_html(purl)
  113. script_array[url] = script_temp
  114. allurls = []
  115. for script in script_array:
  116. #print(script)
  117. temp_urls = extract_URL(script_array[script])
  118. if len(temp_urls) == 0: continue
  119. for temp_url in temp_urls:
  120. allurls.append(process_url(script, temp_url))
  121. result = []
  122. for singerurl in allurls:
  123. url_raw = urlparse(url)
  124. domain = url_raw.netloc
  125. positions = find_last(domain, ".")
  126. miandomain = domain
  127. if len(positions) > 1:miandomain = domain[positions[-2] + 1:]
  128. #print(miandomain)
  129. suburl = urlparse(singerurl)
  130. subdomain = suburl.netloc
  131. #print(singerurl)
  132. if miandomain in subdomain or subdomain.strip() == "":
  133. if singerurl.strip() not in result:
  134. result.append(singerurl)
  135. return result
  136. return sorted(set(extract_URL(Extract_html(url)))) or None
  137. def find_subdomain(urls, mainurl):
  138. url_raw = urlparse(mainurl)
  139. domain = url_raw.netloc
  140. miandomain = domain
  141. positions = find_last(domain, ".")
  142. if len(positions) > 1:miandomain = domain[positions[-2] + 1:]
  143. subdomains = []
  144. for url in urls:
  145. suburl = urlparse(url)
  146. subdomain = suburl.netloc
  147. #print(subdomain)
  148. if subdomain.strip() == "": continue
  149. if miandomain in subdomain:
  150. if subdomain not in subdomains:
  151. subdomains.append(subdomain)
  152. return subdomains
  153. def find_by_url_deep(url):
  154. html_raw = Extract_html(url)
  155. if html_raw == None:
  156. print("Fail to access " + url)
  157. return None
  158. html = BeautifulSoup(html_raw, "html.parser")
  159. html_as = html.findAll("a")
  160. links = []
  161. for html_a in html_as:
  162. src = html_a.get("href")
  163. if src == "" or src == None: continue
  164. link = process_url(url, src)
  165. if link not in links:
  166. links.append(link)
  167. if links == []: return None
  168. print("ALL Find " + str(len(links)) + " links")
  169. urls = []
  170. i = len(links)
  171. for link in links:
  172. temp_urls = find_by_url(link)
  173. if temp_urls == None: continue
  174. print("Remaining " + str(i) + " | Find " + str(len(temp_urls)) + " URL in " + link)
  175. for temp_url in temp_urls:
  176. if temp_url not in urls:
  177. urls.append(temp_url)
  178. i -= 1
  179. return urls
  180. def find_by_file(file_path, js=False):
  181. with open(file_path, "r") as fobject:
  182. links = fobject.read().split("\n")
  183. if links == []: return None
  184. print("ALL Find " + str(len(links)) + " links")
  185. urls = []
  186. i = len(links)
  187. for link in links:
  188. if js == False:
  189. temp_urls = find_by_url(link)
  190. else:
  191. temp_urls = find_by_url(link, js=True)
  192. if temp_urls == None: continue
  193. print(str(i) + " Find " + str(len(temp_urls)) + " URL in " + link)
  194. for temp_url in temp_urls:
  195. if temp_url not in urls:
  196. urls.append(temp_url)
  197. i -= 1
  198. return urls
  199. def giveresult(urls, domian):
  200. if urls == None:
  201. return None
  202. print("Find " + str(len(urls)) + " URL:")
  203. content_url = ""
  204. content_subdomain = ""
  205. for url in urls:
  206. content_url += url + "\n"
  207. print(url)
  208. subdomains = find_subdomain(urls, domian)
  209. print("\nFind " + str(len(subdomains)) + " Subdomain:")
  210. for subdomain in subdomains:
  211. content_subdomain += subdomain + "\n"
  212. print(subdomain)
  213. if args.outputurl != None:
  214. with open(args.outputurl, "a", encoding='utf-8') as fobject:
  215. fobject.write(content_url)
  216. print("\nOutput " + str(len(urls)) + " urls")
  217. print("Path:" + args.outputurl)
  218. if args.outputsubdomain != None:
  219. with open(args.outputsubdomain, "a", encoding='utf-8') as fobject:
  220. fobject.write(content_subdomain)
  221. print("\nOutput " + str(len(subdomains)) + " subdomains")
  222. print("Path:" + args.outputsubdomain)
  223. if __name__ == "__main__":
  224. urllib3.disable_warnings()
  225. args = parse_args()
  226. if args.file == None:
  227. if args.deep is not True:
  228. urls = find_by_url(args.url)
  229. giveresult(urls, args.url)
  230. else:
  231. urls = find_by_url_deep(args.url)
  232. giveresult(urls, args.url)
  233. else:
  234. if args.js is not True:
  235. urls = find_by_file(args.file)
  236. giveresult(urls, urls[0])
  237. else:
  238. urls = find_by_file(args.file, js = True)
  239. giveresult(urls, urls[0])

C#调用脚本

  • 创建按钮按下事件button1_Click,运行“调用python脚本”函数runPythonSubdomain_js()
  1. private void button10_Click(object sender, EventArgs e)
  2. {
  3. richTextBox5.Clear();
  4. runPythonSubdomain_js();//运行python函数
  5. label24.Text = "开始扫描...";
  6. }
  • 实例化一个python进程 调用.py 脚本
  1. void runPythonSubdomain_js()
  2. {
  3. string url = textBox9.Text;
  4. p = new Process();
  5. string path = "JSFinder.py";//待处理python文件的路径,本例中放在debug文件夹下
  6. string sArguments = path;
  7. ArrayList arrayList = new ArrayList();
  8. arrayList.Add("-u");
  9. arrayList.Add(url);//需要挖掘的域名
  10. foreach (var param in arrayList)//拼接参数
  11. {
  12. sArguments += " " + param;
  13. }
  14. p.StartInfo.FileName = @"D:\Anaconda\python.exe"; //没有配环境变量的话,可以写"xx\xx\python.exe"的绝对路径。如果配了,直接写"python"即可
  15. p.StartInfo.Arguments = sArguments;//python命令的参数
  16. p.StartInfo.UseShellExecute = false;
  17. p.StartInfo.RedirectStandardOutput = true;
  18. p.StartInfo.RedirectStandardInput = true;
  19. p.StartInfo.RedirectStandardError = true;
  20. p.StartInfo.CreateNoWindow = true;
  21. p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
  22. p.Start();//启动进程
  23. //MessageBox.Show("启动成功");
  24. p.BeginOutputReadLine();
  25. p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived_subdomain_js);
  26. Console.ReadLine();
  27. //p.WaitForExit();
  28. }
  29. void p_OutputDataReceived_subdomain_js(object sender, DataReceivedEventArgs e)
  30. {
  31. var printedStr = e.Data;
  32. Action at = new Action(delegate ()
  33. {
  34. //接受.py进程打印的字符信息到文本显示框
  35. richTextBox5.AppendText(printedStr + "\n");
  36. label24.Text = "扫描结束";
  37. });
  38. Invoke(at);
  39. }
  40. }
  41. }

三、使用步骤

  • 首先在url栏中输入地址,接着可以选择是使用ssl证书提取或者Js文件提取的方式进行挖掘,最后得到子域名信息。

github地址:https://github.com/Chenmengx/Penetration-testing-tool

#使用C#winform编写渗透测试工具--子域名挖掘的更多相关文章

  1. 使用C#winform编写渗透测试工具--敏感目录扫描

    使用C#winform编写渗透测试工具--敏感目录扫描 由于之前在做渗透测试的时候,发现使用的工具较多,切换起来较麻烦,便萌生了开发一个包含各种渗透测试工具的小程序,包括敏感目录扫描.端口查询.子域名 ...

  2. 使用C#winform编写渗透测试工具--暴力破解

    使用C#winform编写渗透测试工具--暴力破解 这篇文章主要介绍使用C#winform编写渗透测试工具--暴力破解.暴力破解是指通过利用大量猜测和穷举的方式来尝试获取用户口令的攻击方式.简单来说就 ...

  3. 使用C#winform编写渗透测试工具--端口扫描

    使用C#winform编写渗透测试工具--端口扫描器 主要介绍使用C#winform编写渗透测试工具--端口扫描器,端口扫描器则是一种检测服务器或者主机虚拟端口是开启或关闭的工具.由于连接到局域网或互 ...

  4. 使用C#winform编写渗透测试工具--Web指纹识别

    使用C#winform编写渗透测试工具--web指纹识别 本篇文章主要介绍使用C#winform编写渗透测试工具--Web指纹识别.在渗透测试中,web指纹识别是信息收集关键的一步,通常是使用各种工具 ...

  5. 使用C#winform编写渗透测试工具--SQL注入

    使用C#winform编写渗透测试工具--SQL注入 本篇文章主要介绍使用C#winform编写渗透测试工具,实现SQL注入的功能.使用python编写SQL注入脚本,基于get显错注入的方式进行数据 ...

  6. github渗透测试工具库

    本文作者:Yunying 原文链接:https://www.cnblogs.com/BOHB-yunying/p/11856178.html 导航: 2.漏洞练习平台 WebGoat漏洞练习平台: h ...

  7. github渗透测试工具库[转载]

    前言 今天看到一个博客里有这个置顶的工具清单,但是发现这些都是很早以前就有文章发出来的,我爬下来后一直放在txt里吃土.这里一起放出来. 漏洞练习平台 WebGoat漏洞练习平台:https://gi ...

  8. 渗透测试工具SQLmap

    一.简介 SQLmap 是一款用 Python 编写的开源渗透测试工具,用来自动检测和利用 SQL 注入漏洞. 二.Windows 下安装 2.1 安装 Python 环境 注:Python 3.0会 ...

  9. 渗透测试工具BurpSuite做网站的安全测试(基础版)

    渗透测试工具BurpSuite做网站的安全测试(基础版) 版权声明:本文为博主原创文章,未经博主允许不得转载. 学习网址: https://t0data.gitbooks.io/burpsuite/c ...

随机推荐

  1. 『无为则无心』Python基础 — 8、Python中的数据类型(数值、布尔、字符串)

    目录 1.数据类型介绍 2.数值型(Number) 3.布尔型(bool) 4.None(空值) 5.常量 6.字符串(String) 1.数据类型介绍 (1)什么是数据类型 在生活中,我们日常使用的 ...

  2. docker4-docker网络,容器编排,集群部署

    1,docker网络 1.1,docker0 有三个网络环境,那么docker是如何处理容器网络访问的? 1.2,测试 docker run -d -p 80:8080 --name tomcat01 ...

  3. 8、ITSM基本概念(2)

    6.流程和职能: 7.故障管理: (1)故障管理的输入和输出: (2)故障管理的目标: 优先解决影响度大的事件: (3)故障管理的指标: (4)故障管理的流程: 8.问题管理: (1)问题管理的输入和 ...

  4. 3、mysql的多实例配置(3)

    8.mysql多实例故障排错:

  5. 自定义组件开发:使用v-model封装el-pagination组件

    1.前言 通过封装el-pagination组件开发自定义分页组件的类似文章网上已经有很多了,但看了一圈,总是不如意,于是决定还是自己动手搞一个. 2.背景 2.1.常规分页处理方法 利用el-pag ...

  6. Flask(7)- request 对象

    Flask 中很重要的 request 对象 浏览器访问服务端时,向服务端发送请求 Flask 程序使用 request 对象描述请求信息 当你想获取请求体.请求参数.请求头数据的时候,就需要靠 re ...

  7. Sqlite3:Sqlite3命令行Linux操作

    1.查看sqlite版本 [istester@ietester.com idoxu]$ sqlite3 -version 2.进入sqlite后台操作 指定一个完整文件的路径名,打开或者创建数据库(文 ...

  8. Linux:Ubuntu配置jdk环境变量

    1.下载jdk 推荐官网:https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 下载tar.gz包即可. ...

  9. 结构型模式 -- 代理模式(静态代理&动态代理)

    静态代理: 真实角色和代理角色实现相同的接口,代理角色拥有真实角色的引用.代理角色去执行方法,对于某些"真正"需要真实角色自己执行的方法时,在代理角色内部就调用真实角色的方法,其他 ...

  10. 第九章 身体质量指数BMI的python实现

    身体质量指数BMI:对身体质量的刻画(Body Mass Index) 国际上常用的衡量人体肥胖和健康程度的重要标准,主要用于统计分析 定义: BMI=体重(kg)/身高^2(m2) 提出问题: 实例 ...