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

Вопрос - Каковы преимущества Transactional NTFS and Registry

PlebsoVata

RAID-массив
Пользователь
Регистрация
05.10.2019
Сообщения
87
Реакции
34
Недавно наткнулся на хидер <ktmw32.h> и прочие, в которых есть функции CreateFileTransacted, RegCreateKeyTransacted, CreateTransaction и тд.
Каковы их преимущества и недостатки в общем и по сравнению с идентичными функциями без постфикса Transacted?

Понял что так как это все транзакционное, то здесь используется и выполняется принцип ACID(Atomicity, Consistency, Isolation, Durability).
Хочется понять в каких случаях имеет смысл юзать CreateFileTransacted, а в каких просто CreateFile, помимо того что первое работает начиная только с висты.
 
Процитирую википедию:

Технология призвана повышать надёжность создаваемых приложений, способствуя поддержанию целостности данных, и упрощать их разработку благодаря значительному уменьшению количества кода обработки ошибок.
Более подробно можешь почитать тут.
 
Процитирую википедию:


Более подробно можешь почитать тут.
Ну вот например взять такой код, не вижу особой разницы между первым и вторым способом, разве что с TxF кода чутка больше
C++:
#include <Windows.h>
#include <ktmw32.h>
#include <stdio.h>
#pragma comment(lib, "ktmw32.lib")

int main()
{
    // First
    auto transaction = CreateTransaction(NULL, NULL, NULL, NULL, NULL, 0, (WCHAR*)L"Test");

    auto handle = CreateFileTransacted(L"some.txt", GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, transaction, NULL, NULL);

    if (handle != INVALID_HANDLE_VALUE)
    {
        puts("File opened via TxF");
        // Reading data
        CommitTransaction(transaction);
        CloseHandle(handle);
    }
    else
    {
        RollbackTransaction(transaction);
        puts("Error committing transaction");
    }
    CloseHandle(transaction);

    // Second
    auto handle2 = CreateFile(L"some.txt", GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (handle2 != INVALID_HANDLE_VALUE)
    {
        puts("File opened via CreateFile");
        // Reading data
        CloseHandle(handle2);
    }
    else
    {
        puts("Error CreateFile");
    }
}
Нашел что некоторые юзают эти функция при process_doppelganging'e здесь:
в гугле тоже юзают:

И я хочу понять зачем они юзают TxF, почему обычными файловыми функциями нельзя было ограничиться, какие есть нюансы использования и тд, хоть майкрософт и забросили поддержку этого апи и могут удалить его в следующих версиях винды, наверняка в нем есть что-то, а может и нет
 
Ну вот например взять такой код, не вижу особой разницы между первым и вторым способом, разве что с TxF кода чутка больше
C++:
#include <Windows.h>
#include <ktmw32.h>
#include <stdio.h>
#pragma comment(lib, "ktmw32.lib")

int main()
{
    // First
    auto transaction = CreateTransaction(NULL, NULL, NULL, NULL, NULL, 0, (WCHAR*)L"Test");

    auto handle = CreateFileTransacted(L"some.txt", GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, transaction, NULL, NULL);

    if (handle != INVALID_HANDLE_VALUE)
    {
        puts("File opened via TxF");
        // Reading data
        CommitTransaction(transaction);
        CloseHandle(handle);
    }
    else
    {
        RollbackTransaction(transaction);
        puts("Error committing transaction");
    }
    CloseHandle(transaction);

    // Second
    auto handle2 = CreateFile(L"some.txt", GENERIC_READ,
        FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (handle2 != INVALID_HANDLE_VALUE)
    {
        puts("File opened via CreateFile");
        // Reading data
        CloseHandle(handle2);
    }
    else
    {
        puts("Error CreateFile");
    }
}
Нашел что некоторые юзают эти функция при process_doppelganging'e здесь:
в гугле тоже юзают:

И я хочу понять зачем они юзают TxF, почему обычными файловыми функциями нельзя было ограничиться, какие есть нюансы использования и тд, хоть майкрософт и забросили поддержку этого апи и могут удалить его в следующих версиях винды, наверняка в нем есть что-то, а может и нет
Читаем описание техники на одном из ИБ порталов:

  1. Transact—process a legitimate executable into the NTFS transaction and then overwrite it with a malicious file.
  2. Load—create a memory section from the modified (malicious) file.
  3. Rollback—rollback the transaction (deliberately failing the transaction), resulting in the removal of all the changes in the legitimate executable in a way they never existed.
  4. Animate—bring the doppelganger to life. Use the older implementation of Windows process loader to create a process with the previously created memory section (in step 2), which is actually malicious and never saved to disk, "making it invisible to most recording tools such as modern EDRs."

В процессе выполнения NTFS транзакции легитимный файл подменяется вредоносным, в этом фишка техники. А другие его используют в связи с "повышенной надёжностью и упрощением разработки", следуя документации.
 
Читаем описание техники на одном из ИБ порталов:



В процессе выполнения NTFS транзакции легитимный файл подменяется вредоносным, в этом фишка техники. А другие его используют в связи с "повышенной надёжностью и упрощением разработки", следуя документации.
Нашел еще интересный способ применений этих функций для undo\redo в файлах
в CreateFileTransacted передается предпоследним параметром PUSHORT с миниверсией
Все миниверсии файла как-то хранятся, не знаю как, и после CommitTransaction или RollbackTransaction они удаляются.
Чтобы сохранить миниверсию, нужно позвать DeviceIoControl с кодом FSCTL_TXFS_CREATE_MINIVERSION, но почему то она фейлится, вроде по документации все правильно делаю, возможно я криворукий, а возможно в 10 винде уже частично поддержку убрали, хз.
Код ошибки 50 с сообщением: The request is not supported.
Вот код:
C++:
std::string GetLastErrorAsString()
{
    //Get the error message, if any.
    DWORD errorMessageID = ::GetLastError();
    if (errorMessageID == 0)
        return std::string(); //No error message has been recorded

    LPSTR messageBuffer = nullptr;
    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);

    std::string message(messageBuffer, size);

    //Free the buffer.
    LocalFree(messageBuffer);

    return message;
}

void TestFunction()
{
    DWORD timeout = 10 * 1000; // 10 seconds
    auto trans_ = CreateTransaction(NULL, NULL, NULL, NULL, NULL, timeout, NULL);
    if (trans_ == INVALID_HANDLE_VALUE)
        return;


    TXFS_CREATE_MINIVERSION_INFO txfMiniversion{};
    txfMiniversion.MiniVersion = 0xFFFE;
    auto file_ = CreateFileTransacted(L"some.txt", GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL, trans_, &txfMiniversion.MiniVersion, NULL);
    if (file_ == INVALID_HANDLE_VALUE)
    {
        CloseHandle(trans_);
        return;
    }

    DWORD lpBytesReturned = 0;
    BOOL result = DeviceIoControl(
        file_,                                    // handle to file
        FSCTL_TXFS_CREATE_MINIVERSION,            // control code creates a new mini-version
        NULL,                                    // input buffer (null)
        0,                                        // input buffer size
        &txfMiniversion,                        // mini-version info structure
        sizeof(TXFS_CREATE_MINIVERSION_INFO),    // size of output buffer
        &lpBytesReturned,                        // number of bytes returned
        NULL                                    // OVERLAPPED structure (null for synchronous operation)
    );
    if (result == NULL)
    {
        puts("Failed device io");
    }
    puts(GetLastErrorAsString().data());
}
 


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