删除 Linux 程序集 x86 中的一个文件

Delete a file in Linux assembly x86

我正在尝试为 Linux 汇编 x86 编写汇编程序,从目录中删除文件。有什么建议吗?

可能是这样的:

    .section .data
    fpath:
        .asciz "/home/user/filename"  # path to file to delete

    .section .text
    .globl _start
    _start:
    movl , %eax       # unlink syscall 
    movl $fpath, %ebx    # path to file to delete
    int  [=10=]x80 

    movl %eax, %ebx      # put syscall ret value in ebx
    movl , %eax        # exit syscall
    int  [=10=]x80

然后在命令行检查return值,0为成功。

    $>echo $?

我试过这段代码,如果从同一个文件调用,它不会取消link一个文件 目录作为要删除的文件,它会从其他目录中删除 link 个文件。 这是 32 位代码,所以在 64 位 os 上,如果您的源文件不是 link.s, 您需要使用以下命令创建可执行文件:

    $> as --32 -gdwarf2 un-link.s -o un-link.o

如果不需要 运行 使用 gdb 调试器,请忽略 -gdwarf2, 然后 link 与:

    $> ld -m elf_i386 un-link.o -o un-link

希望对你有用

如果要编写从目录中删除文件的汇编代码,可以使用多种方法,但最好的方法之一是使用 linux 系统调用 'unlink'。为了必须使用正确的系统调用,您必须弄清楚您拥有的是 x86 系统、x86-64 系统还是任何其他类型的系统。我将仅使用 x86/x86-64 指定如何执行此操作。

因此系统调用在 linux 中的工作方式如下:
1.
您将一个数字放入 return 寄存器(eax 或 rax 取决于系统)对应于系统调用的号码,例如 </code> 在 x86 上是 sys_exit 而 <code> 是 sys_pause,你必须确保在 %eax 中得到正确的数字,否则它不会工作。 (我觉得有必要强调这一点,这个数字是系统相关的,所以 %eax 中的 x86 系统调用号在 x86-64 系统中不会做同样的事情)。另外,OS的也可能会篡改这个,我只说linux,其他的OS我不说了。

2.
然后将参数移动到系统指定的正确寄存器中,再次为您的特定系统找到一个引用,您将知道将函数参数放入哪些寄存器(某些系统调用不需要参数,所以这一步是不必要的,为什么你需要一个参数 sys_exit, idk).

3.
最后,您使用系统调用让系统知道 运行 一个特定的函数(您通过将数字放入 %eax/%rax 中指定的函数)。

让我们看一个在 x86 和 x86-64 两种不同系统中删除文件的一些汇编代码示例(windows 有它自己的方法,但我不会说那个,虽然它确实存在)。如果我想 delete/unlink 存储在地址 0x7fff50 的文件(假设你不想指定 fpath 并且你知道地址)

在 x86 中:

movl , %eax        # defines which systemcall we are using (10th)
movl [=10=]x7fff50, %ebx  # moves the address of file we want to delete into %ebx (this is where the argument of sys_unlink(x86) is stored)
int  [=10=]x80            # equivalent of syscall that starts the appropriate function

在 x86-64 中:

movq , %rax        # defines which systemcall we are using (87th)
movq [=11=]x7fff50, %rdi  # moves the address of file we want to delete into %rdi (this is where the argument of sys_unlink(x86-64) is stored)
syscall               # starts the appropriate function


如果您更像是一个普通人并且不知道您要删除的文件的绝对地址,我们有一个简单的方法来写文件本身的相对地址,就像这样(从其他答案复制)
.section .data
fpath:
.asciz "/home/user/filename" # path to file to delete


然后系统本身会找出文件的绝对路径(类似于 7fff34fb)的位置,并在编译程序集时将其移动到寄存器中。可能看起来像这样

在 x86-64 中:

.section .data
fpath:
    .asciz "/home/user/filename"  # path to file to delete

.section .text
.globl _start
_start:
movq , %rax        # defines which systemcall we are using (87th)
movq $fpath, %rdi     # moves the address of file we want to delete into %rdi
                      # (this is where the argument of sys_unlink(x86-64) is stored)
syscall               # starts the appropriate function


您可以通过查看 %eax 寄存器来访问函数的输出(通常为 0 表示成功或 1 表示失败状态)。在每个系统调用之后,一个整数被 returned in %eax
您可以将此文本放入文本文件 'program.s'(我建议使用 notepad/notepad++,'.s' 代表汇编代码)并使用带有 $ gcc -c program.s 的 gcc 编译它以获得目标代码,您可以使用 $ objdump -d program.o
打印和查看每个命令涉及的目标代码和十六进制键 有关如何查找哪个系统调用是哪个编号以及将参数放入哪个寄存器的更多信息,请访问此处:

对于 x86-64:https://filippo.io/linux-syscall-table/

我看到很多人为此使用 int 0x80,这已被弃用,对于大多数事情,您不应该使用它,因为它非常慢,并且在未来的任何时候都可能被删除。您应该使用 int 0x80 的唯一情况是 space 节省比速度重要得多,或者目标平台(奔腾 4 之前的 CPU)不支持 sysenter。

在 x86 中,Linux 系统调用的工作方式是将系统调用代码放在 eax 中,并将它的任何参数放在连续的寄存器、ebx、ecx 等中。系统调用的 return 值将放在一个

mov eax, 0xa ;0xa is the 'unlink' syscall, which removes a file
mov ebx, <location in memory of a null terminated string containing a path>
push <LABEL TO JUMP TO AFTER SYSENTER IS COMPLETE>
push ecx
push edx
push ebp
mov ebp, esp
sysenter

如果你不关心你的寄存器在系统调用完成后被垃圾填满(例如在你无论如何都会立即覆盖这些寄存器的内容的情况下)你可以使用这个技巧来节省一些space 并稍微加快速度:

mov eax, 0xa ;0xa is the 'unlink' syscall, which removes a file
mov ebx, <location in memory of a null terminated string containing a path>
push <LABEL TO JUMP TO AFTER SYSENTER IS COMPLETE>
lea ebp, [esp-12]
sysenter