29
Level 37 이번 패커와 프로텍터 2개가 사용 된 바이너리를 언패킹하는 것에 대하여 다룰 것이다. 최근의 악성코드/바이러스들은 자신의 코드를 리버서의 분석 으로부터 감추기 위해 여러가지 보호 기법을 사용하는 만큼, 리버서는 바이너리를 깊게 분석해야 한다. 이런 이유로 인하여 이번에는 코드를 깊게 분석하여 일반적인 분석보다 심도 있는 분석을 할 예정이다. 우선 올리 디버거의 모든 안티 디버깅 플러그인을 비활성화하여 마치 처음 다운로드한 상태처럼 만든다. 그리고 바이너리의 특성상 몇몇 시스템 에서는 실행 조차 되지 않을 수 있다. (아쉽지만 이런 경우 별 다른 조치 방법이 없기 때문에 이번 레벨을 패스하는 것이 좋다) 참고로 올리 디버거에서 바이너리를 열었을 때 위 사진과 달리 올리 디버거의 상태줄에 "System startup breakpoint" 라면서 ntdll 모듈 주소에서 멈추는 경우도 있을 것이다. 레벨 3을 이해한 사람이라면 뭔가 눈치 챘을 것이다.

Lena’s Reversing Tutorial 풀이 - Newbie Hackerbob3rdnewbie.tistory.com/attachment/cfile22.uf@2324C74C5633ACF30… · 우선 올리 디버거의 모든 안티 디버깅 플러그인을

Embed Size (px)

Citation preview

Level 37

이번 패커와 프로텍터 2개가 사용 된 바이너리를 언패킹하는 것에 대하여

다룰 것이다. 최근의 악성코드/바이러스들은 자신의 코드를 리버서의 분석

으로부터 감추기 위해 여러가지 보호 기법을 사용하는 만큼, 리버서는

바이너리를 깊게 분석해야 한다. 이런 이유로 인하여 이번에는 코드를

깊게 분석하여 일반적인 분석보다 심도 있는 분석을 할 예정이다.

우선 올리 디버거의 모든 안티 디버깅 플러그인을 비활성화하여 마치

처음 다운로드한 상태처럼 만든다. 그리고 바이너리의 특성상 몇몇 시스템

에서는 실행 조차 되지 않을 수 있다. (아쉽지만 이런 경우 별 다른 조치

방법이 없기 때문에 이번 레벨을 패스하는 것이 좋다)

참고로 올리 디버거에서 바이너리를 열었을 때 위 사진과 달리 올리 디버거의

상태줄에 "System startup breakpoint" 라면서 ntdll 모듈 주소에서 멈추는

경우도 있을 것이다. 레벨 3을 이해한 사람이라면 뭔가 눈치 챘을 것이다.

PE Tools를 이용하여 해당 바이너리를 열면 위 사진과 같이 약간 비정상적인

구조를 가지고 있는 것을 볼 수 있다. 물론 올리 디버거의 "ollyadvanced"

플러그인을 이용하여 정상적으로 분석할 수 있게 할 수 있지만, 덤프를 위해

서는 바이너리의 구조 자체를 정상적으로 만드는 것이 좋다.

패치 된 바이너리를 "PEiD / DIT"와 같은 패커 탐지 툴을 이용하면 제대로

탐지 되지 않는다. 이런 툴을 손쉽게 우회할 수 있는 것을 보여주는 좋은

예제로써, 너무 툴은 맹신하지 않길 바란다.

우선 ESP Trick을 이용하여 OEP를 찾으려고 하면 “4147C9 | JNZ 401000” 주소에서

HW BP 때문에 멈추게 되고, 해당 주소로 이동하면 해당 주소는 전혀 OEP 처럼

보이지 않는다. 리버싱 경험이 풍부하다면 PEC로 부터 EP를 찾을 수 있다. 따라서

