我遇到了一个整数溢出问题,设法解决了,但只能通过反复试验来解决。
由于这是整数溢出问题,所以我写了一些代码来打印出缓冲区。 缓冲区的开头是存储array [0]的地址。 然后,我开始将MAX_INT和MIN_INT值传递给程序。 我注意到当我将MIN_INT值传递给argv [1]时,它覆盖了缓冲区的开头。因此我传递了MIN_INT + 1值,并注意到它覆盖了缓冲区的第二个地址。从那里很容易解决。
问题是,我不明白为什么这样做。 在place_int_array函数中,当我将MIN_INT + 6的值传递给argv [1]时,if语句“ if(slot> 3)”返回false,因此转到“ else”语句,因为MIN_INT + 6为为负值,因此小于或等于3,因此广告位的值被解释为“ MIN_INT + 6”值。 但是在“ else”语句中,array [slot]在缓冲区中上升到“ array [0] +6”的地址,这意味着,作为“ array”索引的slot的值被解释为“ 6”。 / p>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int secretCode = 10;
void dump_stack(void **stack, size_t n, void **arg0) {
printf("Stack dump (stack at %p, len %d): \n", stack, n);
//if the buffer if not aligned on a dword boundary - force alignment of print
void** alignedStack = (void**)(((unsigned int)stack >> 2) << 2);
while (n-- > 0) {
printf("0x%08x: 0x%08x", (unsigned int)&alignedStack[n], (unsigned int)alignedStack[n]);
if (n == 0) {
printf(" (beginning of buffer)");
}
if (&alignedStack[n] == arg0 + 6+1) {
printf(" (main first argument (argc))");
}
if (&alignedStack[n] == arg0 + 6) {
printf(" (main return address (saved eip))");
}
if (&alignedStack[n] == arg0) {
printf(" (second argument)");
}
if (&alignedStack[n] == arg0 - 1) {
printf(" (first argument)");
}
if (&alignedStack[n] == arg0 - 2) {
printf(" (place_int_array return address (saved eip))");
}
if (&alignedStack[n] == arg0 - 3) {
printf(" (saved ebp)");
}
printf("\n");
}
}
void print_secret_code() {
//TODO - call this from somewhere...
printf("You get better at this stuff, ah?! Go get your treasure, the code is %d\n", secretCode);
}
void fill_array(int array[], size_t len) {
unsigned int i;
for (i = 0; i < len; i++) {
array[i] = i * 10;
}
}
void place_int_array(int slot, int value) {
int array[3];
printf("place_int_array ret address: %p\n", __builtin_return_address(0));
printf("&array: %p\n", &array);
printf("slot: %d\n", slot);
printf("&array[slot]: %p\n", &array[slot]);
fill_array(array, sizeof(array) / sizeof(array[0]));
printf("slot: %d\n", slot);
if (slot > 3) //we stop bad guys here
printf("safe number is greater than 3, out of bounds.\n");
else {
array[slot] = value;
dump_stack((void **) array, 30, (void **) &value);
printf("filled safe %d with %d.\n", slot, value);
}
return;
}
int main(int argc, char **argv) {
printf("print_secret_code function = %p\n", print_secret_code);
if (argc != 3) {
printf("Welcome to Alladin's magic cave!\n");
printf("Enter the secret number into the right safe and get the treasure cave entrance code!\n");
printf("syntax: %s [SAFE NUMBER] [SECRET NUMBER]\n", argv[0]);
//TEMP TEMP - for debugging only
printf("print_secret_code function = %p\n", print_secret_code);
}
else
{
place_int_array(atoi(argv[1]), atoi(argv[2]));
}
exit(0);
}
以下是输出:
[lab8_IntegerOverflow]$ ./aladdinSafe -2147483648 1
print_secret_code function = 0x804864b
place_int_array ret address: 0x804880d
&array: 0xffbd8464
slot: -2147483648
&array[slot]: 0xffbd8464
slot: -2147483648
Stack dump (stack at 0xffbd8464, len 30):
0xffbd84d8: 0xbca9b1bd
0xffbd84d4: 0x72f595ac
0xffbd84d0: 0x00000000
0xffbd84cc: 0x00000000
0xffbd84c8: 0x00000000
0xffbd84c4: 0xf773c000
0xffbd84c0: 0x0804825c
0xffbd84bc: 0x0804a01c
0xffbd84b8: 0xffbd84d4
0xffbd84b4: 0xffbd8534
0xffbd84b0: 0x00000003
0xffbd84ac: 0xf7765cca
0xffbd84a8: 0xffbd8544
0xffbd84a4: 0xffbd8534
0xffbd84a0: 0x00000003 (main first argument (argc))
0xffbd849c: 0xf75aaaf3 (main return address (saved eip))
0xffbd8498: 0x00000000
0xffbd8494: 0xf773c000
0xffbd8490: 0x08048820
0xffbd848c: 0xf773c000
0xffbd8488: 0x0804882b
0xffbd8484: 0x00000001 (second argument)
0xffbd8480: 0x80000000 (first argument)
0xffbd847c: 0x0804880d (place_int_array return address (saved eip))
0xffbd8478: 0xffbd8498 (saved ebp)
0xffbd8474: 0xf7778938
0xffbd8470: 0xffbda5cb
0xffbd846c: 0x00000014 //address of array[2], filled at "fill_array" function with 2*10 = 20 = 0x14
0xffbd8468: 0x0000000a //address of array[1], filled at "fill_array" function with 1*10 = 10 = 0xa
0xffbd8464: 0x00000001 (beginning of buffer) //address of array[0], overwritten with argv[2] = 1.
filled safe -2147483648 with 1.
我希望如果将“ slot> 3”的插槽解释为MIN_INT + 6,那么“ array [slot]”的插槽将被解释为相同。
为什么插槽的值会根据用途改变?
答案 0 :(得分:0)
@IanAbbott知道了。 整数“ slot”在“ array [slot]”下溢,因为编译器将“ slot”乘以4。 因此,当INT_MIN乘以4时-它的下限为0。 当slot = INT_MIN + 6时,当尝试计算array [slot]的地址时,它首先将slot乘以4,等于(INT_MIN + 6)* 4,下溢为0 + 6 * 4,这恰好是地址“ array [0]”上方有6个地址。 但在此语句“ if(slot> 3)”中-slot是一个负数,即INT_MIN + 6,因此“ slot> 3”返回false。