我认为此代码可能容易受到缓冲区溢出的影响。我如何证明呢?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct _AC_DATA
{
int the;
int fan;
bool rec;
} AC_DATA, *PAC_DATA;
typedef struct _RADIO_DATA
{
char speakers_volume[4];
int station;
} RADIO_DATA, *PRADION_DATA;
typedef struct _GLOBAL_DATA
{
AC_DATA ac_data;
RADIO_DATA radio_data;
}GLOBAL_DATA, *PGLOBAL_DATA;
void good()
{
printf("Good!\n");
}
int update_volume(PGLOBAL_DATA pglobal_data, int index, int new_volume)
{
char arr[100];
if(index > 4)
{
printf("error invalid speaker.\n");
return -1;
}
printf("updating the speaker %d to volume %d\n", index, new_volume);
pglobal_data -> radio_data.speakers_volume[index] = new_volume;
}
void hacked()
{
printf("Hacked!\n");
}
int main () {
GLOBAL_DATA global_data = {0};
int index;
int new_volume;
printf("address of main: 0x%X.\n", main);
printf("enter volume index:");
scanf("%d", &index);
printf("enter new volume:");
scanf("%d", &new_volume);
update_volume(&global_data, index, new_volume);
return 0;
}
#1 楼
该错误位于update_volume
中。pglobal_data -> radio_data.speakers_volume[index] = new_volume;
index
是一个整数,它也可以取负值。理想情况下,您不应该能够访问数组中的-ve索引,因为它使您可以在数组前面的内存区域进行读/写操作。在这里,我们只是进行了一次检查以将其最大值限制为4,但是您可以对INT_MIN使用负整数并覆盖一个字节。对于
global_data
,它属于main的堆栈框架。访问负索引可以覆盖堆栈中update_volume
(在main中的某个地方)的返回地址中的一个字节。这使您可以跳到hacked
或good
函数。资源:在使用输入进行模糊测试时,使用ASAN来验证您的声明。
这是为此的ASAN转储。情况。
ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-6.0/bin/llvm-symbolizer ./test
address of main: 0xCA77FE6F.
enter volume index:-36
enter new volume:65
updating the speaker -36 to volume 65
=================================================================
==27759==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffebfb3ff98 at pc 0x55f1ca77fe6f bp 0x7ffebfb3fed0 sp 0x7ffebfb3fec0
WRITE of size 1 at 0x7ffebfb3ff98 thread T0
#0 0x55f1ca77fe6e in update_volume /tmp/re.c:39
#1 0x55f1ca78004b in main /tmp/re.c:57
#2 0x7f237a433b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#3 0x55f1ca77fcf9 in _start (/tmp/test+0xcf9)
Address 0x7ffebfb3ff98 is located in stack of thread T0 at offset 136 in frame
#0 0x55f1ca77fe7e in main /tmp/re.c:47
This frame has 3 object(s):
[32, 36) 'index'
[96, 100) 'new_volume'
[160, 180) 'global_data' <== Memory access at offset 136 underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /tmp/re.c:39 in update_volume
Shadow bytes around the buggy address:
0x100057f5ffa0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f5ffb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f5ffc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f5ffd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f5ffe0: 00 00 f1 f1 f1 f1 04 f2 f2 f2 f2 f2 f2 f2 04 f2
=>0x100057f5fff0: f2 f2 f2[f2]f2 f2 00 00 04 f2 00 00 00 00 00 00
0x100057f60000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f60010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f60020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f60030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100057f60040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==27759==ABORTING
如果这是家庭作业问题,请在发帖时注明。我们很乐意为您提供帮助,但如果您没有像注释中提到的@SYS_V所示显示任何进展/完成的研究,我们将不为您完成所有工作。
评论
为什么当我尝试插入volume_index -10和new_volume 65时会“将扬声器-10更新为音量65”?如果我喜欢示例-36和65,则会收到“将扬声器-36更新为音量65分段错误”
–d.buff
18-09-30在8:12
评论
将代码添加为文本@PawełŁukasik我添加了代码
这是家庭作业吗?在程序逻辑中使用之前,是否要检查程序的所有输入(索引和new_volume)的值?您是否能够触发溢出,段错误,错误,错误,意外行为?您做了什么分析此程序的潜在漏洞?您如何解决此问题?你在说什么?
嘿@SYS_V我输入到程序(索引和new_volume)索引= 102030405060708090 volume = 90程序粉碎,输出为-504445190至第90卷EIP = 004014C1