Post

Replies

Boosts

Views

Activity

Discrepancy between documentation and the actual behavior
I think there's a slight discrepancy between what is being communicated in EndpointSecurity docs, and what is really happening. For example, consider the description of this event: https://developer.apple.com/documentation/endpointsecurity/es_event_type_t/es_event_type_notify_truncate?language=objc "ES_EVENT_TYPE_NOTIFY_TRUNCATE: An identifier for a process that notifies endpoint security that it is truncating a file." But, it seems that this event is fired up only when truncate(2) is called, not when process truncates a file (which can be done in lots of different ways). But the documentation doesn't even mention that it's only about the truncate(2) call, it's impossible to know. Another example: https://developer.apple.com/documentation/endpointsecurity/es_event_type_t/es_event_type_notify_copyfile?language=objc "ES_EVENT_TYPE_NOTIFY_COPYFILE: An identifier for a process that notifies endpoint security that it is copying a file." It seems that this event is only called when copyfile(3) syscall is called. But the docs doesn't mention that syscall at all. The wording suggests that the event should be emitted on every file copy operation, which is probably impossible to detect. I mean, I get that you'd like the docs to be "easy to digest", but I think that such working confuses people. They expect one thing, then they get confusing behavior from ES, because it doesn't match their expectations, and after reaching out to Apple they get concise and clear answer -- but it would be easier for everyone (including Apple devs) when this answer would be included directly in the official docs for the framework.
2
0
251
Oct ’24
EndpointSecurity and network events
Hello, I know that EndpointSecurity doesn't support network events, save for some events related to Unix pipes. In WWDC 2020 #10159 Apple says that: Those of you who have already worked with the EndpointSecurity framework have likely noticed that we do not provide events related to networking operations. This is intentional as these are better covered by the NetworkExtension framework. Could you please give me a short and high-level hint how I can use NetworkExtension to provide connect, disconnect events to a monitoring app, that tries to log those events in a database? I would like to receive the remote IP and remote port + local port. From what I've researched, In NetworkExtension documentation it's stated that it's possible to create a "content filter", which would probably be a good source of information; the problem is that because of the privacy requirements, the "content filter" can't send back any information about user data, because it's separated in a restrictive sandbox. So I'm not sure the "content filter" would even be possible to be used as a source of network events. Other types of categories inside NetworkExtension doesn't seem to be a good match for my use case. Is it possible to use NetworkExtension to get information about network events (connect/disconnect), like EndpointSecurity does for i.e. processes (process start/process end)?
3
0
797
Mar ’24
Multiple problems with ES_EVENT_TYPE_NOTIFY_DUP
Hello, 3 questions regarding Endpoint Security Framework: Does ESF support tracing the dup2(2) function? There is the ES_EVENT_TYPE_NOTIFY_DUP event, but it seems that it only reports dup(2), not dup2(2)? Does ESF support tracing the dup(2), and close(2) calls, if the file descriptor passed to these functions refer to a pipe handle instead of a file handle? If not, do you have any plans of extending the support for pipes as well? Could the es_event_dup_t structure support reporting which file handle has been duplicated into which value (source file descriptor value, and target file descriptor value)? Currently this structure only supports the "target" file object, without any information which file descriptor has been cloned into which file descriptor, which is not helpful at all. For example, if we open file A and we get fd1, then open the same file A and we get fd2, then perform dup(fd1), then with ESF it seems that it's impossible to tell if we've duplicated fd1 or fd2. Also this model doesn't support dup2(2) usage at all.
4
0
719
Mar ’24
Notarization and hot-update feature of an app
Hello, we have an app (a service) that contains an auto-update feature. This auto-update feature allows to update certain components, packaged as dylib files: 1 component = 1 dylib file. Those dylib files are written in a way that the app can unload the old versions and load new versions without restarting itself. So, when the user clicks "update", the app will download new dylibs from the company server, it will unload old dylibs, load new ones, and will start using new dylibs immediately. The dylibs are digitally signed with the same digital sign that was used to sign all the executables in the app. I'm wondering how to solve the notarization problem for this case. Since notarization is a process that results in acquiring a "staple id" that should be placed inside the Contents/CodeResources file, does that mean that it's impossible to distribute "*****" MachO files that are not a part of any bundle? Because those "*****" MachO files do not have any place that allows to embed a "staple id". Do I understand it correctly? Is there a method of embedding a "staple id" any other way than inside the Contents/CodeResources file? What would be a suggested solution to the "auto-update feature that downloads signed dylib files" problem? Should we wrap dylibs into bundles, and download bundles instead of the "*****" dylibs? (since bundles can be stapled).
9
0
1.8k
Nov ’22
Kernel kills my dylib even though it's properly codesigned
Kernel tells me that my dylib has an invalid digital sign, but for 100% it's a proper digital sign. Is this a bug, or a feature? Minimal 100% reproducible example: loader.cpp: #include <cstdio> #include <iostream> #include <dlfcn.h> int main() {    void* handle = dlopen("libtest.dylib", RTLD_NOW);    perror("dlopen");    return handle == nullptr; } test1.cpp: #include <cstdio> #include <iostream> __attribute__((constructor)) void initfunc() {    std::cout << "hello from dylib1\n"; } test2.cpp: #include <cstdio> #include <iostream> __attribute__((constructor)) void initfunc() { std::cout << "hello from dylib2\n"; } Makefile: all: libtest1.dylib libtest2.dylib loader libtest1.dylib: test1.cpp c++ -shared test1.cpp -o libtest1.dylib libtest2.dylib: test2.cpp c++ -shared test2.cpp -o libtest2.dylib loader: loader.cpp c++ loader.cpp -o loader CMakeLists.txt instead of Makefile: cmake_minimum_required(VERSION 3.5) project(crash_test) add_executable(loader loader.cpp) add_library(test1 SHARED test1.cpp) add_library(test2 SHARED test2.cpp) Store all files into one directory and compile the binaries either by using make or cmake. Reproduction scenario (100%): Run Make or CMake to compile the source files, Copy libtest1.dylib to libtest.dylib: $ cp libtest1.dylib libtest.dylib Run ./loader Observe proper runtime without errors: $ ./loader                   hello from dylib1 dlopen: Undefined error: 0 Copy libtest2.dylib to libtest.dylib: $ cp libtest2.dylib libtest.dylib Run ./loader Observe crash: $ ./loader                         [1]    96122 killed     ./loader Remove libtest.dylib Repeat step 5: Copy libtest2.dylib to libtest.dylib: $ cp libtest2.dylib libtest.dylib Run ./loader and observe everything is OK: $ ./loader                   hello from dylib2 dlopen: Undefined error: 0 Is this a bug or a feature? It seems to me that something is caching codesign information based on file inode. Replacing files seem to retain old inode while storing new data inside previously existing inode. Shouldn't replacing the file invalidate this cache, wherever it is? Is this documented somewhere? Maybe macOS requires me to always remove dylibs before reusing their names? I couldn't see any documentation about that. System information I'm observing this on various macOS machines, on real machines and virtualized using Virtualization.framework. Currently I'm using this macOS version: $ sw_vers                ProductName:    macOS ProductVersion: 12.6 BuildVersion:   21G115
2
0
908
Oct ’22