2

How do I get IP address and port number out of bind function in Server application. Can it be achieved with hooks like bphook in immunity debugger?

My problem is that I don't know how to unpack struct psockaddr/sockaddr or how sockaddr is saved on the stack.

5

I will assume you are talking about Windows Sockets and IPv4, since you have not mentioned otherwise. sockaddr is very well described in MSDN. It is defined as for IPv4 as follows:

struct sockaddr {
        ushort  sa_family;
        char    sa_data[14];
};

struct sockaddr_in {
        short   sin_family;
        u_short sin_port;
        struct  in_addr sin_addr;
        char    sin_zero[8];
};

I will use simple server application for demonstration purposes. Firstly let's set breakpoint on bind() and see what stack looks like:

enter image description here

As you can see, pSockAddr is a pointer to sockaddr structure is pushed on to stack as a second argument to the function. Let's go a little further and examine the sockaddr at 0x0031F840:

enter image description here

One very important thing to note is that sin_port and sin_addr are stored using big-endian byte order, meaning the most significant part stored first.

Now let's jump in and get pyCommand created in order to automate it with Immunity Debugger. For this purpose I will use BpHook:

# bindtrace PyCommand by PSS 

from immlib import *

NAME = "bindtrace"

class BindBpHook(BpHook):
    def __init__(self):
        BpHook.__init__(self)

    def run(self, regs):
        imm = Debugger()

        imm.log(" ")
        imm.log("Bind() called:")

        # Read sockaddr structure address
        sockaddr = imm.readLong(regs["ESP"] + 8)        

        # Read 2 bytes of sin_family member
        sockaddr_sin_family = imm.readShort(sockaddr)

        # Read 2 bytes of sin_port and calculate port number 
        # since it is stored as big-endian
        portHiByte = ord(imm.readMemory(sockaddr + 2, 1))
        portLowByte = ord(imm.readMemory(sockaddr + 3, 1))
        sockaddr_sin_port = portHiByte * 256 + portLowByte

        # Read 4 bytes of sin_addr since it is stored as big-endian
        ipFirstByte = ord(imm.readMemory(sockaddr + 4, 1))
        ipSecondByte = ord(imm.readMemory(sockaddr + 5, 1))
        ipThirdByte = ord(imm.readMemory(sockaddr + 6, 1))
        ipForthByte = ord(imm.readMemory(sockaddr + 7, 1))

        # Print results to Log View window
        imm.log("---> Pointer to sockaddr structure: 0x%08x" % sockaddr)
        imm.log("---> sockaddr.sin_family: %d" % sockaddr_sin_family)
        imm.log("---> sockaddr.sin_port: %d" % sockaddr_sin_port)
        imm.log("---> sockaddr.sin_addr: %d.%d.%d.%d" % \
                        (ipFirstByte,ipSecondByte,ipThirdByte,ipForthByte))
        imm.log(" ")
        imm.log("Press F9 to resume")


def main(args):

    imm = Debugger()
    functionToHook = "ws2_32.bind"

    # Find address of the function to hook
    functionAddress = imm.getAddress(functionToHook)

    # Create and install our hook
    myHook = BindBpHook()
    myHook.add(functionToHook, functionAddress)

    imm.log("Hook for %s installed at: 0x%08x" % (functionToHook, functionAddress))

    return "[*] Hook installed."

Installation of the script is very simple. All pyCommands are stored in ./pyCommands folder of Immunity Debugger installation. I named my file bindtrace.py.

Thereafter, we load our executable into Immunity Debugger. Debugger will break automatically at entry point. Right after that we invoke the above pyCommand by typing !bindtrace, and run the executable by pressing F9. As soon as breakpoint hits, we get the result in Log windows, which can be accessed through Alt + L:

enter image description here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.