지난 포스팅(DVIA Jailbreak Detection 1)에 이어서 포스팅하겠습니다.

 

Jailbreak Test 1만 우회를 했었고, Jailbreak Test2 로직 분석 및 우회를 하겠습니다.

 

IDA로 실행파일을 뜯어보면,

 

jailbreak Test2 Tapped:라는 함수를 확인할 수 있습니다. 여기서 탈옥 여부 확인 후 showAlertForJailbreakTestisJailbroken 함수에서 Alert띄워주는 것 같네요.

 

인자로 boolean형을 받고 리턴타입은 없는 것을 확인할 수 있습니다.

 

인자로받은 값을 이용해서 탈옥폰인지 순정폰인지 Alert을 띄워주네요

 

그럼 Frida를 통해 인자값을 변조하도록 하겠습니다.

 

Frida 공홈에 들어가면 기본적으로 나와있는 소스인데, 해당 소스를 통해 앱이 가지고 있는 클래스명을 전부확인이 가능합니다.

 

실행시키면 다음과 같이 IDA에서 확인했던, Jailbreak클래스를 확인할 수 있습니다.

 

위에서 확인했던 클래스 내에 선언되어 있는 함수를 확인하는 소스입니다.

 

IDA에서 확인했던 jailbreakTest2Tapped:를 확인할 수 있네요.

 

이처럼 showAlertForJailbreakTestisJailbroken 함수를 찾아저 해당 함수명을 다 적어줘야 합니다.

앞뒤의 특수문자 - , : 까지 다 적어줘야 프리다에서 후킹이 가능합니다.(이부분에서 한참고생했네요...)

 

IDA에서 클래스 및 함수명까지 확인했는데 굳이 프리다로 또 찾아가는 이유는?

비교해 보면 IDA로 보는 함수명과 프리다로 출력한 함수명이 조금다른것을 볼 수 있는데요, 이 차이 때문에 Frida가 Method를 찾지 못하므로 정확하게 적어주셔야 합합니다.

 

결론적으로, showAlertForJailbreakTestIsJailbroken: 함수를 후킹하는 코드입니다.

 

다만, 후킹할때 args[2]를 변조했는데 IDA에서 확인한 함수 인자는 한개밖에 없었습니다.

이유는

Frida공홈에서 확인이 가능한데, args[2]부터가 실제 파라미터이고 0,1은 self,selector로 정의되어 있다고 합니다.

 

자세한 내용은 다음 블로그에서 확인이 가능합니다.

https://www.letmecompile.com/objective-c-런타임runtime-내부-동작-분석/

DVIA라는 iOS 점검 실습용이 있는데, 실습용으로도 좋고 평소 안드로이드만 하다보니 iOS이 너무 약해서 공부할겸 풀어보고 있는데 괜찮은 앱인 것 같아 포스팅하려 합니다.

 

http://damnvulnerableiosapp.com/

 

DVIA (Damn Vulnerable iOS App) - A vulnerable iOS app for pentesting

A vulnerable iOS app for pentesting

damnvulnerableiosapp.com

앱 다운로드 주소는 다음과 같고, 현재 v2까지 나와있는데 v1부터 풀어보도록 하겠습니다.

 

앱 설치 후에 왼쪽 상단 [Menu] - [Jailbreak Detection]으로 들어갑니다.

 

그럼 다음과 같은 화면을 볼 수 있는데, Jailbreak Test 1,2를 각각 클릭하면 탈옥여부를 탐지하여 Alert창을 띄워줍니다.

 

그럼 실행파일을 IDA를 통해 분석해보겠습니다.

함수명 중 "jail"이란 문자가 들어간 함수명을 검색했을 때 왼쪽상단과 같이 출력됩니다. Test1,2가 있는것으로 보아 각각 Test1,2를 클릭했을 때 실행되는 함수로 추측이 가능합니다.

 

소스코드 중 빨간 네모박스 위의 $OBJC_CLASS_$_DamnVulnerableAppUtilities의 isJailbroken함수로 넘어가네요.

 

즉, jailbreakTest1Tapped: 함수에서 isJailbroken함수를 호출하는 것을 알 수 있습니다.

 

isJailbroken함수를 살펴보면 bool return형을 가진 함수고 내부 탈옥탐지 로직을 확인할 수 있습니다.

