简体   繁体   English

shellcode:在x86_64程序集中将参数传递给execve

[英]shellcode: pass arguments to execve in x86_64 assembly

I'm trying to write a shellcode that runs execve. 我正在尝试编写一个运行execve的shellcode。 The equivalent c program looks like this: 等效的c程序如下所示:

int main ()
{

  char *argv[3] = {"/bin/sh","-i", "/dev/tty", NULL};
  execve("/bin/sh", argv, NULL);

  return 0;
}

The c program runs fine. c程序运行正常。 Then I tries to write my test program like this(revised to push null): 然后我尝试编写我的测试程序(修改为推送null):

#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 have the addresses of the strings in the memory here and we can assume they won't change. 我在这里有内存中字符串的地址,我们可以假设它们不会改变。 But we don't have the address of string '-i'. 但是我们没有字符串'-i'的地址。 So what I'm doing here is pushing the arguments into the stack like this: 所以我在这里做的是将参数推送到堆栈中,如下所示:


Low                  ------------------------------------------------------------------             High

|addressof"/bin/sh"(rsi points to here)|addressof"-i"|addressof"/dev/ssh"|addressof"/bin/sh"(rdi points to here)|-i|

It didn't work. 它没用。 The program compiled ok but when I ran the program, nothing happened. 程序编译正常但是当我运行该程序时,没有任何反应。

I'm not familiar with assembly and I have some concerns about the way arguments are passed, for example, how does the compiler know when the argv argument ends in the memory? 我不熟悉汇编,我对参数的传递方式有一些担忧,例如,编译器如何知道argv参数何时在内存中结束?

EDIT 编辑

Thanks to the suggestion below by Niklas B, I used trace to see if execve actually runs. 感谢Niklas B的以下建议,我使用了trace来查看execve是否实际运行。 And I got execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3, 0x31b7f54a83, 0x692d], [/* 0 vars */]) = -1 EFAULT (Bad address) , which means the second argument is passed wrong. 我得到execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3, 0x31b7f54a83, 0x692d], [/* 0 vars */]) = -1 EFAULT (Bad address) ,这意味着第二个参数传递错误。 Everything that I pushed into the stack is considered part of the argv argument! 我推入堆栈的所有东西都被认为是argv参数的一部分!

After I push nulls into the stack, the strace gives execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3], [/* 0 vars */]) = -1 EFAULT (Bad address) . 在我将空值推入堆栈后,strace给出execve(0x31b7f54a83, [0x31b7f54a83, "-i", 0x31b7e43bb3], [/* 0 vars */]) = -1 EFAULT (Bad address) This is quite close to the right answer only if the addresses are strings... 只有当地址是字符串时,这非常接近正确答案...

Thanks to Brian, I now see where the problem lies now. 感谢Brian,我现在看到问题出在哪里。 The hardcoded addresses are in the share libary of another program. 硬编码地址位于另一个程序的共享库中。 So this program shouldn't run until it's actually fed into that program. 因此,该程序在实际输入该程序之前不应运行。 Thanks everyone, I'll update this as soon as I can. 谢谢大家,我会尽快更新。 Id the problem's solved, I'll mark it as solved. 如果问题解决了,我会将其标记为已解决。

As Kerrek SB and user9000 point out in the comments, the argv array needed to be a null-terminated array of strings. 正如Kerrek SB和user9000在注释中指出的那样, argv数组需要是一个以null结尾的字符串数组。

Once that is fixed, running this program standalone still won't work, as the strings "/bin/sh" and "/dev/tty" presumably don't exist at that location in the program that you have just compiled, but rather exist at that location in the program that the shell code is designed to target. 一旦修复,独立运行该程序仍然无法工作,因为字符串"/bin/sh""/dev/tty"可能不存在于您刚编译的程序中的那个位置,而是存在于shell代码旨在定位的程序中的该位置。 You need to actually inject it into that program so it will execute there, where those strings are at those addresses. 你需要实际将它注入到该程序中,以便它在那里执行,其中那些字符串在那些地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM