Monday, August 5, 2013

Reversing - 파일의 빈영역에 Inline Patch 하기 (1)


 해당 프로그램이 실행압축이나 암호화 등으로 파일 코드를 직접 수정하기 어려울 때
많이 진행하는 Inline Patch 에 대해 실습하겠습니다.

보통의 실행압축이나 암호화 파일은 EP 에서 OEP코드를 복호화 시키고 복호화 시킨
코드쪽으로 점프를 합니다.

이 과정에서 우리에게 필요한 Patch 를 삽입하기 위해 화일의 빈공간 패치할 코드를
입력하고 EP 에서 복호화 과정이 끝나면 OEP가 아닌 우리가 만들어 둔 패치
영역으로 Jmp를 시켜 Patch 가 모두 끝나면 OEP로 돌려 보내는 방법입니다.

이미 복호화가 끝난 상태에서 Patch를 진행하기 때문에 암호화 되어있던,
실행압축이 되어있던 관계없이 정상적으로 Patch가 진행됩니다.

일반적인 코드 Patch 와의 차이점은 프로그램이 실행될 때 마다 매번 Patch코드가
진행이 된다는 점입니다.

실습을 위해 공개된 Patchme 예제를 사용합니다.

InlinePatch 실습 예제 (download from 구글 드라이브)

일단 실행을 해보면 You must patch this MAG !!! 라는 문자열이 담긴 창이 나오고
확인 버튼을 클릭하면 You must unpack me !!! 라는 문자열이 보이게 됩니다.

위 두 문자열을 다른 문자열로 바꿔 출력하는 것이 이번 Inline Patch 목표입니다.
올리(OllyDBG)로 열어 해당 문자열을 찾아봅시다.
아래를 보면 Code가 암호화 되어 보이지 않는다는 것을 알 수 있습니다.















Search for All referenced text strings. 로 찾아보면 보이지 않습니다.
암호화 되어 있다는 것을 유추 할 수 있습니다.












위 call 부분 401001 부분을 따라가서 진행하다 보면 아래와 같은 코드를 보게 됩니다.



















중간에 있는 While 문으로 추정되는

mov ecx,154
xor byte prt ds:[ebx], 44
sub ecx,1
inc ebx
cmp ecx,0
jnz

로 봤을때 이 부분이 복호화 하는 부분으로 유추해 볼 수 있습니다.
특정한 값으로 xor 연산하고 ecx에 있는 값을 하나 감소시키고,
다음바이트로 이동하기 위해 ebx를 하나 증가 시키고, ecx를 비교해서 0이 될때까지
즉 최초 ecx에 넣은 0x154바이트 만큼 반복을 하고 ecx가 0이 되는 순간 while 문을
빠져 나오게 됩니다.

즉 ebx 에 들어있는 주소로부터 0x154 바이트만큼 xor byte ptr ds:[ebx],44 로
복호화가 되는겁니다. 범위는 4010f5 ~ 401248
(4010f5 + 0x154 한값.(offset 에 0도 포함되기 때문에 0x154 더한값에 1을 빼줍니다)

조금더 진행하여 4010b0 주소의 call 을 따라가면 바로 아래부분의(4010bd) 또 다른
복호화문을 만나게 됩니다.















이부분은 401007 부터 401085 까지 0x7f 만큼 xor 7 로 복호화가 진행되고,
이어서 4010f5 부터 401248 까지 0x154 만큼 xor 11 로 다시 한번더 복호화 됩니다.

쭉 진행하다가 4010b6주소의 call 401039를 만나게 되면
아래와 같은 코드가 있습니다.











위 코드에서

push eax
mov ebx,eax
mov ecx,154
mov edx,0
add edx,dword ptr ds:[ebx]
sub ecx,1
inc ebx
cmp ecx,0
jnz 00401046

부분을 보면 ebx 에 들어있는 4바이트를 0x154 만큼 계속해서 누적으로 더해서
edx 에 넣고 있습니다. edx는 4010f5 ~ 401248 부분이 변조가 되었는지
변조 되지 않았는지를 확인하는 checksum 부분입니다.

보통의 checksum 은 이러한 모든 값을 더한후에 sum 값을 가지고 판단합니다.
단 한글자라도 변조가 있었다면 아래의 아스키 문자열 Error crc of this file ...
이라는 메시지박스가 출력 되는것을 알 수 있습니다.

401062 주소의 cmp 를 통해 checksum 값과 31eb8db0 값과 비교를 하는것을 확인
할 수 있습니다. 코드가 변조되지 않았으면, Original EP로 이동하게 됩니다.

우리가 원하는 문자열로 변경하려면 그에 맞게 checksum 비교 부분도 바꿔야합니다.

OEP code (0040121e) 까지 진행이 되었다면
Olly 에서 analysis > analyse code (Ctrl + A) 를 선택하여
현재까지 복호화된 code를 확인해 봅시다.












아래쪽의 DialogBox 를 호출하는 API 함수를 살펴 봅시다.
5개의 인자가 들어가는데 DlgProc 라고 되어있는 4번째 인자가 바로
DialogBoxParam() 이라는 API 호출 주소입니다. 호출주소인 4010f5로 가봅시다.















위 그림에서 아래쪽에 보면 우리가 봤던 최초의 문자열이 있고
그 문자열이 있는 주소를 호출해서 DialogBox가 호출되는 것을 알수 있습니다.
아스키 문자열이 들어있는 주소는 401123 과 40110a 입니다.

지금까지의 코드 흐름과 xor암호화, checksum code를 참고해서 직접 수정해도
되지만 인라인패치를 통해서 코드를 추가해 보도록 하겠습니다.

코드 추가는 2부에서...



- 참고 도서 : Reversing 핵심원리(이승원 저)



No comments:

Post a Comment