이동된 주소에 위치하는 처음 몇 라인은 그냥 가짜 코드로 판단할 수 있다.

"JMP EAX" 명령을 통해 분기된 명령어 역시 OEP 코드로는 보여지지 않는다.

(코드 섹션에 위치하는 것도 아니고, 특정 컴파일러의 EP 처럼 보이지도 않는다.)

아마도 "Stolen-Bytes, 리다이렉션 코드"등의 기법이 사용된 듯 하다. 우선 이 부분에

대해서는 나중에 다룰 것이고, 일단 위 주소에서 보여지는 코드는 다른 무언가

때문에 생성된 EP 일것이기 때문에 PEC를 언패킹 한 뒤 바이너리를 위 주소를

기준으로 덤프할 것이다. 덤프한 뒤 IAT를 복구하고 위 주소부터 리버싱을 다시

시작할 것이다.

위와 같이 “ImpREC” 툴을 이용해도 덤프를 뜰 수 있다. 이제 IAT를 수정해야 한다.

OEP를 바꾼 뒤 "AutoSearch"를 누르면 잘 동작하지 않는 것을 볼 수 있다. IAT를

찾기 위해 "FF 25"를 검색해보았지만 별 다른 소득은 얻지 못했다. 따라서 다른

방법을 이용해야 한다.

* 모든 바이너리는 “kernel32.dl” 파일을 사용하기 때문에 IAT 주소를 알아내기

위한 좋은 모듈이다.

위 사진을 통해 알아낸 IAT 시작/끝 주소는 다음과 같다. ( 403000 / 403390 )

“OEP / RVA / Size” 값을 직접 수정한 뒤 “Get Imports”를 누르면 위 사진처럼

몇몇의 모듈이 “valid:NO” 상태임을 알 수 있다.

문제가 되는 주소를 디스어셈블링 해보면 위 사진처럼 특정 dll 파일에서 사용하는

함수가 있는 것을 볼 수 있다.

dll / 함수 목록에서 “Get Import”를 하면 문제가 되는 주소는 정상적으로 고쳐

지게 된다.

“Plugin Tracers – PECompact 2.7.x” 플러그인을 이용하면 자동으로 검색되는 주소를

전부 수정해 준다.

자동으로 수정했음에도 불구하고 아직도 문제가 되는 주소들은 패커에서 추가한

쓰레기 코드일 가능성이 높기 때문에 잘라 주면 된다.

“자동 수정 – 잉여 주소 잘라내기” 작업을 완료하면 모든 dll 상태가 “valid:YES”로

되기 때문에 이제 IAT를 수정할 수 있다.

덤프/수정된 바이너리를 "PEiD / DIE / RDG Detector"로 패커를 탐지해보면 오직

RDG 만이 그럴듯한 결과를 도출한다. 다행히 해당 결과에서 보여지는 "MSLRH" 이

올바른 정보이다. "MSLRH" 프로텍터는 대상 바이너리의 실제 정보를 숨기기 위해

다른 패커의 시그니쳐를 작성할 수 있다.

지금 분석의 경우에는 알려진 패커가 아니라 프로텍터 자체의 쓰레기 코드가 사용

되었다.

지금까지 트레이싱한 부분이(43E000 ~43E0F3) 가짜 시그니쳐와 연관된 부분이다.

"PUSHAD" 명령 이후에 실행된 것들은 스택에 아무런 변화도 주지 않고 나중에

사용하지 않는 정보를 생성하는 알고리즘이였다. 만약 나중에 다룰 예정인 MSLRH

프로텍터에서 제공하는 또 다른 기능(무결성 체크 등)이 적용되지 않았다면 위

사진을 기준으로 덤프를 떠도 정상적으로 동작한다.

일단 “43EF03” 주소까지 진행 한 후 레지스터의 값과, 시스템 스택의 상태를 보면

위 사진과 같다.

사용되지 않는 2개의 호출(CALL) 명령어와 1개의 점프(JMP) 명령어를 건너 뛰었다.

그리고 다음에 실행되는 "ADD ESP,8" 명령어는 스택의 밸런스를 복구할 것이다.

지금까지는 크게 달라진 것이 없다. 계속 Step-In 트레이싱을 할 것이다.

위 사진에서 볼 수 있는 "0043E13F | RDTSC" 주에서 사용되는 "RDTSC" 명령어는

"ReadTimeDateStampCounter"의 약자이다. 이름 그대로 시간 값을 읽어서 EAX

레지스터에 저장하여 리턴 다. 디버거 밖에서는 항상 "12345678h" 이하의 값을

가지지만 디버거에는 더 큰 값을 가진다. 따라서 해당 명령어를 이용하여 디버거

사용 여부를 탐지할 수 있다. 또한 연속적으로 2개의 "RDTSC" 값을 빼버리면

(subtract) 해당 값은 "FFFFFFh" 이하 값을 가지게 된다. 이 방법 역시 디버거 탐지에

사용될 수 있다.

다시 본론으로 돌아와, 우선 "RDTSC" 문제를 해결하기 전에 코드를 전부 복호화

(난독화를 푸는 행위) 시켜야 한다. 이는 "ollyscript" 플러그인을 이용하여 쉽게

결할 수 있다.

* 올리디버거에서는 "RDTSC"를 무력화 하는 간단한 방법이 있다.

1. CPU 창 우클릭 - "search for" - "all commands" - "cmp r32,0xffffff"

2. 검색 결과 우클릭 - "set log break point on all references" - 나타난

창에서 "pause" 라디오 버튼 체크 - "always" (또한 하단의 박스에서

.eax=0, .run, ok 클릭)

이렇게 하면 모든 RDTSC 체크 명령어가 무력화 된다.

다만 아래의 스크립트를 이용하는 것이 훨씬 쉽고 빠르다.

스크립트 전체 코드

바이너리 코드의 끝 부분을 참조하여 주소를 결정하고, 코드의 끝

부분까지 존재하는 bytes의 개수를 'x' 변수에 세팅

끝 부분( 길이 x bytes )까지 난독화된 opcode를 찾고, 이를 NOP opcode를 치환한다.

스크립트에서 검색하려는 다른 opcode들 또한 실제로는 쓸모 없는 코드의 opcode를 찾아서 nop 처리하는 것이다.

난독화를 해제하는 스크립트의 실행이 끝난 뒤 “43E138” 주소에 “BP 설치 – 실행

– BP 삭제” 작업을 통하여 진행한다. 그리고 아래로 조금 트레이싱을 하면

“RDTSC” 명령어가 사용되는 것을 볼 수 있다.

“43E13E | PUSH EAX” 주소까지 실행하면 첫 번째 RDTSC 값(8620BA93)이 스택에

PUSH 되는 것을 볼 수 있다.

그리고 “43E141 | NOP” 주소까지 실행하면 두 번째 RDTSC 값을 볼 수 있다.

(3CBDD7BF)

스크롤을 내리면 “43E158” 주소에서 이전 2개의 RDTSC 값을 서로 빼고 있는 것을

볼 수 있고, 실행하면 그 결과는 “B69D1D2C” 라는 꽤 큰 값을 가지게 된다.

계속 스크롤을 내려서 RDTSC 차감 연산 결과와 “0FFFFFF” 값을 비교하고 있는

루틴에서 계속 트레이싱을 하면, 결국에는 "INT3" 명령이 실행되어 크래시가

일어날 것이다. 따라서 바이너리를 재시작하여 모든 RDTSC 관련 코드를 스크립트를

이용하여 무력화 시킬 것이다. 그러나 다른 무력화 방법부터 살펴 볼 것이다.

위 비교문 뒤의 조건문을 그냥 패치해 주면 된다. 이제 바이너리를 재시작하여

