Между прочим, большинство людей создают шелл-код, собирая его с помощью обычного ассемблера, такого как NASM, и затем шифруя этот двоичный файл в строку C. Написание собственного ассемблера может быть забавным проектом, но в основном это отдельный проект.
Ваш encode_rex
выглядит несколько разумно, принимая четыре аргумента за четыре бита. Но код в mov
, который вызывает его, иногда проходит 2
, который усекается до 0
!
Кроме того, есть 4 возможности для 2 соответствующих битов расширения (b и x), которые вы ' используется для регулярных ходов. Но ваша цепочка if / else if / else охватывает только 3 из них, игнорируя возможность dest>=8 && src >= 8
=> x:b = 3
Поскольку эти два бита ортогональны, вы должны просто рассчитать их отдельно, как это:
put<uint8_t>(encode_rex(1, 0, dest>=8, src>=8));
Поле SIB-index x
всегда должно быть 0
, потому что у вас нет байта SIB, просто ModRM для reg-reg mov
.
Ваш инициализатор структуры в encode_rex
перепутан, с extend_modrm_reg
, вторым, где он инициализирует поле x
вместо r
. Ваши имена битовых полей совпадают https://wiki.osdev.org/X86-64_Instruction_Encoding#Encoding, но у вас неправильные переменные C ++, инициализирующие их. См. Эту ссылку для описания.
Возможно, у меня есть порядок dest, sr c в обратном порядке, в зависимости от того, используете ли вы код операции mov r/m, r
или mov r, r/m
. Я не проверял дважды, что именно.
Проверка работоспособности от NASM: я собрал с nasm -felf64 -l/dev/stdout
, чтобы получить список:
1 00000000 4889C8 mov rax, rcx
2 00000003 4889C0 mov rax, rax
3 00000006 4D89C0 mov r8, r8
4 00000009 4989C0 mov r8, rax
5 0000000C 4C89C0 mov rax, r8
Вы используете тот же 0x89
код операции, который использует NASM, поэтому ваши префиксы REX должны совпадать.
return *(uint8_t*)&result;
является UB со строгим псевдонимом и небезопасен вне MSV C.
Используйте memcpy для безопасного тип-каламбур. (Или объединение; большинство реальных компиляторов C ++, включая gcc / clang / MSV C, определяют поведение объединения типов объединения, как в C99, в отличие от ISO C ++).