Last active
December 15, 2021 01:35
-
-
Save knightsc/f5417a577c14125426146be4d9a3864e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <errno.h> | |
#include <pthread.h> | |
#include <signal.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <strings.h> | |
#include <unistd.h> | |
#include <sys/ioctl.h> | |
#include <sys/kern_control.h> | |
#include <sys/socket.h> | |
#include <sys/sys_domain.h> | |
#include <sys/time.h> | |
#define ENABLE_KERNEL_HOOK 0x01 | |
#define DISABLE_KERNEL_HOOK 0x02 | |
#define PUT_SCAN_RESULT_MSG 0x04 | |
#define PUT_SCAN_TIME_OUT 0x05 | |
#define PING_KEXT 0x06 | |
#define GENERATE_BYPASS 0x07 | |
#define SCAN_RW_POLICY 0x08 | |
#define SCAN_NW_POLICY 0x09 | |
#define ADD_TRUSTED_PROCESS 0x0d | |
#define FLUSH_TRUSTED_PROCESS 0x0e | |
#define INVALIDATE_BOOSTER_CACHE 0x0f | |
#define ENABLE_BOOSTER_CACHE 0x10 | |
#define SET_LOG_LEVEL 0x11 | |
#define CLEAR_DEVICE_ENTRIES 0x12 | |
#define SET_KERNEL_EXCLUSIONS 0x13 | |
#define CLEAR_KERNEL_EXCLUSIONS 0x14 | |
#define KERN_CONTROL_NAME "com.McAfee.AVKext" | |
#define FILE_SCAN_MESSAGE_SIZE 1080 | |
#define RESULT_ALLOW 1 | |
#define RESULT_DENY 2 | |
#define FC_OPEN_FOR_READ 0x00 | |
#define FC_OPEN_FOR_WRITE 0x01 | |
#define FC_CLOSE 0x02 | |
#define FC_CLOSE_AFTER_MODIFY 0x03 | |
#define FC_DELETE 0x04 | |
#define FC_EXEC 0x05 | |
#define FC_RENAME 0x06 | |
struct FileScanMessage { | |
int64_t inode; | |
int32_t pid; | |
int32_t uid; | |
int32_t gid; | |
int32_t devid; | |
int32_t result; | |
int32_t action; | |
int32_t u1; | |
int32_t u2; | |
int64_t u3; | |
char file[1024]; | |
int64_t u4; | |
}; | |
static int fd; | |
static volatile bool running = true; | |
static pthread_t pingKextThread; | |
void printFileScanMessage(struct FileScanMessage *m) | |
{ | |
printf("inode: 0x%016llx\n", m->inode); | |
printf("pid: %d\n", m->pid); | |
printf("uid: %d\n", m->uid); | |
printf("gid: %d\n", m->gid); | |
printf("devid: 0x%08x\n", m->devid); | |
printf("result: 0x%08x\n", m->result); | |
printf("action: 0x%08x\n", m->action); | |
printf("unknown1: 0x%08x\n", m->u1); | |
printf("unknown2: 0x%08x\n", m->u2); | |
printf("unknown3: 0x%016llx\n", m->u3); | |
printf("file: %s\n", m->file); | |
printf("unknown4: 0x%016llx\n", m->u4); | |
} | |
void intHandler(int sig) { | |
running = false; | |
} | |
void* pingKext(void* data) | |
{ | |
for (;;) { | |
int result = setsockopt(fd, SYSPROTO_CONTROL, PING_KEXT, NULL, 0); | |
if (result == -1){ | |
fprintf(stderr, "Unable to ping kext: %s\n", strerror(errno)); | |
} | |
sleep(55); | |
} | |
} | |
int spawnPingKextThread() | |
{ | |
int result; | |
result = pthread_create(&pingKextThread, NULL, pingKext, NULL); | |
return result; | |
} | |
int connectToKext() | |
{ | |
struct sockaddr_ctl addr; | |
struct ctl_info info; | |
fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); | |
if (fd == -1) { | |
fprintf(stderr, "Unable to create socket\n"); | |
return -1; | |
} | |
bzero(&addr, sizeof(addr)); | |
addr.sc_len = sizeof(addr); | |
addr.sc_family = AF_SYSTEM; | |
addr.ss_sysaddr = AF_SYS_CONTROL; | |
memset(&info, 0, sizeof(info)); | |
strncpy(info.ctl_name, KERN_CONTROL_NAME, sizeof(info.ctl_name)); | |
if (ioctl(fd, CTLIOCGINFO, &info)) { | |
fprintf(stderr, "Unable to send IOCTL to Kext.\n"); | |
return -1; | |
} | |
addr.sc_id = info.ctl_id; | |
addr.sc_unit = 0; | |
int result = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); | |
if (result) { | |
fprintf(stderr, "Unable to connect to Kext\n"); | |
return -1; | |
} | |
return 0; | |
} | |
int setKextTrustedProcesses() | |
{ | |
// Error in flushing trusted processes list | |
// FLUSH_TRUSTED_PROCESS | |
// Unable to get the trusted process 'path' at the given tIndex. | |
//Error in setting trusted processes | |
// ADD_TRUSTED_PROCESS | |
return 0; | |
} | |
int setBoosterCache(int enabled) | |
{ | |
int result; | |
result = setsockopt(fd, SYSPROTO_CONTROL, ENABLE_BOOSTER_CACHE, &enabled, sizeof(enabled)); | |
if (result){ | |
fprintf(stderr, "Unable to change booster cache\n"); | |
} | |
return result; | |
} | |
int initializeKext() | |
{ | |
int result; | |
result = setKextTrustedProcesses(); | |
result = setBoosterCache(0); | |
return result; | |
} | |
int enableFileWatching() | |
{ | |
int result; | |
result = setsockopt(fd, SYSPROTO_CONTROL, ENABLE_KERNEL_HOOK, NULL, 0); | |
if (result){ | |
fprintf(stderr, "Unable to start OAS in kext\n"); | |
} | |
return result; | |
} | |
void runLoop() | |
{ | |
int result; | |
ssize_t count; | |
struct timeval timeout; | |
fd_set readset; | |
char buffer[FILE_SCAN_MESSAGE_SIZE]; | |
char response[sizeof(int64_t) + FILE_SCAN_MESSAGE_SIZE]; | |
timeout.tv_sec = 10; | |
timeout.tv_usec = 0; | |
FD_ZERO(&readset); | |
FD_SET(fd, &readset); | |
while (running) { | |
result = select(fd + 1, &readset, NULL, NULL, &timeout); | |
if (result < 0) { | |
running = false; | |
fprintf(stderr, "Error on select(): %s\n", strerror(errno)); | |
break; | |
} | |
if (FD_ISSET(fd, &readset)) { | |
bzero(&buffer, sizeof(buffer)); | |
count = recv(fd, buffer, FILE_SCAN_MESSAGE_SIZE, 0); | |
if (count < 0) { | |
// error | |
running = false; | |
close(fd); | |
fprintf(stderr, "recv() error: %s\n", strerror(errno)); | |
break; | |
} else if (count == 0) { | |
// socket was closed | |
running = false; | |
close(fd); | |
fprintf(stderr, "Error while receiving requests from kext\n"); | |
break; | |
} else { | |
// Process the message | |
struct FileScanMessage *message = (struct FileScanMessage *)buffer; | |
printFileScanMessage(message); | |
printf("\n"); | |
// Inspect file and set a result | |
if(strstr(message->file, "Clapzok") != NULL) { | |
message->result = RESULT_DENY; | |
} else { | |
message->result = RESULT_ALLOW; | |
} | |
// Send the message back to the kext | |
int64_t n = 1; | |
memcpy(response, &n, sizeof(n)); | |
memcpy(response+sizeof(n), buffer, FILE_SCAN_MESSAGE_SIZE); | |
int result = setsockopt(fd, SYSPROTO_CONTROL, PUT_SCAN_RESULT_MSG, response, sizeof(response)); | |
if (result){ | |
fprintf(stderr, "setsockopt failed on PUT_SCAN_RESULT_MSG: %s\n", strerror(errno)); | |
} | |
} | |
} | |
} | |
} | |
int main(int argc, const char * argv[]) { | |
int result; | |
signal(SIGINT, intHandler); | |
if ((result = connectToKext()) < 0) { | |
exit(1); | |
} | |
if ((result = initializeKext()) < 0) { | |
exit(2); | |
} | |
if ((result = spawnPingKextThread()) < 0) { | |
exit(3); | |
} | |
if ((result = enableFileWatching()) < 0) { | |
exit(4); | |
} | |
runLoop(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment