LINUX.ORG.RU

как записать в elf из самого себя

 


0

1

в общем вопрос бесполезный, но стало интересно, есть ли возможность открыть для записи elf файл из процесса, который и есть процесс - созданный из этого elf файла.

без копирования, создания дополнительных процессов и файлов.

★★★
$ ./a.out 
open: Text file busy

сомневаюсь что можно

crowbar
()
Последнее исправление: crowbar (всего исправлений: 1)
Ответ на: комментарий от Ubuntu1210

It is unspecified whether modifications to the underlying object done after the MAP_PRIVATE mapping is established are visible through the MAP_PRIVATE mapping.

Очевидно вот поэтому (man mmap)

http://hashcode.ru/questions/119844/linux-почему-lsb-elf-shared-object-можно-...

crowbar
()
Последнее исправление: crowbar (всего исправлений: 1)
Ответ на: комментарий от Ubuntu1210

А кто сказал, что файл загружается? Большинство систем предполагают ленивый режим работы. Посему обычно не загружается, а отображается. И эстетам желающим писать вирусы это несколько мешает. Если бы писать было бы разрешено, то возникали бы доп. проблемы с безопасностью, см. как аналог pnacl - там, точно был (а может и есть) фифект в подобном стиле.

io ★★
()

В крайнем случае влезь в ядро и убей там блокировку.

anonymous
()
Ответ на: комментарий от Ubuntu1210

чтобы при сваппинге высвапить его таким образом

anonymous
()

НатюрлихЪ!

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(){
	char b[100];
	size_t r;
	int fd = open("a.out", O_RDONLY);
	if(fd < 1) return 1;
	printf("опынед саксесфулы!\n");
	while((r = read(fd, b, 99)) > 0){
		printf("readed %zd\n bytes\n", r);
	}
	close(fd);
	fd = open("a.out", O_RDONLY);
	if(fd < 1) return 2;
	lseek(fd, SEEK_END, 0);
	if(write(fd, b, 99) < 99) printf("хрен!\n");
	return 0;
}
...
 bytes
readed 99
 bytes
readed 68
 bytes
хрен!

Ща погуглю. Аж самому тырысно.

Eddy_Em ☆☆☆☆☆
()

В этом же как раз фатальное приемущество линакса над вендой.

Там лютые костыли, перезагрузки и прочий треш.

А в линаксе можно сделать apt-get update apt-get или pacman -S pacman

derlafff ★★★★★
()
Ответ на: комментарий от Eddy_Em

O_RDONLY
write

Действительно, почему «хрен»? Странно прямо!

invy ★★★★★
()
Ответ на: комментарий от crowbar
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(){
    char b[100], *ptr;
    size_t r;
    int fd = open("a.out", O_RDONLY);
    if(fd < 1) return 1;
    printf("опынед саксесфулы!\n");
    while((r = read(fd, b, 99)) > 0){
        printf("readed %zd\n bytes\n", r);
    }
    close(fd);
    fd = open("a.out", O_RDWR); // пыщстрока
    if(fd < 1) return 2;
    lseek(fd, SEEK_END, 0);
    ptr = "пыщщ!";
    if(write(fd, b, 8) < 8) printf("хрен!\n");
    return 0;
}

the same shit!

Падает. на строке "пыщстрока"

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Ты бы хоть perror'ом ошибку вывел.

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>

int main()
{
    int f = open("a.out", O_WRONLY);
    if (f == -1) {
        perror("open");
        return 1;
    }
    close(f);
    return 0;
}
crowbar
()
Ответ на: комментарий от Eddy_Em

Ничего не понятно. А что если линукс всё-же позволяет писать в загруженные ELF? То что у тебя из неверного кода получился верный вывод — чисто случайность.

crowbar
()
Ответ на: комментарий от derlafff

нет, только если вы скопировали оригинал elf куда-нибудь в /tmp и сделали exec, после этого можно сколько угодно писать в исходный elf.

IvanR ★★★
() автор топика
Ответ на: комментарий от derlafff

Никто не может.

То о чем ты раньше писал про файловые менеджеры, это не то. Они удаляют файлы и создают новые. Так в линуксе можно.

crowbar
()
Ответ на: комментарий от crowbar

а можно еще вопрос, почему тут получается сегфолт:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

char test[] = "hello world";

int main(void)
{
	void *p = test;
	unsigned long pgsize = sysconf(_SC_PAGESIZE);
	void *data = ((void *)(unsigned long)p - ((unsigned long)p % pgsize));
	printf("p = %p, len = %lu, .data segaddr = %p\n", p, pgsize, data);
	printf("%s\n", test);
	if (mprotect(data, pgsize, PROT_NONE) != 0) {
		perror("mprotect");
		exit(1);
	}
	if (mprotect(data, pgsize, PROT_READ|PROT_WRITE) != 0) {
		perror("mprotect");
		exit(1);
	}
	printf("%s\n", test);
	return 0;
}

причем на строке if (mprotect(data, pgsize, PROT_READ|PROT_WRITE) != 0) {

IvanR ★★★
() автор топика
Ответ на: комментарий от crowbar

Они удаляют файлы и создают новые. Так в линуксе можно.

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

derlafff ★★★★★
()
Ответ на: комментарий от IvanR

пишешь обработчик SIGTERM, который находит fd эльфа и возвращает его на место

с SIGKILL уже ничего не поделать, да

ну и делать это быстро

а еще лучше не делать

derlafff ★★★★★
()
Последнее исправление: derlafff (всего исправлений: 1)
Ответ на: комментарий от GPFault

И как потом продолжить выполнение? Не выйдет.

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от hateyoufeel

Написано же.

We also differentiate updates of 'OS components' (which we want to do in this offline fashion) from application updates

<...> in order to avoid problems related to conflicts of libraries and services that are currently running with those on disk.

Replacing libraries and files while the OS is running can cause problems ranging from application crashes to inconsistent system states where processes are using different versions of a library at the same time.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от pashazz

Скажи ещё спасибо, что не «prochitano» или «п©я─п╬я┤п╦я┌п╟п╫п╬».

mix_mix ★★★★★
()
Ответ на: комментарий от IvanR

Она падает на первом вызове любой функции после ″mprotect(data, pgsize, PROT_NONE)″, потому что в одной странице со строковой константой ″hello world″ оказалась ″dynamic relocation table″.

mky ★★★★★
()
Ответ на: комментарий от IvanR

А если у нас хитрая ФС, которая создает 2 файла, но внутри ФС они заведены на один и тот же буфер, тогда можно будет изменить содержимое.

cvs-255 ★★★★★
()
Последнее исправление: cvs-255 (всего исправлений: 1)

Как можно. Это же устои мирозданья.

iZEN ★★★★★
()

Нет, нельзя. И ошибка ETXTBSY (man open) специально для этого, и она posix, так что не только в Linux нельзя, но и много где ещё

mky ★★★★★
()

Как уже объяснили,

mv $0 ${0}.tmp && cp ${0}.tmp $0 && rm ${0}.tmp && редачим

Krieger_Od ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.