Mac OS X Buffer Overflow Found
MacDork writes "Well, if default settings in Mac OS X made Lance Ulanoff excited, this is really going to make him do the monkey boy dance... SecurityFocus's Bugtraq mailing list just posted a buffer overflow, in the utility for mounting and probing ISO 9660 file systems. No exploits were mentioned. No word on whether 'Max' alerted Apple or anyone outside of the Bugtraq mailing list though." Also, 'Max' made entirely unfounded, sweeping statements about the general quality of Mac OS X from this one little item, but oh well. When you're on top, you make a tempting target.
The error lies in the cd9660.util_main.m file from the isoutil package, specifically, right in the start of the main function:
/* Build our device name (full path), should end up with something like: */
/* /dev/disk1s2 */
if ( (myError = DoVerifyArgs( argc, argv, &mnt_flag )) != 0 )
goto AllDone;
strcpy( &myDeviceName[0], DEVICE_PREFIX );
strcat( &myDeviceName[0], argv[2] );
The strcat function fails with the huge devicename. DoVerifyArgs should check the length of argv[2] to be under 255 characters, but it only checks if it is longer than 2 characters:
/* Make sure device (argv[2]) is something reasonable */
myDeviceLength = strlen( argv[2] );
if ( myDeviceLength < 2 )
{
goto ExitThisRoutine;
}
I'll make a quick fix and test it.
Maybe we deserve this world ?
NUL is '\0' the byte valued 0.
, that tells you where in the string you need to put the address that you want to jump to. The next problem is working out what that address should be. This you can get from the debugger.
C uses '\0' to delimit strings. Therefore a strcat will not go past the first '\0' in the shellcode (or whatever exploit it is you're trying to run).
So, if the code you want to run needs '\0's in it it must build those values on the fly. (e.g. subtract any value from itself and you instantly have a register loaded with 4 zeroes.) If you need opcodes that have 0 somewhere in them, then you need to self-modify, or you need to find a way to write what you want without using such opcodes. Most people go for the former.
That's all there is to being NUL-less. It's easy on x86, but slightly more challenging on fixed-length opcode machines (RISCs and VLIWs). Similarly, avoiding just '\0' is pretty easy - the real skill is from avoiding anything but [a-zA-Z0-9] such that you can pass some input sanitisers. (See posts by Herbert Kleebauer on alt.lang.asm for examples of ascii-only executables (one was called 'beth.com' IIRC, google should find it).)
To calculate the jump, just work out which of the 512 'A's are the 4 that you can see in the debugger stack trace. It's easiest to work this out by not having every character in the overflowing string being the same character. That's why I suggest 'abcdef...'
If you now see the backtrace as containing 0x66676869 then you know it was one of your 'fghi's that you're now looking at. However you don't know which one yet, so try again with a different repeated string with a different length, and 'triangulate'. Or simply use a single probe with a string that doesn't repeat, such as "aaabacad....azbabbbcbd....bzcacbcccd..."
Anyway
Read Aleph One's "smashing the stack for fun and profit" for more info. Once you can do it on one architecture, you'll be equipped to do it pretty much on all of them.
Have fun, but remember to practice safe hex.
YAW.
Your head of state is a corrupt weasel, I hope you're happy.