Skip to content

裸 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_portgetLocalAddress() / getLocalPort()本端
dst_addr / dst_portgetRemoteSocketAddress()对端

字符串处理链 .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
层JavaNative
覆盖裸 TCP(非 SSL)所有走 libssl 的流量
ssl_session_id""(空)会话 ID 字符串
数据可见时机onEnter 现成onEnter 现成

限制 ​

socketWrite0 是 java.net.SocketOutputStream 的方法,覆盖标准 Java socket。但部分 App 用 Native socket(nativeWrite)或自定义网络库,可能 hook 不到。

相关文档 ​

基于 VitePress 构建 · 教学用途