Showing posts with label reversing. Show all posts
Showing posts with label reversing. Show all posts

Monday, August 5, 2013

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

 Reversing - 파일의 빈영역에 Inline Patch 하기 1부에 이어서...

40109b 부터 Decoding 이 이루어지며 checksum 값을 이용하여 변조 여부를 판별하기에
직접 변경하기에는 조금 까다롭습니다.

그래서 파일의 빈 영역을 확인하여 그 공간에 패치를 실행하는 코드를 삽입하고
EP코드에서 Decoding 이 모두 이루어진 다음에 우리가 만든 패치코드로 가는
jmp code 를 삽입한후 patch가 모두 끝나면 OEP로 이동하도록 만들겠습니다.

PEview 라는 유틸을 이용하여 빈공간을 확인해봅시다.













.text 섹션을 보면 size of raw data(file alignment) 는 0x400 이고 실제 사용하는
바이트(Virtual Size) 는 0x280 입니다. 즉 0x400 에서 0x280 을 뺀만큼은
빈 공간으로 Null Padding 영역입니다. 이 공간을 사용하도록 하겠습니다.
(참고로 File에서의 할당 단위는 Size of Raw Data, 또는 File Alignment 라고하고,
  메모리에서는 Section Alignment 라고합니다.)

그럼 빈 공간으로 이동해 봅시다.
Pointer to Raw Data 가 0x400 으로 시작지점은 0x400 입니다. 즉
0x400부터 0x680까지 사용하고 0x680부터 0x800 까지가 빈 영역입니다.

이러한 파일이 메모리 상으로 올라가게 되면 file alignment 가 아닌 section alignment
단위로 바뀌게 됩니다.

image base 값은 00400000 이며, section alignment 는 1000 입니다.
file alignment 에서는 400 + 280 이지만, 메모리에서는 1000 + 280 이라는 얘기입니다.
따라서 이동할 메모리 공간은 00401280 입니다.














이동을 해보면 역시 0 이 채워져 있는 Null Padding 영역임을 알 수 있습니다.
이제 위에서 구한 복호화 된 문자열을 다른 문자열로 patch 하겠습니다.











위 그림과 같이 패치하고 싶은 문자열을 넣고 해당 문자열이 있는 위치를
source로 하여 기존 문자열 [edi] 를 patch 합니다.
문자열은 \0 까지 포함하여 길이를 계산 합니다.














그리고 복호화가 완료되고 OEP로 가기전에 우리가 패치한 부분이
실행이 되게 401083 주소를 jmp 401280 으로 변경합니다.

그런후 저장을 하고 실행을 하게 되면 아래와 같이 checksum 오류가 발생합니다.
바로 401083 영역이 xor 7로 암호화 되어 있는 영역인데 이값을 변경해서 그렇습니다.
(401007~ 401085 까지가 xor 7 로 암호화된 영역입니다)












401083 의 화일에 해당하는 영역 0x483 으로 이동해 보겠습니다.
Hex edit 를 이용해 열어봅니다.












483 영역을보면 01f8e9 이라고 되어 있습니다.
xor 7 로 암호화 된 값이 이 값이 되어야 합니다.
따라서,

01 xor 7 = 6
f8 xor 7 = ff
e9 xor7 = ee
따라서 06ffee 값으로 변경 및 저장해 주셔야 합니다.















그리고 실행하면 정상적으로 patch가 되었음을 알수있다.

















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

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 핵심원리(이승원 저)



Friday, August 2, 2013

Anti-reversing - PEB.Process Heap

 본 블로그는 지식 습득후 저장을 하는 공간입니다.
블로그 내의 게시글을 인터넷에서 악의적으로 사용할 경우 본인에게 책임이 있습니다.

 PEB 구조체 시작지점에서 0x18 만큼 떨어진 지점에는 Process Heap Member의 포인터가 있습니다.
아래에서 보면 0x150000 지점입니다.












여기로 이동해보면 아래와 같습니다.
PEB.Process_Heap 에서 0xC 만큼 떨어진 지점이 Flags, 0x10 만큼 떨어진 지점이 ForceFlags 입니다.
PEB.Process_Heap.Flags 는 평상시에 0x2 값을 가지고 있다가 디버깅당하면 0x50000062 로 변경됩니다.
PEB.Process_Heap.ForceFlags 는 평상시에 0x0 값을 가지고 있다 디버깅당하면 0x40000060 으로 변경됩니다.
PEB.Process_Heap.Flags 와 ForceFlags 를 각각 2와 0으로 setting 하면 우회할 수 있습니다.











추가로
PEB.NtGlobalFlag 가 있는데 PEB 시작주소로부터 0x68 만큼 떨어진 지점에 위치해 있습니다.
아래와 같이 디버깅중일때 보통 0x00000070 으로 set 되어 있습니다.
이값을 0x0 의 값으로 변경해주면 우회할 수 있습니다.
















나머지 Anti-reversing 기법들은 차후에 다루기로 하겠습니다.