.. | ||
ret2win | ||
stack-shellcode | ||
pointer-redirecting.md | ||
README.md | ||
ret2win.md | ||
stack-pivoting-ebp2ret-ebp-chaining.md | ||
stack-shellcode.md | ||
uninitialized-variables.md |
スタックオーバーフロー
htARTE(HackTricks AWS Red Team Expert) を通じて、ゼロからヒーローまでAWSハッキングを学ぶ!
HackTricks をサポートする他の方法:
- HackTricks で企業を宣伝したいまたは HackTricks をPDFでダウンロードしたい場合は、SUBSCRIPTION PLANSをチェックしてください!
- 公式PEASS&HackTricksスワッグを入手する
- The PEASS Familyを発見し、独占的なNFTsのコレクションを見つける
- **💬 Discordグループに参加するか、telegramグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- ハッキングトリックを共有するために、PRを HackTricks および HackTricks Cloud のGitHubリポジトリに提出してください。
スタックオーバーフローとは
スタックオーバーフローは、プログラムがスタックに割り当てられたデータよりも多くのデータを書き込むと発生する脆弱性です。この余分なデータは、隣接するメモリ領域を上書きし、有効なデータの破損、制御フローの混乱、および悪意のあるコードの実行を引き起こす可能性があります。この問題は、入力に対して境界チェックを実行しない安全でない関数の使用によってしばしば発生します。
この上書きの主な問題は、保存された命令ポインタ(EIP/RIP)および保存されたベースポインタ(EBP/RBP)が前の関数に戻るためにスタックに保存されていることです。したがって、攻撃者はこれらを上書きしてプログラムの実行フローを制御することができます。
この脆弱性は通常、関数が割り当てられた量よりも多くのバイトをスタックにコピーするために発生します。そのため、スタックの他の部分を上書きできます。
このような脆弱性に対して一般的な関数には、strcpy
、strcat
、sprintf
、gets
などがあります。また、fgets
、**read
、memcpy
**などの長さ引数を取る関数は、指定された長さが割り当てられた長さよりも大きい場合に脆弱な方法で使用される可能性があります。
たとえば、次の関数は脆弱な可能性があります:
void vulnerable() {
char buffer[128];
printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer);
}
スタックオーバーフローのオフセットを見つける
スタックオーバーフローを見つける最も一般的な方法は、非常に大きな入力を与えることです(例:python3 -c 'print("A"*1000)'
)そして、アドレス 0x41414141
にアクセスしようとしました と示す Segmentation Fault
が期待されます。
さらに、スタックオーバーフローの脆弱性が見つかったら、リターンアドレスを上書きできるオフセットを見つける必要があります。これには通常、De Bruijn sequence が使用されます。これは、サイズ k のアルファベットと長さ n の部分列が与えられた場合、すべての可能な長さ n の部分列が連続した部分列として正確に一度だけ現れる 循環列です。
これにより、EIP を制御するために必要なオフセットを手動で特定する必要がなくなり、これらのシーケンスの1つをパディングとして使用し、それを上書きしたバイトのオフセットを見つけることができます。
これには、pwntools を使用することができます:
from pwn import *
# Generate a De Bruijn sequence of length 1000 with an alphabet size of 256 (byte values)
pattern = cyclic(1000)
# This is an example value that you'd have found in the EIP/IP register upon crash
eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}")
またはGEF:
#Patterns
pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp
スタックオーバーフローの悪用
オーバーフロー中(オーバーフローサイズが十分に大きいと仮定)、スタック内のローカル変数の値を上書きすることができ、保存されたEBP/RBPとEIP/RIP(またはそれ以上)に到達するまで続けることができます。
この種の脆弱性を悪用する最も一般的な方法は、戻り値アドレスを変更して、関数が終了するときに制御フローがユーザーが指定した場所にリダイレクトされるようにすることです。
ただし、他のシナリオでは、単にスタック内のいくつかの変数の値を上書きするだけで、悪用が可能になることがあります(簡単なCTFチャレンジなど)。
Ret2win
この種のCTFチャレンジでは、バイナリ内に呼び出されない関数があり、それを呼び出して勝利する必要があることがあります。これらのチャレンジでは、戻り値アドレスを上書きするオフセットを見つけ、呼び出す関数のアドレスを見つけるだけでよく(通常、ASLRは無効になっている)、脆弱な関数が戻るときには、隠された関数が呼び出されます:
{% content-ref url="ret2win/" %} ret2win {% endcontent-ref %}
スタックシェルコード
このシナリオでは、攻撃者はスタックにシェルコードを配置し、制御されたEIP/RIPを悪用してシェルコードにジャンプし、任意のコードを実行することができます:
{% content-ref url="stack-shellcode/" %} stack-shellcode {% endcontent-ref %}
ROPおよびRet2...テクニック
このテクニックは、前述のテクニックの主要な保護をバイパスするための基本的なフレームワークです:実行可能スタック(NX)がない。これにより、バイナリ内の既存の命令を悪用して任意のコマンドを実行することで、他のいくつかのテクニック(ret2lib、ret2syscallなど)を実行できます:
{% content-ref url="../rop-return-oriented-programing/" %} rop-return-oriented-programing {% endcontent-ref %}
ヒープオーバーフロー
オーバーフローが必ずしもスタックにあるわけではなく、ヒープにあることもあります。例えば:
{% content-ref url="../heap/heap-overflow.md" %} heap-overflow.md {% endcontent-ref %}
保護の種類
脆弱性の悪用を防ぐためのいくつかの保護があります。詳細は以下を参照してください:
{% content-ref url="../common-binary-protections-and-bypasses/" %} common-binary-protections-and-bypasses {% endcontent-ref %}