裸 TCP socketWrite0 hook
📤 抓取不走 SSL 的裸 TCP 发送数据(如自定义二进制协议)。
📎 源码在线查看:
script.js(socketWrite0)
作用
有些 App 流量不走 SSL(自定义 TCP 协议、非 HTTPS 请求),SSL_read/SSL_write hook 不到。r0capture 额外 hook Java 层 SocketOutputStream.socketWrite0,抓这类裸 TCP 明文。
实现
javascript
Java.use("java.net.SocketOutputStream").socketWrite0
.overload('java.io.FileDescriptor', '[B', 'int', 'int').implementation =
function (fd, bytearry, offset, byteCount) {
var result = this.socketWrite0(fd, bytearry, offset, byteCount);
var message = {};
message["function"] = "HTTP_send";
message["ssl_session_id"] = ""; // 空=非SSL
message["src_addr"] = ntohl(ipToNumber(
(this.socket.value.getLocalAddress().toString().split(":")[0]).split("/").pop()));
message["src_port"] = parseInt(this.socket.value.getLocalPort().toString());
message["dst_addr"] = ntohl(ipToNumber(
(this.socket.value.getRemoteSocketAddress().toString().split(":")[0]).split("/").pop()));
message["dst_port"] = parseInt(this.socket.value.getRemoteSocketAddress().toString().split(":").pop());
message["stack"] = Java.use("android.util.Log").getStackTraceString(
Java.use("java.lang.Throwable").$new()).toString();
var ptr = Memory.alloc(byteCount);
for (var i = 0; i < byteCount; ++i)
ptr.add(i).writeU8(bytearry[offset + i] & 0xFF);
send(message, ptr.readByteArray(byteCount))
return result;
}地址解析
从 this.socket(被 hook 对象的 socket 字段)反射出本地/远端地址端口:
| 字段 | 来源 | 方向 |
|---|---|---|
src_addr / src_port | getLocalAddress() / getLocalPort() | 本端 |
dst_addr / dst_port | getRemoteSocketAddress() | 对端 |
字符串处理链 .toString().split(":")[0]).split("/").pop() 处理形如 /192.168.1.5:54321 的 socket 地址字符串。
Java byte[] → ArrayBuffer
javascript
var ptr = Memory.alloc(byteCount);
for (var i = 0; i < byteCount; ++i)
ptr.add(i).writeU8(bytearry[offset + i] & 0xFF);
send(message, ptr.readByteArray(byteCount))Java byte[] 不能直接 readByteArray,需先拷贝到 Native 内存(Memory.alloc + 逐字节 writeU8),再 readByteArray 转 ArrayBuffer send。& 0xFF 处理 Java byte 的符号位(-128~127 → 0~255)。
与 SSL hook 的区别
| 维度 | socketWrite0 (HTTP_send) | SSL_write |
|---|---|---|
| 层 | Java | Native |
| 覆盖 | 裸 TCP(非 SSL) | 所有走 libssl 的流量 |
| ssl_session_id | ""(空) | 会话 ID 字符串 |
| 数据可见时机 | onEnter 现成 | onEnter 现成 |
限制
socketWrite0 是 java.net.SocketOutputStream 的方法,覆盖标准 Java socket。但部分 App 用 Native socket(nativeWrite)或自定义网络库,可能 hook 不到。