위 사진에서는 Cydia.app만 보이지만 소스코드를 더 살펴보면 /bin/bash, apt, 등등이 있는지 확인하는 것을 알 수 있습니다.

 

그 후에 해당 파일이 존재하면 true(탈옥), 존재하지 않다면 false(미탈옥)을 리턴해서 탈옥여부를 확인합합니다.

 

Frida를 통해 리턴함수를 조작하여 탈옥탐지를 우회하도록 하겠습니다.

 

if (ObjC.available) {

try {
var className = "JailbreakDetectionVC";    # 후킹할 클래스 명
var funcName = "- isJailbroken";   # 후킹할 클래스 내 함수명(앞의 -도 적어주셔야 합니다.) 
var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');

 

Interceptor.attach(hook.implementation, {
onLeave
: function(retval) { console.log("[*] Class Name: " + className);  #onLeave함수를 통해 함수호출후 리턴값 조작 
console
.log("[*] Method Name: " + funcName);
console
.log("\t[-] Type of return value: " + typeof retval);
console
.log("\t[-] Original Return Value: " + retval);
newretval
= ptr("0x0")  
retval
.replace(newretval)   # true를 false로 변조하여 탈옥탐지 우회 시 
console
.log("\t[-] New Return Value: " + newretval) } });

}

catch(err) { console.log("[!] Exception2: " + err.message); } }

else { console.log("Objective-C Runtime is not available!"); }

위 소스파일을 js파일로 저장한 후, 파일을 저장한 경로에서 frida -U -l [js파일].js DVIA를 통해 실행하면

 

다음과 같이 탈옥탐지 우회가 가능합니다.

 

iOS는 Android와 다른 부분이 꽤 존재하는데 이부분때문에 상당히 시간이 많이 걸렸네요... 차후에 Try&Err과 주의점(?)도 포스팅 하겠습니다.

 

Frida가 Android는 자료가 많아지는데 iOS는 아직 많이 없는 것 같아 차근차근 올려보겠습니다.

 

 

출처 : https://blog.attify.com/bypass-jailbreak-detection-frida-ios-applications/

iOS에서 Frida를 통해 메모리 덤프를 할일이 있었는데요.

 

잘되던 Frida가 갑자기 iOS와 연결하자 Waiting for USB device to appear...만 뜨고 연결이 되질 않았습니다..ㅠ

 

Windows 10에서 Frida를 사용할때 생기는 일종의 버그아닌 버그라고 합니다. 맨처음 iOS단말을 연결할 때 자체 드라이버를 설치하여 나중에 itunes를 설치해도 windows10에서 설치한 드라이버가 남아서 그렇다고 합니다.

 

해결방법은 수동으로 삭제를 해줘야 해요.

 

https://blog.do9.kr/337

 

[Windows 10 Problem] Waiting for USB device to appear...

