我在基本c中编写lite程序,为参数中传递的二进制文件中的每个字节添加(或子)偏移量。这项工作适用于所有其他ELF,但是当我试图运行时:
$ ./a.out a.out 1
(每个字节加0x01),
fopen()
崩溃并显示错误消息“文本文件繁忙”
我使用lsof
进行了检查,但未在文件系统上打开
我认为当一个可执行文件正在运行时,文件的图像被加载到RAM中并且文件是可访问的
如果有人知道那件事,我会接受它!
感谢您抽出宝贵时间阅读我!
以下是代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void usage (char *pgr_name); // print usage and exit
void fatal(char *s); // print s, call perror("") and exit(-1)
// lite hexdump ([0xff] x16 | ...a...b...c...d )
void dump (const unsigned char *data_buffer, const unsigned int len);
int main(int argc, char **argv) {
FILE *my, *crypted;
void *content;
unsigned char *ascii;
char output[256] = "";
int i, bytes_read, offset;
if (argc < 3)
usage(argv[0]);
offset = atoi(argv[2]);
if (offset < -255 || offset > 0xff) {
printf("bad offset\n");
usage(argv[0]);
}
printf("offset %d\n", offset);
// open src
if ((my = fopen(argv[1], "rb+")) == NULL)
fatal("in opening argv[1]");
// alloc memory for src
if ((content = malloc (10000)) == NULL)
fatal("in malloc");
// read src
bytes_read = fread(content, 1, 9999, my);
printf("%d bytes read\n", bytes_read);
// for reading easily
ascii = (unsigned char *) content;
dump(content, bytes_read);
// apply offset on each bytes
for (i=0; i<bytes_read; i++)
ascii[i] = ascii[i] + offset;
printf("\n\ntranslation complete\n\n");
dump(content, bytes_read);
strncpy(output, argv[1], 250);
strcat(output, ".cry");
// open dest
if ((crypted = fopen(output, "wb+")) == NULL)
fatal("in open crypted");
// write src translated in dest
bytes_read = fwrite(content, 1, bytes_read, crypted);
printf("%d bytes written\n", bytes_read);
// terminate pgrm
fclose(crypted);
fclose(my);
free(content);
return 0;
}
void fatal(char *s) {
if (s) {
fprintf(stderr, "[!] Fatal [!] : %s\n", s);
}
perror("");
exit(-1);
}
void usage (char *pgr_name) {
printf("Usage : %s <binary input> <offset [-255:255]>\n\n", pgr_name);
exit(0);
}
void dump (const unsigned char *data_buffer, const unsigned int len) {
unsigned char byte;
unsigned int i, j;
for (i=0; i<len; i++) {
byte = data_buffer[i];
printf("%02x ", data_buffer[i]);
if (((i%16) == 15 ) || (i==len-1)) {
for (j=0; j < 15-(i%16); j++)
printf(" ");
printf("| ");
for (j=(i-(i%16)); j<=i; j++) {
byte = data_buffer[j];
if (byte > 31 && byte < 127)
printf("%c", byte);
else
printf(".");
}
printf("\n");
}
}
}
答案 0 :(得分:2)
Unix文件系统 - 在Unix,BSD,macOS,Linux等中使用的 - 依赖于inodes。多个文件名可以引用相同的inode。
如果删除了文件名,但inode仍在一个或多个进程中打开,则inode没有引用它的文件名。您仍然可以正常使用打开的文件 - 例如扩展它 - 但是没有其他进程可以打开它(除非您以某种方式为它们提供打开的文件描述符)。
执行ELF二进制文件时,内核会锁定底层的inode。注意:它是锁定的inode,而不是文件名。
这是因为而不是&#34; loading&#34;将数据存入内存,大多数系统只是对数据进行内存映射。例如,在Linux中,这意味着无论您运行的可执行文件或动态库有多少副本,RAM中只存在一个二进制文件副本。
实际上,这意味着您无法在执行ELF二进制文件时修改它。但是,您可以重命名甚至删除该文件,因为它是文件名引用的inode,而不是内核锁定的文件名。 (当然,你可以读取ELF二进制文件就好了,即使它们正被执行;你只需要确保以只读方式打开它们,因为打开它们读写会失败。这是因为大多数Unix文件系统只检查访问权限在开放时间。)
你可以做的是创建一个新文件;写修改后的数据;可选地复制所有者,组,模式,上次访问和上次修改时间戳,和/或扩展属性(xattrs);最后在旧文件名上重命名或硬链接新文件名。 (重命名或硬链接现有文件只会更改现有文件名引用的inode,因此不会违反inode锁定。)
这具有替换(旧二进制)原子的额外好处。无论其他进程何时打开或执行旧二进制文件,它们始终只能看到旧的inode或新的inode,而不是某种中间版本。
答案 1 :(得分:0)
您无法在写入模式下实际打开C中任何程序正在使用的文件。即使您打开文件,在您在该文件上调用fflush()
或fclose()
之前,您在程序中对文件所做的更改也不会显示。