how to mach_inject without sudo - macos

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.

Related

Packaging a Gtk3 app for Windows for the Microsoft store

Has anyone been successful at packaging a Gtk3 app for Windows for the Microsoft store?
I'm playing with this at the moment:
Visual Studio 2019;
Gtk3/Gtkmm distro obtained via vcpkg;
C++ app;
VS Application Packaging Project.
The application runs fine on its own. I then package it, and then run the MSIX bundle installer. When I then run the installed application, it starts but:
an Access Denied error appears in a dialog box;
the application appears with broken icons and incorrect colors (wrong or no theme).
I have tracked the error having to do with Gio-2.DLL where it attempts to spawn a child process, looks like something to do with creating a dbus server/session (??). I believe the child process (dbus server?) starts but then attempts to do something that is not permitted in the sandbox that Windows creates for the app.
Anyone?
After some more investigation, I may have found a workaround. I'll post it here in case it helps anyone else. This workaround allows making a packaged Gtk3 application for Windows. A Windows packaged application runs in a sandbox of sorts, with heavily restricted access to resources outside the package.
First, the issue: during initialization, the version of Gio-2.DLL for Windows spawns a child process to serve as a DBus session daemon (I may get the terminology wrong here as I'm not that familiar with DBus). It does so only for the first instance. If one launches additional instances of applications that use Gio-2.DLL, the additional instances use the existing daemon from the first instance.
To launch the daemon, Gio-2.DLL calls CreateProcess() to fork a RUNDLL32.EXE child, with the full path to Gio-2.DLL (i.e. itself), and g_win32_run_session_bus() as the name of the function to call. It looks like RUNDLL32.EXE does launch successfully, since it is able to display the "RUNDLL" error dialog box. However it fails to make the requested function call into Gio-2.DLL. I gather that at least one of the system calls that RUNDLL32.EXE makes to load the DLL and call the requested function is prohibited when running in a packaged application.
At the moment, my workaround is this. Assume my application executable is called 'myapp.exe':
the application package contains myapp.exe, all the necessary DLLs for Gtk3 and dependencies, and another executable 'dbus_daemon_launcher.exe';
before entering the Gtk main loop, myapp.exe calls CreateProcess() to start dbus_daemon_launcher.exe;
dbus_daemon_launcher.exe is also linked with Gio-2.DLL and makes a call to g_win32_run_session_bus() with the DLL;
myapp.exe then proceeds to start the Gtk main loop. Since the Dbus daemon is then already running, Gio-2.DLL does not attempt to call RUNDLL32.EXE to launch it, which avoids the error.
This workaround has the advantage that it does not require making a custom version of Gio-2.DLL. Also, I'm using Gtk3: perhaps this issue has been addressed in the more recent Gtk4, and the workaround is unnecessary in this case.

How to call system open from bash script

I've hooked the system call to typedef int (*orig_open_f_type)(const char *__file, int __oflag, ...); and thus, whenever a file gets opened, my code gets the event before it is passed on to the system. I created a dynamic library that overrides the open call and inject this library using DYLD_INSERT_LIBRARIES - working on a Mac machine and using XCode. It is a standard step that enables me to hook calls.
Now, I have bash script in which I have some files that I want to open. I have tried xdg-open , cat, exec - but they are not triggering the system call to open the file.
How should I invoke this open call in my bash script?
Please note that I have tested my open call hook, by opening files in C code.
I believe you're running foul of Apple's SIP (System Integrity Protection) which is designed to stop people doing things like that with system-provided executables. SIP was added to Mac OS X El Capitan (10.11) and continues in macOS Sierra (10.12).
To demonstrate whether this is the problem, consider copying /bin/cat to /usr/local/bin/cat and then try hooking (running) the local copy. You might get away with it there. This 'workaround' is purely for demonstration purposes. Basically, if I'm right, SIP is Apple's way of saying "don't go messing with our software".
You can follow links from Can Mac OS X El Capitan run software compiled for Yosemite that expects libraries in /usr/gnu/lib? to find out more about SIP. Following links via What is the "rootless" feature in El Capitan, really? on Ask Different to a blog article on System Integrity Protection, it says explicitly:
Runtime protection
SIP’s protections are not limited to protecting the system from filesystem changes. There are also system calls which are now restricted in their functionality.
task_for_pid() / processor_set_tasks() fail with EPERM
Mach special ports are reset on exec(2)
dyld environment variables are ignored
DTrace probes unavailable
However, SIP does not block inspection by the developer of their own applications while they’re being developed. Xcode’s tools will continue to allow apps to be inspected and debugged during the development process.
For more details on this, I recommend taking a look at Apple’s developer documentation for SIP.
Emphasis added
Basically, this means that you won't be able to hook calls to the open() system call for Apple-supplied software installed in the system directories. You will need to rethink what you are trying to do.
Running any normal command -- like cat -- that processes a file will cause the file to be opened. You can also open a file (and immediately close it) using the shell syntax:
: < /path/to/file
If your system call hook isn't getting called, something must be wrong with your hook -- there's no way these commands are working without opening the file. Alas, you haven't explained how you implemented your hook, so we have no way of debugging that.
The file command opens the file to look at its contents.
$ file /path/to/file
I have suggested this because it eventually leads to having the system call open which can be confirmed using strace.
$ strace file /path/to/file 2>&1 | grep open
I thought one of the good things about using file is that it opens the file in read only mode. In comparison to other ideas, unlike cat, it will not have to run through the entire file, just part of it, so the time complexity using file may be constant. Unlike vim, which someone has suggested, file will return when finished and not block like a text editor would.

Launching an application from another process

We have an application that we have built as a bundle and we want to launch it from another process.
How should we do it?
From what I understand we can use openUrls(), openFile() or execve()
but I don't know which one better suits us.
Thanks
Since you're talking about an application, you don't want to go through the file association mechanisms. They're for opening documents, images etc. with an appropriate application. Since you don't seem to be sure what to ask, I'd say keep it simple:
The exec* family launches an executable directly. But note that it replaces the launching process with the launched application. Your launcher will stop executing at that point. If you want the launcher to continue to run, you want to use something that launches a subprocess. The low-level way is fork/vfork followed by exec, but it's far simpler to launch your app with system, which takes care of all that behind the scenes. (Assuming there are no security concerns about users on the other side of the world injecting execution paths).
If the launcher does not terminate as soon as it launches your app, you'll want to think about whether it "blocks" until the launched application terminates, or whether it launches the app asynchronously-- so that they then run in parallel. The launcher might also "wait" for the return value of the app, to check whether it succeeded and maybe do something afterwards. There are ways to do all that, but since we don't know what you need, I won't go into details.
In short: If the only job of your launcher is to start your app, use execl. If your launcher needs to do more, use system. If neither one quite fits your needs, you'll need to provide more information-- starting with the language your launcher is written in.
PS. Both of these have the advantage of generality and portability. They work for GUI and commandline applications, and they'll work on any Unix-like system, and to some extent on Windows. There's no need to lock yourself into Cocoa for something so simple.
If you're using Cocoa, you can use NSWorkspace's -launchApplication:.
From OSX documentation on NSWorkspaces:
openFile: Opens the specified file specified using the default application associated with its type.
openURL: Opens the location at the specified URL.
With url you can open also file on ftp, or http for example.

Mac OS X app sandbox issue

I am writing a command line tool. There I'd like to create a directory in the /Users/user_name/Library directory. When I run that program from Terminal as a root, then everything is ok, but the problem is when I want to use that tool as a backend for cups (that program is called, also as root, when I print something). The program is called, but in the system.log file I found the error: sandboxd: deny file-write-*. I'm a new Mac OS X programmer and I'm not sure how to fix it. Anybody can help me?
Since Snow Leopard cups is running in a sandbox that prevents it from misbehaving - like accessing user's home. Depending on your OS X version you can get away by using another directory, not user's home. On Lion it is even more restrictive than that. The sandboxing rules are built-in to the cups binary (as opposed to sb scripts), so your only luck may be replacing cups with a version that specifically allows access to what you need in the sandbox (if you really want to go there, the rules are defined by cupsdCreateProfile in cups/scheduler/process.c). AFAICT there is nothing you can do in your application, because sandboxing is designed to prevent exactly what you are trying to do.
Another alternative is to not run cups as root, because sandboxing is only used when cups is run as root.

How to implement an automatic update detection model

Our software is not ever officially installed on Windows, and currently has an update model like this:
Connect to Internet
Click an Update Button
Connect to server-side program
Server-side program creates an md5 hash list of all the files in
the server program directory.
Client-side program creates an md5 hash list of all the files in
the client program directory.
A comparison is done to see if a file needs updated, removed from, or added
to the client's machine, and it does so until complete.
Well, I would like to move to a model I see used more frequently these days where the software is officially installed and something like this happens:
When an internet connection is detected, the program will automatically query the
server to see if there is an updated installation package.
If so, ask the user if they would like to download the new install.
If no, do nothing, if yes, download new install.
Programatically uninstall the old program and start the install of the
new package.
The part I need advice on is number 4 above. What is the best way to programmatically uninstall the old program and start the installation of the new program, while running the original program. I assume there must be some intermediary program that does all the work (shutting down the current program, running it's uninstaller, then starting up the new installer) Is there a better way? I just want to move to a model where we update in full installs and not just files - this will allow us to version our software easier and keep self-contained installations to revert to at any point.
Thanks for your advice!
EDIT: Related question - what's the easiest way to find the install UUID for a particular install?
The way I did it was to have a separate program (let's call it StartUp.exe) that checked for updates and then loaded the real software (let's call that Program.exe). StartUp.exe had the same icon as Program.exe and was the executable that was pointed to by the desktop shortcuts and menu items, using the same name as Program.exe.
So the sequence went something like this:
User double-clicks desktop shortcut or menu item that looks like Program.exe and is called the same name but is actually StartUp.exe
StartUp.exe runs and checks if there are any updates
If there are updates, it simply copies then across (we built a nice system with progress bars but you could simply copy the new files over the old files)
StartUp.exe then runs Program.exe
StartUp.exe then exits
This has the advantage that none of your program files are locked because the loader program is actually a different program. The user is none the wiser because they run a program that looks like and is called the same as the program they want to run and the end result is the program they want does run and is guaranteed to be the most up to date version.
Doing it with an update button would be more complex but we needed to force the most recent version of the program to be the one running (due to database differences between versions) so forcing update on startup worked for us.
I believe the way to do it these days is to use ClickOnce deployment but I've never tried that - it wasn't available when I wrote my system and this method was simple and worked well.

Resources