문제 발생 Windows 10에서 Frida를 USB를 통해 연결하여 사용하려고 할 때 다음과 같은 메시지 이후 정상적으로 동작하지 않는 문제가 있다. > frida-ps -U Waiting for USB device to appear... (-D 옵션을 이용..

blog.do9.kr

다음 사이트를 참고하여 해결했습니다.

 

해결 방법

1. [컴퓨터 관리] > [장치 관리자]

2. [범용 직렬 버스 장치]에 보면 [Apple Mobile Device USB Composite Device], [Apple Mobile Device USB Device] 디바이스 제거

(제거 시, 이 장치의 드라이버 소프트웨어도 삭제)

3. iTunes 설치 파일을 열어서(압축 프로그램 이용) AppleMobileDeviceSupport6464.msi 파일 실행하여 설치

4. 설치 후 장치 관리자 다시 확인해보면 [범용 직렬 버스 컨트롤러]에 [Apple Mobile Device USB Driver]가 추가됨을 확인

5. frida 다시 시도 및 정상 실행 확인

 

주의사항으로는 드라이버 삭제하실 때는 iOS단말을 연결해야 드라이버가 보이고, 삭제하고 단말을 다시 연결하시면 혹은 삭제후에 단말은 연결한 채로 재부팅하시면 windows에서 다시 자체 드라이버를 설치하므로 단말을 제거하고 itunes의 드라이버로 설치하셔야 합니다.

 

'Mobile' 카테고리의 다른 글

iOS 12 - 12.1.2 Jailbreak(with. Unc0ver)  (1) 2019.07.10
Can't connect to App. Have you connected the device?(with.Frida)  (0) 2019.05.08
Uncrackable3-2  (1) 2019.05.08
Ghidra Installation  (0) 2019.04.10
Android Burp 인증서 설치(Android 7.0)  (2) 2019.03.11

소켓으로 통신하는 앱의 경우, 어떻게 통신을 확인해야 할지 몰라서 이참에 Frida 코드를 작성해봤습니다.


일단 소켓의 경우 통신하는 IP/PORT를 확인해야 하므로 frida-trace를 이용해서 해당 어떤 함수를 후킹해야 하는지 확인해 보도록 하겠습니다.


frida-trace -U -i socket "[APP_NAME]"을 통해 생성되는 js파일에 이전 호출한 클래스 및 메소드를 확인하는 코드를 작성하여 어떤 클래스를 호출하는지 확인합니다.


※코드는 다음 포스트에 있는 코드를 사용했습니다.

https://taesun1114.tistory.com/entry/Android에서-호출한-ClassMethod-확인하기-with-Frida?category=729990


확인결과, java.net.Socket를 후킹하여 IP/PORT를 확인하면 될듯 합니다.



https://developer.android.com/reference/java/net/Socket에서 확인한 socket함수입니다.




예시로 사용한 앱은 다음과 같습니다. 별거 없이 버튼클릭하면 소켓을 발송하는 코드입니다.



후킹할 Frida code는 다음과 같습니다.



import sys
import frida

def on_message(message,data):
 print "[%s] -> %s" % (message, data)

PACKAGE_NAME = sys.argv[1]

jscode = """
Java.perform(function(){
 var sock = Java.use('java.net.Socket');

 console.log("Try to Hooking socket...");
 sock.$init.overload('java.lang.String','int').implementation = function(a,b){
  console.log(a.toString()+ " : " +b);
 };
});
"""
 
try:
 device = frida.get_usb_device()
 pid = device.spawn([PACKAGE_NAME])
 print("App is starting ... pid : {}".format(pid))
 process = device.attach(pid)
 device.resume(pid)
 script = process.create_script(jscode)
 script.on('message',on_message)
 print('[*] Running Frida')
 script.load()
 sys.stdin.read()
except Exception as e:
 print(e)



후킹 시, IP / PORT를 정상적으로 출력하는 것을 확인할 수 있습니다.


확인하기까지 상당히 어려웠는데.. 포스팅하다보니 별거 없네요...

$init을 써주는 부분에서 삽질을 많이 했네요


추가로, send 및 recv함수에 frida-trace를 이용해서 hexdump함수를 이용해서 통신내용을 확인할 수 있습니다.


'Mobile' 카테고리의 다른 글

Cydia 에러(Could not connect to the server)  (0) 2019.02.25
Android Method Trace(With.Frida)  (2) 2019.01.29
apktool first type is not attr  (0) 2018.10.04
Android Proxy Burp 인증서 설치  (2) 2018.09.15
Uncrackable3-1  (2) 2018.06.14

저번에 Uncrackable3를 도전했었는데 당시에 다운받았던 앱이 오류가 있었던 건지 실행하면 바로 종료가 되어 분석을 하지 못했는데


며칠전 다시 다운받아 설치해보니 이번엔 잘돌아가네요 :) (당시에 앱 자체의 오류가 맞았을까요....)



앱 실행 시 위와 같이 루팅감지되어 바로 종료가 됩니다


디컴파일 후에 소스코드를 보면



MainActivity의 onCreate부분에서 루팅체크하는걸 볼 수 있습니다 


루팅체크로직을 따라가 보면



다음과 같은걸 볼 수 있는데 저는 Supersu를 사용해서 위 로직에서 탐지가 된듯합니다


간단하게 Frida를 이용해서 우회해 보겠습니다.


jscode = """

    Java.perform(function() {

        console.log("[*] Hooking calls to System.exit");

        root1 = Java.use("sg.vantagepoint.util.RootDetection");

        root1.checkRoot1.implementation = function() {

            console.log("[*] checkRoot1 Hook");

            return false;

        }

        root1.checkRoot2.implementation = function() {

            console.log("[*] checkRoot2 Hook");

            return false;

        }

        root1.checkRoot3.implementation = function() {

            console.log("[*] checkRoot3 Hook");

            return false;

        }

    });

"""


