加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用内联汇编启动shell

发布时间:2020-12-16 01:51:44 所属栏目:安全 来源:网络整理
导读:我正在完成一项学校任务,我完全被难过了.教授和助教没有任何帮助,因为他们为任何学生提供的每一个答案都是“继续寻找,答案就在那里”的一些变化.我正在尝试使用以下代码创建一个 shell: #include stdio.h#include stdlib.hconst char code[] ="x31xc0""x
我正在完成一项学校任务,我完全被难过了.教授和助教没有任何帮助,因为他们为任何学生提供的每一个答案都是“继续寻找,答案就在那里”的一些变化.我正在尝试使用以下代码创建一个 shell:

#include <stdio.h>
#include <stdlib.h>

const char code[] =
"x31xc0"
"x50"
"x68""//sh"
"x68""/bin"
"x89xe3"
"x50"
"x53"
"x89xe1"
"x99"
"xb0x0b"
"xcdx80"
;

int main(int argc,char **argv)
{
printf("running...n");

char buf[sizeof(code)];
strcpy(buf,code);
((void(*)( ))buf)( );
}

我试图将代码[]替换为在线(包括本网站)发现的其他一些示例,以及教授提供的其他pdf示例.这些都没有用.我使用gdb进行反汇编并尝试构建自己的代码[],但也失败了.对于它的价值,我可以说在普通用户中我的应用程序会在((void(*)())buf)();并在同一行的root用户中退出并退出(没有segfault通知).

我不知道在哪里采取这个任务,我不能处理任何后来的缓冲区溢出任务,直到我能理解这个简单的第一步.任何帮助将不胜感激.

编辑:我忘了提到,我已经在OSX 10.8.2上和通过VirtualBox在Ubuntu VM上尝试过这个.我假设它不适用于OSX,但我很绝望. ha对于Ubuntu,我们被要求做:

sudo #sysctl -w kernel.randomize_va_space = 0

sudo apt-get install zsh
CD /箱
sudo rm sh
sudo ln -s / bin / zsh / bin / sh

这些命令应禁用地址空间随机化,安装zsh并将其链接到/ bin / sh.我在VM中完成了所有这些任务,没有任何错误

解决方法

你的代码反汇编成这样的东西:

00000000  31C0              xor eax,eax
00000002  50                push eax
00000003  682F2F7368        push dword 0x68732f2f
00000008  682F62696E        push dword 0x6e69622f
0000000D  89E3              mov ebx,esp
0000000F  50                push eax
00000010  53                push ebx
00000011  89E1              mov ecx,esp
00000013  99                cdq
00000014  B00B              mov al,0xb
00000016  CD80              int 0x80

由ndisasm提供.让我们一步一步地完成这些说明,并在途中分析堆栈帧.

xor eax,eax将eax寄存器清零,因为操作数与其自身的XOR运算总是会产生零. push eax然后将值推送到堆栈上.因此,堆栈当前看起来或多或少像这样(相对于代码开头的esp值显示的偏移量,esp表示esp当前指向的堆栈单元格):

+----------+
     0 | 00000000 |
esp -4 | xxxxxxxx |
       +----------+

接下来,我们有两个push dword指令,它们将一些立即值推送到堆栈,在执行它们之后 – 看起来像这样:

+----------+
     0 | 00000000 |
    -4 | 68732f2f |
    -8 | 6e69622f |
esp -12| xxxxxxxx |
       +----------+

esp当前指向推送到堆栈的第二个立即值的最后一个字节.让我们尝试将推送值解释为ASCII,如果我们从esp的当前值开始按顺序从堆栈读取它们的顺序.我们得到2f62696e2f2f7368的字节序列,它在ASCII中等于/ bin // sh.另外,序列以0结尾,因此它是有效的C字符串.

这是将esp的当前值保存到寄存器ebx中的主要原因.它包含将运行的可执行文件的路径.双斜杠对操作系统来说不是问题,因为POSIX只是忽略多次出现的斜杠并将它们视为一个斜杠.

接下来,我们将eax和ebx的当前值推入堆栈.我们知道eax包含零,ebx包含指向C字符串“/ bin // sh”的指针.堆栈目前看起来像这样:

+----------+
         0 | 00000000 |
        -4 | 68732f2f |
        -8 | 6e69622f |
    ebx -12| 00000000 |
        -16| (ebxVal) |
ecx esp -20| xxxxxxxx |
           +----------+

将寄存器的值压入堆栈后,esp的当前指针将保存在ecx中.

cdq是一种在这种情况下执行非常巧妙的技巧的指令:它将eax的当前值符号扩展到edx:eax寄存器对.因此,在这种情况下,它将edx中的值清零,因为零的符号扩展为零.当然,我们可以使用xor edx,edx清除edx中的值,但该指令用两个字节编码 – 而cdq只占用一个.

下一条指令将值0xb(11)置入eax的低字节寄存器.与前一种情况类似,我们可以只执行mov eax,0xb,但这会导致5字节指令,因为必须将immediates编码为完整的32位值.

int 0x80在Linux上调用系统调用调用程序.它期望eax中的系统调用次数(现在等于0xb,因此将调用sys_execve函数),以及ebx,ecx,edx,esi,edi和ebp中的其他参数.

现在,让我们看一下该系统调用的原型:

int execve(const char *filename,char *const argv[],char *const envp[]);

因此,filename参数放在ebx中 – 它指向/ bin // sh.放置在ecx中的argv是要执行的可执行文件的参数数组,必须以NULL值终止.在Intel架构上,NULL等于0,ecx指向:指向/ bin // sh的指针,然后是NULL值. envp,为NULL,指向环境值数组,必须将其表示为key = value形式的char *值.

成功执行execve会导致当前进程映像被指向可执行文件的映像替换,并使用提供的参数执行.在这种情况下,将使用/ bin // sh的参数执行/ bin / sh(如果存在).

迈克尔可能是正确的,为什么这不起作用:最近的Linux内核将数据页标记为不可执行,并且尝试执行它们将导致分段错误.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读