Почему чтение не разрешено?

Весь код:
#include <fstream>
#include <iostream> 
#include <stdio.h>
#include <iomanip>  
#include <windows.h>

using namespace std;

unsigned char	b[] = "\xa1\x00\x70\xe8\x00";
int mySequency[256] = { 3 };

void *exec = VirtualAlloc(0, sizeof b, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
int main()
{
	memcpy(exec, b, sizeof b);
	((void(*)())exec)();

	system("pause");
	return 0;
}


Простой shellcode выполняется без проблем, например положить какое-то число в регистр, а вот когда в нем происходит попытка чтения или записи переменной mySequency, получаем ошибку:
5b10d7464d08f055127010.jpeg

Пробовал сделать:
DWORD old_protect;
VirtualProtect((DWORD*)mySequency, 256, PAGE_READWRITE, &old_protect);

Никак не влияет.

Данный байтовый код следующей инструкции:
mov eax, dword ptr[mySequency]

В виде ассемблерной вставки в Visual Studio работает без проблем. Подозреваю что нужно что-то еще подкрутить в конфигах проекта, но вроде уже все поотключал...

Покопался в конфигах, вроде как иногда ошибки с памятью пропадают, но теперь появилось:
5b10e44aa2d3f371937173.jpeg
  • Вопрос задан
  • 147 просмотров
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Нет, ваш опкод соответствует инструкции
mov eax, dword ptr [0xe87000]
А кто вам сказал, что переменная mySequency находится по адресу 0xe87000? При каждом запуске программы её адрес может быть другим.
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Отлично, вы уже запустили какой-то код. Но соглашение вызова так и не выдержали.
1. Используйте соглашение вызова STDCALL. Тогда функция должна будет сама подчищать за собой. Поскольку в ней нет никаких локальных переменных, и подчистка не потребуется.
typedef uint32_t WINAPI (*SomeFunc)();
uint32_t result = (SomeFunc)exec();

Заодно это позволит увидеть, что функция запустилась. В любом случае возвращаемое значение будет в eax.
2. В конце нашей функции поставьте RET (опкод CB, если я не ошибаюсь).
3. Вычислите и впатчите в наш код адрес переменной.

я думал тут адрес указывается относительно текущего сегмента, как тогда быть?

Начиная с защищённого режима 386, у нас «плоская память». Сегменты используются только загрузчиками, ВМами и прочей шушерой. Просто вычислите 32-битный адрес и запишите куда надо.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы