求黑吧黑客安全网网vip真相?

个人防火墙的真相
翻译:syspro声明:1、syspro翻译水平有限,有不当之请大家理解。如部分看不懂可以和原文对照。2、欢迎转载,但请不要漏掉原文作者和翻译者的信息。3、欢迎大家指出syspro翻译中的错误,syspro好改正。
有 多种方式来保护你的计算机免受恶意软件的侵害,比如软件防火墙,病毒和Rootkit检测软件等。所有这些防护软件都基于一些众所周知而几乎没有改进的技 术,而且这些技术你也许已经知道,继承这些技术的安全产品也是不完善的。这样的后果通常是可怕的。然而这些安全公司却天真的认为他们的产品是最先进的,包 含了最新的特性,是用户必备的。但是只要你透过他们的华丽的外衣就会看到,他们的Bug和错误甚至比你在学校的设计还要多。虽说生产一款产品首要的是好而 强有力的广告。但沉重的广告和糟糕的测试结合在一起能向用户展示一些产品所谓的强大吗,能使其产生一种强烈的购买欲望吗?当然不行。保护你的个人电脑免受外部的和内部的第三者的攻击是一个好主意。一些保护你的PC远离木马和间谍软件“启发式”的方法好像真在工作。如果他们工作的话,付30到50美元就能获得实时的保护和更新的确是个非常好的想法。可惜,他们不能。首先我想为我糟糕的英语道歉。我们的讨论将会涉及以下产品:ZoneAlarm Firewall 6.xOutpost Firewall 3.x and 4.xLook'n'Stop Firewall 2.0Kerio Firewall 4.3Sygate Firewall 5.6Jetico Firewall 1.0PortsLock Firewall 1.9Tiny Firewall 6.5Norton Internet Security 8.0Comodo Firewall 2.4OnlineArmor 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一个句柄时,他是分配一个无分页的内存并且放入以下几条指令。 58push HookD 68 XX XX XX XX 50jmp HookedH E9 XX XX XX XX然后,他写一些重要的信息在其他内存片,调用HookData和所有在NDIS_PROTOCOL_BLOCK中被hook的句柄:OpenAdapterCompleteHandlerCloseAdapterCompleteHandlerBindAdapterHandlerUnbindAdapterHandler在NDIS_OPEN_BLOCK中的:SendHandlerReceiveHandlerReceivePacketHandlerSendPacketsHandler
对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中:
58push HookD 68 XX XX XX XX 50jmp FakeH 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里:OpenAdapterCompleteHandlerCloseAdapterCompleteHandler
并这样hook NDIS_OPEN_BLOCK:SendHandlerSendPacketsHandler
不是太多?刚好。他能被用来绕过他的NDIS保护,并发送一个包给TCP/IP栈。你虽然已经按了“阻止所有”按钮,但仍然能在本地嗅探器下看到进来的数 据包。我可不喜欢像Kerio防火墙假装的那样假装自己受保护的时候,再去嗅探器下看数据包。从另一个方面来说,Outpost防火墙,喜欢在 NDIS_PROTOCOL_BLOCK中hook更多的句柄:
OpenAdapterCompleteHandlerSendCompleteHandlerTransferDataCompleteHandlerRequestCompleteHandlerReceiveHandlerStatusHandlerReceivePacketHandlerBindAdapterHandlerUnbindAdapterHandler
在 NDIS_OPEN_BLOCK中:Outpost 4.0:SendCompleteHandlerTransferDataCompleteHandlerReceiveHandlerReceivePacketHandlerStatusHandler
Outpost 3.x:SendHandlerTransferDataHandlerSendCompleteHandlerTransferDataCompleteHandlerReceiveHandlerRequestCompleteHandlerReceivePacketHandlerSendPacketsHandlerStatusHandler
他的句柄调用和防火墙之间的代码是非常有趣的:call ImC E8 XX XX XX XX&some specific data&
For Outpost 3.x:
58push [eax] ; FF 30 Pushing the real handler 60push [eax+4] ; FF 70 04push [esp+28h] ; FF 74 24 28 Pushing return addressjmp [eax+8] ; FF 60 08
For Outpost 4.0:
58add eax, 3 ; 83 C0 03 Missing three zero bytes after callpush [eax] ; FF 30 Pushing the real handler 60push [eax+4] ; FF 70 04push [esp+28h] ; FF 74 24 28 Pushing return addressjmp [eax+8] ; FF 60 08像我们看到的那样,那不是一个问题对于卸载所有的HOOK并立即获取系统控制权。如果你厌烦了这中间的汇编代码,他们通常是能够转换成普通C代码的,我能向你展示一些来自Tiny防火墙团队有趣的东西,他假装是真正的安全,并且向我们展示了很多的hook:
NdisOpenAdapterNdisCloseAdapterNdisInitializeWrapperNdisTerminateWrapperNdisMRegisterMiniportNdisIMRegisterLayeredMiniportNdisRegisterProtocolNdisMSetAttributesExNdisRegisterMacNdisIMAssociateMiniportNdisClOpenAddressFamilyNdisCmRegisterAddressFamilyNdisMCmRegisterAddressFamilyNdisMCoSendComplete
哦,看起来很优秀,也真是很优秀的样子,他们试图对这些函数做一个结合HOOK通过设置跳转到他们的句柄。我不喜欢“结合”,知道为什么吗?那不是因为他 难以实现或是有些指令很难“结合”(理论上可行,实践上未必,我不认为在真正函数的开端那样做可行)。主要的原因是那样不安全。Rootkit开发者使用 他是因为那是一种获取控制权的简单的方式,但不要试图把他用作安全软件中,就像用恐怖份子的方法对付恐怖分子一样。还有要说的是,我没有发现任何线程安全 和多处理器安全的代码。再一次失败。当你在“结合”某些代码的时候,你需要确信没有一个线程、没有一个CPU在运行这些代码。Tiny防火墙为每个HOOK句柄申请内存,并拷贝这些C函数在开端和结尾: 55mov ebp, 8B ECsub esp, XX 83 EC XXmov byte ptr [ebp-1], XX C6 45 FF XXmov dword ptr [ebp-8], HookedH C7 45 F8 XX XX XX XX&...&push RealHandlercall [ebp-8]mov esp, ebppop ebpret XXh
于是这就变的相当简单,对于从新句柄偏移0xD去获得真的句柄。对所有的句柄,Tiny都是拷贝上面的代码。hook在NDIS_PROTOCOL_BLOCK中:
SendCompleteHandlerStatusHandler
Hooked 在 NDIS_OPEN_BLOCK中:
TransferDataHandlerSendCompleteHandlerTransferDataCompleteHandlerReceiveHandlerReceivePacketHandlerStatusHandler
需要说的是,有些防火墙变聪明了,如果他们被别人hook的时候,他们会试图恢复他们的hook。例如,Outpost防火墙就检测这个并监视他们的 hook,但仅仅像指针的安全那样。也许他们不认为会有剪接戏法?Outpost小组不知道,白帽子Sygate防火墙也能恢复他们的hook,但他恢复 的仅仅是NDIS_OPEN_BLOCK.SendHandler和 NDIS_OPEN_BLOCK.SendPacketsHandler。那是奇怪的,因为因为他们hook了很多 NDIS_PROTOCOL_BLOCK中的句柄:
OpenAdapterCompleteHandlerCloseAdapterCompleteHandlerTransferDataCompleteHandlerReceiveHandlerStatusHandler
和 NDIS_OPEN_BLOCK 的hook:
SendHandlerTransferDataHandlerTransferDataCompleteHandlerReceiveHandlerReceivePacketHandlerSendPacketsHandlerStatusHandler只有几种防火墙用中间层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设备,它能在协议栈的最上层解释执行:DeviceIpDeviceTcpDeviceUdpDeviceIPMULTICASTDeviceRawIp
好的,你甚至能通过\Device\RawIp来戏弄一些人。对于阻止程序的一个访问网络的请求最好的方式(公开的方式,也是重要的),是附加到这些设备上并监视他们。几乎所有的防火墙都这样做了,因为这是通知用户陌生程序要访问网络的好方法。例如,Look’n’Stop附加他的设备到tcpip.sys设备:DevicePcaTcpFilter -& DeviceTcpDevicePcaUdpFilter -& DeviceUdpDevicePcaRawIpFilter -& DeviceRawIp
\Device\Ip在那里?不是足够的,我们需要确信,所有种类的连接需要被监视,或是他们恰恰通过了这个假冒的保护。你的看见这些设备在你的WinObj工具里:DeviceComodoRawIpFilterDeviceComodoUdpFilterDeviceComodoTcpFilterDeviceComodoIpFilter我希望你能猜到,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_CREATEIRP_MJ_CLOSEIRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROLIRP_MJ_CLEANUP
另一个局部hook的失败是,tcpip.sys仅有TCPDispatch() 和TCPDispatchInternalDeviceControl()2个IRP句柄,第一个被所有 MajorTable填充,把它从另一个句柄上移出时容易的。TCPDispatchInternalDeviceControl()你能通过使用另一个 方法 (例如前面说的追踪方法和反汇编方法)来发现。Sygate防火墙喜欢HOOK这些句柄:IRP_MJ_CREATEIRP_MJ_CLOSEIRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROL
PortsLock防火墙,hook所有MajorTable句柄。好主要,既不将TCPDispatch()也不将TCPDispatchInternalDeviceControl() 给敌人。Tiny防火墙是hook下面的句柄。IRP_MJ_CREATEIRP_MJ_CLOSEIRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROLIRP_MJ_CLEANUP
对于在一个防火墙中仅有这种类型的保护是不严重的,你不这样认为吗?我认为像PortsLock防火墙,Norton Internet Security,Comodo防火墙和其他有“防火墙”这个错误称号的,就像一些有着很漂亮界面的保护系统。恶意软件正在变的越来越猖獗,每天都有大量 的ROOTKIT杯注册,更多老练的,先进的,比防火墙更底层的正在不断涌现。他们试图影响其他进程并隐匿其中。就像一个披着羊皮的狼。我谈到, injection, OpenProcess()/WriteProcessMemory()/CreateRemoteThread()和一个好的shellcode或一个 self-mapped模块等都能透过防护与外部通信,而且工作的很好,也很容易编写,所有需要好的保护而不受其侵害。系统服务标提供内核函数的访问通 道,他是通过调_KiSystemService,那是用用户模式和驱动来实现的。防火墙为了阻止这些动作使系统保持健壮,成功地hook了打开进程、写 进程内存、创建远线程、进程、文件、文件编辑等函数。防火墙喜欢做这些,例如,ZoneAlarm防火墙hook以下系统服务:ZwConnectPortZwCreateFileZwCreateKeyZwCreatePortZwCreateProcessZwCreateProcessExZwCreateSectionZwCreateWaitablePortZwDeleteFileZwDeleteKeyZwDeleteValueKeyZwDuplicateObjectZwLoadKeyZwMapViewOfSectionZwOpenFileZwOpenProcessZwOpenThreadZwReplaceKeyZwRequestWaitReplyPortZwRestoreKeyZwSecureConnectPortZwSetInformationFileZwSetSystemInformationZwSetValueKeyZwTerminateProcess
他监视对注册表,进程,驱动,文件的访问,并阻止自己被关闭。Outpost Firewall 4 hook更多的服务:ZwAssignProcessToJobObjectZwCloseZwCreateFileZwCreateKeyZwCreateProcessZwCreateProcessExZwCreateSymbolicLinkObjectZwCreateThreadZwDeleteFileZwDeleteKeyZwDeleteValueKeyZwLoadDriverZwMakeTemporaryObjectZwOpenFileZwOpenKeyZwOpenProcessZwProtectVirtualMemoryZwQueryDirectoryFileZwQueryKeyZwQueryValueKeyZwReplaceKeyZwRestoreKeyZwSaveKeyZwSaveKeyExZwSetInformationFileZwSetValueKeyZwTerminateProcessZwTerminateThreadZwUnloadDriverZwWriteVirtualMemory
但事实上他仅用了他们的一半。他不关心驱动,你能加载任何你想要的,但他hook了ZwLoadDriver。更多的hook就更好吗?啊哈,对漏洞挖掘 者来说更好。不是每个人都知道代码的质量怎样,它将要运行当我们调用ZwOpenKey时。我的系统将要蓝屏吗?另一个关于hook的例子是Kerio 防火墙:ZwCloseZwCreateFileZwCreateKeyZwCreateProcessZwCreateProcessExZwCreateThreadZwDeleteFileZwDeleteKeyZwDeleteValueKeyZwLoadDriverZwMapViewOfSectionZwOpenFileZwOpenKeyZwResumeThreadZwSetInformationFileZwSetValueKeyZwTerminateProcessZwWriteFile没看见ZwOpenProcess/ZwWriteVirtualMemory的hook。使用Kerio你能插入你想要的每个进程,包括允许的进程。Sygate所用的hook比其他的少:ZwTerminateProcessZwMapViewOfSectionZwAllocateVirtualMemoryZwCreateThreadZwProtectVirtualMemoryZwWriteVirtualMemory他们认为能通过hook ZwWriteVirtualMemory来保护系统。那是有BUG的:你能打开进程,并改变一些线程的context,几乎与 Jetico做的相同:ZwConnectPortZwCreatePortZwCreateThreadZwTerminateProcessZwWriteVirtualMemory不是很有趣。Tiny防火墙做的最有趣:ZwCreateKeyZwCreateSectionZwOpenKeyZwSetInformationProcessZwTerminateProcess你能这样说吗?:这是容易的对于通过ZwWriteVirtualMemory来插入一些东西。当然,但当此恶意行为发生时,用户将被通知。这是个愚蠢的 小玩笑,对于在用户模式下来保护,Tiny防火墙载入他的UmxSbxExw.dll 到每个进程并hook许多进程通过安装每个函数开始的跳转:kernel32.dll:CreateProcessACreateProcessWCreateRemoteThreadDebugActiveProcessFreeLibraryGetProcAddressLoadLibraryExWOpenThreadTerminateProcessTerminateThreadWriteProcessMemory
user32.dll:BroadcastSystemMessageBroadcastSystemMessageABroadcastSystemMessageExABroadcastSystemMessageExWBroadcastSystemMessageWEndTaskExitWindowsExOpenClipboardPostMessageAPostMessageWPostThreadMessageAPostThreadMessageWSendDlgItemMessageASendDlgItemMessageWSendMessageASendMessageCallbackASendMessageCallbackWSendMessageTimeoutASendMessageTimeoutWSendMessageWSendNotifyMessageASendNotifyMessageWSetUserObjectSecuritySetWindowsHookASetWindowsHookExASetWindowsHookExWSetWindowsHookW
advapi32.dll:AbortSystemShutdownWAdjustTokenPrivilegesChangeServiceConfig2AChangeServiceConfig2WChangeServiceConfigAChangeServiceConfigWControlServiceCreateProcessAsUserACreateProcessAsUserWCreateProcessWithLogonWCreateServiceACreateServiceWDeleteServiceEnumDependentServicesAEnumDependentServicesWEnumServicesStatusAEnumServicesStatusExAEnumServicesStatusExWEnumServicesStatusWInitiateSystemShutdownExWInitiateSystemShutdownWOpenSCManagerAOpenSCManagerWOpenServiceAOpenServiceWQueryServiceConfig2AQueryServiceConfig2WQueryServiceConfigAQueryServiceConfigWQueryServiceStatusQueryServiceStatusExSetFileSecurityWSetKernelObjectSecuritySetNamedSecurityInfoWSetSecurityInfoSetServiceObjectSecurityStartServiceAStartServiceW哦,Tiny是个hook怪物。你能看见在kernel32.dll上的hook!WriteProcessMemory在他们的保护之下以防止被插入。 Tiny防火墙团队认为那是一个很酷的保护方式,在一些不稳定的程序中他可能会挂掉。从那些进程中卸载掉他的Dll也不是件难事,恢复所有的函数入口就可 以享受生活了。Outpost也喜欢这样做,他加载他的wl_hook.dll到应该被保护以防止恶意软件的每个进程。那是庞大的hook队列:
kernel32.dll:CreateProcessACreateProcessWCreateRemoteThreadDebugActiveProcessWinExec
ntdll.dll:LdrLoadDllLdrUnloadDllNtCreateThreadNtResumeProcessNtResumeThreadNtSetContextThreadNtSetValueKeyNtSuspendProcessNtSuspendThreadNtTerminateProcessNtWriteVirtualMemoryZwCreateThreadZwResumeProcessZwResumeThreadZwSetContextThreadZwSetValueKeyZwSuspendProcessZwSuspendThreadZwTerminateProcessZwWriteVirtualMemory
user32.dll:CallNextHookExChangeDisplaySettingsExAChangeDisplaySettingsExWDdeConnectDdeConnectListDdeInitializeADdeInitializeWEndTaskExitWindowsExFindWindowExAFindWindowExWPostMessageAPostMessageWSendInputSendMessageASendMessageCallbackASendMessageCallbackWSendMessageTimeoutASendMessageTimeoutWSendMessageWSendNotifyMessageASendNotifyMessageWSetForegroundWindowSetWindowPosSetWindowsHookExASetWindowsHookExW那不是一个保护,是没有必要的代码。是的,他能抵制一些稀有恶意代码,但没有更多。一些防火墙不仅想被作为一个防火墙来使用,他们包含了一些有趣的特性像 间谍软件或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: aNbh0x08xMac0x0 db 9,'nbh:0x%08X mac:0x%08X mah:0x%08X pbc:0x%08X',0Dh,0Ah.text: ; DATA XREF: HookedNdisOpenAdapter+273 o.text: db 9,'med:"%s"',0Dh,0Ah.text: db 9,'drv:"%s"',0Dh,0Ah.text: db 9,'dev:"%s"',0Dh,0Ah.text: db 9,'ada:"%s"',0.text: align 4
我认为没人想因为这些奇怪的记录而看见蓝屏。ZoneAlarm也喜欢记录:.text: aUPacketSProtoS db '%u Packet %s: Prot %s Flags: 0x%08lx Src: %2u.%2u.%2u.%2u '.text: ; DATA XREF: sub_1A693+119 o.text: 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: aVsdatantVstdic db 'VSDATANT:vsTdiClientRequestReceivePreProc(): FO=%p SE=%p RE#'.text: ; DATA XREF: sub_502A6+D3 o.text: db '=%d IRP=%p : TIMEOUT(%u)',0Ah,0
Kerio防火墙团队不包含路径就不能生成他们的驱动:.rdata: aCProjectsNetsecuritytoolsFire db 'C:\Projects\netsecuritytools\Firewall SDK\Build.Release\4.3.'.rdata: db 'x\bin\Release\fwdrv.pdb',0
他们也这样记录:.data: aFwdrvApicopyas db 'FWDRV: ApiCopyAssociatedEndpoint: Local: %u.%u.%u.%u:%u Remo'.data: ; DATA XREF: sub_B4 o.data: db 'te:%u.%u.%u.%u:%u, SpeedIn: %u, SpeedOut: %u, PID: 0x%04X, A'.data: db 'pp: [%s], Service: [%s]',0
并且真是有大量这样的记录:.data: 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::$::$::$::$A02EC6A2CEAC::_IO_STACK_LOCATION *S // eax@1unsigned int S // edi@1PIRP _I // esi@1void *InB // ecx@2int InBufferS // edi@2PVOID OutB // edx@2int OutBufferS // ebx@2int L // eax@3int ReturnL // [sp+8h] [bp-4h]@1
ReturnLength = 0;_Irp = IStack = Irp-&Tail.Overlay.CurrentStackLStatus = 0xC00000BBu;if ( *(_BYTE *)Stack == 14 ){InBuffer = (void *)*((_DWORD *)Stack + 4);InBufferSize = *((_DWORD *)Stack + 2);OutBuffer = Irp-&UserBOutBufferSize = *((_DWORD *)Stack + 1);Irp = (PIRP)*((_DWORD *)Stack + 3);Status = HandleRequest((int)Irp, InBuffer, InBufferSize, OutBuffer, OutBufferSize, &ReturnLength);}Length = ReturnL_Irp-&IoStatus.Status = S_Irp-&rmation = LIofCompleteRequest(_Irp, 0);return S}
int __stdcall HandleRequest(int Ioctl, void *InBuffer, int InBufferSize, void *OutBuffer, int OutBufferSize, int *ReturnLength){…if ( Ioctl == 0x830020EB ){sub_1484A((int)OutBuffer);*v6 = 28;return 0;}
在sub_1484A()里什么是如此的有趣?看看这里:int __stdcall sub_1484A(int a1){ // eax@3CPPEH_RECORD ms_ // [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);}}酷,在内核空间写些东西已经没有任何困难了,我们能制造一个DOS,甚至可以执行代码。我只是不想进一步发掘了,希望剩下的将被同道之一完成。如果我说的 是真的话,似乎每个防火墙都能被绕过,没有东西能做到100%的保护。Rootkit,木马,蠕虫和其他恶意软件变的更加隐蔽、复杂,而且很难被发现。我 不想给出任何关于选择哪款防火墙的建议,只是要确信,你用了一个功能强大的防火墙。
MaD,逆向工程师和研究者。
--------------------------------------------------------------------------------------------------------------------------------------
The truth about personal firewallsBy: MaD.
There are several ways to protect your computer against malicious software, such as software firewall protection, viruses and rootkits activity detection. All this protection software based on some well-known techniques, that are used almost without improvements and how you might already know, implementation of those security products is not perfect. It’s awful, usually. The companies that truly thinks that their products are the most advanced, they include newest features, that are “must have” for users, but if you take a look under the cover, look inside, you will see, that there are more bugs and failures than in your school project. The main idea is to make a product the first one – it’s a good strong advertisement. And yeah, heavy advertisement combined with faked tests that can demonstrate for a user the “power” of some product can result in a strong feeling like “Yeah, I really need it”. Bullshit.
It’s a good idea – protect your PC against attacks from outside of your machine, and from strangers inside. Some heuristic ways to protect your PC from trojans and spyware is good and they are really work. It’s pretty nice idea to pay 30-50$ per every-second-protection and updates, if it’s working. But actually, it doesn’t.
First of all, I wanted to apologize for my awful English. And our talking will be about such products:
ZoneAlarm Firewall 6.xOutpost Firewall 3.x and 4.xLook'n'Stop Firewall 2.0Kerio Firewall 4.3Sygate Firewall 5.6Jetico Firewall 1.0PortsLock Firewall 1.9Tiny Firewall 6.5Norton Internet Security 8.0Comodo Firewall 2.4OnlineArmor Firewall 2.1
Protection of personal software firewalls consist of two basic levels – NDIS (Network Driver Interface Specification) and TDI (Transport Data Interface). NDIS-level is standing over the TCP/IP stack and protection on that level can help to prevent attacks, based on bugs in TCP/IP stack, even if you didn’t update your stack, or it can prevent many spoofing, flood and
attacks. Firewalls, who don’t use NDIS automatically become an outsiders. The losers are PortsLock Firewall, Norton Internet Security, Comodo Firewall etc. Will you really pay 35 per single license of PortsLock, who even doesn’t protect you against low-level TCP/IP attacks? Or 79$ for Comodo? Sad for your system. The real firewalls are sitting on a NDIS level. And here can be two different protection methods based on NDIS. The first one is a NDIS-hooking protection. Main idea of this – the first firewall hooks NdisRegisterProtocol()/NdisOpenAdapter() (and it can be EAT patching or even splicing method as Tiny Firewall does). Then firewall being notified when a NDIS protocol is trying to be registered or when it’s binding to some adapter, and the key moment – firewall is hooking a handlers of NDIS_PROTOCOL_BLOCK and NDIS_OPEN_BLOCK and when the system wants to send a packet or receive it, firewall will be notified when it will happened. It’s interesting when firewalls is trying to set their hooks – almost everybody is hooking handlers right in the NDIS_PROTOCOL_BLOCK, but several firewalls, such as Sygate, Kerio and Jetico are hooking handlers right in the NDIS_PROTOCOL_CHARACTERISTICS, than they call the real NdisRegisterProtocol(), and after that they are moving back an old handlers. More safe, right? So, firewall should work independent from that how much protocols will be registered and how much bindings will be. And yeah, everybody supports that. For example, when ZoneAlarm is hooking a handler, it is allocating non-pageable memory and putting there several instructions:
58push HookD 68 XX XX XX XX 50jmp HookedH E9 XX XX XX XX
after that, it puts some valuable information in other piece of memory, called HookData, and all hooked handlers in NDIS_PROTOCOL_BLOCK:
OpenAdapterCompleteHandlerCloseAdapterCompleteHandlerBindAdapterHandlerUnbindAdapterHandler
And NDIS_OPEN_BLOCK:
SendHandlerReceiveHandlerReceivePacketHandlerSendPacketsHandler
Will be like that:For NDIS_PROTOCOL_BLOCK:
VOIDHookedOpenAdapterComplete(PVOID HookData,IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status,IN NDIS_STATUS OpenErrorStatus);
The real OpenAdapterComplete() handler is placing right here: [HookData + 0x770]
VOIDHookedCloseAdapterComplete(PVOID HookData,IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status);
The real CloseAdapterComplete() handler is placing right here: [HookData + 0x774]
VOIDHookedBindAdapter(PVOID HookData,OUT PNDIS_STATUS Status,IN NDIS_HANDLE BindContext,IN PNDIS_STRING DeviceName,IN PVOID SystemSpecific1,IN PVOID SystemSpecific2);
The real BindAdapter() handler is placing right here: [HookData + 0x764]
VOIDHookedUnbindAdapter(PVOID HookData,OUT PNDIS_STATUS Status,IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE UnbindContext);
The real UnbindAdapter() handler is placing right here: [HookData + 0x768]
For NDIS_OPEN_BLOCK:
VOIDHookedSend(PVOID HookData,IN NDIS_HANDLE NdisBindingHandle,IN PNDIS_PACKET Packet);
The real Send() handler is placing right here: [HookData + 0x1A4]
VOIDHookedReceive(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);
The real Receive() handler is placing right here: [HookData + 0x4D0]
VOIDHookedReceivePacket(PVOID HookData,IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET Packet);
The real ReceivePacket() handler is placing right here: [HookData + 0x570]
VOIDHookedSendPackets(PVOID HookData,IN NDIS_HANDLE MiniportAdapterContext,IN PPNDIS_PACKET PacketArray,IN UINT NumberOfPackets);
The real SendPackets() handler is placing right here: [HookData+2E4h]
Damn you ZoneAlarm, it’s so easy to get a pointer to the real handlers and restore it.
I said, that everybody supports numerous of registered protocols. Actually, not everybody. Sygate thinks that it will be enough to hold all information about protocols and open blocks right in his .data section. Nah, bad idea. His handlers hooking way is similar to ZoneAlarm, but that instructions, for which memory should be allocated, is placing right in the Sygate’s driver Teefer.sys:
58push HookD 68 XX XX XX XX 50jmp FakeH E9 XX XX XX XX
HookData is placing in .data too (btw, it’s 448 bytes long) and totally Sygate can hook 576 handlers (including protocol and open blocks handlers). So, it can be approximately 40-50 NDIS_PROTOCOL_BLOCK and NDIS_OPEN_BLOCK can be hooked (don’t forget that several open blocks can be attached to one protocol block). Maybe 40-50 blocks it’s enough, but it’s really bad practice to code that way, say hello to a buffer overflow.
I have another good example about how necessary to know `what’ and `how much’ to hook. Guys from Kerio Firewall team didn’t know that. Yep, as a nice firewall, it’s setting hooks on NdisRegisterProtocol(), NdisDeregisterProtocol(), NdisOpenAdapter(), NdisCloseAdapter() and hooking a handlers. As I said, Kerio is hooking handlers right in the NDIS_PROTOCOL_CHARACTERISTICS and just then call NdisRegisterProtocol(), but it doesn’t move handlers back to NDIS_PROTOCOL_CHARACTERISTICS. What’s this? Undocumented feature? Don’t think so, just careless coding and misunderstanding of standards and whole kernel. Another good example of that Kerio team don’t know anything about NDIS development, it’s that fact that they’re just don’t know what to hook. Kerio Firewall hooks in NDIS_PROTOCOL_CHARACTERISTICS:
OpenAdapterCompleteHandlerCloseAdapterCompleteHandler
And what does it hook in NDIS_OPEN_BLOCK:
SendHandlerSendPacketsHandler
Not too much? Right. It can be using for bypass his NDIS “protection” and deliver a packet to TCP/IP stack. You even can push “Block all” button and still watch in a local sniffer for incoming packets. Bah, I don’t like to see packets in a sniffer, when I’m pretending to be fully-protected as Kerio Firewall pretending to be.From the other side, Outpost Firewall, who likes to hook much more in NDIS_PROTOCOL_BLOCK:
OpenAdapterCompleteHandlerSendCompleteHandlerTransferDataCompleteHandlerRequestCompleteHandlerReceiveHandlerStatusHandlerReceivePacketHandlerBindAdapterHandlerUnbindAdapterHandler
And in NDIS_OPEN_BLOCK:Outpost 4.0:
SendCompleteHandlerTransferDataCompleteHandlerReceiveHandlerReceivePacketHandlerStatusHandler
Outpost 3.x:
SendHandlerTransferDataHandlerSendCompleteHandlerTransferDataCompleteHandlerReceiveHandlerRequestCompleteHandlerReceivePacketHandlerSendPacketsHandlerStatusHandler
It’s very interesting his intermediate code between handler caller and firewall:
call ImC E8 XX XX XX XX&some specific data&
For Outpost 3.x:
58push [eax] ; FF 30 Pushing the real handler 60push [eax+4] ; FF 70 04push [esp+28h] ; FF 74 24 28 Pushing return addressjmp [eax+8] ; FF 60 08
For Outpost 4.0:
58add eax, 3 ; 83 C0 03 Missing three zero bytes after callpush [eax] ; FF 30 Pushing the real handler 60push [eax+4] ; FF 70 04push [esp+28h] ; FF 74 24 28 Pushing return addressjmp [eax+8] ; FF 60 08
As can you see, it’s not a problem to unhook all this stuff and immediately own the system. If you get bored of this intermediate asm codes, which are using to get to normal C code, I can present you something interesting from Tiny Firewall team, it’s pretending to be really secure and showing us a lot of hooks:
NdisOpenAdapterNdisCloseAdapterNdisInitializeWrapperNdisTerminateWrapperNdisMRegisterMiniportNdisIMRegisterLayeredMiniportNdisRegisterProtocolNdisMSetAttributesExNdisRegisterMacNdisIMAssociateMiniportNdisClOpenAddressFamilyNdisCmRegisterAddressFamilyNdisMCmRegisterAddressFamilyNdisMCoSendComplete
Wow, looks great, and also great is that, that they’re trying to do a splicing-hooks over the functions by setting jmp to their handler. I don’t like splices, know why? It’s don’t because it’s hard to implement or you can find some instruction, which can’t be spliced (theoretically it can be, but in the real life, in the real functions’ prologues, I don’t think so) – the main reason it’s unsafe. Rootkit developers are using that because it’s the simplest way to get control over something, but don’t try to use it in security applications, it’s like using terrorist methods against terrorists. Also, need to say that I didn’t find any thread-safe or multiprocessor-safe code. Failure again. When your’re splice something, you need to be sure that no one thread and no one CPU run this code.Tiny Firewall allocates memory for each hooking handler and copying this C-function with prologue and epilogue:
55mov ebp, 8B ECsub esp, XX 83 EC XXmov byte ptr [ebp-1], XX C6 45 FF XXmov dword ptr [ebp-8], HookedH C7 45 F8 XX XX XX XX&...&push RealHandlercall [ebp-8]mov esp, ebppop ebpret XXh
so it’s pretty easy to get the real handler by offset 0xD from the start of new handler. For all this handlers, Tiny is copying the same previous code.Hooked in NDIS_PROTOCOL_BLOCK:
SendCompleteHandlerStatusHandler
Hooked in NDIS_OPEN_BLOCK:
TransferDataHandlerSendCompleteHandlerTransferDataCompleteHandlerReceiveHandlerReceivePacketHandlerStatusHandler
Need to say, that firewalls become clever and they’re trying to restore their hook, if they will be hooked by someone else. For example, Outpost firewall is detecting this and monitoring his hooks, but just safety of pointers. Probably they didn’t think that there could be splicing tricks? Outpost team don’t know it, white hats Sygate Firewall can restore his hooks too, but it’s restoring just NDIS_OPEN_BLOCK.SendHandler and NDIS_OPEN_BLOCK.SendPacketsHandler. It’s strange, because they’re hooking a lot of handlers in NDIS_PROTOCOL_BLOCK:
OpenAdapterCompleteHandlerCloseAdapterCompleteHandlerTransferDataCompleteHandlerReceiveHandlerStatusHandler
and NDIS_OPEN_BLOCK hooks:
SendHandlerTransferDataHandlerTransferDataCompleteHandlerReceiveHandlerReceivePacketHandlerSendPacketsHandlerStatusHandler
Just several firewalls are using Intermediate NDIS driver for protection on a NDIS level. It’s a clever solution. For example, Look’n’Stop and Outpost 2008 firewalls use IM NDIS drivers. Good improvement since last year, Outpost. But now it’s easier to bypass firewall just because now there is no hooks, no tricks and no any undocumented features used. Now you can smash down all IM NDIS firewalls just bypassing them. Don’t need to disturb firewall handlers by incoming or outgoing packets, you just don’t send packets to them. Anyway, using IM NDIS driver it’s a good, well-known, documented (not so much, but still…) and the one right way to protect the system against outside attacks.
As you might see, techniques are similar from one firewall to other, and ideas even can be stolen and nobody will say that you have stolen an idea. Good way to look under the cover and take something new in your product. Don’t need to think, don’t need to generate ideas, just reversing, debugging and being interested in it. The second main level in firewall building – it’s TDI, Transport Data Interface which can provide more high-level access to a transport protocol stacks in the kernel. Afd.sys, which can be interpreted as winsock, communicating with Windows TCP/IP stack (tcpip.sys) via tdi.sys (TDI layer, which I was talking about). So, there are several ways and places where to set hook and monitor your applications, communicating with network, and the best place where to set your protection – is right on tcpip.sys devices, which are interpreting as an upper-level protocols in stack:
DeviceIpDeviceTcpDeviceUdpDeviceIPMULTICASTDeviceRawIp
Yep, you even can spoof somebody via \Device\RawIp. The best way (and documented way, it’s important) to prevent applications an access to the network, it’s attach to those devices and monitor them. Almost all firewalls do this, because it’s a great way to notify user about strange application, which is going to communicate with network.
For example, Look’n’Stop attaches his devices to tcpip.sys devices:
DevicePcaTcpFilter -& DeviceTcpDevicePcaUdpFilter -& DeviceUdpDevicePcaRawIpFilter -& DeviceRawIp
Where is \Device\Ip? Not enough, we need to be sure, that all types of connections will be monitored, or they just pass through this pseudo-protection.You can see that devices in your WinObj tool:
DeviceComodoRawIpFilterDeviceComodoUdpFilterDeviceComodoTcpFilterDeviceComodoIpFilter
I hope you guessed, it’s Comodo Firewall is attaching devices to the same-named tcpip.sys devices.
Outpost Firewall, Kerio Firewall, Jetico Firewall, Norton Internet Security is just attaching noname devices to Tcp, Udp, Ip, RawIp, nothing interesting. People, who know main ideas of device-stacks organizing should know that it’s pretty easy to throw away this attaches and a firewall won’t get any notifies ever. You just need to find a pointer of tcpip.sys’s DRIVER_OBJECT, walk through the DeviceObject list and make null all DEVICE_OBJECT.AttachedDevice fields. Pretty easy? Sure, but very effective against firewalls, protection of which is placing just near here. Another failure of lame firewalls and big advertisement.Besides of attaching technique, there is another one interesting technique, which is more complicated, but more effective against malware – it’s a MajorTable hooking. Everybody knows, when usermode (or driver, whatever) wants to communicate with a driver, it’s notifying to I/O manager that it wants to communicate with a driver. I/O manager makes an IRP, and (key moment) calls one of the handlers DRIVER_OBJECT.MajorTable[IRP_MJ_XXX]. The same here, in tcpip.sys, some firewalls just hooks an IRP_MJ_XXX handlers and monitoring all calls, passing through allowed requests and denying forbidden. Not so easy to find a real handler, huh? I think almost everybody thinks that it’s impossible. The main idea of finding some hooked handler in that it must be called and then it will be found. By hooking Int 0x01, setting TF and tracing the call of firewall’s handler, we can find a real handler when firewall will call it. Easy. MajorTable-hooking techniques loved by such firewalls as ZoneAlarm Firewall, it is hooking:
IRP_MJ_CREATEIRP_MJ_CLOSEIRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROLIRP_MJ_CLEANUP
another failure of partial-hooking in that tcpip.sys has just two IRP-handlers – TCPDispatch() and TCPDispatchInternalDeviceControl(), the first one is filling all MajorTable and it’s easy to take him from another handler. TCPDispatchInternalDeviceControl() you can find by using another method (such as previous said tracing method or by using disassembler). Sygate Firewall loves to hook that handlers:
IRP_MJ_CREATEIRP_MJ_CLOSEIRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROL
PortsLock Firewall, hooks all of MajorTable handlers. Great idea, don’t give neither TCPDispatch(), nor TCPDispatchInternalDeviceControl() to enemies Tiny Firewall is hooking next handlers:
IRP_MJ_CREATEIRP_MJ_CLOSEIRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROLIRP_MJ_CLEANUP
It’s not serious to have just this type of protection in a firewall, don’t you think so? I think products like PortsLock Firewall, Norton Internet Security (wtf, really Internet Security?), Comodo Firewall and others has a wrong name ‘firewall’. Just some nice-looking with a pretty GUI protection system.
Malware is becoming more aggressive, there are tons of rootkits registering every day, more sophisticated, more advanced, standing on lowest level than firewalls now and every time on a step forward. They’re trying to affect other processes and hide themselves in it. So, it’s a good idea, like a wolf in a sheep’s skin. I’m talking about injection, OpenProcess()/WriteProcessMemory()/CreateRemoteThread() and a good shellcode or a self-mapped module is a good perspective to communicate with outside world, it works good, it’s easy to write, so need to be protected against this. System Services Table is providing access to kernel functions, which is calling via _KiSystemService, which are using by usermode and drivers (Zw-functions). Firewalls successfully hooks functions, that providing access to opening processes, writing stuff into the process’s memory, creating threads, processes, files, editing files etc for preventing this actions and supporting the system in a good health. Firewalls love to do this, for example, ZoneAlarm Firewall is hooking this system services:
ZwConnectPortZwCreateFileZwCreateKeyZwCreatePortZwCreateProcessZwCreateProcessExZwCreateSectionZwCreateWaitablePortZwDeleteFileZwDeleteKeyZwDeleteValueKeyZwDuplicateObjectZwLoadKeyZwMapViewOfSectionZwOpenFileZwOpenProcessZwOpenThreadZwReplaceKeyZwRequestWaitReplyPortZwRestoreKeyZwSecureConnectPortZwSetInformationFileZwSetSystemInformationZwSetValueKeyZwTerminateProcess
It’s watching for accessing to registry, processes, drivers, files, it’s preventing himself from shut downing. Outpost Firewall 4 is hooking much more services:
ZwAssignProcessToJobObjectZwCloseZwCreateFileZwCreateKeyZwCreateProcessZwCreateProcessExZwCreateSymbolicLinkObjectZwCreateThreadZwDeleteFileZwDeleteKeyZwDeleteValueKeyZwLoadDriverZwMakeTemporaryObjectZwOpenFileZwOpenKeyZwOpenProcessZwProtectVirtualMemoryZwQueryDirectoryFileZwQueryKeyZwQueryValueKeyZwReplaceKeyZwRestoreKeyZwSaveKeyZwSaveKeyExZwSetInformationFileZwSetValueKeyZwTerminateProcessZwTerminateThreadZwUnloadDriverZwWriteVirtualMemory
But actually it just uses half of them. It doesn’t care about drivers – you can load any if you want, but it hooks ZwLoadDriver. More hooks – the better? Aha, the better for vulnerability seekers. Not everybody knows what quality of that code, which will run when I call ZwOpenKey. Will my system fall to BSoD? Another example of hooking, Kerio Firewall:
ZwCloseZwCreateFileZwCreateKeyZwCreateProcessZwCreateProcessExZwCreateThreadZwDeleteFileZwDeleteKeyZwDeleteValueKeyZwLoadDriverZwMapViewOfSectionZwOpenFileZwOpenKeyZwResumeThreadZwSetInformationFileZwSetValueKeyZwTerminateProcessZwWriteFile
Can’t see hooks of ZwOpenProcess/ZwWriteVirtualMemory. With Kerio you can inject whatever you want in every process, including allowed processes. Going down, and Sygate shows us, that it is hooking less than others:
ZwTerminateProcessZwMapViewOfSectionZwAllocateVirtualMemoryZwCreateThreadZwProtectVirtualMemoryZwWriteVirtualMemory
They think they protect the system by hooking ZwWriteVirtualMemory, nice try. That is a bug: you could open process, and change some thread’s context. Almostthe same do Jetic
ZwConnectPortZwCreatePortZwCreateThreadZwTerminateProcessZwWriteVirtualMemory
Not so interesting.The most interesting do Tiny Firewall, all his hooks:
ZwCreateKeyZwCreateSectionZwOpenKeyZwSetInformationProcessZwTerminateProcess
You can say that it’s simple to inject something by ZwWriteVirtualMemory? Right, but user will be noticed on this malicious action. It’s a little stupid trick – to have a protection in user mode, Tiny Firewall is loading to each process his DLL UmxSbxExw.dll and hooks many functions by setting jmp in the start of functions:
kernel32.dll:CreateProcessACreateProcessWCreateRemoteThreadDebugActiveProcessFreeLibraryGetProcAddressLoadLibraryExWOpenThreadTerminateProcessTerminateThreadWriteProcessMemory
user32.dll:BroadcastSystemMessageBroadcastSystemMessageABroadcastSystemMessageExABroadcastSystemMessageExWBroadcastSystemMessageWEndTaskExitWindowsExOpenClipboardPostMessageAPostMessageWPostThreadMessageAPostThreadMessageWSendDlgItemMessageASendDlgItemMessageWSendMessageASendMessageCallbackASendMessageCallbackWSendMessageTimeoutASendMessageTimeoutWSendMessageWSendNotifyMessageASendNotifyMessageWSetUserObjectSecuritySetWindowsHookASetWindowsHookExASetWindowsHookExWSetWindowsHookW
advapi32.dll:AbortSystemShutdownWAdjustTokenPrivilegesChangeServiceConfig2AChangeServiceConfig2WChangeServiceConfigAChangeServiceConfigWControlServiceCreateProcessAsUserACreateProcessAsUserWCreateProcessWithLogonWCreateServiceACreateServiceWDeleteServiceEnumDependentServicesAEnumDependentServicesWEnumServicesStatusAEnumServicesStatusExAEnumServicesStatusExWEnumServicesStatusWInitiateSystemShutdownExWInitiateSystemShutdownWOpenSCManagerAOpenSCManagerWOpenServiceAOpenServiceWQueryServiceConfig2AQueryServiceConfig2WQueryServiceConfigAQueryServiceConfigWQueryServiceStatusQueryServiceStatusExSetFileSecurityWSetKernelObjectSecuritySetNamedSecurityInfoWSetSecurityInfoSetServiceObjectSecurityStartServiceAStartServiceW
Wow, Tiny is a hooking monster. You can see hook on kernel32.dll! WriteProcessMemory which is all their protection against inject. Tiny Firewall team thinks that it’s a cool protection, which can be dropped down even by some non-stable application. It’s not hard to unload that DLL from the process, restore all function entries and enjoy life. Btw, Outpost likes this too – it is loading his wl_hook.dll to every process which should protect user against malicious software. That’s a huge list of hooks:
kernel32.dll:CreateProcessACreateProcessWCreateRemoteThreadDebugActiveProcessWinExec
ntdll.dll:LdrLoadDllLdrUnloadDllNtCreateThreadNtResumeProcessNtResumeThreadNtSetContextThreadNtSetValueKeyNtSuspendProcessNtSuspendThreadNtTerminateProcessNtWriteVirtualMemoryZwCreateThreadZwResumeProcessZwResumeThreadZwSetContextThreadZwSetValueKeyZwSuspendProcessZwSuspendThreadZwTerminateProcessZwWriteVirtualMemory
user32.dll:CallNextHookExChangeDisplaySettingsExAChangeDisplaySettingsExWDdeConnectDdeConnectListDdeInitializeADdeInitializeWEndTaskExitWindowsExFindWindowExAFindWindowExWPostMessageAPostMessageWSendInputSendMessageASendMessageCallbackASendMessageCallbackWSendMessageTimeoutASendMessageTimeoutWSendMessageWSendNotifyMessageASendNotifyMessageWSetForegroundWindowSetWindowPosSetWindowsHookExASetWindowsHookExW
It’s not a protection, it’s some unnecessary code. Yes, it can protect against some rare malware, but nothing more.
Some firewalls is pretending to be something more than just firewalls, they include some interesting features like spyware or rootkit detection. And, yeah, it works, and it makes an impression. For the first several minutes before meeting with debug. Some firewalls are trying to monitor loading modules by setting routine via PsSetLoadImageNotiryRoutine() – Jetico Firewall, Look’n’Stop Firewall, Tiny Firewall, ZoneAlarm Firewall, Outpost Firewall do this. For example, Outpost is monitoring for dnsapi.dll load and when it’s loading, it’s notifying to user that some application is trying to use DNS services. It can happened, when you will call gethostbyname(), dnsapi.dll is loading automatically. Not cool. Rename dnsapi.dll to xxx.dll, load it, find a pointer of DnsQuery_A, and use it for resolving, Outpost will shut up. It’s a bad way to make protection here.
Almost in the each of firewall you can find a lot of unused, useless stuff. Sometimes it helps to understand some part of code or giving an example of function naming or you can find there even a debug information (oh lucky!). Look’n’Stop Firewall team don’t make the difference between release and debug, maybe that’s why this stuff left here:
push offset asc_187DC ; "f:\\dev\\lns\\2.05.cur\\tdisys\\w32api.c"push offset aKegetcurren_23 ; "KeGetCurrentIrql() == PASSIVE_LEVEL"call ds:RtlAssert
asserts are useful in debug builds, but not in the release version! Tiny Firewall has a lot of strange formatted-strings logs:
.text: aNbh0x08xMac0x0 db 9,'nbh:0x%08X mac:0x%08X mah:0x%08X pbc:0x%08X',0Dh,0Ah.text: ; DATA XREF: HookedNdisOpenAdapter+273 o.text: db 9,'med:"%s"',0Dh,0Ah.text: db 9,'drv:"%s"',0Dh,0Ah.text: db 9,'dev:"%s"',0Dh,0Ah.text: db 9,'ada:"%s"',0.text: align 4
I think no one wants to see BSoDs because of this strange logging. ZoneAlarm likes logs to
.text: aUPacketSProtoS db '%u Packet %s: Prot %s Flags: 0x%08lx Src: %2u.%2u.%2u.%2u '.text: ; DATA XREF: sub_1A693+119 o.text: db 'Dest: %2u.%2u.%2u.%2u ',0
And especially it likes logs in release version, sure.
.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
I love ZoneAlarm, it gives me some function names:
.text: aVsdatantVstdic db 'VSDATANT:vsTdiClientRequestReceivePreProc(): FO=%p SE=%p RE#'.text: ; DATA XREF: sub_502A6+D3 o.text: db '=%d IRP=%p : TIMEOUT(%u)',0Ah,0
Kerio Firewall team can’t build his driver without paths inside:
.rdata: aCProjectsNetsecuritytoolsFire db 'C:\Projects\netsecuritytools\Firewall SDK\Build.Release\4.3.'.rdata: db 'x\bin\Release\fwdrv.pdb',0
And also they like logs:
.data: aFwdrvApicopyas db 'FWDRV: ApiCopyAssociatedEndpoint: Local: %u.%u.%u.%u:%u Remo'.data: ; DATA XREF: sub_B4 o.data: db 'te:%u.%u.%u.%u:%u, SpeedIn: %u, SpeedOut: %u, PID: 0x%04X, A'.data: db 'pp: [%s], Service: [%s]',0
And it’s really huge amount of logs like that:
.data: aSPagedCodeCa_7 db '%s(): Paged code called on IRQL %d',0
What I wanted to say: doesn’t matter, how much you love logging, you need to move away this trash-logs and trash-code in release version. Less code – less bugs. Probably the next your BSoD will be right in that bad-tested banding debug code.
The first opening of this year became an OnlineArmor Firewall. "Online Armor has a very good chance of waltzing in and stealing top honors as the Scot’s Newsletter Best Software Firewall of 2008" Yeah, right The first tests under DriverVerifier gave me a BSoD. Really interesting, it has fell down under the standard checking tool. So inside you can find IRP_MJ_DEVICE_CONTROL handler, which is handling IOCTLs all with METHOD_NEITHER. Guys, do you know about ProbeForRead()/ProbeForWrite()? They even don’t check pointers on NULL, it’s even fun, the best protection of all Windows users have a huge issues. Guess what it can be? Some portions of Hex-rayed code is following:
int __stdcall DispatchDeviceControl(int DeviceObject, PIRP Irp){struct _IRP::$::$::$::$A02EC6A2CEAC::_IO_STACK_LOCATION *S // eax@1unsigned int S // edi@1PIRP _I // esi@1void *InB // ecx@2int InBufferS // edi@2PVOID OutB // edx@2int OutBufferS // ebx@2int L // eax@3int ReturnL // [sp+8h] [bp-4h]@1
ReturnLength = 0;_Irp = IStack = Irp-&Tail.Overlay.CurrentStackLStatus = 0xC00000BBu;if ( *(_BYTE *)Stack == 14 ){InBuffer = (void *)*((_DWORD *)Stack + 4);InBufferSize = *((_DWORD *)Stack + 2);OutBuffer = Irp-&UserBOutBufferSize = *((_DWORD *)Stack + 1);Irp = (PIRP)*((_DWORD *)Stack + 3);Status = HandleRequest((int)Irp, InBuffer, InBufferSize, OutBuffer, OutBufferSize, &ReturnLength);}Length = ReturnL_Irp-&IoStatus.Status = S_Irp-&rmation = LIofCompleteRequest(_Irp, 0);return S}
int __stdcall HandleRequest(int Ioctl, void *InBuffer, int InBufferSize, void *OutBuffer, int OutBufferSize, int *ReturnLength){…if ( Ioctl == 0x830020EB ){sub_1484A((int)OutBuffer);*v6 = 28;return 0;}
What is so interesting inside sub_1484A()? Look here:
int __stdcall sub_1484A(int a1){ // eax@3CPPEH_RECORD ms_ // [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);}}
Cool, there is not any trouble to write some shit in the kernel space, we can make a DoS or even a code execution. I just don’t want to dig deeper, hope that will be done by o)
Seems like every firewall can be bypassed and I say it’s true, there is no total protection against something. Rootkits, trojans, worms and other malicious software become more stealthed and sophisticated and it’s harder to find them. I don’t want to give any advice on which firewall to use, just be sure, that you use a firewall that has more functionality.
MaD, reverse engineer and researcher
【声明】:黑吧安全网()登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱,我们会在最短的时间内进行处理。
上一篇:【】【】}

我要回帖

更多关于 黑手安全网 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信