Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Linux C程序中写入自己的可执行文件,错误“;“文本文件忙”;_C_Security_Permissions_Binary_Self Modifying - Fatal编程技术网

在Linux C程序中写入自己的可执行文件,错误“;“文本文件忙”;

在Linux C程序中写入自己的可执行文件,错误“;“文本文件忙”;,c,security,permissions,binary,self-modifying,C,Security,Permissions,Binary,Self Modifying,对于一个安全类,我应该为一个程序编写自修改代码,该程序在磁盘上找到自己的可执行文件,读取二进制数据,并对其中的一部分进行加密,然后再将其写回磁盘。这被认为是一种多态病毒,它会改变自身,愚弄检测已知特征的防病毒扫描程序 我把所有的东西都准备好了: 我正在使用/proc/self/exe查找可执行文件 我使用一个简单的AES实现在可执行文件中的一些伪代码中加密16字节字符串 我能够读取中的二进制数据并找到需要加密的部分 我的问题是,我能够打开可执行文件的唯一方式是在只读模式下“rb”。如果我试图

对于一个安全类,我应该为一个程序编写自修改代码,该程序在磁盘上找到自己的可执行文件,读取二进制数据,并对其中的一部分进行加密,然后再将其写回磁盘。这被认为是一种多态病毒,它会改变自身,愚弄检测已知特征的防病毒扫描程序

我把所有的东西都准备好了:

  • 我正在使用
    /proc/self/exe
    查找可执行文件
  • 我使用一个简单的AES实现在可执行文件中的一些伪代码中加密16字节字符串
  • 我能够读取中的二进制数据并找到需要加密的部分
我的问题是,我能够打开可执行文件的唯一方式是在只读模式下
“rb”
。如果我试图以模式
“wb”
“r+b”
打开文件进行写入,我会返回错误
“文本文件忙”
。我是否可以用C编写进程自己的可执行文件?我可以通过某种方式更改权限来做到这一点吗

编辑:我试图实现的是一个可执行文件,它将在每次运行时对自身的一部分进行加密,以便在每次运行后都有一个新的校验和


从可执行二进制文件中读取数据后,如何将其写回或删除并替换为具有相同文件名的新文件?

无法写入当前映射为可执行文件的文件。但是,您可以写入与当前可执行文件路径相同的文件,只要它实际上不是同一个文件-例如,尝试取消正在执行的文件的链接并在其位置创建一个新文件。

为了进行自我修改,我在nasm中编写了一个小代码(可以用作存根),在代码中间(下一个mmap),我们有一个指针,指向我们可以修改的可执行文件的字节

代码如下所示:

BITS 64

section .text
    global _start

_start:
    call _main__

    mov rax, 60
    mov rdi, 0x0
    syscall ; exit(0);

_main__:
    push rbp
    mov rbp, rsp
    sub rsp, 144 ; stat_file
    mov rdi, [rbp+0x18]
    lea rsi, [rsp]
    call _open_self ; open self
    push r12 ; len file
    push rax ; addr
    mov r14, rsi



    mov rdi, [rbp+0x18] ; pathname
    pop rsi ; addr
    pop rdx ; len
    push rdx
    push rsi
    call __create
    mov r13, rax ; second fd

    mov rdi, r14 ; fd
    pop rsi ; addr -> mmap
    pop rdx ; len_file
    call __close_unmap

    mov rax, 87
    mov rdi, [rbp+0x18]
    syscall

    mov rax, 0x3 ; close(scnd_fd);
    mov rdi, r13
    syscall

    mov rax, 86
    push 'nasm'
    lea rdi, [rsp]
    mov rsi, [rbp+0x18]
    syscall ; link tmp name to original name

    mov rax, 87
    lea rdi, [rsp]
    syscall ; delete old tmp file

    leave
    ret


; ===============================

; Open himself
_open_self:
    push rbp
    mov rbp, rsp

    mov r15, rsi ; &stat_file
    mov r12, rdi ; *pathname

    mov rax, 0x2
    mov rsi, 0x0 ; 0_RD
    mov rdx, 509
    syscall

    push rax ; fd

    mov rdi, rax ; fd
    mov rsi, r15 ; struct stat
    mov rax, 5 ; fstat
    syscall

    xor rdi, rdi
    mov rsi, qword [r15+48]
    mov rdx, 0x4
    mov r10, 0x2
    pop r8
    push r8
    mov r9, 0x0
    mov rax, 9
    syscall ; mmap

    ; rax -> byte of the executable that we gonna dump

    mov r12, qword [r15+48]

    pop rsi ; fd
    leave
    ret

; ===============================

; int __create(const char *pathname, void *addr, ssize_t len_bytes_mapped);

__create:
    push rbp
    mov rbp, rsp
    push rsi ; addr
    push rcx ; len

    push 'nasm'
    lea rdi, [rsp]
    mov rax, 0x2
    mov rsi, 0x42 ; 0_CREAT | O_RDWR
    mov rdx, 509
    syscall ; sys_open

    add rsp, 0x8 ; 'nasm'
    mov r9, rax ; fd
    mov rdi, rax ; fd

    mov rax, 0x1
    pop rdx
    pop rsi
    syscall ; sys_write

    mov rax, r9 ; fd final

    leave
    ret

; int __close_unmap(int fd, unsigned lon addr, ssize_t len_file);

__close_unmap:
    push rbp
    mov rbp, rsp

    push rdi

    mov rdi, rsi
    mov rsi, rdx
    mov rax, 11
    syscall ; munmap(addr, len_file)

    pop rdi
    mov rax, 3
    syscall ; close(fd);

    leave
    ret
它有点长,但它只是:

-在读取模式下自行打开(O_RD==0x0)

-执行统计(*路径名和缓冲区结构统计)

-然后是一个mmap(0,buffer_struct_stat.st_size,0x4,MAP_PRIVATE,fd_read_only,0)

-在这里,您可以通过编辑mmap返回的地址处的字节来编辑可执行文件

-创建名为“nasm”的tmp文件

-进行写操作(fd\u tmp、mmap地址、缓冲区结构、统计数据大小)

-关闭两个文件描述符,并映射mmap


-现在很酷:取消链接(路径名)并链接(“nasm”,“路径名”)

尝试自己复制(在只读模式下),执行副本,然后从副本中删除原件。您能详细说明一下吗?同一路径是指在与当前可执行文件相同的目录中创建的新文件,但文件名不同吗?取消链接是指使用此函数吗?是的,您可以
unlink()
或移动(
link()
),然后
unlink()
)可执行文件。谢谢,我可以使用
unlink
函数完成我需要的操作。我首先在模式
“rb”
中打开可执行二进制文件,读取数据,关闭文件,取消文件链接,在模式
“wb”
中打开一个新文件以在同一路径写入,写入修改后的二进制数据,关闭文件,然后使用
chmod
将新文件标记为可执行文件。