那不是一个保护,是没有必要的代码。是的,他能抵制一些稀有恶意代码,但没有更多。一些防火墙不仅想被作为一个防火墙来使用,他们包含了一些有趣的特性像间谍软件或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 ’Crojects
etsecuritytoolsFirewall SDKBuild.Release4.3.’
.rdata:00433704 db ’xinReleasefwdrv.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)
{
…
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,逆向工程师和研究者。