Last active
May 4, 2019 09:35
-
-
Save exelix11/6f12103d53652a13781af37e893e86f5 to your computer and use it in GitHub Desktop.
mitm and block ipc requests for the Yi IOT cameras
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 <stdio.h> | |
#include <malloc.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <mqueue.h> | |
#include <unistd.h> | |
#define LOGGING | |
//#define NOPRINT | |
#if defined(LOGGING) | |
FILE *logFile = NULL; | |
#define printf(...) do { fprintf(logFile, __VA_ARGS__); fflush(logFile); } while(0) | |
#elif defined(NOPRINT) | |
#define printf(...) do { } while(0) | |
#endif | |
int patchProgram(const char* elfPath, const char* targetIpc, const char* saveas) | |
{ | |
FILE *f = fopen(elfPath, "rb"); | |
if (!f) | |
{ | |
printf("Path not found !\n"); | |
return -1; | |
} | |
fseek(f,0,SEEK_END); | |
long int flen = ftell(f); | |
fseek(f,0,SEEK_SET); | |
char *buf = malloc(flen); | |
fread(buf,1,flen,f); | |
fclose(f); | |
f = NULL; | |
int ipcLen = strlen(targetIpc); | |
for (int i = 0; i < flen - ipcLen; i++) | |
if (memcmp(targetIpc, buf + i, ipcLen + 1) == 0) | |
{ | |
printf("Found target at %x\n", i); | |
buf[i + 1] = 'm'; | |
} | |
f = fopen(saveas, "wb"); | |
if (!f) | |
{ | |
printf("could not open output file\n"); | |
free(buf); | |
return -2; | |
} | |
fwrite(buf,1,flen,f); | |
fclose(f); | |
printf("Patched and saved as %s", saveas); | |
free(buf); | |
return 0; | |
} | |
enum MitmAction | |
{ | |
MITM_NO_CHANGE = -1, | |
MITM_BLOCK = 0 | |
}; | |
/* | |
A patch function can return either MITM_BLOCK, MITM_NO_CHANGE or a new size for the message. | |
When returning MITM_NO_CHANGE the buffer should not be modified as it will be passed to the next patch function for the queue. | |
When returning MITM_BLOCK the message will be blocked and won't be passed to other patch functions. | |
When returning a size the message will be immediately forwarded without passing through other functions, it's possible to increase or reduce the size as well to edit the buffer. | |
*/ | |
typedef int (*PatchFunction)(char*, int); | |
void dumpHex(char *buf, int len) | |
{ | |
for (int i = 0; i < len; i++) | |
printf("%.2x ", buf[i]); | |
} | |
int MitmQueue(const char* QueueName, PatchFunction* patchFn) | |
{ | |
char mitmName[strlen(QueueName) + 1]; | |
strcpy(mitmName, QueueName); | |
mitmName[1] = 'm'; | |
printf("mitming %s -> %s\n", QueueName, mitmName); | |
mqd_t readQueue; | |
mqd_t sendQueue; | |
struct mq_attr ma; | |
ma.mq_flags = 0; | |
ma.mq_maxmsg = 16; | |
ma.mq_msgsize = 512; | |
ma.mq_curmsgs = 0; | |
readQueue = mq_open(QueueName, O_RDONLY | O_CREAT, 438, &ma); | |
if (readQueue == -1) | |
{ | |
printf("Error opening the mitm queue %s\n", mitmName); | |
return -2; | |
} | |
sendQueue = mq_open(mitmName, O_WRONLY | O_CREAT, 438, &ma); | |
if (sendQueue == -1) | |
{ | |
printf("Error opening the real queue %s\n", QueueName); | |
return -3; | |
} | |
while (1) { | |
char msgBuf[512]; | |
ssize_t len = mq_receive(readQueue, msgBuf, 512, NULL); | |
if (len == -1) | |
{ | |
printf("Error receiving the message\n"); | |
return -4; | |
} | |
printf("msg len 0x%x ", len); | |
#if !defined(NOPRINT) | |
if (len < 32) dumpHex(msgBuf,len); | |
#endif | |
if (patchFn) | |
{ | |
PatchFunction* p = patchFn; | |
while (*p) | |
{ | |
int res = (*p)(msgBuf,len); | |
if (res != MITM_NO_CHANGE) | |
{ | |
len = res; | |
break; | |
} | |
p++; | |
} | |
if (len == 0) | |
{ | |
printf("blocked by patchFn !\n"); | |
continue; | |
} | |
} | |
ssize_t sent = mq_send(sendQueue, msgBuf, len, 1); | |
if (sent == -1) | |
{ | |
printf("Error sending the message\n"); | |
return -5; | |
} | |
printf("sent ! %x\n", sent); | |
} | |
return 0; | |
} | |
int rmm(char* buf, int len) | |
{ | |
if (len != 16) return MITM_NO_CHANGE; | |
int *arr = (int*)buf; | |
if (arr[0] == 1 && arr[1] == 2 && arr[2] == 0x7C007C && arr[3] == 0) | |
if (access("/tmp/rec_vid",0)) //block the message if this file isn't there | |
return MITM_BLOCK; | |
else | |
printf("(motion_start msg allowed) "); | |
return MITM_NO_CHANGE; | |
} | |
typedef struct FunctionEntry | |
{ | |
PatchFunction fn; | |
const char* name; | |
const char* desc; | |
} FunctionEntry_t; | |
FunctionEntry_t entries[] = | |
{ | |
{rmm, "rmm", "this is used to block recordings if the file /tmp/rec_vid doesn't exist"}, | |
{NULL, NULL, NULL} | |
}; | |
int main(int argc, char** argv) | |
{ | |
#if defined(LOGGING) | |
logFile = fopen("/tmp/mitmlog", "w"); | |
#endif | |
printf("IpcMitm\n"); | |
if (argc == 2) | |
return MitmQueue(argv[1], NULL); | |
else if (argc == 5 && !strcmp(argv[1],"patch")) | |
return patchProgram(argv[2], argv[3], argv[4]); | |
else if (argc >= 3) | |
{ | |
PatchFunction functions[argc - 1]; //there's one extra slot at the end to break the loop in MitmQueue | |
memset(functions,0, sizeof(PatchFunction) * argc - 1); | |
for (int i = 2; i < argc; i++) | |
{ | |
for (int j = 0; entries[j].fn; j++) | |
if (!strcmp(argv[i], entries[j].name)) | |
{ | |
functions[i - 2] = entries[j].fn; | |
break; | |
} | |
if (functions[i - 2]) continue; | |
printf("Couldn't find '%s' patch function !\n", argv[i]); | |
goto NoMatch; | |
} | |
MitmQueue(argv[1], functions); | |
} | |
else | |
{ | |
NoMatch: | |
printf( "Usage:\n" | |
"IpcMitm <queue name>: mitms the specified queue, only for patched binaries. (just logs messages)\n" | |
"IpcMitm <queue name> <handler function 1> <handler function 2> .....: like the one before but the handler function may block or edit some before forwarding them\n" | |
"IpcMitm patch <input file> <queue name> <output file>: patches an executable to use a mitm'd version of the specified queue\n" | |
"List of patch functions:\n"); | |
for (int i = 0; entries[i].fn ; i++) | |
printf("%s : %s\n", entries[i].name, entries[i].desc); | |
} | |
#if defined(LOGGING) | |
fclose(logFile); | |
#endif | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment