2016년 10월 27일 목요일

미라이 봇넷(MIRAI BOTNET) Attack 분석


MIRAI BOTNET 


요새 MIRAI BOTNET이 한창 말이 많아서

과연 내 IoT 제품은 안전할까? 걱정되시는 분들이 많으실 것 같습니다.


그런데 벌써 MIRAI 소스코드가 다 공개되었기 때문에

MIRAI가 실제로 IoT 기기 공격을 어떻게 하는건지 분석했고

주요 부분만 간추려서 정리하였습니다.




일단 바쁘신 분들을 위해 결론만 적어보자면



MIRAI BOTNET에 취약한가?


1. 23번 포트(Telnet)를 쓰고 있다

2. ID/PW가 추측하기 쉽다.


이러면 기본적으로 MIRAI BOTNET 에 취약하다 볼 수 있습니다.

반대로 1, 2 둘 중 하나만 만족하지 않아도 MIRAI BOTNET에 취약하지 않습니다.



그러나 금방 변형이 등장할 것 이므로.....


해결책은?


1. 최대한 (특히 쉘을 제공하는) 포트를 열지 않는다.

2. 아이디 / 패스워드를 어렵고 길게 만든다.



정도가 되겠네요.


MIRAI -> IoT 기기 공격 분석입니다.



1. Injection

공격 방식은 아이디/패스워드 테이블에서 랜덤하게 뽑아서 대입해 보는 것으로,

Burpsuite 의 Intruder로 따지자면 Pitchfork 형태가 되겠습니다.


이 Parameter는 add_auth_entry("아이디", "패스워드", "가중치") 로 설정하는데,

가중치가 높을수록 공격시 랜덤으로 뽑힐 가능성이 높아집니다.



가장 가중치를 높게( 10 ) 설정 한 부분의 난독화를 풀면 

add_auth_entry("root", "xc3511", 10)  입니다.

아이디가 root이면서 패스워드가 xc3511 인 IoT 기기가 특히 많나 보네요.



2. Port



보시면 Packet Header 를 설정하는데, dest 는 23번 (Telnet) 포트로 고정하고,

src는 1024 이하에서 랜덤으로 설정합니다.

이 부분이 중요합니다. MIRAI BOTNET은 23번 포트만 스캐닝 합니다. 



1, 2 번이 끝나고 3번부터는 계속 루프를 돌면서 스캐닝을 합니다.



3. IP

IP는 랜덤하게 가져옵니다.

다만 정말 마구잡이로 랜덤하게 설정하는 것은 아닙니다.

아래처럼, 



Class별로 IP처럼 생긴 숫자만 뽑아서 랜덤하게 만듭니다.



4. Scan

이제 Syn Raw Packet을 만들어 쏘고, Syn +Ack 패킷 받는 걸 계속합니다.

방식은 하나씩 시도 해보는게 아니라

커넥션을 128개까지 만들어서 syn 패킷을 보내놓고,

한꺼번에 처리하는 방식입니다.



5. Attack

Connection이 성립하면 공격을 하는데,

이 부분을 BruteForce라고 부르기가... 좀 애매합니다.

왜냐하면 62개 정도 밖에 안되는 ID / PW 셋을 

모두 다 시도 해보는 것도 아니고 

아래처럼 가중치에 따라 랜덤하게 뽑아서 시도 해보기 때문입니다.






다만 Connection 이 살아있다면, 10번 정도 더 시도 해보긴 합니다.....







마치며...


일단 오늘 MIRAI Botnet 공격( MIRAI -> IoT )의 실체를 파헤쳐 보았는데요.

소스 코드를 보면 복잡하고 어려운 공격이라기 보다

최대한 빠르게 취약한 기기들을 장악하려는 제작자의 의도를 알 수 있습니다.






성공 후 감염은 어떻게 시키는 건지 

CNC 서버와 통신은 어떻게 하는건지 등등


더 볼만한 부분이 많습니다.

MIRAI의 소스는 다음 GitHub주소 에서 보실 수 있습니다.

https://github.com/jgamblin/Mirai-Source-Code



감사합니다.






2016년 10월 4일 화요일

[Android] Frida 사용해보기


입소문으로만 들었던 Frida. 직접 사용해 보기로 했다.
(프리더 아니고 프라다 아니다.)

이상하게도 한국에는 소개된 블로그가 없었다..


기본적으로 DBus 타고 PC쪽이 client, 앱쪽이 server 구조를 갖고 있다.

PC에서 스크립트를 작성해서 실행하면 된다.



다른 것보다 빌드가 제일 힘들었다... 프록시에.. VS2015... Python Path 공백 없어야 되고..
잘되던 nodejs npm 도 안되서 Python 등등 그냥 집에서  빌드 해서 가져 왔다.

바로 frida-ps 치면 에러가 나올텐데 chcp 65001 등으로 콘솔 코드 페이지 바꿔 줘야 한다.

-안드로이드-
인터넷에 영어로 찾아보면 다 있는 내용인데 정리해 본다.

원하는 앱을 실행시키고, {경로}/frida-server (예) /data/local/tmp/frida-server를 실행하면 된다.
윈도에서는 frida-trace -U -i open "원하는 패키지명" 하면 바인딩 된다

일단 프로세스에 Attach 하는 방법은, frida-ps 으로 pid 찾고,
frida -U -p {pid} Attach 하면 된다.
또는 app 이름 알면 앱으로 바로 Attatch 가능하다.
frida -U com.example.seccon2015.rock-paper-scissors

(실제 내가 해본 예제는 블로그에 올릴 수 없는 내용이라서...
글로만 서술했다. 죄송..)

아래는 인터넷에 돌아다니는 예제들인데,

작성 -> Attach 후 -> %load Examples.js 하면 앱 실행하면서 같이 돌아간다.




Hello SyntaxHighlighter

Examples.js

//http://blog.mdsec.co.uk/2015/04/instrumenting-android-applications-with.htmlD
alvik.perform(function () {
   
    var LockManager = Dalvik.use("com.github.orangegangsters.lollipin.lib.managers.LockManager");
    var LockManagerInstance = LockManager.getInstance();
    var AppLock = LockManagerInstance.getAppLock();
 
    for(var i=1230; i<1235; i++)
    {
            var result = AppLock.checkPasscode(i+"");
        send(i + ": " + result);
    }
});





/* Check if a Java/Dalvik/ART VM is available */
if (Java.available) {
    /* enumerate loaded classes */
    Java.enumerateLoadedClasses({
        /* when a class is found send it to the client */
        onMatch: function(className) {
            send(className);
        },
        /* when we are done enumerating classes send "done" to the client */
        onComplete: function() {
            send("done");
        }
    });
/* if a Java/Dalvik/ART VM is not available */
} else {
    send("Java not available in this process");
}



//https://cedricvb.be/post/seccon-2015-reverse-engineering-android-apk-2-400-writeup/#prettyPhoto
Dalvik.perform(function () {
    var c = Dalvik.use("kr.repo.h2spice.yekehtmai.c")
    c.a.implementation = function (str1, str2) {
        console.log("String1: " + str1)
        console.log("String2: " + str2)
    }
});





Java.perform(function () {
    // Function to hook is defined here
    var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');

    // Whenever button is clicked
    MainActivity.onClick.implementation = function (v) {
        // Show a message to know that the function got called
        send('onClick');

        // Call the original onClick handler
        this.onClick(v);

        // Set our values after running the original onClick handler
        this.m.value = 0;
        this.n.value = 1;
        this.cnt.value = 999;

        // Log to the console that it's done, and we should have the flag!
        console.log('Done:' + JSON.stringify(this.cnt));
    };
});



//https://gist.github.com/flankerhqd/c621f5aee06dad53e37c
Dalvik.perform(function () {
    var Activity = Dalvik.use("com.example.myapp.MyActivity");
    Activity.hookMe.overload("java.lang.String").implementation = function () {
        Activity.hookMe.overload("java.lang.String").call(args[0], "foo");//comment out this line won't crash
        return "foo";
    };
});
// This result in immediate crash
// Question: Is args[0] refer to this? How do I refer args, like accessing arg in hookMe?




//http://rotlogix.com/2015/09/13/defeating-ssl-pinning-in-coin-for-android/
Dalvik.perform(function () {

    var SSLPinning = Dalvik.use("com.onlycoin.android.secure.SSLPinning");

        SSLPinning.a.overload("android.content.Context", "[Ljava.lang.String;", "java.lang.String").implementation = function (c, s, ss) {
            send("SSLPinning");
            send(c.toString());
            send(s.toString());
            send(ss.toString());
            this.a.overload("android.content.Context", "[Ljava.lang.String;", "java.lang.String").call(this, c, s, ss);
        };

});




//http://www.welivesecurity.com/la-es/2016/02/04/instrumentando-apps-android-frida/




//https://github.com/frida/frida/issues/49
Dalvik.perform(function () {
var application = Dalvik.use("com.test.test").currentApplication();
var context = application.getApplicationContext();
var package_name = context.getPakcageName();
var package_info = context.getPackageManager().getPakcageInfo(package_info, 64);
send(package_info);
send(context):
send(package_name):
var sign = package_info.signatures[0];
send(signs);
});



2016년 8월 19일 금요일

[Batch] SO 파일에서 OpenSSL 버전 확인


안녕하세요.

So 파일에서 OpenSSL 버전을 확인해주는 배치 스크립트입니다.

버전은 0.9.8a ~ 1.0.2z 까지만 찾아줍니다.

검사가 끝나면 OpenSSL_result.txt 파일이 나옵니다.

제가 만들었고 라이센스 없습니다. 마음껏 쓰세요.


@echo off
rem VERSION SET
Title byOpenSSL 1.0.1
set MIN=98
set MAX=102
color 30
del /F /Q OpenSSL_result.txt >nul
del /F /Q OpenSSL_list.txt >nul
cls
echo --START-------------------------------------------------
findstr /SNM /C:"OpenSSL 0" *.so > OpenSSL_list.txt
findstr /SNM /C:"OpenSSL 1" *.so >> OpenSSL_list.txt
echo --DETECTED----------------------------------------------
echo.
type OpenSSL_list.txt
echo.
echo --DETECT Version----------------------------------------
for /f "delims=" %%i in (OpenSSL_list.txt) do call :GO_FOR %%i
:GO_FOR
 echo OpenSSL detected - %1
 set PRE=%MAX%
 set tmp=%1
 if NOT DEFINED tmp (
  color 70
  del /F /Q OpenSSL_list.txt
  echo.
  echo --RESULT------------------------------------------------
  echo.
  type OpenSSL_result.txt
  echo.
  echo --END---------------------------------------------------
  echo.
  pause >nul
  color
  exit
 )
 :NEXT

 if %PRE% LSS %MIN% (
  echo But There is no OpenSSL - Version 0.9.8a ~ 1.0.2z
  exit/b
 )

 if %PRE% LSS 100 (
  set FIRST=0
  set SECOND=%PRE:~0,1%
  set THIRD=%PRE:~1,1%
 ) ELSE (
  set FIRST=%PRE:~0,1%
  set SECOND=%PRE:~1,1%
  set THIRD=%PRE:~2,1%
 )

 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%a" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%a
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%a>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%b" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%b
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%b>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%c" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%c
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%c>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%d" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%d
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%d>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%e" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%e
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%e>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%f" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%f
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%f>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%g" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%g
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%g>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%h" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%h
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%h>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%i" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%i
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%i>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%j" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%j
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%j>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%k" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%k
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%k>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%l" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%l
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%l>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%m" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%m
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%m>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%n" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%n
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%n>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%o" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%o
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%o>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%p" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%p
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%p>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%q" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%q
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%q>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%r" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%r
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%r>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%s" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%s
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%s>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%t" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%t
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%t>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%u" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%u
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%u>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%v" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%v
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%v>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%w" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%w
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%w>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%x" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%x
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%x>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%y" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%y
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%y>>OpenSSL_result.txt
  exit/b
 )
 findstr /SNM /C:"OpenSSL %FIRST%.%SECOND%.%THIRD%z" %1>nul
 if %ERRORLEVEL% EQU 0 (
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%z
  echo %1 - OpenSSL %FIRST%.%SECOND%.%THIRD%z>>OpenSSL_result.txt
  exit/b
 )

 set /a PRE-=1
 goto NEXT

