Android ***Service 抓包不会抓包

Posted

技术标签:

【中文标题】Android ***Service 抓包不会抓包【英文标题】:Android ***Service to capture packets won't capture packets 【发布时间】:2013-07-19 22:31:13 【问题描述】:

我已经寻找了几个小时的答案,但我无法弄清楚。请帮忙。

我想做的是像应用tPacketCapture一样使用android中的***Service来抓取网络数据包

我首先使用来自谷歌的 Toy*** 示例代码并对其进行修改,因此我不会将数据发送到服务器。但是,我不确定这是否正确。

我的配置方法在调用建立() 之前使用binder.addAddress() 的wlan ip 地址。我使用的是nexus 7,我使用“adb shell netcfg | grep wlan0”来获取地址:

wlan0 UP 192.168.0.6/24 0x00001043 10:bf:48:bf:5f:9d

并将其添加到我的方法中:

    private void configure() throws Exception 
    // If the old interface has exactly the same parameters, use it!
    if (mInterface != null) 
        Log.i(TAG, "Using the previous interface");
        return;
    

    // Configure a builder while parsing the parameters.
    Builder builder = new Builder();
    builder.setMtu(1500);
    builder.addAddress("192.168.0.6", 24);

    try 
        mInterface.close();
     catch (Exception e) 
        // ignore
    

    mInterface = builder.establish();

调用它之后,我调用我修改的 run 方法来传递一个字符串而不是一个 InetSocketAddress,这并不重要,因为我没有在任何地方使用它:

    private void run(String run) throws Exception 
    configure();

    FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

    // Allocate the buffer for a single packet.
    ByteBuffer packet = ByteBuffer.allocate(32767);

    // We use a timer to determine the status of the tunnel. It
    // works on both sides. A positive value means sending, and
    // any other means receiving. We start with receiving.
    int timer = 0;

    // We keep forwarding packets till something goes wrong.
    while (true) 
        // Assume that we did not make any progress in this iteration.
        boolean idle = true;

        // Read the outgoing packet from the input stream.
        int length = in.read(packet.array());
        if (length > 0) 

            Log.i(TAG,"************new packet");
            while (packet.hasRemaining()) 
                Log.i(TAG,""+packet.get());
                //System.out.print((char) packet.get());
            

            // Write the outgoing packet to the tunnel.
            packet.limit(length);
            //  tunnel.write(packet);
            packet.clear();

            // There might be more outgoing packets.
            idle = false;

            // If we were receiving, switch to sending.
            if (timer < 1) 
                timer = 1;
            
        
    

当我执行 adb logcat 时,什么也没有发生。我这样做对吗?我觉得我错过了什么。

谢谢!

编辑:

从日志中我看到以下几行:

