Microsoft Word - AntiCrackingTechnique.doc

Similar documents
hlogin2

Deok9_Exploit Technique

INTRO Basic architecture of modern computers Basic and most used assembly instructions on x86 Installing an assembly compiler and RE tools Practice co

CKKeyPro 적용가이드

Microsoft PowerPoint - chap01-C언어개요.pptx

Microsoft Word - FunctionCall

Microsoft PowerPoint - a6.ppt [호환 모드]

No Slide Title

금오공대 컴퓨터공학전공 강의자료

Microsoft PowerPoint - a8a.ppt [호환 모드]

=

IDA 5.x Manual hwp

chap 5: Trees

Microsoft PowerPoint - a10.ppt [호환 모드]

Microsoft Word - building the win32 shellcode 01.doc

Microsoft PowerPoint - 15-MARS

Microsoft Word - Static analysis of Shellcode.doc

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Microsoft PowerPoint - Java7.pptx

Microsoft PowerPoint - hy2-12.pptx

Microsoft PowerPoint - a5a.ppt [호환 모드]

Microsoft PowerPoint - ch07 - 포인터 pm0415

Microsoft PowerPoint - a9.ppt [호환 모드]

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

A Hierarchical Approach to Interactive Motion Editing for Human-like Figures

<BDC3B8AEBEF320B9F8C8A320C0DBBCBA20B7E7C6BEC0BB20BBCCBEC6B3BBBCAD D466F E687770>

Secure Programming Lecture1 : Introduction

Reusing Dynamic Linker For Exploitation Author : Date : 2012 / 05 / 13 Contact : Facebook : fb.me/kwonpwn

Microsoft Word - ExecutionStack

02.Create a shellcode that executes "/bin/sh" Excuse the ads! We need some help to keep our site up. List Create a shellcode that executes "/bin/sh" C

Microsoft PowerPoint Android-SDK설치.HelloAndroid(1.0h).pptx

3.20 테러 악성코드바이너리분석 손충호 (StolenByte) WOWHACKER Group 해당문서는 WOWHACKER Group 의문서이므로, 무단도용및수 정및변조는할수없습니다. 페이지 1 / 20

슬라이드 1

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Microsoft Word - Reversing Engineering Code with IDA Pro-4-1.doc

A Dynamic Grid Services Deployment Mechanism for On-Demand Resource Provisioning

PowerPoint 프레젠테이션

11장 포인터

vi 사용법

Microsoft Word - Crackme 15 from Simples 문제 풀이_by JohnGang.docx

Microsoft Word - 1. ARM Assembly 실습_xp2.doc

중간고사

PowerPoint Presentation

목차 1. 소개... 3 가. BOF란?... 3 나. 윈도우 BOF 개발환경및사용툴 Shellcode 작성하기... 4 가. cmd 쉘 ) 소스코드작성 ) 디스어셈블리 ) 어셈블리코드편집 간단

PowerPoint 프레젠테이션

1. 자바프로그램기초 및개발환경 2 장 & 3 장. 자바개발도구 충남대학교 컴퓨터공학과

Microsoft Word - PE Infection ? How to Inject a dll.doc

예제와 함께 배워보는 OllyDbg사용법

(Microsoft Word - \270\256\271\366\275\314 \271\370\277\252.doc)

Microsoft Word - Heap_Spray.doc

PowerPoint 프레젠테이션

<4D F736F F D20B9D9C0CCB7B5B9D9C0CCB7AFBDBA5FBCF6C1A42E646F63>

PowerPoint 프레젠테이션

금오공대 컴퓨터공학전공 강의자료

Microsoft Word - Reverse Engineering Code with IDA Pro-2-1.doc

Microsoft PowerPoint - chap06-2pointer.ppt

Microsoft PowerPoint - chap06-5 [호환 모드]

제 14 장포인터활용 유준범 (JUNBEOM YOO) Ver 본강의자료는생능출판사의 PPT 강의자료 를기반으로제작되었습니다.

Chapter ...

OCW_C언어 기초

PowerPoint Template

강의10

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

PowerPoint 프레젠테이션

API 매뉴얼

버퍼오버플로우-왕기초편 10. 메모리를 Hex dump 뜨기 앞서우리는버퍼오버플로우로인해리턴어드레스 (return address) 가변조될수있음을알았습니다. 이제곧리턴어드레스를원하는값으로변경하는실습을해볼것인데요, 그전에앞서, 메모리에저장된값들을살펴보는방법에대해배워보겠습

