I have a small project which implements function hooking in MAC using mach_override() by Jonathan 'Wolf' Rentzsch:https://github.com/rentzsch/mach_override
I have hooked one of the functions of kextstat process from mac.
So when I am executing
$kextstat
OSX is killing this process saying below error:
CODE SIGNING: process 2211[kextstat]: rejecting invalid page at
address 0x7fff5132d000 from offset 0xca53000 in file
"/private/var/db/dyld/dyld_shared_cache_x86_64h"
(cs_mtime:1531207073.366350606 == mtime:1531207073.366350606)
(signed:0 validated:0 tainted:0 nx:0 wpmapped:1 dirty:1 depth:2)
my dynamic library is code-signed.
In my initial observation, i could conclude that mach_override() function in failing in following code:
atomic_mov64((uint64_t *)originalFunctionPtr,
jumpRelativeInstruction);
above code could be found : mach_override.c:342
https://github.com/rentzsch/mach_override
Firstly, you should note that public discussion of Apple's Developer Beta software is a breach of Apple's terms and conditions. Such questions should be posted to Apple's forums, which has a specific section for Beta releases.
That being said, the technology and problem you're seeing is SIP, which includes denial of code injection, as well as protecting system files from being overwritten. The detail that follows is nothing new and exists in pre 10.14 macOS builds, though disabled (by default) in those versions.
When an application is signed, it creates a hash of each file page in the binary, and a super hash of all those hashes. During execution of a binary, when a page fault occurs, or a file (e.g. dylib) is mmap'd into the executing process, amfid (Apple Mobile File Integrity daemon) verifies that the new code is signed and that its signature matches that of the executing binary. If the signature or hashes do not match, then the code is denied loading, or in some cases, the process is killed.
In this case, kextstat contains an Apple certificate that does not match the certificate of your code that you're attempting to inject into kextstat. In addition, the certificate of kexstat includes the platform binary flag, which Developer certificates do not have.
Without a zero-day vulnerability, you're not going to be able to hook kextstat in a commercial environment. If it's just research you want to do, then you can either disable SIP, or remove the signature from the kextstat binary, causing amfid to ignore the certificate verification.
Related
I used to be able to use mach_override to hook any exported function on Mac OS including Catalina. However, now the target app crashed every time and I check the Console and find the following error:
CODE SIGNING: 30911[app] vm_map_protect can't have both write and exec at the same time
What's going on and is that possible I can bypass it without touching the target app's signature?
The hardened runtime is designed specifically to prevent that sort of hooking. The target app's entitlements would have to opt-in to allowing it. If you find a way around it, Apple would consider that a security hole bug and patch it in a future OS release.
It should work if you disable System Integrity Protection, but I don't know if that suits your purpose.
OSX El Capitan and Go 1.6
What I want is simpler than it sounds from the title.
The OSX firewall disallows any unknown application from accepting connections. When any such program starts, the user is presented with a dialog whether or not the said executable should be permitted to receive connections. The user's choice is then remembered.
The above works fine when for example one develops with node where the actual executable is a single binary and the user just needs to allow/deny it once.
When developing in go (and any other compiled language) the created executable is different every time. Which means I get the dialog every single time I start my server.
One way to avoid this dialog is to sign the executable with a self-signed certificate one generates in OSX itself. Once we have the certificate we simply sign the executable and allow/deny it once. Code signatures are always remembered even if the executable binary changes.
So, my question is:
Is there a way to make go run the signing command before running the compiled binary?
Even easier: start the server explicitly on localhost, like:
http.ListenAndServe("localhost:8080", nil)
I wrote a little piece on this recently:
suppressing-accept-incoming-network-connections-warnings-on-osx
Silly me. Took me 5 minutes to write the question and 2 minutes to find the answer and write the script that solves it. I'll post it here in case anybody stumbles on the same problem.
binary=$GOPATH/pkg/kliron/hiss/hiss.a
go build -o $binary hiss/main.go
codesign -f -s klironCode $binary --deep
$binary "$#"
Just use go build.
I'm signing a .dmg containing a .app with a valid Developer ID profile. Everything is signed, frameworks included. When I run codesign -dvvv, the right certificate appears and satisfies its Designated Requirement. The application runs fine.
However, when I upload and download the .dmg, the signature "disappears". When I run codesign -dvvv, it says code object is not signed at all. And GateKeeper naturally refuses to run the application.
Note: it sounds a lot like this issue but I'm definitely signing with the right Developer ID certificate, and the .dmg does not appear "damaged".
[Note: the situation changed significantly in OS X v10.11.5 and v10.12; this answer has been updated to reflect that.]
In general, the thing you really need to sign is the files (mainly the app) inside the disk image, not the image itself. After the image is downloaded, the signature on the individual items will be checked as they are used. Starting in OS X 10.11.5, signing disk images is properly supported and sometimes required, but that's in addition to signing the relevant items inside it.
Through OS X v10.11.4, you could sign the disk image itself (with codesign -s "Developer ID Application: [your company]" example.dmg), but the signature this creates is stored in the form of extended attributes attached to the image file. Actually, it creates three xattrs, named com.apple.cs.CodeDirectory, com.apple.cs.CodeRequirements, and com.apple.cs.CodeSignature. The critical thing to realize is that these attributes are filesystem metadata -- that is, they're attached to the file, not part of the file's contents. The HTTP protocol has very limited support for filesystem metadata, so when you upload or download via HTTP (or FTP or...), it only transfers the file's contents, and the xattrs are lost.
You can see the xattrs with the ls -l# command (and in even more detail with the xattr command):
$ ls -l# example.dmg
-rw-r--r--# 1 gordon staff 338590 Nov 13 2013 example.dmg
com.apple.cs.CodeDirectory 120
com.apple.cs.CodeRequirements 172
com.apple.cs.CodeSignature 8515
com.apple.diskimages.fsck 20
com.apple.diskimages.recentcksum 81
After downloading, the image will have lost those attributes (and probably gained com.apple.quarantine and com.apple.metadata:kMDItemWhereFroms from the download process), and hence will not be considered signed. The files contained in it, on the other hand, should still be properly signed (since their signatures are part of the image file's contents.)
Starting in OS X v10.11.5, codesign supports embedding the signature into the disk image itself, so that it will survive being downloaded over HTTP. Starting in v10.12, gatekeeper will enforce additional restrictions on apps in unsigned disk images that will prevent the app from loading additional content (mainly dynamic libraries) from the disk image, unless they're contained inside the app itself. If you don't know whether that's relevant to your app, go ahead and sign the disk image (actually, it's a good idea anyway), but be sure to run codesign under 10.11.5 or later or the signature won't be in a useful format!
I've written a plugin for finder on Mac(mountain lion) and it works perfectly, but I have to run the bundle with sudo. Then I make a package(Packagemaker) to run this bundle and it failed(install correctly and if I run it by clicking desktop icon it failed, if run though commandline with sudo, it works).
Does anybody know how to fix this issue just like installing dropbox (and then sync icon shows)
The problem you're facing is that, internally, mach_inject calls the function task_for_pid.
This function returns the kernel task id for the given process pid and due to security reasons, Apple now requires that use of this function can only take place from users that are members of either the root or procmod groups. This explains why running sudo works for you.
If you're just developing this for just your own use, the simplest method is to add yourself to the procmod group. However, if you want to distribute the application, you'll need to ensure that any installer installs the program to run as a member of the root or procmod groups.
One possibility is to separate your application into two parts, where the second is registered to run with elevated privileges using SMJobBless. If you don't program in Objective-C, don't worry as the actually parts of SMJobBless that are required are just C function calls; look for AuthorizationCopyRights and SMJobBless in the given example code.
Alternatively, if the application is code-signed, that should work too, though it's not something I've tried myself. You can read about that here.
As of OS X 10.11 (El Capitan), task_for_pid is an entitled function call, only available to software with a specific entitlement in its certificate and no longer available to 3rd party developers.
This breaks mach_inject, making it harder to retrieve another process's mach task, whilst SIP (System Integrity Projection) is enabled.
I've just submitted an app to the Mac App Store that uses some external dynamic libraries.
I got an email from Apple saying that:
Invalid Signature - the executable something.app/Contents/Frameworks/some.dylib is not signed, the signature is invalid, or it is not signed with an Apple submission certificate. Refer to the Code Signing and Application Sandboxing Guide for more information.
The problem is of course caused by the fact that I only signed "my" executable, not the libraries.
Is it common/good practice to also sign the libraries, even though they're not written by me?
Think of digitally signing a file as:
A means of verifying the integrity of that file, thus making it possible to detect whether it’s been modified;
A means of verifying who published that file, which is not the same as writing the corresponding source code. You’re attesting that it was really you who’s shipped that file.
Since dynamic libraries contain executable code, it’s good practice (and in some cases, such as the MAS, mandatory) to digitally sign them for the same reason you sign the main executable file: guaranteeing that your application is exactly what you (and only you) have shipped from your build machine, no changes whatsoever. A running program includes the main executable file and all loaded libraries. If you sign the main executable file only, leaving the dynamic libraries unsigned, it would be possible to alter the dynamic libraries (or even replace them), thus changing what your program does.