애플리케이션 검증 도구 - 애플리케이션 검증 도구 내의 테스트

기본 사항

최소한 기본 설정이 선택된 애플리케이션 검증 도구를 실행해야 합니다. 이러한 각 항목은 고객 환경의 직접적이고 의미 있는 영향을 미치는 충돌 또는 기타 부정적인 시나리오를 발생시키는 영역을 테스트합니다.

  • 예외 - 애플리케이션이 구조적 예외 처리를 사용하여 액세스 위반을 숨기지 않도록 합니다.
  • 핸들 - 애플리케이션이 잘못된 핸들을 사용하려고 하지 않는지 확인하기 위한 테스트
  • 힙 - 힙의 메모리 손상 문제 확인
  • 누수 - dll이 언로드될 때까지 해제되지 않은 dll에서 만든 리소스를 추적하여 누수 감지
  • 잠금 - 중요한 섹션에 대한 올바른 사용량 확인
  • 메모리 - 가상 공간 조작을 위한 API가 올바르게 사용되는지 확인합니다(예: VirtualAlloc, MapViewOfFile).
  • SRWLock - SRW(슬림 판독기/기록기) 잠금에 대한 올바른 사용을 확인합니다.
  • Threadpool - 스레드 풀 API의 올바른 사용을 보장하고 더티 스레드 풀 스레드 및 기타 스레드 풀 관련 문제와 같은 콜백 후 작업자 스레드 상태에 일관성 검사 적용합니다.
  • TLS - 스레드 로컬 스토리지 API가 올바르게 사용되는지 확인합니다.

이러한 테스트에서 생성된 중지 코드 예외에 대한 자세한 내용은 애플리케이션 검증 도구 - 코드 및 정의 중지를 참조 하세요. 이러한 오류를 디버깅하는 방법에 대한 자세한 내용은 Application Verifier - 애플리케이션 검증 도구 중지 디버깅을 참조 하세요.

호환성

호환성 확인 계층 테스트는 Microsoft Windows 운영 체제에 문제가 있을 수 있는 애플리케이션을 식별하는 데 도움이 됩니다. 이러한 검사 대부분은 로고/인증 요구 사항을 테스트하는 데 사용할 수도 있습니다.

이러한 테스트에서 생성된 중지 코드 예외에 대한 자세한 내용은 애플리케이션 검증 도구 - 코드 및 정의 중지를 참조 하세요.

HighVersionLie - Windows에서 가장 일반적인 애플리케이션 호환성 문제 중 일부에 대한 문제를 식별합니다. 운영 체제 버전을 잘못 검색하거나 하드 코딩된 버전 정보를 사용하면 애플리케이션이 이후 운영 체제에서 실패할 수 있습니다.

커즈(Cuzz)

Cuzz(동시성 퍼지) 확인 계층은 동시성 버그 및 데이터 경합 상태를 검색합니다. Cuzz는 애플리케이션 코드의 주요 지점에 임의 지연을 주입하여 스레드 예약을 조정합니다. 다음 시나리오에서는 Cuzz 확인 계층에서 검색할 수 있는 동시성 버그의 유형을 보여 줍니다.

애플리케이션에는 부모 스레드와 자식 스레드가 있습니다. 부모 스레드는 자식 스레드를 시작한 다음 구조체에 대한 메모리를 할당합니다.

// Parent Thread
StartChildThread(...);
g_pointer = ... malloc(...);

자식 스레드는 포인터를 역참조합니다.

//Child Thread
LONG value = g_pointer->someMember;

앞의 코드에는 동시성 버그가 있습니다. 부모 스레드가 메모리를 할당하기 전에 자식 스레드가 포인터를 역참조하려고 하면 포인터가 유효하지 않습니다. 대부분의 경우 부모 스레드는 자식 스레드가 시작되기 전에 메모리를 할당하기 때문에 버그가 자체적으로 나타날 가능성은 매우 낮습니다. 그러나 드물게 자식 스레드가 시작되고 부모 스레드가 메모리를 할당하기 전에 포인터를 역참조하려고 시도할 수 있습니다.

Cuzz 확인 계층은 앞의 예제에 설명된 것과 같이 동시성 버그를 찾을 가능성을 높입니다. Cuzz는 지연을 삽입하는 것 외에는 추가 검사 수행하지 않습니다. 따라서 Cuzz와 직접 연결된 확인 중지는 없습니다. 그러나 Cuzz를 사용하도록 설정하면 동시성 버그가 나타나는 경우 다른 확인 계층이 도움이 됩니다. 예를 들어 경합 조건으로 인해 힙 오버플로가 발생하는 경우 런타임에 경합 조건이 나타나지 않는 한 힙 확인 계층에서 오류를 찾을 수 없습니다. Cuzz는 경합 상태가 발생할 확률을 높여 오류를 식별하는 힙 계층의 효율성을 향상시킵니다.

Cuzz의 최대 이점을 얻으려면 가능한 한 많은 테스트에서 Cuzz를 사용하도록 설정하고 동일한 테스트를 여러 번 반복합니다. Cuzz는 수동 테스트, 기능 테스트 및 스트레스 테스트를 비롯한 모든 테스트에서 사용할 수 있습니다. 또한 가능한 한 많은 애플리케이션 검증 도구 확인 계층을 사용하도록 설정합니다.

Cuzz에 동일한 임의 시드를 제공하여 버그를 재현할 확률을 높일 수 있습니다(속성 참조).

Cuzz는 Win32 동기화 API 호출에서만 지연을 삽입합니다.

Cuzz 속성

Cuzz 확인 계층에 사용할 수 있는 속성은 다음과 같습니다. 속성을 설정하려면 애플리케이션 검증 도구 사용자 인터페이스에서 Cuzz 계층을 선택하고 속성 창을 엽니다.

속성 설명
FuzzingLevel Cuzz에 대한 퍼지 수준을 제어합니다. 시간이 중요한 애플리케이션의 경우 1로 설정하고 일반 애플리케이션의 경우 4로 설정합니다.
RandomSeed 처음에 Cuzz에서 사용하는 임의 시드입니다. 이 값을 0으로 설정하면 Cuzz에서 시간 기반 임의 시드를 생성합니다.

낮은 리소스 시뮬레이션

낮은 리소스 시뮬레이션은 메모리 부족과 같은 낮은 리소스에서 환경을 시뮬레이션하려고 합니다. 이 시뮬레이션은 낮은 메모리 조건에서 발생하는 버그를 식별합니다. 이를 오류 주입이라고도 합니다. 낮은 리소스에서 환경을 시뮬레이션할 수 있습니다. 그러면 다음의 오류 확률 호출을 나타내는 숫자(0~100)를 정의할 수 있습니다.

  • 대기(예: WaitForXXXX API).
  • Heap_Alloc(힙 할당 API).
  • Virtual_Alloc(가상 메모리 할당 API).
  • 레지스트리(레지스트리 API).
  • 파일(CreateFile과 같은 파일 API).
  • 이벤트(CreateEvent와 같은 이벤트 API).
  • MapView(CreateMapView와 같은 MapView API).
  • Ole_Alloc(SysAllocString과 같은 Ole API).

