1   1  /  1  页   跳转

[原创] 加强自我保护的建议!

加强自我保护的建议!

1、建议多使用 inline hook 技术,少使用 ssdt hook  技术。虽然inline 技术使用多了,系统会不稳定,但比ssdt强,只要多测试并优化 使用inline也很稳定。江民 x 现在不是比以前稳定多了吗???

2、建议  使用inline技术挂钩以下函数,保护瑞星不被访问---这样做的话,就做到了应用层拒绝访问  :


      ObOpenObjectByPointer    句柄,防止程序获取瑞星句柄。



      ZwQueryVirtualMemory
枚举进程模块,阻止枚举瑞星的模块。




    PsLookupThreadByThreadId
枚举活动线程 ,瑞星的线程也要保护。



          RtlImageNtHeader
防止打开指定的PE模块,阻止打开瑞星模块。


3、线程的终止其实就是线程的“自杀”,系统通过KeInitializeApc/KeInsertQueueApc把一个APC插入核心态或者用户态中,使线程在运行中自己调用PspExitThread自行了断。建议挂接KeInitializeApc/KeInsertQueueApc,还是inline 技术吧!!!


4、请挂接ZwQuerySystemInformation函数。防止软件通过ZwQuerySystemInformation调用SystemHandleInformation得到系统中的所有句柄。




5、 挂接ZwQueryInformationProcess函数。阻止程序调用ZwQueryInformationProcess  获取 进程的id  。


6、给瑞星线程的ETHREAD.CrossThreadFlags设置PS_CROSS_THREAD_FLAGS_SYSTEM值,这样其它进程就无法结束它了。因为NtTerminateProcessPsTerminateProcessPspTerminateProcess最终都是调用PspTerminateThreadByPointer来将每个线程杀死。而在PspTerminateThreadByPointer里,如果线程是被其它进程强x结束的,就会有个这样的判断:


if (IS_SYSTEM_THREAD (Thread)) {
return STATUS_ACCESS_DENIED;
}


Thread类型是PETHREAD,IS_SYSTEM_THREAD是个宏,如下:
#define IS_SYSTEM_THREAD(Thread) (((Thread)->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_SYSTEM) != 0)


也就是说当线程的ETHREAD.CrossThreadFlags包含PS_CROSS_THREAD_FLAGS_SYSTEM位时,就直接返回拒绝访问,这样线程就不会被结束了。也 就是说当线程的ETHREAD.CrossThreadFlags包含PS_CROSS_THREAD_FLAGS_SYSTEM位时,就直接返回拒绝访 问,这样线程就不会被结束了。




现在只要给我们的进 程里的每个线程都设置PS_CROSS_THREAD_FLAGS_SYSTEM,进程就不会被结束掉了。但是ETHREAD的结构没有文档化,所以还得 自己找到CrossThreadFlags成员在ETHREAD结构里的偏移。可以通过在已导出的相关函数中找一些特征来定位 CrossThreadFlags,黑防中是在PsIsSystemThread里找,但是这个函数在Windows 2000里没有,所以我们换个,换成PsTerminateSystemThread,先看下PsTerminateSystemThread的源码:



NTSTATUS
PsTerminateSystemThread(
__in NTSTATUS ExitStatus
)
{
PETHREAD Thread = PsGetCurrentThread();

if (!IS_SYSTEM_THREAD (Thread)) {
return STATUS_INVALID_PARAMETER;
}

return PspTerminateThreadByPointer (Thread, ExitStatus, TRUE);
}


这里也用到了IS_SYSTEM_THREAD,那么也一定会有定位CrossThreadFlags的代码,如下:

kd> u PsTerminateSystemThread
nt!PsTerminateSystemThread:
805c89f8 8bff mov edi,edi
805c89fa 55 push ebp
805c89fb 8bec mov ebp,esp
805c89fd 64a124010000 mov eax,dword ptr fs:[00000124h]
805c8a03 f6804802000010 test byte ptr [eax+248h],10h
805c8a0a 7507 jne nt!PsTerminateSystemThread+0x1b (805c8a13)
805c8a0c b80d0000c0 mov eax,0C000000Dh
805c8a11 eb09 jmp nt!PsTerminateSystemThread+0x24 (805c8a1c)
805c8a13 ff7508 push dword ptr [ebp+8]
805c8a16 50 push eax
805c8a17 e828fcffff call nt!PspTerminateThreadByPointer (805c8644)
805c8a1c 5d pop ebp
805c8a1d c20400 ret 4



