LINUX.ORG.RU

История изменений

Исправление 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");
}