인라인 패치

이번 시간에는 인라인 코드 패치를 실습해보자!

 

간단히 말해서 '코드 케이브'를 이용해서 패치를 하는 기법입니다. 대상 프로그램이 압축 또는 암호화 되어있어서 직접 파일을 수정하기 어려울 때 '케이브'를 이용해서 패치를 진행합니다.

 

출처 : http://blog.naver.com/PostView.nhn?blogId=ktw1332&logNo=220407203753&parentCategoryNo=&categoryNo=26&viewDate=&isShowPopularPosts=false&from=section

우리가 패치하고 싶은 코드가 OEP영역에 암호화 되어있는 경우 복호화시 어떻게 될지 모르기 때문에 인라인 코드 패치를 진행하는 것이다.

 

실습을 통해서 인라인 패치에 대해서 알아보자!

unpackme#1.aC.exe
0.00MB

먼저 프로그램을 실행 시켜봤더니 다음과 같았다.

저 문구들을 패치하는게 이번 문제인 것 같다.

디버거로 오픈 시에 다음과 같이 암호화 되어있는걸 볼 수 있다.

올리 디버거

 

x32dbg

 

둘이좀 다르게 보여주는데 잘 모르겠다; 아무튼 올리말고 xdbg로 해보자!

일단 내가 찾던 메세지는 검색해본 결과 없고, 좀더 디버깅을 진행해보자!

 

디버깅을 진행하다보면 다음과 같은 코드를 볼 수 있다. 이 형태를 잘 기억해두자

-> 복호화 루프라고 한다.

복호화 루프

xor byte ptr ds:[ebx], 44 에서 특정영역(4010F5 ~ 401248)을 복호화합니다.

그리고 4010B0의 첫 번째 call로 들어가보면 또다른 2개의 복호화 루프를 볼 수 있습니다.

복호화 루프 2

4010C8의 xor에 의해서 401007 ~ 401085가 복호화 되고, 다시 4010DB의 xor로 4010F5 ~ 401248 영역이 복호화 됩니다. 복호화 루프 1과 동일한 범위로 2중 복호화가 진행.

(이거 ebx에서 시작해서 ecx 1씩 줄면서 루프돌리면서 ebx 1씩 증가하는거 관찰하샘)

 

그렇게 2개의 루프를 지나고 다음의 call 401039 명령을 만나게 됩니다.

안으로 들어가보면 다음과 같습니다.

여기서 눈여겨 볼 부분은 checksum 루프 입니다.

먼저 401041의 edx 0을 통해서 edx를 초기화 합니다. 후에 401046에 ADD 명령으로 특정 주소 영역(4010F5 ~ 401248)에서 4바이트 단위로 순차적으로 값을 읽어서 edx에 덧셈 연산으로 누적시켜버립니다!

 

이렇게 루프를 다돌고 탈출하면 edx 레지스터에 특정한 값이 저장되는데, 이게바로 checksum 값 !!!!

ecx=0 되고 edx가 checksum값이 됨 

 

이 checksum 영역은 위에서 설명했다시피 2중으로 암호화되어 있는 영역임. 바로 이영역에 우리가 패치하려는 문자열이 존재할 것 같음.

 

그 후에 내가나온 checksum 값을 비교하는 401062의 CMP/JE 명령을 통해서 서로 다르면 에러 메세지 출력 후에 종료, 같다면 401083의 JMP로 OEP로 가게 됩니다.

checksum 결과에 따른 조건 분기

이러한 checksum 계산 방법은 특정 영역 코드/데이터가 변조되지 않았음을 검증하는 용도로 많이 사용된다고 합니다.

-> 해당 영역에서 한 바이트만 변경되어도 checksum 값이 달라짐

데이터 변조하고 그럼 checksum 비교 부분까지 변조하면 되겠네 ??? 

 

어찌 됐건 OEP로 가보자!

쩜프! 쩜프! 해서 여기까지 도착하게 된다.

OEP !

해당 부분은 보시다시피 다이얼로그를 실행시킵니다. 40123E주소의 다이얼로그를 실행시키면 박스가 나타나게 되죠.

DialogBoxParam() API의 정의는 MSDN에서 찾아볼 수 있습니다.

DialogBoxParam()는 총 5개의 변수를 받습니다. 

INT_PTR DialogBoxParamA(
  HINSTANCE hInstance,
  LPCSTR    lpTemplateName,
  HWND      hWndParent,
  DLGPROC   lpDialogFunc,
  LPARAM    dwInitParam
);

네 ~ 이중에서 4번째 파라미터가 프로시저의 주소라고 합니다.

5개 중 바로 이 4번째 주소!

그래서 PUSH 4010F5로 가봅니다.

패치 문자열 발견!!!

이곳에 패치해야할 문자열이 있는걸 확인할 수 있었습니다. (40110A, 401123) 위치 확인

그럼 인라인 패치를 진행해보도록 합시다.

 

