IAT 구조 분석

12057 단어 PE 구조

IAT 구조 분석


IAT 소개


호환 문제를 해결하려면 다른 버전의 Windows 운영체제와 DLL 버전에서도 정상적으로 작동할 수 있도록 조치를 취해야 한다.
IAT(Import Address Table: 함수 주소표 입력)가 필요합니다.

IAT 포지셔닝


수공 찾기

  • PEview를 이용하여 프로그램을 찾은 NT 헤더의 선택할 수 있는 헤더에 import table가 있습니다. 여기에 RVA가 기록되어 있습니다.
  • 구조체에 따른 IMAGEIMPORT_DESCRIPTOR은 가져오기 테이블 구조에서 dll 이름과 IAT 테이블을 결정하는
  • typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    
         union {
    
              DWORD Characteristics;         
    
              DWORD OriginalFirstThunk;//          (INT), RVA   IMAGE_THUNK_DATA   0x01b218
    
         };
    
          DWORD TimeDateStamp;//    ,   0      
    
          DWORD ForwarderChain;//   0      
    
          DWORD Name;//  DLL    RVA              
    
          DWORD FirstThunk;//          (IAT) RVA,IAT   IMAGE_THUNK_DATA      0x01b000  0x01b3e0
    
    } IMAGE_IMPORT_DESCRIPTOR;
    
  • IAT표의 지침에 따라 가져온 함수의 서수와 이 함수의 이름을 찾습니다
  • typedef struct _IMAGE_IMPORT_BY_NAME {
    
         WORD Hint;         //        
    
         BYTE Name[1];      //       
    
    } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
    

    프로그램 구현

    #include
    #include
    BOOL ImportAddressTablefind(IN HMODULE hModule)
    {
    	IMAGE_DOS_HEADER* pImageDosHearder = (IMAGE_DOS_HEADER*)hModule;
    	IMAGE_OPTIONAL_HEADER* pImageOptionalHeader = (IMAGE_OPTIONAL_HEADER*)((DWORD)hModule + pImageDosHearder->e_lfanew + 24);//        
    	IMAGE_IMPORT_DESCRIPTOR* pImageImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)
    		((DWORD)hModule + pImageOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);//     
    
    	while (pImageImportDescriptor != 0)
    	{
    		LPCSTR base = (PSTR)(PBYTE)GetModuleHandle(NULL);
    		LPCSTR pszModName = (PSTR)(base + pImageImportDescriptor->Name);//          
    		IMAGE_THUNK_DATA* pImageThunkData = (IMAGE_THUNK_DATA*)((DWORD)hModule + pImageImportDescriptor->FirstThunk);//         IAT    0x1b000
    		IMAGE_IMPORT_BY_NAME ** Original =(IMAGE_IMPORT_BY_NAME **) ((DWORD)hModule + pImageImportDescriptor->OriginalFirstThunk);//  0x1b214//0x
    		while (pImageThunkData->u1.Function)
    		{
    			
    			unsigned int fun = (unsigned int)(PBYTE)(*Original)->Name;
    			LPCSTR funcname =base+ fun;
    			LPDWORD lpFunctionAddress = (LPDWORD)&(pImageThunkData->u1.Function);
    			__try
    			{
    				printf("dllname:%s funcname:%s addr:%x
    "
    , pszModName, funcname, *lpFunctionAddress); } __except (1) { system("pause"); } pImageThunkData++; *Original++; } pImageImportDescriptor++; } return true; } int main() { ImportAddressTablefind(::GetModuleHandle(NULL)); system("pause"); }

    IAT 셸 제거 복구


    까닭


    Google은 OD를 이용하여 직접 dump를 실행합니다. 이 때 가져오기 테이블에 따라 IAT 바늘을 찾았는데 바늘이 0인 것을 발견했습니다.하지만 탈피가 끝났을 때 IAT 주소는 이미 적혀 있었다.만약 우리가 직접 dump에서 프로그램을 실행한다면, INT 포인터가 부족하기 때문에 프로그램은 틀림없이 실행할 수 없을 것이다.

    복구


    처음에 도구인 ImpREC를 이용하여 IAT를 자동으로 찾았는데 IAT가 약간 틀렸습니다. OD에 따라 정확한 IAT 표를 찾은 RVA와 size는 마지막에 OEP가 있었습니다. 그러나 두 개의 잘못된 바늘이 더 나왔습니다. 동적 링크 라이브러리 함수 주소가 아닌 것을 보고 삭제하면 됩니다.

    수정된 PE 구조


    프로그램이 새 구간을 만들었습니다. 프로그램의 가져오기 테이블과 가져오기 테이블이 이 구간에 있고 INT는 0이 아닙니다. 구조체입니다IMAGE_IMPORT_BY_NAME의 이중 포인터입니다.이렇게 하면 IAT에 다시 값을 부여할 수 있습니다.

    PE 재배치


    일부 프로그램이 ASLR을 켰기 때문에 IAT를 이용할 때의 주소도 로드 기지의 변화에 따라 달라지고, 하드코딩이 프로그램의 메모리 주소가 현재 로드 주소의 변화에 따라 바뀌는 처리가 바로 재배치이다.
    재배치 테이블은 일반적으로 선택 가능한 헤더의 BASE RELOCATION TABLE에 위치하는데 이것은 하드코딩 주소의 편이를 기록하는 목록이다.그 중에서 표의 앞의 두 개는 기준 주소와 크기 뒤의 typeoffset이다.
    type은 4비트,offset은 12비트,offset+기준주소+프로그램기지=프로그램에서 하드코딩을 바꿀VA
    참조 링크https://www.xuepojie.com/thread-5155-1-1.html https://www.xuepojie.com/forum.php?mod=viewthread&tid=5156&highlight=%B5%DA%C8%FD%CA%AE%CB%C4%D5%C2-

    좋은 웹페이지 즐겨찾기