- You cannot expect your users to change DYLDLIBRARYPATH. The correct solution is to include non-standard libraries with the.app and the user won't have to do anything. The developer, however, may still have to hack the loader path as per my answer. – trojanfoe Feb 4 '19 at 8:00.
- After plugging in the drive to your Mac, navigate to Disk Utility, select the disk and then format it (screenshot below). Click the disk on the left column (in this example, Seagate FreeAgent), then the “Erase” button at the top of the disk utility screen. At this point, you can give the disk a name and select the formatting options.
- Macintosh HD usr lib dyld. There are a tremendous more.exe 's,.app 's, files, etc, etc. I haven't ever encountered this data before on the OS X, especially after doing a Clean Install of OS X in Recovery, again, and again.
After my recent blog post, my old mate @_Dark_Knight_ reached out to me and he asked me a question:
DYLD, 0x1 Library missing. 2020-07-08 15:30:10.113 +0200 OS Version: Mac OS X 10.15.5 (19F101) Report Version: 12 Anonymous UUID: 85FFB3B5-2E09. DYLD, 0x1 Library missing (mac) #896. Closed cdekok opened this issue Jan 17, 2017 4 comments Closed DYLD, 0x1 Library missing (mac) #896.
“Do you typically callout user apps that allow dyld_insert_libraries?”
And a few similar ones, and I will be honest, I had no idea what is he talking about, if only I understood the question :D Despite the fact that my recent blog posts and talks are about macOS, I deal much more with Windows on a daily basis, probably like 95%, and macOS is still a whole new territory for me. So I decided to dig into the question and learn a bit more about this.
As it turns out there is a very well known injection technique for macOS utilizing DYLD_INSERT_LIBRARIES
environment variable. Here is the description of the variable from the dyld man document:
In short, it will load any dylibs you specify in this variable before the program loads, essentially injecting a dylib into the application. Let’s try it! I took my previous dylib code I used when playing with dylib hijacking:
Compile:
For a quick test I made a sophisticated hello world C code, and tried it with that. In order to set the environment variable for the application to be executed, you need to specify DYLD_INSERT_LIBRARIES=[path to your dylib]
in the command line. Here is how it looks like:
Executing my favourite note taker application, Bear (where I’m writing this right now) is also affected:
We can also see all these events in the log (as our dylib puts there a message):
There are two nice examples in the following blog posts about how to hook the application itself:
I will not repeat those, so if you are interested please read those.
Can you prevent this infection? Michael mentioned that you can do it by adding a RESTRICTED segment at compile time, so I decided to research it more. According to Blocking Code Injection on iOS and OS X there are three cases when this environment variable will be ignored:
- setuid and/or setgid bits are set
- restricted by entitlements
- restricted segment
We can actually see this in the source code of dyld - this is an older version, but it’s also more readable: https://opensource.apple.com/source/dyld/dyld-210.2.3/src/dyld.cpp
The function pruneEnvironmentVariables
will remove the environment variables:
If we search where the variable sRestrictedReason
is set, we arrive to the function processRestricted
:
This is the code segment that will identify the restricted segment:
Now, the above is the old source code, that was referred in the article above - since then it has evolved. The latest available code is dyld.cpp looks slightly more complicated, but essentially the same idea. Here is the relevant code segment, that sets the restriction, and the one that returns it (configureProcessRestrictions , processIsRestricted
):
It will set the gLinkContext.allowEnvVarsPath
to false if:
- The main executable has restricted segment
- suid / guid bits are set
- SIP is enabled (if anyone wonders
CSR_ALLOW_TASK_FOR_PID
is a SIP boot configuration flag, but I don’t know much more about it) and the program has theCS_RESTRICT
flag (on OSX = program was signed with entitlements)
But! It’s unset if CS_REQUIRE_LV
is set. What this flag does? If it’s set for the main binary, it means that the loader will verify every single dylib loaded into the application, if they were signed with the same key as the main executable. If we think about this it kinda makes sense, as you can only inject a dylib to the application that was developed by the same person. You can only abuse this if you have access to that code signing certificate - or not, more on that later ;).
There is another option to protect the application, and it’s enabling Hardened Runtime. Then if you want, you can specifically enable DYLD environment variables: Allow DYLD Environment Variables Entitlement - Entitlements. The above source code seems to be dated back to 2013, and this option is only available since Mojave (10.14), which was released last year (2018), probably this is why we don’t see anything about this in the source code.
For the record, these are the values of the CS flags, taken from cs_blobs.h
This was the theory, let’s see all of these in practice, if they indeed work as advertised. I will create an Xcode project and modify the configuration as needed. Before that we can use our original code for the SUID bit testing, and as we can see it works as expected:
Interestingly, in the past, there was an LPE bug from incorrectly handling one of the environment variables, and with SUID files, you could achieve privilege escalation, here you can read the details:OS X 10.10 DYLD_PRINT_TO_FILE Local Privilege Escalation Vulnerability | SektionEins GmbH
I created a complete blank Cocoa App for testing the other stuff. I also export the environment variable, so we don’t need to specify it always:
If we compile it, and run as default, we can see that dylib is injected:
To have a restricted section, on the Build Settings -> Linking -> Other linker flags
let’s set this value:
If we recompile, we will see a whole bunch of errors, that dylibs are being ignored, like these:
Our dylib is also not loaded, so indeed it works as expected. We can verify the segment being present with the size command, and indeed we can see it there:
Alternatively we can use the otool -l [path to the binary]
command for the same purpose, the output will be slightly different.
Next one is setting the app to have ( hardened runtime ), we can do this at the Build Settings -> Signing -> Enable Hardened Runtime
or at the Capabilities section. If we do this and rebuild the app, and try to run it, we get the following error:
If I code sign my dylib using the same certificate the dylib will be loaded:
Dyld 0x1 Library Missing In Macomb County
If I use another certificate for code signing, it won’t be loaded as you can see below. I want to highlight that this verification is always being done, it’s not a Gatekeeper thing.
Interestingly, even if I set the com.apple.security.cs.allow-dyld-environment-variables
entitlement at the capabilities page, I can’t load a dylib with other signature. Not sure what I’m doing wrong.
To move on, let’s set the library validation (CS_REQUIRE_LV
) requirement for the application. It can be done, by going to Build Settings -> Signing -> Other Code Signing Flags
and set it to -o library
. If we recompile and check the code signature for our binary, we can see it enabled:
And we get the same error message as with the hardened runtime if we try to load a dylib with different signer.
The last item to try would be to set the CS_RESTRICT
flag, but the only thing I found about this is that it’s a special flag only set for Apple binaries. If anyone can give more background, let me know, I’m curious. The only thing I could do to verify it, is trying to inject to an Apple binary, which doesn’t have the previous flags set, not a suid file neither has a RESTRICTED segment. Interestingly the CS_RESTRICT
flag is not reflected by the code signing utility. I picked up Disk Utility. Indeed our dylib is not loaded:
I would say that’s all, but no. Let’s go back to the fact that you can inject a dylib even to SUID files if the CS_REQUIRE_LV
flag is set. (In fact probably also to files with the CS_RUNTIME
flag). Yes, only dylibs with the same signature, but there is a potential (although small) for privilege escalation. To show, I modified my dylib:
Let’s sign this, and the test program with the same certificate and set the SUID bit for the test binary and run it. As we can see we can inject a dylib as expected and indeed it will run as root.
In theory you need one of the following to exploit this:
- Have the code signing certificate of the original executable (very unlikely)
- Have write access to the folder, where the file with SUID bit present -> in this case you can sign the file with your own certificate (code sign will replace the file you sign, so it will delete the original and create a new - this is possible because on *nix systems you can delete files from directories, where you are the owner even if the file is owned by root), wait for the SUID bit to be restored (fingers crossed) and finally inject your own dylib. You would think that such scenario wouldn’t exist, but I did find an example for it.
Here is a quick and dirty python script to find #2 items, mostly put together from StackOverflow :D
One last thought on this topic is GateKeeper. You can inject quarantine flagged binaries in Mojave, which in fact is pretty much expected.
However it doesn’t work anymore on Catalina, which is also expected with the introduced changes:
We got a very similar error message as before:
I think applications should protect themselves against this type of dylib injection, and as it stands, it’s pretty easy to do, you have a handful of options, so there is really no reason not to do so. As Apple is moving towards notarization hardened runtime will be enabled slowly for most/all applications (it is mandatory for notarised apps), so hopefully this injection technique will fade away slowly. If you develop an app where you set the SUID bit, be sure to properly set permissions for the parent folder.
GIST link to codes:DYLD_INSERT_LIBRARIES DYLIB injection in macOS / OSX deep dive · GitHub
If you have tried to install OneDrive or CorelDRAW 2019 on a Mac and have received failure messages, read on.
TL;DR – The issue may be with the way your drive is formatted. Mac gives several options to format drives, including case sensitivity (for more information on what that means, see this). Reformatting the operating system (OS) drive to a file system without case sensitivity solved the problem.
Crash Log
Below is the crash log data from the failed CorelDRAW installation:
System Integrity Protection: enabled
Crashed Thread:0
Exception Type:EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:EXC_CORPSE_NOTIFY
Termination Reason:DYLD, [0x1] Library missing
Application Specific Information:
dyld: launch, loading dependent libraries
Dyld Error Message:
Library not loaded: /Library/Preferences/*/libPASMUtility.dylib
Referenced from: /Library/Corel/*/Common.bundle/Contents/MacOS/CrlConfig.dylib
Reason: image not found
Binary Images:
0x10f035000 –0x10f038ffb +com.corel.coreldrawsuite.2019.coreldraw (21.2.0.708 – 21.2.0.708) <32411D16-6E77-3D85-BCAC-87D2742DAE63> /Applications/CorelDRAW Graphics Suite 2019/CorelDRAW 2019.app/Contents/MacOS/CorelDRW
0x10f041000 –0x10f07dff7 +CrlConfig.dylib (0) <C1B5BBCC-BE7D-3995-80CC-DB239E29C2BA> /Library/Corel/*/Common.bundle/Contents/MacOS/CrlConfig.dylib
0x10f0e6000 –0x10f2dbff7 +CrlUtils.dylib (0) <E8ACFE58-EFB9-384E-A075-85B81F539EC3> /Library/Corel/*/Common.bundle/Contents/MacOS/CrlUtils.dylib
0x10f413000 –0x10f500fff +CrlUtl.dylib (0) <4431A68A-98A9-3DD1-91B0-27739541AC0D> /Library/Corel/*/Common.bundle/Contents/MacOS/CrlUtl.dylib
0x10f67f000 –0x10f67fffb +CrlBoxInfo.dylib (0) <B4B51B54-595F-3D46-BB0E-64697FC55F29> /Library/Corel/*/Common.bundle/Contents/MacOS/CrlBoxInfo.dylib
0x10f688000 –0x10f691ff7 +CrlUtf.dylib (0) <A703F48E-BC29-3B02-826E-A13797B6AAB9> /Library/Corel/*/Common.bundle/Contents/MacOS/CrlUtf.dylib
0x111d15000 –0x111da5b5fdyld (733.6) <DAFEA246-2F9A-3DCB-A37C-4246D4F92770> /usr/lib/dyld
0x7fff63805000 – 0x7fff63806ff3libSystem.B.dylib (1281) <1DD1BCD2-2C85-3B81-8CAF-224FB042F441> /usr/lib/libSystem.B.dylib
0x7fff63ae3000 – 0x7fff63b36ffflibc++.1.dylib (800.7) <1D42387D-206A-3F06-9B5F-705B83EAC295> /usr/lib/libc++.1.dylib
0x7fff65645000 – 0x7fff65676ff6libobjc.A.dylib (781) <D866A31E-5CB1-3327-8D22-C4F83C9225D0> /usr/lib/libobjc.A.dylib
<snipped>
Thinking there was some library files missing based on the above log, I tried to correct that, which did not solve the problem. There were several people with the same problem on discussion forums, but I did not see any resolution to the questions. Coincidentally, I was also trying to install Microsoft OneDrive on my Mac and it also failed, but Microsoft’s crash logs provided a bit more context. According to those logs, it was because of the case sensitivity formatting of my Mac’s hard drive (I was using APFS – Case-sensitive, encrypted). This was the first time I’ve ever had anything fail like this.
Dyld 0x1 Library Missing In Macon Ga
Solution
Step 1 – Make a complete Time Machine backup of your Mac on a different disk for disaster recovery purposes. The Time Machine backup will not help with the rest of this because restoring a Time Machine backup also restores the drive’s original formatting.
Step 2 – Get an external hard drive that is the same size or larger than your OS drive. Format this drive in a format that is NOT case-sensitive. I used Mac OS Extended (Journaled). After plugging in the drive to your Mac, navigate to Disk Utility, select the disk and then format it (screenshot below).
Click the disk on the left column (in this example, Seagate FreeAgent), then the “Erase” button at the top of the disk utility screen. At this point, you can give the disk a name and select the formatting options. Select with APFS or Mac OS Extended (Journaled). Don’t worry about encryption now, we will do that later.
Dyld 0x1 Library Missing In Macomb County
Note – There is some information out there about performance with different file systems on different drives. The recommendation is that spinning disks should use Mac OS Extended and solid state drives (SSD) should use APFS.
Step 3 – Create a bootable clone of your Mac OS drive. There are several ways to do this, but I used Carbon Copy Cloner. It worked perfectly and they have a free trial if you want to try it out (note – I have no relationship with this company and get nothing for suggesting this).
Carbon Copy Cloner has a clean interface and is easy to use. Simply select your source drive (your Mac OS drive) and your destination drive (the external drive you just formatted) and begin the clone. At the completion, your cloned drive should be bootable.
Step 4 – Tell your Mac to boot from your external hard drive that contains the cloned image of your Mac. To do this, navigate to system preferences > Startup Disk and then select the external drive. Reboot your computer.
Step 5 – Once rebooted to the cloned external drive, open up disk utility and by using the same steps from step 2 above, format your internal Mac OS drive to a format not using case-sensitivity. I chose APFS and did not select encrypted, yet. We’ll do that at the end.
Step 6 – After the internal drive has been formatted, launch Carbon Copy Cloner and reverse the previous process. You’ll now restore your cloned copy from the external drive to the freshly formatted internal drive. Note – I experienced some delays in the restoration and found two problems: 1) spotlight was trying to index the external drive, and 2) my endpoint protection software was scanning all files as they were being copied. I disabled both spotlight indexing and endpoint protection temporarily, stopped the copying process and then restarted it. It made a huge difference. Carbon Copy Cloner has a blog post about this here.
Step 7 – Once the transfer has completed, go back to System Preferences > Startup Disk and select your internal OS drive as the startup disk. Reboot your Mac to the internal drive. You may see your Mac validating different software packages and you might need to re-authenticate with some cloud-based services, but everything should be functional.
Step 8 (Optional, but highly recommended) – If everything is functioning as expected, apply FileVault encryption to your Mac OS drive. Navigate to System Preferences > Security & Privacy > FileVault and turn on FileVault. This will begin encrypting your OS drive immediately. Make sure to either copy down the recovery key or store it in iCloud. Side note – storing your recovery key in the cloud is handy, but it also means that if your cloud storage is accessed (either via a cyberattack or by law enforcement with a search warrant) the recovery code can be obtained and used to access your Mac. If you are worried about your privacy, it is not recommended to store this recovery key in the cloud.
Step 9 – Erase your external hard drives (you should have two, one with the Carbon Copy Cloner and the other with a Time Machine backup). Remember, you have two full backups of your Mac drive on the external drives and they are not encrypted. It is recommended that you use Mac’s built in tool to securely erase the drive. To do this, navigate to Disk Utility, select the disk from the left column, and click “Erase” on the top of the screen. Next, give your disk a name (if you want), select your formatting and scheme, and then click “Security Options”.
Security Options provides you with several choices. Essentially, you are selecting how many passes of data your Mac will write to the drive to ensure that no remnant of data will be available for someone with forensic expertise. Selecting the first choice of one pass of random data and a second pass of all zeros is perfectly acceptable and the fastest option.
Step 10 – As your OS disk is being encrypted and you are wiping your external backup disk(s), try to reinstall OneDrive, CorelDRAW or whatever app you were having difficulties with. Immediately after I went through these steps, I successfully installed both programs.
Step 11 – Now that your Mac is properly formatted and you have tested everything, it is time to make a full Time Machine backup or clone.
Did this work for you? Please leave comments below if you have questions or if this solved a similar challenge you had with these applications or something else.