애플리케이션 검증 도구 - FAQ(질문과 대답)
일반적인 질문
다음은 애플리케이션 검증 도구의 일반적인 사용과 관련된 질문 목록입니다.
애플리케이션 검증 도구란?
애플리케이션 검증 도구는 Microsoft Windows 애플리케이션에서 버그를 찾는 데 사용되는 런타임 확인 도구입니다. 런타임 도구이므로 확인하려면 애플리케이션 코드를 실행해야 합니다. 따라서 좋은 테스트 검사가 필수적입니다.
애플리케이션 검증 도구의 일반적인 사용 시나리오는 관심 있는 애플리케이션에 대해 사용하도록 설정한 다음(이를 수행하는 방법에 대한 아래 질문 참조) 애플리케이션에 대해 작성한 모든 테스트를 실행하는 것입니다. 디버거 중단 또는 검증 도구 로그 항목의 형태로 발견된 버그에 대한 알림이 표시됩니다.
애플리케이션 검증 도구를 제거할 어떻게 할까요? 있나요?
애플리케이션 검증 도구를 제거하려면 시작을 클릭하여 제어판에 액세스하고 프로그램 추가 또는 제거를 선택한 다음 프로그램 제거, 애플리케이션 검증 도구, 제거를 차례로 클릭합니다.
애플리케이션 검증 도구를 시작할 어떻게 할까요? 있나요?
애플리케이션 검증 도구를 설치한 후 프로그램 목록에서 액세스하거나 명령줄에 Appverif.exe 입력하여 시작할 수 있습니다. 이렇게 하려면 명령 프롬프트 또는 시작 메뉴의 실행 상자로 이동합니다. appverif.exe 입력한 다음 Enter 키를 누릅니다. 그러면 애플리케이션 검증 도구가 시작됩니다.
Appverifer.exe 이진 파일은 시스템 디렉터리에 설치되며 도구 설정을 만드는 데 사용됩니다.
로그는 어디에 저장되어 있나요?
로그는 %USERPROFILE%\AppVerifierLogs에 저장됩니다.
애플리케이션 검증 도구를 사용하는 동안 문제가 있는 경우 어떻게 해야 하나요?
최신 릴리스를 실행하고 있는지 확인합니다. 다른 PC 또는 Windows 버전에서도 동일한 앱을 사용해 보세요.
애플리케이션 검증 도구가 관리 코드를 확인하나요?
AppVerifier는 운영 체제와 애플리케이션 간의 인터페이스를 관리합니다. 따라서 관리 코드가 힙, 핸들, 중요 섹션 등과 관련이 있는 네이티브 API에 대해 interop을 수행하지 않는 한 테스트 사례는 확인된 인터페이스와의 상호 작용을 제공하지 않습니다.
관리 코드를 확인하기 위해 관리되는 디버깅 도우미를 활용하는 것이 좋습니다. Windows 디버거를 사용하여 관리 코드를 디버깅하는 방법에 대해 자세히 알아보세요.
ARM64EC 지원되는가요?
애플리케이션 검증 도구는 ARM64EC 지원하지 않습니다.
디버거 질문
다음은 디버거와 관련하여 받은 질문 목록입니다.
디버거가 필요하다는 오류가 표시되는 이유는 무엇인가요?
Application Verifier 내의 기본 확인 계층에서는 디버거에서 애플리케이션을 실행해야 합니다. 테스트를 선택하기 전에 애플리케이션에 연결된 디버거가 없는 경우 로그된 정보를 얻기 위해 디버거에서 애플리케이션을 실행해야 한다는 대화 상자가 표시됩니다.
디버거에서 애플리케이션을 실행할 어떻게 할까요? 있나요?
디버거 설치 및 설정 항목 참조 - Windows 디버깅 시작
다른 계측 없이 스택 확장을 테스트할 어떻게 할까요? 있나요?
일반적으로 스택 확장은 힙을 비롯한 다른 확인 계층과 격리되어 실제로 테스트되어야 합니다. 그 이유는 다음과 같습니다. 각 확인 계층은 API 또는 일부 루틴으로 내보낸 지점을 "unks"합니다.
예를 들어 CreateFileA에 대한 호출은 appvocre에 대한 호출입니다. NS_SecurityChecks::CreateFileA, appvcore를 호출할 수 있습니다. NS_FillePaths::Kernel32를 호출할 수 있는 CreateFileA! 검증 도구라고 할 수 있는 CreateFileA! ntdll을 호출하는 AVrfpNtCreateFile! NtCreateFile. 계측에 3개의 "누적" 함수 호출이 추가되었으며, 각 호출은 더 많은 스택을 사용할 수 있고 더 많이 사용할 수 있음을 알 수 있습니다.
아래의 경우 LH-verifier.dll 모든 DllMain을 "unking"하고 " 계측된" 힙 코드 경로는 스택 사용량을 더 추가합니다. 디버거에서 삽입된 스레드는 IMAGE_NT_HEADERS 기본값을 사용하지 않으므로 처음에 커밋된 스택은 스레드의 APC 상태를 완료하기에 충분하지 않습니다(APC 상태의 스레드가 초기화 코드를 실행).
Stack-Ckecs를 사용하려는 경우 FirstChanceAccessViolation인 경우 사용해야 하는 유일한 다른 확인 계층일 것입니다.
!avrf 확장을 사용하는 경우 '애플리케이션 검증 도구가 이 프로세스에 대해 사용하도록 설정되어 있지 않습니다...'가 표시됩니다.
전체 오류가 수신되었습니다. Application verifier is not enabled for this process. Use appverif.exe tool to enable it.
shim 확인 계층만 사용하도록 설정되었거나 "순수" 모드의 힙이 활성화되어 있을 수 있습니다. 이러한 원인은 몇 가지 가능한 원인입니다.
테스트 시나리오 질문
다음은 다양한 테스트 시나리오에 대해 받은 질문 목록입니다.
내 서비스에는 애플리케이션 검증 도구를 사용하도록 설정하지만 다른 서비스에는 사용하도록 설정하지 않나요?
System32 디렉터리에서 svchost.exe 복사본을 만들고 "Mysvchost.exe" 복사본을 호출합니다.
regedit을 사용하여 HKLM\System\CurrentControlSet\Services\MyService를 엽니다.
"%SystemRoot%\system32\svchost.exe -k myservice" 값 "ImagePath"를 편집하고 svchost.exe "Mysvchost.exe"로 변경합니다.
AppVerifier 목록에 "Mysvchost.exe"을 추가하고 원하는 테스트를 확인합니다.
다시 부팅하세요.
WOW64에서 실행되는 32비트 애플리케이션에서 시작된 64비트 애플리케이션에서 Application Verifier를 실행할 어떻게 할까요? 있나요?
간단한 버전: 지정된 애플리케이션에서 검증 도구 설정을 사용하도록 설정하는 가장 좋은 방법은 도구의 비트와 대상 프로세스와 일치시키는 것입니다. 즉, 32비트 애플리케이션(모두 WoW64에서 실행)에 32비트 appverif.exe 사용하고 네이티브 64비트 네이티브 대상에 64비트 AppVerif.exe 사용합니다.
긴 버전: 애플리케이션 검증 도구 설정은 "코어" 설정과 "shim" 설정의 적절한 결합입니다.
핵심 설정 - 핵심 설정은 이미지 파일 실행 옵션 아래에 저장됩니다.
"디버거" 값은 시작 애플리케이션에서 읽습니다. 따라서 32비트 devenv.exe 64비트 my.exe 시작하고 디버거에서 실행하려면 WoW6432Node에서 32비트 레지스트리 키를 사용해야 합니다. 32비트 프로세스의 다른 값은 네이티브 IFEO와 WoW6432Node 둘 다에서 읽습니다.
추론은 다음과 같습니다. WoW에서 실행되는 32비트 프로세스는 Wow64 에뮬레이션 루프를 실행하는 64비트 프로세스입니다. 따라서 각 32비트 프로세스는 먼저 64비트 프로세스와 32비트 프로세스입니다. 64비트 IFEO는 Wow64cpu.dll 코드에서 검증 도구를 사용하도록 설정하고, 32비트 IFEO는 32비트 코드에서 검증 도구를 사용하도록 설정합니다.
최종 사용자 관점에서 verifier.dll 두 번 로드됩니다(64비트 세계에서 한 번, 32비트 세계에서 한 번). 대부분의 사람들은 wow64cpu.dll 확인하는 데 신경 쓰지 않으므로 32비트 프로세스에 가장 많이 허용되는 동작은 32비트 부분만 확인하는 것입니다. 이것이 바로 "항상 비트와 일치"의 황금 규칙이 적용되는 이유입니다.
비대화형 창 스테이션에서 실행되는 내 서비스를 디버그하는 어떻게 할까요?
비대화형 창 스테이션에서 실행되는 서비스를 디버그하려면 다음을 수행합니다(ntsd/windbg를 사용하는 경우에만 적용됨).
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options 아래에 레지스트리에 키를 추가합니다. 이 키의 이름은 프로세스의 이름(service.exe)이어야 합니다.
디버거라는 REG_SZ 값을 만들고 이 값을 디버거가 있는 경로로 설정합니다. 디버거의 이름뿐만 아니라 전체 경로를 포함해야 합니다. 명령에는 -server 옵션과 디버거가 수신 대기해야 하는 특정 포트 또는 포트 범위가 포함되어야 합니다. 예를 들어 c:\debuggers\ntsd.exe –server tcp:port=5500:5600 –g –G입니다.
-remote 옵션을 사용하여 디버거를 실행하여 디버거 서버에 연결합니다. 예를 들어 windbg.exe –remote tcp:=localhost,port=55xx입니다. 여기서 'xx'는 서버에서 범위를 사용한 경우 00에서 99까지의 숫자입니다.
AppVerifier가 누출 감지를 수행하나요? Windows 7 이상에서는 프로세스가 메모리를 누수하는 시기를 감지하는 누수 검사 옵션이 있습니다. 이전 운영 체제에서 AppVerifier는 애플리케이션에서 누수 감지를 테스트하지 않지만 다른 메모리 문제를 찾습니다.
보안 문제에 권장되는 테스트는 무엇입니까?
- 힙
- 핸들
- 잠금
- 스택(머신을 다운할 수 있는 서비스 및 중요한 프로세스에만 해당)
ObsoleteAPICalls는 사용되지 않거나 MSDN에서 더 이상 사용되지 않는 API로 표시되는 모든 호출에 대한 경고를 뱉습니다. 애플리케이션이 새 API로 전환하는 것이 중요한지 사례별로 결정해야 합니다. 일부 API는 위험하며 일부 API는 더 많은 옵션을 사용하여 최신 API로 대체되었습니다. 보안 코드 작성의 "위험한 API" 섹션을 살펴보세요. 자세한 내용은 2차 추가입니다.
서비스 및 서버 프로그램과 같이 매우 신뢰할 수 있어야 하는 애플리케이션의 경우 스택 검사도 사용하도록 설정해야 합니다. 이렇게 하면 스택 증가를 사용하지 않도록 설정하여 스택 커밋 크기가 적절한지 확인합니다. 애플리케이션이 스택 오버플로로 즉시 종료되면 더 큰 스택 커밋 크기로 애플리케이션을 다시 컴파일해야 합니다. 테스터이고 Stacks 검사를 사용하는 동안 애플리케이션에 문제가 발생하는 경우 버그를 제출하고 개발자에게 할당하고 테스트를 계속합니다.
특정 질문 테스트
다음은 테스트와 관련된 질문 목록입니다. 질문을 클릭하여 응답을 확인합니다.
중요한 섹션 누출이 중요합니까?
중요한 섹션을 누설할 때마다 이벤트 핸들, 소량의 커널 풀 및 작은 힙 할당이 누출됩니다. 프로세스가 종료되면 정리됩니다.
당신의 과정이 오랜 시간 살아 있어야하는 경우, 다음 이러한 누출은 당신을 물린 수 있습니다. 수정 사항은 케이스의 99%에서 매우 쉽기 때문에(개발자가 RtlDeleteCriticalSection을 호출하는 것을 잊었기 때문에) 해결해야 합니다.
스택 오버플로를 프로그래밍 방식으로 처리할 수 있나요?
초기 스레드 함수에서 예외 처리기를 설정해도 발생할 수 있는 잠재적인 스택 오버플로를 catch할 수 있는 것은 아닙니다. 이는 예외를 디스패치하는 코드에서 현재 활성화 레코드 위에 실행하기 위해 약간의 스택도 필요하기 때문입니다. 스택 확장을 방금 실패했으므로 커밋된 스택의 끝을 단계별로 실행하고 첫 번째 스택을 디스패치하는 동안 두 번째 예외를 발생시킬 가능성이 큽니다. 이중 오류 예외는 프로세스를 무조건 종료합니다.
LoaderLock 테스트에서 DestroyWindow를 호출하는 동안 오류가 발생했습니다. DllMain에서 DestroyWindow를 호출할 수 없는 이유는 무엇인가요? 분리할 스레드를 제어하지 않습니다. 창을 만든 스레드와 동일한 스레드가 아닌 경우 창을 삭제할 수 없습니다. 따라서 창을 누수하고 다음에 창에 메시지가 표시되면 Wndproc가 언로드되었으므로 충돌이 발생합니다.
프로세스 분리를 가져오기 전에 창을 삭제해야 합니다. 위험은 user32가 언로드되지 않는다는 것입니다. 위험은 언로드되고 있다는 것입니다. 따라서 user32가 더 이상 존재하지 않는 Wndproc에 메시지를 전달하므로 창이 수신하는 다음 메시지가 프로세스에 충돌합니다.
Microsoft Windows 운영 체제에는 스레드 선호도가 있습니다. 프로세스 분리는 수행하지 않습니다. 로더 잠금은 실제로 큰 문제가 아닙니다. 문제는 Dllmain입니다. 프로세스 분리는 DLL이 코드를 실행하는 마지막 시간입니다. 당신은 당신이 반환하기 전에 모든 것을 제거해야합니다. 그러나 Windows에는 스레드 선호도가 있으므로 잘못된 스레드에 있는 경우 창을 정리할 수 없습니다.
전역 후크가 설치된 경우(예: spy++가 실행 중임) 로더 잠금이 그림에 입력됩니다. 이 경우 잠재적인 교착 상태 시나리오를 입력합니다. 다시 말하지만, 해결 방법은 프로세스 분리를 가져오기 전에 창을 삭제하는 것입니다.
오버플로를 방지하기 위해 초기 스택 커밋을 늘리는 데 비용이 많이 들나요?
스택을 커밋할 때 페이지 파일 공간만 예약합니다. 성능에 영향을 주지 않습니다. 실제 메모리는 실제로 사용되지 않습니다. 커밋한 스택 공간을 실제로 터치하는 경우 유일한 추가 비용이 발생합니다. 그러나 스택을 미리 커밋하지 않더라도 이런 일이 발생합니다.
모든 서비스를 svchost.exe 방탄으로 실행하는 데 드는 비용을 살펴보겠습니다. 테스트 컴퓨터에서 총 139개의 스레드가 있는 9개의 svchost.exe 프로세스를 가져옵니다. 각 스레드의 기본 스택을 32K로 설정하는 경우 모든 스택을 미리 커밋하려면 약 32K x 200 ~ 6.4Mb의 페이지 파일 공간이 필요합니다.
이것은 안정성을 위해 지불하는 꽤 작은 가격입니다.
예약된 스택 크기는 어떻습니까?
"예기치 않은" 추가 스택이 필요한 IA64/AMD64에서 예외 디스패치와 같은 흥미로운 항목이 있습니다. 스택 요구 사항이 측정하려는 합리적인 시도를 지난 RPC 작업자 스레드에서 일부 처리가 발생할 수 있습니다.
우선 프로세스에 있는 모든 스레드 풀에 대한 아이디어를 얻어야 합니다. 예를 들어 SQL의 데이터베이스 구성 요소를 사용하는 경우 사용자-APC의 대상인 스레드에서 경고 가능한 절전 모드를 사용하기 때문에 경고 가능-대기 스레드가 있는 NT-스레드 풀은 경우에 따라 특별합니다. 이로 인해 중첩된 호출에 문제가 발생할 수 있습니다.
모든 스레드 풀을 알고 나면 스택 요구 사항을 제어하는 방법에 대한 아이디어를 얻을 수 있습니다. 예를 들어 RPC는 스택 커밋에 대한 레지스트리 키를 읽습니다. WDM 펌프 스레드는 이미지에서 가져옵니다. 다른 스레드 풀의 경우 마일리지가 다를 수 있습니다.
모든 스레드가 명확해지면 몇 가지 작업을 수행할 수 있습니다. 거대한 예약 공간이 없으면 스레드가 자주 오고 가는 경우에만 공간 조각화를 해결하는 데 도움이 됩니다. 컨트롤에 안정적인 스레드 풀이 있는 경우 예약된 공간도 줄이는 이점이 있을 수 있습니다. 사용자에 대한 힙 및 주소 공간의 주소 공간을 절약하는 데 도움이 됩니다.
LINKER_STACKCOMMITSIZE=에 적합한 크기를 선택하는 방법에 대한 권장 사항이 있나요?
값은 페이지 크기(CPU에 따라 4k/8k)로 나눌 수 있어야 합니다. 필요한 크기를 결정하는 몇 가지 지침은 다음과 같습니다.
잠재적인 언바운드 깊이(또는 적어도 사용자가 덕트할 수 없는 높은 깊이)를 가진 재귀 함수를 반복 함수로 변환합니다.
알로카 사용량을 줄입니다. 힙 또는 safealloca를 사용합니다.
스택 크기 검사를 줄여 프리페스트를 실행합니다(예: 8k). 너무 많은 스택을 사용하는 것으로 플래그가 지정된 함수를 수정합니다.
스택 커밋을 16k로 설정합니다.
애플리케이션 검증 도구의 "스택" 검사를 사용하여 테스트의 디버거 무리에서 실행합니다.
스택 오버플로가 표시되면 최악의 범죄자를 결정하고 수정합니다. (5단계 참조)
스택 사용량을 더 이상 8k로 줄일 수 없는 경우 64k에 문제가 있는 경우 > 다시 64k로 줄이고 6단계를 참조하세요. 그렇지 않으면 5단계로 이동합니다.
힙 테스트에 대한 메모리 요구 사항은 무엇인가요?
전체 힙 테스트의 경우 256MB의 RAM과 1GB 이상의 페이지 파일이 필요합니다. 일반 힙 테스트의 경우 128MB 이상의 RAM이 필요합니다. 특정 프로세서 또는 디스크 요구 사항은 없습니다.
ALL_ACCESS 중지를 받는 이유는 무엇인가요?
_ALL_ACCESS 사용하는 모든 애플리케이션은 감사 로그가 개체로 실제로 수행한 작업만 반영하지 않으므로 액세스하는 개체를 감사할 수 없게 렌더링합니다.
이 조건은 더 사악한 공격에 대한 위장을 만듭니다. 진행 중인 공격 활동을 검사하는 관리자는 특정 애플리케이션이 항상 이를 수행하므로 키 X에 대한 ALL_ACCESS 요청하는 사람에게 아무런 문제가 없습니다. 관리자는 "사용자가 Word를 실행 중일 것"으로 생각할 것입니다. 관리자는 해커가 내 계정을 침투하고 지금 내가 가지고있는 액세스를 결정하기 위해 시스템을 조사하고 있음을 알 수 없습니다, 그는 자신의 사악한 목적을 위해 악용 할 수있는. 가능성은 무한합니다.
ALL_ACCESS ACL 문제는 항상 부여해야 한다는 것입니다. 언젠가 특정 키에 대한 DELETE 액세스를 거부하려는 경우 이를 수행할 수 없습니다. 실제로 키를 삭제하지 않았더라도 삭제 액세스를 요청하므로 애플리케이션이 중단됩니다.
힙 및 잠금 테스트에서 로그를 가져오지 않는 이유는 무엇인가요?
이러한 테스트는 패키지가 아닌 운영 시스템에 빌드된 확인 계층이며 디버거에서 오류를 보고합니다. 이러한 테스트를 사용하도록 설정된 애플리케이션을 실행하고 크래시가 없는 경우 문제를 보고하지 않습니다.
크래시가 발생하면 디버거에서 실행하거나 애플리케이션을 개발자에게 전달하여 더 자세히 테스트해야 합니다.
오류 주입이 작동하지 않는 이유는 무엇인가요?
오류 주입 확률은 고객 피드백에 따라 2007년 2월 이후에 릴리스된 AppVerifier 빌드에서 백만 개당 파트로 변경되었습니다. 따라서 0n20000의 확률은 2%, 0n500000은 50% 등입니다.
!avrf –flt 디버거 확장을 사용하여 디버거에서 즉시 확률을 변경할 수 있습니다. 그러나 이 작업이 작동하려면 프로세스에 대한 낮은 리소스 시뮬레이션 검사를 설정해야 합니다.
!avrf 디버거 확장은 디버거 패키지와 함께 제공되는 exts.dll 일부입니다. 확률 변경을 지원하는 !avrf의 변경 내용은 최신 디버거 패키지에 있습니다. 오류 주입에 문제가 있는 경우 디버거 및 AppVerifier 패키지를 업데이트하세요.
누출 검증 도구가 특정 리소스 누출을 보고하지 않는 이유는 무엇인가요?
누수 검증 도구는 DLL 또는 EXE 모듈이 로드되는 동안 리소스 누수는 보고하지 않습니다. 모듈이 언로드되면 모듈에서 할당한 리소스가 해제되지 않은 경우 누수 검증 도구에서 중지를 실행합니다.
로드된 DLL 또는 EXE에서 할당된 리소스를 검사하려면 !avrf -leak 디버거 확장을 사용합니다.