Skip to content
This repository has been archived by the owner on Sep 17, 2018. It is now read-only.

Access violation near NULL on destination operand #4

Closed
kongwenbin opened this issue Sep 9, 2017 · 4 comments
Closed

Access violation near NULL on destination operand #4

kongwenbin opened this issue Sep 9, 2017 · 4 comments

Comments

@kongwenbin
Copy link

I have discovered several malformed cue files that would cause bchunk to run into segmentation fault. With the help of gdb exploitable, it can be determined that there was an access violation near NULL on the destination operand.

The following is a full output:

Program received signal SIGSEGV, Segmentation fault.
0x08135475 in main (argc=<optimized out>, argv=<optimized out>) at bchunk.c:488
488                track->startsect = time2frames(t);
(gdb) exploitable
__main__:99: UserWarning: GDB v7.11 may not support required Python API
Description: Access violation near NULL on destination operand
Short description: DestAvNearNull (15/22)
Hash: a9a47a861a48dcf377b1bb07b521fa30.a9a47a861a48dcf377b1bb07b521fa30
Exploitability Classification: PROBABLY_EXPLOITABLE
Explanation: The target crashed on an access violation at an address matching the destination operand of the instruction. This likely indicates a write access violation, which means the attacker may control write address and/or value. However, it there is a chance it could be a NULL dereference.
Other tags: AccessViolation (21/22)
@lukateras
Copy link

Hi, I'd like to prepare a patch for all three CVEs. Could you please share POC files (malformed cue sheets)?

@lukateras
Copy link

lukateras commented Oct 30, 2017

t can be uninitialized when it reaches time2frames(t), particularly when time on INDEX line is missing:

FILE "Tool - Lateralus.flac" WAVE
 TRACK 01 AUDIO
   TITLE "The Grudge"
   INDEX 00

I couldn't reproduce the crash (I'm on amd64?), but Valgrind isn't happy with that:

==6115== Conditional jump or move depends on uninitialised value(s)
==6115==    at 0x4EAA41F: _IO_file_seekoff@@GLIBC_2.2.5 (in /nix/store/yydnhs7migvlbl48wpsxan1yvq2icbr9-glibc-2.25-49/lib/libc-2.25.so)
==6115==    by 0x4EA7938: fseek (in /nix/store/yydnhs7migvlbl48wpsxan1yvq2icbr9-glibc-2.25-49/lib/libc-2.25.so)
==6115==    by 0x40185A: ??? (in /nix/store/dxhx0qj1w1p8k7b1vvlb4nb4nmyw46mw-bchunk-1.2.0/bin/bchunk)
==6115==    by 0x401133: ??? (in /nix/store/dxhx0qj1w1p8k7b1vvlb4nb4nmyw46mw-bchunk-1.2.0/bin/bchunk)
==6115==    by 0x4E5855F: (below main) (in /nix/store/yydnhs7migvlbl48wpsxan1yvq2icbr9-glibc-2.25-49/lib/libc-2.25.so)

Here's a patch that solves this by rejecting malformed cue sheets:

diff -urNZ bchunk-1.2.0.orig/bchunk.c bchunk-1.2.0/bchunk.c
--- bchunk-1.2.0.orig/bchunk.c	2017-10-30 18:03:58.658741629 +0000
+++ bchunk-1.2.0/bchunk.c	2017-10-30 19:17:36.732855884 +0000
@@ -426,12 +426,12 @@
 			printf("\nTrack ");
 			if (!(p = strchr(p, ' '))) {
 				fprintf(stderr, "... ouch, no space after TRACK.\n");
-				continue;
+				exit(3);
 			}
 			p++;
 			if (!(t = strchr(p, ' '))) {
 				fprintf(stderr, "... ouch, no space after track number.\n");
-				continue;
+				exit(3);
 			}
 			*t = '\0';
 			
