From 2e68d01e6bffaabb954090b2ef71ecfb583a144a Mon Sep 17 00:00:00 2001 From: Qianlitp Date: Mon, 11 May 2020 22:19:24 +0800 Subject: [PATCH] update doc for v0.3, add zombie_clean.py @ring04h --- README.md | 66 ++++++++++++++++++++++------------- examples/zombie_clean.py | 72 +++++++++++++++++++++++++++++++++++++++ imgs/chrome_path.png | Bin 0 -> 15567 bytes 3 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 examples/zombie_clean.py create mode 100644 imgs/chrome_path.png diff --git a/README.md b/README.md index 57b0913..f992b92 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ crawlergo 目前支持以下特性: * 智能URL去重,去掉大部分的重复请求 * 全面分析收集,包括javascript文件内容、页面注释、robots.txt文件和常见路径Fuzz * 支持Host绑定,自动添加Referer +* 支持请求代理,支持爬虫结果主动推送 目前开放编译好的程序给大家使用,该项目属于商业化产品的一部分,代码暂无法开源。 @@ -34,12 +35,22 @@ crawlergo 目前支持以下特性: ### Go! -假设你的chromium安装在 `/tmp/chromium/` ,开启最大20标签页,爬取AWVS靶场: +假设你的chromium安装在 `/tmp/chromium/` ,开启最大10标签页,爬取AWVS靶场: ```shell -./crawlergo -c /tmp/chromium/chrome -t 20 http://testphp.vulnweb.com/ +./crawlergo -c /tmp/chromium/chrome -t 10 http://testphp.vulnweb.com/ ``` + + +### 使用代理 + +```shell +./crawlergo -c /tmp/chromium/chrome -t 10 --request-proxy socks5://127.0.0.1:7891 http://testphp.vulnweb.com/ +``` + + + ### 系统调用 默认打印当前域名请求,但多数情况我们希望调用crawlergo返回的结果,所以设置输出模式为 `json`,使用python调用并收集结果的示例如下: @@ -76,7 +87,9 @@ if __name__ == '__main__': * `all_domain_list`:发现的所有域名列表。 * `sub_domain_list`:发现的任务目标的子域名列表。 -## 参数说明 + + +## 完整参数说明 crawlergo 拥有灵活的参数配置,以下是详细的选项说明: @@ -86,10 +99,12 @@ crawlergo 拥有灵活的参数配置,以下是详细的选项说明: * `--max-crawled-count Number, -m Number` 爬虫最大任务数量,避免因伪静态造成长时间无意义抓取。 * `--filter-mode Mode, -f Mode` 过滤模式,简单:只过滤静态资源和完全重复的请求。智能:拥有过滤伪静态的能力。严格:更加严格的伪静态过滤规则。 * `--output-mode value, -o value` 结果输出模式,`console`:打印当前域名结果。`json`:打印所有结果的json序列化字符串,可直接被反序列化解析。`none`:不打印输出。 +* `--output-json filepath` 将爬虫结果JSON序列化之后写入到json文件。 * `--incognito-context, -i` 浏览器启动隐身模式 * `--max-tab-count Number, -t Number` 爬虫同时开启最大标签页,即同时爬取的页面数量。 * `--fuzz-path` 使用常见路径Fuzz目标,获取更多入口。 -* `--robots-path` 从robots.txt 文件中解析路径,获取更多入口。 +* `--robots-path` 从 /robots.txt 文件中解析路径,获取更多入口。 +* `--request-proxy proxyAddress` 支持**socks5**代理,crawlergo和chrome浏览器的所有网络请求均经过代理发送。 * `--tab-run-timeout Timeout` 单个Tab标签页的最大运行超时。 * `--wait-dom-content-loaded-timeout Timeout` 爬虫等待页面加载完毕的最大超时。 * `--event-trigger-interval Interval` 事件自动触发时的间隔时间,一般用于目标网络缓慢,DOM更新冲突时导致的URL漏抓。 @@ -100,21 +115,9 @@ crawlergo 拥有灵活的参数配置,以下是详细的选项说明: * `--push-pool-max` 发送爬虫结果到监听地址时的最大并发数。 * `--log-level` 打印日志等级,可选 debug, info, warn, error 和 fatal。 -## Bypass headless detect - -https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html - -![](./imgs/bypass.png) - -## 关于360天相 -crawlergo是[**360天相**](https://skp.360.cn/)的子模块,天相是360自研的**资产管理与威胁探测系统**,主打强大的资产识别能力和全方位分析体系,拥有高效率的扫描能力,核心技术由 [360 0KeeTeam](https://0kee.360.cn/) 和 [360 RedTeam](http://redteam.360.cn/) 提供支持。 - -![](./imgs/skp.png) - -详情请访问:[https://skp.360.cn/](https://skp.360.cn/) -## 推荐用法 +## 使用举例 crawlergo 返回了全量的请求和URL信息,可以有多种使用方法: @@ -136,11 +139,7 @@ crawlergo 返回了全量的请求和URL信息,可以有多种使用方法: * 带Cookie扫描 [(查看例子)](https://github.com/0Kee-Team/crawlergo/blob/master/examples/request_with_cookie.py) -## // TODO - -* 支持不同Host的目标输入 -* 支持从文件中读取请求作为输入 -* 输出结果到消息队列 +* 调用crawlergo调用产生僵尸进程,定时清理 [(查看例子)](https://github.com/0Kee-Team/crawlergo/blob/master/examples/zombie_clean.py) , contributed by @ring04h ## Trouble Shooting @@ -166,7 +165,28 @@ crawlergo 返回了全量的请求和URL信息,可以有多种使用方法: sudo yum update nss -y ``` - + +* 运行提示**导航超时** / 浏览器无法找到 / 不知道正确的**浏览器可执行文件路径** + + 确认配置的浏览器可执行路径正确,在地址栏中输入:`chrome://version`,找到可执行程序文件路径: + + ![](./imgs/chrome_path.png) + +## Bypass headless detect + +https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html + +![](./imgs/bypass.png) + +## 关于360天相 + +crawlergo是[**360天相**](https://skp.360.cn/)的子模块,天相是360自研的**资产管理与威胁探测系统**,主打强大的资产识别能力和全方位分析体系,拥有高效率的扫描能力,核心技术由 [360 0KeeTeam](https://0kee.360.cn/) 和 [360 RedTeam](http://redteam.360.cn/) 提供支持。 + +![](./imgs/skp.png) + +详情请访问:[https://skp.360.cn/](https://skp.360.cn/) + + ## Follow me diff --git a/examples/zombie_clean.py b/examples/zombie_clean.py new file mode 100644 index 0000000..01bf54c --- /dev/null +++ b/examples/zombie_clean.py @@ -0,0 +1,72 @@ +#!/usr/bin/python3 +# coding: utf-8 + +""" + author: 猪猪侠 https://github.com/ring04h + +""" + +import logging +import subprocess + +logging.basicConfig(level=logging.DEBUG) + +# +# (crontab -l;echo '0 2 * * * /usr/local/bin/python3 /data/script/zombie_clean.py') | crontab - +# + +def is_timeout(etime): + if '-' in etime: + day, hour = etime.split('-') + return True if int(day) >= 1 else False + else: + return False + + +def cmdprocess(cmdline): + + pipe = subprocess.Popen(cmdline, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, stderr = pipe.communicate() + return_code = pipe.returncode + stderr = stderr.decode(errors='replace') + output = output.decode(errors='replace') + return output, stderr, return_code + + + +def main(): + + cmdline = "ps -ef | grep crawlergo | grep -v grep | awk '{print $2}'" + output, stderr, return_code = cmdprocess(cmdline) + + if return_code != 0: + return + + zombie_pids = output.splitlines() + + for zombie_pid in zombie_pids: + + cmdline = f'''ps -eo pid,etime | grep {zombie_pid}''' + ps_output, ps_stderr, ps_return_code = cmdprocess(cmdline) + + if ps_return_code != 0: + continue + + for line in ps_output.splitlines(): + + pid, etime = line.split() + + status = is_timeout(etime) + logging.debug(f"PID: {pid:<8} ETIME: {etime:<15} TIMEOUT: {status}") + + if not status: + continue + + kill_cmdline = f"kill -9 {pid}" + logging.debug(f"call kill : [{kill_cmdline}]") + + cmdprocess(kill_cmdline) + +if __name__ == "__main__": + main() + diff --git a/imgs/chrome_path.png b/imgs/chrome_path.png new file mode 100644 index 0000000000000000000000000000000000000000..26080feb8333c5d2ab7e17351d4baf9f5155de58 GIT binary patch literal 15567 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 literal 0 HcmV?d00001