GOOGLE ADS

воскресенье, 1 мая 2022 г.

ошибка перемещения при реализации моего собственного загрузчика эльфов

В настоящее время я внедряю загрузчик эльфов для эмуляции двоичных файлов с помощью движка единорога. Чтобы избежать реализации моего собственного динамического компоновщика, я загружаю ld-linux-x86-64.so.2 (в движок единорога) и запускаю его с путем к моему динамическому компоновщику. Теперь вот моя проблема:

Я загружаю двоичный файл динамического компоновщика (/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) в память и запускаю его с путем к моему исполняемому файлу (в основном printf("Hello World")). После того, как загрузчик загружает исполняемый файл и libc, в стандартный вывод выводится следующее:

./executable:./executable: no version information available (required by./executable)
./executable: relocation error:./executable: symbol __libc_start_main, version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference

Я скопировал бинарники (ld и libc) из системы, скомпилировал программу hello_world. Это работает, когда я запускаю двоичный файл:

$ /lib/x86_64-linux-gnu/ld-2.21.so./executable
Hello World

Любая идея, почему это не должно работать? Любая идея, где я должен искать свою ошибку? (Обратите внимание, что я использую свой собственный загрузчик)
Вот «strace» загрузчика, работающего в unicorn-engine, который, надеюсь, выполняется правильно (мне нужно смоделировать ядро).

sys_brk(0x0)
sys_open(./executable)
sys_read(3, 0x7fff6c844868, 832)
sys_fstat(3, 0x7fff6c844718)
sys_getcwd(0x8888888800225738, 128)
sys_mmap2(0x400000, 4096, 5, 2066, 3, 0)
sys_mmap2(0x600000, 8192, 3, 2066, 3, 0)
sys_close(3)
sys_uname(0x7fff6c844a22)
sys_access(/etc/ld.so.nohwcap, 0)
sys_mmap2(0x0, 8192, 3, 34, -1, 0)
sys_access(/etc/ld.so.preload, 4)
sys_open(/etc/ld.so.cache)
sys_open(/lib/x86_64-linux-gnu/tls/x86_64/libc.so.6)
sys_stat(/lib/x86_64-linux-gnu/tls/x86_64, 140735013995640)
sys_open(/lib/x86_64-linux-gnu/tls/libc.so.6)
sys_stat(/lib/x86_64-linux-gnu/tls, 140735013995640)
sys_open(/lib/x86_64-linux-gnu/x86_64/libc.so.6)
sys_stat(/lib/x86_64-linux-gnu/x86_64, 140735013995640)
sys_open(/lib/x86_64-linux-gnu/libc.so.6)
sys_read(4, 0x7fff6c8445c8, 832)
sys_fstat(4, 0x7fff6c844478)
sys_close(4)
sys_writev(2, 7fff6c844538, 6)
=>./executable:./executable: no version information available (required by./executable)
sys_mmap2(0x0, 4096, 3, 34, -1, 0)
sys_arch_prctl(4098, 0x6555555500001fc0)
sys_mprotect(0x600000, 4096, 1)
sys_writev(2, 7fff6c844220, 10)
=>./executable: relocation error:./executable: symbol __libc_start_main, version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
sys_exit(127)

И strace на машине скомпилировал бинарники:

