Protect
canary是linux下用来保护栈的一种方式。
0x000000000040068e <+8>: mov rax,QWORD PTR fs:0x28
0x0000000000400697 <+17>: mov QWORD PTR [rbp-0x8],rax
......
0x00000000004006f8 <+114>: mov rcx,QWORD PTR [rbp-0x8]
0x00000000004006fc <+118>: xor rcx,QWORD PTR fs:0x28
0x0000000000400705 <+127>: je 0x40070c <main+134>
0x0000000000400707 <+129>: call 0x400510 <__stack_chk_fail@plt>
0x000000000040070c <+134>: leave
通常在函数开头把fs:0x28的值放到栈上,一般都在ebp上面,到函数要返回的时候把它取出来,检测有没有变化,如果有变化,则调用对应的函数处理。
在加入了canary之后,栈的结构一般是
00:0000│ rsp 0x7fffffffe470 ◂— 0x0
... ↓
02:0010│ 0x7fffffffe480 ◂— 0x1
03:0018│ 0x7fffffffe488 —▸ 0x40075d (__libc_csu_init+77) ◂— 0x75eb394801c38348
04:0020│ 0x7fffffffe490 ◂— 0x0
... ↓
06:0030│ 0x7fffffffe4a0 —▸ 0x400710 (__libc_csu_init) ◂— 0x41ff894156415741
07:0038│ 0x7fffffffe4a8 —▸ 0x400570 (_start) ◂— 0x89485ed18949ed31
08:0040│ 0x7fffffffe4b0 —▸ 0x7fffffffe5a0 ◂— 0x1
09:0048│ 0x7fffffffe4b8 ◂— 0xbcd6c56e4cb3d000
0a:0050│ rbp 0x7fffffffe4c0 —▸ 0x400710 (__libc_csu_init) ◂— 0x41ff894156415741
其中的
09:0048│ 0x7fffffffe4b8 ◂— 0xbcd6c56e4cb3d000
就是canary。
bypass
至今知道3种方法
- 单字节爆破出canary
- 直接leak出canary
- 比较长的字符填充来覆盖stack chk fail这个函数的相关信息