The core idea of Hook packet capture is to dump packets at all times in the plaintext state
HTTP
request
Use sockets to implement native requests
Create a new Android project and add it to mainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run(a) {
httpsock();
}
}).start();
}
private static void httpsock(a){
try {
final String host = "www.httpbin.org";
final int port = 80;
final String path = "/get";
Socket socket = new Socket(host, port);
StringBuilder sb = new StringBuilder();
sb.append("GET " + path + "HTTP / 1.1 \ r \ n");
sb.append("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36\r\n");
sb.append("Host: "+ host+"\r\n");
sb.append("\r\n");
OutputStream outputStream = socket.getOutputStream();
outputStream.write(sb.toString().getBytes());
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer, 0, buffer.length)) ! = -1){
Log.d("response==>".newString(Arrays.copyOf(buffer, len))); }}catch(IOException e) { e.printStackTrace(); }}}Copy the code
Run the
Analysis of the
This is the socket sending the HTTP request packet, writing the packet to an outputStream and sending it. OutputStream is a socket object method. Follow up on socket implementation
These are the interfaces to implement, to find where to implement, follow the setImpl method
You can see that the impL is the instance object, there are branches, look at factory first, search for factory = in the file to see what is assigned,
SocksSocketImpl(); , this is where the socket is implemented.
PlainSocketImpl = PlainSocketImpl = PlainSocketImpl = PlainSocketImpl
Search again for nothing, and then follow up with its parent, AbstractPlainSocketImpl
If (” SocketOutputStream() “); if (” SocketOutputStream() “);
Where you find the SocketOutputStream() object, search for the write() method, which takes bytes
Follow up with socketWrite() by calling the socketWrite0() method
You can see this method in the native layer.
Frida caught
SocketWrite0 () : socketWrite0() : socketWrite0
function main(){
Java.perform(function(){
//Http request
Java.use("java.net.SocketOutputStream").socketWrite0.implementation = function(fd,bytes,off,len){
hexdump(bytes,off,len)
this.socketWrite0(fd,bytes,off,len)
}
// Prints a byte array
function hexdump(bytearry,offset,length){
var HexDump = Java.use("com.android.internal.util.HexDump")
console.log(HexDump.dumpHexString(bytearry,offset,length))
}
})
}
setImmediate(main)
Copy the code
Run frida, run the script, and successfully catch the package
To improve, add request address, stack
function main(){
Java.perform(function(){
//Http request
Java.use("java.net.SocketOutputStream").socketWrite0.implementation = function(fd,bytes,off,len){
/ / address
printAddress(this.socket, true)
/ / request
hexdump(bytes,off,len)
/ / stack
showStacks()
this.socketWrite0(fd,bytes,off,len)
}
function printAddress(socket, isSend){
var localAddress = socket.value.getLocalAddress().toString()
var remoteAddress = socket.value.getRemoteSocketAddress().toString()
if(isSend){
console.log(localAddress +"= = = = >"+ remoteAddress)
}else{
console.log(remoteAddress +"= = = = >"+ localAddress)
}
}
function hexdump(bytearry,offset,length){
var HexDump = Java.use("com.android.internal.util.HexDump")
console.log(HexDump.dumpHexString(bytearry,offset,length))
}
function showStacks() {
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
}
})
}
setImmediate(main)
Copy the code
Request address, stack is printed
Now we’re done with the request part, and we have response
response
Analysis of the
The socket getInputStream is called. GetInputStream and getOuputStream are paired together. Or socketWrite0() is in a SocketOutputStream, so socketRead0() is in a SocketInputStream.
Frida caught
Try using Frida hook and add it to the previous code
//Http response
Java.use("java.net.SocketInputStream").socketRead0.implementation = function(fd,bytes,off,len,timeout){
printAddress(this.socket, true)
hexdump(bytes,off,len)
showStacks()
return this.socketRead0(fd,bytes,off,len,timeout)
}
Copy the code
It is also successful to capture the returned data
I caught all the HTTP packets, but what about HTTPS packets
HTTPS
request
Again, create an HTTPS request
try {
final String host = "www.httpbin.org";
final int port = 443;
final String path = "/get";
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port);
StringBuilder sb = new StringBuilder();
sb.append("GET " + path + "HTTP / 1.1 \ r \ n");
sb.append("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36\r\n");
sb.append("Host: "+ host+"\r\n");
sb.append("\r\n");
Log.d("request body ===>", sb.toString());
OutputStream outputStream = socket.getOutputStream();
outputStream.write(sb.toString().getBytes());
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer, 0, buffer.length)) ! = -1){
Log.d("response ==>".newString(Arrays.copyOf(buffer, len))); }}catch (IOException e) {
e.printStackTrace();
}
Copy the code
After running
Analysis of the
Using debugging, you can quickly locate the object class,
When source search ConscryptFileDescriptorSocket
Address: aospxref.com/android-8.1…
Then search the source file for the internal class SSLOutputStream, which inherits OutputStream and overrides the original write method
Track ssl.write() in the write method
Nativecrypto.ssl_write () : nativecrypto.ssl_write () : nativecrypto.ssl_write () : NativeCrypto
Frida caught
With frida hook under org. Conscrypt. NativeCrypto class under the SSL_write () method
function main(){
Java.perform(function(){
//Https request
Java.use("org.conscrypt.NativeCrypto").SSL_write.implementation = function(ssl,fd,shc,bytes,off,len,timeout){
hexdump(bytes,off,len)
showStacks()
this.SSL_write(ssl,fd,shc,bytes,off,len,timeout)
}
// Prints a byte array
function hexdump(bytearry,offset,length){
var HexDump = Java.use("com.android.internal.util.HexDump")
console.log(HexDump.dumpHexString(bytearry,offset,length))
}
function showStacks() {
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
}
})
}
setImmediate(main)
Copy the code
When run, you will see an error saying that the NativeCrypto class could not be found
Use the objection to look at, whether to exist in memory NativeCrypto, added com. The android prefix, reoccupy frida com.android.org.conscrypt.NativeCrypto try it
The bag was caught this time
response
The response in the same way
Frida caught
//Https response
Java.use("com.android.org.conscrypt.NativeCrypto").SSL_read.implementation = function(ssl,fd,shc,bytes,off,len,timeout){
hexdump(bytes,off,len)
showStacks()
return this.SSL_read(ssl,fd,shc,bytes,off,len,timeout)
}
Copy the code
The complete code
function main(){
Java.perform(function(){
//Http request
Java.use("java.net.SocketOutputStream").socketWrite0.implementation = function(fd,bytes,off,len){
printAddress(this.socket, true)
hexdump(bytes,off,len)
showStacks()
this.socketWrite0(fd,bytes,off,len)
}
//Http response
Java.use("java.net.SocketInputStream").socketRead0.implementation = function(fd,bytes,off,len,timeout){
printAddress(this.socket, false)
hexdump(bytes,off,len)
showStacks()
return this.socketRead0(fd,bytes,off,len,timeout)
}
//Https request
Java.use("com.android.org.conscrypt.NativeCrypto").SSL_write.implementation = function(sslNativePointer,fd,shc,bytes,off,len,timeout){
printHttpsAddress(fd)
hexdump(bytes,off,len)
showStacks()
return this.SSL_write(sslNativePointer,fd,shc,bytes,off,len,timeout)
}
//Https response
Java.use("com.android.org.conscrypt.NativeCrypto").SSL_read.implementation = function(sslNativePointer,fd,shc,bytes,off,len,timeout){
printHttpsAddress(fd)
hexdump(bytes,off,len)
showStacks()
return this.SSL_read(sslNativePointer,fd,shc,bytes,off,len,timeout)
}
function printHttpsAddress(fd, isSend){
var local = Socket.localAddress(fd.getInt$())
var peer = Socket.peerAddress(fd.getInt$())
if(isSend){
console.log(local.ip+":"+local.port +"= = = = >"+ peer.ip+":"+peer.port)
}else{
console.log(peer.ip+":"+peer.port +"= = = = >"+ local.ip+":"+local.port)
}
}
function printAddress(socket, isSend){
var localAddress = socket.value.getLocalAddress().toString()
var remoteAddress = socket.value.getRemoteSocketAddress().toString()
if(isSend){
console.log(localAddress +"= = = = >"+ remoteAddress)
}else{
console.log(remoteAddress +"= = = = >"+ localAddress)
}
}
function hexdump(bytearry,offset,length){
var HexDump = Java.use("com.android.internal.util.HexDump")
console.log(HexDump.dumpHexString(bytearry,offset,length))
}
function showStacks() {
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()));
}
})
}
setImmediate(main)
Copy the code