"One of the best ways to get yourself a reputation as a dangerous citizen these days is to go about repeating the very phrases which our founding fathers used in the great struggle for independence." --Charles Austin Beard
-basic x86 assembly knowledge
-buffer overflow techniques (for implementation of the shellcode)
okay, so you just found a buffer overflow in the latest application.
you overwrite the EIP, and..suddenly you realize you need code to execute.
AND, this code has to be small enough to work in your newfound vulnerability.
so, what do you use? shellcode, of course!
shellcode can be very modular, meaning that it can be used in many different areas,
as long it meets some basic requirements, such as the architecture type and operating system.
shellcode is written in assembly, which means that while it's more difficult to create,
it's much smaller, due to the lack of abstraction. so, let's get started, shall wee?
our first shellcode will perform something very simple. it will call the
exit() syscall in linux. first, let's take a look at the syntax of the
int sys_exit(int status)
-terminates the current process
-status is the return code
here's the code that i wrote to call exit(). (this code is for use in NASM)
this is equivalent to the following code in C:
write those in your favorite text editor, then assemble it and link it.
here's what i did.
finally, we start to see some results from our work! the shellcode is
"xb8x01x00x00x00xbbx00x00x00x00xcdx80" ! but, there's an
obvious problem with this shellcode, and anyone who uses strings in C
will see it instantly. strings cannot contain NULL bytes, because a NULL
byte is used to signify the end of the string. which means, the
vulnerable program would stop reading after "xb8x01". this is a very
bad thing indeed. let's try writing one again, with this knowledge.
first, we notice that 'mov eax, 1' generated 3 null bytes. now, think
about why this would happen. eax is a 32-bit register, and we're only
changing 1 byte with our value of 1. think about it this way:
eax: 00 00 00 00
1: 00 00 00 01
now you can see where the problem might arise. on another note, the
lower 16 bits of eax can be divided into two 8-bit registers, known as
ah and al. as you might be able to tell, ah is the high 8 bits, and al is
the low 8 bits. since 1 only takes up one byte, then we can simply move
it to al.
thus, "mov eax, 1"
becomes "mov al, 1"
now, we still have the second command to worry about. how can we set ebx
to 0 without moving the value of 0 to it? the answer lies within the
bitwise operator XOR. here's a table on how it works:
a | b | c
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 0
when a and b are the same value, then it returns 0. when they are
different, it returns 1. now, think about how this can be applied to
ebx. if you XOR ebx with itself, it will create 0, since ebx has the
same value as ebx (duh?! :P)
thus, "mov ebx, 0"
becomes "xor ebx, ebx"
make the following changes to your shellcode, and re-assemble and link
it. then run 'objdump -d exit' again, and this should be your shiny new
exit: file format elf32-i386
Disassembly of section .text:
8048080: b0 01 mov $0x1,%al
8048082: 31 db xor %ebx,%ebx
8048084: cd 80 int $0x80
thus, our new shellcode is "xb0x01x31xdbxcdx80" ! and, it's NULL
free! next, try using these techniques to create shellcode that spawns a
Cast your vote on this article 10 - Highest, 1 - Lowest
Comments: Published: 12 comments.
HackThisSite is is the collective work of the HackThisSite staff, licensed under a CC BY-NC license.
We ask that you inform us upon sharing or distributing.