Hooking 후킹 – Code path (Inline patch) 코드 패치, 인라인 패치

해당 파일을 직접 변경하는 방법으로 일반적으로 후킹은 메모리를 대상으로 진행하지만, 몇몇 특수한 상황인 경우, 파일을 직접 수정할 수도 있다. 이는 패킹된 데이터에도 종종 이용하는데, 암호화 해제가 완료되는 시점에 해제된 코드를 인라인 패치를 통해서 수정하고 프로그램을 실행하도록 하는 구조이다.

즉 파일에 비어있는 영역을 이용하여 기계어로 처리하는 로직을 변경하는 것이다. 먼저 프로그램 내에서 빈 공간을 확인한 후에 해당 빈 공간에 코드를 작성하고 해당 코드를 처리 흐름에 포함 시키게 된다. 그림으로 간단히 인라인 패치의 흐름을 얘기하자면 이렇다.

[그림] 인라인 패치 처리 흐름

간단한 조작의 경우 이렇게 진행하는 것이 더욱 편리한 경우도 존재한다. 그럼 확인을 위해 간단한 예제 프로그램을 Visual C++을 이용하여 만들어 보자.

inlinepatch.cpp
#include
<stdio.h>

void main()

{

int a = 1;

int b = 2;

int sum = 0;

printf(“a = %d \n”,a);

printf(“b = %d \n”,b);

sum = a + b;

printf (“sum = %d \n”,sum);

return;

}

[예제] 간단한 덧셈 연산 프로그램

위 프로그램은 처리 결과를 3이라는 결과를 가진다.

[그림] 프로그램 실행 결과 3이라는 결과를 확인할 수 있다

만약 여러분이 위 연산 결과를 출력하기 전 추가로 5를 더하는 연산을 진행하고자 한다면 어떻게 해야 할까?

Dll을 만들어 인젝션을 진행할 수도 있지만, 크게 어렵지 않은 작업이라면, 인라인 패치를 통해 간편히 진행할 수 있을 것이다. 그럼 인라인 패치를 Ollydbg를 이용하여 진행해 보자. 먼저 Ollydbg를 이용해 프로그램 내에 비어 있는 공간을 확인해 보자. 필자는 main 함수 부분의 아래 영역을 이용해 보도록 하겠다.

Code path (Inline patch) 코드 패치, 인라인 패치

[그림] 메인 영역 아래 0xCC(INT3) 영역은 사용하지 않는 공간이다

그럼 프로그램의 흐름을 분석하면서 코드를 파일에 직접 추가해 보도록 하자.

010B13B0 I> 55 PUSH EBP

010B13B1 8BEC MOV EBP,ESP

010B13B3 81EC E4000000 SUB ESP,0E4

010B13B9 53 PUSH EBX

010B13BA 56 PUSH ESI

010B13BB 57 PUSH EDI

010B13BC 8DBD 1CFFFFFF LEA EDI,DWORD PTR SS:[EBP-E4]

010B13C2 B9 39000000 MOV ECX,39

010B13C7 B8 CCCCCCCC MOV EAX,CCCCCCCC

010B13CC F3:AB REP STOS DWORD PTR ES:[EDI]

010B13CE C745 F8 01000000 MOV DWORD PTR SS:[EBP-8],1 ß a 변수의 값 1 저장

010B13D5 C745 EC 02000000 MOV DWORD PTR SS:[EBP-14],2 ß b 변수의 값 2 저장

010B13DC C745 E0 00000000 MOV DWORD PTR SS:[EBP-20],0 ß sum 변수 저장용 공간

010B13E3 8BF4 MOV ESI,ESP

010B13E5 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] ß a 변수를 출력하기 위해 EAX레지스터에 옮긴후 printf”a = %d” 출력에 이용한다.

010B13E8 50 PUSH EAX

010B13E9 68 5C570B01 PUSH Inlinepa.010B575C ; ASCII “a = %d \n”

010B13EE FF15 D4820B01 CALL DWORD PTR DS:[<&MSVCR100D.printf>] ; MSVCR100.printf

010B13F4 83C4 08 ADD ESP,8 ß printf 호출에서 사용한 스택 정리

010B13F7 3BF4 CMP ESI,ESP

010B13F9 E8 33FDFFFF CALL Inlinepa.010B1131

010B13FE 8BF4 MOV ESI,ESP

010B1400 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14] ß b 변수를 출력하기 위해 EAX레지스터에 옮긴후 printf”b = %d” 출력에 이용한다.

010B1403 50 PUSH EAX

010B1404 68 4C570B01 PUSH Inlinepa.010B574C ; ASCII “b = %d \n”

010B1409 FF15 D4820B01 CALL DWORD PTR DS:[<&MSVCR100D.printf>] ; MSVCR100.printf

010B140F 83C4 08 ADD ESP,8 ß printf 호출에서 사용한 스택 정리

