Trix

C# преобразование команд asm в байты

11 сообщений в этой теме

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

Дело вот в чем, есть команда

CALL gta-vc.exe +  AE8F0            ||              call 004AE8F0                ||             E8 DD E8 0D 00

Взаимосвязь между командой и байтами я не вижу, как ни крути... Как понял E8 - равносильно команде call,

тогда как упаковать мой адрес в эти байты?

 

 

Вот мой кодец  

Скрытый текст

            int iProcessId = 1480;
            Process proc = Process.GetProcessById(iProcessId);

            IntPtr hHandle = OpenProcess(ProcessAccessFlags.All, false, iProcessId);
            int ptr_base = (int)proc.MainModule.BaseAddress;

            byte[] asm = new byte[] {
            0x68, 0xB1, 0x00, 0x00, 0x00 , //          - push 000000B1 { 177 }
            0xE8, 0xE6, 0xE8, 0x5D, 0xFF,  //          - call gta-vc.exe+AE8F0
            0x59,                          //          - pop ecx
            0xC3                           //          - ret 
};

нашел базовый адрес модуля игры (если ошибаюсь, поправьте) 

Собственно, как записать адрес я затрудняюсь.... 
Подскажите пожалуйста, на сколько мне подсказали, то что я ищу: 

ptr_base + 0xAE8F0  + 5 //Как это можно записать в код? 

Действительно ли нужен отступ именно на 5? Как преобразовать это в байты?

 

 

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Опубликовано: (изменено)

Может проще будет написать дллку на C++ добавить функцию как экспортируемую, и запускать из под C# после импорта? Просто .Net по своей природе не предназначен использовать asm, так что это то ещё извращение.

 

5 часов назад, Trix сказал:

0xE8, 0xE6, 0xE8, 0x5D, 0xFF

 

А вот это уже хрень какая-то, выходит ты вызываешь ff5de8eb по твоим опкодам, а должен вызывать вроде как физический адрес и программа сама рассчитает положение функции(вроде так называется, если нет прошу поправить, чтобы не создавать путницы), т.е тут должно быть:

 

byte[] asm = new byte[] {
            0x68, 0xB1, 0x00, 0x00, 0x00 , //          - push 000000B1 { 177 }
            0xE8, 0xDD, 0xE8, 0x0D, 0x00,  //          - call gta-vc.exe+AE8F0
            0x59,                          //          - pop ecx
            0xC3                           //          - ret 

 

А так все верно и мне кажется должно заработать, если у тебя дллка и она инжектируется в процесс, иначе ты будешь вызывать по этим опкодам функцию внутри своей программы и тогда возможен краш.

 

Но это не точно, т.к не писал на C# и не знаю всех тонкостей.

Изменено пользователем partoftheworlD
0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Опубликовано: (изменено)

Ну чувак... блин. Че за фигня?

На C++ это выглядело бы примерно так:

BYTE call[] = { 0xE8, 0x00, 0x00, 0x00, 0x00,   /* call relative address */
                0xC3 };                         /* ret */

// VirtualAllocEx 
LPVOID pAlloc = VirtualAlloc( NULL, sizeof( call ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );

if( pAlloc != NULL )
{
	// Патчим наш адрес
	*(DWORD*)( call + 1 ) = (DWORD) foo - ( (DWORD) pAlloc + 5 );

	// Тут заменить на WriteProcessMemory
	memcpy( pAlloc, call, sizeof( call ) );

	CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE) pAlloc, NULL, NULL, NULL );

	VirtualFree( pAlloc, NULL, MEM_RELEASE );
}

В моем случае foo это просто тестовая функция. Код проверил, все работает. Удачи.

Изменено пользователем uhx
0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Опубликовано: (изменено)

13 минуты назад, uhx сказал:

В моем случае foo это просто тестовая функция. Код проверил, все работает. Удачи.

:offtopic:

Почему бы не сделать так? Или твой вариант не использует инжект и проделывает все это как внешний чит?

 

typedef void(*Spawner)(dword);

auto *AnyFunction = reinterpret_cast<Spawner>(address);

void main()
{
	AnyFunction(A2);
}

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID lpReserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
		CreateThread(0, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(main), hmodule, 0, 0);
		break;
....

 

Изменено пользователем partoftheworlD
0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Опубликовано: (изменено)

15 минут назад, partoftheworlD сказал:

Почему бы не сделать так? Или твой вариант не использует инжект и проделывает все это как внешний чит?

Дык этот чувак пишет на шарпе, и у него там "как внешний чит".

Он вообще из этой темы пришел:

Поэтому я по его подобию сделал, как у него там примерно. Так то ясен фиг проще дллку закинуть и через нее вызывать, чем внедрять опкоды и выполнять их через CreateRemoteThread

Изменено пользователем uhx
0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Одно дело - смотреть опкоды в дизассемблере, другое - в отладчике, когда он уже загружен в память. Во втором случае все переходы и смещения уже пересчитаны относительно базового адреса, по которому загрузился исполняемый модуль. В первом - нет. Итого:

 