낮은 리소스 시뮬레이션(오류 주입이라고도 함)은 낮은 리소스(예: 메모리 부족)에서 환경을 시뮬레이션하려고 합니다. 이렇게 하면 메모리 부족 조건 내의 버그가 식별됩니다.

낮은 리소스 시뮬레이션 속성

속성을 편집하려면 테스트 영역에서 낮은 리소스 시뮬레이션 검사 상자를 검사 마우스 오른쪽 단추를 클릭하고 속성을 선택합니다.

속성 설명
포함 제한 오류는 지정된 dll에서만 발생합니다. 행당 경로가 없는 하나의 dll 이름입니다. '*'를 지정하면 모든 모듈에 오류가 발생합니다.
제외 지정된 모듈에 대한 오류를 제외합니다. 행당 경로가 없는 하나의 dll 이름입니다.
시간 제한 프로세스 초기화 시 오류가 없는 경우 시간 슬롯(밀리초)을 제공합니다.
Wait WaitForXXXX API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
Heap_Alloc 힙 할당 API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
Virtual_Alloc 가상 메모리 할당 API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
등록 레지스트리 API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
파일 CreateFile과 같은 파일 API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
이벤트 CreateEvent와 같은 이벤트 API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
MapView CreateMapView와 같은 MapView API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
Ole_Alloc SysAllocString과 같은 Ole API의 오류 확률을 나타내는 숫자 [0 – 1000000]입니다.
스택 각 Windows 애플리케이션 스레드는 스택 예약 및 스택 커밋 크기로 시작합니다. 일반적인 사용에서는 스택에 더 많은 공간이 필요할 때마다 스택 커밋이 증가합니다. 자세한 내용은 스레드스레드 스택 크기 만들기를 참조하세요. 시스템에 메모리 부족 상태가 발생하는 경우 스택 커밋 증가가 실패할 수 있습니다. 스택 증가에 실패한 스레드와 전체 애플리케이션이 충돌할 가능성이 큽니다. 이러한 종류의 충돌은 중요한 시스템 프로세스(예: 서비스)에는 허용되지 않습니다. 스택 검사 확인 중인 애플리케이션에 대한 스택 증가를 사용하지 않도록 설정하므로 전체 시스템 메모리 부족 상태를 시뮬레이션할 필요 없이 스택 증가 실패를 시뮬레이션합니다. 애플리케이션이 스택을 확장하려고 하면 예외가 throw됩니다. 이에 의해 검증 도구 중지가 생성되지 않습니다.

LuaPriv

LuaPriv(제한된 사용자 계정 권한 예측자) 테스트는 예측 및 진단이며 관리 권한으로 애플리케이션 실행과 관련된 문제를 표시하는 작업이며, 더 적은 권한(일반적으로 일반 사용자)으로 실행되는 경우 해당 애플리케이션이 제대로 작동하는지 여부를 표시합니다.

UAC 검사이라고도 하는 제한된 사용자 계정 권한 예측 도구(LuaPriv)에는 다음 두 가지 기본 목표가 있습니다.

  • 예측: 관리 권한으로 애플리케이션을 실행하는 동안 더 적은 권한(일반적으로 일반 사용자)으로 실행하는 경우 해당 애플리케이션이 잘 작동하는지 여부를 예측합니다. 예를 들어 애플리케이션에서 관리 권한자 액세스만 허용하는 파일에 쓰는 경우 관리자가 아닌 사용자로 실행되는 경우 해당 애플리케이션은 동일한 파일에 쓸 수 없습니다.

  • 진단: 관리자가 아닌 권한으로 실행하는 동안 현재 실행과 함께 이미 존재할 수 있는 잠재적인 문제를 식별합니다. 이전 예제를 계속하면 애플리케이션이 관리이스트레이터 그룹 구성원 액세스 권한만 부여하는 파일에 쓰려고 하면 애플리케이션에 ACCESS_DENIED 오류가 발생합니다. 애플리케이션이 제대로 작동하지 않으면 이 작업이 원인일 수 있습니다.

LuaPriv는 다음과 같은 유형의 문제를 식별합니다.

잠재적인 문제 설명
제한된 네임스페이스 네임스페이스 없이 명명된 동기화 개체(Event, Semaphore, Mutex 등)를 만들면 운영 체제에서 제한된 네임스페이스에 개체를 배치하도록 선택할 수 있으므로 일부 운영 체제에서 권한 없이 실행이 복잡해질 수 있습니다. 제한된 네임스페이스(예: 전역 네임스페이스)에서 이러한 개체를 만들려면 관리자에게만 부여되는 SeCreateGlobalPrivilege가 필요합니다.
LuaPriv는 이러한 문제를 감지하면 두 문제에 플래그를 지정합니다.
하드 관리주점 검사 일부 애플리케이션은 사용자의 보안 토큰을 심문하여 자신이 얼마나 많은 권한을 가지고 있는지 확인합니다. 이러한 경우 애플리케이션은 사용자가 얼마나 많은 전력을 가지고 있다고 생각하는지에 따라 동작을 변경할 수 있습니다.
LuaPriv는 이 정보를 반환하는 API 호출에 플래그를 지정합니다.
권한 요청 애플리케이션은 필요한 작업을 수행하기 전에 보안 관련 권한(예: SeTcbPrivilege 또는 SeSecurityPrivilege)을 사용하도록 설정할 수 있습니다.
LuaPriv 플래그는 보안 관련 권한을 사용하도록 설정하려고 시도합니다.
누락된 권한 애플리케이션이 사용자에게 없는 권한을 사용하도록 설정하려고 하면 애플리케이션에 권한이 있음을 알릴 수 있으며, 이로 인해 동작 차이가 발생할 수 있습니다.
LuaPriv 플래그가 실패한 권한 요청입니다.
INI 파일 작업 매핑된 INI 파일(WritePrivateProfileSection 및 유사한 API)에 대한 쓰기 시도는 관리자가 아닌 사용자로 실패할 수 있습니다.
LuaPriv는 이러한 작업에 플래그를 지정합니다.
액세스 거부됨 애플리케이션이 개체(파일, 레지스트리 키 등)에 액세스하려고 하지만 액세스 부족으로 인해 시도가 실패하는 경우 애플리케이션은 더 많은 권한으로 실행될 것으로 예상할 수 있습니다.
LuaPriv는 ACCESS_DENIED 및 유사한 오류로 실패하는 개체 열기 시도에 플래그를 지정합니다.
거부 ACE 개체의 DACL에 Deny ACE가 있는 경우 특정 엔터티에 대한 액세스를 명시적으로 거부합니다.
이는 일반적이지 않으며 예측을 어렵게 만들기 때문에 LuaPriv는 AES를 발견할 때 거부 ACE를 플래그로 표시합니다.
액세스가 제한됨 애플리케이션이 일반 사용자에게 부여되지 않은 권한(예: 관리자만 쓸 수 있는 파일에 쓰려고 시도)에 대한 개체를 열려고 하면 일반 사용자로 실행할 때 애플리케이션이 동일하게 작동하지 않을 수 있습니다.
LuaPriv는 이러한 작업에 플래그를 지정합니다.
MAXIMUM_ALLOWED 애플리케이션이 MAXIMUM_ALLOWED 개체를 열면 개체의 실제 액세스 검사 다른 곳에서 발생합니다. 이 작업을 수행하는 대부분의 코드는 제대로 작동하지 않으며 권한 없이 실행할 때 거의 확실하게 다르게 작동합니다.
따라서 LuaPriv는 MAXIMUM_ALLOWED 모든 인시던트에 플래그를 지정합니다.

