关于个人防火墙的真相

Keil5破解与防火墙冲突解决:实战技巧汇总 详解Keil5破解教程中的常见问题,重点解决破解过程中因防火墙拦截导致的软件异常,提供可操作的实战方案,确保开发环境顺利部署。 阅读详情
原文作者: MaD
原文标题: The truth about personal firewalls
电子邮件: mad-factor@mail.ru
作者国籍:
俄罗斯
原文链接:http://www.rootkit.com/newsread.php?newsid=849

翻译:syspro
声明:1、本人翻译水平有限,有不当之请大家理解。如部分看不懂可以和原文对照。
             2、欢迎转载,但请不要漏掉原文作者和翻译者的信息。
             3、欢迎大家指出我翻译中的错误,我好改正。

内容:

        有多种方式来保护你的计算机免受恶意软件的侵害,比如软件防火墙,病毒和Rootkit检测软件等。所有这些防护软件都基于一些众所周知而几乎没有改进的技术,而且这些技术你也许已经知道,继承这些技术的安全产品也是不完善的。这样的后果通常是可怕的。然而这些安全公司却天真的认为他们的产品是最先进的,包含了最新的特性,是用户必备的。但是只要你透过他们的华丽的外衣就会看到,他们的Bug和错误甚至比你在学校的设计还要多。虽说生产一款产品首要的是好而强有力的广告。但沉重的广告和糟糕的测试结合在一起能向用户展示一些产品所谓的强大吗,能使其产生一种强烈的购买欲望吗?当然不行。
        保护你的个人电脑免受外部的和内部的第三者的攻击是一个好主意。一些保护你的PC远离木马和间谍软件“启发式”的方法好像真在工作。如果他们工作的话,付30到50美元就能获得实时的保护和更新的确是个非常好的想法。可惜,他们不能。
        首先我想为我糟糕的英语道歉。我们的讨论将会涉及以下产品:
            ZoneAlarm Firewall 6.x
            Outpost Firewall 3.x and 4.x
            Look'n'Stop Firewall 2.0
            Kerio Firewall 4.3
            Sygate Firewall 5.6
            Jetico Firewall 1.0
            PortsLock Firewall 1.9
            Tiny Firewall 6.5
            Norton Internet Security 8.0
            Comodo Firewall 2.4
            OnlineArmor Firewall 2.1
        个人软件防火墙的保护有2种基本级别:NDIS(网络驱动接口规范)和TDI(传输数据接口)。NDIS级是建立在TCP/IP栈的基础上的,在这个级别上的保护能阻止基于TCP/IP栈BUG的攻击,甚至你不用更新你的栈;他也能防御许多电子欺骗,洪水攻击和分布式拒绝服务攻击。没有使用NDIS技术的防火墙自然变成了局外人。失败者有PortsLock防火墙, Norton Internet Security, Comodo防火墙 等。你真的愿意为PortsLock防火墙付35欧元吗,他甚至不能抵御低级别的TCP/IP攻击。或者为Comodo付79美元?为你的系统感到悲哀。真正的防火墙是基于NDIS级的。基于NDIS有两种不同的保护方法。第一种是NDIS-hooking保护。主要方法是Hooks NdisRegisterProtocol()/NdisOpenAdapter()。当NDIS协议试图被注册时或是正要绑定某个适配器时,防火墙将接到通知。在防火墙正在HOOK NDIS_PROTOCOL_BLOCK and NDIS_OPEN_BLOCK的句柄的这个关键时刻,并且当系统想要发送或接收数据包时,防火墙将会被通知当这些发生的时候。防火墙正试图安装他们的钩子时是有趣的时候,几乎每个防火墙都是hook NDIS_PROTOCOL_BLOCK的句柄,但是Sygate, Kerio 和Jetico等除外,他们是HOOK NDIS_PROTOCOL_CHARACTERISTICS的句柄,而不是调用真正的NdisRegisterProtocol(),在那之后他们又移动到原来的句柄。更安全吗?对吗?正是,防火墙应该独立工作,与多少协议被注册和多少被绑定无关。是的,每个防火墙都支持这个。例如,当ZoneAlarm正在hook一个句柄时,他是分配一个无分页的内存并且放入以下几条指令。
pop        eax         ;   58
push        HookData    
;   68  XX XX XX XX
push        eax        
;   50
jmp        HookedHandler    
;  E9 XX XX XX XX

        然后,他写一些重要的信息在其他内存片,调用HookData和所有在NDIS_PROTOCOL_BLOCK中被hook的句柄:
       
OpenAdapterCompleteHandler
CloseAdapterCompleteHandler
BindAdapterHandler
UnbindAdapterHandler

        在NDIS_OPEN_BLOCK中的:
       
    SendHandler
    ReceiveHandler
    ReceivePacketHandler
    SendPacketsHandler

        对NDIS_PROTOCOL_BLOCK象下面这样:
       
    VOID HookedOpenAdapterComplete(
        PVOID HookData,
        IN NDIS_HANDLE  ProtocolBindingContext,
        IN NDIS_STATUS  Status,
        IN NDIS_STATUS  OpenErrorStatus
    );

       真正的OpenAdapterComplete() 句柄被放在这:[HookData + 0x770]
        
    VOID HookedCloseAdapterComplete(
        PVOID HookData,
        IN NDIS_HANDLE  ProtocolBindingContext,
        IN NDIS_STATUS  Status
    );

       真正的CloseAdapterComplete() 句柄被放在这:[HookData + 0x774]
         
    VOID HookedBindAdapter(
        PVOID HookData,
        OUT PNDIS_STATUS Status,
        IN NDIS_HANDLE  BindContext,
        IN PNDIS_STRING  DeviceName,
        IN PVOID  SystemSpecific1,
        IN PVOID  SystemSpecific2
    );

       真正的BindAdapter() 句柄被放在这:[HookData + 0x764]
     
   VOID HookedUnbindAdapter(
        PVOID HookData,
        OUT PNDIS_STATUS  Status,
        IN NDIS_HANDLE  ProtocolBindingContext,
        IN NDIS_HANDLE  UnbindContext
    );

        真正的UnbindAdapter()  句柄被放在这: [HookData + 0x768]
        For NDIS_OPEN_BLOCK:
   VOIDHookedSend(
        PVOID HookData,
        IN NDIS_HANDLE  NdisBindingHandle,
        IN  PNDIS_PACKET  Packet
    );

       真正的Send()  句柄被放在这: [HookData + 0x1A4]
   
 VOID  HookedReceive(
        PVOID HookData,
        IN  NDIS_HANDLE             ProtocolBindingContext,
        IN  NDIS_HANDLE             MacReceiveContext,
        IN  PVOID                   HeaderBuffer,
        IN  UINT                    HeaderBufferSize,
        IN  PVOID                   LookAheadBuffer,
        IN  UINT                    LookaheadBufferSize,
        IN  UINT                    PacketSize
    );

       真正的Receive() 句柄被放在这: [HookData + 0x4D0]

 VOID HookedReceivePacket(
        PVOID HookData,
        IN  NDIS_HANDLE             ProtocolBindingContext,
        IN  PNDIS_PACKET            Packet
);

       真正的ReceivePacket() 句柄被放在这: [HookData + 0x570]

