코드를 작성하여 PDB를 로드하는 Windows 개발

5949 단어
최근에 dll과 대응하는 PDB를 대량으로 분석하는 프로그램을 작성해야 하는데,
사실 작업은 매우 간단하다. 바로 한 무더기의 편이에 따라 PDB 파일을 통해 dll 안에 대응하는 위치에 대한 명문 기호를 찾는 것이다.
간단한 수요는 이루기 힘들지만,
마이크로소프트의 데모 중에는 다이아라는 데모가 있는데 이 데모는 유사한 기능을 제공할 수 있다.
나는 이 항목을 기쁘게 컴파일했지만 실패했다. 기호를 불러오는 데 실패했다.
단일 디버깅을 통해 몇 가지 작은 문제(예를 들어 msdia120은 이런 것을 등록하지 않았음)를 넘어서 문제가 발생한 위치가loadDataForExe라는 함수에 있음을 발견했다.
이 함수 원형은
virtual HRESULT stdMETHODCALLTYPE loadDataForExe( LPCOLESTR executable, LPCOLESTR searchPath, IUnknown *pCallback) = 0
이를 통해 알 수 있듯이 매개 변수 1은 실행 가능한 파일이고 매개 변수 2는 목표 dll이 살아있는 exe이며 매개 변수 3은 하나의 인터페이스로 NULL을 위한 것이거나 마이크로소프트 데모에 따라 수정하지 않아도 된다.
그러나 실행한 후에 그것이 나에게 경로 오류를 보고하여 목표 pdb를 찾을 수 없다고 말했다.
구체적인 오류와 세부 사항은 말하지 않고 시간을 낭비하다.
이 문제를 어떻게 해결할지 말해 보세요.
 
해결 방법은 비교적 간단하지만,
먼저 사고방식을 정하고 이 함수를 사용할 수 없다는 것은 스스로 기호를 다운로드할 수 없다는 것을 의미한다. 그러면 어떻게 해야 하는지,
해결 방법은 우리가 기호를 다운로드한 후에 바로 불러오면 된다. 또 다른 함수는 사용할 수 있는loadDataFromPdb이다.
생각을 정했으면 길을 평평하게 깔아야 한다. 내가 어떻게 기호를 다운받는지,
가장 간단한 방법은 사실 윈도 자체의 다운로드 기능을 사용하고 개발을 최소화하기 위해 윈DBG 내부의 기능을 사용하여 기호를 자동으로 다운로드할 수 있다.
이렇게 해서 기호 파일이 생겼고, 불러오는 방식이 생겼으니, 기호 파일과 실행 가능한 파일을 어떻게 대응하고, 어떻게 대응해야 하는가가 다르다.
분석을 통해 우리는 실제 기호 파일이 땅에 떨어진 후에 특수한 디렉터리 이름이 있다는 것을 발견했다. 이 이름은 MD5와 비슷하거나 GUID와 비슷하다.
분석 프로그램을 통해 최종적으로 이 디렉터리 이름은 실행 가능한 파일 내부 기록의 GUID이고 마지막에 문자 1을 추가하는 것을 발견했다.
구체적으로 말하면 이렇다.
 1 PCHAR pBuffer = (PCHAR)h;
 2 PCHAR pTemp = pBuffer + 0x3C;
 3 pTemp = pBuffer + *(DWORD *)pTemp;
 4 if (!(pTemp[0] == 'P' && pTemp[1] == 'E' && pTemp[2] == '\0' && pTemp[3] == '\0'))
 5 {
 6     return NULL;
 7 }
 8 PVOID *pv;
 9 pv = (PVOID*)(pTemp + 0xA8);             //         
10 pTemp = pBuffer + (DWORD)*pv;            //                
11 pv = (PVOID *)(pTemp + 4 * 5);           //        
12 pTemp = pBuffer + (DWORD)*pv;            //       UUID   
13 if (!(pTemp[0] == 'R' && pTemp[1] == 'S' && pTemp[2] == 'D' && pTemp[3] == 'S'))
14 {
15     return NULL;
16 }
17 GUID tGuid = { 0 };
18 memcpy_s(&tGuid, sizeof(tGuid), pTemp + 4, sizeof(tGuid));

실행 가능한 파일에 따라 PE 헤더를 찾고 PE 헤더에서 디버깅 바이트를 찾으면
디버그 섹션에서 GUID의 오프셋 주소를 찾았습니다.
GUID 오프셋 주소의 처음 네 글자는 RSDS로 고정되어 있으며 판단 후 문제가 없으면
그 다음은 하나의 GUID 길이,
마지막으로 이 GUID를 포맷해서 문자열로 만들고, 마지막으로 뒤에 문자 '1' 을 추가하면 현재 파일에 대응하는 PDB 디렉터리 이름으로 조립합니다.
그리고 이 디렉터리 이름을 통해 완전한 디렉터리를 연결할 수 있습니다. 마치 Windows dbghelp와 같습니다.dll로 연결된 디렉터리,
그리고 안으로 들어가면 자신이 대응하는 pdb를 찾을 수 있다.
전체 과정의 서술이 끝나다.
 
 
마지막으로 총괄해 봅시다.
pdb를 불러올 수 없는 방법: 스스로 다운로드하고 독립적으로 불러옵니다.
방법:
1: WinDBG 명령줄을 사용하여 실행 파일의 PDB 파일을 다운로드합니다.
2: 실행 파일을 기준으로 PDB 경로를 계산하여 대상 PDB를 찾습니다.
3: 대상 PDB를 찾은 후 loadDataFromPdb에서 PDB를 직접 로드하면 됩니다.

좋은 웹페이지 즐겨찾기