|
Driver Verifier 와 STATUS_WAIT_n
작성중인 드라이버에 딱히 원인을 알수 없는 문제가 생겨 Driver Verifier 옵션을 모두 on 시키고 디버깅 작업시도. 드라이버를 UpperFilter 에 등록하고 IRP_MJ_PNP/IRP_MN_START_DEVICE 에서 STATUS_UNSUCCESSFUL를 return 하도록 하는 부분에서 Driver Verifier 가 아래와 같이 에러를 발생시켰다. *********************************************************************** * THIS VALIDATION BUG IS FATAL AND WILL CAUSE THE VERIFIER TO HALT * * WINDOWS (BUGCHECK) WHEN THE MACHINE IS NOT UNDER A KERNEL DEBUGGER! * ***********************************************************************
WDM DRIVER ERROR: [xxxxx.sys @ 0xF77F1FE0] An IRP dispatch handler ( F77F1FE0 ) has returned a status that is inconsistent with the Irp's IoStatus.Status field. ( Irp = 8746AE90 - Irp->IoStatus.Status = 00000003 - returned = 00000000 ) IRP_MJ_PNP.IRP_MN_REMOVE_DEVICE - [ DevObj=86C043B8, FileObject=00000000, Parameters=00000000 00000000 00000000 00000000 ] http://www.microsoft.com/hwdq/bc/default.asp?os=5.1.2600&major=0xc9&minor=0x224&lang=0x9
Break, Ignore, Zap, Remove, Disable all (bizrd)? IRP_MJ_PNP/IRP_MN_START_DEVICE 에서 STATUS_UNSUCCESSFUL 을 return 하는건 장치를 start 할수 없는경우 당연한 리턴값이므로 전혀 문제될것이 없다. !drvstack 을 통해 driver stack 을 살펴보니 작성중인 드라이버 아래위로 VERIFIER 드라이버 보이고 작성중인 드라이버 앞단에서 status 값이 STATUS_SUCCESS 값이 아닌 STATUS_WAIT_2 또는 STATUS_WAIT_3 이 넘어온다. 그 값을 작성중인 드라이버에서는 STATUS_UNSUCCESSFUL 로 변경시켜 다시 아래의 VERIFIER 드라이버로 넘긴다. (STATUS_WAIT_n 에 대한 정의는 아래와 같이 되어 있는데 전혀 도움이 안된다.) 0x00000001 STATUS_WAIT_1 The caller specified WaitAny for WaitType and one of the dispatcher objects in the Object array has been set to the signaled state. 이 과정에서 Driver Verifier 는 앞뒤의 status 값이 다르기 때문에 에러는 발생시킨다. (Driver Verifier 의 모든 옵션을 on 했지만 아마도 Enhanced I/O verification 으로 추정) 그러면 왜 STATUS_SUCCESS 를 return 하지 않고 STATUS_WAIT_n 와 같은 값을 return 하는걸까? 아래 코드를 보면 IoCallDriver() 호출이후 성공시 다음 처리를 하도록 되어 있다. status = IoCallDriver(...); if status == STATUS_SUCCESS 그러나 위와 같은 코드에서는 Driver Verifier 옵션을 on 시켰을 경우 원하는 대로 동작하지 않는 경우가 생긴다. 물론 Driver Verifier 를 on 하지 않는 경우에도 원하는 동작을 하지 않는 경우가 생긴다. (아래의 NT_SUCCESS macro 정의를 보면 성공값은 0으로 정의된 STATUS_SUCCESS 만 있는 것이 아니다.) 따라서 if 문 에서 성공값을 검사할때 STATUS_SUCCESS 값을 검사하지 않고 NT_SUCCESS(...)와 같은 macro 사용하여야 한다.NT_SUCCESS(status) status의 값이 성공 유형에 대한 값(0−0x3FFFFFFF) 또는 정보 유형에 대한 값(0x40000000-0x7FFFFFFF) 이면 TRUE.
NT_INFORMATION(status) status의 값이 정보 유형에 대한 값(0x40000000-0x7FFFFFFF) 이면 TRUE.
NT_WARNING(status) status의 값이 경고 유형에 대한 값(0x80000000−0xBFFFFFFF) 이면 TRUE.
NT_ERROR(status) status의 값이 오류 유형에 대한 값(0xC0000000 - 0xFFFFFFFF) 이면 TRUE. NTSTATUS 의 성공값 또는 기타 에러에 대한 검사는 NT_SUCCESS() 또는 NT_ERROR()를 사용해야 할듯.
hongyver
2012/11/07 08:55
2012/11/07 08:55
Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다
inf 파일로 드라이버 설치시 경고창 없이 설치하기
1. 64bit 에서 경고창 없이 설치
64bit OS에서 변경된 보안기능으로 서명되지 않은 장치 드라이버는 사용할수 없기 때문에 드라이버 파일에 모든 인증을 받아 사용해왔다. XP 64bit에서는 NDIS 5.x 를 지원하는 Passthru를 기반으로 작성했고 64bit Win7에서는 NDIS 6.x 이상을 지원하는 filter를 기반으로 작성하였기 때문에 각각 inf 파일을 이용하여 설치해야 한다. 따라서 bindview 예제를 가지고 설치 테스트를 했는데 이 설치 과정에서 문제가 발생했다.분명 singtool로 드라이버 인증을 하였음에도 불구하고 서명되지 않은 어쩌구 저쩌구 설치하겠느냐? 설치하지 않겠느냐? 라는 대화창이 뜬다. 사용자에게 선택권을 주면 사용자가 설치하지 않는 경우가 있기 때문에 보안 프로그램 특성상 경고창 없이 설치를 해야만 하기때문에 이 과정을 강제로 skip을 해야한다. 서명 어쩌구 저쩌구 애매한 문구 때문에 다소 삽질(?)을 했으나 결국 inf파일로 설치하는 드라이버는 Windows Logo 관련 WHQL 인증을 받지 않으면 위와 같은 경고창이 뜨는걸 확인. WHQL인증을 받아볼까 알아봤다가 .... 포기하고 ...결국 bindview 코드를 분석해서 수정하고 설치하는 몇차례 삽질을 거쳐 win7 64bit에서는 아래의 과정으로 경고창 없이 설치가 가능하다. 1. bindview 예제에 있는 SetupCopyOEMInf 를 생략하고 INetCfgClassSetup class의 Install 을 통해서 설치하도록 설치 프로그램 작성 2. SetupCopyOEMInf 를 삭제했기 때문에 수동으로 inf, sys 파일을 windows\inf 폴더에 복사2. 설치프로그램을 통해 inf 파일로 드라이버 설치 3. windows\system32\drivers 폴더에 드라이버가 복사가 되지 않으니 수동으로 sys 파일을 복사이렇게 하면 Win7에서 경고창없이 설치가 되고 동작도 문제가 없다.(vista에서는 테스트 해보지 않았지만 문제없이 될거라고 생각한다.)그런데 문제는 XP 64bit의 Passthru를 설치하려고 했더니 설치가 되지 않는다. 우선 inf 파일이 2개 인데다가 Win7에서 설치한 방법으로는 드라이버 파일을 찾는 대화창이 표시된다.또 삽집을 통해 방법이 다소 다르지만 XP 64bit에서도 경고창 없이 설치가 가능하다. 1. bindview 예제에 있는 SetupCopyOEMInf 를 생략하고 INetCfgClassSetup class의 Install 을 통해서 설치하도록 설치 프로그램 작성( 중요한건 2개의 inf 파일을 모두 같이 install 해야한다. 테스트해보니 미니포트용 inf (netsf_m.inf)를 설치하지 않아도 됨) 2. SetupCopyOEMInf 를 삭제했기 때문에 역시 마찬가지로 수동으로 2개의 inf, sys 파일을 windows\inf 폴더에 복사 3. inf 파일의 SourceDisksNames 섹션과 SourceDisksFiles 섹션의 항목을 주석처리하고 C:\WINDOWS\ServicePackFiles 에 sys 파일을 복사(sys 파일을 찾는 경로명을 생략하면 ServicePackFiles에서 드라이버를 찾기때문에)4. 설치프로그램을 통해 inf 파일로 드라이버 설치5. windows\system32\drivers 폴더에 드라이버가 복사가 되지 않으니 수동으로 sys 파일을 복사 Unintalll은 설치과정의 반대로만 하면된다. 2. 32bit에서 경고창없이 설치 win7에서는 64bit와 같은 과정을 통하면 경고창 없이 설치가능하였음.혹시 그래도 경고창이 뜬다면 아래 링크참고.테스트는 해보지 않았으니 참고할것.(disable하여 설치후 다시 enable하면 크게 문제 없을듯)http://www.killertechtips.com/2009/05/05/disable-driver-signing-windows-7/XP에서는 64bit에서 처럼 설치하였더니 실패. 레지스트리에 HKEY_LOCAL_MACHINE\Software\Microsoft\Driver Signing 를 0으로 설정하여야 함. 하지만 쉽게 변경이 되지 않으니 아래 링크를 참고 Osrloader.exe 로 서비스 생성(모든 옵션은 그냥 디폴트로 설정)후 테스트 해볼것.
gabriel 님 리플 정리(테스트 해보지 않았으니 실제 적용시 테스트 하셔야 합니다.) 1. xp 드라이버서명 무시는 아래의 코드를 참조하시고 예제 처럼 사용하시면 됩니다.예제)SetRegistyDriverInstall(0); //xp 드라이버설치 무시...드라이버설치코드...SetRegistyDriverInstall(1);//xp 드라이버설치 경고서명무시하는 코드void SetRegistyDriverInstall(BYTE ignoreOn){ HCRYPTPROV hCryptProv; HCRYPTHASH hHash; BYTE data[16]; DWORD len; DWORD seed; HKEY hkey; char input[4]; // HKLM\System\WPA\PnP\seed if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\WPA\\PnP", 0, KEY_READ, &hkey)!=ERROR_SUCCESS) { return ; } len=sizeof(seed); if(RegQueryValueEx(hkey, "seed", NULL, NULL, (BYTE*)&seed, &len)!=ERROR_SUCCESS) { } if(hkey) { RegCloseKey(hkey); } if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) // flag values { } else { if (GetLastError() == NTE_BAD_KEYSET) { if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { } } } // End of else. //-------------------------------------------------------------------- // Create a hash object. if(!CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)) { return ; } //-------------------------------------------------------------------- // Compute the cryptographic hash on the data. input[0]=0; input[1]=ignoreOn; // This is the Value! input[2]=0; input[3]=0; if(!CryptHashData(hHash, (BYTE*)input, sizeof(input), 0)) { return ; } //-------------------------------------------------------------------- if(!CryptHashData(hHash, (BYTE*)&seed, sizeof(seed), 0)) { return ; } //-------------------------------------------------------------------- len=sizeof(data); if(!CryptGetHashParam(hHash, HP_HASHVALUE, data, &len, 0)) { return ; } //-------------------------------------------------------------------- // Clean up. // Destroy the hash object. if(hHash) { if(!(CryptDestroyHash(hHash))) { return ; } } // Release the CSP. if(hCryptProv) { if(!(CryptReleaseContext(hCryptProv,0))) { return ; } } //-------------------------------------------------------------------- // HKLM\Software\Microsoft\Windows\CurrentVersion\Setup\PrivateHash if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Setup", 0, KEY_WRITE, &hkey)!=ERROR_SUCCESS) { len=sizeof(seed); if(RegSetValueEx(hkey, "PrivateHash", 0, REG_BINARY, data, sizeof(data))!=ERROR_SUCCESS) { } if(hkey) { RegCloseKey(hkey); } } //-------------------------------------------------------------------- // HKLM\Software\Microsoft\Driver Signing\Policy if(!RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Driver Signing", 0, KEY_WRITE, &hkey )!=ERROR_SUCCESS) { len=sizeof(seed); if(RegSetValueEx(hkey, "Policy", 0, REG_BINARY, &ignoreOn, 1)!=ERROR_SUCCESS) { } if(hkey) { RegCloseKey(hkey); } } //-------------------------------------------------------------------- // HKLM\Software\Microsoft\Driver Signing\Policy if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Driver Signing", 0, KEY_WRITE, &hkey )!=ERROR_SUCCESS) { len=sizeof(seed); if(RegSetValueEx(hkey, "Policy", 0, REG_BINARY, &ignoreOn, 1 )==ERROR_SUCCESS) { } if(hkey) { RegCloseKey(hkey); } }}2. 윈도우 7 에서의 방법저 같은 경우 display드라이버라서 INetCfgClassSetup 함수와는 매칭 이 되지 않았습니다.그래서 안되는가 하고 고민하다가 우연찬게 알수없는 드라이버 상태에서 다시시작을 누르게 됐는데 그 순간 바로 설치가 되더라구요.말이 길어 졌는데 짧게 말씀드리자면1.windows/inf로 드라이버을 복사한다2.UPDATEDRIVERFORPLUGANDPLAYDEVICES로 설치할때 실패하도록한다(성공하도록하면 경고창에 뜨기 때문에 실패할수 있는 옵션을 넣으면 됩니다)3.드라이버을 다시시작한다.이렇게 하면 경고창 없이 자동으로 설치가 됩니다.그리고 저같은 경우 디지탈인증을 서명한 상태였습니다 서명이 안되면 3번에서 경고창이 뜹니다.재생각에는 서명한 상태에서 저와 같은 방식을 사용하면 모든 드라이버가 자동으로 설치가 되지 않을까 생각합니다.
hongyver
2011/07/26 09:12
2011/07/26 09:12
Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다
이름변경을 위한 IRP_MJ_SET_INFORMATION IRP 생성
기본적으로 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]
hongyver
2011/06/21 09:58
2011/06/21 09:58
Trackback Address :: 이 글에는 트랙백을 보낼 수 없습니다
|
|
google.com
google.com