dact 뭐 파일 압축을 해주는 놈인데 afl fuzzer를 이용해서 fuzzing 을 하고 이 dact를 exploit 해서 쉘을 얻어내는 것이 목표다. 일단 처음 시작은 어디서 어떻게 segmentation fault가 떴는지였다.
input으로 crash_file 을 주었을 때 dact_common.c 의 478번째줄에서 file_extd_urlent++ 가 계속 되면서 접근할 수 없는 주소로 접근을 해버린다. 그리고 file_extd_urls는 char*[256]의 자료형이다. 즉 file_extd_urlent 가 256이 넘어가면 sfp,ret에 접근이 가능해서 원하는 곳으로 점프가 가능하다는 것이다. 저 parse_url_subst 함수가 어떻게 작동하는지는 잘 모르지만, 만약 여기서 ROP가 가능하다면 그냥 exploit이 가능하다는 것이다.
일단 parse_url_subst 함수를 까보자. pasre.c 파일에 정의되어있다.
char *parse_url_subst(const char *src, const char *fname) {
static struct utsname system_info;
static int sysinfo_init=0;
uint32_t cmd=0, x, strsz;
const char *loc=src, *ploc=loc, *eloc;
char *ret, *ret_s, found=0, *smbuf;
if (!strstr((char *) src,"@@")) return(strdup(src));
....
우리가 원하는 것을 바로 실행시켜버릴 것만 같은 코드가 등장했다! 첫번째 인자로 문자열을 받는데, 해당 문자열에 @@이 포함되지 않으면 그냥 문자열 자체를 복사해서 리턴해버린다! 일단 이건 익스플로잇을 위한 리버싱이니까, 여기서 분석 종료.
이제 프로그램의 전체 흐름을 볼 필요가 있을 듯 하다. 저 dact_common.c 의 478번째 줄까지 프로그램이 어떠한 과정을 거쳐서 실행되는지를 단순하게 보자. 먼저 dact_common.c 의 478번째 줄은 dact_process_file 함수의 일부분이고 dact_process_file 함수는 dact.c 에서 단 한번 호출된다. 그리고 인자로 여러가지를 받는데, 뭐 일단 우리가 터트릴 때 사용한 프로그램 인자는 -dcf crash_file 였기 때문에, 저 두개의 인자가 어떻게 사용됬는지를 중요하게 보아야 한다.
일단 인자를 보면 대강 알겠지만, 첫번째 인자는 filename 이름의 file을 openat으로 열어서 얻은 fd이다. 두번째 인자는 output으로 생성할 파일의 fd이고, 3번째 인자는 잘 모르겠고 , 5번째 인자는 crc라고 되있는거 보면 체크섬같이 검사하는 용도인 것 같고, 6번째는 blocksize , 7번째는 cipher라니까 암호랑 관련있는건데 어떤 암호알고리즘을 쓸지 정하는 것이라고 대강 유추가 가능하다.
뭐 실제로 코드를 봐도 대강 비슷하다. ciphers가 암호알고리즘들의 함수포인터 배열이다. 사실 익스를 하는데에 이부분을 크게 상관없다.
글쓰다가 티스토리 세션만료되서 날라간 관계로 짧은 write up으로 변경. (다른 곳을 찾던지 해야지..)
먼저 이 취약점의 핵심은 파일의 읽을 크기를 파일헤더에서 가져온다는 것이다. 파일의 24~27부분이 뒷부분의 읽을 크기를 지정한다. 이 뒤부터 while문을 돌면서 계속 읽는다. 따라서 뒷부분에 file_extd_urls 를 return address까지 덮을 수 있을 크기만큼 코드를 구성한다. 여기서 중요한 점은 함수의 인자가 많기 때문에 스택까지 매개변수로 사용되서 문제가 생길 수 있다.
바로 이부분인데, cipher 부분을 저 file_extd_urls가 오버런한 부분이 차지하게 되면 cipher은 힙의 주소를 가르키게 되고 함수포인터 실행에 문제가 생긴다. 따라서 cipher을 반복문에서 마지막으로 -1로 세팅해준다.
이 과정이 끝나면 이렇게 rip 컨트롤을 할 수 있다. 이제 쉘코드를 실행해주면 된다.
'Security > Write-Up' 카테고리의 다른 글
card write up (0) | 2020.12.16 |
---|