dll의 마운트 주소를 고정하는 방법

2978 단어
dll을 디버깅할 때 짜증나는 일이 하나 있다. 바로 dll가 불러오는 주소가 고정되지 않는다는 것이다. (기본적으로 설정된 dll 주소는 항상 0x100000000이고 여러 개의 같은 주소의 dll가 불러올 때 뒤의 주소는 반드시 다시 지정된다) 이것은 전후 여러 번의 디버깅을 할 때 분석 결과보다 약간의 번거로움을 초래한다. 이 문제를 해결하려면 두 가지 방법이 있다.방법1: dll 파일PE 헤더의 ImageBase를 직접 수정하면 사용할 수 없는 주소입니다.그러나 이 방법은 작은 한계가 있다. 바로 일부 파일은 검사가 존재하고 파일을 고친 후에 문제가 생길 수 있다. 예를 들어 불러오기를 거부하는 것과 같은 것이다.이런 상황은 두 번째 방법을 써야 한다.
방법2: dll의 마운트 주소를 동적으로 수정합니다
물론, 우선 dll의 마운트 주소가 어디에 결정되었는지 알아야 한다.다음은 dll의 불러오는 과정입니다
kernel32!LoadlibraryA
->kernel32!LoadLibraryExA
->kernel32!LoadLibraryExW
->ntdll!LdrLoadDll
->ntdll!LdrpLoadDll
->ntdll!LdrpMapDll
->ntdll!LdrpCreateDllSection
->ntdll!ZwOpenFile  //      
->ntdll!ZwCreateSection //    
->ntdll!ZwMapViewOfSection //  

 
관건은 바로 이 단계를 비추는 것이다. 함수 원형은 다음과 같다.
NTSTATUS 
  ZwMapViewOfSection(
    IN HANDLE  SectionHandle,
    IN HANDLE  ProcessHandle,
    IN OUT PVOID *BaseAddress,
    IN ULONG_PTR  ZeroBits,
    IN SIZE_T  CommitSize,
    IN OUT PLARGE_INTEGER  SectionOffset  OPTIONAL,
    IN OUT PSIZE_T  ViewSize,
    IN SECTION_INHERIT  InheritDisposition,
    IN ULONG  AllocationType,
    IN ULONG  Win32Protect
    );

세 번째 매개변수는 매핑할 기본 주소입니다. 이 매개변수에 대해 MSDN에는 BaseAddress Pointer to a variable that receives the base address of the view라는 설명이 있습니다.If the value of this parameter is not NULL, the view is allocated starting at the specified virtual address rounded down to the next 64-kilobyte address boundary.
즉, 만약에 이 매개 변수가 NULL이 아니라면 이 주소를 뒤로 정렬한 후 기본 주소로 하고 시스템이 dll을 불러올 때 이 함수를 호출할 때 매개 변수가 가리키는 값은 0이다. 즉, 스스로 빈 주소를 분배하는 것이다. 우리는 여기에 이 함수를 연결하기만 하면 된다. 목표 dll이 불러올 때 이 값을 NULL로 설정하지 않으면 분배되지 않은 고정 주소를 가리키게 된다.예를 들어 0x60000000 같은 거~ 이 갈고리는 링3에서도 할 수 있고 링0에서도 할 수 있지만 링3에서는 갈고리를 잡은 dll이 목표 dll 전에 불러오는 것을 보증해야 하기 때문에 아예 링0으로 하겠습니다.
 
if(PreviousMode == UserMode &&    dll) { *BaseAddress = 0x60000000 ;//       } return OriginalZwMapViewOfSection(SectionHandle,ProcessHandle,BaseAddress...);

ZwMapViewOfSection의 Hook 함수에서 목표 dll인지 아닌지를 판단하려면 하나의 SectionHandle 매개 변수만 사용할 수 있지만 하나의 SectionHandle만으로는 어느 dll인지 판단하기 어렵다. (ring0은 SectionObject.Segment.ControlArea.FilePointer를 직접 추출하여 판단할 수 있고 비교적 정확하다) 내가 사용하는 방법은 ZwQuerySection이 문단의 SectionImageInformation 정보를 조회한 다음에 ImageFileSize를 취하여 판단하는 것이다.이 ImageFileSize는 목표 dll의 실제 파일 크기입니다. 이 방법은 링3과 링0을 모두 사용할 수 있습니다. 판단에 문제가 크지 않지만 절대적으로 정확하려면 ZwCreate Section 때의 FileHandle과 결합하여 판단하는 것이 좋습니다.

좋은 웹페이지 즐겨찾기