【题目】Are overflows just a stack concern?
c源代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FLAGSIZE_MAX 64
// amount of memory allocated for input_data
#define INPUT_DATA_SIZE 5
// amount of memory allocated for safe_var
#define SAFE_VAR_SIZE 5
int num_allocs;
char *safe_var;
char *input_data;
void check_win() {
if (strcmp(safe_var, "bico") != 0) {
printf("\nYOU WIN\n");
// Print flag
char buf[FLAGSIZE_MAX];
FILE *fd = fopen("flag.txt", "r");
fgets(buf, FLAGSIZE_MAX, fd);
printf("%s\n", buf);
fflush(stdout);
exit(0);
} else {
printf("Looks like everything is still secure!\n");
printf("\nNo flage for you :(\n");
fflush(stdout);
}
}
void print_menu() {
printf("\n1. Print Heap:\t\t(print the current state of the heap)"
"\n2. Write to buffer:\t(write to your own personal block of data "
"on the heap)"
"\n3. Print safe_var:\t(I'll even let you look at my variable on "
"the heap, "
"I'm confident it can't be modified)"
"\n4. Print Flag:\t\t(Try to print the flag, good luck)"
"\n5. Exit\n\nEnter your choice: ");
fflush(stdout);
}
void init() {
printf("\nWelcome to heap0!\n");
printf(
"I put my data on the heap so it should be safe from any tampering.\n");
printf("Since my data isn't on the stack I'll even let you write whatever "
"info you want to the heap, I already took care of using malloc for "
"you.\n\n");
fflush(stdout);
input_data = malloc(INPUT_DATA_SIZE);
strncpy(input_data, "pico", INPUT_DATA_SIZE);
safe_var = malloc(SAFE_VAR_SIZE);
strncpy(safe_var, "bico", SAFE_VAR_SIZE);
}
void write_buffer() {
printf("Data for buffer: ");
fflush(stdout);
scanf("%s", input_data);
}
void print_heap() {
printf("Heap State:\n");
printf("+-------------+----------------+\n");
printf("[*] Address -> Heap Data \n");
printf("+-------------+----------------+\n");
printf("[*] %p -> %s\n", input_data, input_data);
printf("+-------------+----------------+\n");
printf("[*] %p -> %s\n", safe_var, safe_var);
printf("+-------------+----------------+\n");
fflush(stdout);
}
int main(void) {
// Setup
init();
print_heap();
int choice;
while (1) {
print_menu();
int rval = scanf("%d", &choice);
if (rval == EOF){
exit(0);
}
if (rval != 1) {
//printf("Invalid input. Please enter a valid choice.\n");
//fflush(stdout);
// Clear input buffer
//while (getchar() != '\n');
//continue;
exit(0);
}
switch (choice) {
case 1:
// print heap
print_heap();
break;
case 2:
write_buffer();
break;
case 3:
// print safe_var
printf("\n\nTake a look at my variable: safe_var = %s\n\n",
safe_var);
fflush(stdout);
break;
case 4:
// Check for win condition
check_win();
break;
case 5:
// exit
return 0;
default:
printf("Invalid choice\n");
fflush(stdout);
}
}
}
【解题】观察源码发现漏洞点在
if (strcmp(safe_var, "bico") != 0)
init()初始化函数中的safe_var变量内容是bico,input_data变量内容是pico,要想让程序输出flag需要令safe_var≠bico,
safe_var内容没有渠道直接改变,但程序提供了heap的地址结构,如下:

我们发现,
input_data占据地址范围是0x5a4c332f22b0到0x5a4c332f22cf,共32个地址,对应32个字节,即可容纳32个字符
一旦输入超过32个字节就会导致堆溢出,多余的输入内容会覆盖下一个地址内容,即0x5a4c332f22d0处的bico就会被覆盖。
这就达到了我们的目的,修改safe_var处的内容。
因此我们执行该程序,

选择1查看当前堆状态,如下:

选择2修改input_data内容为32个A字符:
![]()
由于scanf("%s")语句会默认在末尾添加一个“\0”,因此表面上我们输入了32个字符,实际是32个A加上1个"\0",而第33个字符"\0"此时溢出给了下一个地址
0x5a4c332f22d0,此时我们再次选择1查看当前heap状态,如下:

(注意,C 字符串在显示时,遇到"\0"就立刻停止,因此,虽然只溢出了一个位置的字符,但因为这个字符就是"\0",所有后面所有字符都不再显示)
此时的safe_var变量已经被溢出的"\0"覆盖,满足了flag的输出条件safe_var≠bico,
选择4选项,print flag:

OVER
浙公网安备 33010602011771号