본문 바로가기
보안/iOS

[iOS] 앱 바이너리 패치(SSL 인증서 검증 우회)

by stephen26 2022. 2. 27.

플러터(Flutter) 앱은 CA 인증서 저장소 대신 앱 자체 인증서 저장소를 사용하기 때문에 프레임워크 내 SSL 인증서 검증을 실시하는 함수에 대한 후킹을 통해 검증 절차 우회가 필요하다.

 

그리고 이에 대한 우회 방법으로 인증서 검증 함수 후킹 과정을 설명한 바 있다. 

 

[iOS] 플러터(Flutter) HTTPS 프록시 연결

지난 글에서 플러터(Flutter) 앱의 프록시 설정에 대해서 다룬 바 있다. 하지만 해당 설정 만으로는 HTTPS 패킷을 캡처할 때 오류가 발생한다. [iOS] 플러터(Flutter) 앱 프록시 설정 Flutter 앱은 시스템

noasand.tistory.com

 

오늘은 다른 방법으로 인증서 검증을 우회해보고자 한다. 그리고 겸사겸사 바이너리 패치에 대한 과정을 기록으로 남겨둔다.

 


해당 함수는 'ssl_x509.cc' 파일 내 선언되어 있으며 함수 명은 'ssl_crypto_x509_session_verify_cert_chain( )' 이다. 이 함수가 플러터 앱에서 SSL 인증서의 유효성을 검증한다.

 

이 함수가 메모리 상에 올라왓을 때 offset을 찾아내고 후킹한 뒤 반환 값을 변조하는 방법도 있지만 후킹 툴 사용이 제한적일 때를 대비해 바이너리 패치를 진행해보도록 한다.

 

이 함수는 플러터 앱 내 "Flutter.framework" 파일에 포함되어 있다.

 

3utools 도구를 사용하여 디바이스에 설치된 플러터 앱의 경로에서 해당 파일을 직접 추출하도록 한다. 대부분의 앱은 "/private/var/containers/Bundle/Application/" 이 *경로에 존재한다.

 

*위 경로가 안 보인다면 "Apple File Conduit 2" 트윅을 단말에 설치하도록 한다. 이 트윅은 탈옥 디바이스의 내부 디렉토리에 접근할 수 있도록 해준다.

 

위에서 가져온 "Flutter" 파일을 IDA로 열어 앞서 오픈소스에서 확인한 하드코딩 된 문자열 "ssl_client"를 통해 함수의 위치를 찾아낸다.

 

찾아낸 함수를 분석해보면 Bool 타입으로 인증서 검증에 성공했을 땐 v37 변수에 "1", 실패했을 때는 "0"을 반환한다.

 

Byte Array로 인증서 검증 결과가 저장되는 코드 분기의 Byte 값을 확인할 수 있다. 인증서 검증에 실패했을 때는 "14 00 80 52", 성공했을 때는 "34 00 80 52"이다. armconverter.com을 사용하면 어셈블리 코드를 헥스 코드로 편하게 변환해볼 수 있다.

 

검증 여부에 상관 없이 모든 반환 값을 참인 "1"로 변조하면 검증을 우회할 수 있을 것이다. 추가로 변조가 필요한 주소는 각각 "0x4CEC64",  "0x4CEC84"이다.

 

바이너리 편집 도구인 Hxd로 "Flutter" 파일을 열고 앞서 찾은 Byte 패턴을 통해 위 주소로 이동한다. 그리고 검증 실패 시 반환되는 "0" 값을 모두 "1"로 패치한다. 패치한 주소는 "0xB5AC64", "0xB5AC84" 으로 위에서 찾은 RVA 주소와도 같다.

 

이렇게 패치한 파일을 다시 IDA로 디컴파일하여 결과를 살펴보면 모든 반환 값이 참의 값으로 저장되도록 수정된 것을 볼 수 있다.

 

디바이스의 앱 설치 경로 내 기존 Flutter 프레임워크 파일을 제거하고 패치한 파일로 대체하고 앱 종료 후 실행해주면 아래처럼 HTTPS 검증을 우회하고 패킷을 캡처할 수 있는 것을 볼 수 있다.

댓글