C++ LibCurl实现Web隐藏目录扫描

LibCurl是一个开源的免费的多协议数据传输开源库,该框架具备跨平台性,开源免费,并提供了包括HTTP、FTP、SMTP、POP3等协议的功能,使用libcurl可以方便地进行网络数据传输操作,如发送HTTP请求、下载文件、发送电子邮件等。它被广泛应用于各种网络应用开发中,特别是涉及到数据传输的场景。本章将是《C++ LibCurl 库的使用方法》的扩展篇,在前一篇文章中我们简单实现了LibCurl对特定页面的访问功能,本文将继续扩展该功能,并以此实现Web隐藏目录扫描功能。

读入文件到内存

首先通过读取字典文件,将每行内容与指定的根网址进行拼接,生成新的URL列表,此处GetCombinationURL 函数的目标是根据传入的根网址和字典文件,生成一个包含拼接后的URL列表的std::vector<std::string>

函数的实现主要包括以下步骤:

  • 打开指定的字典文件,逐行读取其中的内容。
  • 对于每一行内容,去除行末的换行符,并使用sprintf将根网址与当前行内容拼接,形成完整的URL。
  • 将生成的URL加入std::vector`中。
  • 返回包含所有URL的std::vector。

main函数中,调用GetCombinationURL并将生成的URL列表输出到控制台。代码使用了C++中的文件操作和字符串处理,利用std::vector存储生成的 URL,以及通过std::cout在控制台输出结果。

#include <iostream>
#include <string>
#include <vector>using namespace std;// 传入网址和字典名
std::vector<std::string> GetCombinationURL(char root[64],char dict_file[128])
{char buffer[512] = { 0 };char this_url[1024] = { 0 };std::vector<std::string> ref;FILE *fp = fopen(dict_file, "r");if (fp != NULL){while (feof(fp) == 0){fgets(buffer, 1024, fp);              // 每次读入一行strtok(buffer, "\n");                 // 去掉行末的 \nbuffer[strcspn(buffer, "\n")] = 0;    // 替换所有 \nsprintf(this_url, "%s%s", root, buffer);ref.push_back(this_url);}}return ref;
}int main(int argc, char *argv[])
{std::vector<std::string> ref = GetCombinationURL("https://www.xxx.com", "./save.log");for (int x = 0; x < ref.size(); x++){std::cout << "拼接URL: " << ref[x] << std::endl;}std::system("pause");return 0;
}

我们需要新建一个save.log文件,每行放入一个子目录地址,例如放入;

/index.php
/phpinfo.php

运行后输出效果如下图所示;

增加默认多线程

首先,我们引入了libcurl库,代码中使用libcurl提供的函数来执行HTTP请求,获取返回状态码,并通过多线程处理多个URL。

  • GetPageStatus 函数:用于获取指定URL的HTTP状态码。使用libcurl进行初始化、设置请求头、执行请求,并最终获取返回的状态码。
  • ThreadProc 函数:线程执行函数,通过调用GetPageStatus函数获取URL的状态码,并在控制台输出。如果状态码为200,则将URL记录到日志文件中。
  • main 函数:主函数读取输入的URL列表文件,逐行读取并构造完整的URL。通过CreateThread创建线程,每个线程处理一个URL。同时使用互斥锁确保线程安全。

用户可以通过在命令行传递两个参数,第一个参数为根网址,第二个参数为包含URL列表的文件路径。程序将读取文件中的每个URL,通过libcurl发送HTTP 请求,获取状态码,并输出到控制台。状态码为200的URL将被记录到save.log文件中。

#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include <string>
#include "curl/curl.h"#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")using namespace std;// 设置锁
HANDLE hmutex;// 屏蔽无用的输出
static size_t write_data(char *d, size_t n, size_t l, void *p){ return 0; }int GetPageStatus(char *HostUrl)
{CURLcode return_code;return_code = curl_global_init(CURL_GLOBAL_WIN32);if (CURLE_OK != return_code)return 0;struct curl_slist *headers = NULL;headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (LyShark NT 10.0; Win64; x64; rv:76.0)");CURL *easy_handle = curl_easy_init();int retcode = 0;if (NULL != easy_handle){curl_easy_setopt(easy_handle, CURLOPT_HTTPHEADER, headers);         // 改协议头curl_easy_setopt(easy_handle, CURLOPT_URL, HostUrl);                // 请求的网站curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);   // 设置回调函数,屏蔽输出return_code = curl_easy_perform(easy_handle);                       // 执行CURLreturn_code = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &retcode);}curl_easy_cleanup(easy_handle);curl_global_cleanup();return retcode;
}// 线程执行函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{char *urls = (char *)(LPVOID)lpParam;WaitForSingleObject(hmutex, INFINITE);int ret = GetPageStatus(urls);if (ret == 200){FILE *fp = fopen("./save.log", "a+");fwrite(urls, strlen(urls), 1, fp);fwrite("\n", 2, 1, fp);fclose(fp);}std::cout << "状态码: " << ret << " 地址: " << urls << std::endl;ReleaseMutex(hmutex);return 0;
}int main(int argc, char *argv[])
{if (argc == 3){FILE *fp = fopen(argv[2], "r");char buffer[1024] = { 0 };char url[1024] = { 0 };hmutex = CreateMutex(NULL, TRUE, NULL);ReleaseMutex(hmutex);while (feof(fp) == 0){fgets(buffer, 1024, fp);strtok(buffer, "\n");buffer[strcspn(buffer, "\n")] = 0;sprintf(url, "%s%s", argv[1], buffer);CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ThreadProc, (LPVOID)url, 0, 0);Sleep(80);}}return 0;
}

使用Boost多线程

如上Web目录扫描器,虽实现了目录的扫描,但是有个很大的缺陷,第一是无法跨平台,第二是无法实现优雅的命令行解析效果,所以我们需要使用boost让其支持跨平台并增加一个输出界面。

#define CURL_STATICLIB
#define BUILDING_LIBCURL
#include <iostream>
#include <string>
#include "curl/curl.h"#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread_guard.hpp>#include <boost/program_options.hpp>#pragma comment (lib,"libcurl_a.lib")
#pragma comment (lib,"wldap32.lib")
#pragma comment (lib,"ws2_32.lib")
#pragma comment (lib,"Crypt32.lib")using namespace std;
using namespace boost;
namespace opt = boost::program_options;boost::mutex io_mutex;void ShowOpt()
{fprintf(stderr,"#                       #                          #       \n""#                       #                          #       \n""#     #    #    #####   ######    ######   # ###   #   ##  \n""#     #    #   #        #     #  #     #   ##      #  #    \n""#     #    #    ####    #     #  #     #   #       ###     \n""#      #####        #   #     #  #    ##   #       #  #    \n""#####      #   #####    #     #   #### #   #       #   ##  \n\n");
}// 传入网址和字典名
std::vector<std::string> GetCombinationURL(char *root, char *dict_file)
{char buffer[512] = { 0 };char this_url[1024] = { 0 };std::vector<std::string> ref;FILE *fp = fopen(dict_file, "r");if (fp != NULL){while (feof(fp) == 0){fgets(buffer, 1024, fp);              // 每次读入一行strtok(buffer, "\n");                 // 去掉行末的 \nbuffer[strcspn(buffer, "\n")] = 0;    // 替换所有 \nsprintf(this_url, "%s%s", root, buffer);ref.push_back(this_url);}}return ref;
}// 屏蔽无用的输出
static size_t write_data(char *d, size_t n, size_t l, void *p){ return 0; }int GetPageStatus(std::string HostUrl)
{CURLcode return_code;return_code = curl_global_init(CURL_GLOBAL_WIN32);if (CURLE_OK != return_code)return 0;CURL *easy_handle = curl_easy_init();int retcode = 0;if (NULL != easy_handle){curl_easy_setopt(easy_handle, CURLOPT_URL, HostUrl);                // 请求的网站curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);   // 设置回调函数,屏蔽输出return_code = curl_easy_perform(easy_handle);                       // 执行CURLreturn_code = curl_easy_getinfo(easy_handle, CURLINFO_RESPONSE_CODE, &retcode);}curl_easy_cleanup(easy_handle);curl_global_cleanup();return retcode;
}// 线程执行函数
void ThreadProc(std::string url)
{boost::lock_guard<boost::mutex> global_mutex(io_mutex);int ret = GetPageStatus(url);if (ret == 200){FILE *fp = fopen("./save.log", "a+");fwrite(url.c_str(), strlen(url.c_str()), 1, fp);fwrite("\n", 2, 1, fp);fclose(fp);}std::cout << "状态码: " << ret << " 地址: " << url << std::endl;
}int main(int argc, char * argv[])
{opt::options_description des_cmd("\n Usage: LyShark URL扫描工具 Ver:1.1 \n\n Options");des_cmd.add_options()("url,u", opt::value<std::string>(), "指定需要的URL地址")("dict,d", opt::value<std::string>(), "指定字典")("help,h", "帮助菜单");opt::variables_map virtual_map;try{opt::store(opt::parse_command_line(argc, argv, des_cmd), virtual_map);}catch (...){ return 0; }// 定义消息opt::notify(virtual_map);// 无参数直接返回if (virtual_map.empty()){ShowOpt();std::cout << des_cmd << std::endl;return 0;}else if (virtual_map.count("help") || virtual_map.count("h")){ShowOpt();std::cout << des_cmd << std::endl;return 0;}else if (virtual_map.count("url") && virtual_map.count("dict")){std::string scan_url = virtual_map["url"].as<std::string>();std::string scan_path = virtual_map["dict"].as<std::string>();// 由于string与char* 需要转换,所以拷贝后转换char src[1024] = { 0 };char path[1024] = { 0 };strcpy(src, scan_url.c_str());strcpy(path, scan_path.c_str());std::vector<std::string> get_url = GetCombinationURL(src, path);boost::thread_group group;for (int x = 0; x < get_url.size(); x++){group.create_thread(boost::bind(ThreadProc, get_url[x]));_sleep(50);}group.join_all();}else{std::cout << "参数错误" << std::endl;}return 0;
}

传入参数运行,当访问出现200提示,则自动保存到save.log中,运行效果如下。

  • main.exe --url https://www.lyshark.com --dict c://dict.log

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

响应体和状态码

后端响应体和状态码设计 主流技术&#xff1a;响应体 和 状态码结合使用 响应体&#xff1a;数据 响应 给前端的 格式 1、为什么要设计统一响应体? 1、系统默认提供许多的状态码&#xff0c;但HTTP的状态码数量有限。 通过修改响应返回的JSON数据&#xff0c;更好的表达业务中…

【docker下安装jenkins】(一)

目的&#xff1a;在Linux操作系统&#xff08;x86_64)下&#xff0c;使用docker部署jenkins&#xff0c;python使用压缩包安装 安装jenkins的步骤 &#xff11;、编排jenkins的docker-compose.yml文件 说明&#xff1a;这里遇到部署jenkins后&#xff0c;占用内存8G,所以重新…

scala解析命令行参数详解

如何用scala解析命令行参数&#xff1a; 首先&#xff0c;需要在项目中添加Apache Commons CLI库的依赖。可以在pom.xml中加&#xff0c; 也可以在build.sbt文件中添加如下行&#xff1a; libraryDependencies "commons-cli" % "commons-cli" % "…

HarmonyOS第一课-对比Kotlin,快速入门TypeScript

编程语言简介 基础类型 1. 布尔值 TypeScript 和 Kotlin: 两者都有 boolean 类型&#xff0c;用于表示 true 或 false。 ts示例&#xff1a; let isDone:boolean falsekotlin示例&#xff1a; val isDone: Boolean false2. 数字 TypeScript: 有 number 类型&#xff0c…

hadoop 配置历史服务器 开启历史服务器查看 hadoop (十)

1. 配置了三台服务器&#xff0c;hadoop22, hadoop23, hadoop24 2. hadoop文件路径: /opt/module/hadoop-3.3.4 3. hadoop22机器配置历史服务器的配置文件&#xff1a; 文件路径&#xff1a;/opt/module/hadoop-3.3.4/etc/hadoop 文件名称&#xff1a;mapred-size.xml 新增历…

帮我想几个关于实人认证API的中文文章标题

引言 随着信息时代的迅速发展&#xff0c;数据变得愈加庞大和复杂。在这个大数据的时代&#xff0c;企业面临着海量信息的管理和利用挑战。为了更有效地获取并利用数据&#xff0c;企业信息模糊搜索API成为了企业数据智能引擎的一部分&#xff0c;为企业提供了精准的企业列表检…

RK3588产测软件介绍

1. 简介 本公司研发的产测软件是用于在量产的过程中快速地甄别产品功能和器件的好坏&#xff0c;即重点 FCT&#xff08;Functional Test&#xff09;测试&#xff0c;进而提高生产效率和检测的准确性。 2. 产测软件介绍 QT开发的ARM平台产测图形化软件&#xff0c;一键开启傻…

【问题处理】WPS提示不能启动此对象的源应用程序如何处理?

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近在用WPS打开word文件中&#xff0c;插入的Excel附件时&#xff0c;无法打开&#xff0c;提示&#xff1a;“不能启动此对象的源应用程序”。 经过上网查找处理办法&#xff0c;尝试解决&#xff0c;现将解决过程记…

前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章 —— 系列文章目录

系列文章目录 第一章 技术栈简介 (开篇) 第二章 环境部署 (Node等环境安装) 第三章 项目创建 (Vite项目初始化) 第四章 认识项目目录 第五章 Element-Plus组件库安装和使用 第六章 样式格式化 (Sass) 第七章 路由配置 (vue-router路由守卫) 第八章 请求配置 (Axios请求和响应拦…

大模型LLM 在线量化;GPTQ\AWQ量化及推理

1、大模型LLM 在线量化 参考:https://www.cnblogs.com/bruceleely/p/17348782.html ##8bit model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).quantize(8).half(

HDR相关文章收集

一文分清HDR10/HDR10/Dolby Vision 什么是4K HDR&#xff1f;HDR10、HDR10 PRO、杜比视界HDR区别 HDR中显示器标准和视频编码标准 芯片支持HDR解码 HDR详解 HDR技术趋势浅析 BT.2100 HDR 基本规范 图形图像基础知识&#xff08;5&#xff09;---- HDR 基本概念

Linux socket编程(4):服务端fork之僵尸进程的处理

在上一节利用fork实现服务端与多个客户端建立连接中&#xff0c;我们使用fork函数来实现服务端既可以accept新的客户端连接请求&#xff0c;又可以接收已连接上的客户端发来的消息。但在Linux中&#xff0c;在子进程终止后&#xff0c;父进程需要处理该子进程的终止状态&#x…

ChatGLM3-6B安装

1 CentOS7 安装Python 10 1.1 安装基础环境 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel1.2 升级 OpenSSL 不升级 OpenSSL&#xff0c;pip instal…

【开源】基于Vue.js的车险自助理赔系统的设计和实现

项目编号&#xff1a; S 018 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S018&#xff0c;文末获取源码。} 项目编号&#xff1a;S018&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车…

[GFCTF 2021]wordy 编写去花IDAPYTHON

首先查壳 发现没有东西 然后放入ida 发现没有main并且软件混乱 发现这里1144的地方 出错 IDA无法识别数据 报错内容是EBFF 机器码 这里看了wp知道是很常见的花指令 所以我们现在开始去花 这里因为我们需要取出 EBFF 下面的地址也都是 EBFF 所以工作量大 使用IDApython脚本即…

EasyRecovery2024最新永久破解版本安装包下载

当我们处理重要的文件数据时&#xff0c;遇到突然停电导致数据来不及保存&#xff0c;再次打开电脑后&#xff0c;此前处理的数据可能丢失&#xff0c;这无疑会影响我们的工作进度&#xff0c;数据恢复软件在此时就派上用场&#xff0c;那么下面就来具体介绍EasyRecovery软件的…

FL Studio21怎么破解?2024年最新FLStudio21.2.0安装解锁特别版下载使用图文教程

用FL Studio编曲&#xff0c;让音乐成为你的翅膀&#xff0c;飞翔在无尽的创作海洋中吧&#xff01; FL Studio作为一款功能强大且备受赞誉的音乐制作软件&#xff0c;为你提供了一个独特的创作平台。通过FL Studio&#xff0c;你可以自由地创作、编曲&#xff0c;制作属于自己…

4.6 Windows驱动开发:内核遍历进程VAD结构体

在上一篇文章《内核中实现Dump进程转储》中我们实现了ARK工具的转存功能&#xff0c;本篇文章继续以内存为出发点介绍VAD结构&#xff0c;该结构的全程是Virtual Address Descriptor即虚拟地址描述符&#xff0c;VAD是一个AVL自平衡二叉树&#xff0c;树的每一个节点代表一段虚…

API测试:了解API接口测试与API接口测试指南

本文为您提供API接口测试的全面指南。从基础概念到测试方法&#xff0c;再到最佳实践&#xff0c;本文将帮助您深入了解API测试&#xff0c;确保您的API稳健、高效。 一、API测试的基础概念 API&#xff08;应用程序编程接口&#xff09;是不同软件应用程序之间的通信桥梁。A…

【算法】区间调度算法

目录 1.概述2.代码实现3.应用 1.概述 &#xff08;1&#xff09;区间调度算法 (Interval Scheduling Algorithm) 是一种在给定的一组任务中&#xff0c;选择尽可能多的相互不冲突的任务的算法。在这个问题中&#xff0c;每个任务都有一个开始时间和结束时间。两个任务是相互冲…