gcc -shared -fPIC inject_tcp.c -o inject.so -ldl
Last active
May 25, 2022 15:08
-
-
Save yurynix/3122594894e88f43dc49c5d3265c0561 to your computer and use it in GitHub Desktop.
Intercept open calls
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
#define _GNU_SOURCE | |
#include <dlfcn.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
//#include <unistd.h> | |
//#include <sys/stat.h> | |
#include <stdarg.h> | |
#include <curl/curl.h> | |
#include <stdlib.h> | |
extern ssize_t write(int, const void *, size_t); // from unistd.h | |
// | |
// returns: | |
// 0 - file does not exists | |
// 1 - file exists | |
// -1 - failure | |
int is_remote_file_exists(const char* url) { | |
CURL *curl = curl_easy_init(); | |
if (curl) { | |
/* First set the URL that is about to receive our POST. This URL can | |
just as well be a https:// URL if that is what should receive the | |
data. */ | |
curl_easy_setopt(curl, CURLOPT_URL, url); | |
/* get us the resource without a body - use HEAD! */ | |
curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); | |
/* Perform the request */ | |
CURLcode res = curl_easy_perform(curl); | |
if (res != CURLE_OK) { | |
fprintf(stderr, "curl_easy_perform() failed: %s\n", | |
curl_easy_strerror(res)); | |
return -1; | |
} | |
long http_code = 0; | |
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); | |
printf("status code: %ld\n", http_code); | |
/* always cleanup */ | |
curl_easy_cleanup(curl); | |
return http_code == 200 ? 1 : 0; | |
} | |
return -1; | |
} | |
typedef int (*orig_open_f_type)(const char *pathname, int flags); | |
orig_open_f_type orig_open64 = NULL; | |
typedef long int (*orig_syscall_type)(long int syscallNumber, ...); | |
orig_syscall_type orig_syscall = NULL; | |
void writeLogToFile(const char *logline) { | |
// FILE *log = fopen("/tmp/trace.txt", "a+"); | |
// fprintf(log, "%s\n", logline); | |
// fclose(log); | |
} | |
int endsWith(const char *str, const char *suffix) | |
{ | |
if (!str || !suffix) | |
return 0; | |
size_t lenstr = strlen(str); | |
size_t lensuffix = strlen(suffix); | |
if (lensuffix > lenstr) | |
return 0; | |
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0; | |
} | |
int open64(const char *pathname, int flags) { | |
printf("open64('%s', %d)\n",pathname, flags); | |
writeLogToFile(pathname); | |
// https://sudonull.com/post/120265-Practical-use-of-LD_PRELOAD-or-function-substitution-in-Linux | |
//if (endsWith(pathname, ".js")) { | |
if (strstr(pathname, "node_modules")) { | |
//opening tcp socket | |
struct sockaddr_in servaddr; | |
int socketfd = socket(AF_INET, SOCK_STREAM, 0); | |
bzero(&servaddr,sizeof(servaddr)); | |
servaddr.sin_family = AF_INET; | |
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // addr | |
servaddr.sin_port = htons(32000); // port | |
printf("Before connect\n"); | |
if (connect(socketfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) { | |
printf("[Open] FD: %d TCP Connected\n", socketfd); | |
write(socketfd, pathname, strlen(pathname)); | |
return socketfd; | |
} else { | |
printf("[Open] FD: %d TCP Connection failed!\n", socketfd); | |
// let it fallback below | |
} | |
} | |
int fd = orig_open64(pathname,flags); | |
printf("open64('%s') => %d\n", pathname, fd); | |
return fd; | |
} | |
/* | |
int __fxstat64(int ver, int fildes, struct stat64 * stat_buf) { | |
printf("__fxstat64 %d %d\n", ver, fildes); | |
return 0; | |
} | |
int __xstat64(int ver, const char * path, struct stat64 * stat_buf) { | |
printf("__xstat64(%d, %s, %lx)\n", ver, path, (unsigned long)stat_buf); | |
return 0; | |
} | |
*/ | |
int stat64(int ver, const char * path, void * stat_buf) { | |
printf("stat(%d, %s, %lx)\n", ver, path, (unsigned long)stat_buf); | |
return 0; | |
} | |
struct uv__statx_timestamp { | |
int64_t tv_sec; | |
uint32_t tv_nsec; | |
int32_t unused0; | |
}; | |
struct uv__statx { | |
uint32_t stx_mask; | |
uint32_t stx_blksize; | |
uint64_t stx_attributes; | |
uint32_t stx_nlink; | |
uint32_t stx_uid; | |
uint32_t stx_gid; | |
uint16_t stx_mode; | |
uint16_t unused0; | |
uint64_t stx_ino; | |
uint64_t stx_size; | |
uint64_t stx_blocks; | |
uint64_t stx_attributes_mask; | |
struct uv__statx_timestamp stx_atime; | |
struct uv__statx_timestamp stx_btime; | |
struct uv__statx_timestamp stx_ctime; | |
struct uv__statx_timestamp stx_mtime; | |
uint32_t stx_rdev_major; | |
uint32_t stx_rdev_minor; | |
uint32_t stx_dev_major; | |
uint32_t stx_dev_minor; | |
uint64_t unused1[14]; | |
}; | |
long int syscall(long int syscallNumber, ...) { | |
printf("syscall %ld ", syscallNumber); | |
if (syscallNumber == 291) { | |
va_list args; | |
va_start(args, syscallNumber); | |
int dirfd = va_arg(args, int); | |
char * path = va_arg(args, char *); | |
int flags = va_arg(args, int); | |
unsigned int mask = va_arg(args, unsigned int); | |
struct uv__statx* statxbuf = va_arg(args, struct uv__statx*); | |
printf("path: %s ", path); | |
va_end(args); | |
if (endsWith(path, "node_modules")) { | |
// https://docs.huihoo.com/doxygen/linux/kernel/3.7/include_2uapi_2linux_2stat_8h_source.html | |
// We tell it's a directory | |
statxbuf->stx_mode = 0040000; | |
printf("Return OK and IS_DIR\n"); | |
return 0; | |
} else { | |
printf("\n"); | |
} | |
char url_prefix[] = "http://localhost:3201"; | |
char * url = malloc(sizeof(char) * (strlen(path) + strlen(url_prefix) + 1)); | |
strncpy(url, url_prefix, strlen(url_prefix)); | |
strncpy(url + strlen(url_prefix), path, strlen(path) + 1); | |
printf("url: %s\n", url); | |
if (is_remote_file_exists(url) == 1) { | |
free(url); | |
return 0; | |
} | |
free(url); | |
} else { | |
printf("\n"); | |
} | |
__builtin_return( | |
__builtin_apply( | |
(void(*)())orig_syscall, __builtin_apply_args(), 512)); | |
} | |
__attribute__((constructor)) void init() { | |
printf("Intercepting open() calls\n"); | |
if (orig_open64 == NULL) { | |
orig_open64 = (orig_open_f_type)dlsym(RTLD_NEXT, "open64"); | |
} | |
if (orig_syscall == NULL) { | |
orig_syscall = (orig_syscall_type)dlsym(RTLD_NEXT, "syscall"); | |
} | |
} |
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
const net = require('node:net'); | |
const server = net.createServer((c) => { | |
// 'connection' listener. | |
console.log('client connected'); | |
c.on('end', () => { | |
console.log('client disconnected'); | |
}); | |
c.write('{"main":"pizdetz.js", "name": "@yarnpkg/lockfile", "version": "1.2.3"}\r\n', () => c.end()); | |
c.on('data', d => console.log('data', d.toString())); | |
//c.end(); | |
}); | |
server.on('error', (err) => { | |
throw err; | |
}); | |
server.listen(32000, () => { | |
console.log('server bound'); | |
}); | |
const http = require('node:http'); | |
// Create a local server to receive data from | |
const httpServer = http.createServer((req, res) => { | |
console.log('req', req.url); | |
res.writeHead(404, { 'Content-Type': 'application/json' }); | |
res.end(JSON.stringify({ | |
data: 'Hello World!' | |
})); | |
}); | |
httpServer.listen(3201); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment