IO_buf란?
파일스트림은 buffering이라는 기술을 구현해 더 안정적이고 효율적으로 동작하게 된다.
즉, 데이터의 생산자와 소비자가 서로 처리속도가 다를 경우 예를 들어, 데이터 처리 속도가 [생산자 > 소비자]인 상황에서
완충 역할을 하게 된다.
SysCall은 커널 단에서 작업을 수행하기 위해 존재한다고 말했다,
(Application 단에서 디바이스를 조작할 수 있으면, 공격자의 칩입이나 사용자의 실수에 너무 취약하기 때문임)
즉, 어떤 프로세스가 있다면 이 프로세스가 사용하는 데이터는 User ↔ Kernel 영역을 돌아가면서 실행하게 된다.
(이를 context switching 이라고 부름)
이때 context엔 레지스터 값이나 flag와 같은 정보들이 저장된다.
만약 아래의 코드에서 Hello world를 한 글자마다 context switching을 수행한다고 생각하면, 무조건 손해라는 것을 알 수 있을 것이다.
#include <stdio.h>
char buf[0x400];
int main()
{
setvbuf(stdout, buf, 0, 0x400);
//if computer can deal with only one character for each switching, what happened?
printf("Hello World!\n");
getchar();
}
그럼 buffer을 사용하여 Hello world를 담아 한번에 처리하면 어떨까?!
이 기술이 File Stream(대표적으로 stdout, stdin, stderr)에 그대로 나타난다.
#include <stdio.h>
char buf[0x400];
int main()
{
setvbuf(stdout, buf, 2, 0x400);
printf("Hello World!\n");
getchar();
}
setvbuf(stdout, buf, 2, 0x400); 으로 코드를 변경한 후 stdout을 보면 특정 buffering 영역을 가르키고,
그것은 shortbuf(file stream 내부에 존재함)라는 곳을 가르킨다.
이때 프로그램의 실행 결과는 출력을 하지 않는 것으로 보인다.
그 이유는 H를 하나 처리하고 다시 user 화면으로 돌아갔기 때문이다.
만약 enter를 한번 입력하면 context switching을 여러 번 진행하여 모든 문자열이 출력될 것이다.
곧 진행할 실험에서 A * x 만큼 입력하고 stdin의 buffer을 보면 A가 잔뜩 찍혀있고,
이는 stdin에 의해 stdin buffer에 데이터가 써짐을 의미한다.
이제 실험을 위해 scanf("%s", buf);, setvbuf(stdout, buf, 1, 0x400);으로 바꾸자.
#include <stdio.h>
char buf[0x400];
int main()
{
setvbuf(stdout, buf, 1, 0x400);
printf("Hello World!\n");
scanf("%s", buf);
}
그럼 setvbuf(stdin, 0, 2, 0); 을 추가하면 어떨까?
#include <stdio.h>
char buf[0x400];
int main()
{
setvbuf(stdout, buf, 1, 0x400);
setvbuf(stdin, 0, 2, 0);
printf("Hello World!\n");
scanf("%s", buf);
}
위 코드를 빌드한 후 stdin의 IO_buf_end 위치에 데이터를 [원래 IO_buf_end + 0x100] 으로 덮은 값으로 변경해보자.
만약 stdin의 IO_buf_end 위치에 데이터를 [원래 IO_buf_end + 0x100] 으로 덮은 후 다시 A * x 만큼 입력하면?
터짐 → 그 다음에 관계없는 영역까지 침범해버리기 때문이다.
이를 피하기 위해 보통 뒤의 데이터들은 기존에 적힌 데이터를 그대로 입력해주는 것이 좋다.
즉, 정리하자면 아래와 같다.
- 파일 스트림(stdin, stdout, stderr ... )은 bufferinf 기술을 사용한다.
- IO_buf_base부터 IO_buf_end가 buffer의 쓸 수 있는 공간이다.
- _IONBF 상태일 때, (2) 1 바이트짜리 buffer가 파일 스트림 내부에 만들어진다.
- IO_buf_end를 조작한 후 stdin의 파일스트림 구조체를 조질 수 있다^^
이제 마구잡이로 쓸 수 있게 되었고, 심지어 stdin의 IO_buf_end를 unsorted bin attack을 통해 unsorted bin의 위치까지 덮을 수 있게 된다면,
(우연찮게도 stdin에서 unsorted bin까지의 거리가 멀지 않음) wow! 프로세스 내에서 엄청난 자유도를 얻게 된다!
그러나...
우리가 hook을 덮을 수 있는 상황이 아니라면?
(버그 패치 이슈나 seccomp 등에 의해 막힌다면?)
다음엔 FSOP에 대해 설명해보겠다.
'Systemhacking > Base info' 카테고리의 다른 글
File Stream Oriented Programming (0) | 2023.07.19 |
---|---|
malloc consolidate with Fastbin_Dup Consolidate (1) | 2023.06.04 |
small bin attack (0) | 2023.06.04 |
unsorted bin attack (0) | 2023.06.02 |
unsafe Unlink in heap (0) | 2022.11.07 |
댓글