- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我创建了系统调用但未找到。这是我在 asm 中的代码
section .text
global _start
_start:
xor eax,eax
push eax
push dword '//ls'
push dword '/bin'
mov ebx,esp
mov al,0xb
int 0x80
;/bin//ls
当由此构建静态 32 位可执行文件并运行它时,我得到:
A NULL argv[0] was passed through an exec system call.
Aborted (core dumped)
这里发生了什么以及如何解决它?
最佳答案
您的代码按您的预期工作,进行了成功的 execve("/bin//ls", NULL, NULL)
系统调用。
问题在于 GNU ls
与 sh
或其他一些程序不同,它在运行空 argv[]< 时选择中止 ()/
。通常的约定是将程序名称作为第一个参数传递 (argv[0]
)。
您的程序使用 /bin//sh
而不是 ls
可以正常工作
execve
的 argv 和 envp args 来自离开 ECX 和 EDX = 0,因为 Linux 选择在进入用户空间之前设置它们。 (这避免了内核信息泄漏,而不是让它们未初始化)。显然,这在将使用包含未知值的寄存器运行的 shellcode 中不起作用。
顺便说一句,Linux execve()
does document它支持传递 envp 和/或 argv=NULL
而不是 argv = (char*[]){NULL};
(指向 NULL 的指针)。不是为未指向有效内存的 argv
返回 -EFAULT
,而是将 NULL 特殊情况作为空数组。
我可以使用 ls (GNU coreutils) 8.31
在 Arch Linux 上重现您的结果
$ nasm -felf32 exec.asm
$ ld -melf_i386 -o exec exec.o
$ ./exec
A NULL argv[0] was passed through an exec system call.
Aborted (core dumped)
您可以使用 strace
来确定消息不是来自您的进程。
$ strace ./exec
execve("./exec", ["./exec"], 0x7ffd7090ed90 /* 54 vars */) = 0 <=== starting your program
strace: [ Process PID=21152 runs in 32 bit mode. ]
execve("/bin//ls", NULL, NULL) = 0 <==== This is your system call
# then ls starts up normally
strace: [ Process PID=21152 runs in 64 bit mode. ]
brk(NULL) = 0x55b5fbaff000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffe1d74c5b0) = -1 EINVAL (Invalid argument)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
... normal dynamically-linked executable startup stuff ...
... until it writes a message to stderr and raises SIGABRT ...
write(2, "A NULL argv[0] was passed throug"..., 55A NULL argv[0] was passed through an exec system call.
) = 55
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
getpid() = 21152
gettid() = 21152
tgkill(21152, 21152, SIGABRT) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=21152, si_uid=1000} ---
+++ killed by SIGABRT (core dumped) +++
Aborted (core dumped)
如果您查看 ls
的源代码,您可能会看到 abort()
函数调用,尤其是当您搜索它打印的字符串时。
正如我所说,bash
和大多数其他 shell 不这样做。
如果你确实想修复它,你可能想创建一个指针数组 {"/bin//ls", NULL}
并将指向它的指针作为第二个参数传递。
...
mov ebx, esp ; path
push eax ; 0
push ebx ; pointer to the filename
mov ecx, esp ; argv = pointer to that array
cdq ; envp = EDX = 0 (broadcast high bit of EAX into EDX)
mov al, 0xb
int 0x80
为了更好的测量,我添加了 EDX 归零。
这对我有用:ls
成功运行。
关于linux - 如何修复 'SYSCALL execve' : ls complains about a NULL argv[0],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57682494/
目前我正在学习 C 并试图理解这些说明。它们真的不同吗? ++*argv *argv++ *(++argv) *(argv++) 谢谢! 最佳答案 后缀递增运算符的优先级高于指针取消引用运算符,而不是
我正在与在 Hostgator 共享主机上运行的 PHP CLI 的一个(也许)简单问题作斗争。一个简单的代码: 在我的本地机器上运行时以及其他几个 php 实例: php test.php arg
谁能解释一下原因 int main(int argc, const char * argv[]) { while (* argv) puts(* argv++); return 0 ;
从 K&R 的 C 书的第 5.10 章开始,argv 的概念被引入以允许命令行参数。 argv 是指向字符指针数组的指针。据此,以下代码如何检查提供的参数是否以连字符开头? (*++argv)[0]
我不明白 sys.argv 和 argv 之间的区别,网上没有任何东西给我我理解的概念。如果两者相同!我们什么时候使用 sys.argv 什么时候使用 argv ? 如果不是,sys.argv 是什么
我正在编写一个接受参数的 C 程序,char *argv[] 来决定运行哪个 exec()。我有 execlp(argv[1], argv[1], NULL) 可以正常工作。出于某种原因,execvp
char** argv 和 char* argv[] 有什么区别?在 int main(int argc, char** argv) 和 int main(int argc, char* argv[]
我目前有一个 python 脚本,可以在大型网络中完成一项非常有用的任务。我所做的是使用 lsof -iTCP -F 和其他一些选项来转储所有监听的 TCP 套接字。我能够得到 argv[0],这不是
为什么 argvs 的行为很奇怪?示例: 这将按预期工作,打印第一个参数的第一个字符。 printf("%c", *argv[1]); 但是,这将打印 ascii 表中的字符(又名“更大”,表示为数字
我做了一个小的重复异或加密器。您可以使用您选择的键对您选择的字符串进行异或运算,它可以选择将其输出到文件中。 无论何时使用单个单词(无空格)字符串和键运行程序,都没有问题。但是,只要字符串或键中有空格
我刚开始学习 C,想知道我应该在我的主要方法中使用其中的哪一个。有什么不同吗?哪个更常见? 最佳答案 由于您刚开始学习 C,我建议您首先真正尝试了解数组和指针之间的区别,而不是共同的东西。 在参数和数
所以我在编译器转换的函数中传递数组时在幕后阅读过 int myArray(int arr[]) 进入 int myArray(int *arr) 例如,大多数时候数组也会衰减为指针 arr[0] 与相
我正在编写一个小的 shell 程序,它接受一个命令并执行它。如果用户输入无效命令,则 if 语句返回 -1。如果命令正确,它就会执行命令,但是一旦它执行了命令,程序就会结束。我做错了什么是不执行它之
是否可以传入自定义参数列表? 与现实生活中的用例相比,更多是出于好奇,但例如,我可能希望在让 argparse 完成其工作之前将所有参数转换为小写。 最佳答案 Yes .只需传入要parse_args
我知道这个问题很基础,我也是新手,所以请帮我解决这个问题: 我有这个代码: int wmain(int argc, wchar_t *argv[]) { if (*argv[1] == L'-
这个问题在这里已经有了答案: Understanding slicing (38 个答案) 关闭 3 个月前。 我写了这段代码: #!/usr/bin/env python import sys i
我的程序获取主要参数,我的任务是检查用户是否在执行文件和参数之间输入了空格。 这是一个没有在 argv[0] 为 HW01 和 argv[1] 之间输入空格的人的例子/n: HW01/n 但是如果有人
我的 c 技能很生疏,所以如果这是一个愚蠢的问题,我深表歉意,但我什至没想过要寻找这个简单问题的答案。此代码编译时没有任何警告: #include int run_script( int argc,
这个问题在这里已经有了答案: Should I use char** argv or char* argv[]? (10 个答案) What does the 'array name' mean i
我有以下代码片段: int main(int argc, char *argv[]) { char line[MAXLINE]; long lineno = 0; i
我是一名优秀的程序员,十分优秀!