工控安全系统编程之 WinInet系列函数实现下载

1.实验要求

使用其他函数完善实验1下载功能

  1. 使用WinInet系列函数实现下载
  2. 使用socket函数实现下载
    比URLDownloadToFile的优势在于免杀

备选:
3. 在驱动层自动发包,实现网络功能
4. 自定义协议栈,利用IOCTL向底层发包实现网络功能

2.源代码
版本1
老师的

#include <Windows.h>
#include <WinInet.h>

#pragma comment(lib, "wininet.lib")

using namespace std;

DWORD MyURLDownloadToFile(TCHAR szURL[], TCHAR szLocalPath[])
{
	HINTERNET	hSession;
	HINTERNET	hConnection;
	HANDLE		hFile;
	BYTE		bsBuffer[1024];
	DWORD		dwBytesRead;
	DWORD		dwRet;

	dwRet = 0;
	hSession = hConnection = NULL;
	hFile = NULL;
	//建立会话
	hSession = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
	//打开
	hConnection = InternetOpenUrl(hSession, szURL, NULL, 0, INTERNET_FLAG_RELOAD, 0);
	hFile = CreateFile(szLocalPath, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	//循环读取下载数据
	while (1)
	{
		dwRet = InternetReadFile(hConnection, bsBuffer, sizeof(bsBuffer), &dwBytesRead);
		if (FALSE == dwRet)
		{
			dwRet = GetLastError();
			break;
		}
		else if (0 == dwBytesRead)
		{
			dwRet = 0;
			break;
		}
		WriteFile(hFile, bsBuffer, dwBytesRead, &dwBytesRead, NULL);
	}
	CloseHandle(hFile);
	InternetCloseHandle(hConnection);
	InternetCloseHandle(hSession);

	return	dwRet;
}

int main()
{
	MyURLDownloadToFile("http://10.3.1.91/hi.exe", "C:\\Users\\Administrator\\Desktop\\hahaha.exe");
	return 0;
}

程序运行
在这里插入图片描述

版本2
网上copy Mulinb的

#include <windows.h>
#include <wininet.h>

#include <string>
#include <iostream>
using namespace std;

#pragma comment(lib, "wininet.lib")

//下载
#define  DOWNHELPER_AGENTNAME         "MyAppByMulinB"
#define  LEN_OF_BUFFER_FOR_QUERYINFO  128
#define  DOWNLOAD_BUF_SIZE            (10*1024)  //10KB
#define  MAX_DOWNLOAD_REQUEST_TIME    10  
#define  MAX_DOWNLOAD_BYTESIZE        (1000*1024*1024) //1000MB


BOOL _TryHttpSendRequest(LPVOID hRequest, int nMaxTryTimes); //多次发送请求函数

															 //HTTP下载函数,通过先请求HEAD的方式然后GET,可以通过HEAD对下载的文件类型和大小做限制
BOOL DownloadUrl(std::string strUrl, std::string strFileName)
{
	BOOL bRet = FALSE;
	if (strUrl == "" || strFileName == "")
		return FALSE;

	//定义变量
	HINTERNET hInet = NULL; //打开internet连接handle
	HINTERNET hConnect = NULL; //HTTP连接
	HINTERNET hRequestHead = NULL; //HTTP Request
	HINTERNET hRequestGet = NULL; //HTTP Request
	HANDLE hFileWrite = NULL; //写文件的句柄
	char* pBuf = NULL; //缓冲区
	DWORD dwRequestTryTimes = MAX_DOWNLOAD_REQUEST_TIME; //尝试请求的次数
	DWORD dwDownBytes = 0; //每次下载的大小
	DWORD dwDownFileTotalBytes = 0; //下载的文件总大小
	DWORD dwWriteBytes = 0; //写入文件的大小
	char bufQueryInfo[LEN_OF_BUFFER_FOR_QUERYINFO] = { 0 }; //用来查询信息的buffer
	DWORD dwBufQueryInfoSize = sizeof(bufQueryInfo);
	DWORD dwStatusCode = 0;
	DWORD dwContentLen = 0;
	DWORD dwSizeDW = sizeof(DWORD);

	//分割URL
	CHAR pszHostName[INTERNET_MAX_HOST_NAME_LENGTH] = { 0 };
	CHAR pszUserName[INTERNET_MAX_USER_NAME_LENGTH] = { 0 };
	CHAR pszPassword[INTERNET_MAX_PASSWORD_LENGTH] = { 0 };
	CHAR pszURLPath[INTERNET_MAX_URL_LENGTH] = { 0 };
	CHAR szURL[INTERNET_MAX_URL_LENGTH] = { 0 };
	URL_COMPONENTSA urlComponents = { 0 };
	urlComponents.dwStructSize = sizeof(URL_COMPONENTSA);
	urlComponents.lpszHostName = pszHostName;
	urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
	urlComponents.lpszUserName = pszUserName;
	urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
	urlComponents.lpszPassword = pszPassword;
	urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
	urlComponents.lpszUrlPath = pszURLPath;
	urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;

	bRet = InternetCrackUrlA(strUrl.c_str(), 0, NULL, &urlComponents);
	bRet = (bRet && urlComponents.nScheme == INTERNET_SERVICE_HTTP);
	if (!bRet)
	{
		goto _END_OF_DOWNLOADURL;
	}

	//打开一个internet连接
	hInet = InternetOpenA(DOWNHELPER_AGENTNAME, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);
	if (!hInet)
	{
		bRet = FALSE;
		goto _END_OF_DOWNLOADURL;
	}

	//打开HTTP连接
	hConnect = InternetConnectA(hInet, pszHostName, urlComponents.nPort, pszUserName, pszPassword, INTERNET_SERVICE_HTTP, 0, NULL);
	if (!hConnect)
	{
		bRet = FALSE;
		goto _END_OF_DOWNLOADURL;
	}

	//创建HTTP request句柄
	if (urlComponents.dwUrlPathLength != 0)
		strcpy_s(szURL, urlComponents.lpszUrlPath);
	else
		strcpy_s(szURL, "/");

	//请求HEAD,通过HEAD获得文件大小及类型进行校验
	hRequestHead = HttpOpenRequestA(hConnect, "HEAD", szURL, "HTTP/1.1", "", NULL, INTERNET_FLAG_RELOAD, 0);
	bRet = _TryHttpSendRequest(hRequestHead, dwRequestTryTimes);
	if (!bRet)
	{
		goto _END_OF_DOWNLOADURL; //请求HEAD失败
	}

	//查询content-length大小
	dwContentLen = 0;
	dwSizeDW = sizeof(DWORD);
	bRet = HttpQueryInfo(hRequestHead, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH, &dwContentLen, &dwSizeDW, NULL);
	if (bRet)
	{
		//检查是否文件过大
		if (dwContentLen > MAX_DOWNLOAD_BYTESIZE)
		{
			bRet = FALSE;
			goto _END_OF_DOWNLOADURL;
		}
	}

	//校验完成后再请求GET,下载文件
	hRequestGet = HttpOpenRequestA(hConnect, "GET", szURL, "HTTP/1.1", "", NULL, INTERNET_FLAG_RELOAD, 0);
	bRet = _TryHttpSendRequest(hRequestGet, dwRequestTryTimes);
	if (!bRet)
	{
		goto _END_OF_DOWNLOADURL; //请求HEAD失败
	}

	//创建文件
	hFileWrite = CreateFileA(strFileName.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (INVALID_HANDLE_VALUE == hFileWrite)
	{
		bRet = FALSE;
		goto _END_OF_DOWNLOADURL;
	}

	//分配缓冲
	pBuf = new char[DOWNLOAD_BUF_SIZE]; //分配内存
	if (!pBuf)
	{
		bRet = FALSE;
		goto _END_OF_DOWNLOADURL;
	}

	//多次尝试下载文件
	dwDownFileTotalBytes = 0;
	while (1)
	{
		dwDownBytes = 0;
		memset(pBuf, 0, DOWNLOAD_BUF_SIZE*sizeof(char));
		bRet = InternetReadFile(hRequestGet, pBuf, DOWNLOAD_BUF_SIZE, &dwDownBytes);
		if (bRet)
		{
			if (dwDownBytes > 0)
			{
				dwDownFileTotalBytes += dwDownBytes;
				bRet = WriteFile(hFileWrite, pBuf, dwDownBytes, &dwWriteBytes, NULL); //写入文件
				if (!bRet)
				{
					goto _END_OF_DOWNLOADURL;
				}
			}
			else if (0 == dwDownBytes)
			{
				bRet = TRUE;
				break; //下载成功完成
			}
		}
	}

	//清理
_END_OF_DOWNLOADURL:
	if (INVALID_HANDLE_VALUE != hFileWrite)
		CloseHandle(hFileWrite);
	if (pBuf)
		delete[] pBuf;
	if (hRequestGet)
		InternetCloseHandle(hRequestGet);
	if (hRequestHead)
		InternetCloseHandle(hRequestHead);
	if (hConnect)
		InternetCloseHandle(hConnect);
	if (hInet)
		InternetCloseHandle(hInet);

	return bRet;
}

//多次发送请求函数
BOOL _TryHttpSendRequest(LPVOID hRequest, int nMaxTryTimes)
{
	BOOL bRet = FALSE;
	DWORD dwStatusCode = 0;
	DWORD dwSizeDW = sizeof(DWORD);
	while (hRequest && (nMaxTryTimes-- > 0)) //多次尝试发送请求
	{
		//发送请求
		bRet = HttpSendRequestA(hRequest, NULL, 0, NULL, 0);
		if (!bRet)
		{
			continue;
		}
		else
		{
			//判断HTTP返回的状态码
			dwStatusCode = 0;
			dwSizeDW = sizeof(DWORD);
			bRet = HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwStatusCode, &dwSizeDW, NULL);
			if (bRet)
			{
				//检查状态码
				if (HTTP_STATUS_OK == dwStatusCode) //200 OK
				{
					break;
				}
				else
				{
					bRet = FALSE;
					continue;
				}
			}
		}
	}

	return bRet;
}


int main(int argc, char* argv[])
{
	cout << "正在下载...";
	BOOL bR = DownloadUrl("http://10.3.1.91/hi.exe", "C:\\Users\\Administrator\\Desktop\\hihi.exe");
	if (bR)
		cout << "完成" << endl;
	else
		cout << "失败" << endl;
	cin.get();
	return 0;
}

程序运行
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值