# Creating "Ransomware" Using WinRT

This isn't ransomware.

This is the blueprint for a ransomware testing payload for a "Purple Team" scenario. I am curious of EDR visibility into WinRT (Universal Windows Platform (UWP) apps) — so I crafted a C++ application, which strictly uses WinRT functionality from WINAPI-like-C++, compiled as a WIN32 app, to see how it looks.

This proof-of-concept is essentially a glorified asychronous file string console printer. What makes it unique is it relying entirely on WinRT from a Win32 app.

WinRT possesses the ability to encrypt files. I opted to not introduce file encryption functionality (although it would be bare-bones, plain password protected) into this proof-of-concept because I think ransomware in general is highly susceptible to abuse even in its most basic forms.

Regardless, I think this code is interesting and I wanted to share it. Maybe it'll inspire someone else to review WinRT more, or someone will pick up this code and experiment with it in an enterprise environment.\
\- smelly smellington

```
#include <windows.h>
#include <stdio.h>
#include <roapi.h>
#include <windows.storage.h>
#include <windows.storage.search.h>
#include <windows.foundation.h>
#include <windows.system.threading.h>

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

using namespace ABI::Windows::Storage;
using namespace ABI::Windows::Storage::Search;
using namespace ABI::Windows::System::Threading;
using namespace ABI::Windows::Foundation;

typedef __FIAsyncOperation_1___FIVectorView_1_Windows__CStorage__CIStorageItem IAsyncOperationOfFiles;
typedef __FIVectorView_1_Windows__CStorage__CIStorageItem IAsyncItems;

class ThreadFileProcessor : public IWorkItemHandler {
public:

    ThreadFileProcessor(IStorageItem* FileObject) : ReferenceCount(1), File(FileObject)
    {
        if (File)
            File->AddRef();
    }

    virtual ~ThreadFileProcessor() 
    {
        if (File)
            File->Release();
    }

    HRESULT __stdcall QueryInterface(REFIID Riid, PVOID* ppv)
    {
        if (!ppv)
            return E_POINTER;

        if (Riid == __uuidof(IUnknown) || Riid == __uuidof(IWorkItemHandler))
        {
            *ppv = (IWorkItemHandler*)this;
            AddRef();
            return S_OK;
        }

        *ppv = NULL;
        return E_NOINTERFACE;
    }

    ULONG __stdcall AddRef() { return InterlockedIncrement(&ReferenceCount); }

    ULONG __stdcall Release()
    {
        ULONG Result = _InterlockedDecrement(&ReferenceCount);
        if (Result == 0)
            delete this;

        return Result;
    }

    HRESULT __stdcall Invoke(IAsyncAction* Action)
    {
        HSTRING FileName = NULL;
        HRESULT Result = S_OK;

        if (!File)
            return E_ABORT;

        Result = File->get_Name(&FileName);
        if (SUCCEEDED(Result))
        {
            UINT32 Length = 0;
            LPCWSTR Buffer = NULL;

            Buffer = WindowsGetStringRawBuffer(FileName, &Length);

            printf("File processing: %ws\r\n", Buffer);
        }

        if (FileName)
            WindowsDeleteString(FileName);

        if (File)
            File->Release();

        return S_OK;
    }

private:
    LONG ReferenceCount;
    IStorageItem* File;
};

SIZE_T StringLengthW(_In_ LPCWSTR String)
{
    LPCWSTR String2;

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

    return (String2 - String);
}

INT main(VOID)
{
    HRESULT Result = S_OK;
    
    IKnownFoldersStatics* KnownFolders = NULL;
    IStorageFolder* DocumentsFolder = NULL;
    IInspectable* Inspectable = NULL;
    IQueryOptions* Options = NULL;
    IStorageItemQueryResult* ItemResult = NULL;
    IStorageFolderQueryOperations* Operation = NULL;
    IAsyncOperationOfFiles* AsyncOperation = NULL;
    IAsyncItems* Items = NULL;
    IAsyncInfo* Information = NULL;
    IThreadPoolStatics* ThreadPoolStatics = NULL;
    
    WCHAR StorageString[] = L"Windows.Storage.KnownFolders";
    WCHAR QueryString[] = L"Windows.Storage.Search.QueryOptions";
    WCHAR ThreadString[] = L"Windows.System.Threading.ThreadPool";

    HSTRING KnownFolderClassId = NULL;
    HSTRING QueryOptionsClassId = NULL;
    HSTRING ThreadPoolClassId = NULL;

    UINT32 ObjectCount = 0;

    Result = RoInitialize(RO_INIT_MULTITHREADED);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = WindowsCreateString(StorageString, (UINT32)StringLengthW(StorageString), &KnownFolderClassId);
    if (!SUCCEEDED(Result) || !KnownFolderClassId)
        goto EXIT_ROUTINE;

    Result = RoGetActivationFactory(KnownFolderClassId, IID_IKnownFoldersStatics, (PVOID*)&KnownFolders);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = KnownFolders->get_DocumentsLibrary(&DocumentsFolder);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = WindowsCreateString(QueryString, (UINT32)StringLengthW(QueryString), &QueryOptionsClassId);
    if (!SUCCEEDED(Result) || !QueryOptionsClassId)
        goto EXIT_ROUTINE;

    Result = RoActivateInstance(QueryOptionsClassId, &Inspectable);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Inspectable->QueryInterface(IID_IQueryOptions, (PVOID*)&Options);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Options->put_FolderDepth(FolderDepth_Deep);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = DocumentsFolder->QueryInterface(IID_IStorageFolderQueryOperations, (PVOID*)&Operation);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Operation->CreateItemQueryWithOptions(Options, &ItemResult);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = ItemResult->GetItemsAsyncDefaultStartAndCount(&AsyncOperation);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = AsyncOperation->QueryInterface(IID_IAsyncInfo, (PVOID*)&Information);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = WindowsCreateString(ThreadString, (UINT32)StringLengthW(ThreadString), &ThreadPoolClassId);
    if (!SUCCEEDED(Result) || !ThreadPoolClassId)
        goto EXIT_ROUTINE;

    
    while (TRUE)
    {
        AsyncStatus Status;
        Result = Information->get_Status(&Status);
        if (!SUCCEEDED(Result))
            goto EXIT_ROUTINE;

        if (Status == AsyncStatus::Completed)
            break;
    }

    Result = AsyncOperation->GetResults(&Items);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = Items->get_Size(&ObjectCount);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    Result = RoGetActivationFactory(ThreadPoolClassId, IID_IThreadPoolStatics, (PVOID*)&ThreadPoolStatics);
    if (!SUCCEEDED(Result))
        goto EXIT_ROUTINE;

    for (UINT32 i = 0; i < ObjectCount; i++)
    {
        IStorageItem* File = NULL;
        
        Result = Items->GetAt(i, &File);
        if (SUCCEEDED(Result) && File)
        {
            IAsyncAction* Action = NULL;
            ThreadFileProcessor* FileProcessor = new ThreadFileProcessor(File);

            Result = ThreadPoolStatics->RunAsync(FileProcessor, &Action);
            
            if (FileProcessor)
                FileProcessor->Release();

            if (Action)
                Action->Release();
        }

        if (File)
            File->Release();
    }

    Sleep(1);

EXIT_ROUTINE:

    if (KnownFolderClassId)
        WindowsDeleteString(KnownFolderClassId);

    if (QueryOptionsClassId)
        WindowsDeleteString(QueryOptionsClassId);

    if (ThreadPoolClassId)
        WindowsDeleteString(ThreadPoolClassId);

    if (KnownFolders)
        KnownFolders->Release();

    if (DocumentsFolder)
        DocumentsFolder->Release();

    if (Inspectable)
        Inspectable->Release();

    if (Operation)
        Operation->Release();

    if (ItemResult)
        ItemResult->Release();

    if (AsyncOperation)
        AsyncOperation->Release();

    if (Items)
        Items->Release();

    if (Information)
        Information->Release();

    if (ThreadPoolStatics)
        ThreadPoolStatics->Release();

    RoUninitialize();

    return ERROR_SUCCESS;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://malwaresourcecode.com/home/my-projects/proof-of-concepts/creating-ransomware-using-winrt.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
