同一值的Int值不同?

时间:2019-05-07 11:47:21

标签: c integer-overflow stack-smash

我遇到了一个整数溢出问题,设法解决了,但只能通过反复试验来解决。

由于这是整数溢出问题,所以我写了一些代码来打印出缓冲区。 缓冲区的开头是存储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]”的插槽将被解释为相同。

为什么插槽的值会根据用途改变?

1 个答案:

答案 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。