exit/b



2016년 6월 1일 수요일

Android Signing Verify( CERT.RSA, CERT.SF, MANIFEST.MF mean )



안드로이드를 보면 'Apk Signing' 이라는 말이 많이 나옵니다.

그리고 누구나 마켓에 앱을 올리기 위해 앱을 사이닝 합니다.

하지만 플랫폼이 어떤식으로 검증하는지는

실제로 잘 모르는 분들이 많습니다. 저 또한 안드로이드 보안 한다면서

대강만 알고 있었기에 이번에 제대로 정리합니다.


Apk Signing 을 하면 META-INF 폴더안에 3가지 파일이 생기는데,

CERT.RSA, CERT.SF, MANIFEST.MF 파일입니다.


먼저 MANIFEST.MF 파일을 보면 다음과 같은 구조로 되어있습니다.


Manifest-Version: 1.0
Created-By: 1.0 (Android SignApk)

Name: res/drawable-hdpi-v4/a.png
SHA1-Digest: 9N951JbaBqMwJu6neE80ZxknAaA=

Name: res/drawable-hdpi-v4/b.png
SHA1-Digest: aKuzkBMBNNlmgMu9Kfcl7CVk2Ec=


아시다시피 각 파일에 대한 해시값이 계산되어 기록되어있습니다.


CERT.SF 파일은 다음과 같은 구조로 되어있습니다.


Signature-Version: 1.0
Created-By: 1.0 (Android SignApk)
SHA1-Digest-Manifest: 7xpSMheWj+9cc+YiEZUoa52CaZc=

Name: res/drawable-hdpi-v4/a.png
SHA1-Digest: 5tNwzpVMTwTTh82YDhYYPnI7Ljc=

Name: res/drawable-hdpi-v4/b.png
SHA1-Digest: 5l/YxPScJe4eaks0aiKJHIwKrK4=


가장 윗 부분에는 MANIFEST.MF 에 대한 해시값이,
나머지는 MANIFEST.MF 에 기록되어있는 Name, SHA 값, \r\n 값까지 포함해서 3줄을 
해시한 값입니다.



CERT.RSA 에는 공개키와 주체 등이 적혀있고

동일한 앱 이름인데 다른 사이닝 키를 사용하면 충돌합니다.

여기까지는 대부분 아시는 부분입니다.



그런데 위 내용만 안다면 다음과 같은 의문이 생기게 됩니다.

해커가 hack.png 파일을 해시해서 MANIFEST.MF 와 CERT.SF 에 각각 계산해 넣고,

CERT.RSA를 그대로 둔다면....



네. 당연히 막히는데 이유는 다음과 같습니다.


CERT.SF 를 키스토어 개인키로 암호화 한 시그니쳐가 CERT.RSA에 기록되기 때문입니다.


그래서 안드로이드 플랫폼에서는 공개키로 CERT.RSA에 기록된 시그니쳐를 복호화 하고,

실제 CERT.SF 와 비교하는 방식으로 앱 검증을 하게 됩니다. 


이런 내용이 상세히 기록되어있는 블로그는 거의 없고.. 
그냥 앱을 사이닝해서 검증한다는식으로 얼버무리거나
'CERT.SF 내부의 암호화된 값들을 공개키를 이용하여 복호화 하고' 
같은 말도안되는 정보가 많아서 기록으로 남깁니다.




