mardi 27 mars 2018

C++ Web Request Crash

I'm working on a pretty big project that also involves making some get requests, pulling data from websites etc. For that this library: [CHttpClient] is used.

Sometimes when web requests are made like shown below, the program just crashes without any verbal error message or anything like that. When I looked at the previously used strings in memory in ollydbg, there were some blocks that had tons of '??????' in them. I suspect that somewhere there is an overflow occuring, but I cannot for the life of it figure out where. Also setting a try / catch around the code segment in question does not help. It would be great if you could point me into a direction, as the last resort I see would be to switch up the library.

This right below is the "top level" call that's being made.

if (!HttpUtils::makeGetRequest(L"https://calendar.yahoo.com", outCookies, response))
        return false;

(outCookies is a NameValueMap (defined below) with the users cookies, response is a std::wstring in which the response is stored)

typedef std::map<std::wstring, std::wstring> NameValueMap;

I have a HttpUtils.cpp class that handles the HTTP requests. Source code for that is as follows (the commented out MessageBoxes are for debugging purposes)

The makeRequest method is the one in question

#include "HttpUtils.h"
#include <memory>

using namespace andrivet::ADVobfuscator;

bool Utilities::HttpUtils::makePostRequest(const wchar_t* url, NameValueMap& postData, NameValueMap& cookies, std::wstring& outResponse)
{
    return makeRequest(url, REQUEST_TYPE::POST, postData, cookies, NameValueMap(), outResponse);
}

bool Utilities::HttpUtils::makePostRequest(const wchar_t* url, NameValueMap& postData, std::wstring& outResponse)
{
    return makeRequest(url, REQUEST_TYPE::POST, postData, NameValueMap(), NameValueMap(), outResponse);
}

bool Utilities::HttpUtils::makeGetRequest(const wchar_t* url, std::wstring& outResponse)
{
    return makeRequest(url, REQUEST_TYPE::GET, NameValueMap(), NameValueMap(), NameValueMap(), outResponse);
}

bool Utilities::HttpUtils::makeGetRequest(const wchar_t* url, NameValueMap& cookies, std::wstring& outResponse)
{
    return makeRequest(url, REQUEST_TYPE::GET, NameValueMap(), cookies, NameValueMap(), outResponse);
}


bool Utilities::HttpUtils::makeRequest(const wchar_t* url, REQUEST_TYPE type, NameValueMap& postData, NameValueMap& cookies, NameValueMap& headers, std::wstring& outResponse)
{
    CHttpClientW httpClient;
    std::unique_ptr<CHttpResponseW> response;
    std::wstringstream responseStream;
    bool redirect_flag = true;
    std::wstring cur_url = url;


    try
    {
        //Add default user agent
        httpClient.SetInternet(L"Mozilla/5.0 (compatible; Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");

        //Add post data if needed
        for (auto postEntry : postData)
            httpClient.AddParam(postEntry.first.c_str(), postEntry.second.c_str());


        //Add header if needed
        for (auto header : headers)
            httpClient.AddHeader(header.first.c_str(), header.second.c_str());


        while (redirect_flag)
        {
            //Add cookies if needed
            for (int i = 0; i < httpClient.GetHeaderCount(L"Cookie"); i++)
                httpClient.RemoveHeader(L"Cookie"), i;

            if (cookies.size())
            {
                std::wstring cookieString = getCookieString(cookies);

                httpClient.AddHeader(L"Cookie", cookieString.c_str());
            }

            //Check if cur_url is good
            if (cur_url.size() > 4 && cur_url.substr(0, 4) != L"http")
            {
                std::wstring baseUrl;

                if (cur_url[0] == L'/')
                {
                    //Need to construct URL adding baseURL
                    if (!getBaseUrl(url, baseUrl))
                        return false;

                    cur_url = baseUrl + cur_url;
                }
                else
                {
                    // TODO: What shall I do ?!

                    return false;
                }
            }

            //Perform request
            if (type == GET)
            {
                //MessageBox(0, cur_url.c_str(), L"CUR_URL REQ", 0);
                try
                {
                    response.reset(httpClient.RequestGet(cur_url.c_str()));
                }
                catch (std::overflow_error &err)
                {
                    MessageBoxA(0, "ERROR", "Debug", 0);
                }
            }
            else
                response.reset(httpClient.RequestPost(cur_url.c_str()));

            if (response->GetStatus() == 302)
            {
                MessageBoxA(0, "Redirect", "Debug", 0);
                redirect_flag = true;

                if (response->GetHeaderCount(L"Location") == 0)
                    return false;

                //Update next url
                cur_url = response->GetHeader(L"Location", 0);

                //Update cookies if needed
                handleSetCookie(response.get(), cookies);
            }
            else
            {
                redirect_flag = false;
                //Get response text
                if (Ryeol::Utils::getResponseContent(response.get(), responseStream, 8192))
                {
                    outResponse = responseStream.str();
                    //MessageBox(0, outResponse.c_str(), L"Printing outResponse", 0);
                    responseStream.clear();

                    return true;
                }
            }
        }
    }
    catch (httpclientexception& e) {
        return false;
    }

    return false;
}

void Utilities::HttpUtils::handleSetCookie(CHttpResponseW* response, NameValueMap& inOutCookies)
{
    int count = response->GetHeaderCount(L"Set-Cookie");

    for (int i = 0; i < count; i++)
    {
        std::wstring curSetCookie = response->GetHeader(L"Set-Cookie", i);
        std::wstring name, value;

        if (getCookieFromSetCookie(curSetCookie, name, value))
            inOutCookies[name] = value;
    }
}

bool Utilities::HttpUtils::getBaseUrl(const std::wstring& url, std::wstring& outBase)
{
    const std::wstring protocol_end = L"://";
    const int offs1 = url.find(protocol_end);

    if (offs1)
    {
        //Get next '/'
        const int offs2 = url.find(L'/', offs1 + protocol_end.size());

        outBase = url.substr(0, offs2);

        return true;
    }

    return false;
}

std::wstring Utilities::HttpUtils::getCookieString(NameValueMap& cookies)
{
    CHttpEncoderW encoder;
    std::wstring cookieString;

    for (auto cookie : cookies)
    {
        size_t encodedSize = encoder.UrlEncodeLenW(cookie.second.c_str());
        //PWSTR encodedBuf = new WCHAR[encodedSize];

        //Add name as it is
        cookieString += cookie.first;
        cookieString += L"=";

        //URL encode cookie value
        //encoder.UrlEncodeW(encodedBuf, cookie.second.c_str());

        //Add encoded value to cookieString
        cookieString += cookie.second;
        cookieString += L"; ";

        //Release encodedBuf
        //delete[] encodedBuf;
    }

    return cookieString;
}

bool Utilities::HttpUtils::getCookieFromSetCookie(std::wstring& setCookie_str, std::wstring& outName, std::wstring& outValue)
{
    int offset1 = setCookie_str.find(L"=");
    int offset2 = setCookie_str.find(L";", offset1);

    if (offset1 != std::wstring::npos && offset2 != std::wstring::npos)
    {
        outName = setCookie_str.substr(0, offset1);
        outValue = setCookie_str.substr(offset1 + 1, offset2 - offset1 - 1);

        return true;
    }

    return false;
}

Thanks in advance for your help!




Aucun commentaire:

Enregistrer un commentaire