[목차]

 

 

0. 개요

1.프리다로 작업을 자동화 하기

2. Python 바인딩 기본 구조 설명

3. Python 바인딩 기본 구조 Spawn

4. Python 바인딩 파일 제작

5. Python 바인딩 파일 실행

6. 추가 바인딩 코드 예제

7. 메시지 처리하기 (send 함수)

 

 

 

 

[개요]

 

 

처음 실습에서는

1) frida 쉘(CLI)에 자바스크립트 코드를

직접 한 줄씩 삽입/입력하는 실습을 진행하였는데

 

이 경우 오탈자로 인한 코드 수정 또는

코드의 재사용이 힘들다는 단점 때문에

효율성을 높이려 다음 실습에서는

 

2) 자바스크립트 파일을 작성한 뒤

해당 파일을 프리다에서 load 해

삽입/사용하는 실습을 진행했고

 

이번에는 거기서 한 발짝 더 나아가

 

3) 파이썬 바인딩을 이용해

파이썬 코드를 실행하는 것으로

모든 것을 한 번에 할 수 있는 방법을

다룬다.

 

굳이 파이썬이 아닌

C 또는 node.js 바인딩을 통해서 또한

프리다 작업 자동화가 가능한데

본 실습에서는 파이썬 바인딩을 사용한다.

 

 

 

 


 

 

 

1. 프리다로 작업을 자동화 하기

 

 

파이썬 코드 실행으로

아래와 같은 기능 구현 가능함

 

1) 프로세스를 식별하고 연결

2) 연결된 디바이스에서 구현하려는 프로세스와 세션 연결

3) 자바스크립트로 작성된 페이로드 자동 삽입

 

 

# 기본 코드 뼈대 구조

import frida, sys

jscode = """payload_code"""

session = frida.get_usb_device().attach("com.package.name")
script = session.create_script(jscode)
script.load()
sys.stdin.read()
 

 

 

 

 

 

2. Python 바인딩 기본 구조 설명

# frida, sys 모듈 가져오기
import frida, sys

# 삽입할 자바스크립트 코드 넣기
jscode = """payload_code"""

# frida를 시작하고 USB 장치의 특정 패키시 프로세스 연결
session = frida.get_use_device().attach("com.package.name")

# jscode에 있는 스크립트 코드를 frida에서 사용할 수 있도록 생성
script = session.create_script(jscode)

# 생성한 script 로드
script.load()

# script가 동작하기 전에 종료되는 문제 예방
sys.stdin.read()

 

 

 

 

 

 

3. Python 바인딩 기본 구조 Spawn

# frida를 시작하고 USB 장치에 연결
device = frida.get_usb_device()

# 연결된 USB 장치에서 com.package.name 프로세스 '생성' (이 때 메인 스레드는 시작되지 않은 상태여야 한다)
pid = device.spawn(["com.package.name"])

# com.package.name 프로세스 연결
session = device.attach(pid)

# jscode에 있는 스크립트 코드를 frida에서 사용할 수 있도로고 생성
script = session.create_script(jscode)

# 생성한 script를 로드 (앱의 메인 스레드가 실행 전인 상태이다)
script.load()

# com.package.name 프로세스 메인 스레드 실행
device.resume(pid)

# script가 동작하기 전에 종료되는 문제 예방
sys.stdin.read()

 

 

 


 

 

 

 

4. Python 바인딩 파일 제작

 

 

목표 : 실습 1에서 진행했던

android.app.Activity 클래스의

onResume 함수가 호출될 때마다

알려주는 스크립트를 파이썬 바인딩으로

작성한다.

 

 

onresume.py

import frida, sys

jscode = """
console.log("[+] onResume 후킹 작업을 시작합니다.");
setImmediate(function(){       //에뮬레이션 시간초과 되더라도 프리다가 스크립트를 백그라운드에서 자동 실행해줌
    Java.perform(function(){   //현재 스레드가 가상 머신에 연결되었는지 확인 후 내부 코드 실행
        var Activity = Java.use("android.app.Activity");  // 다루는 클래스 설정 - android.app.Activity < onResume()의 클래스
        Activity.onResume.implementation = function() {  // 클래스에 대한 객체를 반환한 Activity를 가지고 클래스 내부 함수인 onResume 지정 후 재작성(implementation)
            console.log("[+] onResume() 함수가 호출되었습니다!");  // 재작성한 윗 줄이 실행될때마다 로그로 찍어본다. 
            this.onResume();     // 기존에 선언되어 있는 onResume()를 그대로 실행해줘야 정상 로직으로 인식하기 때문에 재 선언!
        }
    })
});
"""

process = frida.get_usb_device(timeout=10).attach("com.android.chrome") // timeout 값 설정해줘야 한다!
script = process.create_script(jscode)
script.load()
sys.stdin.read()
 

 

 

 

# 참고

 

위 바인딩 코드의

process = frida.get_usb_device(timeout=10).attach("com.android.chrome")

부분 관련,

 

프리다 버전이 업데이트되면서

frida.get_usb_device를 사용할 때

인자 값으로 timeout을 설정해 주지 않으면

연결이 바로 끊기면서 다음과 같은

device not found 에러가 뜬다.

 

 

