Вызов функций внутри шеллкода

Я хотел бы собрать небольшой double(...) функционирует как шелл-код x64. У меня уже есть рабочая программа для генерации закодированной сборки для простых математических операций, таких как a + b / a, где a а также b являются double параметры для функции.

Сгенерированный код загружается в исполняемый файл mmap буфер и может быть вызван позже.

У меня есть следующая проблема: я хотел бы позвонить math.h функции как sin, exp и т.д. внутри моего сгенерированного шеллкода. Так как все call коды операций так или иначе используют 32-битные адреса или относительные переходы, я не могу легко использовать эти инструкции. Поэтому я попытался реализовать свой собственный call-инструкция так:

lea rax, [rip+0x0] ;load instruction pointer into rax
add rax, <offset-to-return-to>
push rax

moveabs rax, <adress-of-function> ;load the function pointer to rax
jmp rax

Это мой код для генерации этих инструкций:

//lea rax, [rip+0x0]
insertAll(code,std::list<uint8_t>{ 0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00 });
//add rax, <offset-to-return-to>
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC0, <offset-to-return-to>});

//push rax
code.push_back(0x50);

//moveabs rax, address-of-function
uint8_t reg = 0; //rax
uint8_t rexWPrefix = 0x48 + (reg > 8);
uint8_t opCode = 0xB8 + (reg % 8);
insertAll(code,std::list<uint8_t>{ rexWPrefix, opCode });
code.insert(code.end(),reinterpret_cast<uint8_t*>(&fabs),reinterpret_cast<uint8_t*>(&fabs) + 8);

//jmp rax
insertAll(code,std::list<uint8_t>{ 0xFF, 0xE0 });

К сожалению, вызов функций таким способом не работает, программа вылетает с SIGSEGV ошибка. Что-то не так с моим ассемблерным кодом или кодировкой инструкции? Какое значение должно <offset-to-return-to> есть, чтобы функция вернулась в правильное положение?

Отказ от ответственности: я знаю, что это не лучший способ обработки динамического генерирования кода … Я мог бы просто скомпилировать динамическую библиотеку и загрузить ее с dlsym, Это просто интересный способ узнать о кодах сборки / шеллкодах, и к нему не следует относиться слишком серьезно 🙂

0

Решение

Я нашел три ошибки. jmp инструкция не абсолютная, а афаик RIP-родственник. я использовал push + ret в качестве альтернативы, потому что ret переходит на абсолютный адрес, лежащий в стеке.

Кроме того, я не знал, что для вызывающей стороны обязательно резервировать теневое пространство 4 * 8 байт в стеке. Подробности можно найти Вот.

Наконец, код для вставки указателя функции в код инструкции был неверным. Я случайно вставил первые 8 байтов кода функции вместо значения указателя:

code.insert(code.end(),reinterpret_cast<uint8_t*>(&fabs),reinterpret_cast<uint8_t*>(&fabs) + 8);

Это готовый рабочий код:

//add rsp,0x20  --> shadow space of 4*8 bytes
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC4, 0x20 } );
//lea rax, [rip+0x0]
insertAll(code,std::list<uint8_t>{ 0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00 });
//add rax, 18
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xC0, 18 });
//push rax
code.push_back(0x50);

//moveabs rax, address-of-function
uint8_t reg = 0; //rax
uint8_t rexWPrefix = 0x48 + (reg > 8);
uint8_t opCode = 0xB8 + (reg % 8);
insertAll(code,std::list<uint8_t>{ rexWPrefix, opCode });
void* address = reinterpret_cast<void*>(&my_abs);
code.insert(code.end(),reinterpret_cast<uint8_t*>(&address),reinterpret_cast<uint8_t*>(&address) + sizeof(address));

//push rax
code.push_back(0x50);
//retq
code.push_back(0xC3);
//sub rsp,0x20  --> shadow space of 4*8 bytes
insertAll(code,std::list<uint8_t>{ 0x48, 0x83, 0xEC, 0x20 } );
1

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

Других решений пока нет …

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