기타

일반적으로 간과되는 문제는 기타 테스트에서 캡처됩니다.

  • 위험한 API - 애플리케이션이 다음과 같은 안전하지 않은 작업을 사용하고 있는지 확인하기 위해 추적합니다.
    • TerminateThread에 대한 위험한 호출입니다.
    • 메모리 부족 조건에서 잠재적인 스택 오버플로입니다.
    • 여러 스레드가 계속 실행되는 동안 호출된 종료 프로세스입니다.
    • LoadLibrary는 DllMain 중에 호출됩니다.
    • FreeLibrary는 DllMain 중에 호출됩니다.
  • 더티 스택은 메모리 패턴으로 스택의 사용되지 않는 부분을 주기적으로 채웁니다. 이렇게 하면 해당 스레드의 컨텍스트에서 이후 함수 호출에서 초기화되지 않은 변수를 검색하는 데 도움이 될 수 있습니다.
  • TimeRollOver는 GetTickCount 및 TimeGetTime API가 평소보다 빠르게 롤오버되도록 합니다. 이렇게 하면 애플리케이션에서 시간 롤오버 처리를 더 쉽게 테스트할 수 있습니다.

기타 속성

위험한 API 검사 변경할 수 있는 속성이 하나 있습니다.

DllMainCheck - DllMain이 활성 상태일 때 LoadLibrary/FreeLibrary 호출을 확인합니다.

네트워킹

네트워킹 테스트는 WinSock API의 부적절한 사용을 찾습니다. 예를 들어 성공적인 WSAStartup() 전에 또는 분산에 성공한 WSACleanup() 호출 후에 네트워킹 API가 호출된 경우입니다. WinSock에 대한 자세한 내용은 winsock.h 헤더Windows 소켓 2를 참조하세요.

속성

다음 속성은 Net 확인 계층에 사용할 수 있습니다. 속성을 설정하려면 애플리케이션 검증 도구 사용자 인터페이스에서 네트워킹 공급자를 선택하고 속성 창을 엽니다.

속성 설명
FragmentsEnabled TCP IPv4 및 IPv6 소켓에서 받은 데이터 스트림의 조각화를 사용하도록 설정합니다.
FragmentSize Winsock 수신 API 호출에 버퍼로 반환되는 최대 바이트 수를 지정합니다.

FragmentsEnabled 속성을 사용하면 네트워킹 검증 도구 공급자의 기능을 통해 네트워크에서 TCP 스트림을 구문 분석하는 애플리케이션의 테스트 및 확인을 용이하게 할 수 있습니다. 사용하도록 설정되면 애플리케이션이 반환하기 전에 전체 버퍼를 채워야 하는 경우가 아니면 데이터를 수신하는 Winsock에 대한 모든 호출은 FragmentSize 바이트까지만 수신됩니다(MSG_WAITALL 플래그로 제어됨). TCP 프로토콜이나 Winsock은 버퍼로 반환될 수 있는 바이트 수에 대한 보장을 제공하지 않으므로 이 검사 사용하면 Winsock에 대한 호출당 수신된 바이트 수와 관계없이 네트워크에서 데이터 스트림을 구문 분석하는 코드가 올바르게 수행되는지 확인하는 데 도움이 됩니다. 스트림 파서의 문제는 높은 프로필 버그의 원인이었고, 이러한 속성은 특히 테스트하기 어렵기 때문에 정확성 확인을 용이하게 하기 위해 제공됩니다. 참고: 반환된 데이터는 변경되지 않습니다. 특정 속도로만 속도가 느려집니다. 애플리케이션은 이 사용 또는 사용 안 함으로 정확히 동일한 방식으로 동작해야 합니다.

다음 명령줄에서는 들어오는 모든 TCP 스트림을 myApp.exe 만든 모든 TCP IPv4 및 IPv6 소켓과 myApp.exe 의해 로드된 모든 이진 파일로 조각화할 수 있습니다.

appverif -enable Networking -for myApp.exe -with Networking.FragmentsEnabled=True Networking.FragmentSize=10

!avrf 디버거 확장

!avrf -net -socket count - 열린 소켓 및 닫힌 소켓 핸들 수를 표시합니다.

!avrf -net -socket dump [-v] [HANDLE] - 소켓 핸들을 표시합니다.

!avrf -net -wsastacks - WSAStartup/WSACleanup에 대한 현재 WSA 초기화 수 및 스택 추적의 시간순 목록을 표시합니다.

!avrf -net -wsastacks count - 현재 WSA init 수를 표시합니다.

!avrf -net -socket count - 이 명령은 열려 있고 닫힌 모든 추적 중인 소켓 핸들의 전체 수를 제공합니다. 이러한 항목은 순환 큐에서 추적되므로 추적되는 총계의 최대값이 있습니다. 소켓 핸들을 할당하는 Winsock API 중 하나가 호출되면 열린 목록에 소켓이 추가됩니다. 예를 들어 socket(), WSASocket(), accept()입니다. 소켓 핸들에서 closesocket() 함수가 호출되면 소켓이 열린 목록에서 닫힌 목록으로 이동합니다.

!avrf -net -socket dump [-v] [HANDLE] - 이 명령은 소켓 핸들을 열거합니다. "-socket dump"는 소켓 값으로 추적된 모든 열린 소켓 핸들과 닫힌 소켓 핸들을 나열합니다. 선택적 -v 플래그는 각 SOCKET 값을 인쇄한 직후에 열기 또는 닫기 호출 스택을 추가로 인쇄합니다. 선택적 HANDLE 필드에는 지정된 SOCKET 핸들과 열려 있거나 닫는 호출 스택만 나열됩니다.

다음은 다양한 -socket 사용 옵션의 예입니다.

0:008> !avrf -net -socket count
Number of open socket handles   = 16
Number of closed socket handles = 12
 
