mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
88 lines
6.0 KiB
Markdown
88 lines
6.0 KiB
Markdown
# DDexec / EverythingExec
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|
||
|
||
## コンテキスト
|
||
|
||
Linuxでは、プログラムを実行するためには、それがファイルとして存在し、ファイルシステム階層を通じて何らかの方法でアクセス可能でなければなりません(これは`execve()`の動作方法です)。このファイルはディスク上またはRAM(tmpfs、memfd)に存在する可能性がありますが、ファイルパスが必要です。これにより、Linuxシステム上で実行されるものを制御することが非常に簡単になり、脅威や攻撃者のツールを検出したり、彼らが何かを実行しようとするのを防ぐことが容易になります(例:特権のないユーザーが実行可能ファイルをどこにでも配置することを許可しない)。
|
||
|
||
しかし、この技術はすべてを変えるために存在します。望むプロセスを開始できない場合... **既存のプロセスをハイジャックします**。
|
||
|
||
この技術により、**読み取り専用、noexec、ファイル名のホワイトリスト、ハッシュのホワイトリストなどの一般的な保護技術を回避することができます...**
|
||
|
||
## 依存関係
|
||
|
||
最終的なスクリプトは、以下のツールに依存しており、攻撃しているシステムでアクセス可能である必要があります(デフォルトでは、これらはどこにでも存在します):
|
||
```
|
||
dd
|
||
bash | zsh | ash (busybox)
|
||
head
|
||
tail
|
||
cut
|
||
grep
|
||
od
|
||
readlink
|
||
wc
|
||
tr
|
||
base64
|
||
```
|
||
## 技術
|
||
|
||
プロセスのメモリを任意に変更できる場合、そのプロセスを乗っ取ることができます。これは、既存のプロセスをハイジャックし、別のプログラムに置き換えるために使用できます。これを達成するには、`ptrace()`システムコールを使用するか(これはシステムでシステムコールを実行する能力が必要です)、または、より興味深いことに、`/proc/$pid/mem`に書き込むことができます。
|
||
|
||
ファイル`/proc/$pid/mem`は、プロセスの全アドレス空間の1対1のマッピングです(_e. g._ `0x0000000000000000`から`0x7ffffffffffff000`までのx86-64)。これは、オフセット`x`でこのファイルから読み書きすることは、仮想アドレス`x`の内容を読み取ったり変更したりすることと同じであることを意味します。
|
||
|
||
さて、私たちは直面する4つの基本的な問題があります:
|
||
|
||
- 一般的に、ファイルのルートとプログラムの所有者のみがそれを変更できます。
|
||
- ASLR。
|
||
- プログラムのアドレス空間にマッピングされていないアドレスに読み書きしようとすると、I/Oエラーが発生します。
|
||
|
||
これらの問題には、完璧ではないものの良い解決策があります:
|
||
|
||
- ほとんどのシェルインタプリタは、子プロセスによって継承されるファイルディスクリプタの作成を許可します。書き込み権限を持つ`mem`ファイルを指すfdを作成できます... そのfdを使用する子プロセスはシェルのメモリを変更できるようになります。
|
||
- ASLRは問題ではありません。シェルの`maps`ファイルやprocfsの他のファイルをチェックすることで、プロセスのアドレス空間に関する情報を得ることができます。
|
||
- したがって、ファイルに対して`lseek()`を行う必要があります。シェルからは、悪名高い`dd`を使用しない限り、これを行うことはできません。
|
||
|
||
### 詳細に
|
||
|
||
手順は比較的簡単で、理解するために特別な専門知識は必要ありません:
|
||
|
||
- 実行したいバイナリとローダーを解析して、必要なマッピングを特定します。次に、広義には、カーネルが`execve()`への各呼び出し時に行うのと同じ手順を実行する「シェル」コードを作成します:
|
||
- そのマッピングを作成します。
|
||
- バイナリをそれに読み込みます。
|
||
- 権限を設定します。
|
||
- 最後に、プログラムの引数でスタックを初期化し、ローダーが必要とする補助ベクタを配置します。
|
||
- ローダーにジャンプし、プログラムに必要なライブラリをロードさせます。
|
||
- 実行中のシステムコールから戻るアドレスを`syscall`ファイルから取得します。
|
||
- その場所を上書きします。これは実行可能であり、シェルコードで上書きします(`mem`を通じて書き込み不可のページを変更できます)。
|
||
- 実行したいプログラムをプロセスのstdinに渡します(その「シェル」コードによって`read()`されます)。
|
||
- この時点で、ローダーがプログラムに必要なライブラリをロードし、それにジャンプするのはローダーの役割です。
|
||
|
||
**ツールは** [**https://github.com/arget13/DDexec**](https://github.com/arget13/DDexec) **をチェックしてください**
|
||
|
||
## EverythingExec
|
||
|
||
`dd`の代替手段はいくつかあり、そのうちの1つである`tail`は、現在`mem`ファイルを`lseek()`するために使用されるデフォルトのプログラムです(これは`dd`を使用する唯一の目的でした)。これらの代替手段は:
|
||
```bash
|
||
tail
|
||
hexdump
|
||
cmp
|
||
xxd
|
||
```
|
||
`SEEKER` 変数を設定することで、使用するシーカーを変更できます。_例_:
|
||
```bash
|
||
SEEKER=cmp bash ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)
|
||
```
|
||
スクリプトに実装されていない別の有効なシーカーを見つけた場合は、`SEEKER_ARGS` 変数を設定して使用することができます:
|
||
```bash
|
||
SEEKER=xxd SEEKER_ARGS='-s $offset' zsh ddexec.sh ls -l <<< $(base64 -w0 /bin/ls)
|
||
```
|
||
ブロックする、EDR。
|
||
|
||
## 参考文献
|
||
|
||
- [https://github.com/arget13/DDexec](https://github.com/arget13/DDexec)
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|