스크립트를 이용해 모든 RDTSC 코드를 무력화 할 것이다.

스크립트 실행이 완료되면 스크롤을 내리면서 스크립트가 어떤 작업을 수행했는지

살펴 볼 것이다.

리버싱 경험이 풍부하다면 위 사진의 코드가 바로 "SEH(Structured Exception

Handler)" 설치 코드인 것을 알 수 있을 것이다. SEH에 대하여 아주 간단하게

설명하자면, 기본적으로 "Exception"이 발생하면 어플리케이션 크래시가 발생한다.

다만 어플리케이션이 시작 할 때 SEH를 설치할 수 있는데, 이는 실행 가능성이

있는 "Exceptions" 들을 SEH에서 처리하게 하여 크래시 발생을 피하는 것이다.

( 많은 프로텍터에서 "Exceptions"을 이용하여 디버깅 탐지를 한다 )

따라서 위 사진의 코드를 해석해보면, "Exception"이 발생한 경우 "51Ah" 만큼

멀리 있는 바이트들 ESP 포인터에 복사하고, 나머지 2개의 명령어는 "SEH"를

설치하고 스택에 PUSH하여 나중에 사용할 수 있게 준비하는 것이다.

리턴 되는 포인터 값은 "43E377 + 51A == 43E891" 이다. 만약 트레이싱을 하

면서 ESP 값이 변경되서 스택창에서 리턴 값을 볼 수 없다면 “View – SEH

chain”에서 볼 수도 있다.

위 주소의 명령어를 실행하는 순간 알 수 없는 값(???)을 이용하기 때문에

“액세스 위반 Exceptions(이하 예외)”가 발생할 것이다.

액세스 위반이 발생하면, 예외 처리를 위해 ntdll 주소로 이동 된다.

이전에 “SEH chain”을 보면 리턴 주소가 “43E891” 이었기 때문에 해당 주소에

“BP 설치 – 실행 – BP 제거” 작업을 수행하여 진행한다.

* 일반적으로 "Exception"을 처리 할 때, 올리 디버거 "exception" 옵션에서

커널을 제외한 모든 값을 체크 해제해서 리버서가 "exception"을 처리 할 수

있게 한다. ( 그리고 Shift+F7/F8/F9 를 이용한다 ). 그러나 이번 레벨의 목적은

아니기 때문에 모든 옵션을 체크한 상태로 분석을 진행하였다.

분기 후 쭉쭉 트레이싱 하면 위 사진의 코드 루틴를 볼 수 있는데, 바로 "HW

BP"를 탐지하고 있는 것이다. 아직 HW BP를 설치하지 않았기 때문에 임의로

1개를 설치해서 어떤 일이 일어나는지 볼 것이다.

HW BP 체크 루틴 조금 위쪽에 HW BP를 설치하고 실행한 뒤 트레이싱을

해보면 “43EB13” 주소에서 첫 번째 슬롯에 설치된 HW BP를 탐지한다.

탐지된 결과를 우회하기 위해서는 그냥 ECX 값을 “00000000”로 초기화 하면 된다.

물론 HW / SW BP를 사용해도 되지만, HW BP는 위 사진과 같이 HW BP를

탐지하는 라인을 실행할 때만 HW BP를 삭제하고 SW BP는 사용하자마자 삭제

해야 한다. 따라서 설치한 HW BP 주소를 나중에 사용하기 위해서는 적어두는

것이 바람직하다.

모든 BP를 제거 한 뒤 트레이싱 하면 위 사진의 코드 루틴을 볼 수 있다.

"43EDB1" 주소를 보면 바이너리에서 사용하는 RDTSC 코드 중 하나를 볼 수

있는데, 이전에 실행한 스크립트가 처리 했기 때문에 크래시가 발생하지 않을

것이다.

코드 분석을 해보면 일단 (원래는 HW BP 주소를 가지고 있을) ECX 레지스터를