@@ -460,12 +460,12 @@
 		} else if ((p = strstr(s, "INDEX"))) {
 			if (!(p = strchr(p, ' '))) {
 				printf("... ouch, no space after INDEX.\n");
-				continue;
+				exit(3);
 			}
 			p++;
 			if (!(t = strchr(p, ' '))) {
 				printf("... ouch, no space after index number.\n");
-				continue;
+				exit(3);
 			}
 			*t = '\0';
 			t++;

@kongwenbin
Copy link
Author

Hi @yegortimoshenko , from my understanding, the issues cannot be reproduced on x64 machines. I discovered them on my test machine running Linux ubuntu 4.10.0-32-generic #36~16.04.1-Ubuntu SMP Wed Aug 9 09:18:53 UTC 2017 i686 i686 i686 GNU/Linux.

Once again, really amazing how you fixed the bug before I can provide more information. Very elegant fixed to reject any malformed cue files there.

Just to be sure, can also perform verification on the following payload, as attached.
poc.zip

@lukateras
Copy link

lukateras commented Oct 31, 2017

I've managed to trigger segfault on amd64 with this payload on unpatched bchunk v1.2.0:

$ uname -a
Linux yegatool 4.13.9 #1-NixOS SMP Sat Oct 21 15:55:07 UTC 2017 x86_64 GNU/Linux
$ valgrind bchunk poc21.bin poc21.cue /tmp/zzz
==14309== Memcheck, a memory error detector
==14309== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14309== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14309== Command: bchunk poc21.bin poc21 /tmp/zzz
==14309== 
binchunker for Unix, version 1.2.0 by Heikki Hannikainen <hessu@hes.iki.fi>
	Created with the kind help of Bob Marietta <marietrg@SLU.EDU>,
	partly based on his Pascal (Delphi) implementation.
	Support for MODE2/2352 ISO tracks thanks to input from
	Godmar Back <gback@cs.utah.edu>, Colas Nahaboo <Colas@Nahaboo.com>
	and Matthew Green <mrg@eterna.com.au>.
	Released under the GNU GPL, version 2 or later (at your option).

Reading the CUE file:

... ouch, no space after track number.
Track ... ouch, no space after INDEX.
==14309== Invalid write of size 8
==14309==    at 0x401013: ??? (in /nix/store/dxhx0qj1w1p8k7b1vvlb4nb4nmyw46mw-bchunk-1.2.0/bin/bchunk)
==14309==    by 0x4E5855F: (below main) (in /nix/store/yydnhs7migvlbl48wpsxan1yvq2icbr9-glibc-2.25-49/lib/libc-2.25.so)
==14309==  Address 0x28 is not stack'd, malloc'd or (recently) free'd
==14309== 
==14309== 
==14309== Process terminating with default action of signal 11 (SIGSEGV)
==14309==  Access not within mapped region at address 0x28
==14309==    at 0x401013: ??? (in /nix/store/dxhx0qj1w1p8k7b1vvlb4nb4nmyw46mw-bchunk-1.2.0/bin/bchunk)
==14309==    by 0x4E5855F: (below main) (in /nix/store/yydnhs7migvlbl48wpsxan1yvq2icbr9-glibc-2.25-49/lib/libc-2.25.so)
==14309==  If you believe this happened as a result of a stack
==14309==  overflow in your program's main thread (unlikely but
==14309==  possible), you can try to increase the size of the
==14309==  main thread stack using the --main-stacksize= flag.
==14309==  The main thread stack size used in this run was 10022912.
 01 0�:003:02==14309== 
==14309== HEAP SUMMARY:
==14309==     in use at exit: 1,124 bytes in 5 blocks
==14309==   total heap usage: 7 allocs, 2 frees, 6,244 bytes allocated
==14309== 
==14309== LEAK SUMMARY:
==14309==    definitely lost: 0 bytes in 0 blocks
==14309==    indirectly lost: 0 bytes in 0 blocks
==14309==      possibly lost: 0 bytes in 0 blocks
==14309==    still reachable: 1,124 bytes in 5 blocks
==14309==         suppressed: 0 bytes in 0 blocks
==14309== Rerun with --leak-check=full to see details of leaked memory
==14309== 
==14309== For counts of detected and suppressed errors, rerun with: -v
==14309== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
segmentation fault

Again, after patches it behaves as expected:

$ valgrind result/bin/bchunk poc21.bin poc21.cue /tmp/zzz
==14356== Memcheck, a memory error detector
==14356== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==14356== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==14356== Command: result/bin/bchunk poc21.bin poc21.cue /tmp/zzz
==14356== 
binchunker for Unix, version 1.2.0 by Heikki Hannikainen <hessu@hes.iki.fi>
	Created with the kind help of Bob Marietta <marietrg@SLU.EDU>,
	partly based on his Pascal (Delphi) implementation.
	Support for MODE2/2352 ISO tracks thanks to input from
	Godmar Back <gback@cs.utah.edu>, Colas Nahaboo <Colas@Nahaboo.com>
	and Matthew Green <mrg@eterna.com.au>.
	Released under the GNU GPL, version 2 or later (at your option).

Reading the CUE file:

... ouch, no space after track number.
Track ==14356== 
==14356== HEAP SUMMARY:
==14356==     in use at exit: 1,133 bytes in 5 blocks
==14356==   total heap usage: 7 allocs, 2 frees, 6,253 bytes allocated
==14356== 
==14356== LEAK SUMMARY:
==14356==    definitely lost: 0 bytes in 0 blocks
==14356==    indirectly lost: 0 bytes in 0 blocks
==14356==      possibly lost: 0 bytes in 0 blocks
==14356==    still reachable: 1,133 bytes in 5 blocks
==14356==         suppressed: 0 bytes in 0 blocks
==14356== Rerun with --leak-check=full to see details of leaked memory
==14356== 
==14356== For counts of detected and suppressed errors, rerun with: -v
==14356== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ echo $?
3

Thanks again @kongwenbin :-)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants