Search code examples
iostcpportjailbreak

How to list open ports in iOS?


I am using a *jailbroken device and I want to write an application to list the open ports (e.g. TCP ports).

I have two ideas:

  • Use some native API to get list of opened ports
  • execute shell command to get a list of opened ports and parse the result of this shell command.

Which API or shell command should I use and how can I trigger it programmatically?


Solution

  • The way I would do this is to have your app invoke the UNIX lsof command programmatically. lsof lists open "files", which on a BSD system includes sockets, which includes TCP sockets.

    It used to be that Saurik published a version of lsof that was available on Cydia. Unfortunately, I haven't been able to get that to work recently. You might try it yourself, as software from Saurik should generally be trustworthy. You could also try compiling the lsof source code yourself, as it's available online.

    However, I found a discussion thread about this here. User Firewire888 was able to get a homebuilt version of lsof working on iOS. If you trust their work, then you can download the binary file here. Per their instructions:

    1. On mac osx download ldid for macosx. https://networkpx.googlecode.com/files/ldid
    2. On mac osx download scaner's version of lsof in this thread. Thanks again!
    3. On mac osx run ldid -S lsof
    4. scp or whatever means get lsof to /usr/sbin/lsof on iPhone ( has to be in /usr/sbin otherwise get error can't fork )

    So, you need to fake codesign that version of lsof and then install it on your iPhone at /usr/sbin/lsof.

    Then, you can use the Private API NSTask (public on OS X) to run the shell command from within your app, and capture the output.

    For example, using the command:

    lsof -i4tcp
    

    will list all IPv4 TCP ports.

    In your Objective-C code, you'd do this:

    #include "NSTask.h"
    
    - (void) listTcpPorts {
       NSTask *task = [[NSTask alloc] init];
       [task setLaunchPath: @"/usr/sbin/lsof"];
       [task setArguments: [[NSArray alloc] initWithObjects: @"-i4tcp", nil]];
    
       NSPipe *pipe= [NSPipe pipe];
       [task setStandardOutput: pipe];
    
       NSFileHandle *file = [pipe fileHandleForReading];
    
       [task launch];
    
       NSData *data = [file readDataToEndOfFile];
    
       NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
       NSLog(@"tcp ports: \n %@", output);
    }
    

    This requires downloading the NSTask header, which you can find here.

    which gave me the standard output:

    Sep 11 18:53:47 iPhone5 HelloJB[34535] <Warning>: tcp ports: 
        COMMAND     PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
        apsd        143 mobile    9u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51216->17.172.238.202:5223 (ESTABLISHED)
        apsd        143 mobile   10u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51215->17.149.37.18:5223 (ESTABLISHED)
        apsd        143 mobile   12u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51215->17.149.37.18:5223 (ESTABLISHED)
        apsd        143 mobile   14u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51216->17.172.238.202:5223 (ESTABLISHED)
        dataacces   166 mobile   25u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51276->pc-in-f193.1e100.net:https (ESTABLISHED)
        dataacces   166 mobile   27u  IPv4 0x12345678      0t0  TCP 10.244.7.127:51276->pc-in-f193.1e100.net:https (ESTABLISHED)
        afcd      26764 mobile    9u  IPv4 0x12345678      0t0  TCP localhost:51284->localhost:51285 (ESTABLISHED)
        MobileSaf 33165 mobile   11u  IPv4 0x12345678      0t0  TCP 192.168.4.119:51349->stackoverflow.com:http (ESTABLISHED)
        MobileSaf 33165 mobile   12u  IPv4 0x12345678      0t0  TCP 192.168.4.119:51349->stackoverflow.com:http (ESTABLISHED)
        Weather   33191 mobile    5u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50181->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
        Weather   33191 mobile    7u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50182->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
        Weather   33191 mobile    8u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50181->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
        Weather   33191 mobile   10u  IPv4 0x12345678      0t0  TCP 192.168.4.119:50182->yts2.yql.vip.gq1.yahoo.com:http (LAST_ACK)
        notificat 33929 mobile    4u  IPv4 0x12345678      0t0  TCP localhost:51295->localhost:51296 (ESTABLISHED)
        notificat 33929 mobile    5u  IPv4 0x12345678      0t0  TCP localhost:51301->localhost:51302 (ESTABLISHED)
        notificat 33929 mobile    6u  IPv4 0x12345678      0t0  TCP localhost:51318->localhost:51319 (ESTABLISHED)
        notificat 33929 mobile    7u  IPv4 0x12345678      0t0  TCP localhost:51330->localhost:51331 (ESTABLISHED)
        syslog_re 34468 mobile    3u  IPv4 0x12345678      0t0  TCP localhost:51321->localhost:51322 (ESTABLISHED)
    

    You can choose to use different command line options, and/or parse the output, to suit your needs. Good luck!