现在的位置: 首页 > 综合 > 正文

The truth about personal firewalls

2013年02月04日 ⁄ 综合 ⁄ 共 27081字 ⁄ 字号 评论关闭
文章作者:MaD.
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

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.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

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 DDoS 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:

pop        eax        ; 58
push        HookData    ; 68 XX XX XX XX
push        eax        ; 50
jmp        HookedHandler    ; 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:

OpenAdapterCompleteHandler
CloseAdapterCompleteHandler
BindAdapterHandler
UnbindAdapterHandler

And NDIS_OPEN_BLOCK:

SendHandler
ReceiveHandler
ReceivePacketHandler
SendPacketsHandler

Will be like that:
For NDIS_PROTOCOL_BLOCK:

VOID
  HookedOpenAdapterComplete(
    PVOID HookData,
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status,
    IN NDIS_STATUS  OpenErrorStatus
    );

The real OpenAdapterComplete() handler is placing right here: [HookData + 0x770]

VOID
  HookedCloseAdapterComplete(
    PVOID HookData,
    IN NDIS_HANDLE  ProtocolBindingContext,
    IN NDIS_STATUS  Status
    );

The real CloseAdapterComplete() handler is placing right here: [HookData + 0x774]

VOID
  HookedBindAdapter(
    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]

VOID
  HookedUnbindAdapter(
    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:

VOID
  HookedSend(
    PVOID HookData,
    IN NDIS_HANDLE  NdisBindingHandle,
    IN  PNDIS_PACKET  Packet
);

The real Send() handler is placing right here: [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
);

The real Receive() handler is placing right here: [HookData + 0x4D0]

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

The real ReceivePacket() handler is placing right here: [HookData + 0x570]

VOID
  HookedSendPackets(
    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:

pop        eax        ; 58
push        HookData    ; 68 XX XX XX XX
push        eax        ; 50
jmp        FakeHandler    ; 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:

OpenAdapterCompleteHandler
CloseAdapterCompleteHandler

And what does it hook in NDIS_OPEN_BLOCK:

SendHandler
SendPacketsHandler

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:

OpenAdapterCompleteHandler
SendCompleteHandler
TransferDataCompleteHandler
RequestCompleteHandler
ReceiveHandler
StatusHandler
ReceivePacketHandler
BindAdapterHandler
UnbindAdapterHandler

And in NDIS_OPEN_BLOCK:
Outpost 4.0:

SendCompleteHandler
TransferDataCompleteHandler
ReceiveHandler
ReceivePacketHandler
StatusHandler

Outpost 3.x:

SendHandler
TransferDataHandler
SendCompleteHandler
TransferDataCompleteHandler
ReceiveHandler
RequestCompleteHandler
ReceivePacketHandler
SendPacketsHandler
StatusHandler

It’s very interesting his intermediate code between handler caller and firewall:

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

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:

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

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:

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

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:

SendCompleteHandler
StatusHandler

Hooked in NDIS_OPEN_BLOCK:

TransferDataHandler
SendCompleteHandler
TransferDataCompleteHandler
ReceiveHandler
ReceivePacketHandler
StatusHandler

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:

OpenAdapterCompleteHandler
CloseAdapterCompleteHandler
TransferDataCompleteHandler
ReceiveHandler
StatusHandler

and NDIS_OPEN_BLOCK hooks:

SendHandler
TransferDataHandler
TransferDataCompleteHandler
ReceiveHandler
ReceivePacketHandler
SendPacketsHandler
StatusHandler

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:

DeviceIp
DeviceTcp
DeviceUdp
DeviceIPMULTICAST
DeviceRawIp

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 -> DeviceTcp
DevicePcaUdpFilter -> DeviceUdp
DevicePcaRawIpFilter -> 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:

DeviceComodoRawIpFilter
DeviceComodoUdpFilter
DeviceComodoTcpFilter
DeviceComodoIpFilter

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_CREATE
IRP_MJ_CLOSE
IRP_MJ_DEVICE_CONTROL
IRP_MJ_INTERNAL_DEVICE_CONTROL
IRP_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_CREATE
IRP_MJ_CLOSE
IRP_MJ_DEVICE_CONTROL
IRP_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_CREATE
IRP_MJ_CLOSE
IRP_MJ_DEVICE_CONTROL
IRP_MJ_INTERNAL_DEVICE_CONTROL
IRP_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:

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

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:

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

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:

ZwClose
ZwCreateFile
ZwCreateKey
ZwCreateProcess
ZwCreateProcessEx
ZwCreateThread
ZwDeleteFile
ZwDeleteKey
ZwDeleteValueKey
ZwLoadDriver
ZwMapViewOfSection
ZwOpenFile
ZwOpenKey
ZwResumeThread
ZwSetInformationFile
ZwSetValueKey
ZwTerminateProcess
ZwWriteFile

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:

ZwTerminateProcess
ZwMapViewOfSection
ZwAllocateVirtualMemory
ZwCreateThread
ZwProtectVirtualMemory
ZwWriteVirtualMemory

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. Almost
the same do Jetico:

ZwConnectPort
ZwCreatePort
ZwCreateThread
ZwTerminateProcess
ZwWriteVirtualMemory

Not so interesting.The most interesting do Tiny Firewall, all his hooks:

ZwCreateKey
ZwCreateSection
ZwOpenKey
ZwSetInformationProcess
ZwTerminateProcess

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:
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

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:
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

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: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

I think no one wants to see BSoDs because of this strange logging. ZoneAlarm likes logs too:

.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

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: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 Firewall team can’t build his driver without paths inside:

.rdata:00433704 aCProjectsNetsecuritytoolsFire db 'C:/Projects/netsecuritytools/Firewall SDK/Build.Release/4.3.'
.rdata:00433704 db 'x/bin/Release/fwdrv.pdb',0

And also they like logs:

.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

And it’s really huge amount of logs like that:

.data:0043B1D4 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::$::$::$::$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)
{
  …
  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)
{
  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;
}

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 one of my colleagues ;)

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 

抱歉!评论已关闭.