История изменений
Исправление
pavlick,
(текущая версия)
:
Собрал .so без единой зависимости (от других .so). Т.е. все необходимый либы подключаем при линковки исполняемого файла, этими либами будут разрешаться все зависимости (в том числе и libc.so).
Пример:
pavlick-fm /tmp/1 $ cat lib.c
#include <stdio.h>
void fn() { printf("hello world\n"); }
pavlick-fm /tmp/1 $ cat exe.c
void fn();
int main() {fn();}
pavlick-fm /tmp/1 $ gcc -fPIC -shared lib.c -o libmy.so
pavlick-fm /tmp/1 $ gcc exe.c ./libmy.so -o exe
pavlick /tmp/1 $ ./edit_elf libmy.so
ELF has been successfully fixed
pavlick-fm /tmp/1 $ readelf -d libmy.so
# было
Динамический раздел со смещением 0x2e20 содержит 24 элемента:
Тег Тип Имя/Знач
0x0000000000000001 (NEEDED) Совм. исп. библиотека: [libc.so.6]
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x111c
# стало
Динамический раздел со смещением 0x2e20 содержит 23 элемента:
Тег Тип Имя/Знач
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x111c
...
Утилиту edit_elf написал сам, её задача - найти .dynamic секцию, добраться до первой записи «NEEDED», и затереть её сдвигом остальными записями секции. Т.е. либа ничего не требует, подставляю только нужные -l при во время линковки исполняемого файла.
pavlick /tmp/2 $ cat edit_elf.c
#include <elf.h>
#include <stdio.h>
#define ERROR \
do { \
printf("error, exit\n");\
return 1; \
} while (0);
int main(int argc, const char *argv[])
{
if (argc < 2)
ERROR;
FILE *file = fopen(argv[1], "r+b");
if (file == NULL)
ERROR;
Elf64_Ehdr elf_header;
if (fread(&elf_header, sizeof(elf_header), 1, file) != 1 ||
fseek(file, elf_header.e_shoff, SEEK_SET) != 0)
ERROR;
if (elf_header.e_shoff == 0) {
printf("ELF has no section table, exit");
return 0;
}
Elf64_Shdr sec_header;
for (int i = 0; i < elf_header.e_shnum; ++ i) {
if (fread(&sec_header, sizeof(sec_header), 1, file) != 1)
ERROR;
if (sec_header.sh_type == SHT_DYNAMIC)
break;
}
if (sec_header.sh_type != SHT_DYNAMIC) {
printf("ELF has no dynamic section, exit");
return 0;
}
if (fseek(file, sec_header.sh_offset, SEEK_SET) != 0)
ERROR;
Elf64_Dyn dyn_entry;
while (1) {
if (fread(&dyn_entry, sizeof(dyn_entry), 1, file) != 1)
ERROR;
if (dyn_entry.d_tag == DT_NULL) {
printf("ELF has no NEEDED libraries, exit");
return 0;
}
if (dyn_entry.d_tag == DT_NEEDED)
break;
}
while (1) {
if (fread(&dyn_entry, sizeof(dyn_entry), 1, file) != 1 ||
fseek(file, ftell(file)-sizeof(dyn_entry)*2, SEEK_SET) != 0 ||
fwrite(&dyn_entry, sizeof(dyn_entry), 1, file) != 1 ||
fseek(file, ftell(file)+sizeof(dyn_entry), SEEK_SET) != 0)
ERROR;
if (dyn_entry.d_tag == DT_NULL)
break;
}
printf("ELF has been successfully fixed\n");
}
Исправление
pavlick,
:
Собрал .so без единой зависимости (от других .so). Т.е. все необходимый либы подключаем при линковки исполняемого файла, этими либами будут разрешаться все зависимости (в том числе и libc.so).
Пример:
pavlick-fm /tmp/1 $ cat lib.c
#include <stdio.h>
void fn() { printf("hello world\n"); }
pavlick-fm /tmp/1 $ cat exe.c
void fn();
int main() {fn();}
pavlick-fm /tmp/1 $ gcc -fPIC -shared lib.c -o libmy.so
pavlick-fm /tmp/1 $ gcc exe.c ./libmy.so -o exe
pavlick /tmp/1 $ ./edit_elf libmy.so
ELF has been successfully fixed
pavlick-fm /tmp/1 $ readelf -d libmy.so
# было
Динамический раздел со смещением 0x2e20 содержит 24 элемента:
Тег Тип Имя/Знач
0x0000000000000001 (NEEDED) Совм. исп. библиотека: [libc.so.6]
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x111c
# стало
Динамический раздел со смещением 0x2e20 содержит 23 элемента:
Тег Тип Имя/Знач
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x111c
...
Утилиту edit_elf написал сам, её задача - найти .dynamic секцию, добраться до первой записи «NEEDED», и затереть её сдвигом остальными записями секции. Т.е. либа ничего не требует, подставляю только нужные -l при во время линковки исполняемого файла.
pavlick /tmp/2 $ cat edit_elf.c
#include <elf.h>
#include <stdio.h>
#define ERROR \
do { \
printf("error, exit\n");\
return 1; \
} while (0);
int main(int argc, const char *argv[])
{
if (argc < 2)
ERROR;
FILE *file = fopen(argv[1], "r+b");
if (file == NULL)
ERROR;
Elf64_Ehdr elf_header;
if (fread(&elf_header, sizeof(elf_header), 1, file) != 1 ||
fseek(file, elf_header.e_shoff, SEEK_SET) != 0)
ERROR;
if (elf_header.e_shoff == 0) {
printf("ELF has no section table, exit");
return 0;
}
Elf64_Shdr sec_header;
for (int i = 0; i < elf_header.e_shnum; ++ i) {
if (fread(&sec_header, sizeof(sec_header), 1, file) != 1)
ERROR;
if (sec_header.sh_type == SHT_DYNAMIC)
break;
}
if (sec_header.sh_type != SHT_DYNAMIC) {
printf("ELF has no dynamic section, exit");
return 0;
}
if (fseek(file, sec_header.sh_offset, SEEK_SET) != 0)
ERROR;
Elf64_Dyn dyn_entry;
while (1) {
if (fread(&dyn_entry, sizeof(dyn_entry), 1, file) != 1)
ERROR;
if (dyn_entry.d_tag == DT_NULL)
printf("ELF has no NEEDED libraries, exit");
if (dyn_entry.d_tag == DT_NEEDED)
break;
}
while (1) {
if (fread(&dyn_entry, sizeof(dyn_entry), 1, file) != 1 ||
fseek(file, ftell(file)-sizeof(dyn_entry)*2, SEEK_SET) != 0 ||
fwrite(&dyn_entry, sizeof(dyn_entry), 1, file) != 1 ||
fseek(file, ftell(file)+sizeof(dyn_entry), SEEK_SET) != 0)
ERROR;
if (dyn_entry.d_tag == DT_NULL)
break;
}
printf("ELF has been successfully fixed\n");
}
Исходная версия
pavlick,
:
Собрал .so без единой зависимости (от других .so). Т.е. все необходимый либы подключаем при линковки исполняемого файла, этими либами будут разрешаться все зависимости (в том числе и libc.so).
Пример:
pavlick-fm /tmp/1 $ cat lib.c
#include <stdio.h>
void fn() { printf("hello world\n"); }
pavlick-fm /tmp/1 $ cat exe.c
void fn();
int main() {fn();}
pavlick-fm /tmp/1 $ gcc -fPIC -shared lib.c -o libmy.so
gcc exe.c ./libmy.so -o exe
pavlick /tmp/1 $ ./edit_elf libmy.so
ELF has been successfully fixed
pavlick-fm /tmp/1 $ readelf -d libmy.so
# было
Динамический раздел со смещением 0x2e20 содержит 24 элемента:
Тег Тип Имя/Знач
0x0000000000000001 (NEEDED) Совм. исп. библиотека: [libc.so.6]
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x111c
# стало
Динамический раздел со смещением 0x2e20 содержит 23 элемента:
Тег Тип Имя/Знач
0x000000000000000c (INIT) 0x1000
0x000000000000000d (FINI) 0x111c
...
Утилиту edit_elf написал сам, её задача - найти .dynamic секцию, добраться до первой записи «NEEDED», и затереть её сдвигом остальными записями секции. Т.е. либа ничего не требует, подставляю только нужные -l при во время линковки исполняемого файла.
pavlick /tmp/2 $ cat edit_elf.c
#include <elf.h>
#include <stdio.h>
#define ERROR \
do { \
printf("error, exit\n");\
return 1; \
} while (0);
int main(int argc, const char *argv[])
{
if (argc < 2)
ERROR;
FILE *file = fopen(argv[1], "r+b");
if (file == NULL)
ERROR;
Elf64_Ehdr elf_header;
if (fread(&elf_header, sizeof(elf_header), 1, file) != 1 ||
fseek(file, elf_header.e_shoff, SEEK_SET) != 0)
ERROR;
if (elf_header.e_shoff == 0) {
printf("ELF has no section table, exit");
return 0;
}
Elf64_Shdr sec_header;
for (int i = 0; i < elf_header.e_shnum; ++ i) {
if (fread(&sec_header, sizeof(sec_header), 1, file) != 1)
ERROR;
if (sec_header.sh_type == SHT_DYNAMIC)
break;
}
if (sec_header.sh_type != SHT_DYNAMIC) {
printf("ELF has no dynamic section, exit");
return 0;
}
if (fseek(file, sec_header.sh_offset, SEEK_SET) != 0)
ERROR;
Elf64_Dyn dyn_entry;
while (1) {
if (fread(&dyn_entry, sizeof(dyn_entry), 1, file) != 1)
ERROR;
if (dyn_entry.d_tag == DT_NULL)
printf("ELF has no NEEDED libraries, exit");
if (dyn_entry.d_tag == DT_NEEDED)
break;
}
while (1) {
if (fread(&dyn_entry, sizeof(dyn_entry), 1, file) != 1 ||
fseek(file, ftell(file)-sizeof(dyn_entry)*2, SEEK_SET) != 0 ||
fwrite(&dyn_entry, sizeof(dyn_entry), 1, file) != 1 ||
fseek(file, ftell(file)+sizeof(dyn_entry), SEEK_SET) != 0)
ERROR;
if (dyn_entry.d_tag == DT_NULL)
break;
}
printf("ELF has been successfully fixed\n");
}