0:008> !avrf -net -socket dump
CLOSED SOCKET HANDLE - 0x47c
CLOSED SOCKET HANDLE - 0x2cc
CLOSED SOCKET HANDLE - 0x8c4
CLOSED SOCKET HANDLE - 0x6bc
CLOSED SOCKET HANDLE - 0x44c
CLOSED SOCKET HANDLE - 0x578
CLOSED SOCKET HANDLE - 0x6f4
CLOSED SOCKET HANDLE - 0x5b4
CLOSED SOCKET HANDLE - 0x4d8
CLOSED SOCKET HANDLE - 0x3cc
CLOSED SOCKET HANDLE - 0x4fc
CLOSED SOCKET HANDLE - 0x4e0
OPEN SOCKET HANDLE - 0xfd4
OPEN SOCKET HANDLE - 0x7d8
OPEN SOCKET HANDLE - 0xf8c
OPEN SOCKET HANDLE - 0xf88
OPEN SOCKET HANDLE - 0xae0
OPEN SOCKET HANDLE - 0xe58
OPEN SOCKET HANDLE - 0xdfc
OPEN SOCKET HANDLE - 0xcf8
OPEN SOCKET HANDLE - 0xa18
OPEN SOCKET HANDLE - 0x7a0
OPEN SOCKET HANDLE - 0x7b0
OPEN SOCKET HANDLE - 0x534
OPEN SOCKET HANDLE - 0xcdc
OPEN SOCKET HANDLE - 0x1f0
OPEN SOCKET HANDLE - 0x444
OPEN SOCKET HANDLE - 0x8bc
 
0:008> !avrf -net -socket dump -v 0x47c
 
The socket handle is closed
 
vfNet!VfHookclosesocket
WININET!ICSocket::_UnSafeCloseSocket
WININET!ICSocket::Dereference
WININET!CFsm_GetConnection::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::OpenConnection_Fsm
WININET!CFsm_OpenConnection::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::OpenConnection
WININET!HTTP_REQUEST_HANDLE_OBJECT::MakeConnection_Fsm
WININET!CFsm_MakeConnection::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::SendRequest_Fsm
WININET!CFsm_SendRequest::RunSM
WININET!CFsm::Run
WININET!DoFsm
WININET!HTTP_REQUEST_HANDLE_OBJECT::HttpSendRequest_Start
WININET!CFsm_HttpSendRequest::RunSM
WININET!CFsm::Run
WININET!CFsm::RunWorkItem
SHLWAPI!ExecuteWorkItemThreadProc
vfbasics!AVrfpRtlWorkerCallback
ntdll!RtlpTpWorkCallback
ntdll!TppWorkerThread
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart

!avrf -net -wsastacks [count]

Winsock을 사용하려면 애플리케이션 개발자가 Winsock을 호출하기 전에 WSAStartup()을 한 번 이상 호출해야 합니다. 이는 Winsock 프로세스 전체에서 추적됩니다. 초기 참조 수는 Winsock 카탈로그 및 공급자를 초기화하고 로드하도록 Winsock 라이브러리(ws2_32.dll)에 지시합니다. WSAStartup에 대한 추가 호출은 횟수를 참조하는 증가합니다. Winsock은 또한 애플리케이션 개발자가 Winsock에 대한 호출을 '완료'했을 때 WSACleanup()을 호출해야 합니다. WSACleanup에 대한 호출은 WSAStartup()에 대한 이전 호출과 올바르게 쌍을 이루어야 합니다. WSACleanup()에 대한 호출은 프로세스 전체 참조 수를 감소합니다. 참조 수가 0으로 떨어지면 Winsock은 리소스를 해제하고 Winsock 카탈로그 및 공급자를 언로드합니다.

이 명령은 현재 "WSAStartup" 초기화 루틴의 전체 참조 수 값을 제공하고 프로세스 내에서 수행된 WSAStartup 및 WSACleanup에 대한 호출 스택을 나열합니다. 이는 고정 순환 큐 내에서 기본 있으므로 완료되지 않도록 보장되지 않습니다. 가장 최근의 N 호출만 가능합니다.

다음은 다양한 -wsastacks 사용 옵션의 예입니다.

0:008> !avrf -net -wsastacks count
 
Current WSARefCount: 1 (WSAStartup call count minus WSACleanup call count for the target process)
 
 
0:008> !avrf -net -wsastacks
 
Current WSARefCount: 1 (WSAStartup call count minus WSACleanup call count for the target process)
 
 
THREAD ID: 0xe4c called WSAStartup
vfNet!WSAInitStacks<NetAllocatorViaPrivateHeap>::AddWSAStackTrace
vfNet!VfHookWSAStartup
WININET!LoadWinsock
WININET!GlobalDataInitialize
WININET!InternetSetOptionA
WININET!InternetSetOptionW
IEFRAME!LCIEUpdateSessionStartTime
IEFRAME!LCIETab_ThreadProc
iertutil!_IsoThreadProc
vfbasics!AVrfpStandardThreadFunction
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart

NTLM

이 애플리케이션 검증 도구 플러그 인은 NTLM 프로토콜의 사용을 감지하기 위해 인증 API AcquireCredentialsHandle 및 InitializeSecurityContext에 대한 개별 프로세스 호출을 모니터링합니다. NTLM은 애플리케이션 및 운영 체제의 보안을 손상시킬 수 있는 결함이 있는 오래된 인증 프로토콜이며 사용해서는 안 됩니다.

NTLM 인증 위험

오래된 NTLM 인증 프로토콜의 가장 중요한 단점은 서버 인증이 없다는 것입니다. 그러면 공격자가 사용자를 속여 스푸핑된 서버에 연결할 수 있습니다. 누락된 서버 인증의 결과로 NTLM을 사용하는 애플리케이션은 "리플렉션" 공격이라고 하는 공격 유형에 취약할 수도 있습니다. 이 후자를 사용하면 공격자가 사용자의 인증 대화를 합법적인 서버로 하이재킹하고 이를 사용하여 사용자의 컴퓨터에 대한 공격자를 인증할 수 있습니다. NTLM의 취약성 및 이를 악용하는 방법은 보안 커뮤니티에서 연구 활동을 늘리는 대상입니다.

Kerberos는 몇 년 동안 사용 가능했지만 많은 애플리케이션은 여전히 NTLM만 사용하도록 작성됩니다. 이렇게 하면 불필요하게 애플리케이션의 보안이 줄어듭니다. 그러나 Kerberos는 모든 시나리오에서 NTLM을 대체할 수 없습니다. 즉, 주로 클라이언트가 할 일기본 가입되지 않은 시스템에 인증해야 하는 경우(홈 네트워크가 가장 일반적일 수 있습니다). 협상 보안 패키지는 가능하면 Kerberos를 사용하는 이전 버전과 호환되는 타협을 허용하고 다른 옵션이 없는 경우에만 NTLM에 되돌리기. NTLM 대신 Negotiate를 사용하도록 코드를 전환하면 애플리케이션 호환성이 거의 또는 전혀 도입되지 않으면서 고객의 보안이 크게 향상됩니다. 협상 자체는 은색 글머리 기호가 아닙니다. 공격자가 강제로 NTLM으로 다운그레이드할 수 있지만 악용하기가 훨씬 더 어려운 경우가 있습니다. 그러나 한 가지 즉각적인 개선 사항은 Negotiate를 올바르게 사용하도록 작성된 애플리케이션이 NTLM 리플렉션 공격에 자동으로 영향을 받지 않는다는 것입니다.

