shellcode:将参数传递给x86_64程序集中的execve
我试图编写一个运行execve的shellcode。等效的c程序如下所示:shellcode:将参数传递给x86_64程序集中的execve
int main()
{
char *argv[3] = {"/bin/sh","-i", "/dev/tty", NULL};
execve("/bin/sh", argv, NULL);
return 0;
}
c程序运行良好。然后我试图写我这样的测试程序(修订推空):
#include<stdio.h>
int main(){
__asm__(
"xor %rdx,%rdx\n\t" //rdx is the third argument for execve, null in this case.
"push %rdx\n\t"
"mov -8(%rbp),%rdx\n\t"
"mov $0x692d,%rdi\n\t" //$0x6924 is 'i-'
"push %rdi\n\t" //push '-i' to the stack
"lea -16(%rbp),%rax\n\t" //now rax points to '-i'
"mov $0x31b7f54a83,%rdi\n\t" //the address of /bin/sh
"push %rdi\n\t" //push it to the stack
"push %rdx\n\t" //end the array with null
"mov $0x31b7e43bb3,%rdi\n\t" //the address of "/bin/sh"
"push %rdi\n\t" //push the address of "/dev/tty to the stack
"push %rax\n\t" //push the address of '-i' to the stack
"mov $0x31b7f54a83,%rdi\n\t"
"push %rdi\n\t" //push the address of /bin/sh again to the stack
"mov %rsp,%rsi\n\t" //rsi now points to the beginning of the array
"mov -24(%rbp),%rdi\n\t" //rdi now points to the addresss of "/bin/sh"
"mov $0x3b,%rax\n\t" // syscall number = 59
"syscall\n\t"
);
}
我在内存中的字符串的地址在这里和我们可以假设,他们将不会改变。但是我们没有字符串'-i'的地址。所以我在这里做是推动参数进栈是这样的:
Low ------------------------------------------------------------------ High
|addressof"/bin/sh"(rsi points to here)|addressof"-i"|addressof"/dev/ssh"|addressof"/bin/sh"(rdi points to here)|-i|
它没有工作。程序编译好,但是当我运行程序时,什么都没有发生。
我对汇编并不熟悉,并且对参数传递的方式有些担忧,例如,编译器如何知道argv参数何时结束于内存中?
编辑
多亏了由Niklas低于B的建议,我曾经跟踪,看是否execve的实际运行。我得到了execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3, 0x31b7f54a83, 0x692d], [/* 0 vars */]) = -1 EFAULT (Bad address)
,这意味着第二个参数被错误地传递。我推入堆栈的所有内容都被认为是argv参数的一部分!
在我将零点推入堆栈之后,strace给出execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3], [/* 0 vars */]) = -1 EFAULT (Bad address)
。如果地址是字符串,这是非常接近正确的答案...
感谢布赖恩,我现在看到现在的问题在哪里。硬编码地址位于另一个程序的共享库中。所以这个程序不应该运行,直到它被实际送入该程序。谢谢大家,我会尽快更新。如果问题解决了,我会将其标记为已解决。
正如Kerrek SB和user9000在注释中指出的那样,argv
数组需要是以空字符结尾的字符串数组。
修复之后,单独运行此程序仍然不起作用,因为"/bin/sh"
和"/dev/tty"
这些字符串可能不存在于刚刚编译的程序中的该位置,而是存在于该位置的程序设计了shell代码的目标。您需要实际注入该程序,以便在那里执行,这些字符串位于这些地址。
无效终止!空终止! –
@KerrekSB所以我需要将0x00推入堆栈呢? – Gnijuohz
(不是说这与您的问题有关。)数组需要由空指针终止。另外,将'NULL'作为参数传递是一种非可移植的Linux黑客攻击,不应该依赖它。参见[手册](http://man7.org/linux/man-pages/man2/execve.2.html)。 –