# 整数オーバーフロー {% hint style="success" %} AWSハッキングの学習と練習:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ GCPハッキングの学習と練習:[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
HackTricksをサポートする * [**サブスクリプションプラン**](https://github.com/sponsors/carlospolop)をチェック! * 💬 [**Discordグループ**](https://discord.gg/hRep4RUj7f)に参加するか、[**telegramグループ**](https://t.me/peass)に参加するか、**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**をフォロー**してください。 * **HackTricks**と**HackTricks Cloud**のgithubリポジトリにPRを提出して、ハッキングトリックを共有してください。
{% endhint %} ## 基本情報 **整数オーバーフロー**の中心にあるのは、コンピュータプログラミングのデータ型の**サイズ**とデータの**解釈**によって課せられる制限です。 例えば、**8ビット符号なし整数**は、**0から255**までの値を表すことができます。8ビット符号なし整数に256の値を格納しようとすると、その格納容量の制限により、0にラップアラウンドします。同様に、**16ビット符号なし整数**は、**0から65,535**までの値を保持できますが、65,535に1を加えると値が0に戻ります。 さらに、**8ビット符号付き整数**は、**-128から127**までの値を表すことができます。これは、1ビットが符号(正または負)を表すために使用され、残りの7ビットが大きさを表すためです。最も負の数は**-128**(バイナリ `10000000`)で表され、最も正の数は**127**(バイナリ `01111111`)です。 ### 最大値 潜在的な**Web脆弱性**に関して、サポートされる最大値を知っておくことは非常に興味深いです: {% tabs %} {% tab title="Rust" %} ```rust fn main() { let mut quantity = 2147483647; let (mul_result, _) = i32::overflowing_mul(32767, quantity); let (add_result, _) = i32::overflowing_add(1, quantity); println!("{}", mul_result); println!("{}", add_result); } ``` {% endtab %} {% tab title="C" %} 整数オーバーフローは、整数演算において結果が変数のデータ型の範囲を超える場合に発生します。これは、攻撃者が意図しないコードパスを実行したり、メモリの破壊を引き起こしたりする可能性がある深刻なセキュリティリスクです。整数オーバーフローは、特にC言語などの低レベル言語でプログラミングされたアプリケーションでよく見られます。適切な入力検証や境界値チェックを行うことで、整数オーバーフローによる脆弱性を防ぐことが重要です。 {% endtab %} ```c #include #include int main() { int a = INT_MAX; int b = 0; int c = 0; b = a * 100; c = a + 1; printf("%d\n", INT_MAX); printf("%d\n", b); printf("%d\n", c); return 0; } ``` ## 例 ### 純粋なオーバーフロー charをオーバーフローさせたため、印刷される結果は0になります: ```c #include int main() { unsigned char max = 255; // 8-bit unsigned integer unsigned char result = max + 1; printf("Result: %d\n", result); // Expected to overflow return 0; } ``` ### 符号付きから符号なしへの変換 ユーザー入力から読み取られた符号付き整数が、適切な検証なしに符号なし整数として扱われる状況を考えてみましょう。 ```c #include int main() { int userInput; // Signed integer printf("Enter a number: "); scanf("%d", &userInput); // Treating the signed input as unsigned without validation unsigned int processedInput = (unsigned int)userInput; // A condition that might not work as intended if userInput is negative if (processedInput > 1000) { printf("Processed Input is large: %u\n", processedInput); } else { printf("Processed Input is within range: %u\n", processedInput); } return 0; } ``` ### その他の例 * [https://guyinatuxedo.github.io/35-integer\_exploitation/int\_overflow\_post/index.html](https://guyinatuxedo.github.io/35-integer\_exploitation/int\_overflow\_post/index.html) * パスワードのサイズを格納するのに1バイトしか使用されていないため、オーバーフローさせて4の長さだと思わせることが可能で、実際には260であるため、長さチェック保護をバイパスできます。 * [https://guyinatuxedo.github.io/35-integer\_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer\_exploitation/puzzle/index.html) * いくつかの数値が与えられた場合、z3を使用して最初の数値に掛けると第二の数値が得られる新しい数値を見つける: ``` (((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569) ``` * [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/) * パスワードのサイズを格納するのに1バイトしか使用されていないため、オーバーフローさせて4の長さだと思わせることが可能で、実際には260であるため、長さチェック保護をバイパスし、スタック内の次のローカル変数を上書きして両方の保護をバイパスできます。 ## ARM64 これはARM64でも変わりません。[**このブログポスト**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)で確認できます。