use boost asio to download the pdb files.

This commit is contained in:
BeneficialCode
2024-12-27 14:42:50 +08:00
parent 6c260e1ec2
commit 528bd780ff
9 changed files with 256 additions and 132 deletions
+1
View File
@@ -73,6 +73,7 @@ LRESULT CGotoKeyDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
{ L"DisablePath",LR"(HKEY_CURRENT_USER\SOFTWARE\Policies\Microsoft\Windows\Safer\CodeIdentifiers\0\Paths)"},
{ L"Internet Settings",LR"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings)"},
{ L"Session Manager",LR"(HKLM\System\CurrentControlSet\Control\Session Manager)"},
{ L"NetworkCards",LR"(HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards)"},
};
for (const auto& [name, path] : locations) {
+1 -1
View File
@@ -100,7 +100,7 @@ void ImportsHandling::UpdateImportInTreeView(const ImportThunk* pImportThunk, CT
}
void ImportsHandling::UpdateModuleInTreeView(const ImportModuleThunk* importThunk, CTreeItem item) {
swprintf_s(Text, L"%s (%d) FThunk: " PRINTF_DWORD_PTR_HALF, importThunk->m_ModuleName, importThunk->m_ThunkMap.size(), importThunk->m_FirstThunk);
swprintf_s(Text, L"%s (%lld) FThunk: " PRINTF_DWORD_PTR_HALF, importThunk->m_ModuleName, importThunk->m_ThunkMap.size(), importThunk->m_FirstThunk);
item.SetText(Text);
int icon = (int)GetAppropiateIcon(importThunk->IsValid());
+7 -1
View File
@@ -120,11 +120,17 @@ PCWSTR CObjectCallbackTable::TypeToString(ObjectCallbackType type) {
CString CObjectCallbackTable::DecodeOperations(ULONG operations) {
CString result;
bool needSeparator = false;
if ((operations & OB_OPERATION_HANDLE_CREATE) == OB_OPERATION_HANDLE_CREATE) {
result += L"HANDLE_CREATE" + CString(L" | ");
result += L"HANDLE_CREATE";
needSeparator = true;
}
if ((operations & OB_OPERATION_HANDLE_DUPLICATE) == OB_OPERATION_HANDLE_DUPLICATE) {
if (needSeparator) {
result += L" | ";
}
result += L"HANDLE_DUPLICATE";
}
+229 -95
View File
@@ -3,30 +3,15 @@
#include <filesystem>
#include <Helpers.h>
#include <fstream>
#include <asio.hpp>
#include <asio\ssl.hpp>
using Poco::URIStreamOpener;
using Poco::StreamCopier;
using Poco::Path;
using Poco::Exception;
using Poco::Net::HTTPStreamFactory;
using Poco::Net::FTPStreamFactory;
using Poco::SharedPtr;
using Poco::Net::HTTPSStreamFactory;
using Poco::Net::SSLManager;
using Poco::Net::Context;
using Poco::Net::InvalidCertificateHandler;
using Poco::Net::ConsoleCertificateHandler;
using Poco::Net::HTTPSClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPMessage;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPClientSession;
#pragma comment(lib,"Ws2_32")
#pragma comment(lib,"Iphlpapi")
#pragma comment(lib,"Crypt32")
bool SymbolFileInfo::SymDownloadSymbol(std::wstring localPath) {
std::wstring path = localPath + L"\\" + _path.GetString();
std::filesystem::create_directories(path);
@@ -113,90 +98,239 @@ bool SymbolFileInfo::GetPdbSignature(ULONG_PTR imageBase,PIMAGE_DEBUG_DIRECTORY
}
downslib_error SymbolFileInfo::Download(std::string url, std::wstring fileName, std::string userAgent,
unsigned int timeout,downslib_cb cb, void* userdata){
std::ofstream fileStream;
fileStream.open(fileName, std::ios::out | std::ios::trunc | std::ios::binary);
unsigned int timeout, downslib_cb cb, void* userdata) {
std::ofstream fileStream(fileName, std::ios::out | std::ios::trunc | std::ios::binary);
if (!fileStream) {
return downslib_error::incomplete;
}
SharedPtr<InvalidCertificateHandler> pCertHandler = new ConsoleCertificateHandler(false); // ask the user via console
Context::Ptr pContext = new Context(Context::CLIENT_USE, "", Context::VerificationMode::VERIFY_NONE);
SSLManager::instance().initializeClient(0, pCertHandler, pContext);
Poco::URI uri(url);
if (uri.getScheme() == "http") {
try
{
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
HTTPClientSession session(uri.getHost(), uri.getPort());
HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
session.sendRequest(request);
HTTPResponse response;
session.peekResponse(response);
if (response.getStatus() == HTTPResponse::HTTPStatus::HTTP_FOUND) {
uri = response.get("Location");
}
}
catch (Poco::Exception& exc)
{
fileStream << exc.displayText() << std::endl;
return downslib_error::incomplete;
}
}
else if (uri.getScheme() == "https") {
try
{
HTTPSClientSession session(uri.getHost(), uri.getPort());
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
session.sendRequest(request);
HTTPResponse response;
session.peekResponse(response);
if (response.getStatus() == HTTPResponse::HTTPStatus::HTTP_FOUND) {
uri = response.get("Location");
}
}
catch (Poco::Exception& exc)
{
fileStream << exc.displayText() << std::endl;
return downslib_error::incomplete;
}
}
downslib_error ret = PdbDownLoader(uri, fileStream);
cb(userdata, 100, 100);
fileStream.close();
return ret;
}
using tcp = asio::ip::tcp;
namespace ssl = asio::ssl;
unsigned long long SymbolFileInfo::GetPdbSize(std::string url, std::wstring fileName, std::string userAgent,
unsigned int timeout) {
try {
asio::io_context ioc;
ssl::context ctx(ssl::context::sslv23_client);
return 0;
int redirect_count = 0;
const int max_redirects = 5;
while (redirect_count < max_redirects) {
std::string protocol, host, path;
if (url.substr(0, 8) == "https://") {
protocol = "https";
url = url.substr(8);
}
else if (url.substr(0, 7) == "http://") {
protocol = "http";
url = url.substr(7);
}
else {
throw std::runtime_error("Invalid URL protocol");
}
size_t path_pos = url.find('/');
host = (path_pos == std::string::npos) ? url : url.substr(0, path_pos);
path = (path_pos == std::string::npos) ? "/" : url.substr(path_pos);
tcp::resolver resolver(ioc);
auto const results = resolver.resolve(host, protocol);
std::string request = "GET " + path + " HTTP/1.1\r\n"
"Host: " + host + "\r\n"
"User-Agent: " + userAgent + "\r\n"
"Accept: */*\r\n"
"Connection: close\r\n\r\n";
if (protocol == "https") {
ssl::stream<tcp::socket> stream(ioc, ctx);
SSL_set_tlsext_host_name(stream.native_handle(), host.c_str());
asio::connect(stream.next_layer(), results.begin(), results.end());
stream.handshake(ssl::stream_base::client);
asio::write(stream, asio::buffer(request));
asio::streambuf response;
asio::error_code header_ec;
asio::read_until(stream, response, "\r\n\r\n", header_ec);
if (header_ec) {
throw asio::system_error(header_ec);
}
std::istream response_stream(&response);
std::string http_version;
unsigned int status_code;
std::string status_message;
response_stream >> http_version >> status_code;
std::getline(response_stream, status_message);
if (status_code == 301 || status_code == 302 || status_code == 307 || status_code == 308) {
std::string header;
while (std::getline(response_stream, header) && header != "\r") {
if (header.substr(0, 9) == "Location:") {
std::string new_url = header.substr(10);
new_url.erase(0, new_url.find_first_not_of(" \t"));
new_url.erase(new_url.find_last_not_of(" \r\n") + 1);
if (new_url[0] == '/') {
new_url = protocol + "://" + host + new_url;
}
url = new_url;
redirect_count++;
goto continue_redirect;
}
}
}
if (status_code != 200) {
return downslib_error::incomplete;
}
// Skip remaining headers
std::string header;
while (std::getline(response_stream, header) && header != "\r");
// Write any data that was already read along with the headers
if (response.size() > 0) {
fileStream << &response;
}
// Read the response body in chunks
const size_t chunk_size = 8192;
std::vector<char> buffer(chunk_size);
asio::error_code ec;
size_t bytes_transferred = 0;
while (true) {
bytes_transferred = stream.read_some(asio::buffer(buffer), ec);
if (ec) {
// Check if this is a normal end of stream
if (ec == asio::error::eof ||
ec.value() == 1 || // stream_truncated
ec == asio::ssl::error::stream_truncated) {
break; // Normal termination
}
throw asio::system_error(ec);
}
if (bytes_transferred > 0) {
fileStream.write(buffer.data(), bytes_transferred);
if (!fileStream) {
throw std::runtime_error("Failed to write to file");
}
}
if (bytes_transferred == 0) {
break;
}
}
break;
}
else { // HTTP
tcp::socket socket(ioc);
asio::connect(socket, results.begin(), results.end());
asio::write(socket, asio::buffer(request));
asio::streambuf response;
asio::error_code header_ec;
asio::read_until(socket, response, "\r\n\r\n", header_ec);
if (header_ec) {
throw asio::system_error(header_ec);
}
std::istream response_stream(&response);
std::string http_version;
unsigned int status_code;
std::string status_message;
response_stream >> http_version >> status_code;
std::getline(response_stream, status_message);
if (status_code == 301 || status_code == 302 || status_code == 307 || status_code == 308) {
std::string header;
while (std::getline(response_stream, header) && header != "\r") {
if (header.substr(0, 9) == "Location:") {
std::string new_url = header.substr(10);
new_url.erase(0, new_url.find_first_not_of(" \t"));
new_url.erase(new_url.find_last_not_of(" \r\n") + 1);
if (new_url[0] == '/') {
new_url = protocol + "://" + host + new_url;
}
url = new_url;
redirect_count++;
goto continue_redirect;
}
}
}
if (status_code != 200) {
return downslib_error::incomplete;
}
// Skip remaining headers
std::string header;
while (std::getline(response_stream, header) && header != "\r");
// Write any data that was already read along with the headers
if (response.size() > 0) {
fileStream << &response;
}
// Read the response body in chunks
const size_t chunk_size = 8192;
std::vector<char> buffer(chunk_size);
asio::error_code ec;
size_t bytes_transferred = 0;
while (true) {
bytes_transferred = socket.read_some(asio::buffer(buffer), ec);
if (ec) {
if (ec == asio::error::eof || ec.value() == 1) {
break; // Normal termination
}
throw asio::system_error(ec);
}
if (bytes_transferred > 0) {
fileStream.write(buffer.data(), bytes_transferred);
if (!fileStream) {
throw std::runtime_error("Failed to write to file");
}
}
if (bytes_transferred == 0) {
break;
}
}
break;
}
continue_redirect:
continue;
}
if (redirect_count >= max_redirects) {
throw std::runtime_error("Too many redirects");
}
}
catch (std::exception&) {
fileStream.close();
return downslib_error::incomplete;
}
if (cb) {
cb(userdata, 100, 100);
}
fileStream.close();
return downslib_error::ok;
}
SymbolFileInfo::SymbolFileInfo() {
Poco::Net::initializeSSL();
HTTPStreamFactory::registerFactory();
HTTPSStreamFactory::registerFactory();
FTPStreamFactory::registerFactory();
}
SymbolFileInfo::~SymbolFileInfo() {
FTPStreamFactory::unregisterFactory();
HTTPSStreamFactory::unregisterFactory();
HTTPStreamFactory::unregisterFactory();
Poco::Net::uninitializeSSL();
}
downslib_error SymbolFileInfo::PdbDownLoader(Poco::URI& uri, std::ostream& ostr) {
try {
std::unique_ptr<std::istream> pStr(URIStreamOpener::defaultOpener().open(uri));
StreamCopier::copyStream(*pStr.get(), ostr);
return downslib_error::ok;
}
catch (Exception& exc) {
ostr << exc.displayText() << std::endl;
return downslib_error::incomplete;
}
}
+1 -19
View File
@@ -1,18 +1,5 @@
#pragma once
#include <Poco/URIStreamOpener.h>
#include <Poco/StreamCopier.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Net/HTTPStreamFactory.h>
#include "Poco/Net/HTTPSStreamFactory.h"
#include <Poco/Net/FTPStreamFactory.h>
#include <Poco/SharedPtr.h>
#include <Poco/Net/SSLManager.h>
#include <Poco/Net/ConsoleCertificateHandler.h>
#include <Poco/Net/PrivateKeyPassphraseHandler.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
struct CV_HEADER {
DWORD Signature;
@@ -60,11 +47,6 @@ struct SymbolFileInfo {
downslib_error Download(std::string url, std::wstring fileName,
std::string userAgent, unsigned int timeout,downslib_cb = nullptr, void* userdata = nullptr);
unsigned long long GetPdbSize(std::string url, std::wstring fileName, std::string userAgent,
unsigned int timeout);
downslib_error PdbDownLoader(Poco::URI& uri, std::ostream& ostr);
CString _pdbSignature;
CString _pdbFile;
PdbValidationData _pdbValidation;
+14 -12
View File
@@ -2,10 +2,6 @@
#include "SystemUsersView.h"
#include <algorithm>
#include "SortHelper.h"
#include <Poco/DateTime.h>
#include <Poco/Timestamp.h>
#include <Poco/DateTimeFormatter.h>
#include <Poco/Timezone.h>
#include <lm.h>
#include <sddl.h>
#include <SecurityHelper.h>
@@ -13,17 +9,23 @@
std::string CSystemUsersView::GetReadableTime(DWORD time) const {
Poco::Int64 timestamp = time;
if (timestamp == 0) {
if (time == 0) {
return std::string("Never");
}
Poco::Timestamp ts(timestamp * Poco::Timestamp::resolution());
Poco::DateTime utcDateTime(ts);
int timeZoneOffset = Poco::Timezone::utcOffset();
Poco::DateTime localDateTime = utcDateTime + Poco::Timespan(timeZoneOffset, 0);
std::string readableTime = Poco::DateTimeFormatter::format(localDateTime, "%Y-%m-%d %H:%M:%S");
return readableTime;
// Convert DWORD time to std::chrono::system_clock::time_point
std::chrono::system_clock::time_point tp = std::chrono::system_clock::from_time_t(time);
// Convert to time_t for localtime conversion
std::time_t tt = std::chrono::system_clock::to_time_t(tp);
// Convert to local time
std::tm local_tm = *std::localtime(&tt);
// Format the time as a string
std::ostringstream oss;
oss << std::put_time(&local_tm, "%Y-%m-%d %H:%M:%S");
return oss.str();
}
+1 -1
View File
@@ -110,7 +110,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<AdditionalIncludeDirectories>..\PEParser;..\WinSysCore;..\PdbParser;..\Utils</AdditionalIncludeDirectories>
<ConformanceMode>true</ConformanceMode>
<ExceptionHandling>false</ExceptionHandling>
<ExceptionHandling>Sync</ExceptionHandling>
<TreatWarningAsError>false</TreatWarningAsError>
</ClCompile>
<Link>
-1
View File
@@ -13,7 +13,6 @@
#define _WIN32_WINNT 0x0601
#define _WIN32_IE 0x0700
#define _RICHEDIT_VER 0x0500
#define _HAS_EXCEPTIONS 0
// 解决标准库std::min与min宏冲突
#define NOMINMAX
+2 -2
View File
@@ -9,8 +9,8 @@
```
vcpkg install capstone[x86]:x86-windows-static
vcpkg install capstone[x86]:x64-windows-static
vcpkg install poco[netssl]:x86-windows-static
vcpkg install poco[netssl]:x64-windows-static
vcpkg install asio[openssl]:x86-windows-static
vcpkg install asio[openssl]:x64-windows-static
```
## Compiling