여태까지 한게 이렇게 된다고함https://flack3r.tistory.com/entry/%EC%9D%B8%EB%9D%BC%EC%9D%B8-%ED%8C%A8%EC%B9%98

 

그렇다면 ... 프로그램의 흐름을 좀 위의 그림을 통해서 살펴보고 가봅시다 어려움 ㅡㅡ

401000	[EP Code]
40109B		[Decode]
4010A3			XOR [B] with 44
4010C8			XOR [C] with 7
4010DB			XOR [B] with 11
401039			[A]
401046				Checksum [B]
401090				XOR [C] with 17
401083				JMP OEP

일단.. [EP Code]는 [Decode]를 호출하며 디코딩 부분에서는 [B] - [A] - [B] 순서로 디코딩 작업이 이루어짐.

그러면면서 암호가 해제된 [A] 영역의 코드를 실행하게 되는데,,, 디코딩 과정해서 아까봤다시피 edx로 checksum 값이 떨어지게 됨. 이 checksum값을 [A]영역에서 cmp/je 하며 쳌썸 변경여부를 판별함.

그런 다음에 [C] 영역을 디코딩하고 마지막으로 OEP(40121E)로 점프함!

 

이걸 직접 디버깅하면서 확인해보라고 하시지만 어렵다...

 

인라인 패치 실습

어찌됐건 우리는 [B]영역의 문자열을 패치해야 되는데,, 이중으로 암호화되어있음, 그리고 쳌썸까지 써가면서 데티ㅓ가 변조되었는지 비교하기 때문에 이럴때 인라인 패치를 하면 좀 수월하게 패치할 수 있다고 함.

 

작업 순서는 이렇게 됨

#1. 파일의 적절한 위치에 패치시킬 문자열 삽입 (null padding 구역)

#2. [A]영역의 JMP OEP를 내가 삽입시킨 Patch Code로 점프시킴

#3. 프로그램이 실행되어 [A]의 JMP Patch Code를 만나면 패치 코드에서 문자열을 변경한후 OEP로 JMP하면 끝!

(동굴 판다고 생각하면 쉽네요)

 

패치코드를 설치하는데에 있어서 일반적으로 3가지 정도의 방법을 제시해줌

1. 널패딩

2. 마지막 섹션을 확장해 공간을 확보한 후 설치

3. 새로운 섹션을 확장해 공간을 확보한 후 설치

-> PE 구조가 중요하구나...

 

책에서하는 1번 방법으로 실행해 보겠음. PE Viewr로 열어보자.

나는 PE를 배웠다

 

살펴보면 첫 번째 섹션은 일단 400 ~ 800까지이며 680의 영역까지 데이터가 들어가 있고 이는 메모리의 401000 ~ 401280의 영역에 대비되어짐. 즉 메모리의 401280 ~ 402000의 영역은 널 패딩 영역임을 알 수 있음.

 

HxD로 그럼 파일 옵셋을 보며 널패딩 구역에 해당하는 680구역을 보자!

 

정말 널패딩 영역임을 확인할 수 있다!

 

이곳에 패치 케이브를 설치하자!

먼저 앞서 다시 디버깅을 진행하면서 OEP(40121E)로 가자

쨘!

여기서 앞서 찾은 널 패딩이 680 ~ 800 이기 때문에 이걸 메모리랑 대응 시켰을때 401280 ~ 401400 입니다.

그렇다면 이부분에 패치코드를 다음과 같이 작성해보자 !

(olly랑 달라서 헷갈렷다능...)

 

kyumpack ㅋㅋㅋ

코드작성하고 40121E 원래의 OEP로 점프시켜주면 패치코드가 실행되겠져 ??!

마지막으로 앞서만든 패치코드가 실행되도록 401083 주소의 jmp oep(40121e)를 패치코드 주소로 변경합니다!

변경!

그리고 해당 부분은 XOR 7 암호화를 하고있습니다. 여기서 주의할 것은 현재보이는 'E9 96 01'은 암호화가 풀린 상태의 모습이고, 파일에서 실제로 암호화된 모습은 다음과 같습니다.

 

파일의 'EE 91 06'이 XOR 7 복호화를 통해서 'E9 96 01'로 바뀐 것입니다. 패치 코드 주소는 401280 이므로 JMP명령은 다음과 같습니다.

위에서 확인 누르면 ㅇㅇ

이 instruction의 'E9 F8 01'을 그대로 쓰면 안 되고 복호화를 고려해서 XOR 7을 수행한 후에 씁니다.

 

'E9 F8 01' -> 'EE FF 06'

끝입니다. 이렇게 해서 완성!

kyumpack.exe
0.00MB

=> 글자 짤린다 ㅜㅜ 사내 MDS 때문인거 같다ㅠㅠ

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Reversing' 카테고리의 다른 글

DLL 인젝션  (2) 2019.04.12
리버싱 10  (0) 2019.04.11
리버싱 8  (0) 2019.04.09
리버싱 7  (0) 2019.04.05
리버싱 6  (2) 2019.04.04

+ Recent posts