NTLM 사용에 대한 마지막 주의 사항: Windows에서는 운영 체제 수준에서 NTLM 사용을 사용하지 않도록 설정할 수 있습니다. 애플리케이션이 NTLM에 대한 종속성이 어려운 경우 NTLM을 사용하지 않도록 설정하면 인증에 실패합니다.

애플리케이션에서 NTLM이 "하드 코딩"되는 요인은 무엇인가요?

NTLM에 대한 하드 종속성을 유발하는 두 가지 요소가 있습니다. 첫 번째는 애플리케이션에서 사용할 인증 패키지로 NTLM을 명시적으로 선택하는 것입니다. 일부 프로토콜 및 API의 경우 API AcquireCredentialsHandle()에 대한 호출과 같이 NTLM을 선택하는 것이 분명합니다. 다른 프로토콜의 경우 그렇게 명확하지 않을 수 있습니다. 예를 들어 RPC의 기본 인증 패키지(RPC_C_AUTHN_DEFAULT)는 네트워크를 통해 RPC를 사용하는 경우 실제로 NTLM에 대한 별칭이며, NTLM을 선택하는 명시적 플래그에도 NTLM 약어가 없습니다(RPC_C_AUTH_WINNT). 이러한 종류의 구문을 사용하면 NTLM을 선택하지 않아도 쉽게 선택할 수 있습니다.

개발자는 NTLM 대신 다른 인증 방법(예: 협상 패키지)을 사용해야 합니다(SPNEGO 또는 SNEGO 패키지라고도 함). Negotiate가 Kerberos 사용을 시도하려면 클라이언트 및 서버 구성 요소 모두에서 패키지 선택이 일치해야 하므로 애플리케이션의 클라이언트 및 서버 부분 모두 Negotiate를 사용해야 합니다. 어느 한 쪽에서 NTLM을 사용하는 경우(레거시 버전과 마찬가지로) 협상은 여전히 작동하지만 항상 NTLM에 되돌리기. 애플리케이션에 Negotiate를 사용하도록 지시하는 방법은 프로토콜에 따라 다릅니다. 가장 일반적인 프로토콜 중 일부(RPC, LDAP, DCOM, HTTP)는 나중에 항목 5000 – 애플리케이션에서 명시적으로 NTLM 패키지를 선택했습니다.

NTLM이 사용되는 두 번째 요소는 클라이언트가 인증 프로세스에 유효한 서버 대상 이름을 제공하지 않는 경우입니다. 상호 인증(예: Kerberos)을 지원하거나 요구하는 프로토콜에서 대상 이름은 상호 인증을 달성하는 데 사용됩니다. 인증 API(예: InitializeSecurityContext)는 일반적으로 "TargetName", "PrincipalName" 또는 "ServerPrincipalName"과 같은 선택적 매개 변수를 사용합니다. 이는 do기본 컨트롤러가 대상 서비스에 대한 자격 증명을 가져오기 위해 올바른 do기본 계정을 선택하는 데 사용하는 식별자입니다. NTLM에는 서버 인증 개념이 없으므로 NTLM이 성공적으로 인증하는 데 이 매개 변수가 필요하지 않습니다. 반면 Kerberos는 클라이언트가 인증하는 서비스에 유효한 서비스 티켓을 가져와야 합니다. 대상 이름이나 잘못된 대상 이름을 지정하지 않으면 Kerberos 인증이 항상 실패합니다. 협상이 패키지로 선택되면 대상 이름(또는 잘못된 대상 이름)을 제공하지 않으면 Kerberos를 완전히 건너뛰고 NTLM이 사용됩니다. 대부분의 인증 API는 NULL이 오류 없이 수락될 경우 대상 이름을 선택적 매개 변수로 사용합니다. 개발자가 이를 재정의하고 명시적 대상 이름인 NTLM(또한 반사 가능한 NTLM)을 제공하지 않는 한 결과가 됩니다.

NTLM 플러그 인 작동 방식

검증 도구 플러그는 다음 오류를 검색합니다.

  • NTLM 패키지는 AcquireCredentialsHandle(또는 상위 수준 래퍼 API) 호출에서 직접 지정됩니다.

  • InitializeSecurityContext 호출의 대상 이름은 NULL입니다. 이 경우 협상은 NTLM으로 직접 돌아갑니다.

  • InitializeSecurityContext 호출의 대상 이름은 올바른 형식의 SPN, UPN 또는 NetBIOS 스타일 do기본 이름이 아닙니다. 이 경우 do기본 컨트롤러는 "보안 주체를 찾을 수 없음" 오류를 반환하여 Negotiate가 NTLM으로 대체됩니다.

