Publisher and Table for Event Tap Capture (KeyDown) (#3829)

This commit is contained in:
Mitchell Grenier 2017-10-16 13:07:24 -07:00 committed by Teddy Reed
parent 869ac6fe5e
commit cd88cecc9a
4 changed files with 206 additions and 0 deletions

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include <osquery/flags.h>
#include "osquery/events/darwin/event_taps.h"
namespace osquery {
/// Flag that turns the eventing system for event taps on or off
FLAG(bool,
enable_keyboard_events,
false,
"Enable listening for keyboard events");
REGISTER(EventTappingEventPublisher, "event_publisher", "event_tapping");
CGEventRef EventTappingEventPublisher::eventCallback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void* refcon) {
auto ec = createEventContext();
EventFactory::fire<EventTappingEventPublisher>(ec);
return event;
}
Status EventTappingEventPublisher::setUp() {
if (!FLAGS_enable_keyboard_events) {
return Status(1, "Publisher disabled via configuration");
}
return Status(0);
}
void EventTappingEventPublisher::tearDown() {
stop();
}
void EventTappingEventPublisher::stop() {
WriteLock lock(run_loop_mutex_);
if (run_loop_source_ != nullptr) {
CFRunLoopRemoveSource(run_loop_, run_loop_source_, kCFRunLoopCommonModes);
CFRelease(run_loop_source_);
run_loop_source_ = nullptr;
}
if (run_loop_ != nullptr) {
CFRunLoopStop(run_loop_);
run_loop_ = nullptr;
}
}
void EventTappingEventPublisher::restart() {
stop();
WriteLock lock(run_loop_mutex_);
run_loop_ = CFRunLoopGetCurrent();
CGEventMask eventMask = (1 << kCGEventKeyDown);
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly,
eventMask,
eventCallback,
NULL);
run_loop_source_ =
CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(run_loop_, run_loop_source_, kCFRunLoopCommonModes);
CGEventTapEnable(eventTap, true);
CFRelease(eventTap);
}
Status EventTappingEventPublisher::run() {
restart();
CFRunLoopRun();
return Status(0);
}
bool EventTappingEventPublisher::shouldFire(
const EventTappingSubscriptionContextRef& mc,
const EventTappingEventContextRef& ec) const {
return true;
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#pragma once
#include <ApplicationServices/ApplicationServices.h>
#include <osquery/events.h>
namespace osquery {
struct EventTappingSubscriptionContext : public SubscriptionContext {};
struct EventTappingEventContext : public EventContext {};
using EventTappingEventContextRef = std::shared_ptr<EventTappingEventContext>;
using EventTappingSubscriptionContextRef =
std::shared_ptr<EventTappingSubscriptionContext>;
/// This is a dispatched service that handles published EventTapping events.
class EventTappingConsumerRunner;
class EventTappingEventPublisher
: public EventPublisher<EventTappingSubscriptionContext,
EventTappingEventContext> {
DECLARE_PUBLISHER("event_tapping");
public:
Status setUp() override;
void tearDown() override;
void stop() override;
void restart();
Status run() override;
EventTappingEventPublisher() : EventPublisher() {}
virtual ~EventTappingEventPublisher() {
tearDown();
}
private:
/// Apply normal subscription to event matching logic.
bool shouldFire(const EventTappingSubscriptionContextRef& mc,
const EventTappingEventContextRef& ec) const override;
static CGEventRef eventCallback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void* refcon);
/// This publisher thread's runloop.
CFRunLoopSourceRef run_loop_source_{nullptr};
CFRunLoopRef run_loop_{nullptr};
/// Storage/container operations protection mutex.
mutable Mutex run_loop_mutex_;
};
} // namespace osquery

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include "osquery/events/darwin/event_taps.h"
namespace osquery {
class EventTapsKeySubscriber
: public EventSubscriber<EventTappingEventPublisher> {
public:
Status init() override {
return Status(0);
}
void configure() override;
Status Callback(const EventTappingEventContextRef& ec,
const EventTappingSubscriptionContextRef& sc);
};
REGISTER(EventTapsKeySubscriber, "event_subscriber", "key_events");
void EventTapsKeySubscriber::configure() {
auto sc = createSubscriptionContext();
subscribe(&EventTapsKeySubscriber::Callback, sc);
}
Status EventTapsKeySubscriber::Callback(
const EventTappingEventContextRef& ec,
const EventTappingSubscriptionContextRef& sc) {
Row r;
add(r);
return Status(0);
}
} // namespace osquery

View File

@ -0,0 +1,7 @@
table_name("key_events")
description("Track key events.")
schema([
Column("time", BIGINT, "Time")
])
attributes(event_subscriber=True)
implementation("events/darwin/key_events@key_events::genTable")