ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DLL 인젝션
    HACK!!/Reversing 2016.08.07 16:53

    DLL(Dynamic Linked Library)

    DLL은 동적 링크 라이브러리의 약자로 다른 프로그램에서 사용하는 함수들을 모아둔 것이다.


    DLL Injection

    DLL injection은 실행 중인 다른 프로세스에 특정 DLL을 강제로 삽입하는 것이다.

    LoadLibrary()를 스스로 호출하도록 명령하여 사용자가 원하는 DLL을 로딩하는 것이다.

    DLL injection과 DLL loading이 다른 점은 로딩 대상이 프로세스가 내 자신이냐 아님 다른 프로세스냐 하는 것이다. 프로세스에 DLL이 로딩되면 자동으로 DllMain() 함수가 실행된다. 


    DLL injection 구현 방법

    • 원격 스레드 생성(CreateRemoteThread() API)
    • 레지스트리 이용(AppInit_DLLs 값)
    • 메시지 후킹(SetWindowsHookEx() API)



    practice

    test.zip

    tory.7z

    tory.7z은 인젝터가 들어있고 test.zip은 dll 파일과 계산기가 들어있다.


    먼저 계산기의 PID는 1736이다.


    정상적인 계산기의 모습


    인젝터를 켜고 삽입할 딜과 PID를 적는다.

    정상적으로 삽입이 된걸 볼 수 있다.

    한글로 숫자가 출력되는걸 볼 수 있다.


    방법1


    1
    h_process = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, int(pid))
    cs

    우선 OpenProcess()를 사용해 PROCESS_ALL_ACCESS 권한의 calc.exe 프로세스 핸들을 구한다.


    1
    arg_address = kernel32.VirtualAllocEx(h_process, 0, dll_len, VIRTUAL_MEM, PAGE_READWRITE)
    cs

    calc.exe에 로딩 할 DLL 파일의 경로를 알려줘야한다.

    그리고 메모리 공간을 할당한다. 공간은 DLL_경로 문자열 길이 만큼!


    1
    kernel32.WriteProcessMemory(h_process, arg_address, dll_path, dll_len, byref(written))

    cs

    앞에서 할당받은 버퍼 주소에 DLL의 경로 문자열을 쓴다.


    1
    2
    h_kernel32 = kernel32.GetModuleHandleA("kernel32.dll")
    h_loadlib = kernel32.GetProcAddress(h_kernel32, "LoadLibraryA")

    cs

    LoadLibrary()를 호출하기 위해 그 주소가 필요하다. 우리는 calc.exe의 로딩된 kernel32.dll의 LoadLibrary()의 시작 주소를 알아내야하는데 소스를 보면 인젝터에 로딩된 kernel32.dll의 LoadLibrary의 시작 주소를 얻어내고 있다. 만약 kernel32.dll이 프로세스마다 서로 다른 주소에 로딩된다면 위 소스는 잘못된 것이며 메모리 참조 오류가 발생할 것이다. 


    하지만 Windows운영체제에서 kernel32.dll은 프로세스마다 같은 주소에 로딩이 된다.

    DLL Injection 기법은 바로 위와 같이 OS 핵심 DLL이 자신만의 고유한 주소에 로딩되는 것을 보장해주는 Windows OS 특성을 이용한 기법이다.


    1
    kernel32.CreateRemoteThread(h_process, None, 0, h_loadlib, arg_address, 0, byref(thread_id))
    cs

    LoadLibaray()를 호출하도록 명령만 내리면 된다. 하지만 Windows에서는 그런 API를 제공하지 않는다. 그래서 CreateRemoteThread()를 사용한다. 이 API는 다른 프로세스에게 쓰레드를 실행시켜준다.

    API를 사용해 LoadLibrary()를 호출하다록 만든다.


    방법2

    이번 방법은 레지스트리를 이용하는 것이다. 윈도우에서 기본으로 제공하는 AppInit_DLLs와 LoadAppInit_DLLs라는 이름의 레지스트리 항목이 있는데 AppInit_DLLs에 인젝션을 원하는 DLL의 경로를 쓰고 LoadAppInit_DLLs의 값을 1로 변경한 후 재부팅하면 실행되는 모든 프로세스에 해당하는 DLL을 인젝션 해준다. 


    위 기법의 원리는 User32.dll이 프로세스에 로딩될 때 AppInit_DLLs항목을 읽어서 값이 존재하면 LoadLibrary를 이용하여 사용자 DLL을 로딩하는 것이다. 따라서 모든 프로세스가 아니라 user32.dll을 로딩하는 프로세스에만 해당되는 사항이다.


    방법3

    또 다른 방법으론 메시지 후킹이 있다. SetWindowsHookEx()를 이용하여 메시지 훅을 설치하면 OS에서 hook prcedure를 담고 있는 DLL을 프로세스에게 강제로 인젝션한다.





















    'HACK!! > Reversing' 카테고리의 다른 글

    upx unpacker  (6) 2017.03.20
    DLL 인젝션  (1) 2016.08.07
    [Reverse Lab 스터디] UPX PE 분석  (0) 2016.07.21
    MSDN ANNOTATIONS  (5) 2016.01.11

    댓글 1

Designed by Tistory.