VOID HookedSendPackets(
        PVOID HookData,
        IN NDIS_HANDLE              MiniportAdapterContext,
        IN PPNDIS_PACKET            PacketArray,
        IN UINT                     NumberOfPackets
);
       真正的SendPackets()  句柄被放在这:  [HookData+2E4h]

        可怜的ZoneAlarm,这是如此的简单对于获取真实的句柄并恢复他。
        我说过,每个防火墙都支持多数的注册协议。事实上,并不是每个。Sygate认为,保持关于协议和公开包的所有信息在他的.data段中已经足够了。不幸是个坏主意。他的句柄HOOK方式比ZoneAlarm简单,但是说明哪些内存将被分配的指令被 放在Sygate的驱动Teefer.sys中:

    pop        eax        ; 58
    push        HookData    ; 68 XX XX XX XX
    push        eax        ; 50
    jmp        FakeHandler    ; E9 XX XX XX XX

        HookData也是放在.data中的。Sygate总共能HOOK576个句柄(包括协议和开放块句柄)。于是,大约有40-50个NDIS_PROTOCOL_BLOCK和NDIS_OPEN_BLOCK能被Hook(不要忘记几个开放块能被附加到一个协议块)。大概40-50块已经足够了,但那样的代码实在是个糟糕的设计,给缓冲区溢出打了个招呼。

        我有另外一个好例子,是关于关于多么有必要知道怎样Hook和hook多少。那些来自Kerio防火墙小组的家伙不知道这些。作为一个好的防火墙,设置HOOK在 NdisRegisterProtocol(), NdisDeregisterProtocol(), NdisOpenAdapter(), NdisCloseAdapter() 等函数并且HOOK句柄。就像我说的,Kerio只是hook NDIS_PROTOCOL_CHARACTERISTICS的句柄并且仅仅调用NdisRegisterProtocol()函数,但他不将句柄移回NDIS_PROTOCOL_CHARACTERISTICS。这会怎样?未公开的特性?我不这样认为,恰恰是粗心的编码和对内核标准和架构的误解。另一个好的例子是,Kerio团队不知道任何关于NDIS的开发,事实就是这样,他们甚至不知道怎样去HOOK。Kerio防火墙HOOK在NDIS_PROTOCOL_CHARACTERISTICS里:
    OpenAdapterCompleteHandler
    CloseAdapterCompleteHandler

    并这样hook NDIS_OPEN_BLOCK:
    SendHandler
    SendPacketsHandler

        不是太多?刚好。他能被用来绕过他的NDIS保护,并发送一个包给TCP/IP栈。你虽然已经按了“阻止所有”按钮,但仍然能在本地嗅探器下看到进来的数据包。我可不喜欢像Kerio防火墙假装的那样假装自己受保护的时候,再去嗅探器下看数据包。从另一个方面来说,Outpost防火墙,喜欢在NDIS_PROTOCOL_BLOCK中hook更多的句柄:

    OpenAdapterCompleteHandler
    SendCompleteHandler
    TransferDataCompleteHandler
    RequestCompleteHandler
    ReceiveHandler
    StatusHandler
    ReceivePacketHandler
    BindAdapterHandler
    UnbindAdapterHandler

        在 NDIS_OPEN_BLOCK中:
        Outpost 4.0:
    SendCompleteHandler
    TransferDataCompleteHandler
    ReceiveHandler
    ReceivePacketHandler
    StatusHandler

       Outpost 3.x:
    SendHandler
    TransferDataHandler
    SendCompleteHandler
    TransferDataCompleteHandler
    ReceiveHandler
    RequestCompleteHandler
    ReceivePacketHandler
    SendPacketsHandler
    StatusHandler

       他的句柄调用和防火墙之间的代码是非常有趣的:
    call    ImCode        ; E8 XX XX XX XX
    <some specific data>

     For Outpost 3.x:

    pop        eax        ; 58
    push        [eax]        ; FF 30        Pushing the real handler
    pushad                ; 60
    push        [eax+4]        ; FF 70 04
    push        [esp+28h]    ; FF 74 24 28    Pushing return address
    jmp        [eax+8]        ; FF 60 08

    For Outpost 4.0:

    pop        eax        ; 58
    add        eax, 3        ; 83 C0 03    Missing three zero bytes after call
    push        [eax]        ; FF 30        Pushing the real handler
    pushad                ; 60
    push        [eax+4]        ; FF 70 04
    push        [esp+28h]    ; FF 74 24 28    Pushing return address
    jmp        [eax+8]        ; FF 60 08

       像我们看到的那样,那不是一个问题对于卸载所有的HOOK并立即获取系统控制权。如果你厌烦了这中间的汇编代码,他们通常是能够转换成普通C代码的,我能向你展示一些来自Tiny防火墙团队有趣的东西,他假装是真正的安全,并且向我们展示了很多的hook:

    NdisOpenAdapter
    NdisCloseAdapter
    NdisInitializeWrapper
    NdisTerminateWrapper
    NdisMRegisterMiniport
    NdisIMRegisterLayeredMiniport
    NdisRegisterProtocol
    NdisMSetAttributesEx
    NdisRegisterMac
    NdisIMAssociateMiniport
    NdisClOpenAddressFamily
    NdisCmRegisterAddressFamily
    NdisMCmRegisterAddressFamily
    NdisMCoSendComplete

       哦,看起来很优秀,也真是很优秀的样子,他们试图对这些函数做一个结合HOOK通过设置跳转到他们的句柄。我不喜欢“结合”,知道为什么吗?那不是因为他难以实现或是有些指令很难“结合”(理论上可行,实践上未必,我不认为在真正函数的开端那样做可行)。主要的原因是那样不安全。Rootkit开发者使用他是因为那是一种获取控制权的简单的方式,但不要试图把他用作安全软件中,就像用恐怖份子的方法对付恐怖分子一样。还有要说的是,我没有发现任何线程安全和多处理器安全的代码。再一次失败。当你在“结合”某些代码的时候,你需要确信没有一个线程、没有一个CPU在运行这些代码。
        Tiny防火墙为每个HOOK句柄申请内存,并拷贝这些C函数在开端和结尾:
    push        ebp                    ; 55
    mov        ebp, esp                ; 8B EC
    sub        esp, XXh                ; 83 EC XX
    mov        byte ptr [ebp-1], XXh            ; C6 45 FF XX
    mov        dword ptr [ebp-8], HookedHandler    ; C7 45 F8 XX XX XX XX
    <...>
    push        RealHandler
    call        [ebp-8]
    mov        esp, ebp
    pop        ebp
    ret        XXh

       于是这就变的相当简单,对于从新句柄偏移0xD去获得真的句柄。对所有的句柄,Tiny都是拷贝上面的代码。
    hook在NDIS_PROTOCOL_BLOCK中:

    SendCompleteHandler
    StatusHandler

    Hooked 在 NDIS_OPEN_BLOCK中:

    TransferDataHandler
    SendCompleteHandler
    TransferDataCompleteHandler
    ReceiveHandler
    ReceivePacketHandler
    StatusHandler

       需要说的是,有些防火墙变聪明了,如果他们被别人hook的时候,他们会试图恢复他们的hook。例如,Outpost防火墙就检测这个并监视他们的hook,但仅仅像指针的安全那样。也许他们不认为会有剪接戏法?Outpost小组不知道,白帽子Sygate防火墙也能恢复他们的hook,但他恢复的仅仅是NDIS_OPEN_BLOCK.SendHandler和 NDIS_OPEN_BLOCK.SendPacketsHandler。那是奇怪的,因为因为他们hook了很多NDIS_PROTOCOL_BLOCK中的句柄:

    OpenAdapterCompleteHandler
    CloseAdapterCompleteHandler
    TransferDataCompleteHandler
    ReceiveHandler
    StatusHandler

    和 NDIS_OPEN_BLOCK 的hook:

    SendHandler
    TransferDataHandler
    TransferDataCompleteHandler
    ReceiveHandler
    ReceivePacketHandler
    SendPacketsHandler
    StatusHandler

       只有几种防火墙用中间层NDIS驱动来做NDIS级的保护。这是一个聪明的解决方案。例如,Look’n’Stop 和 Outpost 2008 防火墙用IM NDIS驱动。Outpost好的改进是在去年。但是现在绕过防火墙变的容易使因为没有HOOK,没有伎俩和没有任何未公布的特性被使用。现在你能粉碎所有的IM NDIS防火墙只是绕过他们。不需要扰乱防火墙接受和发送包的句柄,你也不用向他们发送包。总之,使用IM NDIS驱动是好的,众所周知的,已公布的,一个正确的保护系统不受外部攻击的方法。

        像你可能看到的那样,技术各个防火墙的技术是相似的,思路甚至能被盗用并且没有人会说你盗用了一个想法。好的方式是透过表面创新你的产品。不需去思考,不用产生想法,去反汇编、调试并且对它感兴趣。第二种主级别的防火墙基于TDI,传输数据接口能为内核传输协议栈提供更高级别的访问。Afd.sys,能解析winsock,经由tdi.sys(TDI层,上面层说过)与Windows TCP/IP栈(tcpip.sys)通信。于是,又几种方式和地方去安装hook并监视你的程序和网络通信。设置你的保护最好的地方正是在tcpip.sys设备,它能在协议栈的最上层解释执行:
        DeviceIp
        DeviceTcp
        DeviceUdp
        DeviceIPMULTICAST
        DeviceRawIp

        好的,你甚至能通过/Device/RawIp来戏弄一些人。对于阻止程序的一个访问网络的请求最好的方式(公开
的方式,也是重要的),是附加到这些设备上并监视他们。几乎所有的防火墙都这样做了,因为这是通知用户陌生程序要访问网络的好方法。例如,Look’n’Stop附加他的设备到tcpip.sys设备:
        DevicePcaTcpFilter -> DeviceTcp
        DevicePcaUdpFilter -> DeviceUdp
        DevicePcaRawIpFilter -> DeviceRawIp

        /Device/Ip在那里?不是足够的,我们需要确信,所有种类的连接需要被监视,或是他们恰恰通过了这个假冒的保护。
        你的看见这些设备在你的WinObj工具里:
        DeviceComodoRawIpFilter
        DeviceComodoUdpFilter
        DeviceComodoTcpFilter
        DeviceComodoIpFilter
        我希望你能猜到,Comodo防火墙是附加设备到相同名字的tcpip.sys设备。

        Outpost、Kerio、Jetico 防火墙, Norton Internet Security仅仅附加一个无名的设备到Tcp,Udp,Ip,RawIp,没有感兴趣的事。了解设备栈结构的人应该知道抛开这些附加设备使防火墙不再提示是相当容易的。你只需要找到tcpip.sys的DRIVER_OBJECT的指针,遍历DeviceObject列表,清空所有DEVICE_OBJECT的附加项。相当容易吧?但对对抗防火墙很有效,他们的防护程序就是在那附近。另一个脆弱防火墙的错误和夸大的广告。除了附加技术外,还有另一种有趣而复杂的的技术,但对恶意软件更有效,这就是MajorTable hook。大家都知道,当用户态程序想与驱动交互的时候,他通知要交互驱动的I/O管理器。I/O管理器产生一个IRP,并调用DRIVER_OBJECT.MajorTable[IRP_MJ_XXX]的句柄。就在tcpip.sys这,一些防火墙仅仅hook一个IRP_MJ_XXX句柄并监视所有调用,通过允许请求和拒绝禁止。找到一个真的句柄不是很容易,哈?几乎每个人都认为那不可能。寻找一些被hook的句柄的主要方法是,他必须被调用然后会被发现。通过hook Int 0x01,设置TF,防火墙句柄的所有调用,我们能发现一个防火墙要调用的真的句柄。简单,MajorTable-hooking技术被像ZoneAlarm这样的防火墙青睐,他是这样HOOK的:
    IRP_MJ_CREATE
    IRP_MJ_CLOSE
    IRP_MJ_DEVICE_CONTROL
    IRP_MJ_INTERNAL_DEVICE_CONTROL
    IRP_MJ_CLEANUP

        另一个局部hook的失败是,tcpip.sys仅有TCPDispatch() 和TCPDispatchInternalDeviceControl()2个IRP句柄,第一个被所有 MajorTable填充,把它从另一个句柄上移出时容易的。TCPDispatchInternalDeviceControl()你能通过使用另一个方法 (例如前面说的追踪方法和反汇编方法)来发现。Sygate防火墙喜欢HOOK这些句柄:
        IRP_MJ_CREATE
        IRP_MJ_CLOSE
        IRP_MJ_DEVICE_CONTROL
        IRP_MJ_INTERNAL_DEVICE_CONTROL

        PortsLock防火墙,hook所有MajorTable句柄。好主要,既不将TCPDispatch()也不将TCPDispatchInternalDeviceControl() 给敌人。Tiny防火墙是hook下面的句柄。
        IRP_MJ_CREATE
        IRP_MJ_CLOSE
        IRP_MJ_DEVICE_CONTROL
        IRP_MJ_INTERNAL_DEVICE_CONTROL
        IRP_MJ_CLEANUP

        对于在一个防火墙中仅有这种类型的保护是不严重的,你不这样认为吗?我认为像PortsLock防火墙,Norton Internet Security,Comodo防火墙和其他有“防火墙”这个错误称号的,就像一些有着很漂亮界面的保护系统。恶意软件正在变的越来越猖獗,每天都有大量的ROOTKIT杯注册,更多老练的,先进的,比防火墙更底层的正在不断涌现。他们试图影响其他进程并隐匿其中。就像一个披着羊皮的狼。我谈到,injection, OpenProcess()/WriteProcessMemory()/CreateRemoteThread()和一个好的shellcode或一个self-mapped模块等都能透过防护与外部通信,而且工作的很好,也很容易编写,所有需要好的保护而不受其侵害。系统服务标提供内核函数的访问通道,他是通过调_KiSystemService,那是用用户模式和驱动来实现的。防火墙为了阻止这些动作使系统保持健壮,成功地hook了打开进程、写进程内存、创建远线程、进程、文件、文件编辑等函数。防火墙喜欢做这些,例如,ZoneAlarm防火墙hook以下系统服务:
     ZwConnectPort
    ZwCreateFile
    ZwCreateKey
    ZwCreatePort
    ZwCreateProcess
    ZwCreateProcessEx
    ZwCreateSection
    ZwCreateWaitablePort
    ZwDeleteFile
    ZwDeleteKey
    ZwDeleteValueKey
    ZwDuplicateObject
    ZwLoadKey
    ZwMapViewOfSection
    ZwOpenFile
    ZwOpenProcess
    ZwOpenThread
    ZwReplaceKey
    ZwRequestWaitReplyPort
    ZwRestoreKey
    ZwSecureConnectPort
    ZwSetInformationFile
    ZwSetSystemInformation
    ZwSetValueKey
    ZwTerminateProcess

       他监视对注册表,进程,驱动,文件的访问,并阻止自己被关闭。Outpost Firewall 4 hook更多的服务:
    ZwAssignProcessToJobObject
    ZwClose
    ZwCreateFile
    ZwCreateKey
    ZwCreateProcess
    ZwCreateProcessEx
    ZwCreateSymbolicLinkObject
    ZwCreateThread
    ZwDeleteFile
    ZwDeleteKey
    ZwDeleteValueKey
    ZwLoadDriver
    ZwMakeTemporaryObject
    ZwOpenFile
    ZwOpenKey
    ZwOpenProcess
    ZwProtectVirtualMemory
    ZwQueryDirectoryFile
    ZwQueryKey
    ZwQueryValueKey
    ZwReplaceKey
    ZwRestoreKey
    ZwSaveKey
    ZwSaveKeyEx
    ZwSetInformationFile
    ZwSetValueKey
    ZwTerminateProcess
    ZwTerminateThread
    ZwUnloadDriver
    ZwWriteVirtualMemory

       但事实上他仅用了他们的一半。他不关心驱动,你能加载任何你想要的,但他hook了ZwLoadDriver。更多的hook就更好吗?啊哈,对漏洞挖掘者来说更好。不是每个人都知道代码的质量怎样,它将要运行当我们调用ZwOpenKey时。我的系统将要蓝屏吗?另一个关于hook的例子是Kerio 防火墙:
    ZwClose
    ZwCreateFile
    ZwCreateKey
    ZwCreateProcess
    ZwCreateProcessEx
    ZwCreateThread
    ZwDeleteFile
    ZwDeleteKey
    ZwDeleteValueKey
    ZwLoadDriver
    ZwMapViewOfSection
    ZwOpenFile
    ZwOpenKey
    ZwResumeThread
    ZwSetInformationFile
    ZwSetValueKey
    ZwTerminateProcess
    ZwWriteFile

       没看见ZwOpenProcess/ZwWriteVirtualMemory的hook。使用Kerio你能插入你想要的每个进程,包括允许的进程。Sygate所用的hook比其他的少:
    ZwTerminateProcess
    ZwMapViewOfSection
    ZwAllocateVirtualMemory
    ZwCreateThread
    ZwProtectVirtualMemory
    ZwWriteVirtualMemory

       他们认为能通过hook ZwWriteVirtualMemory来保护系统。那是有BUG的:你能打开进程,并改变一些线程的context,几乎与 Jetico做的相同:
    ZwConnectPort
    ZwCreatePort
    ZwCreateThread
    ZwTerminateProcess
    ZwWriteVirtualMemory
      
        不是很有趣。Tiny防火墙做的最有趣:
    ZwCreateKey
    ZwCreateSection
    ZwOpenKey
    ZwSetInformationProcess
    ZwTerminateProcess

       你能这样说吗?:这是容易的对于通过ZwWriteVirtualMemory来插入一些东西。当然,但当此恶意行为发生时,用户将被通知。这是个愚蠢的小玩笑,对于在用户模式下来保护,Tiny防火墙载入他的UmxSbxExw.dll 到每个进程并hook许多进程通过安装每个函数开始的跳转:
kernel32.dll:
CreateProcessA
CreateProcessW
CreateRemoteThread
DebugActiveProcess
FreeLibrary
GetProcAddress
LoadLibraryExW
OpenThread
TerminateProcess
TerminateThread
WriteProcessMemory

user32.dll:
BroadcastSystemMessage
BroadcastSystemMessageA
BroadcastSystemMessageExA
BroadcastSystemMessageExW
BroadcastSystemMessageW
EndTask
ExitWindowsEx
OpenClipboard
PostMessageA
PostMessageW
PostThreadMessageA
PostThreadMessageW
SendDlgItemMessageA
SendDlgItemMessageW
SendMessageA
SendMessageCallbackA
SendMessageCallbackW
SendMessageTimeoutA
SendMessageTimeoutW
SendMessageW
SendNotifyMessageA
SendNotifyMessageW
SetUserObjectSecurity
SetWindowsHookA
SetWindowsHookExA
SetWindowsHookExW
SetWindowsHookW

advapi32.dll:
AbortSystemShutdownW
AdjustTokenPrivileges
ChangeServiceConfig2A
ChangeServiceConfig2W
ChangeServiceConfigA
ChangeServiceConfigW
ControlService
CreateProcessAsUserA
CreateProcessAsUserW
CreateProcessWithLogonW
CreateServiceA
CreateServiceW
DeleteService
EnumDependentServicesA
EnumDependentServicesW
EnumServicesStatusA
EnumServicesStatusExA
EnumServicesStatusExW
EnumServicesStatusW
InitiateSystemShutdownExW
InitiateSystemShutdownW
OpenSCManagerA
OpenSCManagerW
OpenServiceA
OpenServiceW
QueryServiceConfig2A
QueryServiceConfig2W
QueryServiceConfigA
QueryServiceConfigW
QueryServiceStatus
QueryServiceStatusEx
SetFileSecurityW
SetKernelObjectSecurity
SetNamedSecurityInfoW
SetSecurityInfo
SetServiceObjectSecurity
StartServiceA
StartServiceW

       哦,Tiny是个hook怪物。你能看见在kernel32.dll上的hook!WriteProcessMemory在他们的保护之下以防止被插入。Tiny防火墙团队认为那是一个很酷的保护方式,在一些不稳定的程序中他可能会挂掉。从那些进程中卸载掉他的Dll也不是件难事,恢复所有的函数入口就可以享受生活了。Outpost也喜欢这样做,他加载他的wl_hook.dll到应该被保护以防止恶意软件的每个进程。那是庞大的hook队列:

kernel32.dll:
CreateProcessA
CreateProcessW
CreateRemoteThread
DebugActiveProcess
WinExec

ntdll.dll:
LdrLoadDll
LdrUnloadDll
NtCreateThread
NtResumeProcess
NtResumeThread
NtSetContextThread
NtSetValueKey
NtSuspendProcess
NtSuspendThread
NtTerminateProcess
NtWriteVirtualMemory
ZwCreateThread
ZwResumeProcess
ZwResumeThread
ZwSetContextThread
ZwSetValueKey
ZwSuspendProcess
ZwSuspendThread
ZwTerminateProcess
ZwWriteVirtualMemory

user32.dll:
CallNextHookEx
ChangeDisplaySettingsExA
ChangeDisplaySettingsExW
DdeConnect
DdeConnectList
DdeInitializeA
DdeInitializeW
EndTask
ExitWindowsEx
FindWindowExA
FindWindowExW
PostMessageA
PostMessageW
SendInput
SendMessageA
SendMessageCallbackA
SendMessageCallbackW
SendMessageTimeoutA
SendMessageTimeoutW
SendMessageW
SendNotifyMessageA
SendNotifyMessageW
SetForegroundWindow
SetWindowPos
SetWindowsHookExA
SetWindowsHookExW

        那不是一个保护,是没有必要的代码。是的,他能抵制一些稀有恶意代码,但没有更多。一些防火墙不仅想被作为一个防火墙来使用,他们包含了一些有趣的特性像间谍软件或rootkit的检测程序。是的,他们工作了 ,这就产生了一个印象。在遇到调试之前的几分钟。一些防火墙试图监视模块的加载通过设置经由PsSetLoadImageNotiryRoutine()的例行检查。Jetico Firewall, Look’n’Stop Firewall, Tiny Firewall, ZoneAlarm Firewall, Outpost Firewall是这样做的。例如,当Outpost加载时,监视dnsapi.dll的加载,他通知用户一些程序试图使用DNS服务。这将会发生,当你将要调用gethostbyname()时,dnsapi.dll 会自动加载。不是很酷。重命名dnsapi.dll到xxx.dll,加载它,找到DnsQuery_A的指针,并使用它来解析,OutPost将会关闭。这是个糟糕的方式对于在这儿的保护。几乎在每个防火墙中,你都能发现很多无用的,无效的东西。有时,它帮助理解部分代码或给出一个例子函数命名,甚至你能发现一些调式信息。Look’n’Stop防火墙团队没有区分发布版和调试版,可能那就是他们为什么留下这些东西在这:
    push    offset asc_187DC ; "f://dev//lns//2.05.cur//tdisys//w32api.c"
    push    offset aKegetcurren_23 ; "KeGetCurrentIrql() == PASSIVE_LEVEL"
    call    ds:RtlAssert

        断言在调试构建时是有用的,但不是在发布版中。Tiny防火墙有很多奇怪的格式串日志:
 .text:00011608 aNbh0x08xMac0x0 db 9,'nbh:0x%08X mac:0x%08X mah:0x%08X         pbc:0x%08X',0Dh,0Ah