후킹 스크립트는 위와 같이 간단하게 탐지가 되어도 false를 리턴하게 작성하였습니다


실행해보면...



다음과 같이 에러가 나는데요 여기서 왜 에러가 나는지 몰라 한동안 깊은 삽질을 했네요 :(


결론은 MainActivity에서 libfoo.so파일을 호출해서 native코드를 실행하는데 .so파일의 경우 로드될때 .init_array가 먼저 실행된다고 합니다


그럼 .so파일의 .init_array를 살펴보겠습니다 ida에서 Control + S를 눌러 확인이 가능합니다



Ctrl + S를 이용하여 .init_array를 확인해 보면

아래 그림과 같이 offset sub_8D50을 호출하는 것을 알 수 있습니다

 


sub_8D50으로 들어가면 pthread_create를 이용한 anti-debugging 기법같은데요 thread가 생성되며 호출되는 함수(sub_8BC0)를 살펴보겠습니다



이 함수안에보면 메모리를 읽어 frida와 xposed를 확인하는 루틴이 존재하네요 ㅠㅠㅠ

frida를 이용해서 후킹하려고 하면 여기서 탐지되어 강제로 종료되는 것을 확인할 수 있습니다



android_log_print를 보면 37942자리에 있는 값을 ddms에 로그로 띄워주는 것 같네요 

37942 = 0x9436이므로 해당 주소로 가보면



탐지될 경우 UnCrackable3에 Tampering dtected! Terminating...이라고 출력될 것 같네요



ddms로 로그를 확인해보면 프리다로 실행시켰을 경우, 다음과 같이 탐지되는 것을 볼 수 있습니다



하나로 끝내려고 했는데 너무 길어져서 다음에 이어 작성해야겠네요 ;)

Uncrackable3-2로 끝내겠습니다 :)


문제 풀이(3-2)는 아래에서 확인하시면 됩니다~

https://taesun1114.tistory.com/entry/Uncrackable3-2

'Mobile' 카테고리의 다른 글

apktool first type is not attr  (0) 2018.10.04
Android Proxy Burp 인증서 설치  (2) 2018.09.15
APK IDA로 동적디버깅  (0) 2018.02.22
welcome to droid (codegate2018)  (2) 2018.02.11
INSTALL FAILED TEST_ONLY  (1) 2018.02.06

frida를 이용해서 다른 스크립트 작성 중 검색을 통해 Uncrackable 실습앱을 발견하다보니, 순서가 뒤죽박죽이네요


Uncrackable 실습앱은 level3까지 나와있습니다

마지막인데.. 앱을 설치하고 실행하면 그냥 종료되네요 

처음엔 이것도 우회해야 하는 건가 싶어 한참을 헤맷으나 확인해보니 출제자 에러인 것 같습니다

DDMS를 통해 실행 후 로그를 확인해 봤습니다


로그를 확인하니 세그멘테이션 오류인 듯 합니다


디컴파일 후 소스를 확인해 보겠습니다



앱 분석 당시에는 그냥 출제자 에러인가 보다 하고 넘겼는데... 글을 작성하면서 소스를 보니 뭔가 verifyLibs에서 뭔가를 해주네요


일단 글작성후에 다시 분석을 해보도록 하겠습니다



분석할 당시에는 libfoo.so파일의 strncpy 함수를 호출할 때 인자로 NULL이 들어가서 세그멘테이션 에러가 발생한다고 생각했는데..


글 작성하면서 다시 보니, lib에 뭔가 조치를 해줘야 앱이 실행되는 걸까요? 조금 더 분석해 봐야 겠네요 :)



'Mobile' 카테고리의 다른 글

welcome to droid (codegate2018)  (2) 2018.02.11
INSTALL FAILED TEST_ONLY  (1) 2018.02.06
Uncrackable1 - frida  (4) 2018.01.30
Android에서 호출한 Class/Method 확인하기 - with Frida  (0) 2018.01.26
Uncrackable2 - Radare2  (0) 2018.01.23