2016년 1월 22일 금요일

Android so file decompile & patch


-안드로이드 Native (C, C++) .so 파일 디컴파일 하기-

IDA와 Hex ray 가 필요하다. Hex ray는 코드를 잘 정리해서 보여주는데

이게 없으면 디컴파일이 한층 더 힘드니 있는게 좋다.


그리고 원래 IDA 에서 Edit - Patch program - Assemble 을 하면

어셈블리어를 쉽게 조작 할 수 있는데, 안드로이드 so파일에 시도하면

ARM 프로세서 모듈이라면서 안해준다.



그래서 어셈블리어 레벨에서 패치는 불가하고, 기계어 레벨 패치를 해야 한다.

근데 ARM 기계어는 잘 정리된 곳을 못 찾았고

내가 쓸 코드는 MOVS, CMP, BEQ, BNE 정도 밖에 안되서 그냥 노가다로 정리 했다.

--- MOVS R0 는 기계어로 0x20 ---

MOVS R0, #1 -> 1을 R0에 저장
0x01 0x20

MOVS R1, #0
0x00 0x21

MOVS R2, #0
0x00 0x22

MOVS R2, #0x10
0x10 0x22

MOVS R3, #0
0x00 0x23

MOVS R7 R4
0x27 0x1C

MOVS R0 R5
0x28 0x1C

--- CMP R0 는 기계어로 0x28 ---

CMP R0, #0 -> R0 가 0 이면 플래그 0
0x00 0x28

CMP R3, #0
0x00 0x2B

CMP R3, #6 -> R3 이 6 이면 플래그 0
0x06 0x2B

CMP R0, R3
0x98 0x42

---BEQ, BNE 는 각각 기계어로 0xd0, 0xd1---

BEQ loc_7E4C -> 플래그 값이 0이면 점프
0x07 0xD0

BNE loc_7E52 -> 플래그 값이 0이 아니면 점프
0x04 0xD1

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

다행히 기계어 코드 패치는 프로세서에 관계없이 IDA에서 가능하다.

Edit - Patch program - Change byte 하고 Apply patches to input file 을 하면 적용 된다.


이제 한번 시험삼아 도전해 본다.



저 네모박스를 다음과 같이 고칠 것이다.

1. MOVS R0, #0     //return 에 0 복사
2. CMP R0, #0       //return 값이 0이면 Flag 0
3. BEQ loc_ret        //Flag 0 이면 loc_ret 로 이동 (loc_ret은 임시로 붙인 이름)


그럼 리턴값에 0을 넣고 특정 위치로 점프한다.

단순히 NOP로 채운게 아니라서 다시 복구하거나 다른 곳으로 점프시키기도 쉽다.


먼저 1, 2번을 아까 노가다로 알아낸 기계어로 패치하면 다음과 같다.



이제 3번 BEQ점프를 하면 되는데 이것도 단순히 주소를 빼면 안되서

직접 한칸 두칸 점프해 보면서 식을 구해 보았다.

X = (목적지 주소 출발지 주소 – 2)/2 - 1 


나는 00007E2A 에서 00007F1A 로 점프할거니까 위 식으로 계산해보면 0x76 이 나온다.



기계어 코드 패치하고 그래프를 확인 해 보면 새로운 분기가 생긴 것을 확인 해 볼 수 있다.




처음 해 보는거라 뭔가 노가다가 많이 들어갔지만 나름 재미있었고 유용할 것 같다.



2016년 1월 20일 수요일

APK to Java in Node.js


Node.js 에서 APK 파일을 읽어서 Java 파일로 만들어 줍니다.

js 파일과 같은 위치에 programs 폴더가 있어야 하고

그 안에 7-Zip, dex2jar-2.0, jd-cli-0.9.1 프로그램이 있어야 하고

