# Cách đọc từ stream của fgets ## Tản mạn - Đây là kiến thức mình gặp khi tham gia 1 giải khá lmao nhưng tự nhiên minh gặp 1 bài easy nhưng lại có 1 cái trick khá là lạ ![image](https://hackmd.io/_uploads/B1yjdSO5Jl.png) - Challenge cho hàm `win` đọc flag ở thư mục cha, tuy không thể ROP để set-up nhảy thằng từ đầu nhưng mà có thể nhảy thẳng đến open để đọc flag. Nhưng chuyện đơn giản vậy thì đâu có gì để nói. ![image](https://hackmd.io/_uploads/SJhXtB_9kg.png) -> **segmentation fault rồi** ![image](https://hackmd.io/_uploads/SkwvYHd51g.png) -> Tại sao `flag` lại ghi đè luôn saved rip của `_IO_getline_info` - Đẻ giải mã tại sao flag có thể ghi đè được như vậy thì mình quyết định debug xem `fgets` đã làm gì ? ## Deep debug - Sau khi debug thì đoạn xử lí từ file vào buffer sẽ là hàm `_IO_default_uflow` [source](https://elixir.bootlin.com/glibc/glibc-2.35/source/libio/genops.c#L360) ![image](https://hackmd.io/_uploads/r1Ss3Hd91g.png) ![image](https://hackmd.io/_uploads/ryE02BO9Jx.png) - Đọc 1 hồi debug + reverse + đọc source của glibc mình tìm ra đoạn mà đọc từ buffer (heap) vào stack [source](https://elixir.bootlin.com/glibc/glibc-2.35/source/libio/iogetline.c#L100) ```c if (t != NULL) { size_t old_len = ptr-buf; len = t - fp->_IO_read_ptr; if (extract_delim >= 0) { ++t; if (extract_delim > 0) ++len; } memcpy ((void *) ptr, (void *) fp->_IO_read_ptr, len); fp->_IO_read_ptr = t; return old_len + len; } memcpy ((void *) ptr, (void *) fp->_IO_read_ptr, len); fp->_IO_read_ptr += len; ptr += len; n -= len; ``` ![image](https://hackmd.io/_uploads/SkdfW8u51e.png) ![image](https://hackmd.io/_uploads/ryUObIu91e.png) -> Ở đây `_IO_default_uflow` sẽ sao chép nội dung ở heap vào stack - `Debug` tiếp xem đoạn này của `stack` xuất phát từ đâu, ảnh hưởng gì đến `segfault` ![image](https://hackmd.io/_uploads/ryqemLO9kl.png) ``` stack = 0x7fffffffde81 saved rip = 0x7fffffffde98 -> Nếu flag quá dài thì hoàn toàn có thể gây ra buffer overflow ``` ## Bypass :::warning - Câu hỏi đặt ra bây giờ là có thể bypass được đoạn này không ?? -> Chúng ta sẽ xem địa chỉ stack này lấy từ đâu :::