C ++ - Изменение инструкции ASM другого файла - PullRequest
0 голосов
/ 25 октября 2019

Мне удалось изменить исполняемый файл так, чтобы он делал именно то, что я хотел, используя Ollydbg

006D0CFA  |. 84DB           TEST BL,BL

, ставший

006D0CFA  |. 84DB           NOP

, и он прекрасно работает.

Теперь я хочу сделать это с C ++. Я думаю, что мог бы использовать WriteProcessMemory, но это не то, что я пытаюсь сделать.

Что я хочу сделать, это сделать программу на C ++ (используя Qt, я не знаю, может ли эта информация помочь) "залатать" бинарный файл. Я хочу, чтобы двоичный файл был изменен с помощью новой инструкции.

Я пытался сделать это:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QTextStream>
#include <QtDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QString textCracked = getFileText(FILE_CRACKED);
    QString textOriginal = getFileText(FILE_ORIGINAL);
    runDiff(textOriginal, textCracked);
}

MainWindow::~MainWindow()
{
    delete ui;
}

QString MainWindow::getFileText(QString filename)
{
    QFile file(filename + ".exe");
    QFile file2(filename + ".txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return "";
    if (!file2.open(QIODevice::WriteOnly | QIODevice::Text))
        return "";
    QTextStream in(&file);
    QTextStream in2(&file2);
    QString line = "";
    while (!in.atEnd()) {
        line += in.readAll();
        in2 << line;
    }
    file.close();
    file2.close();
    return line;
}

void MainWindow::runDiff(QString original, QString cracked)
{
    qDebug() << "Size : " << original.size();
    for(int i = 0 ; i < original.size() ; i++)
    {
        if(original[i] != cracked[i])
            qDebug() << i << ", Original : " << original[i] << " | Cracked : " << cracked[i];
    }
}

И у меня есть такой вывод:

Size :  3324384
2941742 , Original :  '\u201e'  | Cracked :  '\u0090'
2941743 , Original :  '\u00db'  | Cracked :  '\u0090'

Проблемыс моим методом:

  • Мне нужно сделать двоичный файл для исправления второго, сделав его менее полезным, чем ожидалось.
  • Я не могу использовать адрес asm
  • Мой размер 3 324 384. Я ожидал, что у меня будет 2 957 310 (006D2FFE (последняя инструкция в Ollydbg) - 401000 (первая инструкция в Ollydbg)). Откуда эта разница?

Заранее спасибо. Я, наверное, что-то забыл, не стесняйтесь спрашивать больше деталей

Ответы [ 3 ]

0 голосов
/ 14 ноября 2019

В комментариях Нокс уточнил, что он хочет редактировать файл, а не процесс. Вот простой проект, который иллюстрирует, как исправить файл:

#include <windows.h>
#include <iostream>
#include <fstream>

int main()
{
    HANDLE hFile = CreateFile("test.txt", FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_DELETE, 0, CREATE_ALWAYS, 0, 0);
    CloseHandle(hFile);

    std::fstream fs("test.txt", std::ios::in | std::ios::out | std::ios::binary);

    fs.write("\x52\x61\x6B\x65\x53\x75\x63\x6B\x73", 10);
    std::streampos size = fs.tellg();

    char* buffer = new char[size];

    fs.seekg(0, std::ios::beg); //change offset here
    fs.read(buffer, size);

    std::cout << "file says: " << buffer << std::endl;

    fs.seekg(0, std::ios::beg);
    fs.write("\x52\x61\x6B\x65\x52\x6F\x63\x6B\x73", 10);

    std::cout << "file patched!\n";

    fs.seekg(0, std::ios::beg);
    fs.read(buffer, size);

    std::cout << "file says: " << buffer << std::endl;

    fs.close();
    delete[] buffer;

    return 0;
}

Объяснение:

  • Создать файл

  • Открыть поток файлов в режиме ввода, вывода и в двоичном режиме

  • Запишите в него несколько байтов, эти байты представляют ASCII "RakeSucks"

  • tellg () дает текущую позицию потока, которая также имеет размер

  • Чтобы показать вам, как вы читаете из файла

  • Мы используем seekg (), чтобы перейти к началу

  • Если вы хотите перейти к определенному смещению файла для исправления, замените 0 своим смещением.

  • Мы создаем буфер и используем read () для чтения только что написанного текста, а затем выводим его на консоль

  • Затем мы используем seekg ()чтобы вернуться к началу файла

  • Мы используем write (), чтобы перезаписать наши оригинальные байты новыми.

  • Опять мыпрочитайте байты и этовыходы "RakeRocks"

0 голосов
/ 15 ноября 2019

Благодаря каждому комментарию / ответу, вот что я сделал:

QString MainWindow::getFileText(QString filename)
{
    // Creating QFile's object and checking if it is rightly opened
    QFile test(filename + "Patched.exe");
    QFile file(filename);
    QDataStream in(&test); // Input object
    if(!test.open(QIODevice::WriteOnly))
        return "";
    if(!file.open(QIODevice::ReadOnly))
       return "";


    QByteArray datas = file.read(file.size());
    process_datas(*datas); // Modify datas in another function
    in.writeRawData(datas, static_cast<int>(file.size())); // Save datas in the new file
    file.close();
    test.close();
    return "";
}

он сохраняет ту же архитектуру, что и GuidedHacking, но использует Qt. Я пытался сделать много вещей, чтобы это работало, и первое, что мне нужно было сделать, это рассмотреть больше, чем я думал: 1) ну да, это именно то, что вы намеревались сделать 2) вам нужно смещение файла 3) не используйте QTextStream - Шут

Спасибо всем.

0 голосов
/ 12 ноября 2019

Страницы памяти, которые содержат инструкции по сборке, будут иметь разрешения на выполнение, но не на запись. Чтобы изменить их, вы должны использовать VirtualProtectEx перед попыткой записи.

Для этого мы можем использовать небольшую оболочку для исправления байтов:

void PatchEx(HANDLE hProcess, char* dst, char* src, int size)
{
    DWORD oldprotect;
    VirtualProtectEx(hProcess, dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
    WriteProcessMemory(hProcess, dst, src, size, NULL);
    VirtualProtectEx(hProcess, dst, size, oldprotect, &oldprotect);
}

Если выЧтобы применить NOP, вы можете использовать эту функцию:

void NopEx(char* dst, unsigned int size, HANDLE hProcess)
{
    char* nopArray = new char[size];
    memset(nopArray, 0x90, size);

    DWORD oldprotect;
    VirtualProtectEx(hProcess, dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
    WriteProcessMemory(hProcess, dst, nopArray, size, NULL);
    VirtualProtectEx(hProcess, dst, size, oldprotect, &oldprotect);
    delete[] nopArray;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...