You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

彩票游戏代码漏洞利用原理探究:输入16位数字为何能中奖?

问题描述

我在对一段C语言彩票游戏代码做漏洞利用时,发现输入16个不同数字就能中奖。我查看了entry和results数组的内存地址,但搞不懂二者的关联,也不确定是不是和漏洞有关。想问问这个现象是不是内存位置导致的,具体原理是什么?

目标代码

#include <stdio.h>
#include <stdlib.h>
#include<time.h>

int main(int argc, char *argv[]) {
  int entry[6];
  int results[6];
  int i = 0, tmp = 0;

  /* Generate power balls */                                                                   
  srand(time(NULL));                                                                          
  for (int i = 0; i < 6; i++) {                                                       
    results[i] = rand() % 99;                                                           
  }


  printf("RULE: You are to enter a sequence of six two-digit numbers between 10 and 99.\n");
  printf("  - The numbers should be separated by a single space.\n");
  printf("  - The seventh number should be -1, indicating the completion of the sequence\n");
  printf("Enter the numbers:\n");
  while(tmp != -1) {
    scanf("%d", &tmp);
    if (tmp == -1) break;
    entry[i] = tmp;
    i++; 
  }

  /* Check results */
  int match = 0;
  for (int i = 0; i < 6; i++) {
    printf("The lottery number is: %d\n", results[i]);
    printf("Your guess is: %d\n", entry[i]);
    if (results[i] == entry[i]) {
      match++;
    }
  }

  if (match != 6){
    printf("Unfortunately, there has been a mismatch! Better luck next time!\n");
  }
  else {
    printf("Congratulations, all the numbers match! You have won a gazillion dollars\n");
  }
  return 0;
}
漏洞原理分析

这个现象确实是栈内存布局越界覆盖导致的,核心逻辑拆解如下:

1. 局部变量的栈内存排列规律

C语言中,函数的局部变量会被编译器分配在栈空间中,通常按声明顺序反向排列(不同编译器细节可能有差异,但核心逻辑一致)。这段代码里,main函数的局部变量栈布局(从高地址到低地址)大致为:

  • tmp(int类型,占4字节)
  • i(int类型,占4字节)
  • results[6](6个int,共24字节)
  • entry[6](6个int,共24字节)

2. 无边界限制的数组越界写入

代码的输入循环完全没有限制i的最大值:只要输入的不是-1,就会持续执行entry[i] = tmp; i++;。而entry数组只有6个元素,合法下标范围是0-5。当i超过5后,写入操作就会越界,覆盖entry数组之后的栈内存——也就是results数组的空间。

3. 输入16个数字中奖的具体逻辑

我们可以通过内存偏移计算来理解:

  • 当i从6开始,每输入一个数字,就会覆盖results数组的一个元素(i=6对应results[0],i=7对应results[1],直到i=11覆盖results[5])。
  • 继续输入数字,i会超过11,开始覆盖i和tmp自身的内存。当i被覆盖为0后,后续输入的数字会重新从entry[0]开始写入,把之前的entry数组内容也覆盖成新输入的值。
  • 最后输入-1结束循环时,entry和results数组的6个元素已经被你输入的数字统一覆盖成相同值,所以比对时match等于6,直接触发中奖逻辑。

本质就是利用无限制的数组越界写入,把原本随机生成的results数组改成和entry数组完全一致的内容,从而实现“全匹配”中奖。


内容的提问来源于stack exchange,提问作者user19980968

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:45:57