010B1412 3BF4 CMP ESI,ESP

010B1414 E8 18FDFFFF CALL Inlinepa.010B1131

// a 변수의 값인 1을 EAX 레지스터에 복사한후 ADD 명령을 이용해서 b 변수와 더하고 연산 결과를 [EBP-20]에 저장하게 된다. 우리는 이 더하기 연산 이후 JMP 명령을 이용해 프로그램의 빈영역에 추가 연산을 진행해보자.

010B1419 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]

010B141C 0345 EC ADD EAX,DWORD PTR SS:[EBP-14]

010B141F 8945 E0 MOV DWORD PTR SS:[EBP-20],EAX
ß 이 명령을 변경한다.

// 기존 값 덮어쓰기에 앞서 먼저 기존 값을 복사해 놓도록 하자.

[그림] 바이너리 형식으로 복사

// 복사가 잘 되었다면, 키보드의 스페이스 바를 눌러 해당 값을 사용되지 않는 영역으로 이동시키자 이때 “Fill with NOP’s”를 체크하여야 사이즈가 원본 보다 작은 경우 남는 공간에 자동으로 NOP(공백)를 채우게 된다.

↓ 수정되는 데이터 크기가 기존보다 작은 경우 NOP로 채운다.

[그림] 비어있는 공간으로 진행흐름을 바꾼다

// 이제 JMP 명령의 주소에 우리가 원하는 코드를 삽입 할 수 있는데 여기에서는 기존 결과에 5를 추가로 더하는 연산을 해보도록 하자.

[그림] 이동 위치에 조작하고자 하는 코드 삽입

// 그리고 좀전에 바이너리로 클립보드에 복사해 두었던 내용을 ADD EAX, 5 아래 붙여 넣자. 그럼 EAX의 값에 5를 더한 값을 [EBP-20]에 저장하게 된다. 우리가 원하는 코드를 모두 삽입하였으므로 기존 코드 흐름으로 다시 JMP 구분으로 되돌리면 모든 구성이 완료 된다.

[그림] 다시 원래의 코드로 복귀한다

// 이렇게 인라인 패치를 완료한 코드의 변경된 내용은 다음과 같다.

013C141F EB 34 JMP SHORT Inlinepa.013C1455 ß 원하는 코드를 삽입하기 위해 비어있는 영역으로 이동

013C1421 90 NOP ß 기존 코드 크기보다 내용이 작아 NOP(공백 코드)으로 채운다.

013C1422 8BF4 MOV ESI,ESP

013C1424 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20]

013C1427 50 PUSH EAX

013C1428 68 3C573C01 PUSH OFFSET Inlinepa.??_C@_0L@GFNJPHG@su>; ASCII “sum = %d

013C142D FF15 D4823C01 CALL DWORD PTR DS:[<&MSVCR100D.printf>] ; MSVCR100.printf

013C1433 83C4 08 ADD ESP,8

013C1436 3BF4 CMP ESI,ESP

013C1438 E8 F4FCFFFF CALL Inlinepa.013C1131

013C143D 33C0 XOR EAX,EAX

013C143F 5F POP EDI

013C1440 5E POP ESI

013C1441 5B POP EBX

013C1442 81C4 E4000000 ADD ESP,0E4

013C1448 3BEC CMP EBP,ESP

013C144A E8 E2FCFFFF CALL Inlinepa.013C1131

013C144F 8BE5 MOV ESP,EBP

013C1451 5D POP EBP

013C1452 C3 RETN

013C1453 CC INT3

013C1454 CC INT3

013C1455 83C0 05 ADD EAX,5 ß 우리가 원하는 ADD 5 연산 코드를 삽입한다.

013C1458 8945 E0 MOV DWORD PTR SS:[EBP-20],EAX ß 해당 결과를 기존 [EBP-20]에 저장한다.

013C145B ^EB C5 JMP SHORT Inlinepa.013C1422 ß 다시 원래 코드로 복귀한다.

013C145D CC INT3

013C145E CC INT3

013C145F CC INT3

[실습] 인라인 패치 진행

위 내용처럼 인라인 패치는 파일 자체의 내용을 수정하여 자신이 원하는 코드를 삽입해 아래와 같이 기존 결과인 3을 8로 수정할 수 있다.

[그림] 처리 결과가 변경되었다

이렇게 삽입한 코드는 현재 Ollydbg를 재시작하거나 닫으면 추가한 내용들이 사라지게 된다. 이를 지속적으로 사용하기 위해서 파일을 저장해 변경 내용을 영구적으로 유지할 수 있다. Ollydbg의 메모리 창에서 Copy to excutable file
à
Save file 메뉴를 이용해 다름 이름으로 파일을 저장하면 된다.

[그림] 실행파일 복사 기능을 이용해 변경 내용을 다른 실행 파일로 저장할 수 있다

Facebook Comments

Leave A Reply

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.