Jit ассемблер в C ++, используя функции C

Я разрабатываю простую систему сборки JIT на C ++, но я хочу вызывать функции C в этой системе jit, так что, как я думал … мне нужен указатель команды … но я не знаю, как я могу получить это …

Это мой код

#include <cstdio>
#include <vector>
#include <windows.h>

int Execute(std::vector<unsigned char> code)
{
int eaxRegister;

unsigned char* func = (unsigned char*)VirtualAlloc( 0, code.size() + 1, 0x1000, 0x40 );

memcpy( func, code.data(), code.size() );
func[code.size()] = 0xC3; // add the ret to the final of code final

CallWindowProc( (WNDPROC)func, 0, 0, 0, 0 );

_asm mov eaxRegister, eax;

VirtualFree( func, code.size() + 1, 0x4000 );

return eaxRegister;
}

int main()
{
std::vector<unsigned char> code;

//mov eax, 10
code.push_back( 0xc7 );
code.push_back( 0xc0 );
code.push_back( 0xa );
code.push_back( 0x0 );
code.push_back( 0x0 );
code.push_back( 0x0 );

//mov ecx, 10
code.push_back( 0xc7 );
code.push_back( 0xc1 );
code.push_back( 0xa );
code.push_back( 0x0 );
code.push_back( 0x0 );
code.push_back( 0x0 );

//add eax, ecx
code.push_back( 0x3 );
code.push_back( 0xc1 );

// push MESSAGE
const char* ohi = "HI";
code.push_back( 0x69 );
code.push_back( *ohi );

// call prinf ?????
code.push_back( 0xe8 );
code.push_back( 0xfff/* offset of printf */ ) ;

// add esp, 4
code.push_back( 0x83 );
code.push_back( 0xc4 );
code.push_back( 0x04 );
code.push_back( 0x0 );
code.push_back( 0x0 );
code.push_back( 0x0 );

int exec = Execute( code );
printf("SUM = %d", exec);

return 0;
}

Итак, моя проблема в том, как я могу получить смещение команды printf для использования в JIT, или как я могу использовать функцию C, используя JIT ???

Спасибо
Александр

1

Решение

printf (без паренов) оценит по адресу функции printfтак что вы, очевидно, хотите code.push_back(printf);

Изменить: Конечно, так как вы определили code как простой вектор`, это не будет работать как есть. Вам нужно будет сдвинуть назад отдельные байты адреса по одному. Вот короткая демонстрация, показывающая, что нужно нажать ее обратно, затем распечатать результаты и показать, что это почти то же самое, что вы получили, передав адрес в printf и конвертировав с помощью% p:

#include <vector>
#include <stdio.h>
#include <iostream>

int main() {
std::vector<unsigned char> code;

auto a = printf;
char *p = (char *) &a;

printf("%p\n", printf);

for (int i=0; i<sizeof(a); i++)
code.push_back(*p++);

for (int i=0; i<code.size(); i++)
std::cout << std::hex << (unsigned int)code[i] << " ";
return 0;
}

Как видите,% p показывает весь указатель вместе, тогда как это показывает один байт за раз. В Windows (оборудование с прямым порядком байтов) это приведет к тому, что байт будет в обратном порядке.

3

Другие решения

Как отмечает Джерри, вы можете получить адрес extern "C" функция, просто используя имя функции. Проблема в том, что просто поместить это в ваш кодовый поток не поможет: вам нужно сгенерировать реальную инструкцию CALL. Что еще хуже, обычная инструкция CALL на x86 (0xe8) использует относительную к ПК адресацию, которую вы не можете с готовностью использовать, так как вы не знаете, по какому адресу будет в конечном итоге ваш код (значение возможного вызова VirtualAlloc вернусь). Вы можете обойти это, не используя режим адресации с ПК:

void gen_call(std::vector<unsigned char> &code, void *address) {
// mov eax,address
code.push_back(0xb8);
code.push_back((uint32_t)address & 0xff);
code.push_back(((uint32_t)address >> 8) & 0xff);
code.push_back(((uint32_t)address >> 16) & 0xff);
code.push_back(((uint32_t)address >> 24) & 0xff);
// call eax
code.push_back(0xff);
code.push_back(0xd0);
}

Кроме того, ваш код «push MESSAGE» неверен — вы нажимаете первый символ сообщения, но на самом деле вы хотите нажать адрес строки.

0

Я решил вопрос, я перешел на использование reinterpret_cast

вот мое решение:

#include <cstdio>
#include <vector>
#include <windows.h>

using namespace std;

class Buffer: public vector<unsigned char>
{
public:
void push_dword(DWORD dw)
{
push_back(dw);
push_back(dw >> 8);
push_back(dw >> 16);
push_back(dw >> 24);
}

void push_ptr(const void *p)
{
push_dword(reinterpret_cast<DWORD>(p));
}

int Execute()
{
char *func = reinterpret_cast<char *>(VirtualAlloc(
0, size() + 1, MEM_COMMIT, PAGE_EXECUTE_READWRITE ));

memcpy( func, data(), size() );
func[size()] = 0xC3; // add the ret to the final of code final

int ret = (*reinterpret_cast<int(*)()>(func))();

VirtualFree( func, 0, MEM_RELEASE );

return ret;
}
};

int main()
{
Buffer code;

// push MESSAGE
const char* ohi = "HI\n";
code.push_back( 0x68 );
code.push_ptr( ohi );

// mov eax, printf
code.push_back( 0xb8 );
code.push_ptr( reinterpret_cast<void *>(&printf) );

// call eax
code.push_back( 0xff );
code.push_back( 0xd0 );

// add esp, 4
code.push_back( 0x83 );
code.push_back( 0xc4 );
code.push_back( 0x04 );

int exec = code.Execute();
printf("SUM = %d\n", exec);

return 0;
}
0
По вопросам рекламы [email protected]