Frida 자료를 찾던 중 좋은 실습앱이 있어 Frida를 통해 Uncrackable1 앱 우회를 하겠습니다



앱 실행 시, 루팅탐지 후 종료하게 됩니다


디컴파일 후에 루팅 탐지 로직을 확인하면 다음과 같습니다



sg.vantagepoint.a.c.class에서 루팅을 확인하는데 총 3번에 걸쳐서 탐지를 합니다


해당 실습앱이 올라와 있는 사이트에서는 exit 함수를 후킹하여 exit함수 호출 시 아무런 동작도 하지 않도록 하는데, activity가 떠있는 상태에서는 굳이 루팅체크로직을 일일히 후킹하지 않더라도 이런 방법으로도 우회가 가능하네요 :)


그럼 exit를 후킹하여 앱종료 명령 시, 무시하는 코드를 작성하도록 합니다


import sys
import frida

def on_message(message,data):
    print "[%s] -> %s" % (message, data)


PACKAGE_NAME = "sg.vantagepoint.uncrackable1"

jscode = """
    Java.perform(function() {
        console.log("[*] Hooking calls to System.exit");
        exitClass = Java.use("java.lang.System");
        exitClass.exit.implementation = function() {
            console.log("[*] System.exit called");
        }

     
    });
"""
   
try:
    device = frida.get_usb_device(timeout=10)
    pid = device.spawn([PACKAGE_NAME]) 
    print("App is starting ... pid : {}".format(pid))
    process = device.attach(pid)
    device.resume(pid)
    script = process.create_script(jscode)
    script.on('message',on_message)
    print('[*] Running Frida')
    script.load()
    sys.stdin.read()
except Exception as e:
    print(e)


exit호출 시 콘솔에 로그 출력만 하도록 후킹을 걸고 String을 입력 후 버튼을 눌러보겠습니다




문자열 비교 후 알람을 출력합니다 다시 디컴파일 된 소스코드를 확인해보면



분기문이 보입니다 sg.vantagepoint.a.a.class에서 문자열을 비교하는 것 같습니다



arrayOfByte2에 찾아야할 문자열이 암호화 후 저장되어 있고, sg.vantagepoint.a.a.a를 호출하여 arrayOfByte2를 복호화하여 입력값과 비교하는 것 같습니다


위 화면의 네모박스에 있는 스트링은 AES복호화할 때 사용하는 키값인 것 같네요


sg.vantagepoint.a.a.class를 확인해보니 맞는 것 같습니다 


이 class에서 복호화된 문자열을 return하므로 해당 함수를 후킹하여 복호화된 문자열을 추출하도록 하겠습니다


import sys
import frida
def on_message(message,data):
    print "[%s] -> %s" % (message, data)

PACKAGE_NAME = "sg.vantagepoint.uncrackable1"
jscode = """
    Java.perform(function() {
        console.log("[*] Hooking calls to System.exit");
        exitClass = Java.use("java.lang.System");
        exitClass.exit.implementation = function() {
            console.log("[*] System.exit called");
        }
     
  a = Java.use("sg.vantagepoint.a.a");
        a.a.implementation = function(a,b){
            console.log("[*]Hooking in a.Class");
            retVal = this.a(a,b);
            passcode='';
            for(i=0;i<retVal.length;i++){
                passcode+=String.fromCharCode(retVal[i]);
            }
            console.log("Secret key :"+passcode);
            return retVal;
        }
    });
"""
   
try:
    device = frida.get_usb_device(timeout=10)
    pid = device.spawn([PACKAGE_NAME]) 
    print("App is starting ... pid : {}".format(pid))
    process = device.attach(pid)
    device.resume(pid)
    script = process.create_script(jscode)
    script.on('message',on_message)
    print('[*] Running Frida')
    script.load()
    sys.stdin.read()
except Exception as e:
    print(e)


위에서 작성한 exit()함수 후킹 소스에 덧붙여 sg.vantagepoint.a.a.a를 후킹하는 스크립트를 추가합니다


단순하게 기존 함수의 리턴값을 받아 출력하는 함수입니다


실행시켜 보면 복호화된 문자열이 출력되는 것을 볼 수 있습니다 :)




'Mobile' 카테고리의 다른 글