또한 플러그 인은 NTLM으로 다운그레이드를 감지할 때 경고를 기록합니다. 예를 들어 Do기본 컨트롤러에서 SPN을 찾을 수 없는 경우입니다. 이는 합법적인 경우가 많기 때문에 경고로만 기록됩니다(예: 가입되지 않은 시스템에 인증할 때기본.

플러그 인 중지 옵션 구성

기본적으로 오류로 분류된 모든 이벤트는 디버그 중단을 발생하도록 설정됩니다. 모든 경고 이벤트는 이벤트 세부 정보만 기록하도록 설정됩니다.

오류 이벤트로 인해 중지/중단이 발생합니다.

  • 5000 – 애플리케이션에서 NTLM 패키지를 명시적으로 선택했습니다.

  • 5001 – 패키지 협상 목록에 NTLM만 포함

  • 5002 – 패키지 목록 협상 잘못된 NTLM 제외

  • 5003 – 서버의 대상 이름 또는 형식이 잘못된 대상 이름 없음

기록된 경고 이벤트:

  • 5010 – NTLM으로 다운그레이드 감지됨

NTLM 중지

5000 – 애플리케이션에서 NTLM 패키지를 명시적으로 선택했습니다.

심각도 – 오류

애플리케이션 또는 하위 시스템은 AcquireCredentialsHandle 호출에서 협상 대신 NTLM을 명시적으로 선택합니다. 클라이언트와 서버가 Kerberos를 사용하여 인증할 수 있더라도 NTLM의 명시적 선택으로 인해 이를 방지할 수 있습니다.

이 오류를 해결하는 방법

이 오류의 수정 사항은 NTLM 대신 협상 패키지를 선택하는 것입니다. 이 작업은 클라이언트 또는 서버에서 사용하는 특정 네트워크 하위 시스템에 따라 달라집니다. 몇 가지 예가 아래에 나와 있습니다. 사용 중인 특정 라이브러리 또는 API 집합에 대한 설명서를 참조해야 합니다.

애플리케이션에서 사용하는 API(매개 변수) 잘못된 값 올바른 값 주의
AcquireCredentialsHandle(pszPackage) "NTLM" NEGOSSP_NAME 또는 "협상"
RPC 클라이언트: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx (AuthnSv) RPC Server: RPCServerRegisterAuthInfo(AuthnSvc) RPC_C_AUTHN_WINNT 또는 RPC_C_AUTH_DEFAULT RPC_C_AUTH_GSS_NEGOTIATE RPC 서버가 NTLM/WINNT 패키지를 등록하는 것은 오류가 아닙니다. 이는 NTLM만 지원하는 이전 클라이언트를 지원하는 데 종종 필요합니다. 이는 모든 클라이언트가 Kerberos를 사용할 수 있는 경우에도 NTLM을 사용하도록 강제하기 때문에 NTLM 패키지만 등록된 경우 오류입니다.
DCOM: SetBlanket CoSetProxyBlanket(dwAuthnSvc) CoCreateInstanceEx(자체 API에 전달된 COSERVERINFO 구조체의 멤버인 COAUTHINFO 구조체의 dwAuthnSvc 멤버로 전달됨) RPC_C_AUTHN_WINNT RPC_C_AUTHN_DEFAULT 또는 RPC_C_AUTHN_GSS_NEGOTIATE 협상은 통신이 항상 네트워크를 통해 발생하는 경우에만 사용해야 합니다. 동일한 컴퓨터의 클라이언트와 서버 간에 DCOM 호출이 발생하는 경우 DEFAULT를 사용하고 DCOM에서 사용할 올바른 패키지를 선택하도록 허용해야 합니다.
LDAP: ldap_bind_s(메서드) LDAP_AUTH_NTLM LDAP_AUTH_NEGOTIATE
HTTP WinHTTPSetCredentials(AuthScheme) WINHTTP_AUTH_SCHEME_NTLM WINHTTP_AUTH_SCHEME_NEGOTIATE

5001 – 패키지 협상 목록에 NTLM만 포함

심각도 – 오류

AcquireCredentialsHandle을 사용하는 경우 Negotiate에서 사용하거나 무시할 패키지 목록을 제공할 수 있습니다. 지정된 목록에 따라 가장 적절하고 안전한 인증 패키지를 선택하기 위해 Negotiate에 기본 제공되는 논리를 재정의할 수 있습니다. 패키지 목록에 NTLM만 포함하거나 Kerberos를 제외하는 경우 결과는 모두 협상을 우회하고 NTLM SSP 패키지를 직접 명시적으로 선택하는 것과 동일합니다.

하위 패키지 목록을 지정하는 것은 대부분의 상위 계층 API(예: RPC)가 호출자가 협상 패키지 목록을 제어할 수 없으므로 AcquireCredentialsHandle을 직접 호출할 때만 가능합니다.

Microsoft는 애플리케이션이 이런 방식으로 협상 패키지 목록을 조작하려고 시도하지 않는 것이 좋습니다.

이 오류를 해결하는 방법

하위 패키지 목록을 지정하지 않고 협상 패키지를 사용하거나 Kerberos가 포함되어 있는지 확인합니다.

애플리케이션에서 사용하는 API(매개 변수) 잘못된 값 올바른 값
AcquireCredentialsHandle(pAuthData 매개 변수로 전달된 SEC_WINNT_AUTH_IDENTITY_EX 구조체의 PackageList 멤버) "! Kerberos" 또는 "NTLM" NULL 또는 "Kerberos, NTLM" 또는 "Kerberos, ! NTLM" 또는 "! NTLM"

5002 – 패키지 목록 협상 잘못된 NTLM 제외

심각도 - 경고

AcquireCredentialsHandle을 호출할 때 애플리케이션은 Negotiate에서 지원하는 패키지 목록에서 NTLM을 제외하려고 했습니다. 그러나 잘못된 구문이 NTLM을 제외하는 데 사용되었으므로 목록에 다시 기본.

이 오류를 해결하는 방법 다음 구문을 사용하여 Negotiate에서 NTLM 패키지를 제외합니다.

애플리케이션에서 사용하는 API(매개 변수) 잘못된 값 올바른 값
AcquireCredentialsHandle(pAuthData 매개 변수로 전달된 SEC_WINNT_AUTH_IDENTITY_EX 구조체의 PackageList 멤버) "-NTLM" "! NTLM"

5003 – 서버의 대상 이름 또는 형식이 잘못된 대상 이름 없음

심각도 – 오류

Negotiate 패키지를 사용하는 경우 null 또는 잘못된 대상 이름(보안 주체 이름이라고도 함)을 제공하면 Kerberos가 실패하고 NTLM이 해당 위치에서 사용됩니다. 인증을 호출할 때 항상 유효한 대상 이름을 지정해야 합니다. 대상 이름은 할 일기본 컨트롤러가 애플리케이션이 인증하려는 서버의 계정 세부 정보를 가져올 수 있도록 하는 고유 식별자입니다. do기본 컨트롤러에 이 정보가 있으면 클라이언트와 서버 모두에서 이해(암호 해독 가능)할 적절한 Kerberos 티켓을 빌드할 수 있습니다.

이 오류를 해결하는 방법

대상 이름은 각각 do기본 컨트롤러에서 올바른 서버 계정 개체를 찾는 데 사용할 수 있는 세 가지 형식으로 지정할 수 있습니다. 이러한 형식은 SPN(서비스 사용자 이름), UPN(사용자 계정 이름) 및 NetBIOS 2부로 구성된 do기본\account 이름입니다. SPN은 가장 일반적인 형태이며 다른 Kerberos 구현과 가장 상호 운용 가능합니다. SPN에 대한 전체 토론은 이 문서의 범위를 벗어나지만 가장 간단하고 가장 일반적인 SPN 양식에는 서비스 클래스와 호스트 이름이라는 두 부분으로 구성됩니다. 서비스 클래스는 서버 애플리케이션의 유형을 식별합니다(예: http 또는 ldap와 같은 특정 애플리케이션 유형 또는 호스트와 같은 제네릭). 두 번째 부분은 정규화된 do기본 이름 또는 서버의 플랫(NetBIOS) 이름입니다. Windows 클라이언트 및 서버는 FQDN 및 플랫 이름에 대한 "호스트"에 대한 SPN을 자동으로 등록합니다. 또한 do기본 컨트롤러는 "http", "ldap", "rpc", "tapi" 등의 항목에 대해 약 40개의 애플리케이션별 서비스 클래스를 "호스트" SPN에 매핑합니다.

o 서버 운영 체제의 컨텍스트에서 실행되는 애플리케이션의 대상 이름(예: localsystem, 네트워크 서비스 또는 localservice)을 지정합니다. 클라이언트 애플리케이션은 자동으로 등록된 "호스트" SPN 또는 해당 별칭 중 하나를 사용할 수 있습니다. 할 일기본 사용자 계정의 컨텍스트에서 실행되는 애플리케이션에 인증하려면 해당 계정에 대한 SPN을 등록해야 합니다.

사용자 계정의 경우 사용자 계정 이름에서 빌드된 암시적 UPN 양식과 계정이 상주하는 할 일기본 사용할 수도 있습니다useraccountname@domain.dom. 사용자 계정에 대한 추가 UPN을 만들 수 있지만(각각에 대해 만들 수 있는 UPN 접미사 사용기본) Kerberos 대상 이름으로는 작동하지 않으며, 실제 로그온 계정 이름 및 실제 계정에 해당하는 UPN만 사용할 수 있습니다기본.

마지막으로 로컬 시스템, 네트워크 서비스 또는 로컬 서비스로 실행되는 서비스의 경우 NT4 스타일 do기본\username(또는 할기본\computername)을 계속 사용할 수 있습니다. 이는 할 일기본 사용자 계정 또는 컴퓨터 계정의 컨텍스트에서 실행되는 대상에 대해 작동합니다.

애플리케이션에서 사용하는 API(매개 변수) 대상 이름을 설정하는 매개 변수 주의
InitializeSecurityContext pszTargetName
RPC 클라이언트: RPCBindingSetAuthInfoEx RPCBindingSetAuthInfoEx(AuthnSv) ServerPrincipalName 서버/서비스가 실행 중인 계정의 대상 이름이어야 합니다. RPCServerRegisterAuthInfo에 설정된 값과 같을 필요는 없습니다.
DCOM: SetBlanket CoSetProxyBlanket(dwAuthnSvc) CoCreateInstanceEx(자체 API에 전달된 COSERVERINFO 구조체의 멤버인 COAUTHINFO 구조체의 dwAuthnSvc 멤버로 전달됨) pServerPrincName COLE_DEFAULT_PRINCIPAL 사용하여 COM이 바인딩 정보에서 이름을 자동으로 선택하도록 할 수 있습니다.
LDAP: 없음 LDAP 클라이언트에서 자동으로 생성됩니다.
HTTP 없음 WinHTTP 및 WinInet는 URL 서버 이름에서 대상 이름을 제공합니다.

5010 – NTLM으로 다운그레이드 감지됨

심각도 - 경고

애플리케이션별 Negotiate가 올바르게 형식이 지정된 대상 이름을 사용했음에도 불구하고 Negotiate가 NTLM으로 다운그레이드되는 원인이 되었습니다. 상황에 따라 오류 또는 예상 동작을 나타낼 수 있습니다. 예를 들어 컴퓨터가 할 일의 일부가 아니거나기본 할 일기본 컨트롤러에 액세스할 수 없는 위치에서 사용되는 경우 Negotiate는 애플리케이션이 NTLM을 사용하여 인증할 수 있도록 자동으로 다운그레이드될 것으로 예상됩니다. 그러나 do기본 컨트롤러를 사용할 수 있을 때 이 중지가 발생하고 일반적으로 Kerberos가 사용될 것으로 예상하는 경우 거의 확실하게 문제가 있음을 나타냅니다.

이 오류를 해결하는 방법

이 상황에서 NTLM이 아닌 Kerberos를 사용했어야 한다고 판단한 경우 다운그레이드가 발생한 여러 가지 가능성이 있습니다.

• 대상 이름이 올바른 형식일지라도 do기본(또는 포리스트)에 존재하지 않았습니다.

o 클라이언트 애플리케이션에서 올바른 대상 이름을 빌드하는 검사 합니다. 서비스 클래스가 올바른가요? 호스트 이름이 올바른가요?

o 컴퓨터의 컨텍스트에서 실행되는 서버 프로세스이거나 다른 do기본 계정입니다. 이전의 경우 SPN은 자동으로 등록되며, 후자의 경우 SPN을 등록하거나 암시적 UPN 또는 플랫 이름과 같은 대체 양식을 사용해야 할 수 있습니다.

o 할 일기본 컨트롤러 또는 DNS 서버와의 통신을 방해하는 네트워크 연결 문제가 있나요?

o 대상 SPN이 둘 이상의 계정에 등록되어 있나요? 이로 인해 do기본 컨트롤러가 인증 시도를 거부하게 됩니다.

인쇄

인쇄 검증 도구는 애플리케이션이 인쇄 하위 시스템을 호출할 때 발생할 수 있는 문제를 찾고 해결하는 데 도움이 됩니다. 인쇄 검증 도구는 인쇄 하위 시스템의 두 계층인 PrintAPI 계층과 PrintDriver 계층을 대상으로 합니다.

인쇄 API 계층

인쇄 검증 도구는 프로그램과 Winspool.drv 간의 인터페이스를 테스트하고 prntvpt.dll 해당 DLL의 인터페이스를 테스트합니다. winspool.drv 및 prntvpt.dll 내보낸 API에 대한 MSDN 도움말 섹션에서 이 인터페이스의 함수를 호출하는 규칙을 검토할 수 있습니다.

드라이버 계층 인쇄

또한 인쇄 검증 도구는 UNIDRV.DLL, UNIDRUI.DLL, PSCRIPT5.DLL, PS5UI.DLL 또는 MXDWDRV.DLL 같은 핵심 인쇄 드라이버와 인쇄 드라이버 플러그 인 간의 인터페이스를 테스트합니다. MSDN 및 WDK에서 이 인터페이스에 대한 정보를 찾을 수 있습니다.

일반적으로 디버그 버전만 애플리케이션 검증 도구를 실행하므로 성능은 일반적으로 문제가 되지 않습니다. 이 기능 또는 다른 애플리케이션 검증 도구 검사 사용으로 인해 성능 문제가 발생하는 경우 필요한 모든 검사 수행할 때까지 한 번에 하나의 검사 실행합니다.

WebServices

WWSAPI(Windows Webservices API) 확인 계층

WWSAPI 플러그 인을 통해 개발자는 다음의 인스턴스를 catch할 수 있습니다.

  • 잘못된 내장 WWSAPI 개체를 참조하는 WWSAPI가 호출됩니다.

  • 이미 사용 중인 단일 스레드 개체를 참조하는 WWSAPI가 호출되고 있습니다.

  • 비동기 호출이 보류 중인 상태에서 해제된 내장 개체입니다.

  • 짧은 스레드에서 차단 API 호출

또한 이 플러그 인은 다음과 같습니다.

  • 인스턴스화에서 삭제까지 개체의 사용을 추적합니다.

  • 비동기적으로 완료할 수 있는 호출을 동기적으로 완료하도록 강제합니다. 이는 WS_ASYNC_CONTEXT 호출에서 특정 동작에 따라 애플리케이션을 방지하기 위한 것입니다.

  • API가 잘못된 개체를 전달하거나 개체가 !avrf –ws –obj 디버거 확장(아래 참조)을 사용하여 사용 중일 때 사람이 읽을 수 있는 설명을 제공합니다.

  • 채널, 서비스 프록시 및 서비스 호스트의 경우 추적된 각 호출은 개체의 현재 상태를 표시합니다.

기본적으로 다음 검사 사용 설정됩니다.

Property NameDescriptionValidateObjectValidates intrinsic 개체가 validTrackObjectTracks의 수명 동안 개체 사용을 추적합니다.

속성 UI를 통해 이 공급자에서 사용할 수 있는 다른 검사ers는 다음과 같습니다.

NameDescriptionCheckTimeoutValida 속성은 시간 제한 내에서 비동기 함수가 완료되며, TimeoutValForceSyncForce로 지정되며, WS_ASYNC_CONTEXT 컨텍스트가 API에 제공될 때 사용할 동기화 경로입니다.

열려 있고 닫힌 내장 WWSAPI 개체를 표시하는 디버거 확장(!avrf –ws –obj)이 제공됩니다. 이 확장은 개체에 의해 접미사가 있는 경우 이 개체의 사용에 대한 자세한 정보를 표시합니다.

!avrf -ws –obj

이 명령은 추적 중인 기본 WWSAPI 개체(생성 및 닫힘)를 표시합니다. 닫힌 개체는 순환 큐에 저장되므로 추적된 총 개체 수에 대한 최대값이 있습니다.

WsCreateChannel(), WsCreateChannelForListener(), WsCreateServiceHost(), WsCreateServiceProxy(), WsCreateServiceProxyFromTemplate(), WsCreateError(), WsCreateHeap(), WsCreateHeap()teListener(), WsCreateMetadata(), WsCreateMessage(), WsCreateMessageForChannel(), WsCreateReader(), WsCreateWriter(), WsCreateXmlBuffer(), WsReadXmlBuffer(), WsReadXmlBufferFromBytes()

해당 WsFree*() 함수가 호출되고 완료되면 개체가 만든 목록에서 해제된 목록으로 이동됩니다.

!avrf –ws –obj [OBJECT]

이 명령은 내장 WWSAPI 개체의 사용을 표시합니다. 사용 정보에는 개체를 만들고, 사용하고, 해제할 때의 스택이 포함됩니다. 개체가 채널, 서비스 호스트 또는 서비스 프록시인 경우 개체를 사용하여 API가 호출되기 전에 개체의 상태를 표시합니다.

다음은 !avrf –ws –obj 사용 옵션의 예입니다.

0:001> !avrf -ws -obj
Objects dependent on internal objects allocated:


Objects currently allocated:

 0x00000000048566C0 (Type=Heap, Thread=0x000001bc, Pending Operations=0)
 0x0000000001BE6780 (Type=Error, Thread=0x000001bc, Pending Operations=0)
 0x0000000001C13580 (Type=Service Proxy, Thread=0x000001bc, Pending Operations=0)

Freed objects:

 0x0000000001C17170 (Type=Service Proxy, Thread=0x000001bc)
 0x0000000004856730 (Type=Heap, Thread=0x000001bc)
 0x0000000001BE6820 (Type=Error, Thread=0x000001bc)

0:001> !avrf -ws -obj 0x0000000001C13580

Object @ 0x0000000001C13580
        Type = Service Proxy
        Thread = 0x000001bc
        Internal Reference = 0x00000000026C5E80

Created stack:
  vfnws!VfHookWsCreateServiceProxy+0x00aa
  BLUESTONE!WST_WebServices::WsCreateServiceProxy+0x00d8
  BLUESTONE!ServiceProxy::Connect+0x0116
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Last 4 operations

Operation #1 created in thread 0x00000000000001BC

Service proxy state before operation = Created

Callstack:
  vfnws!VfHookWsGetServiceProxyProperty+0x0053
  BLUESTONE!WST_WebServices::WsGetServiceProxyProperty+0x009b
  BLUESTONE!ServiceProxy::GetState+0x004b
  BLUESTONE!ServiceProxy::VerifyState+0x001c
  BLUESTONE!ServiceProxy::Connect+0x01c7
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Operation #2 created in thread 0x00000000000001BC

Service proxy state before operation = Created

Callstack:
  vfnws!VfHookWsOpenServiceProxy+0x0079
  BLUESTONE!WST_WebServices::WsOpenServiceProxy+0x0092
  BLUESTONE!ServiceProxy::Connect+0x03d3
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Operation #3 created in thread 0x00000000000001BC

Service proxy state before operation = Open

Callstack:
  vfnws!VfHookWsGetServiceProxyProperty+0x0053
  BLUESTONE!WST_WebServices::WsGetServiceProxyProperty+0x009b
  BLUESTONE!ServiceProxy::GetState+0x004b
  BLUESTONE!ServiceProxy::VerifyState+0x001c
  BLUESTONE!ServiceProxy::Connect+0x0484
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x0607
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Operation #4 created in thread 0x00000000000001BC

Service proxy state before operation = Open

Callstack:
  vfnws!VfHookWsCall+0x00a6
  BLUESTONE!DefaultBinding_ICalculator_Add+0x008b
  BLUESTONE!ServiceModelTestGroup_Simple_Function+0x010a
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x069a
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d

Asynchronous Callback = BLUESTONE!ServiceModelTestGroup_Simple_Callback
Asynchronous CallbackState = 0x0000000005EBDC30

Completed asynchronously with HRESULT=0x00000000 in thread 0x00000000000001BC

Asynchronous callback stack:
  vfnws!VfHookWsCall+0x00e3
  BLUESTONE!DefaultBinding_ICalculator_Add+0x008b
  BLUESTONE!ServiceModelTestGroup_Simple_Function+0x010a
  BLUESTONE!ServiceModel_SimpleTest::SimpleClient+0x069a
  BLUESTONE!ServiceModelTestGroup_Simple_Test02_Run+0x0041
  BLUESTONE!Fnshell2::FnshellConfiguration::RunTest+0x002e
  BLUESTONE!Fnshell2::TESTCASE::Run+0x00d6
  BLUESTONE!fnsMsgProc+0x02d6
  BLUESTONE!fnsRunTestsWorkerThread+0x085f
  KERNEL32!BaseThreadInitThunk+0x000d
  ntdll!RtlUserThreadStart+0x001d


Closed stack:

0:001>

Services

서비스 테스트는 Windows 서비스의 적절한 사용을 검사. 예를 들어 서비스가 제대로 시작되고 중지됩니다. 이러한 테스트에서 생성된 중지 코드 예외에 대한 자세한 내용은 Application Verifier - Stop Codes - Services를 참조 하세요.

성능

성능 테스트는 잘못된 대기 기간을 사용하는 Windows 함수 호출과 같이 시스템 성능 및 에너지 소비에 영향을 주는 API의 효율적인 사용을 위해 검사. 이러한 테스트에서 생성된 중지 코드 예외에 대한 자세한 내용은 Application Verifier - Stop Codes - Perf를 참조 하세요.

중단

DllMain 스레드가 차단된 다른 스레드를 대기하는 경우와 같이 시스템이 응답하지 않는 API 사용을 테스트합니다. 이러한 테스트에서 생성된 중지 코드 예외에 대한 자세한 내용은 Application Verifier - Stop Codes - Hangs를 참조 하세요.

ARM64EC 지원

다음 공급자는 ARM64EC 지원하지 않으므로 ARM64EC 실행 중인 프로그램이 중단됩니다.

참고 항목

애플리케이션 검증 도구 - 개요

애플리케이션 검증 도구 - 기능

애플리케이션 검증 도구 - 애플리케이션 테스트

애플리케이션 검증 도구 - 코드 및 정의 중지

애플리케이션 검증 도구 - 애플리케이션 검증 도구 디버깅 중지

애플리케이션 검증 도구 - 질문과 대답