prey/prey-node-client

View on GitHub
lib/agent/providers/hardware/mac.js

Summary

Maintainability
A
2 hrs
Test Coverage
/* eslint-disable consistent-return */
const { exec } = require('child_process');
const si = require('systeminformation');
const system = require('../../../system/mac/index');

const ramVendors = {
  '0x014F': 'Transcend Information',
  '0x2C00': 'Micron Technology, Inc.',
  '0x802C': 'Micron Technology, Inc.',
  '0x80AD': 'Hynix Semiconductor Inc.',
  '0x80CE': 'Samsung Electronics, Inc.',
  '0xAD00': 'Hynix Semiconductor Inc.',
  '0xCE00': 'Samsung Electronics, Inc.',
};

const parseSystemProfilerProperties = (str) => {
  const obj = {};
  str.toString().split('\n').forEach((line) => {
    if (line !== '') {
      const split = line.split(': ');
      const key = split[0].trim().toLowerCase().replace(/\s/g, '_');
      const val = (split[1] || '').replace(/'/g, '');
      obj[key] = val;
    }
  });
  return obj;
};

const callSystemProfiler = (type, cb) => {
  const cmd = `/usr/sbin/system_profiler ${type}`;
  exec(cmd, cb);
};

const getSystemProfilerData = (type, cb) => {
  callSystemProfiler(type, (err, stdout) => {
    if (err) return cb(err);
    const obj = parseSystemProfilerProperties(stdout);
    cb(null, obj);
  });
};

exports.get_firmware_info = (callback) => {
  getSystemProfilerData('SPHardwareDataType', (err, spData) => {
    if (err) return callback(err);
    const data = {
      device_type: spData.model_name.indexOf('Book') === -1 ? 'Desktop' : 'Laptop',
      model_name: spData.model_name,
      vendor_name: 'Apple',
      bios_vendor: 'Apple',
      bios_version: spData.boot_rom_version,
      mb_version: (system.is_m1_or_m2()) ? system.get_info_chip() : spData['smc_version_(system)'],
      serial_number: spData['serial_number_(system)'],
      uuid: spData.hardware_uuid,
    };
    callback(null, data);
  });
};

exports.get_processor_info = system.get_processor_info;

exports.get_ram_module_list = (cb) => {
  const list = [];
  if (system.is_m1_or_m2()) {
    si.mem((stdoutsi) => {
      list.push({
        bank: 'Bank 0',
        size: (stdoutsi.total / 1024) / 1024,
        speed: null,
        vendor: 'Unknown',
        memory_type: null,
        serial_number: null,
      });
      cb(null, list);
    });
  } else {
    callSystemProfiler('SPMemoryDataType', (err, out) => {
      if (err) return cb(err);
      out.toString().split('BANK').forEach((block) => {
        if (!block.match('Size')) return;
        const parts = block.split('\n\n');
        const obj = parseSystemProfilerProperties(parts[1]);
        list.push({
          bank: `Bank${parts[0]}`,
          size: parseInt(obj.size, 10) * 1024,
          speed: parseInt(obj.speed, 10),
          vendor: ramVendors[obj.manufacturer] || 'Unknown',
          memory_type: obj.type,
          serial_number: obj.serial_number,
        });
      });
      cb(null, list);
    });
  }
};

exports.get_prey_user_version = (cb) => {
  system.get_prey_user_version((err, preyUserVersion) => {
    if (err) return cb(err);
    try {
      return cb(null, preyUserVersion);
    } catch (e) {
      return cb(new Error(`Error:${e.message}`));
    }
  });
};

exports.get_osquery_running = (cb) => {
  exec('ps aux | grep "/opt/osquery/lib/osquery.app/Contents/MacOS/osqueryd --flagfile=/private/var/prey/osquery.flags" | grep "^root" | awk \'{print $2}\' | tr -d \'\\n\'', (err, stdout, stderr) => {
    if (err) return cb(null, false, 'osquery_running');
    if (stderr) return cb(null, false, 'osquery_running');
    const matchResult = stdout.match(/\d+/);
    if (matchResult && !Number.isNaN(Number(matchResult[0]))) {
      return cb(null, true, 'osquery_running');
    } else {
      return cb(null, false, 'osquery_running');
    }
  });
};