FSOP관련해서 궁금한게 있습니다!!
FSOP할때 flag나 read base,write base등등 파일스트림값들을 어떻게 바꿀지 항상 고민이 되서 고수분들은 어떤 레퍼런스를 보고 하시는지 궁금합니다.
Source code를 직접 보아도 솔직히 해석이 잘 안됩니다...
고수분들은 어떻게 하시는지 궁금합니다.
+추가 setvbuf나 fgets를 FSOP로 libc leak이나 AAW를 할 수 있는지도 궁금합니다<--이게 궁금해서 찾아보다가 질문드립니다
음.. 인자로 주는 _IO_FILE구조체의 멤버를 건드릴 수 있다는 가정하에 setvbuf나 fgets내부에서 _IO_new_do_write함수를 호출한다면 libc leak은 가능할것 같습니다. 이건 결국 glibc소스코드를 봐야 알 수 있는거라... 저는 소스코드 보기 귀찮을때는 그냥 gdb에서 si하면서 안으로 계속 타고들어가보기도 합니다. gdb로 계속 파고들어가면서 흐름 보기만 해도 웬만해선 루틴 파악 되고 저는 이게 소스코드 분석보다 조금더 편하긴 합니다. 그리고 FSOP로 aaw는 fgets일 경우에는 가능할것같네요. 드림핵 강의중에 fsop로 aaw하는 부분이 있는데 _IO_new_file_underflow함수를 fgets내부에서 호출할 경우에는 aaw가 가능할것 같습니다. setvbuf도 마찬가지고요. 물론 이것도 fgets내부를 들어가봐야 알 수 있는거긴 합니다.
심심해서 그냥 혼자 코드 뜯어봤습니다. glibc 2.23
기준입니다.
setvbuf
얘는 별거 없습니다.
case _IOFBF:
...
if (_IO_DOALLOCATE (fp) < 0)
눈에 띄는건 얘밖에 없는데 그냥 malloc & free 하는 녀석.
결론: 공격하기엔 심심한 녀석.
fgets
이 녀석이 아주 흥미롭습니다. 안그래도 옛날에 강의 보면서 fread만 aaw 설명되어 있는데
정작 ctf에는 얘가 더 많이 나와서 한번 분석이나 해볼까 미뤘었는데 좋은 기회였습니다.
위아래로 에러 검출하고 뒤처리 다 하는데 가장 핵심 부분은 여기.
_IO_fgets()
count = _IO_getline (fp, buf, n - 1, '\n', 1);
_IO_getline() 함수는 내부 함수인 _IO_getline_info() 함수 호출.
_IO_getline_info()
int c = __uflow (fp);
...
if (c == delim)
{
if (extract_delim > 0)
*ptr++ = c;
else if (extract_delim < 0)
_IO_sputbackc (fp, c);
if (extract_delim > 0)
++len;
return ptr - buf;
}
__uflow() 함수는 뭔가 있을 줄 알았더니만 결과적으로 _IO_wstr_underflow() 함수를 부르는데 암것도 없습니다.
다음으로 _IO_sputbackc() 함수가 나왔습니다. 네, 희망이 보이죠?
_IO_sputbackc()
else
result = _IO_PBACKFAIL (fp, c);
_IO_jump_t 구조체에서 __pbackfail를 부르는데 쭉쭉 가다보면 _IO_wstr_pbackfail() 함수 만나고요, 안에 보면
_IO_wstr_pbackfail()
_IO_wint_t
_IO_wstr_pbackfail (_IO_FILE *fp, _IO_wint_t c)
{
if ((fp->_flags & _IO_NO_WRITES) && c != WEOF)
return WEOF;
return _IO_wdefault_pbackfail (fp, c);
}
네! 맞습니다. 별거 없습니다.
결론
이렇게 되면 남은 방법은 _IO_jump_t의 pbackfail 부분에 _libc_IO_vtables 영역 내에 존재하는 다른 함수의 주소(ex. overflow와 오프셋 계산해서 주소 바꿔버리기??)로 바꾼 다음 연계할 수 밖에 없다고 생각합니다.
그냥 초보자의 간단한 분석입니다. 고수분들 틀린 점 있으면 아낌없이 지적해주시고 심심해서 적은 글입니다.
감사합니다.