Rev
리버싱 핵심원리 20장
2024. 10. 6. 20:11

20장 인라인 패치 실습

인라인 패치 (inline patch)

  • 원하는 코드를 직접 수정하기 어려울 때 간단히 코드 케이브 (code cave) 라고 하는 패치 코드는 삽입한 후 실행해 프로그램을 패치시키는 기법
  • 실행 압축되거나 암호화되어 파일을 직접 수정하기 어려운 경우, 파일을 패치할 때 자주 사용된다.

기본 : EP 코드는 암호화된 OEP 코드를 복호화한 후 OEP 코드로 점프

  • 패치하기 원하는 코드가 암호화된 OEP영역에 존재하면 패치시키기 어렵다
    • → 파일 내 코드 케이브라고 한느 별도의 패치코드를 설치한 후 EP 코드의 복호화 과정 이후 JMP 명령어를 수정해 코드 케이브가 실행되도록 한다
    • 코드 케이브 내에 패치 코드를 실행 후 (이미 OEP코드가 복호화 되었기 때문에 그대로 수정 가능) OEP로 가면됨
  • 즉, 실행될 때마다 (별도의 패치코드를 실행해) 매번 프로세스 메모리의 코드를 패치함
  코드 패치 인라인 패치
대상 파일 파일 & 메모리
횟수 1번 파일에는 1번만, 메모리는 실행될 때마다
방법 Direct (원하는 위치에 직접 패치) Indirect (코드 케이브를 미리 설치한 후 메모리에서 원하는 영역이 복호화되었을 때 패치)

실습 - Patchme

EP 코드

아래 암호화된 코드가 나열되어있음

 

이렇게 string을 살펴보면 모든 문자열이 암호화되어있어 이상태로는 원하는 문자열을 찾을 수 없음
코드를 조금만 시켜 함수로 들어가보면,, 이런 코드를 발견할 수 있음.

  • 복호화 루프1 (0x44로 0x154번 4010F5~401248을 XOR명령으로 복호화)
  • 복호화 루프2 (0x7로 0x7F번 401007~401085을 XOR 명령으로 복호화)
  • 복호화 루프3 (0x11로 0x154번 4010F5~401248을 XOR 명령으로 복호화)

복호화루프가 끝나면 해당 함수로 들어오게됨

  • CheckSum 계산 루프를 보면 4010F5~401248에서 4바이트단위로 순차적으로 값을 읽어 add연산으로 누적시킨다.
    • Checksum : 특정 영역의 코드/데이터가 변조되지 않았음을 검증하는 용도로 많이사용한다.
      • CheckSum 값이 31EB8DB0 과 같다면 (코드가 변조되지않았다면), OEP로 jump한다
      • 다르다면 에러메세지 출력하고 프로그램이 종료된다.

OEP코드 : Data로 표현된 경우 Ctrl+A로 코드로 분석가능 (단, 복호화 다하고 눌러야 OEP코드가 나온다)

  • 40123E 주소를 보면 다이얼로그를 실행시키는 코드가 함수 명령이 있다. 그리고 40122C 주소를 보면 DIgProc 주소가 4010F5라는 것을 알 수 있다.

40110A, 401123을 패치해야함을 알 수 있다.

코드 구조

  • A,B,C영역은 암호화된 코드이며, EP code와 decoding code 영역에는 암호화를 해제하는 복호화 코드가 존재
//대략적인 코드 흐름
[EP Code]  // 단순히 Decoding Code 호출 역할
	[Decoding Code]  // 디코딩 작업
		XOR [B] with 44  // [B] - [A] - [B] 순서로 XOR 
		XOR [A} with 7
		XOR [C] with 11
		[A]  // 암호화 해제된 [A] 영역 코드 실행
			Checksum [B]  // 변경 여부 판단
			XOR [C] with 17
			JMP OEP  // OEP 로 점프

인라인 패치 실습

  • 이중으로 암호화된 [B] 영역을 패치시켜야하고, checksum을 따로 구해야하므로 수정이 어려움
    • → 인라인 패치 해보자.
1. 파일의 적절한 위치에 문자열을 패치하는 코드 삽입
2. [A]의 JMP OEP 명령을 JMP Patch Code로 수정
3. JMP PatchCode를 만나면(이미 모든코드는 복호화가 되어있고 Checksum을 통과했기 떄문에) 패치코드에서 문자열을 변경한 후 OEP로 JMP하면 됨.

 

패치코드 위치?

  1. 파일의 빈 영역에 설치 (크기 작을 때)
  2. 마지막 섹션 확장한 후 설치 (크기 클 때, 권장)
  3. 새로운 섹션 추가한 후 설치 (크기가 클 때)

  • 첫번째 섹션의 size of raw data는 400이고, virrtual size는 280이다.
    • 크기는 400이지만, 여기서는 280크기만 메모리에 로딩된다
      • 680~800 쓰이지않음 (NULL Padding)

null padding확인
OEP 로 이동

  • 빈영역의 file offset : 680~800
    • VA 로 변환 : 401280~401400

  • Assemble 의 space , Edit의Ctrl+E 로 편집해준다.
  • Copy to executable - All modifications 명령으로 저장

패치코드 실행하기

  • JMP OEP를 JMP CodeCave(401280)으로 변경
    • JMP 명령문의 instruction : E9 F8010000
      • 그대로 쓰는게 아니라 복호화를 고려해 xor7 수행 후 써야함
        • E9 → EE
        • F8 → FF
        • 01 → 06

 

'Rev' 카테고리의 다른 글

dungeon-in-1983  (0) 2025.01.03
리버싱 핵심원리 21장 ~ 23장  (0) 2024.11.04
리버싱 핵심원리 16장  (0) 2024.09.28
리버싱 핵심원리 2부  (0) 2024.09.23
KnockOn Bootcamp ROP  (0) 2024.09.18
let textNodes = document.querySelectorAll("div.tt_article_useless_p_margin.contents_style > *:not(figure):not(pre)"); textNodes.forEach(function(a) { a.innerHTML = a.innerHTML.replace(/`(.*?)`/g, '$1'); });