Я пытаюсь выяснить, как регистр% fs инициализируется при создании изображения эльфа вручную.
Простой фрагмент, который я хотел бы запустить:
.text
nop
movq %fs:0x28, %rax;
1: jmp 1b
Который должен читаться со смещением 0x28 в сегменте% fs.Обычно здесь хранится канарейка стека.Поскольку я вручную создаю образ эльфа, сегмент% fs вообще не настроен моим кодом, и это не получается (?).
Вот как я создаю образ эльфа:
0000000000000000 <.text>:
0: 90 nop
1: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
8: 00 00
a: eb fe jmp 0xa
Я создаю текстовый сегмент с помощью
echo 9064488b042528000000ebfe | xxd -r -p > r2.bin
Затем я преобразую в elf:
ld -b binary -r -o raw.elf r2.bin
objcopy --rename-section .data=.text --set-section-flags .data=alloc,code,load raw.elf
В этот момент raw.elf
содержит мои инструкции.Затем я связываюсь с ld -T raw.ld -o out.elf -M --verbose
, где raw.ld:
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_entry)
PHDRS {
phdr4000000 PT_LOAD;
}
SECTIONS
{
_entry = 0x4000000;
.text 0x4000000 : { raw.elf (.text) } :phdr4000000
}
Теперь я могу запустить .elf с помощью gdb:
gdb --args out.elf
и установить точку останова на 0x4000000:
(gdb)break *0x4000000
(gdb)run
Первый nop
может быть пройден через stepi
, однако канарейка стека читает mov %fs:0x28,%rax
segfaults.
Я полагаю, что это ожидается, учитывая, что, возможно, ОС не настраивается% фс.Для простой программы mc: int main() { return 0; }
, скомпилированной с gcc --static m.c -o m
, я могу прочитать из% fs.Добавление:
long can()
{
long v = 0;
__asm__("movq %%fs:0x28, %0;"
: "=r"(val)::);
return v;
}
позволяет мне читать из% fs - хотя я сомневаюсь, что% fs: 28 настроен, потому что ld.so не запущен (это статический образ).
Вопрос:
Кто-нибудь может указать, где% fs настроен во время выполнения c для статических изображений?