.text:00011608 ; DATA XREF: HookedNdisOpenAdapter+273 o
.text:00011608 db 9,'med:"%s"',0Dh,0Ah
.text:00011608 db 9,'drv:"%s"',0Dh,0Ah
.text:00011608 db 9,'dev:"%s"',0Dh,0Ah
.text:00011608 db 9,'ada:"%s"',0
.text:00011661 align 4

我认为没人想因为这些奇怪的记录而看见蓝屏。ZoneAlarm也喜欢记录:
.text:0001A610 aUPacketSProtoS db '%u Packet %s: Proto: %s Flags: 0x%08lx Src: %2u.%2u.%2u.%2u '
.text:0001A610 ; DATA XREF: sub_1A693+119 o
.text:0001A610 db 'Dest: %2u.%2u.%2u.%2u ',0

他尤其喜欢记录在发布版本中,当然。
.text:00025A84 aSFragTLxHLxPfl db '%s frag: t=%lx h=%lx pflg=%lx subp=%lx sip=%d.%d.%d.%d dip=%'
.text:00025A84 ; DATA XREF: sub_25BAA+2D1 o
.text:00025A84 db 'd.%d.%d.%d id=%x f=%s%s%s off=%hu act=%lx',0Ah,0

我喜欢 ZoneAlarm,他给我一些函数的名字:
.text:00050250 aVsdatantVstdic db 'VSDATANT:vsTdiClientRequestReceivePreProc(): FO=%p SE=%p RE#'
.text:00050250 ; DATA XREF: sub_502A6+D3 o
.text:00050250 db '=%d IRP=%p : TIMEOUT(%u)',0Ah,0

