后面检测网站是否挂掉

用ajax发送同步请求来判断网站是否挂掉不能解决跨域访问的问题。。
可以在后台用定时任务去检测试
代码如下:
public void httpConnetion(String urlStr,AsformwebSite webSite) {
URL url = null;
try {
url = new URL(urlStr);
URLConnection URLconnection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) URLconnection;
int responseCode = httpConnection.getResponseCode();
System.out.println(responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {//HTTP_OK 为200
} else {
//oa提醒
addRemind(webSite);
//短信提醒
sendSm(webSite.getF5(),"网站'"+webSite.getF2()+"'出现异常,请检查网站服务!");
}
} catch (Exception e) {
//oa提醒
addRemind(webSite);
//短信提醒
sendSm(webSite.getF5(),"网站'"+webSite.getF2()+"'出现异常,请检查网站服务!");
}
}
<think>我们正在讨论如何Hook eglSwapBuffers函数。根据用户提供的引用,特别是引用[1]和引用[4],我们知道在Android系统中,可以通过so注入和Inline Hook技术来挂钩系统函数。eglSwapBuffers是EGL的一个函数,用于交换前后缓冲区,通常在图形渲染中使用。 目标:Hook eglSwapBuffers函数,以便在每次调用时执行我们的自定义代码。 步骤: 1. 注入进程:首先需要将我们的so库注入到目标进程(例如surfaceflinger进程)中。这可以通过ptrace实现(如引用[4]所述),或者使用其他注入技术。 2. 获取目标函数地址:在注入的so库中,我们需要获取eglSwapBuffers函数的地址。因为eglSwapBuffers是动态链接库(如libEGL.so)中的导出函数,我们可以通过dlopen和dlsym获取其地址。 3. 实现Inline Hook:修改eglSwapBuffers函数开头处的指令,跳转到我们的自定义函数。同时,需要构建一个trampoline函数来执行被覆盖的原始指令,并跳回原函数继续执行。 4. 编写自定义Hook函数:在这个函数中,我们可以执行自定义逻辑(例如,记录调用信息、修改参数、阻止交换等),然后调用trampoline函数以继续原始流程。 注意:由于eglSwapBuffers可能被多个线程调用,我们需要确保Hook操作是线程安全的。 具体实现细节: 步骤1:注入进程 我们可以参考引用[4]中提到的libinject,它提供了Android平台(x86和arm)上的注入代码。注入后,我们的so库会被加载到目标进程。 步骤2:获取eglSwapBuffers地址 在注入的so库中,我们可以这样获取eglSwapBuffers的地址: void *handle = dlopen("libEGL.so", RTLD_NOW); void *eglSwapBuffers_addr = dlsym(handle, "eglSwapBuffers"); 步骤3:实现Inline Hook 以32位为例(64位需要调整跳转指令,因为地址是64位的): - 保存原始函数的前5个字节(因为jmp指令需要5个字节,在32位中)。 - 构建跳转指令:jmp指令的操作码是0xE9,后面跟着一个32位的偏移量(目标地址 - 当前指令地址 - 5)。 - 修改内存权限(使用mprotect或VirtualProtect)以允许写入。 - 将跳转指令写入目标函数的开头。 步骤4:构建trampoline - 分配一块可执行内存(使用mmap或VirtualAlloc)。 - 将原始函数的前5个字节复制到这块内存。 - 在这5个字节后面,再添加一条跳转指令,跳回原始函数第6个字节处(即跳回原函数继续执行)。 步骤5:编写Hook函数 - 我们的Hook函数需要与原始函数有相同的调用约定和参数。eglSwapBuffers的原型是: EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); - 在Hook函数中,我们可以执行自定义操作,然后调用trampoline函数(它将执行原始的前5字节指令并跳回原函数)。 64位注意事项: 在64位系统上,由于地址空间较大,直接使用5字节的jmp可能不够,因为偏移量可能超出32位范围。因此,通常使用一个中间跳板(绝对地址跳转): mov rax, 0x1234567890 ; 目标地址 jmp rax 这需要14个字节(48 B8 ... FF E0)。因此,我们需要覆盖更多的原始指令(14字节),并保存这些指令,然后在trampoline中执行它们并跳回。 但是,由于eglSwapBuffers是系统函数,我们不知道它开头是否有足够的指令(至少5或14字节)让我们覆盖而不破坏指令的完整性。因此,我们需要使用指令长度解析(或使用现成的Hook库)来确保正确。 为了避免重复造轮子,我们可以使用现有的Hook库,如引用[3]中提到的,或者使用流行的库如Substrate(Android平台)或Frida。 根据引用[3],用户已经编译了针对x86和arm的so库,我们可以参考其实现。 实现代码示例(32位ARM): 1. 构建跳转指令(32位): // 计算跳转偏移:hook_function_addr - (target_addr+4) 因为ARM是三级流水线,PC指向当前指令+8,但这里我们使用相对跳转,所以计算方式不同。 // 实际上,在ARM模式下,跳转指令(B或BL)是相对于PC+8的偏移(以字为单位,即4字节)。但是,我们使用LDR PC, [PC, #?]这种绝对跳转更简单。 然而,在ARM中,通常使用如下方式跳转: LDR PC, [PC, #-4] ; 这条指令读取下一条指令地址处的值到PC DWORD hook_function_addr 这样需要8个字节。因此,我们需要覆盖8个字节(两条指令)。 或者使用: MOVW PC, #low16(hook_addr) MOVT PC, #high16(hook_addr) 但这样需要8字节,并且需要计算。 更常见的是使用: LDR PC, =hook_function_addr ; 这会被汇编成LDR PC, [PC, #0] 和一个立即数 即: FF 00 F0 E5 ; LDR PC, [PC, #0] 小端模式 [4字节的hook_function_addr] 这样总共8字节。 2. 构建trampoline:将覆盖的8字节指令复制到trampoline,然后在trampoline的最后加上跳回原函数+8的指令(同样使用LDR PC跳转)。 由于不同架构(x86, x86_64, arm, arm64)的指令不同,实现起来较为复杂。因此,建议使用现有的Hook库。 推荐方法:使用现有的Hook框架 根据引用[2]和引用[3],我们可以使用一些现成的库,如: - Frida:一个动态插桩框架,支持多种平台,包括Android。它提供了JavaScript接口来Hook函数。 - Substrate:Android平台上的Hook框架,但主要支持ARM。 - PLT Hook:通过修改PLT/GOT表来Hook函数,但eglSwapBuffers是动态库的导出函数,通常可以通过PLT Hook实现,但Inline Hook更通用。 但是,用户要求使用Inline Hook(从上下文推断)。 因此,我们给出一个使用Inline Hook的框架示例,例如使用“Dobby”(一个较新的Hook框架,支持多平台): - GitHub: https://github.com/jmpews/Dobby 使用Dobby的示例代码: #include "dobby.h" static void (*orig_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); static void hook_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { // 自定义代码 LOG("eglSwapBuffers called"); return orig_eglSwapBuffers(dpy, surface); } // 在注入的so初始化时调用 void hook() { void *eglSwapBuffers_addr = DobbySymbolResolver("libEGL.so", "eglSwapBuffers"); DobbyHook(eglSwapBuffers_addr, (void *)hook_eglSwapBuffers, (void **)&orig_eglSwapBuffers); } 这样,Dobby会处理不同架构的Hook细节,包括trampoline的构建。 如果用户希望自己实现,那么需要针对不同架构编写不同的Hook代码,这比较复杂。但根据引用[4],用户已经扩展了libinject以支持x86和arm,所以可以参考其代码。 总结步骤: 1. 注入so到目标进程(如使用ptrace注入)。 2. 在so的初始化函数(如__attribute__((constructor)))中,获取eglSwapBuffers地址。 3. 使用Inline Hook技术(自己实现或使用库)挂钩该函数。 4. 在自定义的Hook函数中执行所需操作。 注意:由于eglSwapBuffers是图形渲染的关键函数,Hook时要注意性能,避免长时间操作,否则可能导致掉帧。 根据引用[1],用户之前已经尝试过Hook eglSwapBuffers,所以可以参考其代码。 下面是一个自己实现Inline Hook的简单示例(32位x86): // 假设我们已经获取了eglSwapBuffers的地址 void *target = eglSwapBuffers_addr; // 步骤1:构建跳转指令 unsigned char jmp_code[5] = {0xE9, 0x00, 0x00, 0x00, 0x00}; uint32_t offset = (uint32_t)my_hook - (uint32_t)target - 5; memcpy(jmp_code+1, &offset, 4); // 步骤2:保存原始指令 unsigned char orig_code[5]; memcpy(orig_code, target, 5); // 步骤3:构建trampoline // 分配可执行内存 void *trampoline = mmap(NULL, 1024, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // 复制原始指令 memcpy(trampoline, orig_code, 5); // 构建跳回指令:跳回target+5 unsigned char jmp_back[5] = {0xE9, 0x00, 0x00, 0x00, 0x00}; offset = (uint32_t)(target + 5) - (uint32_t)(trampoline + 5) - 5; memcpy(jmp_back+1, &offset, 4); memcpy(trampoline+5, jmp_back, 5); // 步骤4:修改目标函数 // 更改内存保护 mprotect(target, 5, PROT_READ | PROT_WRITE | PROT_EXEC); memcpy(target, jmp_code, 5); // 步骤5:定义Hook函数 // 注意:Hook函数必须与原始函数有相同的调用约定 EGLBoolean my_hook(EGLDisplay dpy, EGLSurface surface) { // 自定义代码 // ... // 调用trampoline,它执行原始指令并跳回原函数 return ((EGLBoolean (*)(EGLDisplay, EGLSurface))trampoline)(dpy, surface); } 但是,上述代码在32位x86上可行,在64位或其他架构需要调整。 因此,建议使用现成的Hook库,如Dobby,以支持多架构。 最后,注意Android设备需要root权限,因为注入系统进程需要root。 根据用户提供的引用,我们参考了[1][3][4],这些资料提供了在Android上进行so注入和Hook的实例,特别是针对eglSwapBuffers的Hook[^1][^3][^4]。</think>### Hook eglSwapBuffers 的实现方法 要 Hook `eglSwapBuffers` 函数的所有调用,需要结合 **SO 注入** 和 **Inline Hook** 技术。以下是详细步骤: --- ### 1. **SO 注入目标进程** 首先需要将自定义的 SO 库注入到目标进程(如 `surfaceflinger` 或图形渲染进程)中: ```c // 注入代码示例(基于 ptrace) pid_t target_pid = find_target_process("surfaceflinger"); ptrace_attach(target_pid); void* remote_mem = alloc_remote_memory(target_pid, lib_path_size); ptrace_write(target_pid, remote_mem, lib_path, lib_path_size); void* dlopen_addr = get_remote_symbol(target_pid, "libdl.so", "dlopen"); call_remote_function(target_pid, dlopen_addr, remote_mem, RTLD_NOW); ``` - **关键点**: - 使用 `ptrace` 附加到目标进程[^4] - 通过 `dlopen` 远程加载自定义 SO 库 - 需要 root 权限(系统进程注入) --- ### 2. **定位 eglSwapBuffers 地址** 在注入的 SO 库初始化时获取函数地址: ```c // 获取函数地址 void* egl_handle = dlopen("libEGL.so", RTLD_NOW); void* orig_eglSwapBuffers = dlsym(egl_handle, "eglSwapBuffers"); ``` - **注意**:不同设备可能使用不同图形库(如 `libvulkan.so`),需动态适配。 --- ### 3. **实现 Inline Hook** 修改函数入口指令跳转到自定义函数: ```c // 32位 ARM 跳转指令(8字节覆盖) uint32_t hook_addr = (uint32_t)my_eglSwapBuffers; uint32_t orig_addr = (uint32_t)orig_eglSwapBuffers; uint8_t jump_code[8] = { 0x04, 0xF0, 0x1F, 0xE5, // LDR PC, [PC, #-4] hook_addr & 0xFF, (hook_addr >> 8) & 0xFF, (hook_addr >> 16) & 0xFF, (hook_addr >> 24) & 0xFF }; // 保存原始指令并写入跳转 memcpy(orig_bytes, orig_eglSwapBuffers, 8); // 保存原指令 change_mem_permission(orig_addr, 8, PROT_READ | PROT_WRITE | PROT_EXEC); memcpy(orig_eglSwapBuffers, jump_code, 8); // 写入Hook指令 ``` - **64位适配**:需使用更长跳转指令(如 `MOV+JMP` 组合),通常覆盖 12-16 字节[^4]。 --- ### 4. **构建 Trampoline 函数** 复制被覆盖的指令并跳回原函数: ```c // 分配可执行内存 void* trampoline = mmap(NULL, 128, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); // 复制原始指令 + 跳回指令 memcpy(trampoline, orig_bytes, 8); uint32_t return_offset = orig_addr + 8 - (uint32_t)(trampoline + 8); uint8_t return_jump[8] = { /* 跳回原函数+8的指令 */ }; memcpy(trampoline+8, return_jump, 8); ``` --- ### 5. **实现自定义 Hook 函数** ```c // 自定义Hook函数 EGLBoolean my_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { // 自定义逻辑(如截图/性能监控) log_swap_time(); record_fps(); // 调用原始函数 return ((EGLBoolean(*)(EGLDisplay, EGLSurface))trampoline)(dpy, surface); } ``` - **参数处理**:需匹配原函数签名(`EGLDisplay` + `EGLSurface`) - **线程安全**:添加锁机制(如 `pthread_mutex`) --- ### 6. **注意事项** 1. **指令完整性**: - 覆盖指令时需完整复制基本块(避免拆解指令) - 使用反汇编引擎(如 Capstone)验证指令边界 2. **多线程同步**: ```c static pthread_mutex_t hook_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&hook_mutex); // Hook操作 pthread_mutex_unlock(&hook_mutex); ``` 3. **反检测措施**: - 移除 SO 库中的 `INJECT`/`HOOK` 等特征字符串 - 动态解密关键代码(防止静态分析) - 禁用调试标志(`/proc/self/status` 的 TracerPid) --- ### 现成框架推荐 1. **Dobby**(跨平台 Hook 框架): ```c #include "dobby.h" void* target = DobbySymbolResolver("libEGL.so", "eglSwapBuffers"); DobbyHook(target, my_eglSwapBuffers, (void**)&orig_eglSwapBuffers); ``` 2. **Frida**(无需编译): ```javascript // frida脚本 Interceptor.attach(Module.getExportByName("libEGL.so", "eglSwapBuffers"), { onEnter: function(args) { console.log("SwapBuffers called!"); } }); ``` 3. **Substrate**(Android 专用): ```c MSHookFunction(eglSwapBuffers, my_eglSwapBuffers, &orig_eglSwapBuffers); ``` > 完整实现参考:[Android so注入与挂钩实现](http://bbs.pediy.com/showthread.php?t=141355)[^4] --- ### 常见问题解决 - **崩溃问题**:检查指令覆盖是否破坏相邻函数 - **无效Hook**:确认目标进程是否正确加载 SO - **权限错误**:确保 SELinux 处于 permissive 模式 - **架构适配**:分别编译 x86/ARMv7/ARM64 版本[^3] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值