DBI on Android - ADBI(Android Dynamic Binary Instrumentation)







  • DBI(Dynamic Binary Instrumentation)
   동적으로 바이너리에 코드를 삽입하여 실행하는 것을 말한다. 이를 통해 소스코드를 수정하지 않고도 API Trace, 인자값 조작 및 리턴값 조작,
    이외에도 다양한 동적 조작을 할 수 있다. DBI를 구현하는 방법은 여러가지가 있겠지만 내가 알고 있는 방법은(혹은 본 것은) 후킹과 에뮬레이션이다.
    후킹이든 에뮬레이션이든 조사 혹은 조작하길 바라는 시점에서 코드 흐름을 변경하여 원하는 조사 혹은 조작을 한 뒤 원래 코드 흐름으로 돌려주는 것이다.
    리버싱을 할 때 쉽게 분석을 할 수 있도록 도와주며, 취약점 분석 측면에서도 큰 도움을 줄 수 있다. 이번 포스팅에서는 분석(Trace)를 위주로 할 것이다.
  


  • ADBI(the Android Dynamic Binary Instrumentation toolkit)


     안드로이드 환경에서 DBI를 하기 위한 툴킷으로, crmulliner 라는 사람이 만들었으며 github 에 공개해 놓았다. 코드를 살펴보니, 

     후킹을 통해 구현해 놓았고, 예제 소스를 보고 직접 라이브러리(.so)를 만들어서 타겟 프로그램에 인젝션 하는 방식으로 동작한다. 

     조사 혹은 조작할 함수의 앞 뒤에서 직접 C언어로 프로그래밍을 하면 된다. 후킹 방식은 대상 함수의 첫줄을 변조하여 후킹함수로

     점프하여 조작을 수행하는 방식으로 되어있다. 사용자는 후킹함수 내에서 조작을 하거나 값을 조사한 뒤 대상 원본 함수를 후킹할

     수도, 아예 호출을 하지 않고 임의의 값을 리턴할 수도 있다. 





 1. 설치


  adbi 를 사용하기 위해서는 먼저 ndk 가 필요하다. ARM 크로스 컴파일 시 ndk 를 이용하기 때문이다.



1) ndk 설치


  아래 다운로드 페이지에서 자신의 OS 환경에 맞는 버전을 다운로드 하도록 하자. 


  http://developer.android.com/intl/ko/ndk/downloads/index.html

  

 


    설명에도 나와있듯이 다운로드한 파일에 실행권한을 주고 실행만 해 주면 설치는 끝이 난다.






2) adbi 설치


   # git clone https://github.com/crmulliner/adbi


  



 


2. 예제 소스코드 분석


  본격적으로 adbi 를 사용해보기 전에 먼저 소스코드를 분석해 보면서 원리를 파악해 보도록 하자.



hyunmini$ tree ./

./

├── README.md

├── build.sh                               // 컴파일 스크립트

├── clean.sh                               // 초기화(컴파일 이전으로 복구)

├── hijack

│   ├── hijack.c                         // 라이브러리 인젝션 소스

│   └── jni

│       └── Android.mk

└── instruments

    ├── base

    │   ├── base.c

    │   ├── base.h

    │   ├── hook.c                     // 후킹 소스

    │   ├── hook.h

    │   ├── jni

    │   │   ├── Android.mk

    │   │   └── Application.mk

    │   ├── util.c

    │   └── util.h

    └── example

        ├── epoll.c                          // instrument 예제 소스

        ├── epoll_arm.c                  // instrument 예제 소스

        └── jni

            └── Android.mk




  

1) hijack.c   -  라이브러리 인젝션 소스



윈도우 운영체제에서는 DLL 인젝션을 통해 주로 타 프로세스를 조작했는데, 마찬가지 개념으로 *nix 계열 운영체제에서는 so 인젝션을 통해 

타 프로세스를 조작할 수 있다. hijack.c 소스코드는 바로 이러한 라이브러리 인젝션을 수행해 주는 코드이다.


라이브러리 인젝션을 위해서 hijack.c 에서는 아래와 같은 방법을 사용한다. 윈도우 DLL 인젝션과 거의 동일하다.



    (1)  PTRACE 를 이용하여 현재 컨텍스트(레지스트리 등의 정보)를 구한다. 이후 대부분의 과정에서 PTRACE API 를 이용한다.


    (2)  인젝션 하려는 라이브러리 이름을 스택 메모리에 쓴다.


    (3)  쉘코드(dlopen() 함수를 실행하는)를 스택메모리에 쓴다.


    (4)  mprotect() 를 호출하여 스택에 실행권한을 부여한다.


    (5)  pc 레지스터를  스택의 쉘코드의 주소로 변경하여 dlopen() 함수를 강제로 호출한다. 


    (6)  라이브러리가 대상 프로세스에 강제로 로드되며 후킹 코드가 실행된다.




코드 중 중요한 부분만 살펴 보도록 하자.  조금 내려가다 보면 쉘코드가 보인다. 단순히 레지스터에 스택의 값을 넣어 주는 역할만 한다.



[그림] dlopen 을 실행해 주는 간단한 쉘코드



nop 로 비어있는 부분에는 호출에 필요한 인자값에 맞춰 각각의 값을 넣어주게 된다. 이때도 PTRACE 를 이용하게 된다. 


아래로 조금만 더 내려가 보면 메인함수가 시작되고, 아래와 같이 dlopen() 함수의 주소를 구하는 부분이 나온다.



[그림] 동적으로 dlopen 주소 얻기


 linker 프로세스에서 


(작성중)









+ Recent posts