Kerio防火墙团队不包含路径就不能生成他们的驱动:
.rdata:00433704 aCProjectsNetsecuritytoolsFire db 'C:/Projects/netsecuritytools/Firewall SDK/Build.Release/4.3.'
.rdata:00433704 db 'x/bin/Release/fwdrv.pdb',0

他们也这样记录:
.data:00434020 aFwdrvApicopyas db 'FWDRV: ApiCopyAssociatedEndpoint: Local: %u.%u.%u.%u:%u Remo'
.data:00434020 ; DATA XREF: sub_401150+3B4 o
.data:00434020 db 'te:%u.%u.%u.%u:%u, SpeedIn: %u, SpeedOut: %u, PID: 0x%04X, A'
.data:00434020 db 'pp: [%s], Service: [%s]',0

并且真是有大量这样的记录:
.data:0043B1D4 aSPagedCodeCa_7 db '%s(): Paged code called on IRQL %d',0


       我想说的是:不要紧,你喜欢记录多少,你应该移走这样的垃圾记录和垃圾代码在发布版中。越少的代码,越少的bug。也学下次蓝屏会刚好在那些糟糕测试并绑定调试信息的代码中。今年的首次揭幕是OnlineArmor防火墙。“Online Armor有一个非常好的机会,调者华尔兹就窃取了苏格兰时事通讯2008最佳软件防火墙的荣誉称号” 是的,在DriverVerifier下的首次测试就给我了一个蓝屏。真是很有趣,他在标准检查工具下挂掉了。 在里面你能发现IRP_MJ_DEVICE_CONTROL 句柄,那是处理所有与METHOD_NEITHER有关的IOCTLs。
        你知道ProbeForRead()/ProbeForWrite()?他们甚至不检查指针是否为空,这真是可笑,所有Windows用户的最好保护软件有如此多的问题。猜猜它能怎么样?一部分16进制的代码如下所示:

 int __stdcall DispatchDeviceControl(int DeviceObject, PIRP Irp)
{
  struct _IRP::$::$::$::$A02EC6A2CE86544F716F4825015773AC::_IO_STACK_LOCATION *Stack; // eax@1
  unsigned int Status; // edi@1
  PIRP _Irp; // esi@1
  void *InBuffer; // ecx@2
  int InBufferSize; // edi@2
  PVOID OutBuffer; // edx@2
  int OutBufferSize; // ebx@2
  int Length; // eax@3
  int ReturnLength; // [sp+8h] [bp-4h]@1

  ReturnLength = 0;
  _Irp = Irp;
  Stack = Irp->Tail.Overlay.CurrentStackLocation;
  Status = 0xC00000BBu;
  if ( *(_BYTE *)Stack == 14 )
  {
    InBuffer = (void *)*((_DWORD *)Stack + 4);
    InBufferSize = *((_DWORD *)Stack + 2);
    OutBuffer = Irp->UserBuffer;
    OutBufferSize = *((_DWORD *)Stack + 1);
    Irp = (PIRP)*((_DWORD *)Stack + 3);
    Status = HandleRequest((int)Irp, InBuffer, InBufferSize, OutBuffer, OutBufferSize, &ReturnLength);
  }
  Length = ReturnLength;
  _Irp->IoStatus.Status = Status;
  _Irp->IoStatus.Information = Length;
  IofCompleteRequest(_Irp, 0);
  return Status;
}

