[英]ptrace change syscall number arm64
我正在嘗試使用 ptrace 在 linux arm64 上將調用從一個系統調用更改為另一個系統調用。
據我了解,系統調用號在 x8 中,讀取系統調用的寄存器證實了這一點。 我更改了這個數字並調用了 SETREGSET 並且調用了舊的系統調用而不是新的系統調用。 當我檢查從 syscall x8 返回的寄存器設置為我給他的 syscall 時,它應該是。
更改同一系統調用的其他參數有效。
我看到一些地方使用 PTRACE_SET_SYSCALL 但我找不到很多關於它的信息,我嘗試使用它但它似乎在這個拱形結構中不受支持,它沒有定義並且寫入數字因為不存在而失敗。
我究竟做錯了什么? 為什么不起作用?
這是代碼,為了簡單起見,我刪除了打印和驗證,對於這個例子,我只是試圖停止寫入系統調用:
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
int status;
waitpid(pid, &status, 0);
while (ptrace(PTRACE_SYSCALL, pid, NULL, NULL) == 0)
{
waitpid(pid, &status, 0);
struct user_pt_regs regs;
struct iovec io;
io.iov_base = ®s;
io.iov_len = sizeof(regs);
ptrace(PTRACE_GETREGSET, pid, (void*)NT_PRSTATUS, &io);
// reg[7] is 0 before syscall and 1 after
if (regs.regs[7] == 0)
{
// Change write syscall
if (regs.regs[8] == 64)
{
// Change the syscall to getpid (doesn't matter)
regs.regs[8] = 172;
ptrace(PTRACE_SETREGSET, pid, (void*)NT_PRSTATUS, &io);
}
}
}
至於tracee,一個簡單的hello world with write with sleep;
char buf[] = "hello world\n";
while(1)
{
write(1, buf, sizeof(buf));
sleep(5);
}
雖然程序運行時沒有錯誤並打印正確的寄存器,但系統調用不會改變,它會繼續打印 hello world
在 arm64 上,出於兼容性原因,內核將即將執行的系統調用存儲在單獨的變量pt_regs.syscallno
中,而ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov)
確實更改了寄存器(請參閱內核源代碼中struct pt_regs
的定義: commit:eec4df2/arch/arm64/include/asm/ptrace.h:178 )。
當在 arm 或 arm64 上並且使用CONFIG_COMPAT=yes
編譯內核時,可以通過ptrace(PTRACE_SET_SYSCALL, pid, NULL, syscallno)
更改系統調用號。
對於沒有CONFIG_COMPAT=yes
的 arm64 內核,您需要ptrace(PTRACE_SETREGSET, pid, NT_ARM_SYSTEM_CALL, &iov)
。
例子:
int syscallno;
struct iovec iov = {
.iov_base = &syscallno,
.iov_len = sizeof (int),
};
ptrace(PTRACE_SETREGSET, traceePid, NT_ARM_SYSTEM_CALL, &iov);
NT_ARM_SYSTEM_CALL 的NT_ARM_SYSTEM_CALL
定義如下: commit:eec4df2/arch/arm64/kernel/ptrace.c:1173 。
使用SYS_write
或SYS_chdir
類的參數阻止系統調用的另一種方法是將參數設置為無效地址,因此它將失敗並顯示EINVAL
:
struct user_regs_struct regs;
struct iovec iov = {
.iov_base = ®s,
.iov_len = sizeof (struct user_regs_struct),
};
ptrace(PTRACE_GETREGSET, traceePid, NT_PRSTATUS, &iov);
regs.regs[0] = 123;
regs.regs[1] = 456;
regs.regs[3] = 789;
ptrace(PTRACE_SETREGSET, traceePid, NT_PRSTATUS, &iov);
在系統調用中注冊使用: Chromium OS Docs 。
出於某種原因,您似乎必須在寄存器0
設置系統調用號,而不是像 aarch64 ABI 所期望的那樣設置為8
。
// Change the syscall to getpid (doesn't matter)
regs.regs[0] = 172;
我不確定為什么會這樣; 也許 ptrace 在進入syscall
函數時停止執行進程,然后將第一個參數(在寄存器 0 中)移動到寄存器 8 本身中的實際系統調用號參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.