2015-04-07 48 views
-2

我正在嘗試編寫一個程序集,用於從目錄中刪除文件的Linux程序集x86。有小費嗎?刪除Linux程序集中的一個文件x86

+3

您需要調用'unlink'系統調用,或從libc的類似命名的函數,或libc的'remove'函數。不知道爲什麼你找不到這些信息... – Jester

+1

搜索'在Linux程序集中的系統調用'或其他一些,這很容易找到。 – teppic

+0

或者創建一個調用'unlink'的簡單C程序,用'gcc -S'編譯它,並查看輸出。 –

回答

2

也許是這樣的:

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

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

    movl %eax, %ebx  # put syscall ret value in ebx 
    movl $1, %eax  # exit syscall 
    int $0x80 

然後在命令行檢查返回值,0是成功的。

$>echo $? 

我嘗試這樣的代碼,如果來自同一 目錄中的文件調用來刪除它不會解除鏈接的文件時,它會從其他迪爾斯取消鏈接文件。 這是32位代碼,以便在64位操作系統,如果你的源文件是聯合國link.s, 你需要創建一個可執行文件:

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

離開了-gdwarf2如果你不這樣做需要使用gdb調試器中運行, 然後用鏈接:

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

希望它爲你工作

+0

*我試過這段代碼,如果從與要刪除的文件相同的目錄中調用該文件,它將不會取消鏈接,它將取消與其他dirs *文件的鏈接。你的例子總是調用['unlink(「/ home/user/filename」)](http://man7.org/linux/man-pages/man2/unlink.2.html),這是絕對路徑當然,不管當前目錄是什麼,它都會執行相同的操作。如果你想讓它使用相對路徑,你可以'unlink(「filename」)'。使用'strace'來查看你正在做什麼系統調用。 –

0

如果你想寫一個從目錄中刪除一個文件彙編代碼,您可以使用多種方法,但我最好的方法之一s使用linux系統調用'unlink'。爲了必須使用適當的系統調用,您必須弄清楚您是否有x86系統或x86-64系統或任何其他類型的系統。我將指定如何僅使用x86/x86-64來完成此操作。

所以系統調用的工作,如Linux的以下幾點:
1.
你把一個數字對應於一個系統調用的數量,像$1返回寄存器(EAX或RAX取決於系統)是在x86和$29是sys_exit sys_pause,你必須確保你在%eax中得到正確的數字,否則它將不起作用。 (我覺得需要強調這一點,這個數字是系統依賴的,所以%eax中的x86系統調用號碼在x86-64系統中不會做同樣的事情)。此外,操作系統也可能會篡改這一點,我只會談論Linux,我不能說任何其他操作系統。

2.
然後您將參數插入了由系統指定了正確的寄存器,再次找到適合您的特定系統的引用,你就會知道哪些寄存器把你的論據,功能分爲(一些系統調用不需要參數,所以這一步是不必要的,爲什麼你需要一個sys_exit參數,idk)。

3.
然後最後使用系統調用讓系統知道運行特定函數(通過將數字放入%eax /%rax指定的函數)。

讓我們看看一些彙編代碼的例子,它刪除了兩個不同系統,x86和x86-64中的文件(windows有自己的方法,但我不會談論那個,儘管它確實存在)。如果我想刪除/取消鏈接存儲在地址0x7fff50的文件(讓我們說你不想指定fpath,你知道地址)

在86:

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

在X86-64:

movq $87, %rax  # defines which systemcall we are using (87th) 
movq $0x7fff50, %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 $87, %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失敗狀態)的輸出。在每個系統調用之後,返回一個整數%eax
您可以將此文本放入一個文本文件'program.s'(我建議使用notepad/notepad ++,'.s'代表彙編代碼)並使用gcc進行編譯與$ gcc -c program.s獲取目標代碼,並且您可以使用$ objdump -d program.o
打印並查看目標代碼和每個命令使用的十六進制密鑰有關如何查找哪個系統調用是哪個數字以及將哪個註冊表進行爭論的更多信息在,去這裏:

對於X86-64:https://filippo.io/linux-syscall-table/

+0

即時絕對地址對於一個例子來說是一個非常奇怪的選擇。在x86-64上,函數調用約定與syscall調用約定幾乎相同,因此它可能已經在rdi中。否則,我會建議asm新手例子使用的通常的靜態存儲,所以'mov $ path_buffer,%rdi'或'mov path_pointer,%rdi' –

+0

編輯添加更多有用的版本 –

+0

我想你應該拿出奇怪的版本,而不是先顯示出來,然後按照正常的方式。 –

2

我看到很多的使用int 0x80這個人,這是一個過時d對於大多數情況,你不應該使用它,因爲它非常緩慢,將來可能會在任何時候被刪除。您應該使用int 0x80的唯一情況是節省空間比速度更重要或者目標平臺上不支持sysenter(Pentium 4之前的CPU)。

在x86中,Linux系統調用通過在eax中包含syscall代碼以及在連續寄存器,ebx,ecx等中的任何參數來工作。系統調用的返回值將被放置在eax中。

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 

如果你不關心你的寄存器被系統調用完成(如在你將立即反正覆蓋這些寄存器的內容的情況下),可以使用這種伎倆來保存後堆滿了垃圾一些空間和速度的東西有點:

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 
+0

[Linux有嚴格的不中斷用戶空間策略](http://stackoverflow.com/questions/25954270/what-does-it-mean-to-break-user-space)。除非您完全不支持32位ABI(在x86-64內核中),否則「int 0x80」將永遠消失。另外值得一提的是,32位glibc通過內核VDSO頁面使用sysenter,因此您可能希望建議調用由內核導出的sysenter包裝。 –

+0

我認爲你在第二個塊中有一個bug:LEA放入EBP的值會被覆蓋而不被使用。 –

+0

真的最好的建議是編寫64位代碼並使用'syscall'指令(使用不同的寄存器來傳遞參數和不同的系統調用號碼。請參閱[x86標記wiki](http://stackoverflow.com/tags/) x86/info)用於ABI文檔)。 'syscall'不需要在用戶空間和內核之間進行復雜的跳舞,這很像'int 0x80',所以對初學者來說很容易。 32位的x86大多已經過時了(特別是在沒有有效的register-args/non-x87 32位ABI的Linux上),所以我認爲編碼32位'sysenter'更像是一個「有趣的事實」比通常有用的東西。 –