스택에 PUSH 한 뒤, EDI 로 POP 한다. 그 다음 복호화 알고리즘이 실행되는데

(299 bytes 이후 주소에서) 이 때 EDI 값을 사용하고 있다. 따라서 ECX 레지스

터에 HW BP 주소가 있으면 잘못된 복호화 알고리즘이 실행되어 크래시가 발생

할 것이다.

계속 트레이싱 하면 위 사진의 코드 루틴을 볼 수 있는데, "43F0D6" 주소까지

트레이싱 하다 보면 위 루틴이 "GetProcAddress" 함수 주소를 찾고 있는 것을

알 수 있다.

그리고 위 사진의 명령어를 이용하여 "GetProcAddress" 주소에 SW BP가 설치

되어 있는지 판단한다. 설치되어 있지 않으면 분기가 일어난다.

조금만 트레이싱을 하면 위 사진과 같은 코드 루틴이 나타나는데, 꽤 난해한

부분이다. 처음에는 멍 때려서 분석을 처음부터 다시 시작했다. 위 코드 루틴은

트레이싱을 방지하는 보호 기법이다. 루틴을 점프해서 넘어가지 않으면 계속

반복되면서 "Exceptions"이 발생하여 트레이싱을 하지 못하게 된다.

위 코드 루틴에서 “SEH 설치 – 예외 처리 발생”를 하고 있기 때문에 건너

뛰어야 한다.

Zero-Flag 값을 임의로 변경하여 우선 문제가 되는 루틴을 건너 뛴다.

건너 뛰면 또 다른 복호화 루프(43F14F ~ 43F160) 루틴이 나타난다. 분석

할 필요는 없기 때문에 루프 이후 주소에 “BP 설치 / 실행 / BP 제거” 작업을

수행한다.

트레이싱을 통해 “43F3DD” 주소까지 진행하면, 꽤 많은 분기문이 보여지는데

아마도 난독화 코드일 확률이 높다. 따라서 다시 한번 난독화 해제 스크립트를

실행하고 재 분석(Ctrl + A)을 하면 제대로 된 명령어들이 보여진다.

위와 같은 루틴이 꽤 많이 보이는데 코드 분석을 해보면 "GetProcAddress"를

이용하여 바이너리에 필요한 API의 주소를 찾은 다음 나중에 사용할 포인터에

저장하고 있는 것이다.

“Step-In (F7)” 트레이싱을 하면서 위 주소까지 진행하면 “43F807” 주소로

조건에 따라 분기하고 있는 것을 볼 수 있다.

만약에 분기가 일어나서 실행되지 않는 코드들을 보면 위와 같은 API 함수

들이 사용되는데, 실제 디버거에서 전체 코드를 보고 쉽게 설명하면 우선

처음 어플리케이션은 자신의 프로세스가 이미 실행되고 있는지 판단한다.

실행되고 있으면 OEP에 도달하기 위해 계속 명령어를 실행하고, 아니면

자기 자신을 위 사진의 주소에서 실행시키는데, 종료 되기 전에 몇초 동안

딜레이가 발생한다. 그래서 이제 막 실행된 프로세스가 딜레이가 발생중인/

실행중인 프로세스를 탐지하고 OEP까지 진행시킨다. 이 방법은 꽤 좋은

안티 디버깅 기법이다. 즉, 위 사진의 코드가 실행되기 않게 분기해야지

안 그러면 자기 자신을 다시 실행하고 현재 실행중인(분석중인) 프로세스를

종료시킬 것이다.

따라서 “43F7B5” 주소까지 진행한 뒤 Zero-Flag 값을 변경하여 분기가 일어

나게 한다.

플래그 값 변경 후 트레이싱을 하면서 위 사진의 주소까지 진행한다.

“43FA8A” 주소까지 실행하면 기본적으로 분기가 일어나지 않는다. 만약

