服务器端 bind() 函数,immlib

逆向工程 Python 免疫调试器
2021-06-16 17:27:01

如何从服务器应用程序的绑定功能中获取 IP 地址和端口号。可以在免疫调试器中使用像 bphook 这样的钩子来实现吗?

我的问题是我不知道如何解压 struct psockaddr/sockaddr 或如何将 sockaddr 保存在堆栈中。

1个回答

我假设您在谈论 Windows 套接字和 IPv4,因为您没有另外提及。sockaddrMSDN 中有很好的描述它对于 IPv4 的定义如下:

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];
};

我将使用简单的服务器应用程序进行演示。首先让我们设置断点bind(),看看堆栈是什么样的:

在此处输入图片说明

如您所见,pSockAddr是一个指向sockaddr结构的指针作为函数的第二个参数被压入堆栈。让我们更进一步检查sockaddrat 0x0031F840

在此处输入图片说明

需要注意的一件非常重要的事情是sin_portsin_addr使用大端字节序存储,这意味着最重要的部分首先存储。

现在让我们进入并创建pyCommand以便使用Immunity Debugger使其自动化为此,我将使用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."

脚本的安装非常简单。所有 pyCommands 都存储在 Immunity Debugger 安装的 ./pyCommands 文件夹中。我将我的文件命名为bindtrace.py.

此后,我们将可执行文件加载到 Immunity Debugger 中。调试器将在入口点自动中断。紧接着,我们通过键入调用上面的 pyCommand !bindtrace,然后按 运行可执行文件F9一旦断点命中,我们就会在日志窗口中得到结果,可以通过Alt + L以下方式访问

在此处输入图片说明