gta-vc.exe +  AE8F0 - тот адрес, что тебе показывает отладчик.

004AE8F0 - куда будем прыгнем по факту. Тут 400000 - базовый адрес.

E8 DD E8 0D 00 - опкоды из отладчика. E8 - это call, причем относительный, значит прыгать мы будем на 000DE8DD байт вперед (вниз по коду).

 

В общем, посмотри, по какому адресу загрузился gta-vc.exe. Скорее всего, если из этого адреса вычесть 000DE8DD, то получится 000F0E8A.

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, keng сказал:

Одно дело - смотреть опкоды в дизассемблере, другое - в отладчике, когда он уже загружен в память. Во втором случае все переходы и смещения уже пересчитаны относительно базового адреса, по которому загрузился исполняемый модуль. В первом - нет. Итого:

 

gta-vc.exe +  AE8F0 - тот адрес, что тебе показывает отладчик.

004AE8F0 - куда будем прыгнем по факту. Тут 400000 - базовый адрес.

E8 DD E8 0D 00 - опкоды из отладчика. E8 - это call, причем относительный, значит прыгать мы будем на 000DE8DD байт вперед (вниз по коду).

 

В общем, посмотри, по какому адресу загрузился gta-vc.exe. Скорее всего, если из этого адреса вычесть 000DE8DD, то получится 000F0E8A.

Окей, Кенг, я примерно понял, поковыерялся, дошло что это действительно относительный адрес.. 

Правда, как его вычислить ух, это непонятно 

 У меня есть следующие значения 

Смещение на функцию, Базовый адрес, Адрес инъекции, как мне с этим всем можно узнать последующие байты после call?

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Окей, нашлось решение, всем спасибо за участие, если кому-то остался актуален этот вопрос, то вот решение 

jmp - E8, а адрес вычисляется по следующей инструкции:

Нужный адрес(в моем случае gta-vc.exe+AE8F0  - адрес инъекции, куда поместили байты -  5 (место на jmp(1байт) + адрес(4байта))

 

В принципе, пришел к выводу, что как команда call, так и jmp относительна)) 

Всем еще раз спасибо ^_^

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
15 minutes ago, Trix said:

Окей, нашлось решение, всем спасибо за участие, если кому-то остался актуален этот вопрос, то вот решение 

jmp - E8, а адрес вычисляется по следующей инструкции:

Нужный адрес(в моем случае gta-vc.exe+AE8F0  - адрес инъекции, куда поместили байты -  5 (место на jmp(1байт) + адрес(4байта))

 

В принципе, пришел к выводу, что как команда call, так и jmp относительна)) 

Всем еще раз спасибо ^_^

call - это push + jmp в одном флаконе. На стеке сохраняется адрес возврата.

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
22 часа назад, Trix сказал:

Окей, нашлось решение, всем спасибо за участие, если кому-то остался актуален этот вопрос, то вот решение 

jmp - E8, а адрес вычисляется по следующей инструкции:

Нужный адрес(в моем случае gta-vc.exe+AE8F0  - адрес инъекции, куда поместили байты -  5 (место на jmp(1байт) + адрес(4байта))

 

В принципе, пришел к выводу, что как команда call, так и jmp относительна)) 

Всем еще раз спасибо ^_^

Так я тебе про это две темы затирал)

 

В 05.05.2017 в 03:40, uhx сказал:

На C++ это выглядело бы примерно так:


BYTE call[] = { 0xE8, 0x00, 0x00, 0x00, 0x00,   /* call relative address */
                0xC3 };                         /* ret */

// VirtualAllocEx 
LPVOID pAlloc = VirtualAlloc( NULL, sizeof( call ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );

if( pAlloc != NULL )
{
	// Патчим наш адрес
	*(DWORD*)( call + 1 ) = (DWORD) foo - ( (DWORD) pAlloc + 5 );

	// Тут заменить на WriteProcessMemory
	memcpy( pAlloc, call, sizeof( call ) );

	CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE) pAlloc, NULL, NULL, NULL );

	VirtualFree( pAlloc, NULL, MEM_RELEASE );
}

В моем случае foo это просто тестовая функция. Код проверил, все работает. Удачи.

А это тебе не помогло? Хоть и на плюсах, но принцип тот же. Формула для расчета адреса ведь есть. Я думал после этого хоть понятно станет...

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 06.05.2017 в 13:35, uhx сказал:

Так я тебе про это две темы затирал)

 

А это тебе не помогло? Хоть и на плюсах, но принцип тот же. Формула для расчета адреса ведь есть. Я думал после этого хоть понятно станет...

Ну, видишь, я отличаюсь интеллектом. В плане доходит оч. долго:wacko:

Первым делом обратил внимание на ассемблерную команду, а потом на байт-код, поэтому и сбился, но зато запомнится 

0

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас