如何优雅的抓包

  1. 1. 如何优雅的抓包
    1. 1.1. 通过Objection定位关键位置
    2. 1.2. 代码实现
      1. 1.2.1. 获取http response
      2. 1.2.2. 获取https response

如何优雅的抓包

目标:喜马拉雅FM

要求:获取软件的发送数据的端口和数据

环境:Kali Lunux/Android

通过Objection定位关键位置

$ objection -N -h 192.168.31.227 -g com.ximalaya.ting.android explore

首先通过以上命令进入objection交互界面,如图0-1所示

0-1

图0-1

现在需要找到所有和Socket有关的函数

$ android hooking search classes socket

搜索结果如图0-2所示

0-2

图0-2
1
2
3
4
5
6
7
8
9
10
11
[Landroid.bluetooth.BluetoothSocket$SocketState;
[Landroid.net.LocalSocketAddress$Namespace;
android.bluetooth.BluetoothServerSocket
android.bluetooth.BluetoothSocket
android.bluetooth.BluetoothSocket$SocketState
...
sun.nio.ch.SocketAdaptor$1
sun.nio.ch.SocketAdaptor$2
sun.nio.ch.SocketAdaptor$SocketInputStream
sun.nio.ch.SocketChannelImpl
sun.nio.ch.SocketDispatcher

⚠注意:

在Objection中android hooking watch class 无法hook构造参数!需要手动修改 agent.js实现watch class的地方,然后添加$init来hook构造参数

将之前得到的搜索结果全部hook(这里可以通过保存hook搜索结果到文本,将文本每行前面加入 android hooking watch class-c参数hook文本里所有函数 ),观察发送数据时那些函数被调用了

0-30-31

图0-3

打印可疑的函数的堆栈,发现java.net.SocketOutputStream.write(SocketOutputStream.java:161) 如图所示0-4

0-4

图0-4

通过查看Android源码SocketOutputStream.java:161发现write()函数又调用了socketWrite()函数 如图0-5所示

socketWrite(byte b[], int off, int len)

byte b[]: 要写入的数据

int off: 数据中的起始偏移量

int len:被写入的字节数

0-50-51

图0-5

代码实现

获取http response

hook
java.net.SocketOutputStream.write()

java.net.SocketOutputStream.read()

因为Socket是底层的二进制数据传输,hook了Socket,对上层应用绝大多数都逃不过,除非自定义协议。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*Java.use("java.net.SocketOutputStream").socketWrite.overload('[B', 'int', 'int').implementation = function(b,off,len){
var result = this.socketWrite(b,off,len)
console.log('写入的数据:',b)
console.log('偏移量:',off)
console.log('被写入的字节数:',len)

var ByteString = Java.use("com.android.okhttp.okio.ByteString");
//console.log(ByteString.of(b).hex())
jhexdump(b)
return result;
}*/
Java.use("java.net.SocketOutputStream").write.overload('[B', 'int', 'int').implementation = function(bytearry,int1,int2){
var result = this.write(bytearry,int1,int2)
console.log("HTTP write result,bytearry,int1,int2=>",result,bytearry,int1,int2)
var ByteString = Java.use("com.android.okhttp.okio.ByteString")
//console.log("bytearray contents=>", ByteString.of(bytearry).hex())
jhexdump(bytearry)
return result
}
Java.use("java.net.SocketInputStream").read.overload('[B', 'int', 'int').implementation = function(bytearry,int1,int2){
var result = this.read(bytearry,int1,int2)
console.log("HTTP read result,bytearry,int1,int2=>",result,bytearry,int1,int2)
var ByteString = Java.use("com.android.okhttp.okio.ByteString")
//console.log("bytearray contents=>", ByteString.of(bytearry).hex())
jhexdump(bytearry)
return result
}
function jhexdump(array){
var ptr = Memory.alloc(array.length)
for (var i = 0;i<array.length;++i){
Memory.writrS8(ptr.add(i),array[i]);
console.log(hexdump(ptr,{offset:0,length:array.length,header:false,ansi:false}))
}
}

获取https response