2013-07-27 8 views
2

특정 명령어의 메모리 내 주소 (악용 쓰기 용)는 어떻게 찾을 수 있습니까?DLL에서 특정 명령어의 메모리 내 주소를 찾는 방법

특히 을 가리킬 수있는 주소가없는 서비스 팩이없는 Windows XP의 user32.dll에서 call ebp 명령어를 찾고 있습니다. 나는 Immunity DebuggerOllyDBG을 대상에 설치했습니다.

+0

음, DLL은 재배치 (그리고 _are 이전 being_) 그래서 당신은 단지 이제까지의 모듈의 기본 주소와 같은 주소 상대를 찾을 수 있습니다 신뢰할 수있는 방식으로. – Damon

+0

@Damon은 모든 최신 OS에 해당하지만 Windows XP에서는 ASLR이 없기 때문에 DLL의 메모리 내 위치는 OS 버전과 SP 버전간에 매우 일치합니다. –

+0

ASLR에 대해서도 생각조차하지 못했지만, 그것은 물론 다른 문제 일 것입니다. 일상적으로 발생하는 일반적인 DLL 리베이스를 생각하고있었습니다. 모든 DLL은 대개 동일한 기본 주소를가집니다 (링커에게 임의의 주소를 선택하도록 지시 할 수는 있지만 주소 공간을 더욱더 파편화합니다 ...).로드 될 때 리베이스됩니다. 첫 번째 DLL은 대개 원래 주소에로드 된 kernel32입니다. 그런 다음 일반적으로 NLS이고 다른 모든 DLL (user32 포함)은 모두 재배치됩니다. 부수적으로 그들은 매번 같은 주소로 끝날 수도 있지만 누가 알 수 있습니다. – Damon

답변

6

명령어를 찾으려면 코드, .text 섹션이 시작하고 끝나는 위치를 파악한 다음 DLL을로드하고 지침을 찾을 때까지 라이너 검색을 수행해야합니다.

// test.c 
// gcc -Wall -shared test.c -o test.dll 
#include <stdio.h> 

__declspec(dllexport) void test(void) { 
    asm("call *%ebp"); 
    puts("test"); 
    asm("call *%ebp"); 
} 

를 컴파일하고 올리 디버그에서 DLL을로드하고 을 클릭 CTRL + FCALL EBP 검색 :

6BEC125A |. FFD5   CALL EBP 
6BEC125C |. C70424 6430EC6> MOV DWORD PTR SS:[ESP],test.6BEC3064 ; |ASCII "test" 
6BEC1263 |. E8 74060000  CALL <JMP.&msvcrt.puts>    ; \puts 
6BEC1268 |. FFD5   CALL EBP 
다음

우리는 두 call ebp 지침을 가지고 테스트 DLL을

첫 번째 지침의 주소는 0x6bec125a이고 두 번째 주소는 0x6bec1268입니다. call ebp의 opcode는 0xff 0xd5이므로이를 기억하십시오.

이제 우리는 당신이 -h와 objdump를 사용할 수있는 코드의 경계를 찾을 필요가 :

> objdump --headers test.dll 

test.dll:  file format pei-i386 

Sections: 
Idx Name   Size  VMA  LMA  File off Algn 
    0 .text   00000984 6bec1000 6bec1000 00000600 2**2 
        CONTENTS, ALLOC, LOAD, READONLY, CODE, DATA 

    1 .data   00000008 6bec2000 6bec2000 00001000 2**2 
        CONTENTS, ALLOC, LOAD, DATA 

    2 .rdata  0000011c 6bec3000 6bec3000 00001200 2**2 
        CONTENTS, ALLOC, LOAD, READONLY, DATA 
    .... 

> 

코드는 VMA, 가상 메모리 주소, 0x6bec1000에서 시작하고 끝나는 때문에 그 크기는 0x984입니다 0x6bec1000 + 0x984 = 0x6bec1984는 같이

0x6bec1000 
.... 
what is between are the DLL instructions 
.... 
0x6bec1984 

나는 지금까지 분명 바랍니다.

우리는 우리의 call ebp 스캐너를 코딩 할 경우