플래그 값을 변경하여 분기를 시키면 “43FAB6 | JMP 43FABE => 43FADF”

주소에서 메시지박스 함수가 호출되는데 뭔가 좋지 않은 듯 하기 때문에

플래그 값을 변경하지 않고 그냥 진행할 것이다.

* “43FA8A” 주소에서 분기가 일어나지 않고 계속 트레이싱을 하면 또 한번의

복호화 루틴이 나타난다. 해당 루틴 이후에 “BP 설치 / 실행 / BP 제거”

작업을 한 뒤 트레이싱을 해보면 “43FD87” 주소부터 또 다른 코드 루틴이

나타나는데 이 역시 쓰레기 코드이다. 따라서 한번 더 난독화 해제

스크립트를 실행해야 한다.

쭉쭉 트레이싱을 하면 위 사진의 코드 루틴을 볼 수 있다. 이전에 보았던

것처럼 SEH 설치 후 예외를 발생시키는 코드이다.

예외가 발생하면, “SEH chain” 메뉴를 참고하여 리턴 되는 주소로 이동하여

“BP 설치 / 실행 / BP 제거” 작업을 수행한다.

계속 트레이싱을 하면 역시 이전에 보았던 HW BP 루틴이 나타난다. 지금은

설치된 HW BP가 없기 때문에 그냥 지나가도 된다.

트레이싱하면 “4406A1” 주소에 도달되는데, 해당 주소 루틴에서 사용되는

문자열로 보아 올리 디버거와 “IMP Rec” 툴을 탐지하고 있는 듯 하다.

당연히 탐지가 되기 때문에 “4406C3” 주소에서 분기가 일어난다.

분기가 일어나면 보나마나 디버거가 종료될 것이기 때문에 Zero-Flag 값을

변경하여 분기 되지 않게 한다.

쭉쭉 트레이싱 하면 위 사진의 코드 루틴까지 이동된다. 프로텍터에서 올리

디버거의 자체적인 취약점을 "OutputDebugString" API를 이용하여 디버거

크래시를 유발하고 있다. 따라서 패치 해야 분석을 계속할 수 있다.

* 올리 디버거에서는 포맷 에러가 존재한다. 올리 디버거에서 디버거 메시지를

처리 하는 부분에 포맷 스트링 버그가 존재한다. 이미 알려진 버그이기

때문에 종종 안티 디버깅 기법에 사용되기도 한다. 올리 디버거 크래시를

유발하는 이 취약점은 바이너리가 디버깅 되는 동안 디거버에게 특별한

메시지가 전송되었 을 때 이용(output 디버그 문자열 Exception / 이벤트라

불림)된다. 이름처럼 "OutputDebugStringA" API 함수는 프로세싱(파일의

처리)를 위해 디버거에서 문자열을 전송하는데, 해당 문자열은 올리

디버거 하단에 상태창에 나타난다. 바로 이 부분에서 특별한 문자열이

올리 디버거의 크래시를 유발시키는 것이다. 실제로 해당 버그가 플러그

인이나 기타 방법에 의해 처리되지 않으면 올디 디버거가 종료되서 분석

을 더 이상 할 수 없다.

간단하게 해당 부분을 실행하지 말고 이후 주소에 “New origin here”를

설정한 뒤 진행하면 된다.

계속 트레이싱 하면 “440F26” 주소에 도달하는데 해당 루틴의 아래쪽을

보면 "ZwQueryInformationProcess" 함수를 사용한다. 이 함수 역시 올리

디버거를 탐지하여, 탐지 된 경우 디버거 크래시를 유발한다. 따라서

“440F2A” 주소까지 진행 후 Zero-Flag 값을 변경하여 분기를 발생시켜 해당

함수가 호출 되지 않게 해야 한다.

계속 트레이싱 하면 “4411CC” 주소에 도달하는데 해당 루틴의 아래쪽을 보면

