Watching the winter and summer olympics is literally the only reason I have to watch TV these days, and since the content is so locked up in media deals, buying a cable TV package seems to be the only option to see it in the US. Not so.
NBC (which carries the olympics) is broadcast free to air in HD, along with a few other major channels and a pile of crap that isn't fit for human consumption (like 24hr home shopping). Getting at this free content is basically a case of picking the right antenna.
1. Check available channels
Put your zipcode into the station direction finder at antennaweb.org to find out what channels are available in your area and where the TV transmitters are.
2. Buy an antenna
For best results you should probably use a high-gain outdoors antenna. But if you are renting, or want to do it on the cheap, you might want to check out Lifehacker's list of the best indoor antennas. In the SF bay area I can tune 82 channels, including NBC aka KNTV, with the un-amplified Mohu leaf which cost me $40. The leaf also happens to be the top recommendation from Lifehacker.
I have it mounted indoors about 9ft up the wall and I'm receiving all the channels listed by antennaweb. I even get KTLN, which antennaweb says is being broadcast from 57 miles away! The antennaweb recommended antenna to receive at that kind of distance is a large directional antenna with pre-amp, but the Mohu leaf is killing it. Amazing.
3. Tune channels
Follow your TV's instructions for tuning channels. You may have to move your antenna around to find the best reception.
Tuesday, February 11, 2014
Wednesday, December 18, 2013
OpenSSL: verify a windows code signing cert on linux
HOWTO test the signing chain of a windows code signing cert. You'll probably need to convert it to pem first:
openssl pkcs12 -in signing_cert.pfx -out file.pem openssl verify -verbose -purpose any file.pemChances are pretty good that you'll be missing an intermediate signing cert, and the cert issuers don't make it particularly easy to find them. Your best bet is to google the CN from the issuer. Once you have the intermediate you can tell openssl about it using the "untrusted" option, which is helpfully missing from the verify commandline documentation.
openssl x509 -in file.pem -text -noout openssl verify -verbose -purpose any -untrusted intermediate_untrusted.pem file.pem
Saturday, December 7, 2013
Windows 8 and Ubuntu 13.10 with encrypted root on a UEFI HP Envy 15-j085nr
I recently went through the pain of creating a Windows/Linux dual boot, here are some rough notes for the benefits of others. Since the HP envy is UEFI, some of the existing wisdom on the Internets doesn't apply.
Start by installing windows normally. Since, like most laptops, it ships with an OEM install on a separate partition, this basically just means turning it on and following the prompts.
Create an ubuntu boot USB boot drive (super easy, just download the relevant ISO and use startup-disk-creator)
Reboot to USB in UEFI mode (I followed Settings|General|Advanced Startup, but apparently Shift-Restart also works). This should get you the black UEFI GRUB menu. You can tell you have booted with UEFI if the /sys/firmware/efi directory is present.
Secure Boot is now supported but it will probably cause you problems and require disabling (use F10 to get to the UEFI menu). My install worked fine with it enabled, but when I attempted to boot windows from the ubuntu boot manager the verification failed and it went into some sort of automatic self repair mode. I interrupted this without any negative consequences.
When Ubuntu starts the screen might just go black: use the hardware keys to turn the brightness up. Since UEFI uses GPT rather than MBR partitioning (archlinux has a great writeup of the details), you'll need to use gdisk rather than fdisk to inspect the disk. The syntax is basically the same.
Choose "Try without installing". I found this was handy because if the installer crashes you still have your desktop session. From this point I mostly followed these instructions to create the encrypted container manually. The installer almost works for this setup, but not quite. You can create the boot partition and the encrypted volume in the installer gui but there appears to be no way to tell it to do LVM inside the container to separate swap and root. After following the partitioning instructions my disk ended up looking like this:
I eventually settled on using the Ubuntu boot manager with the compromise of hitting F9 and using the UEFI boot menu to get to Windows (since I'm not intending to use it very often). This are the efibootmgr commands I used to make ubuntu the default (I also ended up deleting rEFInd using efibootmgr).
For those wondering how well the HP Envy 15-j085nr plays with Ubuntu 13.10 the answer is pretty well. Graphics (1366x768), sound, function keys are all good. There appears to be some sort of packet loss problem with the RTL8188EE wireless driver that I'm still investigating. Here's some details to help pre-purchase investigating:
Update 2013-12-30: Spoke too soon. Wireless performance was still terrible (30% - 80% packet loss) despite installing the latest proprietary driver and firmware. I eventually gave up on this card and driver and bought a Intel Corporation Centrino Advanced-N 6235 for $24, which works perfectly: 0% loss. Same access point, same location in the room, etc. The conclusion I draw is that the RTL8188EE linux driver and/or firmware/hardware itself is just terrible. I was concerned that the BIOS wouldn't allow the new card since apparently it has a whitelist of wireless card replacements, and this one wasn't on the list in the maintenance manual, but no problems.
Start by installing windows normally. Since, like most laptops, it ships with an OEM install on a separate partition, this basically just means turning it on and following the prompts.
Create an ubuntu boot USB boot drive (super easy, just download the relevant ISO and use startup-disk-creator)
Reboot to USB in UEFI mode (I followed Settings|General|Advanced Startup, but apparently Shift-Restart also works). This should get you the black UEFI GRUB menu. You can tell you have booted with UEFI if the /sys/firmware/efi directory is present.
Secure Boot is now supported but it will probably cause you problems and require disabling (use F10 to get to the UEFI menu). My install worked fine with it enabled, but when I attempted to boot windows from the ubuntu boot manager the verification failed and it went into some sort of automatic self repair mode. I interrupted this without any negative consequences.
When Ubuntu starts the screen might just go black: use the hardware keys to turn the brightness up. Since UEFI uses GPT rather than MBR partitioning (archlinux has a great writeup of the details), you'll need to use gdisk rather than fdisk to inspect the disk. The syntax is basically the same.
Choose "Try without installing". I found this was handy because if the installer crashes you still have your desktop session. From this point I mostly followed these instructions to create the encrypted container manually. The installer almost works for this setup, but not quite. You can create the boot partition and the encrypted volume in the installer gui but there appears to be no way to tell it to do LVM inside the container to separate swap and root. After following the partitioning instructions my disk ended up looking like this:
$ sudo gdisk -l /dev/sda GPT fdisk (gdisk) version 0.8.7 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Disk /dev/sda: 1953525168 sectors, 931.5 GiB Logical sector size: 512 bytes Disk identifier (GUID): 0236CBF5-85E3-4F99-B92F-F33CADBAAAAA Partition table holds up to 128 entries First usable sector is 34, last usable sector is 1953525134 Partitions will be aligned on 2048-sector boundaries Total free space is 13677 sectors (6.7 MiB) Number Start (sector) End (sector) Size Code Name 1 2048 821247 400.0 MiB 2700 Basic data partition 2 821248 1353727 260.0 MiB EF00 EFI system partition 3 1353728 1615871 128.0 MiB 0C01 Microsoft reserved part 4 1615872 670988287 319.2 GiB 0700 Basic data partition 5 1899788288 1953513471 25.6 GiB 0700 Basic data partition 6 670988288 674893823 1.9 GiB 8300 /boot 7 674893824 1899788287 584.1 GiB 8300 cryptrootWhen I rebooted I had a working Ubuntu install with an encrypted root, but no way of accessing windows. I tried a few things at this point, probably all of which you should avoid (you should probably just skip to the next paragraph). I booted the Windows recovery partition (F11), followed the prompts to get a shell and ran bootrec. I also installed EasyBCD, which allegedly supports UEFI as of version 2.2, but the boot manager it installed couldn't boot Ubuntu even though it recognised it. I then installed rEFInd. I had to reorder the boot manager priority with efibootmgr to put it first, but when I did I found it could boot Ubuntu fine, but not Windows :(
I eventually settled on using the Ubuntu boot manager with the compromise of hitting F9 and using the UEFI boot menu to get to Windows (since I'm not intending to use it very often). This are the efibootmgr commands I used to make ubuntu the default (I also ended up deleting rEFInd using efibootmgr).
$ sudo efibootmgr -o 0002,3002,0001,0000,2001,2002,2003 $ sudo efibootmgr BootCurrent: 0002 Timeout: 0 seconds BootOrder: 0002,3002,0001,0000,2001,2002,2003 Boot0000* rEFInd Boot Manager Boot0001* Windows Boot Manager Boot0002* ubuntu Boot0003* Internal Hard Disk or Solid State Disk Boot0005* Internal Hard Disk or Solid State Disk Boot0009* Internal Hard Disk or Solid State Disk Boot2001* USB Drive (UEFI) Boot2002* Internal CD/DVD ROM Drive (UEFI) Boot3000* Internal Hard Disk or Solid State Disk Boot3001* Internal Hard Disk or Solid State Disk Boot3002* Internal Hard Disk or Solid State Disk Boot3003* Internal Hard Disk or Solid State DiskThen as I was installing a newer kernel to try and debug a wireless networking issue I saw this after installation of 3.12:
Found Windows Boot Manager on /dev/sda2@/EFI/Microsoft/Boot/bootmgfw.efi Adding boot menu entry for EFI firmware configurationand all of a sudden I had a windows option in the GRUB bootloader menu! Hooray! Not sure if the new kernel was required, or perhaps just a grub-update.
For those wondering how well the HP Envy 15-j085nr plays with Ubuntu 13.10 the answer is pretty well. Graphics (1366x768), sound, function keys are all good. There appears to be some sort of packet loss problem with the RTL8188EE wireless driver that I'm still investigating. Here's some details to help pre-purchase investigating:
00:00.0 Host bridge: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller (rev 06) 00:02.0 VGA compatible controller: Intel Corporation 4th Gen Core Processor Integrated Graphics Controller (rev 06) 00:03.0 Audio device: Intel Corporation Xeon E3-1200 v3/4th Gen Core Processor HD Audio Controller (rev 06) 00:14.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB xHCI (rev 05) 00:16.0 Communication controller: Intel Corporation 8 Series/C220 Series Chipset Family MEI Controller #1 (rev 04) 00:1a.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB EHCI #2 (rev 05) 00:1b.0 Audio device: Intel Corporation 8 Series/C220 Series Chipset High Definition Audio Controller (rev 05) 00:1c.0 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #3 (rev d5) 00:1c.2 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #1 (rev d5) 00:1c.3 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #4 (rev d5) 00:1c.6 PCI bridge: Intel Corporation 8 Series/C220 Series Chipset Family PCI Express Root Port #7 (rev d5) 00:1d.0 USB controller: Intel Corporation 8 Series/C220 Series Chipset Family USB EHCI #1 (rev 05) 00:1f.0 ISA bridge: Intel Corporation HM87 Express LPC Controller (rev 05) 00:1f.2 SATA controller: Intel Corporation 8 Series/C220 Series Chipset Family 6-port SATA Controller 1 [AHCI mode] (rev 05) 00:1f.3 SMBus: Intel Corporation 8 Series/C220 Series Chipset Family SMBus Controller (rev 05) 01:00.0 Network controller: Realtek Semiconductor Co., Ltd. RTL8188EE Wireless Network Adapter (rev 01) 03:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. Device 5227 (rev 01) 09:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 0c)Update 2013-12-26: I filed a bug for the packet loss problem. Thanks to some forums I realised that the Realtek download page for the RTL8188CE driver actually includes the RTL8188EE and a bunch of others, something that is certainly not obvious from the page itself. After installing the kernel source, the next problem was that the Realtek driver source doesn't actually compile, and is apparently only supported up to 3.9 kernels. Errors on 3.11.0-14 look like this:
make -C /lib/modules/3.11.0-14-generic/build M=/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013 modules
make[1]: Entering directory `/usr/src/linux-headers-3.11.0-14-generic'
CC [M] /home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.o
In file included from /home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.c:39:0:
/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/pci.h:247:15: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtl_pci_probe’
int __devinit rtl_pci_probe(struct pci_dev *pdev,
^
/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.c: In function ‘rtl_action_proc’:
/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.c:885:32: error: ‘struct ieee80211_conf’ has no member named ‘channel’
rx_status.freq = hw->conf.channel->center_freq;
^
/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.c:886:32: error: ‘struct ieee80211_conf’ has no member named ‘channel’
rx_status.band = hw->conf.channel->band;
^
/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.c: In function ‘rtl_send_smps_action’:
/home/g/rtl_92ce_92se_92de_8723ae_88ee_linux_mac80211_0012.0207.2013/base.c:1451:24: error: ‘struct ieee80211_conf’ has no member named ‘channel’
info->band = hw->conf.channel->band;
Freedom Ben's modified version worked for me however, and seems to have mostly solved the wireless problems I was seeing, and although there's still more packet loss than I would like the laptop is usable now.Update 2013-12-30: Spoke too soon. Wireless performance was still terrible (30% - 80% packet loss) despite installing the latest proprietary driver and firmware. I eventually gave up on this card and driver and bought a Intel Corporation Centrino Advanced-N 6235 for $24, which works perfectly: 0% loss. Same access point, same location in the room, etc. The conclusion I draw is that the RTL8188EE linux driver and/or firmware/hardware itself is just terrible. I was concerned that the BIOS wouldn't allow the new card since apparently it has a whitelist of wireless card replacements, and this one wasn't on the list in the maintenance manual, but no problems.
Wednesday, November 6, 2013
Disable Find My Mac by Modifiying Nvram Configuration
`When Find My Mac (FMM) is enabled, it writes information into the Mac's nvram. This enables the configuration to persist across OS-level changes, including a full system re-image. This is great if it's been stolen and you want to track it, but not so great if you bought a second hand mac, or your employer gave you a repurposed mac. The previous owner will be able to track the mac's location and even issue a remote wipe.
Apple advises you to disable FMM when handing over ownership. That's fine if you have the owner's cooperation, but it's more problematic if the owner was some guy on craig's list, or last summer's intern who is now building water wells in Kenya. So we need a way to programmatically disable the functionality.
The relevant nvram variables are shown below. fmm-computer-name is just a base64 encoded string of the computer's host name.
Apple advises you to disable FMM when handing over ownership. That's fine if you have the owner's cooperation, but it's more problematic if the owner was some guy on craig's list, or last summer's intern who is now building water wells in Kenya. So we need a way to programmatically disable the functionality.
The relevant nvram variables are shown below. fmm-computer-name is just a base64 encoded string of the computer's host name.
$ nvram -x -p <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">The fmm-mobileme-token-FMM data is a base64-encoded binary plist that holds the FMM configuration. The purpose seems pretty obvious, it will beacon to https://p08-fmip.icloud.com with the authToken, AppleID, and other machine metadata. The person ID and username in the plist correspond to the Apple ID account that registered with FMM. Values changed here to protect the innocent :)
<plist version="1.0">
<dict>
[snip]
<key>fmm-computer-name</key>
<data>
bXljb21wdXRlcm5hbWU=
</data>
<key>fmm-mobileme-token-FMM</key>
<data>
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
</data>
<?xml version="1.0" encoding="UTF-8"?>The solution is just to kill the nvram variables:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>authToken</key>
<string>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~</string>
<key>dataclassProperties</key>
<dict>
<key>com.apple.Dataclass.DeviceLocator</key>
<dict>
<key>apsEnv</key>
<string>Production</string>
<key>authMechanism</key>
<string>token</string>
<key>hostname</key>
<string>p08-fmip.icloud.com</string>
<key>scheme</key>
<string>https</string>
</dict>
</dict>
<key>enabledDataclasses</key>
<array>
<string>com.apple.Dataclass.DeviceLocator</string>
</array>
<key>personID</key>
<string>1111111111</string>
<key>userInfo</key>
<dict>
<key>InUseOwnerDisplayName</key>
<string>A User Name</string>
</dict>
<key>userid</key>
<integer>502</integer>
<key>username</key>
<string>myappleidusername@gmail.com</string>
</dict>
</plist>
nvram -d fmm-computer-name nvram -d fmm-mobileme-token-FMMAnd in fact, you should probably just clear everything during your re-imaging process:
nvram -cProbably unnecessary but you could also disable the LaunchDaemon which lives here:
/System/Library/LaunchDaemons/com.apple.findmymac.plistOr just check that the disable is active in /var/db/launchd.db/com.apple.launchd/overrides.plist:
<key>com.apple.findmymacd</key>
<dict>
<key>Disabled</key>
<true/>
</dict>
<key>com.apple.findmymacmessenger</key>
<dict>
<key>Disabled</key>
<true/>
</dict>
Tuesday, October 29, 2013
Exceptions.plist: interesting tweaks, including Gatekeeper forced opt-in
The Exceptions.plist is quite interesting:
defaults read /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Exceptions.plistApple is using it to force opt-in a variety of apps for Gatekeeper protection by setting "LSFileQuarantineEnabled = 1". The list of apps on mavericks as of today is:
com.microsoft.Entourage com.microsoft.explorer com.omnigroup.OmniWeb5 com.operasoftware.opera com.panic.Transmit jp.hmdt.shiira org.gudy.azureus2 org.m0k.transmission org.mozilla.camino org.mozilla.firefox org.mozilla.mozilla org.mozilla.navigator org.mozilla.seamonkey org.mozilla.thunderbird org.pythonmac.unspecified.BitTorrent org.xlife.XtorrentApple also applies uses Exceptions.plist to apply categories to apps that aren't distributed through the appstore (where categories are presumably applied to all apps) e.g.
"com.Google.GoogleEarthPlus" = {
LSApplicationCategoryType = "public.app-category.reference";
};
There's also LSMaximumVersionRequiringJava, which I think probably controls whether the OS should prompt the user to install Java for particular versions of various software:
"com.adobe.Photoshop" = {
Java = {
};
LSApplicationCategoryType = "public.app-category.graphics-design";
LSMaximumVersionRequiringJava = "12.19";
};
And miscellaneous tweaks, these for power management and display:
AppNapOverrides = {
"com.apple.CrashTestDummy" = (
{
SoftDisabled = 1;
}
);
};
HighResolutionOverrides = {
"com.apple.AppleQmaster" = (
{
HighVersion = "3.5.3";
SoftDisabled = 1;
}
);
Daniel's documented VMWare version blacklisting for 10.8 appears to be gone in 10.9.
BIOS malware
Interesting recent developments on the BIOS malware front. MITRE delivered Copernicus and this blackhat talk, and Dragos Ruiu is on the tail of something very interesting if the claims can be believed and it isn't just a long troll...
Update: picked up by arstechnica.
Update: picked up by arstechnica.
Saturday, October 26, 2013
OS X XProtect
XProtect is Apple’s built-in AV system for OS X. I took at look at it on 10.8 (Mountain Lion). Virus definitions are stored in a simple format here:
It (I assume) verifies the signature, and checks the version number in the downloaded version:
When I first started looking at XProtect Apple didn't have signatures for eicar, so seeing it in action was a little tricky, or required real malware. Now they do and it looks like this:
XProtect doesn't detect it since the quarantine bit isn't present. Upload it somewhere and download it with a browser to get the quarantine bit applied. Double-click and you will see this warning:
If you leave 'report malware' ticked, regardless of whether you click OK or Cancel, the malware report is sent to Apple and you get a nice malware report in:
If you try running the same file (with quarantine) from the commandline, XProtect won't fire because it only applies to files launched through LaunchServices, similar to GateKeeper.
Modifying signatures is as simple as changing the plist:
I didn't test adding signatures, but since the plist seems to be unprotected from modification (i.e. the signature checked at download time isn't stored and checked when it is read from disk), and changes take effect immediately, it should be as simple as modifying the plist. After testing with XprotectUpdater, local modifications seem to persist as long as the version number is higher in the local version.
Some things have changed in 10.9. XProtectUpdater seems to have been removed or subsumed into another part of the OS, possibly part of the regular software update. This seems like a good move considering the comment above about malware attacking it. If I find out more I'll write another post.
/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.plistThis is part of the definition for a variant of MacDefender:
<key>Description</key>
<string>OSX.MacDefender.B</string>
<key>LaunchServices</key>
<dict>
<key>LSItemContentType</key>
<string>com.apple.installer-package</string>
</dict>
<key>Matches</key>
<array>
<dict>
<key>MatchFile</key>
<dict>
<key>NSURLNameKey</key>
<string>Info.plist</string>
</dict>
<key>MatchType</key>
<string>Match</string>
<key>Pattern</key>
<string>4946506B67466C6167417574686F72697A6174696F6E416374696F6E3C2F6B65793E0A093C737472696E673E4E6F417574686F72697A6174696F6E3C2F737472696E673E0A093C6B65793E4946506B67466C616744656661756C744C6F636174696F6E3C2F6B65793E0A093C737472696E673E2F4170706C69636174696F6E733C2F737472696E673E0A09</string>
</dict>
It contains a simple cleartext signature for a binary string in the Info.plist inside the MacDefender installer:
In [1]: a="4946506B67466C6167417574686F72697A6174696F6E416374696F6E3C2F6B65793E0A093C737472696E673E4E6F417574686F72697A6174696F6E3C2F737472696E673E0A093C6B65793E4946506B67466C616744656661756C744C6F636174696F6E3C2F6B65793E0A093C737472696E673E2F4170706C69636174696F6E733C2F737472696E673E0A09"
In [2]: a.decode('hex')
Out[2]:'IFPkgFlagAuthorizationAction\n\t<string>NoAuthorization</string>\n\t<key>IFPkgFlagDefaultLocation</key>\n\t<string>/Applications</string>\n\t'
The XProtect updater (/usr/libexec/XProtectUpdater) runs as a launch daemon (/System/Library/LaunchDaemons/com.apple.xprotectupdater.plist), set to run every 24 hours and at load time by default.
XProtectUpdater works by downloading a signed version of the plist from apple.It (I assume) verifies the signature, and checks the version number in the downloaded version:
<key>meta</key>
<dict>
<key>Version</key>
<integer>2024</integer>
<key>PlugInBlacklist</key>
<dict>
<key>10</key>
<dict>
<key>com.macromedia.Flash Player.plugin</key>
<dict>
<key>MinimumPlugInBundleVersion</key>
<string>11.3.300.271</string>
</dict>
<key>com.oracle.java.JavaAppletPlugin</key>
<dict>
<key>BlockedPlugInBundleVersions</key>
<array>
<string>1.7.06.24</string>
</array>
</dict>
</dict>
</dict>
</dict>
against the one recorded in:
/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.meta.plistand updates the metadata and signature plists if the version on disk is older. An sqlite database seems to be used as part of the update process:
/var/root/Library/Caches/XProtectUpdater/Cache.db
Observing detection/cleaning behaviour
When I first started looking at XProtect Apple didn't have signatures for eicar, so seeing it in action was a little tricky, or required real malware. Now they do and it looks like this:
<dict>
<key>Description</key>
<string>OSX.eicar.com.i</string>
<key>Matches</key>
<array>
<dict>
<key>Identity</key>
<data>
M5WFbOgfK3OC3ucmAveYtkLxQUA=
</data>
<key>MatchFile</key>
<dict>
<key>NSURLNameKey</key>
<string>eicar.com</string>
</dict>
<key>MatchType</key>
<string>Match</string>
</dict>
</array>
</dict>
Breaking that down:
- Description will show up in the "will damage your computer" warning box as seen below.
- Matches all criteria must match for alert to be shown
- Identity a base64 encoded sha1 hash.
- NSURLNameKey filename
- MatchType whether to match the filetype. Values are MatchAny, or Match. In this case it relies purely on the extension part of the filename specified in NSURNNameKey (so eicar.com will match, but downloading the same file as eicar.txt won't, and downloading eicar.com and renaming it eicar.txt also will avoid the warning). This makes sense since com has no header and eicar is just a test AV file.
In [12]: identity = "M5WFbOgfK3OC3ucmAveYtkLxQUA="
In [13]: identity.decode("base64").encode("hex")
Out[13]: '3395856ce81f2b7382dee72602f798b642f14140'
In [14]: import hashlib
In [15]: hashlib.sha1(open("eicar.com").read()).hexdigest()
Out[15]: '3395856ce81f2b7382dee72602f798b642f14140'
The signature format also supports various other NSURL filesystem resource keys as seen in this sig:
<key>MatchFile</key>
<dict>
<key>NSURLFileSizeKey</key>
<integer>50000</integer>
<key>NSURLNameKey</key>
<string>FileAgent</string>
<key>NSURLTypeIdentifierKey</key>
<string>public.unix-executable</string>
</dict>
<key>MatchType</key>
<string>Match</string>
Lets look at a full signature, OpinionSpy is the simplest, here it is in full:
<dict>
<key>Description</key>
<string>OSX.OpinionSpy</string>
<key>LaunchServices</key>
<dict>
<key>LSItemContentType</key>
<string>{(com.sun.java-archive|com.apple.application-bundle)}</string>
</dict>
<key>Matches</key>
<array>
<dict>
<key>MatchFile</key>
<dict>
<key>NSURLTypeIdentifierKey</key>
<string>com.sun.java-archive</string>
</dict>
<key>MatchType</key>
<string>Match</string>
<key>Pattern</key>
<string>504B010214000A0000000800547D8B3B9B0231BC{4}502D0700250000000000{12}636F6D2F697A666F7267652F697A7061636B2F70616E656C732F706F696E7374616C6C6572</string>
</dict>
</array>
</dict>
Note that type match is specified by UTI, and we have a pattern match rather than just a hash match. Replacing {4} and {12} with 4 and 12 bytes of stuff (I chose A's), here is a one-liner that generates a file that matches the signature:
$ python -c "open('eicar.jar','w').write('504B010214000A0000000800547D8B3B9B0231BCAAAAAAAA502D0700250000000000AAAAAAAAAAAAAAAAAAAAAAAA636F6D2F697A666F7267652F697A7061636B2F70616E656C732F706F696E7374616C6C6572'.decode('hex'))"
Which gives you part of a jar file (this signature works against the jar archive itself, not the contents):
$ hexdump -C eicar.jar 00000000 50 4b 01 02 14 00 0a 00 00 00 08 00 54 7d 8b 3b |PK..........T}.;| 00000010 9b 02 31 bc aa aa aa aa 50 2d 07 00 25 00 00 00 |..1.....P-..%...| 00000020 00 00 aa aa aa aa aa aa aa aa aa aa aa aa 63 6f |..............co| 00000030 6d 2f 69 7a 66 6f 72 67 65 2f 69 7a 70 61 63 6b |m/izforge/izpack| 00000040 2f 70 61 6e 65 6c 73 2f 70 6f 69 6e 73 74 61 6c |/panels/poinstal| 00000050 6c 65 72 |ler| 00000053If you double-click the file, you'll see something like this since the jar doesn't actually work:
XProtect doesn't detect it since the quarantine bit isn't present. Upload it somewhere and download it with a browser to get the quarantine bit applied. Double-click and you will see this warning:
If you leave 'report malware' ticked, regardless of whether you click OK or Cancel, the malware report is sent to Apple and you get a nice malware report in:
/Users/me/Library/Logs/DiagnosticReports/XProtect_2012-09-26-102829_my-MacBook-Pro.diagwhich looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>LSQuarantineAgentBundleIdentifier</key>
<string>com.google.Chrome</string>
<key>LSQuarantineDataURL</key>
<string>https://some.download.url</string>
<key>LSQuarantineOriginURL</key>
<string>https://some.referrer/url</string>
<key>LSQuarantineTimeStamp</key>
<date>2012-09-26T17:09:40Z</date>
<key>UserAction</key>
<string>trash</string>
<key>XProtectSignatureName</key>
<string>OSX.OpinionSpy</string>
</dict>
</array>
</plist>
and similar information is written to system.log:
Sep 26 10:28:29 my-MacBook-Pro.local CoreServicesUIAgent[4961]: Adding LSProperties {
LSQuarantineAgentBundleIdentifier = "com.google.Chrome";
LSQuarantineAgentName = "Google Chrome";
LSQuarantineDataURL = "https://some.download.url";
LSQuarantineEventIdentifier = "EEEEEEEE-DEAD-DEAD-DEAD-BEEFBEEFBEEF";
LSQuarantineIsOwnedByCurrentUser = 1;
LSQuarantineOriginURL = "https://some.referrer/url";
LSQuarantineTimeStamp = "2012-09-26 17:09:40 +0000";
LSQuarantineType = LSQuarantineTypeWebDownload;
} to malware report for file://localhost/Users/me/Downloads/eicar.jar
Sep 26 10:28:29 my-MacBook-Pro.local CoreServicesUIAgent[4961]: Saved diag report for XProtect version ??? to /Users/me/Library/Logs/DiagnosticReports/XProtect_2012-09-26-102829_my-MacBook-Pro.diag
Sep 26 10:28:29 my-MacBook-Pro.local CoreServicesUIAgent[4961]: Successfully submitted CR malware report
Sep 26 10:28:29 my-MacBook-Pro com.apple.launchd.peruser.501[126] ([0x0-0x182182].com.apple.JarLauncher[4960]): Exited: Killed: 9
If you untick 'report malware', no report is written and nothing about the malware is logged, which is terrible for sysadmins who want to know what malware has been found on their machines :(If you try running the same file (with quarantine) from the commandline, XProtect won't fire because it only applies to files launched through LaunchServices, similar to GateKeeper.
$ java -jar eicar.jar Invalid or corrupt jarfile eicar.jar
Modifying signatures
Modifying signatures is as simple as changing the plist:
/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.plistI tested by downloading eicar as above, checking it was detected, then modifying the signature in the XProtect.plist and re-launching: it wasn't detected. When I put the original signature back, it was detected once again.
I didn't test adding signatures, but since the plist seems to be unprotected from modification (i.e. the signature checked at download time isn't stored and checked when it is read from disk), and changes take effect immediately, it should be as simple as modifying the plist. After testing with XprotectUpdater, local modifications seem to persist as long as the version number is higher in the local version.
Summary
- Signatures are in the clear. An attacker who has been signatured doesn't need to spend any time figuring out what is signatured and testing modifications, they can just release a new version that evades the signature. Not a big deal since this is usually fairly easy without access to the actual signature, and since XProtect only has a small number of infrequently updated signatures the attacker will likely have to adapt to beat 3rd-party AV long before this anyway.
- Only covers files with the quarantine bit set that are run via LaunchServices. Malware delivered by binaries that haven't opted-in with LSFileQuarantineEnabled won't be detected, and malware that writes files outside the normal APIs (e.g. with a Java browser plugin exploit) probably also won't be detected. Execution via the commandine or POSIX APIs also won't be blocked. Apple is really only targeting the download and double click malware that has been common to-date.
- XProtect relies on unsigned plists for storing signatures and for storing XProtectUpdater version information that controls updates. However, while most mac users continue to run as admin malware doesn't need to target these, it can overwrite the updater itself: one variant of Flashback already did this, which is presumably why the MRT was written and distributed via software update.
Update for Mavericks (10.9)
Some things have changed in 10.9. XProtectUpdater seems to have been removed or subsumed into another part of the OS, possibly part of the regular software update. This seems like a good move considering the comment above about malware attacking it. If I find out more I'll write another post.
Subscribe to:
Posts (Atom)