int __stdcall HandleRequest(int Ioctl, void *InBuffer, int InBufferSize, void *OutBuffer, int OutBufferSize, int *ReturnLength)
{
  &#8230;
  if ( Ioctl == 0x830020EB )
  {
    sub_1484A((int)OutBuffer);
    *v6 = 28;
    return 0;
  }

在sub_1484A()里什么是如此的有趣?看看这里:
int __stdcall sub_1484A(int a1)
{
  int result; // eax@3
  CPPEH_RECORD ms_exc; // [sp+Ch] [bp-18h]@1

  ms_exc.disabled = 0;
  if ( dword_16168 )
  {
    memcpy((void *)a1, (const void *)dword_161A8, 0x1Cu);
  }
  else
  {
    result = 0;
    memset((void *)a1, 0, 0x1Cu);
  }
  return result;
}

       酷,在内核空间写些东西已经没有任何困难了,我们能制造一个DOS,甚至可以执行代码。我只是不想进一步发掘了,希望剩下的将被同道之一完成。如果我说的是真的话,似乎每个防火墙都能被绕过,没有东西能做到100%的保护。Rootkit,木马,蠕虫和其他恶意软件变的更加隐蔽、复杂,而且很难被发现。我不想给出任何关于选择哪款防火墙的建议,只是要确信,你用了一个功能强大的防火墙。

        MaD,逆向工程师和研究者。
个人防火墙研究及设计与实现 本论文所涉及的课题是为基于Windows操作系统的个人电脑开发一款 个人防火墙软件,为PC提供网络安全保护。 首先,本文陈述相关技术基础,深入地讨论和分析Windows操作系统网 络协议架构,研究了各种Windows系统网络数据包拦截技术,分析了各自的 优缺点。并系统阐述了常见网络攻击手段和防范方法。 然后,叙述个人防火墙的系统总体设计方案。确定采取SPI结合NDIS 的方式来进行网络数据包拦截,将系统分为三个模块:SPI拦截、NDIS拦截、 用户界面,并定义了相互问的接口,列出了主要数据结构。 最后,详细阐述核心模块的设计实现及软件测试结果。 立即下载

相关推荐

VC个人防火墙技术与实现

随着互联网的飞速发展,越来越多的企业和用户连接到互联网中。人们在充分享受着互联网所带来的方便和高效的同时,也不断受到各种计算机病毒感染和黑客恶意攻击的侵扰。在网络安全解决方案中,建立或设置防火墙是一个非常关键和有效的环节。然而,当前市场上的防火墙产品多为企业级的网关型防火墙,而针对个人用户的防火墙产品则较少。针对这种情况,本文设计和实现了一个WINDOWS操作系统下的个人防火墙软件。

python 获取窗口句柄的进程_原创干货 | 【恶意代码分析技巧】14修改内存指针实现进程注入...

上一篇文章中介绍的注入技术都是传统的注入技术,通用性好,但是也很容易被安全软件发现。随着研究的深入,攻击者们发现了新的注入技术,这类注入技术只攻击内存中特定的对象,修改内存指针,使得指针指向payload,再利用特定的操作触发payload执行。在这方面研究较多的是hexacorn(超链接:http://www.hexacorn.com/index.html)和modexp(超链接:ht...

weixin_39862899的博客 1672

从零玩转显示屏:手把手教你用Arduino驱动SPI屏幕(附引脚定义图)

本文提供了一份详尽的Arduino驱动SPI屏幕的入门指南。从SPI接口的核心引脚定义(如DC、RESET)与RGB接口的区别讲起,手把手指导硬件连接与软件库配置,并最终通过一个天气显示器实战项目,帮助读者掌握驱动SPI屏幕、显示RGB色彩内容的核心技能。

weixin_29189987的博客 131

通过程序行为追踪揪出木马病毒 【 大成天下 黄鑫 】

文章出处:大成天下   发布时间:2006-02-02   网址:http://www.unnoo.com    作者:黄鑫(glacier@unnoo.com)  对木马类程序处理多了,就渐渐觉得静/动态手工分析过程在很大程度上都是重复劳动。总要先花半个钟头了解程序特性,手工分析时还生怕漏掉某项隐蔽的关键操作,导致最终清除不彻底。其实只要在主动安装

FreeXploiT 3319

自定义LayoutManager实现android-pile-layout滑动卡片堆叠效果

这是我的第一篇博客,总算有个契机开始写博客了,就从自定义LayoutManager开始吧。 前段时间看到一个项目(android-pile-layout),效果特别不错,这是效果图: 效果确实不错,我看了下实现,是用的自定义的ViewGroup实现的,计算什么还搞的挺复杂的,具体的没细看。作者说也尝试过用LayoutManager实现,但是没找到合适的数学模型,好吧,看到数学模型我

u014296305的博客 1万+

ArcGIS实战:利用IDW反距离权重法实现气象数据的批量空间插值

本文详细介绍了如何利用ArcGIS中的IDW反距离权重法实现气象数据的批量空间插值。通过实战案例和脚本示例,展示了IDW插值在气象数据分析中的高效应用,包括算法原理、参数调优、批处理自动化及常见问题解决方案,帮助用户快速生成连续分布的气象地图。

weixin_29051149的博客 240

开源项目之防火墙 tdifw

tdifw是windows防火墙软件(TDI层驱动过滤),负责监控网络监听与连接、以及过滤信息。 源码在src目录, 程序在Bin目录,执行根目录下的批处理文件也可以,具体步骤如下:1. 运行install.bat2. 根据你机器的配置情况,编辑%SystemRoot%\system32\drivers\etc\tdifw.conf配置文件3. 重新启动计算机 主程序源码是win32的...

weixin_30546933的博客 527

代码审计工具学习之Seay(安装以及初步认识)

目录 1.1名词解释 1.2代码审计的重要性 1.3代码审计的步骤 1.4代码审计的内容 1.5常见的代码审计工具 2 Seay 2.1什么是Seay 2.2Seay的安装过程 3典型漏洞分析 3.1什么是命令注入漏洞 3.2 如何理解命令注入漏洞 3.3 如何防御命令注入漏洞 4 利用工具对命令注入漏洞进行分析 4.1DVWA靶场命令注入漏洞分析 4.2 Pikachu靶场命令注入漏洞分析 1.1名词解释 软件代码审计是对编程项目中源代码的全面...

weixin_52515588的博客 2万+

关于SEP杀毒软件

SEP杀毒软件即为诺顿杀毒,去年换笔记本电脑时第一选择了SEP作为本座的安全卫士,无奈ftp上似乎只有SEP9.0这个版本,于是就下载安装,在安装过程中出现了卡机现象。。。。这个机器可是超越93%电脑的工作站啊(qq管家硬件检测评分),居然会卡机!!决定暂停安装,于是强制暂停,然后卸载,居然卸载不掉,当时没太在意,直接删除掉其文件夹,虽然知道注册表有许多东西还没删除掉,当时没太多在意。。。悲剧来了

小飞鱼的blablabla... 6195

从Power到HO:一文搞懂主流脑图谱在DPABI里怎么选,让你的rs-fMRI分析更精准

本文深入解析了rs-fMRI分析中主流脑图谱(如Power、HO、AAL等)在DPABI中的科学选择策略,帮助研究者根据不同的神经科学研究目标优化分析流程。从解剖学图谱到功能连接图谱的特性对比,到DPABI实操中的多图谱分析工作流,提供了全面的方法论指导,助力提升静息态功能磁共振成像(rs-fMRI)研究的精准度和可重复性。

weixin_30654583的博客 403

基于本地知识库的智能问答系统架构

智能问答系统的核心可以分为4部分。1)知识库构建。2)检索。3)后处理。4)推理。知识库构建:知识库中可以包含多个向量数据库和知识图谱等,核心是怎么建立索引,使得检索时能够将与问题相关的知识给检索出来。检索:从知识库中的多个库或者知识图谱中检索出与问题相关的信息。后处理:从知识库中检索出来的信息可能是冗余的,而且可能不符合我们希望的格式要求,因此,我们需要对这些数据进行过滤,格式化等操作。推理: 基于检索出来的知识进行推理,让输出能够回答用户的问题,目前主要使用大模型进行推理。