“VirtualProtect” 함수를 사용한다. "VirtualProtect" 함수는 호출된 프로세스의

가상 주소 공간 내에서 커밋된 현재 페이지의 접근 보호 설정을 변경할 수

있다. 따라서 안티 디버깅 보다는 안티 덤프라고 볼 수 있다. 어찌되었든

회는 해야 한다. 참고로 탐지 코드에서, "SetUnhandledExceptionFilter"를

사용하여 SEH에서 처리하지 않는 "Exceptions"을 만들어 올리 디버거로

넘긴 뒤 디버거 크래시를 유발한다.

이번에도 해당 분기문(2개) 주소까지 진행 후 Zero-Flag 값을 변경하여 우회

한다.

트레이싱을 하면 “GetModuleHandleA” 함수를 이용하여 필요한 값을 세팅

하는 부분으로 이동된다. “Step-In” 트레이싱을 하면서 어떤 값이 세팅되는지

봐야 한다.

비교문이 있는 것으로 보아 몇몇의 플래그(위 사진에서는 [ESI+D])를 이용

하여 디버거 종료/크래시 유발 등의 코드로 분기시키는 듯하다.

계속 트레이싱을 하면 코드의 거의 끝 부분을 볼 수 있다. 위 사진의 코드

루틴은 간단하고 짧은 알고리즘을 이용하여 2개의 해쉬 값을 구한다. 그리고

해당 값들에 대하여 차감 연산(해쉬 A - 해쉬 B = 결과 C)을 한뒤, 결과(C)

를 "JMP OEP" 명령어로 활용한다.

결국 "3CA8CB" 값이 OEP가 되는 것을 알 수 있다. 이제 지금까지 살펴보았던

문제점을 해결해야 한다. 올바른 해쉬 값은 쉽게 계산되기 때문에 이를

이용할 수 있지만 좀 더 쉬운 방법을 이용할 것이다. 분석할 때 알아겠지만

어플리케이션은 자기 자신의 프로세스가 동작 중이지 않으면 실행시키고

있다. 따라서 일단 어플리케이션을 실행시키고 바이너리를 열어서 디버깅을

진행할 수도 있다.

또 다른 방법도 있는데 이를 위해서는 분석할 때 분기문을 조작하기 위해

했던 작업을 하여 최종적으로 OEP를 찾는 것이다.

참고로 해쉬 계산 알고리즘/"GetProcAddress" API 코드/암호화 된 코드

내부를 제외하면 SW BP를 이용할 수 있다.

첫 번째 방법(어플리케이션 실행 – 분석 진행)을 사진 없이 간단하게 설명할

것이다.

> 우선 올리 디거버 말고 다른 디버거(x86/이뮤니티)를 이용하여 해당

바이너리를 연다.

> 만약 올리 디버거를 이용하려면 “OLLYDBG“ 문자열을 사용

하는 루틴을 우회해야 한다.

> 바이너리에서 연 뒤, 디버거 바깥(정상 환경)에서 실행시킨다.

> “44A1A40 | JNZ 43E0F3” 주소에 “BP 설치 / 실행 / BP 제거” 작업을

수행하여 HW BP 탐지 부분을 우회한다.

> “441B64 | RETN” 주소에 “HW BP on access” 설치 후 실행한다.

> HW BP 제거하면 “441B5F” 주소에 OEP 값이 보여진다.

( 본인의 경우 402170 )

> “IMPRec” 툴을 이용하여 덤프 => IAT 수정을 하면 된다.

> “OEP = 2170 ” 설정

> “AutoSearch” 클릭

> “Get Imports” 클릭

> “Show Invliad => ‘valid:No’ 상태인 주소를 삭제

(Delete thunks)

> Advanced Commands => Select Code Section(s) 클릭

> Full Dump 클릭

> 새로운 바이너리로 저장 (ex : dump_com.exe)

> Fix Dump 클릭

> 이전에 저장한 바이너리 대상