이름변경을 위한 IRP_MJ_SET_INFORMATION IRP 생성
2011/06/21 09:58


기본적으로 ZwSetInformationFile 함수를 사용하나 rootkit등의 우회나 이름 변경시 추가 작업을 위한 hook등이 필요할때 드라이버에서 IRP_MJ_SET_INFORMATION IRP를 생성하여 파일의 이름을 변경한다.

파일명은 //device//harddiskvolume[n]//path를 포함한 file명 또는 //??//[drive]://path를 포함한 file명, //DosDevice//[drive]://path를 포함한 file명 와 같이 설정하는 점과 직접 생성한 IRP 이므로 완료루틴에서 pending 처리하지 않는다는 점을 고려한 대략의 코드는 아래와 같다.

IRP_MJ_SET_INFORMATION의 dispatch 루틴에서 특정 원본 파일의 이름을 강제로 a.ppt로 변경하는 코드이므로 원하는 파일명을 rename 하기 위해서는 추가적으로 FileObject를 구하여 한다.

XP에서 간단한 테스트는 문제없었으나 실제 사용을 위해서는 OSR의 Cracking Rename Operations 참고하여 수정하여 사용할것.(책임회피)
http://www.osronline.com/article.cfm?article=85
[code c++]
{
...

PIO_STACK_LOCATION pIrpSp;
KEVENT event;
NTSTATUS status;
PIRP pNewIrp = NULL;
PFILE_RENAME_INFORMATION pNewRename = NULL;
ULONG NewRenameLen =  wcslen(L"\\??\\c:\\a.ppt") * 2;
ULONG NewRenameSize = sizeof(FILE_RENAME_INFORMATION) + NewRenameLen;

KeInitializeEvent(&event, SynchronizationEvent, FALSE);

pNewRename = ExAllocatePoolWithTag(PagedPool, NewRenameSize, 'hong');
if(pNewRename == NULL)
  /// return 리소스부족;

memcpy(pNewRename, pRenameInfo, sizeof(FILE_RENAME_INFORMATION));
pNewRename->FileNameLength = NewRenameLen;
wcsncpy(pNewRename->FileName, L"\\??\\c:\\a.ppt", NewRenameLen/2);

pNewIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if(pNewIrp == NULL)
  /// return 리소스부족;

pNewIrp->Flags |= IRP_BUFFERED_IO;
pNewIrp->RequestorMode = KernelMode;
pNewIrp->UserIosb = &pIrp->IoStatus;
pNewIrp->UserEvent = &event;
pNewIrp->Tail.Overlay.OriginalFileObject = currentIrpStack->FileObject; // 원본 File Object
pNewIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pNewIrp->AssociatedIrp.SystemBuffer = (PVOID)&pNewRename;

pIrpSp = IoGetNextIrpStackLocation(pNewIrp);
pIrpSp->MajorFunction = IRP_MJ_SET_INFORMATION;
pIrpSp->FileObject = currentIrpStack->FileObject;
pIrpSp->DeviceObject = DeviceObject;
pIrpSp->Parameters.SetFile.Length = NewRenameSize;
pIrpSp->Parameters.SetFile.FileInformationClass = FileRenameInformation;
pIrpSp->Parameters.SetFile.FileObject = currentIrpStack->FileObject;
pIrpSp->Parameters.SetFile.ReplaceIfExists = pNewRename->ReplaceIfExists;

IoSetCompletionRoutine(pNewIrp, CompleteRoutine, 0, TRUE, TRUE, TRUE);
IoCallDriver( devExt->NLExtHeader.AttachedToDeviceObject, pNewIrp );
KeWaitForSingleObject( &event, Executive, KernelMode, TRUE, 0);
ExFreePoolWithTag(pNewRename, 'hong');

        ...
}
/// 직접만든 IRP는 pending을 하지 않음
NTSTATUS CompleteRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp,PVOID Context)
{
*Irp->UserIosb = Irp->IoStatus;
KeSetEvent(Irp->UserEvent, 0, FALSE);
IoFreeIrp(Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}
[/code]
2011/06/21 09:58 2011/06/21 09:58
Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다