I/ActivityManager(  460): START u0 act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.android.toy***/.Toy***Client from pid 10247
I/ActivityManager(  460): Start proc com.example.android.toy*** for activity com.example.android.toy***/.Toy***Client: pid=10287 uid=10122 gids=50122, 3003, 1028
I/ActivityManager(  460): Displayed com.example.android.toy***/.Toy***Client: +1s144ms
I/***     (  460): Switched from [Legacy ***] to com.example.android.toy***
D/***     (  460): setting state=IDLE, reason=prepare
I/Toy***Service(10287): running ***Service
D/***     (  460): setting state=CONNECTING, reason=establish
D/***Jni  (  460): Address added on tun0: 192.168.0.6/24
I/***     (  460): Established by com.example.android.toy***.Toy***Service on tun0
W/ContextImpl(  460): Calling a method in the system process without a qualified user: android.app.ContextImpl.bindService:1406 com.android.server.connectivity.***.establish:289 com.android.server.ConnectivityService.establish***:3263 android.net.IConnectivityManager$Stub.onTransact:504 android.os.Binder.execTransact:351 
D/***     (  460): setting state=AUTHENTICATING, reason=establish

所以它似乎正在连接。

完整来源:

public class Toy***Service extends ***Service implements Handler.Callback, Runnable 
    private static final String TAG = "Toy***Service";

    private Handler mHandler;
    private Thread mThread;

    private ParcelFileDescriptor mInterface;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) 
        // The handler is only used to show messages.
        if (mHandler == null) 
            mHandler = new Handler(this);
        

        // Stop the previous session by interrupting the thread.
        if (mThread != null) 
            mThread.interrupt();
        

        // Start a new session by creating a new thread.
        mThread = new Thread(this, "Toy***Thread");
        mThread.start();
        return START_STICKY;
    

    @Override
    public void onDestroy() 
        if (mThread != null) 
            mThread.interrupt();
        
    

    @Override
    public boolean handleMessage(Message message) 
        if (message != null) 
            Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
        
        return true;
    

    @Override
    public synchronized void run() 
        Log.i(TAG,"running ***Service");
        try 
            run***Connection();
         catch (Exception e) 
            e.printStackTrace();
            //Log.e(TAG, "Got " + e.toString());
         finally 
            try 
                mInterface.close();
             catch (Exception e) 
                // ignore
            
            mInterface = null;

            mHandler.sendEmptyMessage(R.string.disconnected);
            Log.i(TAG, "Exiting");
        
    

    private boolean run***Connection() throws Exception 

        configure();

        FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

        // Allocate the buffer for a single packet.
        ByteBuffer packet = ByteBuffer.allocate(32767);

        // We keep forwarding packets till something goes wrong.
        while (true) 
            // Assume that we did not make any progress in this iteration.
            boolean idle = true;

            // Read the outgoing packet from the input stream.
            int length = in.read(packet.array());
            if (length > 0) 

                Log.i(TAG,"************new packet");
                System.exit(-1);
                while (packet.hasRemaining()) 
                    Log.i(TAG,""+packet.get());
                    //System.out.print((char) packet.get());
                
                packet.limit(length);
                //  tunnel.write(packet);
                packet.clear();

                // There might be more outgoing packets.
                idle = false;
            
            Thread.sleep(50);
        
    

    public String getLocalIpAddress()
    
        try 
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) 
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) 
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    Log.i(TAG,"****** INET ADDRESS ******");
                    Log.i(TAG,"address: "+inetAddress.getHostAddress());
                    Log.i(TAG,"hostname: "+inetAddress.getHostName());
                    Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
                    if (!inetAddress.isLoopbackAddress()) 
                        //IPAddresses.setText(inetAddress.getHostAddress().toString());
                        Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
                        return inetAddress.getHostAddress().toString();
                     else
                        Log.i(TAG,"It is a loopback address");
                    
                
            
         catch (SocketException ex) 
            String LOG_TAG = null;
            Log.e(LOG_TAG, ex.toString());
        

        return null;
    

    private void configure() throws Exception 
        // If the old interface has exactly the same parameters, use it!
        if (mInterface != null) 
            Log.i(TAG, "Using the previous interface");
            return;
        

        // Configure a builder while parsing the parameters.
        Builder builder = new Builder();
        builder.setMtu(1500);
        builder.addAddress("192.168.0.6", 24);
        try 
            mInterface.close();
         catch (Exception e) 
            // ignore
        

        mInterface = builder.establish();
    

【问题讨论】:

在run中的while循环处设置断点,如果命中了告诉我。 不,什么都没有。你得到这个工作了吗? 好吧,我需要查看更多您的代码。你在某处开始讨论吗? 你说调用configure之后你调用run,但是run做的第一件事就是再次调用configure。将有助于查看完整的代码。 我可以截取数据包,但是如何将这些数据包发送到实际目的地?你最后能做到吗? 【参考方案1】:

好的,这并不容易,但我想出了如何捕获数据包。由于我对网络不是很熟悉(但这项新工作要求我熟悉),所以我很难正确设置所有内容。基本上在 ***Service.builder 中设置了正确的路由后,我就可以正确接收数据包了。

所以:

builder.addAddress("192.168.0.6", 24); // was wrong, you need to put an internal IP (10.0.2.0 for example)

builder.addRoute("0.0.0.0", 0); // needs to be this.

您无需通过 builder.addDnsServer() 设置 DnsServer 即可使其工作。希望这对任何人都有帮助!

【讨论】:

我能够转发数据包。如果我没记错的话,我只需要读取 TCP 标头并打开另一个到该目的地的套接字并无标头发送它。当您收到响应时,您必须在将其发送回输出流之前添加 TCP 标头。这是针对 TCP 的(我只关心)。 SSL 也需要 SSL 握手。 是的,您需要将数据包转发到接口,从而转发到外部。 抱歉它不是开源的。这是生产软件,所以我也没有关于此的博客。 是的,响应的 TCP 标头需要反转,就像您的浏览器(例如)从服务器获得响应一样。还需要添加 IP 标头。 你只需要分解数据包附带的TCP头,将其从数据包中删除,并将其发送到相应的套接字。不确定这是否是您要问的。【参考方案2】:

我的配置方法在>调用建立()之前使用binder.addAddress()的wlan ip地址。我使用的是nexus 7,我使用“adb shell netcfg | grep >wlan0”来获取地址:

wlan0 UP 192.168.0.6/24 0x00001043 10:bf:48:bf:5f:9d

我在 python 中编写了一个简单的脚本,以图形方式向您展示来自 adb 的 netcfg。 它每秒都在更新。

https://github.com/ilanben/graphical_netcfg

享受:)

【讨论】:

以上是关于Android ***Service 抓包不会抓包的主要内容,如果未能解决你的问题,请参考以下文章

如何防止android app被kill

Android应用安全 | Android应用基础知识和代理抓包

2-1 如何抓不同的接口(手机抓包,web网页抓包)

Android 配置Fiddler抓包

如何用Fiddler对Android应用进行抓包

如何用Fiddler对Android应用进行抓包