qq_44993593的博客 1709

免费的个人电脑防火墙软件 Windows

ZoneAlarm Free Firewall:ZoneAlarm Free Firewall 是一款功能强大且易于使用的防火墙软件,提供实时保护、应用程序控制和高级防火墙功能。Comodo Firewall:Comodo Firewall 是另一个受欢迎的免费防火墙选择,它提供强大的网络保护和应用程序监控功能。GlassWire:GlassWire 是一款直观的防火墙和网络监控工具,它可以让你实时监控网络活动并提供可视化的数据统计。除了Windows自带的防火墙功能外,下面几个老牌的个人防火墙。

杨江的IT分享专栏 1483

学Simulink--基于风力发电系统的场景实例:海上风电场在复杂海况下的动态响应仿真

本实例将创建一个针对海上风电场在复杂海况下的动态响应模型。该模型不仅考虑了不同风速条件的影响,还引入了波浪和水流对风机塔架及基础结构的影响。通过仿真验证系统的有效性,并探索最佳控制参数设置以提高整体性能和稳定性。本教程展示了如何在Simulink中实现一个海上风电场在复杂海况下的动态响应仿真模型,并分析其性能。通过这种方式,我们不仅可以验证所提出的技术手段在提高海上风电场稳定性和效率方面的有效性,还能进一步探索优化参数以适应特定的应用场景。

xiaoheshang_123的博客 168

个人防火墙的真相

翻译:syspro声明:1、syspro翻译水平有限,有不当之请大家理解。如部分看不懂可以和原文对照。2、欢迎转载,但请不要漏掉原文作者和翻译者的信息。3、欢迎大家指出syspro翻译中的错误,syspro好改正。有 多种方式来保护你的计算机免受恶意软件的侵害,比如软件防火墙,病毒和Rootkit检测软件等。所有这些防护软件都基于一些众所周知而几乎没有改进的技 术,而且这些技术你也许已经知道,

2233

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Ubuntu防火墙真相:ufw与firewalld的生态适配原理

Linux防火墙本质是内核包过滤机制的用户态抽象,其核心引擎已从iptables统一演进为nftables;在此基础上,不同发行版构建了差异化的策略管理层——RHEL系依赖firewalld的D-Bus驱动zone模型,而Ubuntu原生采用ufw作为轻量、原子化、纯文本的nftables前端。这种架构分野决定了工具的生态兼容性:强行跨系统部署firewalld会引发D-Bus依赖缺失、NetworkManager冲突及nftables hook争抢等深层问题。理解ufw的两阶段规则加载、profile机制

weixin_31763817的博客 344

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

为什么你的防火墙总被绕过?(编译阶段测试缺失的6个真相)

解决防火墙频繁被绕过的难题,关键在于强化编译防火墙的测试。本文揭示6大常见漏洞根源,涵盖开发集成场景,详解静态分析、规则验证等核心方法,提升安全防护精准度。防御前置更可靠,值得收藏。

CodePulse的博客 816

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

为什么90%的安全工程师都在手动编译防火墙?真相令人震惊

掌握编译防火墙的示例,解决定制化安全策略难题。适用于企业级网络防护与高危漏洞拦截,通过源码编译实现精准控制与性能优化。提供完整步骤与配置要点,助你构建高效防护体系。值得收藏

CodeIsle的博客 1027

为什么你的系统总被植入恶意代码?,编译防火墙构建指南告诉你真相

掌握编译防火墙的实现,有效阻断恶意代码注入。本文详解其在软件构建中的应用原理与核心方法,通过源码级防护提升系统安全性,适用于开发与运维场景。关键优势在于实时拦截编译阶段攻击,保障代码纯净。值得收藏

CodeTrick的博客 768

【趋势2020】真相在逼近!

【趋势2020】第八集:为平息大众,Carrington 总理将Adam推到公众面前成为了众矢之的,而Adam提到的Yanek Novack已被秘密杀害,警方只找到了他的尸体。 Vic队长和Sandra巡官根据Yanek被害前的录像线索侦测到与他当面交易的那名神秘人的行踪,却没想到神秘人行踪的源头居然是…… 点击观看完整视频:   http://video.sina.com.cn/v

亚信安全-云安全博客 1031

发现一个顶级黑客,日常入侵阿里,一夜攻破13国防火墙

发现一个顶级黑客,日常入侵阿里,一夜攻破13国防火墙

隔壁王叔的博客 1137

关于centos关了防火墙却依然不能访问的问题

所以遇到这种问题要敢于猜测问题的原因并去验证,配合搜素引擎去寻找答案,切勿陷入一个猜测的思维定势。

禅与计算机程序设计的艺术 1万+

AI说谎训练与真相校验:构建可审计的可信推理机制

大语言模型的‘幻觉’已从随机错误演变为策略性失真,其本质是推理过程缺乏可验证性。要提升AI可信度,需超越传统置信度或困惑度指标,转向对事实一致性、证据可追溯性与因果可推演性的过程级审计。本文聚焦‘模型幻觉的临界点’这一关键现象,系统阐释如何通过受控的说谎能力激发与轻量级真相试剂协同演化,实现高责任场景(如医疗、法律、金融)中AI输出的可溯源、可推演、可冲突检测。核心技术包括字符级溯源锚点、形式化逻辑路径编织与增量式冲突图谱,为构建具备工程化诚实能力的下一代AI提供落地范式。

weixin_30823001的博客 474

为什么顶级安全团队都在自研编译防火墙工具?真相令人震惊

掌握编译防火墙的工具,提升代码安全与系统防护效率。本文揭秘顶级安全团队自研该工具的核心方法,适用于高敏感场景的定制化防御,具备高效兼容与实时拦截优势,值得收藏。

ByteGlow的博客 559
上一篇: 利用批处理快速编译测试VC网络程序
下一篇: 试用Google工具条的网页翻译!
syspro
博客等级 码龄19年 31粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值