Post

Replies

Boosts

Views

Activity

Reply to Intercept request headers with AppProxy ?
There is nothing technically stopping you from doing this Great! Given that i don't want to redirect the flow and only modify the headers i think NETransparentProxyProvider might be the better option for me. however this will be something that you need to research on your own I didn't find any information on how to do this. Do you know if there is a function from the NETransparentProxyProvider that can give me access to the headers? Thanks for the help btw :)
Apr ’21
Reply to Intercept request headers with AppProxy ?
Im having trouble understanding how this transparent proxy would work. Given that i only want to modify the headers of this requests flowing through my proxy and not re-route them i should return false in handleNewFlow ? Im trying to follow the link you provided but i can't seem to grasp how this works. let flow: NEAppProxyTCPFlow let connection: NWConnection // Reads from the flow and writes to the remote connection. func outboundCopier() { flow.readData { (data, error) in if error == nil, let readData = data, !readData.isEmpty { connection.send(content: readData, completion: .contentProcessed( { connectionError in // Handle completion success or error. // Set up another read if there is no error. if connectionError == nil { self.outboundCopier() } })) } else { // Handle error case or the read that contains empty data. } } } Where should i create that NWConnection? Should i initialize one with the endpoint data contained in the flow i receive? Also I asume the headers i want are contained in the data from readData but how can interpret this data and modify it?
Apr ’21
Reply to NEFilterSocketFlow remoteHostname property
Yes, I can get the remoteEndpoint populated guard let socketFlow = flow as? NEFilterSocketFlow,     let remoteEndpoint = socketFlow.remoteEndpoint as? NWHostEndpoint,     let localEndpoint = socketFlow.localEndpoint as? NWHostEndpoint else {      return nil }       if #available(macOS 11.0, *) { if let hostname = socketFlow.remoteHostname {      // Access hostname     } }
May ’21
Reply to Process arguments from audit token
Ok so here is what I came up with. This works fine, the only thing I have yet to see is if it has any memory leaks. I hope this helps someone in the future :) If you have any suggestions to the func please let me know. Also, you should first convert the audit_token to pid using the function mentioned above. func getArgs(from pid: Int32) -> [NSString]? {   var arguments: [NSString] = []   var mib: [Int32] = [0, 0, 0]   var argsMax: Int = 0   mib[0] = CTL_KERN   mib[1] = KERN_ARGMAX   var size = MemoryLayout<Int>.stride(ofValue: argsMax)   if sysctl(&mib, 2, &argsMax, &size, nil, 0) == -1 {     return nil   }   let processArgs = UnsafeMutablePointer<CChar>.allocate(capacity: argsMax)   mib[0] = CTL_KERN   mib[1] = KERN_PROCARGS2   mib[2] = pid size = argsMax as size_t   // Get process arguments   if sysctl(&mib, 3, processArgs, &size, nil, 0) == -1 {     return nil   }   if size <= MemoryLayout<Int>.size {     return nil   }   var numberOfArgs: Int32 = 0   //Get number of args   memcpy(&numberOfArgs, processArgs, MemoryLayout.size(ofValue: numberOfArgs)) // Initialize the pointer to the start of args   var parser: UnsafeMutablePointer<CChar> = processArgs + MemoryLayout.size(ofValue: numberOfArgs) // Iterate until NULL terminated path   while parser < &processArgs[size] {     if 0x0 == parser.pointee {       // arrived ar argv[0]       break     }     parser += 1   }   // sanity check   if parser == &processArgs[size] {     return nil   }   while parser < &processArgs[size] {     if 0x0 != parser.pointee {       break     }     parser += 1   }   // sanity check   if parser == &processArgs[size] {     return nil   }   var argStart: UnsafeMutablePointer<CChar>? = parser   // Get all args   while parser < &processArgs[size] {     if parser.pointee == CChar(0) {       if nil != argStart {         let argument = NSString(utf8String: argStart!)         if argument != nil {           arguments.append(argument!)         }       }       argStart = parser + 1       if arguments.count == numberOfArgs {         break       }     }     parser += 1   }   // Is this free necessary?   free(processArgs)   return arguments }
Jun ’21
Reply to Get all Domain names in macos ?
Would this work? Just accessing the NEAppProxyFlow and returning true without having to handle the flow // NEDNSProxyProvider override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { NSLog("DNSProxyProvider: handleFlow") if let tcpFlow = flow as? NEAppProxyTCPFlow { let remoteHost = (tcpFlow.remoteEndpoint as! NWHostEndpoint).hostname let remotePort = (tcpFlow.remoteEndpoint as! NWHostEndpoint).port // Do whatever I want with this data } else if let udpFlow = flow as? NEAppProxyUDPFlow { let localHost = (udpFlow.localEndpoint as! NWHostEndpoint).hostname let localPort = (udpFlow.localEndpoint as! NWHostEndpoint).port // Do whatever I want with this data } return true }
Jun ’21
Reply to How to handle System Extension willCompleteAfterReboot
Another question I had about the willCompleteAfterReboot is why is this called? I want to better understand this problem I am having about extensions needing a reboot to complete an upgrade. What is preventing the system from starting my extension without the need of a reboot? I am using a Network Extension, if I were to add Endpoint Security to my extension would something in the activation process change? I can't see antivirus software that uses this framework requiring a reboot for every update to their extension.
Jul ’21
Reply to Crash when using String(cString:)
Ok I found out what is happening but I need help fixing it. Look at this code // Inside function that handles process exec messages     guard let copiedMessage = copyMessage(msg) else {       es_respond_auth_result(esClient.client!, msg, ES_AUTH_RESULT_ALLOW, false)        return     }     DispatchQueue.global().async { var process: ProcessDetails? = nil        let deadline = copiedMessage.pointee.deadline let semaphore = DispatchSemaphore(value: 0) DispatchQueue.global().async { // This may take some time          process = ProcessDetails(process: copiedMessage.pointee.event.exec.target.pointee) semaphore.signal()       }       _ = semaphore.wait(timeout: DispatchTime(uptimeNanoseconds: deadline - (2 * NSEC_PER_SEC)))       es_respond_auth_result(...)       freeMessage(copiedMessage)     } I am calling description inside my ProcessDetails class, the problem is that if the timeout of the semaphore runs out I will free the copiedMessage but the initialization of ProcessDetails is still going so that results in a crash. How could I kill that seconds thread before freeing the message? Or should I somehow set another semaphore and wait for that thread to finish (even though I already responded to the message) to free the message?
Aug ’22
Reply to Crash when using String(cString:)
As per Quinns request here is a more detailed version of my code static func handleProcessExec(_ msg: UnsafePointer<es_message_t>) {     let target = msg.pointee.event.exec.target.pointee guard msg.pointee.process.pointee.is_es_client == false else {      es_respond_auth_result(esClient.client!, msg, ES_AUTH_RESULT_ALLOW, true)       return     }     // copy message so it can be used on another thread     guard let copiedMessage = copyMessage(msg) else {       es_respond_auth_result(esClient.client!, msg, ES_AUTH_RESULT_DENY, false)       return     }     DispatchQueue.global().async { var process: ProcessDetails? = nil let deadline = DispatchTime(uptimeNanoseconds: copiedMessage.pointee.deadline - (2*NSEC_PER_SEC)) let semaphore = DispatchSemaphore(value: 0) // RuleResult contains what rule matched and if we should allow/deny var result = RuleResult() let timestamp = copiedMessage.pointee.time.tv_sec DispatchQueue.global().async { process = ProcessDetails(process: copiedMessage.pointee.event.exec.target.pointee) ESEventRulesRunner.runProcessExecRules(process: process!, &result) semaphore.signal()        }       _ = semaphore.wait(timeout: deadline)       es_respond_auth_result(esClient.client!, copiedMessage, result.verdict, false)       if result.verdict == ES_AUTH_RESULT_DENY {         // Log event to api let event = ESEvent(process: process!, timestamp: timestamp, ruleType: result.type)         Api.postEvent(event: event) }       freeMessage(copiedMessage)     }       }
Aug ’22
Reply to Apps/files do not open when the result is cached with es_respond_flags_result
Hi, I am having the same issue that Uddalak described. But in my case this only happens when I attach Xcode's debugger to my system extension. As soon as I do it the entire system becomes unresponsive for 30 secs until my app is killed (no crash log). It doesn't matter if I use the 0x7fffffff or 0xffffffff flags or if I cache the response or not. In my event handler block I allow all events, like this: es_respond_flags_result(client, msg, 0x7fffffff, true)
Aug ’22