INSTALL FAILED TEST_ONLY  (1) 2018.02.06
Uncrackable3 - frida  (0) 2018.01.30
Android에서 호출한 Class/Method 확인하기 - with Frida  (0) 2018.01.26
Uncrackable2 - Radare2  (0) 2018.01.23
Android Anti-Debugging  (1) 2018.01.23
Java에서 자신을 호출한 클래스나 함수는 Throwable의 getStackTrace를 이용하여 확인할 수 있습니다

Android에서도 Frida를 이용해 무결성을 훼손하지 않고 호출한 함수를 확인해 보겠습니다

예제로 작성한 APP 소스입니다

package com.example.gnsan.chfrida;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.button).setOnClickListener(Click);
}
Button.OnClickListener Click = new View.OnClickListener(){
public void onClick(View v){
chfrida();
}
};
void chfrida(){
chfrida2();
TextView textview = (TextView)findViewById(R.id.test);
textview.setText("Hello World!!!");
}
void chfrida2(){
}
}

간단하게 버튼을 클릭하여 텍스트를 변경하는 앱입니다. 호출 함수를 확인하기 위해 chfrida / chfrida2를 작성하였습니다


Frida 소스입니다


line:13에서 Throwable를 로드하고 line:16에서 instance 생성 및 line:17에서 getStackTrace를 호출합니다



실행하면 위에서 부터 차례로 호출했던 함수를 출력하네요 :)




'Mobile' 카테고리의 다른 글

Uncrackable3 - frida  (0) 2018.01.30
Uncrackable1 - frida  (4) 2018.01.30
Uncrackable2 - Radare2  (0) 2018.01.23
Android Anti-Debugging  (1) 2018.01.23
Instant Run(Split apk)  (1) 2018.01.10

앱 실행시 어떤 class가 로드되는지 앱 진단 중 필요해서 뒤적이다가 

Java.enumerateLoadedClasses라는 함수를 발견했습니다.


아래 내용은 프리다 공홈에서 가져왔습니다.



Java.enumerateLoadedClasses를 이용한 앱 실행 중 로드되는 클래스를 출력하는 함수입니다.


Usage : python <하단소스저장파일이름>.py <패키지이름>


import sys
import frida

def on_message(message,data):
    print "[%s] -> %s" % (message, data)


PACKAGE_NAME = sys.argv[1]

jscode = """
Java.perform(function(){
    Java.enumerateLoadedClasses(
    {
      onMatch: function(className)
      {
        send(className);
      },
      onComplete:function(){}
    });

});
"""
   
try:
    device = frida.get_usb_device(timeout=10)
    pid = device.spawn([PACKAGE_NAME]) 
    print("App is starting ... pid : {}".format(pid))
    process = device.attach(pid)
    device.resume(pid)
    script = process.create_script(jscode)
    script.on('message',on_message)
    print('[*] Running Frida')
    script.load()
    sys.stdin.read()
except Exception as e:
    print(e)




코드 실행 시 화면이며, 안드로이드 내장 클래스까지 출력되어 상당히 지저분합니다.


시간 날때 실행 패키지의 클래스만 출력되도록 다듬도록 하겠습니다.



================================= 18.01.08 추가 ========================================================


난독화되어 있는 앱으로 확인한 결과, 실행시 난독화가 풀리는게 아니고 난독화가 진행되면 앱에서 해당 클래스 및 함수의 이름이 바뀌어서 저장되는 것 같습다.


실행 시 클래스 로드 할때도 변경된 함수로 로드하네요.


솔루션을 이용하는 앱의 경우 솔루션이 .dex의 헤더를 망가트려 디컴파일이 안되게 하는데 이를 믿고 난독화를 안하는 앱이 대다수입니다.


이런 앱들은 해당 스크립트로 함수 내부 클래스 네임을 불러올 수 있으므로 난독화는 필수로 해야 할 듯 하네요



'Mobile' 카테고리의 다른 글

Android Anti-Debugging  (1) 2018.01.23
Instant Run(Split apk)  (1) 2018.01.10
Apktool Error (apktool.yml)  (0) 2018.01.03
IOS SSL(HTTPS)통신하기  (0) 2018.01.02
Android Proxy Check 우회(Frida)  (0) 2017.12.28

