CTF Pwn

# 目次

- Setup
    - [Kali Setup](https://qiita.com/kannkyo/items/3c29df1c2df60926d47d)
- [Pwn](https://qiita.com/kannkyo/items/92fa2e19ad4f31141190)
- [Stegano](https://qiita.com/kannkyo/items/776996b9b7fe1779690c)
- Web
    - [Web Awesome Injection](https://qiita.com/kannkyo/items/b334bca02c8a24331615)

# 偵察

## 実行スクリプト

### パラメータ設定

```bash
FILE=
```

### スクリプト作成

```python
tee main.py <<EOF
from pwn import *

context.log_level = 'debug'

# Settings
FILE = sys.argv[1]
# context(arch='powerpc')

# elf
elf = ELF(FILE)
EOF
```

### 実行

```bash
file $FILE
python main.py $FILE
checksec --file=$FILE --format=json | jq
```

## 出力例

```
$ file $FILE
python main.py $FILE

file_name: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=xxx, for GNU/Linux 3.2.0, not stripped
[*] '/path/to/elf'
    Arch:       amd64-64-little
    RELRO:      Full RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    FORTIFY:    Enabled
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No

checksec --file=$FILE --format=json | jq
{
  "file_name": {
    "relro": "partial",
    "canary": "yes",
    "nx": "yes",
    "pie": "no",
    "rpath": "no",
    "runpath": "no",
    "symbols": "yes",
    "fortify_source": "no",
    "fortified": "0",
    "fortify-able": "0"
  }
}
```


| 制御機構                              | 値              | pwntools | checksec | 意味                                           |
| ------------------------------------- | --------------- | -------- | -------- | ---------------------------------------------- |
| RELRO (RELocation Read Only)          | No/Partial/Full | x        | x        | 書き込み禁止                                   |
| STACK CANARY                          | Yes/No          | x        | x        | 開始時にスタックにランダム値（カナリヤ）を格納 |
| NX (No eXecute)                       | Yes/No          | x        | x        | スタック領域のコード実行禁止                   |
| PIE (Position Independent Executable) | Yes/No          | x        | x        | 実行ファイル配置アドレスをランダム化           |
| RPATH                                 | Yes/No          | -        | x        | 実行ファイル共有ライブラリのサーチリストを格納 |
| RUNPATH                               | Yes/No          | -        | x        | RPATH 　＋　LD_LIBRALY_PATH優先                |
| FORTIFY                               | Yes/No          | -        | x        | GCC、GLIBC のセキュリティ機能                  |
| SHSTK (Shadow Stack)                  |                 | x        | -        | リターンアドレス監視 (Intel)                   |
| IBT (Indirect BranchTracking)         |                 | x        | -        | 不正間接分岐監視 (Intel)                       |
| Stripped                              | Yes/No          | x        | -        |                                                |

### PIE

絶対アドレスは変わるが、相対アドレスは変わらない。
どこかの関数の絶対アドレスがわかれば、任意の関数の絶対アドレスを算出可能。

## 詳細調査

### アドレス一覧

```python
from pwn import *

elf = ELF('/home/kali/Desktop/download/vuln')

# すべての関数のアドレスを表示
for func in sorted(elf.symbols):
    try:
        print(f'{func}: {hex(elf.symbols[func])}')
    except:
        pass
```

# Fuzzing

```python
import click
from pwn import *


def pre(server: remote, timeout: int):
    pass


def post(server: remote, timeout: int):
    pass


@click.command()
@click.option('-i', '--ip', prompt='IP address', help='The IP address to fuzz.')
@click.option('-p', '--port', prompt='Port number', type=int, help='The port number to fuzz.')
@click.option('-s', '--step', default=100, help='Step size for fuzzing.')
@click.option('-t', '--timeout', default=5, help='Timeout for the connection.')
@click.option('--verbose', is_flag=True, help='Enable verbose output.')
@click.option('--debug', is_flag=True, help='Enable debug output.')
def main(ip: str, port: str, step: int, timeout: int, verbose: bool, debug: bool):  # noqa E501
    click.echo("[+] Fuzzing to OVERFLOW")

    for counter in range(step, 30 * step, step):
        payload = "A" * counter + '\n'
        payload = payload.encode('utf-8')

        s = remote(ip, port)
        try:
            r = s.recv(1024, timeout=timeout)
            if debug:
                click.echo(r)

            # pre function
            pre(s, timeout)
            if debug:
                click.echo(r)
                
            # send payload
            click.echo("Fuzzing with %s bytes" % len(payload))
            s.send(payload)
            r = s.recv(1024, timeout=timeout)
            if verbose or debug:
                click.echo(r)

            # post function
            post(s, timeout)
            if debug:
                click.echo(r)

        except Exception as e:
            click.echo("Could not connect to " + ip + ":" + str(port))
            click.echo("Error: " + str(e), err=True)
            sys.exit(0)
        finally:
            s.close()

        time.sleep(1)


if __name__ == '__main__':
    main()

```