apk, sources 폴더가 있어야 합니다.

apk 폴더 안에 풀고 싶은 apk 파일을 넣고 인자로 주면 sources에 풀립니다.

제가 만들었고 라이센스 없습니다.


Hello SyntaxHighlighter

apk2java

exports.apk2java = function(apkName){

var nodePath=process.cwd();
var programsPath=nodePath+"\\programs";
const exec = require('child_process').exec;


var d = new Date();
var folderName=d.getTime();
var srcPath=programsPath+"\\sources\\"+folderName;
 
 console.log("Start APK -> Zip -> dex");
 exec(programsPath+"\\7-Zip\\7z.exe x \""+programsPath+"\\apk\\"+apkName+"\" -y -o"+srcPath, (err, stdout, stderr) => {
  if (err) {
   console.error(err);
   console.log("End - Fail.");
   return;
  }
  if(stderr){
   console.log("stderr");
   //console.error(stderr);
  } 
   console.log("Start APK -> Zip -> dex -> jar");
   exec(programsPath+"\\dex2jar-2.0\\d2j-dex2jar.bat "+srcPath+"\\classes.dex "+"-o "+srcPath+"\\classes.jar", (err, stdout, stderr) => {
  if (err) {
   console.log("err");
   console.error(err);
   console.log("End - Fail.");
   return;
  }  
  if(stderr){
   console.log("stderr");
   //console.error(stderr);
  } 
  console.log("Start APK -> Zip -> dex -> jar -> java");
  exec("java -jar "+programsPath+"\\jd-cli-0.9.1\\jd-cli.jar -od "+srcPath+"\\javaSrc "+srcPath+"\\classes.jar", (err, stdout, stderr) => {
   if (err) {
    console.error(err);
    console.log("End - Fail.");
    return;
   }  
   if(stderr){
    console.log("stderr");
   } 
   //console.log(stdout);
   console.log("End - Success.");
   
  });
   });
 });
}

2016년 1월 8일 금요일

MITM을 위한 Proxy 설정방법


ARP Spoofing이 안되는 경우 ( 정책 상 Blocking 되는 경우)

iptables를 이용하면 됩니다.

iptables -t nat -A OUTPUT -p tcp -o wlan0 -j DNAT --to ip:port

주의 할 것은, 모든 tcp 통신을 포워딩 하기 때문에

DNS 쿼리도 이곳으로 날리게 됩니다.

따라서 먼저 한번 접속해서 도메인 이름을 알도록 하거나

--dports 80,443 등 옵션을 추가해 주는 것이 좋습니다.


2016년 1월 4일 월요일

Network Ping Batch

네트워크 상태를 시각적으로 보여주는 배치파일입니다.

제가 만들었고 라이센스 없습니다.

---------------------------------------------------------------
@echo off
title Bye. by B.Y.
:start
mkdir C:\PT
set t=%time:~-5%
set pingIP=168.126.63.1
set cnt=0
:re
set /a cnt+=1
cls
echo -^> %pingIP%
if %cnt% EQU 1 echo State : /
if %cnt% EQU 2 echo State : ─
if %cnt% EQU 3 echo State : \
if %cnt% EQU 4 (
echo State : │
set cnt=0
)
ping %pingIP% -n 2 | find /c "%pingIP%의 응답: 바이트=" >C:\PT\%t%.txt
set /p a=del /f C:\PT\%t%.txt
if %a% GEQ 1 color 03
if %a% EQU 0 color 04
goto re

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





아래는 ICMP 스캔입니다. 192.168.0 까지 입력하면
192.168.0.1 ~ 192.168.0.255 까지 스캔 해 줍니다.
---------------------------------------------------------------

@echo off
set a=1
echo 스캔을 원하는 아이피 대역
set /p ip=
:start
ping %ip%.%a% -n 1 | find "의 응답" >> scan.txt
echo ping to %ip%.%a%
set /A a+=1
if %a% NEQ 255 goto start
:end