Terminal variable set from 'defaults' command

Discussion in 'Mac Programming' started by mhoward84, Apr 6, 2012.

  1. mhoward84 macrumors newbie

    May 20, 2011
    Hi, I am trying to write the standard output of the defaults command to a variable. When I do the following
    VAR1=$( defaults read ~/.MacOSX/environment/DYLD_INSERT_LIBRARIES )


    echo $VAR1

    I simply get a blank line then the command prompt. I also can't redirect the output to a document.

    Is there any way to do this with this command? Thanks in advance
  2. chown33, Apr 6, 2012
    Last edited: Apr 6, 2012

    chown33 macrumors 604

    Aug 9, 2009
    Break It Down. The problem may not be what you think it is.

    First, check that your syntax is correct for the inner command:
    defaults read ~/.MacOSX/environment/DYLD_INSERT_LIBRARIES
    If you just paste that into a Terminal window, what is the output? Post it, please, including any error messages.

    If the output isn't what you expect, please describe what you expected, and how you decided that the posted defaults command-line is what should work.

    Also describe exactly what you're trying to do. If you're trying to read the environment.plist file, looking for a DYLD_INSERT_LIBRARIES entry, perhaps related to the Flashback trojan, then please say that's what you're trying to do. Because if that's what you're trying to do, your syntax is wrong. You should start by reading the man page for the defaults command. You might also read about PListBuddy (google it).

    Article with correct examples of defaults commands:
  3. mhoward84 thread starter macrumors newbie

    May 20, 2011
    Thanks for the response chown.
    I want to build a script that I can distribute to customers that will examine the results of this command and the other 2 and verify that the trojan isn't installed.

    Upon further examination it appears it might just be easier to download someone else's script and distribute it or use some of their script to construct my own.
  4. subsonix, Apr 7, 2012
    Last edited: Apr 7, 2012

    subsonix macrumors 68040

    Feb 2, 2008
    defaults writes to stderr, you need to direct it to stdout. It might also make sense to pipe it to: grep -E "( does not exist)$" or something before you assign it to a variable, also use meaningful names for variables.

    DYLD=$(defaults read ~/.MacOSX/environment DYLD_INSERT_LIBRARIES 2>&1 | grep -E "( does not exist)$")
    # similar for the other tests
    if [ -n "$DYLD" ] && [ -n "$SAFARI" ] && [ -n "$FIREFOX" ]
        echo "ok"
        echo "Oh noes!"
    Edit: I have not tested this on a machine that has this trojan, keep that in mind. It might actually be better to do it manually to be sure instead of taking the risk of a false positive or worse, a false negative.
  5. chown33 macrumors 604

    Aug 9, 2009
    It does write to stdout, when invoked correctly, on a plist value that exists, in a plist or domain that exists.

    If invoked incorrectly, or on a plist file or domain that doesn't exist, or with a key that doesn't exist, the stdout stream contains no bytes.

    It only writes error messages to stderr, like many other Unix/Posix commands. In this design, the fact that nothing is written to stdout is intended to mean "no such thing", usually coupled with a non-zero exit status (shell: $?).

    For example, if the cat command is invoked to cat a file that doesn't exist, the stdout stream gets no bytes, the stderr stream gets an error message, and cat's exit status is not-success (i.e. non-zero).

    Try these:
    defaults read com.apple.TextEdit; echo $?
    defaults read com.apple.TextEdit WidthInChars; echo $?
    defaults read com.apple.TextEdit ExplodingPenguin; echo $?


    This seems like a good idea, especially if you're not extremely familiar with writing shell scripts that need to deal with error conditions.
  6. subsonix macrumors 68040

    Feb 2, 2008
    Right, but in this case the idea is to catch the case where a plist does not exist so stderr needs to be redirected to assign it to the variable. The non existence of these plist files is the only case we know about. Likewise for the removal, a script can't be made by the information posted by Fsecure since the exact output is not known.
  7. subsonix macrumors 68040

    Feb 2, 2008
    Really? If you are not capable of writing it, how are you going to assess that the script you are using is correct? The best is to follow the exact instructions given by Fsecure.
  8. chown33 macrumors 604

    Aug 9, 2009
    I'm not following your logic.

    If you didn't redirect and grep the stderr stream, the value assigned to the variable is "" (empty string). How is that not a definitive indicator that there is either no such file, or no such key?

    It's conceivable that the file does exist, and the key exists with a value of "" (empty string), and this would not be a uniquely detectable condition. I'm not seeing how it's harmful, though, since it means DYLD_INSERT_LIBRARIES is defined to be the empty string. How is that harmful?

    If it were strictly necessary to detect "no such file or no such key", then checking the exit status of 'defaults' is simpler:
    example=$(defaults read ~/.MacOSX/environment DYLD_INSERT_LIBRARIES 2>/dev/null || echo "###")
    If defaults has any non-zero exit status (i.e. no such file or no such key), then example will be assigned the string "###" (any other distinctive string would suffice). It's not necessary to parse the stderr messages looking for a grep pattern. Using the exit status of defaults is sufficient in this case.

    I also see that your example is still using the wrong syntax for defaults [1]. So it will behave as if the file and/or key doesn't exist, producing a false negative.

    It is entirely possible to script the "use the path retrieved from the plist" procedure using PListBuddy. It's also possible using defaults and awk. I'm not going to suggest it's trivial, or even simple (as such scripts go). It is, however, quite possible to get the value assigned to DYLD_INSERT_LIBRARIES and do something with that pathname.

    I surmise that Fsecure simply isn't interested in producing a free solution, since they explicitly say that non-advanced users should contact their support.

    There may even be a better choice of scripting language than bash. Perhaps python or perl.

    Personally, I'm not going to spend a lot of time on it, because none of the Mac users I know personally have this infection, and the ones I talked to recently are well aware of how to avoid it.

    [1] according to this Fsecure web page and this one.


    You're right, I rescind my suggestion.

    The best strategy is to not compound one mistake with another, and to not trust scripts posted from unknown sources, no matter how good they might look at first glance.
  9. subsonix macrumors 68040

    Feb 2, 2008
    Calm down, I'm using an example that fits the code in post 1 and explicitly test the condition posted by Fsecure.

    Technically correct, and you could come up with 5 or more different ways of doing it, the point was to replicate what was known exactly.

    Yeah that's correct I simply copy pasted it from the first post.

    Golf clap.
  10. chown33 macrumors 604

    Aug 9, 2009
    Except you lost the ~.

    VAR1=$( defaults read ~/.MacOSX/environment/DYLD_INSERT_LIBRARIES )
    Your revised code:
    DYLD=$(defaults read /.MacOSX/environment DYLD_INSERT_LIBRARIES 2>&1 | grep -E "( does not exist)$")
  11. subsonix macrumors 68040

    Feb 2, 2008

    You almost never post code.
  12. chown33 macrumors 604

    Aug 9, 2009
    Source for an Objective-C app that checks for infection:
    (For OS version 10.5 and up)

    Via this article on Ars Technica.

    I wonder how many of the affected Macs are running an OS and Java version so old they can't be updated? Or on hardware so old they can't be updated?

    If they're not updatable, this malware is a persistent threat to those machines. The only easy prevention mechanism would be the "disable Java" checkbox in Safari's security preferences window.
  13. subsonix, Apr 9, 2012
    Last edited: Apr 9, 2012

    subsonix macrumors 68040

    Feb 2, 2008
    Turning off Java in the browser should take care of that. I have had it turned off for several years without noticing any difference, I can probably count the instances on one hand where it had to be turned on explicitly for some reason.

Share This Page