학습목차 2.1 다차원배열이란 차원배열의주소와값의참조

Microsoft PowerPoint - e pptx

PowerPoint 프레젠테이션

Frama-C/JESSIS 사용법 소개

chap x: G입력

T100MD+

Tcl의 문법

<BEEEBCC0BAEDB8AEBEEEC1A4B8AE2E687770>

Microsoft PowerPoint - es-arduino-lecture-03

17장 클래스와 메소드

강의 개요

PowerPoint Presentation

슬라이드 1

학습목표 함수프로시저, 서브프로시저의의미를안다. 매개변수전달방식을학습한다. 함수를이용한프로그래밍한다. 2

목 차 1. 개요 취약점분석추진배경 취약점요약 취약점정보 취약점대상시스템목록 분석 공격기법및기본개념 시나리오 공격코드

윈도우즈프로그래밍(1)

Chapter 4. LISTS

Microsoft PowerPoint - 부호기와 복호기.PPT

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

Microsoft PowerPoint - chap05-제어문.pptx

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

Data Structure

2007_2_project4

<4D F736F F F696E74202D204B FC7C1B7CEB1D7B7A55F F6E48616E646C6572B8A6C5EBC7D1BFA1B7AFB0CBC3E2B9D7BCF6C1A

hlogin7

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap10-함수의활용.pptx

Visual Basic 반복문

Microsoft PowerPoint - ch10 - 이진트리, AVL 트리, 트리 응용 pm0600

The_IDA_Pro_Book

SRC PLUS 제어기 MANUAL

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

Transcription:

Reverse Engineering Anti-Cracking Techniques 저자 : Nicolaous George (ishtus@astalavista.com) & Charalambous Glafkos (glafkos@astalavista.com) 편역 : Kancho ( kancholove@gmail.com ) 이문서는 www.milw0rm.com의 [papers] 에 2008년 6월 26일게시되었습니다. 문서의내용을바탕으로공부한내용을정리하였습니다. 오류나질문이있으시면메일보내주시기바랍니다. 역자의주는본문내기울임꼴이나각주로나타내겠습니다. 들어가며 이문서는리버스엔지니어들이목적을달성하기위해따를수있는대부분의방법에대한이해를높이기위한가이드이다. 또한시리얼키검사나인증방법과같은소프트웨어의민감한정보를보호하는더나은방법에대한조언을포함하고있다. 이문서는누군가의이상을바꾸는것에대한것이아니라, 리버스엔지니어링이더안전한세상을만들수있다고믿는사람들을위한것이다. 만약당신이이런생각을하는사람이아니라면, 이문서는당신을위한것이아니다. 이문서는리버스엔지니어들에의해사용되는다양한기술을다루고있지않으므로만약빠진것이있다면망설이지말고메일을보내달라. 할것들 다룰주제들 : - PE packer와암호화툴 - 온라인검사 - 악성코드분석 - x64 리버스엔지니어링 - 취약점발견과 exploiting 다른주제에대한제안도환영한다. 제안하거나도움될것이있다면메일보내달라.