실습에서는 timeout 시간을

넉넉히 10초로 설정했지만

1초로 설정해도 정상적으로

돌아갔다.

 

 

 


 

 

5. Python 바인딩 파일 실행

 

크롬 실행 후

파이썬으로 스크립트를 돌려주면

 

 

크롬 앱이

onResume 상태가 될 때마다

알람이 울린다!

 

 

 

 

 

6. 추가 바인딩 코드 예제

 

 

1) 파이썬 바인딩으로 특정 디바이스를

지정하여 연결하는 경우!

import frida, sys, os

jscode= """
setImmediate(function(){
	Java.perform(function() {
		console.log("[*] System.exit() 후킹을 시작합니다.");
		var exitBypass = Java.use("java.lang.System");
		exitBypass.exit.implementation = function () {
			console.log("[*] Hooking Success");
		};
	});
})
"""

device_id = '127.0.0.1:62001'
os.system('nox_adb -s ' + device_id + ' forward tcp:27042 tcp:27042')

session = frida.get_remote_device(timeout=3).attach("owasp.mstg.uncrackable1")
script = session.create_script(jscode)
script.load()
sys.stdin.read()
 

device_id 변수에 지정할 디바이스 아이디 입력 후

os.system 명령어로 adb 명령어를 실행하여

프리다 기본 포트로 포트포워딩 하면

지정된 디바이스로 연결됨!

 

 

 

 

2) FRIDA 활용 복수 작업

루팅 탐지 우회 & 암호 복호화

import frida, sys

jscode= """
setImmediate(function(){
	Java.perform(function() {
		console.log("[*] Hooking System.exit()");
		var exitBypass = Java.use("java.lang.System");
		exitBypass.exit.implementation = function () {
			console.log("[*] Hooking Success");
		}
    
		console.log("[*] Hooking Decrypted Secret");
		var decrypteClass = Java.use("sg.vantagepoint.a.a");
		decrypteClass.a.overload('[B','[B').implementation = function(arg1, arg2) {
			retval = this.a(arg1, arg2);
			secret = ''
			for(i=0; i<retval.length; i++) {
				secret += String.fromCharCode(retval[i]);
			}
			console.log("[*] Decrypted : " + secret);
			return retval;
		}
	})
})
"""
session = frida.get_usb_device().attach("owasp.mstg.uncrackable1")
script = session.create_script(jscode)
script.load()
sys.stdin.read()
 

Java.perform() 안에 각 기능을 하는

코드를 추가하면 사용 가능!

 

 

 


 

 

7. 메시지 처리하기

 

지금까지는 스크립트 파일에서

메시지를 처리할 때 주로

console.log 함수를 사용했는데

파이썬 바인딩에서는

send 함수를 사용한다.

 

send 함수는 메시지를

파이썬 스크립트로

전달하여 데이터를 처리하는데

 

수집한 데이터를 모았다가

원하는 구문을 분석하고

필요한 정보만 지정, 출력이

가능하다.

 

 

# send(message [,data])

프리다 기반 애플리케이션에

자바스크립트 객체 메시지 전송

 

# script.on('message', on_message)

프리다 스크립트에서 보낸 메시지를 처리할

콜백 함수를 설정

 

# on_message(message, data)

- script.on('message', on_message)에서

등록한 핸들러에 대한 정의를 하는 부분

- 단순히 message 매개변수를

콘솔에 출력하는 역할

 

 

 

# 실습

import frida, sys

def on_message(message, data):
    print(message)

jscode = """
setImmediate(function(){     
    Java.perform(function(){   
        var Activity = Java.use("android.app.Activity");  
        Activity.onResume.implementation = function() { 
            send("[+] send 함수 실습! onResume() 함수가 호출되었습니다!")   
            this.onResume();     
        }
    })
});
"""

process = frida.get_usb_device(timeout=1).attach("com.android.chrome")
script = process.create_script(jscode)
script.on('message', on_message) 
script.load()
sys.stdin.read()
 

 

# 돌려보면

 

json 형식으로 출력이 되는데

 

우리가 send로 보낸 데이터가

payload 키의 값으로 담겨

전송이 되는 것을 볼 수 있다.

 

이번에는 코드를 수정해

우리가 원하는 내용만

출력 되도록 실습해본다.

 

 

 

# 코드 업그레이드

import frida, sys

def on_message(message, data):
    if message['type'] == 'send':   # message 값의 type이 send이면 message 중 payload를 출력
        print(message['payload'])
    else:                  # type이 send가 아니면 그냥 message 출력
        print(message)

jscode = """
setImmediate(function(){     
    Java.perform(function(){   
        var Activity = Java.use("android.app.Activity");  
        Activity.onResume.implementation = function() { 
            send("[+] send 함수 실습! onResume() 함수가 호출 되었습니다!")   
            this.onResume();     
        }
    })
});
"""

process = frida.get_usb_device(timeout=1).attach("com.android.chrome")
script = process.create_script(jscode)
script.on('message', on_message) 
script.load()
sys.stdin.read()
 

 

# 돌려보면

 

 

 


 

 

[도움 출처]

: 보안프로젝트 김태영 팀장

728x90

+ Recent posts