鸿蒙网络请求流程
- @ohos.net.http
鸿蒙的网络库请求逻辑在libhttp.z.so中,内部使用curl实现。
寻找hook点
基于curl提供的debug功能 curl.se/libcurl/c/d…
我们需要想办法利用 curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); 设置上我们自己的trace函数。
查看libhttp.z.so plt表 中curl相关方法
hook代码实现
Hook方法 利用xhook(从Android版本简单修改适配鸿蒙版本) 这边选择hook curl_easy_setopt方法
int *curl_easy_setopt_origin;
typedef int *(*type_t2)(void *, int, void *);
static void hookCurl() {
int r = xh_core_register("libhttp.z.so", "curl_easy_setopt", (void *)curl_easy_setopt_proxy,
(void **)&curl_easy_setopt_origin);
xh_core_refresh(0);
xh_core_clear();
}
代理方法
当监听到10002 也就是url被设置时 同时设置curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace);
int *curl_easy_setopt_proxy(void *curl, int i, void *args) {
int *res = ((type_t2)curl_easy_setopt_origin)(curl, i, args);
if (i == 10002) {
((type_t2)curl_easy_setopt_origin)(curl, 20094, (void *)my_trace);
((type_t2)curl_easy_setopt_origin)(curl, 41, (void *)1L);
}
return res;
}
调用堆栈
trace及dump方法
把trace数据写入文件路径 /data/storage/el2/base/haps/entry/files/1234
static int my_trace(void *handle, curl_infotype type, char *data, size_t size, void *userp) {
struct data *config = (struct data *)userp;
const char *text;
(void)handle; /* prevent compiler warning */
switch (type) {
case CURLINFO_TEXT:
default: /* in case a new one is introduced to shock us */
return 0;
case CURLINFO_HEADER_OUT:
text = "=> Send header";
break;
case CURLINFO_DATA_OUT:
text = "=> Send data";
break;
case CURLINFO_HEADER_IN:
text = "<= Recv header";
break;
case CURLINFO_DATA_IN:
text = "<= Recv data";
break;
}
FILE *stream = fopen("/data/storage/el2/base/haps/entry/files/1234", "a");
if (stream == NULL) {
return 0;
}
dump(text, stream, (unsigned char *)data, size, 1);
return 0;
}
static void dump(const char *text, FILE *stream, unsigned char *ptr, size_t size, char nohex) {
unsigned int width = 0x10;
if (nohex)
/* without the hex output, we can fit more on screen */
width = 0x80;
fprintf(stream, "%s, %10.10lu bytes (0x%8.8lx)\n", text, (unsigned long)size, (unsigned long)size);
char *dest = (char *)malloc(size + 1);
snprintf(dest, size + 1, "%s\n", ptr);
fprintf(stream, "%s\n", dest);
fflush(stream);
free(dest);
}
实现效果
总结
整体实现还很粗糙,但总算也缓解了鸿蒙上调试接口时拿不到接口调试数据的困难。plt hook是比较稳定的hook方式,如果后续鸿蒙还使用curl作为网络库,我们可以基于此做更多便捷的网络工具。