3.8 KiB
整数溢出
{{#include ../banners/hacktricks-training.md}}
基本信息
在整数溢出的核心是计算机编程中数据类型的大小所施加的限制和数据的解释。
例如,一个8位无符号整数可以表示从0到255的值。如果你尝试在8位无符号整数中存储值256,由于其存储容量的限制,它会回绕到0。同样,对于一个16位无符号整数,它可以容纳从0到65,535的值,将1加到65,535会将值回绕到0。
此外,一个8位有符号整数可以表示从**-128到127的值。这是因为一个位用于表示符号(正或负),剩下7个位用于表示大小。最小的负数表示为-128**(二进制10000000
),最大的正数是127(二进制01111111
)。
最大值
对于潜在的网络漏洞,了解最大支持值是非常有趣的:
{{#tabs}} {{#tab name="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 name="C"}}
#include <stdio.h>
#include <limits.h>
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;
}
{{#endtab}} {{#endtabs}}
示例
纯溢出
打印的结果将是 0,因为我们溢出了 char:
#include <stdio.h>
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;
}
Signed to Unsigned Conversion
考虑一种情况,其中从用户输入读取一个有符号整数,然后在一个将其视为无符号整数的上下文中使用,而没有进行适当的验证:
#include <stdio.h>
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
-
仅使用 1B 来存储密码的大小,因此可能会溢出并使其认为长度为 4,而实际上是 260,以绕过长度检查保护
-
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/
- 仅使用 1B 来存储密码的大小,因此可能会溢出并使其认为长度为 4,而实际上是 260,以绕过长度检查保护并在栈中覆盖下一个局部变量,从而绕过这两种保护
ARM64
这在 ARM64 中没有变化,正如你在 这篇博客文章中看到的。
{{#include ../banners/hacktricks-training.md}}