Be myself :: 인라인 패치

달력

32024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

인라인 패치

Reversing 2014. 5. 11. 13:45

1 개요

인라인 패치를 통해 지금까지 배운 내용들을 총 정리하는 시간을 가지자. 패치를 통해 파일의 내용이 어떻게 가상메모리상에 올라가는지, 가상메모리에 올라간 프로그램이 어떻게 실행 되는지 등의 그림을 그릴 수 있을 것이다. 이 기법은 후킹을 할때도 이용된다. 

2 분석

일단 파일의 내용이 어떻게 가상메모리 상에 올라가고, 연산되는지 전체적인 그림을 그리자
먼저 unpackme#1.aC.exe파일을 실행시켜 보자. 파일은 http://ap0x.jezgra.net/download/patchme_no1.rar 에서 받을 수 있다.

NAG(잔소리)라고 쓴 글자를 바꾸라는 것 같다.

Status의 메시지도 바꾸는 것이 우리의 목표이다.

일단 올리디버거로 디버깅하기 전에 우선, PE구조를 분석하여 이 파일이 가상메모리상에서 어떻게 존재하게 되는지 파악한다. 다음과 같은 그림이 그려진다. (각자 그려보자)

자, 이제 대략적인 메모리 구조가 파악이 됐으니 ollyDbg로 뜯어보면서 확인 이 메모리상에서 어떤 일이 벌어지는지 확인해 보자. 우선 분석을 하다보면 첫 번째, 반복 루틴을 만나게 된다.

EBX에 0x4010F5~0x401249까지의 값에 44의 XOR값으로 연산되고 있다. 여기서 XOR 은 기본적인 암호화, 복호화 연산에 잘 사용된다. 예를들어 a XOR 11로 암호화하고 a XOR 11로 복호화 하는식이다. 그렇다면 위의 값은 44로 위의 주소 값에 존재하는 값을 복호화 하고 있다. 계속 트레이싱 해보자. 두 번재 반복 루틴을 만난다.

EBX의 0x401007~0x401086까지의 값을 7로 복호화 하고있다. 계속 살펴 보자.

세 번째 루틴이다. EBX의 0x4010F5~0x401249 의 값을 11로 다시 복호화 하고 있다. 즉, 0x4010F5~0x401249영역은 첫 번째와 세 번째 루틴에서 두 번 복호화 하고 있다. 두 번 암호화 된 것이다.

자 계속 트레이싱 해보자.

0x401062의 명령어를 보면 0x4010F5~0x401249 영역의 값을 더한 값을 31EB8DB0의 값과 비교하고 있다. 이 것은 이 데이터가 손실되진 않았는지, 변형되진 않았는지 확인하는 CheckSum값이다. 계속 트레이싱 해보자. CALL 0040108A부분을 들어가면 다음과 같은 루틴이 확인된다.

EBX에 0x40124A~0x401280 까지의 값을 17로 복호화 하고 있다.

자, 지금까지의 과정을 정리해 보면 다음과 같다.

1.0x4010F5~0x401249까지의 값에 44의 XOR값으로 연산
2.0x401007~0x401086까지의 값을 7로 복호화
3.0x4010F5~0x401249 의 값을 11로 다시 복호화
4.0x4010F5~0x401249 영역의 값을 더한 값을 31EB8DB0의 값과 비교
5.0x40124A~0x401280 까지의 값을 17로 복호화
6.JMP 0040121E명령어로 OEP로 점프

이를 제일 처음에서 살펴 보았던 가상메모리상의 구조와 함께 이해하자. 그럼 다음과 같은 그림이 그려진다.

(출처: http://www.partner114.com/bbs/board.php?bo_table=B33&wr_id=91)
자 이제 분석이 끝났으니, 어떻게 패치 할까 고민해 보자. 우리는 인라인 패치 방법을 진행하려 한다. 이 방법은 파일의 빈영역에 명령어를 집어 넣고 OEP로 점프하는 부분을 우리가 입력한 패치 코드부분으로 JMP하도록 한다음, 패치를 수행한 후 원래의 OEP로 되돌려 주면 된다. 그럼 일단 빈영역을 확보해야 하는데, 우리는 text section을 이용하도록 하자. 앞에서 살펴 보았듯이 text section은 0x401280 부분에 끝이 나게된다. 그렇다면, 이 부분에 파일이 비었는지 확인을 해야하는데 이는 RVA->RWA변환을 하면 된다. 0x401280(RVA) – 0x1000(Virtual Address) + 400(PointerToRawData) = 680이다. 이부분을 헥스 에디터로 살펴 보자.

공간이 충분한 것 같다. 그럼 이 부분을 올리디버거를 이용해 어셈블리로 명령어를 입력해 파일을 저장한 후, JMP OEP부분을 이 부분으로 바꾸면 패치가 완료 된다.

다음과 같이 명령어를 입력하자.

자 이제 이 파일을 저장하자. 그 다음 OEP로 가는 부분을 찾아보자

명령어가 E9 96 01로 되어있는데 이 부분을 우리가 원하는 주소로 입력하면 된다.

이렇게 변경하면 명령어가 E9 F8 01 이렇게 된다. 이 값을 XOR 7으로 다시 암호화 해서 파일에 값을 적어 넣으면 완성이다. 401083(RVA)->483(RAW)값 이므로 이 위치의 값을 밑의 그림처럼 바꾸면 된다.

저장한 다음, 파일을 실행 시키면 다음과 같이 뜬다.

성공이다.!

'Reversing' 카테고리의 다른 글

SEH를 이용한 안티디버깅  (1) 2014.05.15
TLS 콜백 안티디버깅  (0) 2014.05.15
Upack 분석중 정리  (0) 2014.05.10
UPX압축 디버깅  (0) 2014.05.09
IAT와 EAT  (0) 2014.05.08
Posted by flack3r
|