$ strace /lib/x86_64-linux-gnu/ld-2.21.so./dynamic_x86_64_print_args 
execve("/lib/x86_64-linux-gnu/ld-2.21.so", ["/lib/x86_64-linux-gnu/ld-2.21.so", "./dynamic_x86_64_print_args"], [/* 23 vars */]) = 0
brk(0) = 0x5636dd9f3000
open("./dynamic_x86_64_print_args", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0@\4@\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=8528,...}) = 0
getcwd("/vagrant/tdb/static", 128) = 20
mmap(0x400000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x400000
mmap(0x600000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x600000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc3a45e1000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
//...
// SNIP 100 tries to load the libc.so.6 that is not there
//...
open("/home/vagrant/villoc/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/home/vagrant/villoc", {st_mode=S_IFDIR|0775, st_size=4096,...}) = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=55962,...}) = 0
mmap(NULL, 55962, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fc3a45d3000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\v\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1869392,...}) = 0
mmap(NULL, 3972864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fc3a4209000
mprotect(0x7fc3a43c9000, 2097152, PROT_NONE) = 0
mmap(0x7fc3a45c9000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7fc3a45c9000
mmap(0x7fc3a45cf000, 16128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fc3a45cf000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc3a4208000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc3a4207000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc3a4206000
arch_prctl(ARCH_SET_FS, 0x7fc3a4207700) = 0
mprotect(0x7fc3a45c9000, 16384, PROT_READ) = 0
mprotect(0x600000, 4096, PROT_READ) = 0
mprotect(0x5636dba3b000, 4096, PROT_READ) = 0
munmap(0x7fc3a45d3000, 55962) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0),...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fc3a45e0000
write(1, "arg 0./dynamic_x86_64_print_arg"..., 34arg 0./dynamic_x86_64_print_args
) = 34
exit_group(0) =?
+++ exited with 0 +++


Решение проблемы

Глядя на ваши системные вызовы...

sys_mmap2(0x400000, 4096, 5, 2066, 3, 0)
sys_mmap2(0x600000, 8192, 3, 2066, 3, 0)

Похоже, у вас MAP_FIXEDустановлен бит.

MAP_FIXEDявляется опасным инструментом - он с радостью перезапишет все, что находится по этому адресу. Скорее всего, ваш загрузчик использует эти адреса. Я знаю, что /lib64/ld-linux-x86-64.so.2использует, MAP_FIXEDно...

> readelf --segments /lib64/ld-linux-x86-64.so.2
Elf file type is DYN (Shared object file)
Entry point 0x1140
There are 7 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000021960 0x0000000000021960 R E 200000
LOAD 0x0000000000021b40 0x0000000000221b40 0x0000000000221b40
0x0000000000001438 0x0000000000001610 RW 200000
DYNAMIC 0x0000000000021e00 0x0000000000221e00 0x0000000000221e00
0x0000000000000190 0x0000000000000190 RW 8
NOTE 0x00000000000001c8 0x00000000000001c8 0x00000000000001c8
0x0000000000000024 0x0000000000000024 R 4
GNU_EH_FRAME 0x000000000001eda4 0x000000000001eda4 0x000000000001eda4
0x0000000000000674 0x0000000000000674 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000021b40 0x0000000000221b40 0x0000000000221b40
0x00000000000004c0 0x00000000000004c0 R 1
Section to Segment mapping:
Segment Sections...
00.note.gnu.build-id.hash.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_d.rela.dyn.rela.plt.plt.text.rodata.stapsdt.base.eh_frame_hdr.eh_frame
01.data.rel.ro.dynamic.got.data.bss
02.dynamic
03.note.gnu.build-id
04.eh_frame_hdr
05
06.data.rel.ro.dynamic.got

... похоже, он не использует адреса, MAP_FIXEDдля которых он используется. Это умный зверь.

> strace /lib64/ld-linux-x86-64.so.2 `which readelf` |& grep mmap
mmap(0x400000, 503808, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x400000
mmap(0x67a000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7a000) = 0x67a000
mmap(0x67d000, 10248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x67d000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0af3a38000
mmap(NULL, 313165, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0af39eb000
mmap(NULL, 2109744, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0af3614000
mmap(0x7f0af3816000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f0af3816000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0af39ea000
mmap(NULL, 3985920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0af3246000
mmap(0x7f0af3609000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c3000) = 0x7f0af3609000
mmap(0x7f0af360f000, 16896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0af360f000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0af39e8000
mmap(NULL, 106172832, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0aecd04000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0af3a37000

Если я использую MAP_FIXEDBad Way™ в своей собственной системе, я получаю похожее сообщение:

./myloader: symbol lookup error:./myloader: undefined symbol: 

Но учитывая, что мы просто разбиваем память здесь, может случиться что угодно.

Комментариев нет:

Отправить комментарий

Laravel Datatable addColumn returns ID of one record only

Я пытаюсь использовать Yajra Datatable для интеграции DataTable на свой веб-сайт. Я смог отобразить таблицу, но столкнулся с проблемой. В по...