http://taesun1114.tistory.com/entry/안드로이드-프록시-사용-유무-체크에서 포스팅했던 Proxy Check하는 App을 이용하여 Proxy Check를 우회해 보려고 합니다.


Frida 공식 홈페이지는 아래와 같으며, 홈페이지를 통해 여러 정보를 획득할 수 있습니다.

https://www.frida.re/docs/home/



Test App Souce)


package com.example.gnsan.myapplication;

import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.*;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textview = (TextView)findViewById(R.id.test);
if(System.getProperty("http.proxyHost")!=null) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setPositiveButton("확인", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
android.os.Process.killProcess(android.os.Process.myPid());
}
});
alert.setMessage("Denied Proxy");
alert.show();
textview.setText(System.getProperty("http.proxyHost"));
}
}
}

프록시 유무를 체크한 후, 프록시를 사용중이라면 알림을 띄운 후 앱을 종료하는 간단한 소스입니다.


          

<프록시 사용 x>                                <프록시 사용 o>





프록시를 우회하는 Frida Code는 다음과 같습니다.



import sys
import frida



def on_message(message,data):
 print "[RET Value] -> %s" % (message)



PACKAGE_NAME = "com.example.gnsan.myapplication"

jscode = """
 Java.perform(function(){
  var System = Java.use("java.lang.System");   //System.getProperty함수는 java.lang.System
  System.getProperty.overloads[0].implementation = function(prop){ 
   return ;  // 프록시를 사용하지 않을 때 getProperty함수는 null을 리턴함
  }
 });
"""


try:
     device = frida.get_usb_device(timeout=10)
     pid = device.spawn([PACKAGE_NAME])    //Packagename으로 앱을 찾음
     print("App is starting ... pid : {}".format(pid))
     process = device.attach(pid)        
     device.resume(pid)    //resume을 해주지 않으면 화면을 불러올 수 없음
     script = process.create_script(jscode)
     script.on('message',on_message)
     print('[*] Running Frida')
     script.load()
     sys.stdin.read()
except Exception as e:
     print(e)



출처: http://hyunmini.tistory.com/111?category=523090 [Hyunmini]


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

실패한 jscode


var isproxy = Java.use("java.lang.System");
 isproxy.getProperty.implementation=function(a){   

 

  //overloads를 해주지 않으면 error 

  //어느경우에 overload를 하는지 아시는분은 댓글로 부탁드립니다

  //overload는 다음을 통해 알게됨 : 출처: http://hyunmini.tistory.com/111?category=523090 [Hyunmini]


 console.log("getProperty's called!");
 this.getProperty();
 };



var test = Java.use("java.lang.System");
 Interceptor.attach(Module.findExportByName(null,'getProperty'),{

             //findExportByName으로 getProperty를 찾으려했으나 실패함
  onLeave: function(retVal){
   console.log("HI");
   var orig_rtn = retVal.toString();
   send("return vallue :"+orig_rtn);
   retVal.replace("null");
  }
 };


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

  .overload() Example
    .overload('java.lang.String')
    .overload('android.app.Activity')
    .overload('int')
    .overload('[B') // byte array
    .overload('float')
    .overload('android.content.Context')
    .overload('[C')
    .overload('android.content.Context', 'android.view.View')
    .overload('android.app.Activity', 'com.cherrypicks.hsbcpayme.model.object.PayMeNotification')
    .overload('android.content.Context', 'boolean')
    .overload('android.content.Context', 'int')
    .overload('android.content.Context', 'java.lang.String')
    .overload('android.app.Activity', 'int')
    .overload('java.lang.String', 'java.lang.String')
    .overload('android.content.Context', 'android.graphics.Bitmap')
    .overload('java.lang.String', 'java.io.File')
    .overload('android.content.Context', 'java.lang.String', 'java.util.List')
    .overload('java.lang.String', 'java.lang.String', 'java.lang.String')
    .overload('java.lang.String', '[B', '[B')
    .overload('java.lang.String', 'java.lang.String', 'android.content.Context')
    .overload('android.app.Activity', 'com.cherrypicks.hsbcpayme.model.object.PayMeNotification', 'int')
    .overload('[B', '[B', '[B')
    .overload('android.content.Context', 'java.lang.String', 'java.lang.String')
    .overload('android.app.Activity', 'int', 'int', 'int', 'boolean')

+ Recent posts