# 2025-12-15_"Flag Printer 2100": 251217
{%preview https://alpacahack.com/daily/challenges/flag-printer-2100 %}
Level: Medium
Type: Rev
solved day: 2025,12,17
## solution
```sh
$ file ./print_flag
./print_flag: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=4779e9456734b25b443894084d1ef12e88a94719, for GNU/Linux 3.2.0, not stripped
$ ldd ./print_flag
/work/fakesleep.so (0x00007fffff7bb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fffff5c2000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffffffc8000)
$ strings -a ./print_flag | egrep -i 'flag|sleep|show_flag|year|2100|75'
sleep
I'll sleep for 75 years...
show_flag
sleep@GLIBC_2.2.5
```
```
# sleep/nanosleep を無効化する共有ライブラリを作成
$ cat > fakesleep.c <<'EOF'
#define _GNU_SOURCE
#include <time.h>
#include <unistd.h>
unsigned int sleep(unsigned int s){ return 0; }
int nanosleep(const struct timespec *req, struct timespec *rem){ return 0; }
EOF
$ gcc -shared -fPIC -o fakesleep.so fakesleep.c
# 実行(LD_PRELOAD と実行コマンドを同じ行で)
$ chmod +x print_flag
$ export LD_PRELOAD=$PWD/fakesleep.so
$ ./print_flag
I'll sleep for 75 years...
Alpaca{G00d_Morning_AlpacaH4ck!}
````
## How I thought.
```sh
# 重要な観察
file # → ELF 64-bit, PIE, dynamically linked
ldd # → libc.so.6 に依存(GLIBC)→ LD_PRELOAD が効く
strings # → "sleep" / "I'll sleep for 75 years..." / "show_flag"
```
* **仮説**: 「75年後にフラグ」= 実装は `sleep()` / `nanosleep()` による**長時間待機** → その後 `show_flag`
* **戦術**: 動的リンクなので **`LD_PRELOAD`** で `sleep()` / `nanosleep()` を**即リターン**に差し替え、待機をスキップして**フラグ表示**
* **ポイント**:
* `LD_PRELOAD=<so> ./binary` の形で**同じ行**に実行コマンドを書く。
* もし時刻比較型(2100年判定)なら、`time()/clock_gettime()` を **2100‑01‑01** の epoch(`4102444800`)に偽装するフックで突破可能
* 静的リンク/フック不可なら、`objdump/gdb` で `sleep` 呼び出し直前の **`edi=0`** にして `sleep(0)` にする(または条件ジャンプ反転で直接フラグ側へ)