리버스엔지니어링툴 인터넷상에서많은리버스엔지니어링툴들이무료혹은구매를통해사용가능하다. 가장발전된디스어셈블링과디버깅툴은다음과같다. - OllyDBG [http://www.ollydbg.de/] ( 버전 2가곧나올예정 ) - IDA Pro Disassembler and Debugger [http://www.hex-rays.com/] - W32Dasm [http://www.google.com] ( 오래되었으나제공하는기능중몇개는놀랄만하다 ) - SoftICE (2006년 4월부터진행중지 ) - WinDbg [http://www.microsoft.com/whdc/devtools/debugging/default.mspx] 추가적으로다른툴들도사용된다. 툴이름과간단한설명은다음과같다. - PROTECTiON id [http://pid.gamecopyworld.com/] 윈도우실행파일의 packer/encryptor 시그너처와프로그램컴파일러를알려주는데사용 [http://en.wikipedia.org/wiki/executable_compression] - Import REConstructor [http://www.google.com/] 실행파일의손상된 import table(iat) 의복구에사용 - System Internals [http://technet.microsoft.com/en-us/sysinternals/default.aspx] FileMon, RegMon 같은프로그램으로대상프로그램의동작을모니터하는데사용될수있다. 다른대안으로는모든프로그램활동정보를제공하는 sandbox가있다. 리버스엔지니어링접근 우리는리버스엔지니어가사용하는접근을볼것이다. 이장에서사용되는디버거는수정된버전의 OllyDBG( 원래버전도잘동작한다 ) 이다. 예제소프트웨어 프로그램이름 : Example.v1.0.exe ( 시리얼검사 ) Md5sum: 4c78179f07c33e0f9ec8f2b0509bd069 컴파일러 : 볼랜드델파이다운로드 1 : http://www.astalavista.com/media/directory/uploads/fcee1505e1287ac6729c610aadd8bedd.zip 1 원래문서에서는해당프로그램을공개하지않았다. 역자가저자에게메일을보낸결과위의링크를가르쳐주었다. 예제프로그램이버그가좀있어서공개하지않았다고한다. 아무튼역자의메일에친절히답변해준저자 George에게다시한번감사드린다.

프로그램분석 먼저우리의접근방법을정하는것과어떻게동작하는지에대한더나은이해를위해프로그램기능을분석할필요가있다. 보다시피프로그램의형태는간단하다. 주된기능은사용자이름과시리얼검사이다. 첫번째로텍스트상자에임의의값을집어넣고, Check 버튼을누르고프로그램반응을살피는것이다. 시리얼검사알고리즘전에주어진길이제한내의시리얼문자열이들어왔는지검사하는함수가있다고추측할수있는결과를보여준다. 그런다음프로그램이동작하는방식에대한더많은정보를알기위해프로그램을디스어셈블링하고디버깅하는단계로가자. 앞으로나올내용은리버스엔지니어가사용할방법들과소프트웨어를방어하는몇가지제안들이다. 접근방법 1 ( 문자열참조 ) 첫번째단계 : 오른쪽클릭 Search for 선택 All referenced text strings 선택

두번째단계 : 보다시피메시지문자열은다이얼로그박스와쉽게연결되어있다. 문자열을더블클릭해서다이얼로그함수로직접이동할수있다. 세번째단계 : 시리얼검사가어렵게코딩되어있지만, 약간의경험이있는리버스엔지니어는이함수가어디서호출되는지추적할수있고프로그램흐름을패치할수있다. 네번째단계 : 여기서이함수의시작부분에라벨을설정 ( 쉽게참조하기위해 ) 한다. 오른쪽클릭 Label 선택.

Long/Short Error 로라벨설정. 다섯번째단계 : 밑에서볼수있듯이이함수는서로가까이있는세개의다른주소에서호출된다. 여섯번째단계 : 첫번째호출한곳 (004571B7) 으로이동한다. 오른쪽클릭 Go to Call from 004571B7 선택. 성공적으로시리얼검사알고리즘내에도달했다. 만약호출한곳에서시리얼검사와관련된동작을하지않는것으로보인다면다른호출한주소로이동해서살펴보면된다.

제안 ( 접근방법 1 에대해 ) 문자열참조를통해민감한프로그램함수가분석당하지않기위해서는프로그래머는다음의과정을따르면된다. - 전역변수나배열에문자열들을저장해서필요할때참조한다. Pseudo 코드예제 : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ array[] mymsges = {'The Serial number you entered is too short or too long', 'The Serial number you entered is not valid', 'Thank You for registering.'} //Code omitted function registrationcheck(): if(invalid_length) then sendmessage(mymsges[0]) if(invalid_serial) then sendmessage(mymsges[1]) if(valid_serial) then sendmessage(mymsges[2]) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 추가적으로프로그래머는배열내부의문자열을암호화하고필요할때복호화할수있다 ( 좋은암호화기법을쓸필요도없고간단한알고리즘이면된다 ). ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //This can be done separately. //Let s assume that the result of this code will be: dkg$2 kf2 gkfoaplk string thank_you = Thank You for registering for(each letter in thank_you) do add_5_to_ascii_value(letter) print thank_you //program serial check If(valid_serial) then sendmessage(decrypt( dkg$2 kf2 gkfoaplk )) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- 파일이나레지스트리에문자열을저장한다. 접근방법 2 ( Windows API 에 Breakpoint ) 이접근방법에서는 MessagBoxA API에 breakpoint를설정한다. 어떤프로그램은 MessagBoxW, MessageBoxExA, MessageBoxExW를사용할수있다. 첫번째단계 : ( Ollydbg의 Command Bar plug-in 2 사용. Command Bar plug-in은기본적으로존재한다. ) bp MessageBoxA 를적고엔터를친다. Breakpoints를보면확인가능하다. 또는그냥 Ctrl+G 를누른후 MessageBoxA를치면해당함수의시작부분에위치하게된다. 여기서 F2를눌러 breakpoint를설정해도된다. ( Ollydbg의 Names 창을사용 ) Alt+E 를눌러 Executable Modules 리스트로이동 Executable을선택하고 Ctrl+N 을누름 MessageBoxA 를찾음 오른쪽클릭 Toggle breakpoint on import 선택 2 Ollydbg의 plug-in을이용해서훨씬다양하고편리한기능을사용할수있다. Plug-in은사용자가직접제작할수있는데자세한것은 ollydbg 홈페이지를참고하면된다. 제작된 plug-in은다음사이트에서다운로드받을수있다. - http://www.openrce.org/downloads/browse/ollydbg_plugins plug-in은보통 DLL형태인데, ollydbg가실행되는같은폴더에위치시켜주기만하면 ollydbg를실행시켰을때메뉴에서 plug-in이추가된것을확인할수있다. 저자의메일에의하면 ollydbg가약간의버그가있기때문에 command bar plug-in을사용했다고한다.

이경우앞서 Breakpoints에설정되었던것이사라지게되어두번째단계에서 breakpoint가걸리지않는다. 따라서역자의환경에서는할필요가없었다. 이문제를저자에게문의해본결과 Toggle breakpoint on import 는함수자체가아닌함수를가리키는포인터의주소에 break를설정하는것이며, 프로그램의컴파일러에따라동작여부가달려있다고한다. 두번째단계 : 프로그램실행 임의의데이터입력 Check 누름. User32 라이브러리내의 MessageBoxA API에 break가걸린다. 세번째단계 : Return 까지프로그램실행 ( 함수끝날때까지 Ctrl+F9 또는 F8 누름 ) 네번째단계 : 함수를빠져나옴 ( F8 누름 ).

보다시피접근방법 1 에서세번째단계에서와같은위치에도착했다. 제안 ( 접근방법 2 에대해 ) API에대한 Breakpoint 설정을통해프로그램이분석되지않기위해서는프로그래머는 API 사용을제한해야한다. 프로그램을최소한의 API 호출로작성해라. API를사용하는대신자신만의메시지박스를생성해라. 접근방법 3 ( 스택추적 ) 리버스엔지니어가사용할수있는또다른흥미있는접근방법은 스택추적 이다. 스택추적이란스택을통해진행과정을역추적하는기술이다. CPU에의해 CALL < 함수 > 명령이실행되었을때, Instruction Pointer(EIP) 의값더하기다음명령까지의바이트수가스택에저장 (push) 된다 (return address를의미 ). 호출된함수가끝나고 RETN 명령어가실행될때프로세서는스택에서값을빼와서 (pop) 함수를호출한다음곳으로돌아간다. 예를들어 : Call 0xF 가실행되면, offset 3 의값이스택에저장 (push) 된다. RETN 이실행되면, 스택에서 offset 3의값을스택에서가져와서 (pop) EIP 에저장한다. 첫번째단계 : 프로그램실행 임의의값을입력 Check 누름 프로그램중지 두번째단계 : Call stack 창열기. Ollydbg 메뉴의 K를누르거나 Alt+K를누르면된다. Call stack 내용을보면서로호출하는함수들이있다. 등록루틴메인프로그램을추적할수있는함수는 MessageBoxExA 이지만효과적이지는않다. 그함수를어디서호출하는지알아볼필요가있다.

세번째단계 : 오른쪽클릭 Follow address in stack 선택 네번째단계 : USER32.MessageBoxExA 에서 USER32.77D3082F 로리턴한다. USER32.77D3082F 는 MessageBoxA 함수이

다 ( 왜그런지모르겠다면, user32.dll 내부를살펴보면된다 ). 그러므로우리가찾는함수는 Example_.00456FA7 에존재한다. 제안 ( 접근방법 3 에대해 ) 스택추적을막는것은어려운기술이다. 어떤사람은프로그램내의모든민감한함수의 CALL 과 RETN 명령을 JMP 로바꿈으로써할수있다고주장할수있다. 이는 바이너리코드 obfuscation 이라고불린다. 코드 obfuscation은원래프로그램바이너리코드를변환하는기술이므로코드읽기나정적디스어셈블리에의한분석을어렵게한다. 이방법이리버스엔지니어들을혼란스럽게하지만, 소프트웨어를보호하지는못한다. 단지코드분석을지연시키기만한다. 코드 obfuscation의기본아이디어는데이터와코드섹션을합치는것이다. 또한 obfuscation은디스어셈블리와스택추적을막기위해다음처럼 OPCODE들을바꾼다. - CALL 을 PUSH, POP, RET, JMP 로바꾼다. 그리고 JMP 를 PUSH, RET 로바꾼다. 예를들어, 원래코드 Obfuscate된코드 PUSH 0 PUSH 0 CALL 7E450747 PUSH EIP+< 다음명령어까지의바이트 > JMP 7E450747 MOV EBX, 1 POP EAX RETN JMP EAX JMP 00456F94 PUSH 00456F94 RETN - JMP 분기를항상만족하는조건분기 ( 예, JE, JNZ, JL) 로바꾼다. 또한이방법은리버스엔지니어들을혼란스럽게하고다른코드섹션으로보낼수있다. 원래코드 Obfuscate된코드 JMP 00456F94 MOV EAX, 1

CMP EAX, 0 JE <JUNK_CODE> JNE 00456F94 - 도달하지않는부분에명령어를추가한다. - 오프셋에대한직접적인참조사용을피한다 ( 예, JMP 00456F94). 해당오프셋값을혼란스럽게하기위해간단한계산을사용하고나서호출한다. 예를들어, ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MOV EAX, 00456000 ; EAX = 00456000 ADD EAX, 00000F94 ; EAX = 00456F94 JMP EAX ; JMP 00456F94 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 바이너리코드패치 접근방법 1 의여섯번째단계에서볼수있듯이, 이코드는입력된시리얼코드가적합한지여부를판단하고적절하게등록을하기위해사용자의실수를알려주는실제알고리즘이다. 리버스엔지니어가성공적으로코드를패치하고프로그램흐름을조절하기위해사용하는여러방법이존재한다. 이를하기전에실제코드를분석해야하고실제패치목표위치가어디인지이해해야한다. 첫번째단계 : 화면을스크롤해서올려함수시작부분이나근처에 breakpoint를설정한다 (breakpoint를설정하려면해당명령어를선택해서 F2를누르면된다 ). 그리고프로그램을실행시킨다.

두번째단계 : 명령어마다한스텝씩따라가면서이코드가어떤동작을하는지이해하도록노력한다. 아래그림에서보듯, 0x0045716F의 CALL 명령어가텍스트상자의 Username: 안에입력한문자열의포인터를리턴한다. 코드섹션 : 현재명령어 : 스택 : 다음 0x0045718F의 CALL 명령어는 Serial: 텍스트상자안에사용자가입력한문자열의포인터를리턴한다. 코드섹션 :

현재명령어 : 스택 : 다음코드는 EAX에사용자가입력한시리얼번호를로드하고, 입력이 null인지검사한다. 0x0045E5A8(0x0045719C 오프셋참조 ) 가가리키는값은오프셋 0x004571A4에서 EAX에로드된시리얼아스키값이다. If( EAX == null ) { //do something }

레지스터창 : 아래보다시피또하나의길이검사루틴이있다. 이번에는 ESI가사용자가입력한시리얼번호의길이를가지고있으며이는 1과비교된다. 길이가 1이면 Long/Short Error 가호출 ( 접근방법 1의네번째단계참조 ) 된다. 코드섹션 : 레지스터창 : 아래하이라이트된코드는십진수로의시리얼넘버길이의첫번째문자열값 ( 예를들어길이가 28이면 2 ) 과 1 ( 아스키값 0x31) 을비교한다. 어떻게길이가아스키문자열로바뀌는지궁금한사람들을위해 0x4571C3에서의 CALL 명령을따라가면다음루프를볼수있다. 0040840D > 31D2 /XOR EDX,EDX

0040840F. F7F1 DIV ECX 00408411. 4E DEC ESI 00408412. 80C2 30 ADD DL,30 00408415. 80FA 3A CMP DL,3A 00408418. 72 03 JB SHORT Example_.0040841D 0040841A. 80C2 07 ADD DL,7 0040841D > 8816 MOV BYTE PTR DS:[ESI],DL 0040841F. 09C0 OR EAX,EAX 00408421.^75 EA \JNZ SHORT Example_.0040840D 코드섹션 : 현재명령어 : 다음은위의것과비슷하지만두번째숫자를검사한다. 이런경우에두번째숫자는 4, hex 값으로 0x34와같아야한다.

그래서지금까지의프로그램코드는다음과같이생겼다. char first = getchar(length,1,?); //Get first character if (first!= 1 ) { char second = getchar(length,2,?); //Get second character } else { } if(second!= 4 ) { //continue with serial check } else { sendlongshorterror(); } sendlongshorterror(); 참고 :? 문자는리턴된값데이터타입의알려지지않은값을의미한다. 대부분은입력한시리얼번호의길이가 14이지않기때문에 F9를눌러서다시시리얼번호를입력한다 ( 이번에는시리얼번호를 123456789abcde 를입력했다 ). 세번째단계 : 0x00457226의 CALL을따라가보면 (F7을눌러 ) 아래그림과같은코드를볼수있다.

네번째단계 : 아래코드를보자. 00457068 /$ 53 PUSH EBX 00457069. 56 PUSH ESI 0045706A. 57 PUSH EDI 0045706B. 55 PUSH EBP 0045706C. 83C4 F8 ADD ESP,-8 0045706F. BB 01000000 MOV EBX,1 00457074. BE ACE54500 MOV ESI,Example_.0045E5AC ; ASCII "123456789abcde" 00457079 > 8BCE /MOV ECX,ESI 0045707B. 8BD3 MOV EDX,EBX 0045707D. A1 A8E54500 MOV EAX,DWORD PTR DS:[45E5A8] 00457082. E8 BDFEFFFF CALL Example_.00456F44 00457087. 43 INC EBX 00457088. 46 INC ESI 00457089. 83FB 0F CMP EBX,0F 0045708C.^75 EB \JNZ SHORT Example_.00457079 0045708E. A1 A4E54500 MOV EAX,DWORD PTR DS:[45E5A4] 00457093. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX 00457097. 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+4] 0045709B. 85C0 TEST EAX,EAX 0045709D. 74 05 JE SHORT Example_.004570A4 0045709F. 83E8 04 SUB EAX,4 004570A2. 8B00 MOV EAX,DWORD PTR DS:[EAX] 004570A4 > 85C0 TEST EAX,EAX 004570A6. 7E 16 JLE SHORT Example_.004570BE 004570A8. BB 01000000 MOV EBX,1 004570AD > 8B15 A4E54500 /MOV EDX,DWORD PTR DS:[45E5A4] 004570B3. 0FB6541A FF MOVZX EDX,BYTE PTR DS:[EDX+EBX-1] 004570B8. 03EA ADD EBP,EDX 004570BA. 43 INC EBX 004570BB. 48 DEC EAX 004570BC.^75 EF \JNZ SHORT Example_.004570AD 004570BE > BB 0E000000 MOV EBX,0E 004570C3. B8 ACE54500 MOV EAX,Example_.0045E5AC ; ASCII "123456789abcde" 004570C8. BA BCE54500 MOV EDX,Example_.0045E5BC 004570CD > 0FB608 /MOVZX ECX,BYTE PTR DS:[EAX] 004570D0. 890A MOV DWORD PTR DS:[EDX],ECX

004570D2. 83C2 04 ADD EDX,4 004570D5. 40 INC EAX 004570D6. 4B DEC EBX 004570D7.^75 F4 \JNZ SHORT Example_.004570CD 004570D9 > 803D ACE54500 >/CMP BYTE PTR DS:[45E5AC],7B 004570E0. 74 07 JE SHORT Example_.004570E9 004570E2. BF 01000000 MOV EDI,1 004570E7. EB 46 JMP SHORT Example_.0045712F 004570E9 > 8BC5 MOV EAX,EBP 004570EB. B9 0A000000 MOV ECX,0A 004570F0. 99 CDQ 004570F1. F7F9 IDIV ECX 004570F3. 0FB605 ADE5450> MOVZX EAX,BYTE PTR DS:[45E5AD] 004570FA. 3BD0 CMP EDX,EAX 004570FC. 75 06 JNZ SHORT Example_.00457104 004570FE. 830424 02 ADD DWORD PTR SS:[ESP],2 00457102. EB 2B JMP SHORT Example_.0045712F 00457104 > BB 0C000000 MOV EBX,0C 00457109. BE ADE54500 MOV ESI,Example_.0045E5AD ; ASCII "23456789abcde" 0045710E > 0FB606 /MOVZX EAX,BYTE PTR DS:[ESI] 00457111. B9 0A000000 MOV ECX,0A 00457116. 33D2 XOR EDX,EDX 00457118. F7F1 DIV ECX 0045711A. 8BCA MOV ECX,EDX 0045711C. 83F9 0E CMP ECX,0E 0045711F. 73 0A JNB SHORT Example_.0045712B 00457121. 83F9 01 CMP ECX,1 00457124. 76 05 JBE SHORT Example_.0045712B 00457126. E8 05FFFFFF CALL Example_.00457030 0045712B > 46 INC ESI 0045712C. 4B DEC EBX 0045712D.^75 DF \JNZ SHORT Example_.0045710E 0045712F > 83FF 01 CMP EDI,1 00457132.^75 A5 \JNZ SHORT Example_.004570D9 00457134. 8B0424 MOV EAX,DWORD PTR SS:[ESP] 00457137. 83E8 02 SUB EAX,2 0045713A. 75 05 JNZ SHORT Example_.00457141 0045713C. E8 A7FEFFFF CALL Example_.00456FE8 00457141 > 59 POP ECX

00457142. 5A POP EDX 00457143. 5D POP EBP 00457144. 5F POP EDI 00457145. 5E POP ESI 00457146. 5B POP EBX 00457147 \. C3 RETN 이코드는실제시리얼번호검사를수행한다. 디버깅시코드를분석할때볼수있듯이, 0x0045713C 에위치한 CALL 명령을실행시키지않도록하는많은 jump 명령을볼수있다. 보통원하는결과가나올수있는여러방법들이존재한다. 이러한방법중에는패치, 분석, 재구성또는코드 ( 어셈블리 ) 복사 (ripping) 들을포함한다. 이프로그램에서는단지몇개의방법들이있다. 보다시피위의코드는시리얼키를검사하고사용자와시리얼키간의일치여부에대해알려준다. 다음방법은실제로는적용될수없을지모르지만어떻게리버스엔지니어들이일해야하는지에대해기본적이고간단한아이디어를제공한다. 접근방법 1 ( 분기패치 ) 프로그램흐름을패치하는하나의방법은조건분기수정을통해서이다. 사용자가입력한시리얼키가올바르지않다는것을결정하는시리얼키검사알고리즘이존재하는곳은많다. 여기는, 첫번째검사 : 위의바이너리분석에서볼수있듯이함수는시리얼키길이를아스키문자열로바꾸고첫번째문자가아스키로 1 이며 hex로는 0x31 인지검사한다. 간단한패치는, 0x004571DC의 opcode를더블클릭하고 JE SHORT 004571E5 를 JMP SHORT 004571E5 로바꾼다. 그러면 0x004571DE에위치한 CALL은절대호출되지않는다.

두번째검사 : 0x0045721D의조건분기에서도첫번째검사와동일하게적용한다. 그러므로두번째단계에서의코드를바이너리코드패치는다음과같이바꾼다. char first = getchar(length,1,?); //Get first character if(true) { //This is always true char second = getchar(length,2,?); //Get second character if(true) { //This is always true //continue with serial check } else { sendlongshorterror(); //This is never called } } else { sendlongshorterror(); //This is never called }

세번째검사 : 마찬가지로조건분기를무조건분기 (JMP) 로패치한다. 일반적으로이런방식으로하면된다. 약간의버그가있지만기본적인아이디어는이해하리라믿는다. 접근방법 2 ( 함수대체 ) 더간단한방법은아래와같이에러메시지함수를수정하여이를성공할때호출되는함수를가리키도록하는것이다. 먼저코드부분을검색해서 thank you for registering 문자열을출력하는부분을찾아라벨을 thank_you 로등록한다. 그리고나서에러메시지를출력하는부분을찾아시작부분에스페이스바를눌러코드를 JMP thank_you 로바꾼다.

참고 : 이는프로그래머가모든것을한함수내에다넣지않을만큼현명하다면제대로동작하지않을것이다. 시리얼생성 ( 키생성 ) 여기서는 크래커 가프로그램코드를분석하고, 입력한시리얼이옳은지를검사하는것이아니라항상올바른시리얼키 ( 외부제약의조건없이 ) 를생성하는방법으로등록알고리즘을재구성한다. 시리얼생성알고리즘재구성에대해아래몇가지방법이사용된다. 코드재구성 리버스엔지니어가저수준어셈블리어를고수준프로그래밍언어 (C, C++,.NET, JAVA 등 ) 로변환하는방법으로함수나함수집합의동작을이해하기위한알고리즘의분석 ( 보통디버깅을통해 ). 예제 : - 저수준 : 004570AD > /MOV EDX,DWORD PTR DS:[45E5A4] ; Load username string in EDX 004570B3 MOVZX EDX,BYTE PTR DS:[EDX+EBX-1] ; Get letter in position EBX-1 (in each ; loop the pointer is incr by 1) 004570B8. ADD EBP,EDX ; Add the hexadecimal ASCII value of the letter in EBP (UserCount) 004570BA. INC EBX ; Increase the pointer (EBX) 004570BB. DEC EAX ; Decrease the loop counter 004570BC.^ \JNZ SHORT Example_.004570AD ; Stop branching only when the loop ; counter reaches zero(0) 004570BE > MOV EBX,0E

004570C3. MOV EAX,Example_.0045E5AC 004570C8. MOV EDX,Example_.0045E5BC 004570CD > /MOVZX ECX,BYTE PTR DS:[EAX] ; Get the ASCII char stored in memory ; at EAX (Serial string pointer) 004570D0. MOV DWORD PTR DS:[EDX],ECX ; Store it an array of integer ; (see next operation)? 004570D2. ADD EDX,4 ; Move 4 bytes to the right => An array of 32bit Integer values 004570D5. INC EAX ; Move memory pointer one(1) byte to the right 004570D6. DEC EBX ; Decrease loop counter 004570D7.^ \JNZ SHORT Example_.004570CD ; Stop branching when loop ; counter reaches zero(0) 004570D9 > CMP BYTE PTR DS:[45E5AC],7B ; Compare first character ; from the ASCII value with 0x7B ( "{" ) //Code omitted - 고수준 ( 자바 ) String username = getusername(); int sum = 0; for(int i = 0;i < username.length(); i++) { sum += username.charat(i); } String serial = getserial(); int[] array = new int[255]; if(serial.length()<=255) { //Well, Java is safe but we don t need exceptions popping around. for(int i = 0;i < serial.length(); i++) { array[i] = serial.charat(i); } } If(serial.charAt(0) == { ) { //Code omitted 코드복사 ( ripping ) 이는프로그램의바이너리코드를다른프로그램이나직접어셈블리코딩을지원하는상위프로그래밍언어안에복사하는여러방법들을말한다. 코드복사방법은디버깅에드는시간과노력이코드재구성에비해상당히줄어들기때문에코드재구성과는상관없다. 예제 : - 저수준 :

004570AD > /MOV EDX,DWORD PTR DS:[45E5A4] ; Load username string in EDX 004570B3 MOVZX EDX,BYTE PTR DS:[EDX+EBX-1] ; Get letter in position EBX-1 (in each ; loop the pointer is incr by 1) 004570B8. ADD EBP,EDX ; Add the hexadecimal ASCII value of the letter in EBP (UserCount) 004570BA. INC EBX ; Increase the pointer (EBX) 004570BB. DEC EAX ; Decrease the loop counter 004570BC.^ \JNZ SHORT Example_.004570AD ; Stop branching only ; when the loop counter reaches zero(0) 004570BE > MOV EBX,0E 004570C3. MOV EAX,Example_.0045E5AC 004570C8. MOV EDX,Example_.0045E5BC 004570CD > /MOVZX ECX,BYTE PTR DS:[EAX] ; Get the ASCII char stored ; in memory at EAX (Serial string pointer) 004570D0. MOV DWORD PTR DS:[EDX],ECX ; Store it an array of integer ; (see next operation)? 004570D2. ADD EDX,4 ; Move 4 bytes to the right => An array of 32bit Integer values 004570D5. INC EAX ; Move memory pointer one(1) byte to the right 004570D6. DEC EBX ; Decrease loop counter 004570D7.^ \JNZ SHORT Example_.004570CD ; Stop branching when ; loop counter reaches zero(0) 004570D9 > CMP BYTE PTR DS:[45E5AC],7B ; Compare first character ; from the ASCII value with 0x7B ( "{" ) //Code omitted - 고수준복사 (High Level Rip): //Code omitted getusername(username); getpassword(password); user_length := length(username); pass_length := length(password); asm @loop1: MOV EAX,user_length MOV EBX,1 MOV EDX,&username MOVZX EDX,BYTE [EDX+EBX-1] ADD EBP,EDX INC EBX DEC EAX

end; JNZ @loop1 //Code omitted 기타 라이센스서비스의사용은리버스엔지니어와키생성의위험을증가시킨다. 나는당신의소프트웨어에다른회사의프로그램컴포넌트와함께구현하는것을반대하지않으며그것이보안상의결점이라고생각하지않는다. 이를보안위험요소라고하는것은구현상의불완전성과소프트웨어를이해하기위해보낸시간이부족해서이다.