我们有时候getshell会遇到各种问题(system栈占用太多,字节对齐,execve参数有三个等等),所以最方便的是使用execv,因为execv只用两个参数,但是呢execv底层还是使用的execve,也就是说避免不了会存在栈布局的问题,在64位下我们可以使用pop布局寄存器的参数,但是32位是通过偏移作为参数,需要我们布局栈空间(特别是环境变量位置)
execv函数是execve()函数的库封装,我们看下exec族函数:
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。
再看下execve:
int execve(const char *filename, char *const argv[], char *const envp[]);
-
filename
:指定新程序的路径和名称。 -
argv
:传递给新程序的命令行参数数组。 -
envp
:传递给新程序的环境变量数组。
下面是一个使用execve函数的简单示例:
#include <unistd.h>
int main() {
char *argv[] = { "/bin/ls", "-l", NULL };
char *envp[] = { "PATH=/bin", NULL };
execve("/bin/ls", argv, envp);
return 0;
}
上述示例中,我们通过调用execve函数执行了"/bin/ls"程序,并传递了命令行参数"-l"
和环境变量"PATH=/bin"
。
当然我们最常用的还是把最后两个参数赋值成0
来看下例题如下:
(1)main函数
写入bss段上一段数据然后作为参数传给函数0x80485EC
(2)0x80485EC函数
这里strlen和strcpy是会被x00截断,但是v6是int8类型,存在整数溢出,当v6=261的时候正好溢出为5绕过判定条件,最后strcpy会把bss上内容拷贝到栈上,存在栈溢出漏洞
先看exp:
第一次溢出布局栈空间是为了execv的环境变量能通过寻址找到为0的地址,执行puts输出libc地址,然后返回到main函数
第一次赋值栈上面的多余内容是因为返回main之后push的
第二次赋值可以看到覆盖了一部分第一次的内容,并且返回execv
现在execv下的execve环境正确了
需要注意的是第一次布局是为了布局envp(因为环境变量的寻址是 mov eax, dwordptr [ebx - 0xb8]的位置)
原文始发于微信公众号(由由学习吧):execv环境攻击
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论