关于论证main(),2011 C标准说(5.1.2.2.1:2):
如果argc的值大于零,则数组成员argv [0]到argv [argc-1]包含指向字符串的指针,在程序启动之前由主机环境给出实现定义的值.
如果此上下文中的"字符串"一词被解释为"0终止字符串",即一个非0字符序列后跟最后的'\ 0',或者/或某些实现可能以不同的方式将参数传递给程序?
在POSIX平台上,是exec*由函数验证的exec*函数族之一的参数作为指向格式良好的字符串的指针(以及如何?),或者setuid程序是否应该假设它已经通过格式良好的0-终止字符串作为参数?
我正在编写一个简单的shellcode,它需要execve()一个ARM平台(Raspberry PI上的Linux)并且第二个参数被困在了execve.根据文件:
int execve(const char *filename, char *const argv[], char *const envp[]);
Run Code Online (Sandbox Code Playgroud)
如果我打电话execve("/bin/sh", {NULL}, {NULL});(从装配的角度来看),这对我来说完全削减了它:
.data
.section .rodata
.command:
.string "/bin/sh"
.text
.globl _start
_start:
mov r7, #11
ldr r0, =.command
eor r1, r1 @ temporarily forget about argv
eor r2, r2 @ don't mind envp too
svc #0
mov r7, #1
eor r0, r0
svc #0
Run Code Online (Sandbox Code Playgroud)
上面的程序集很好地编译,并在我的测试机器上运行时唤起shell /bin/sh.但是,我所有的麻烦都是在特定的目标盒子上没有/bin/sh本身,但只有一个符号链接busybox需要我执行类似的东西execve("/bin/busybox", {"/bin/busybox", "sh", NULL}, {NULL}).
至于我的理解,数组在内存中是连续的,所以我所要做的就是以连续的方式在内存中分配字节,然后将指针提供给我认为是"数组"的开头.考虑到这一点,我尝试了以下内容: …
我写了一个程序来计算传递给execve系统调用的参数的总大小。
我已经用最大参数大小测试了这个程序,期望只有在超过限制时才会发生“参数列表太长”错误ARG_MAX。在我看来,命令行的最大总大小应该尽可能接近ARG_MAX限制,即不能在不超过此限制的情况下添加额外的参数(文件名)。
但我看到了另一种行为:“未使用”字节的数量以不可预测的方式波动,而环境和程序名称保持不变,只有参数数量发生变化。
问题:
程序
计数算法如下:
尺寸argv+ 尺寸envp+ 尺寸argc
的argv是一个指针阵列,以字符串(指针char),因此循环通过此阵列,并加入到一个结果字符串的长度,牢记每个由NULL字节结束。然后将它们的指针添加到结果 - 指针的大小为 8 字节。因此:the number of pointers * 8+lengths of strings (each with a NULL byte)
与envp- 字符串长度与 NULL 字节和指针几乎相同。但是最后一个指针通过指向 NULL 字节来表示数组的末尾,因此将其添加到 result 中8 bytes + 1 bytes。
该argc是简单的int。
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int …Run Code Online (Sandbox Code Playgroud) 我运行了几个程序,fork()然后execve()是第三个程序.这些程序的所有内容都已完成,但最后第三个程序没有返回...即命令提示符不会出现.
如果我wait()在调用程序中使用一个命令,那么execve只有当wait语句的顺序与execve程序结束的顺序匹配时,程序才会返回.为什么会这样?
这是简化的代码:
int main()
{
int child1,child2,status;
char*newargv1[] = {./xyz",NULL};
char *newargv2[] = {./abc",NULL};
if((child1 = fork())==0)
execve(newargv1[0],newargv1,NULL);
if((child2 = fork())==0)
execve(newargv2[0],newargv2,NULL);
while(wait(&status) != child1);
while(wait(&status) != child2);
}
Run Code Online (Sandbox Code Playgroud)
如果child1首先完成,它可以正常工作../xyz和./abc有一些简单的处理和控制到达终点.
我试图在汇编中编写shellcode.我需要执行/usr/bin/killall命令和/usr/bin/wget命令.我有两个命令在shellcode中使用execve()syscall 完美运行.但是现在我想要将这两个结合起来,但这是不可能的,因为程序在执行第一个execve()调用时退出.(摘自execve():execve()成功后不返回).
我该如何进行2次execve()通话?还是有另一种方法来调用都/usr/bin/killall和/usr/bin/wget同一个shell代码?
提前问候和感谢!
在 execve 函数中,参数通过指针数组传递。如果这些指针指向前一个堆栈中的内存,这些内存是否仍然可以在新的过程映像中访问。
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char filename[20] = "a.out";
char str[20] = "hello\n";
char *argv[3];
argv[0] = filename;
argv[1] = str;
argv[2] = NULL;
execve("/hel/a.out", argv, NULL);
return 0;
}
/* /hel/a.out code */
#include <stdio.h>
int main(int argc, char *argv[], char *envp[])
{
printf("%s\n", argv[1]); /** Here, should the memory pointed by argv[1]
* be freed after execve has been called?
*/
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试编写某种漏洞利用程序,但在使我的 asm 代码在堆栈上的任何位置运行时遇到问题。就是这样:
BITS 64
global _start
_start:
mov rax, 59
jmp short file
c1:
pop rdi
jmp short argv
c2:
pop rsi
mov rdx, 0
syscall
ret
file:
call c1
db '/bin/sh',0
argv:
call c2
dq arg, 0 <- problem
arg:
db 'sh',0
Run Code Online (Sandbox Code Playgroud)
由于选定的行,此代码将无法在堆栈上的任何位置工作,因为此代码可以在堆栈上的任何位置执行,因此 nasm 无法正确计算 arg 的地址。(这是shellcode 在作为单独代码单独运行时以及在使用 C++ 代码运行时调用不同系统调用的后续操作,这是问题所在。)
我已经轻松地用 jmp/call/pop 技巧替换了字符串,但指向字符串的指针仍然存在问题。
如果没有给出任何参数或重定向使用,cat 命令将从标准输入中读取。但是当我用它执行它时,execve()它的行为并不像在 bash 中那样。
代码:
#include <unistd.h>
#include <fcntl.h>
int main(int ac, char **av, char **env)
{
char *args[] = {"/bin/cat",NULL};
int ps = fork();
if (!ps)
execve("/bin/cat",args, env);
}
Run Code Online (Sandbox Code Playgroud)
输出 :
cat: stdin: Input/output error
Run Code Online (Sandbox Code Playgroud)
我尝试不带参数运行它,但它返回一个错误。
我试图在Linux上使用execve()from 生成一个新进程unistd.h.我试过传递以下参数,execve("/bin/ls", "/bin/ls", NULL);但没有得到任何结果.我也没有出错,程序就退出了.有没有理由发生这种情况?我尝试以root用户身份启动它.我需要使用的原因execve()是因为我试图让它在这样的汇编调用中工作
program: db "/bin/ls",0
mov eax, 0xb
mov ebx, program
mov ecx, program
mov edx, 0
int 0x80
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在尝试通过 execve() 运行 touch 命令,这是我的代码:
#include <stdio.h>
#include <unistd.h>
int main()
{
char * c[2]={"/usr/bin/touch","test.txt"};
execve(c[0],c,NULL);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但似乎文件没有被触及或日期没有被更新。来人帮帮我。