很 明显test    byte ptr [eax+248h],10h中的248h就是CrossThreadFlags在ETHREAD里的偏移了,test    byte ptr [eax+xxxxxxxx],10h的16进制是f680xxxxxxxx10,现在只要先获得PsTerminateSystemThread的地 址,然后向后搜索0x80f6,搜索到后再后面的4个字节就是CrossThreadFlags在ETHREAD里的偏移了。

得到了偏移,下面就是写代码了,驱动部分:

#include <ntifs.h>
#include <ntddk.h>

#define PS_CROSS_THREAD_FLAGS_SYSTEM 0x00000010UL //form wrk 1.2 base\ntos\inc\ps.h
#define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
UNICODE_STRING usSymLink;
RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
IoDeleteSymbolicLink(&usSymLink);
IoDeleteDevice(pDriverObject->DeviceObject);
}

NTSTATUS DispatchCreateClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

return STATUS_SUCCESS;
}

NTSTATUS DispatchControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
NTSTATUS nRet = STATUS_UNSUCCESSFUL;
ULONG_PTR uInf = 0;
PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp);
PVOID pSysBuff = pIrp->AssociatedIrp.SystemBuffer;

switch (pIoStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_THREAD_PROTECT:
PETHREAD pEThread;
PsLookupThreadByThreadId(HANDLE(*(PULONG)pSysBuff), &pEThread);
UNICODE_STRING usName;
RtlInitUnicodeString(&usName, L"PsTerminateSystemThread");
PUSHORT pOffset = (PUSHORT)MmGetSystemRoutineAddress(&usName);

//search "test byte ptr [eax+xxxxxxxx],10h",hex:f680xxxxxxxx10
while (*pOffset != 0x80f6)
pOffset = PUSHORT((PUCHAR)pOffset + 1);
PULONG pFlags = PULONG((PUCHAR)pEThread + *(PULONG)(pOffset + 1));
DbgPrint("pOffset:%08x, CrossFlagOffset:%08x\r\n", pOffset, *(PULONG)(pOffset + 1));
*pFlags |= PS_CROSS_THREAD_FLAGS_SYSTEM; //set PS_CROSS_THREAD_FLAGS_SYSTEM bit
nRet = STATUS_SUCCESS;
uInf = 0;
break;
}

pIrp->IoStatus.Status = nRet;
pIrp->IoStatus.Information = uInf;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return nRet;
}

extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
pDriverObject->DriverUnload = DriverUnload;
pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchControl;

UNICODE_STRING usDeviceName;
RtlInitUnicodeString(&usDeviceName, L"\\Device\\ThreadProtect");

NTSTATUS nRet;
PDEVICE_OBJECT pDeviceObject;
nRet = IoCreateDevice(pDriverObject, 0, &usDeviceName, FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject);
if (!NT_SUCCESS(nRet))
return nRet;

UNICODE_STRING usSymLink;
RtlInitUnicodeString(&usSymLink, L"\\??\\ThreadProtect");
nRet = IoCreateSymbolicLink(&usSymLink, &usDeviceName);
if (!NT_SUCCESS(nRet))
{
IoDeleteDevice(pDeviceObject);
return nRet;
}
return STATUS_SUCCESS;
}



这段代码要解释的都在上面了。EXE部分的代码就不用帖了,只要将每个线程的ID通过DeviceIoControl传入驱动即可:

#define IOCTL_THREAD_PROTECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

DeviceIoControl(hDevice, IOCTL_THREAD_PROTECT, &nThreadId, sizeof(nThreadId), 0, 0, &nByteRet, 0);



若运行不了自行想办法到注册表里删除先前的ThreadProtect键值。

如何结束用这种方法保护的进程?方法大大的有,插入APC,然后PspExitThread就不会经过PspTerminateThreadByPointer了。




请改进





用户系统信息:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.62 Safari/534.3 TheWorld Chrome
分享到:
gototop
 

回复:加强自我保护的建议!

您提的建议已收集,感谢您的支持。
gototop
 
1   1  /  1  页   跳转
页面顶部
Powered by Discuz!NT