, 우리는 흐르는을 수행해야합니다
  1. 는 PE의 정보를 읽고 얻을 실행 섹션 정보, 일반적으로 .text를 상대 주소와 가상 크기를 찾을 수 있습니다.
  2. LoadLibrary을 사용하여 DLL을로드하면 DLL의 기본 주소가 반환됩니다.
  3. 코드 섹션의 시작 부분의 가상 주소는 다음과 같습니다. DLL 기본 주소 + 코드 섹션 virtualAddress 및 DLL 기본 주소 + 코드 섹션 virtualAddress + VirtualSize에서 끝납니다.
  4. 이제 우리는 코드를 반복하여 0xff 0xd5, call ebp의 opcode, 간단한 라이너 검색을 찾을 준비가되었습니다.

    > gcc -Wall findopcode.c -o findopcode 
    > findopcode.exe test.dll 
    [*] Code section: `.text' 
    [*] Base address : 0x6bec0000 
    [*] Start address: 0x6bec1000 
    [*] End address : 0x6bec1984 
    [*] Found `call ebp` at: 0x6bec125a 
    [*] Found `call ebp` at: 0x6bec1268 
    
    > 
    

    그것은 꽤 잘,의는 user32.dll을 해보자 작품 :

    > findopcode.exe \Windows\System32\user32.dll 
    [*] Code section: `.text' 
    [*] Base address : 0x75680000 
    [*] Start address: 0x75681000 
    [*] End address : 0x756e86ef 
    [*] Found `call ebp` at: 0x756b49b5 
    
    > 
    

    // findopcode.c 
    // gcc -Wall findopcode.c -o findopcode 
    
    #include <windows.h> 
    #include <stdio.h> 
    #include <string.h> 
    
    int main(int argc, char **argv) { 
        const char opcode[] = {0xff, 0xd5}; // The opcode of `call ebp' 
        FILE *dllFile; 
        HMODULE dllHandle; 
    
        IMAGE_DOS_HEADER dosHeader; 
        IMAGE_NT_HEADERS NtHeaders; 
        IMAGE_SECTION_HEADER sectionHeader; 
    
        unsigned int i; 
        unsigned char *starAddr; 
        unsigned char *endAddr; 
    
        if(argc < 2) { 
         printf("usage: %s [DLL]\n", argv[0]); 
         return -1; 
        } 
    
        if((dllFile = fopen(argv[1], "rb")) == NULL) { 
         perror("[!] Error"); 
         return -1; 
        } 
    
        // Read the basic PE headers 
        fread(&dosHeader, sizeof(dosHeader), 1, dllFile); 
        fseek(dllFile, dosHeader.e_lfanew, SEEK_SET); 
        fread(&NtHeaders, sizeof(NtHeaders), 1, dllFile); 
    
        // Search for the executable section, .text section. 
        for(i = 0 ; i < NtHeaders.FileHeader.NumberOfSections ; i++) { 
         fread(&sectionHeader, sizeof(sectionHeader), 1, dllFile); 
         // If we found a section that contains executable code, 
         // we found our code setion. 
         if((sectionHeader.Characteristics & IMAGE_SCN_CNT_CODE) != 0) { 
          printf("[*] Code section: `%s'\n", sectionHeader.Name); 
          break; 
         } 
        } 
    
        fclose(dllFile); 
    
        // Load the DLL to get it's base address 
        if((dllHandle = LoadLibraryA(argv[1])) == NULL) { 
         printf("[!] Error: loading the DLL, 0x%.8x\n", (unsigned int) GetLastError()); 
         return -1; 
        } 
    
        // The code start at : base address + code virtual address 
        starAddr = (unsigned char *) dllHandle + sectionHeader.VirtualAddress; 
        // It ends at : base address + code virtual address + virtual size 
        endAddr = (unsigned char *) starAddr + sectionHeader.Misc.VirtualSize; 
    
        printf("[*] Base address : 0x%.8x\n", (unsigned int) dllHandle); 
        printf("[*] Start address: 0x%.8x\n", (unsigned int) starAddr); 
        printf("[*] End address : 0x%.8x\n", (unsigned int) endAddr); 
    
        // Simple liner search, when ever we find `0xff 0xd5' we print that address 
        for(endAddr -= sizeof(opcode) ; starAddr < endAddr ; starAddr++) { 
         if(memcmp(&opcode, (void *) starAddr, sizeof(opcode)) == 0) { 
          printf("[*] Found `call ebp` at: 0x%.8x\n", (unsigned int) starAddr); 
         } 
        } 
    
        FreeLibrary(dllHandle); 
        return 0; 
    } 
    

    를 컴파일하고 DLL로 테스트 : 여기

은 간단한 구현

난 하나만 찾았습니다 call ebp a t 0x756b49b5. 당신은 몇 가지 이상한 액세스 할 수있는 몇 가지 영역을 치면

 if(IsBadReadPtr(starAddr, sizeof(opcode)) == 0 && 
      memcmp(&opcode, (void *) starAddr, sizeof(opcode)) == 0) { 

그래서 프로그램이 실패하지 않습니다 : 당신이 방법 당신은 memcmpIsBadReadPtr를 사용하여 읽기 전에 읽기 액세스 권한이 있는지 확인하고자합니다.

+2

와우! 우수 답변. 매우 유익하고 유익한 정보. 정말 고맙습니다! –

0

다른 방법은에서 msfpescan을 사용하는 것입니다 metasploit framework :

msfpescan -j ebp user32.dll