Возможно вы искали: 'King of the Road'

May 15 2025 18:19:30
  • Как сделать 8Gamers.Ru домашней страницей?
  • Игры
    • База данных по играх
    • Игровые новости
    • Игровая индустрия
    • Обзоры на игры
    • Прохождения игр
    • Гайды к играм
    • Превью о играх
    • Игровые тизеры
    • Игровые арты
    • Игровые обои
    • Игровые скриншоты
    • Игровые обложки
    • Игровые трейлеры
    • Игровое видео
    • Вышедшие игры
    • Ближайшие релизы игр
  • Кино и ТВ
    • База данных по кино
    • Статьи о кино
    • Постеры
    • Кадры из кино
    • Кино трейлеры
    • Сегодня в кино
    • Скоро в кино
  • Комиксы и манга
    • Манга по алфавиту
    • База данных по комиксах
    • Читать онлайн комиксы
    • Читать онлайн манга
    • База персонажей
  • Читы и коды
    • Чит-коды для PC игр
    • Чит-коды для консольных игр
    • Трейнеры
    • Коды Game Genie
  • Моддинг
    • Модификации
    • Карты к играм
    • Программы для моддинга
    • Статьи о моддинге
  • Геймдев
    • Всё о создании игр
    • Список движков
    • Утилиты в помощь игроделу
    • Конструкторы игр
    • Игровые движки
    • Библиотеки разработки
    • 3D-модели
    • Спрайты и тайлы
    • Музыка и звуки
    • Текстуры и фоны
  • Рецензии
    • Игры
    • Кино
    • Аниме
    • Комиксы
    • Мангу
    • Саундтреки
  • Саундтреки
    • Лирика
  • Файлы
    • Патчи к играм
    • Русификаторы к играм
    • Сохранения к играм
    • Субтитры к кино
  • Медиа
    • Видео
    • Фото
    • Аудио
    • Фан-арты
    • Косплей
    • Фото с виставок
    • Девушки из игр
    • Рисунки
    • Рисуем онлайн
    • Фотохостинг
  • Юмор
    • Анекдоты
    • Афоризмы
    • Истории
    • Стишки и эпиграммы
    • Тосты
    • Цитаты
  • Флеш
    • Азартные
    • Аркады
    • Бродилки
    • Гонки
    • Для девочек
    • Для мальчиков
    • Драки
    • Квесты
    • Леталки
    • Логические
    • Мультфильмы
    • Открытки
    • Приколы
    • Разное
    • Спорт
    • Стратегии
    • Стрелялки
Статистика

Статей: 87772
Просмотров: 96111483
Игры
Injustice:  Gods Among Us
Injustice: Gods Among Us
...
Dark Souls 2
Dark Souls 2
Dark Souls II - вторая часть самой хардкорной ролевой игры 2011-2012 года, с новым героем, сюжето...
Battlefield 4
Battlefield 4
Battlefield 4 - продолжение венценосного мультиплеер-ориентированного шутера от первого ли...
Кино
Steins;Gate
Steins;Gate
Любители японской анимации уже давно поняли ,что аниме сериалы могут дать порой гораздо больше пи...
Ку! Кин-дза-дза
Ку! Кин-дза-дза
Начинающий диджей Толик и всемирно известный виолончелист Владимир Чижов встречают на шумной моск...
Обзоры на игры
• Обзор Ibara [PCB/PS2] 18357
• Обзор The Walking ... 18801
• Обзор DMC: Devil M... 19879
• Обзор на игру Valk... 15877
• Обзор на игру Stars! 17764
• Обзор на Far Cry 3 17948
• Обзор на Resident ... 16024
• Обзор на Chivalry:... 17508
• Обзор на игру Kerb... 17981
• Обзор игры 007: Fr... 16619
Превью о играх
• Превью к игре Comp... 17960
• Превью о игре Mage... 14464
• Превью Incredible ... 14721
• Превью Firefall 13479
• Превью Dead Space 3 16334
• Превью о игре SimC... 14730
• Превью к игре Fuse 15442
• Превью Red Orche... 15542
• Превью Gothic 3 16343
• Превью Black & W... 17354
Главная » Статьи » Разное » [Phrack] A Content-Blind Cancelbot for Usenet (CBCB) (security news)

[Phrack] A Content-Blind Cancelbot for Usenet (CBCB) (security news)

Ключевые слова: security, news, (найти похожие документы)

Subject: [Phrack] A Content-Blind Cancelbot for Usenet (CBCB)
.oO Phrack Magazine Oo.

Volume Seven, Issue Forty-Nine

File 09 of 16

by Dr.Dimitri Vulis (KOTM)

A Content-Blind Cancelbot for Usenet (CBCB)

Usenet News is a popular system for transmitting articles. Historically it
used to propagate over UUCP. However today most of the transmission is done
over the Internet TCP/IP connections using the NNTP protocol (RFC 977).

Each article consists of a series of headers of the form
Keyword: value
followed by a blank line, followed by the body of the message.
Some required headers are self-explanatory: From:, Date:, Subject:.

The Newsgroups: header identifies a series of keywords that can be used
to search for articles in the newsfeed. For example:
Newsgroups: news.admin.policy,comp.lang.c
identifies a Usenet article relevant to both Usenet administrative policy
and to the C computer language.

The Message-Id: header uniquely identifies each article. For example:
Message-Id: <12341223@whitehouse.gov>
The message-ids are not supposed to be recycled.

The cancelbot program is supposed to search the user-specified newsgroups for
articles whose headers match user-specified regular expressions and to issue
special 'cancel' control articles. It will copy some of the headers from the
original message and add a special header:
Control: cancel <message-id>

This program is an NNTP client. Much of the processing is offloaded to an
NNTP server, to which the cancelbot talks using the Internet sockets protocol.

This cancelbot does not look at article bodies and is therefore content-blind.

Inputs:

argv[1] (required) hosts file

A line that starts with # is a comment. Otherwise, each line contains the
following 5 fields:

1. hostname (some.domain.com) or ip address (a.b.c.d)
2. port (normally 119)
3. Y/N - do we ask this host for NEWNEWS/HEADER?
4. I/P/N - do we inject cancels to this host with IHAVE, POST, not at all
5. Timeout - the number of seconds to wait for a response from this server.

Example of a hosts file:

# ask the local server for new news and post back the cancels
127.0.0.1 119 Y P 60
# don't get message-ids from remote server, but give it cancels via IHAVE
news.xx.net 119 N I 300


argv[2] (required) target file

A line that starts with # is a comment. Otherwise, each line contains the
following 9 fields:

1. List of newsgroups to be scanned for new messages. This is not interpreted
by the cancelbot, but passed on to the NNTP server. Per RFC 997, multiple
groups can be separated by commas. Asterisk "*" may be used to match multiple
newsgroup names. The exclamation point "!" (as the first character) may be used
to negate a match. Warning: specifying a single * will generate a lot of data.

Example: news.groups,comp.*,sci.*,!sci.math.*

2. A watchword (case-sensitive) that needs to be contained in the article
headers for the cancel to be issued.

3. Format of the Subject: header in the cancel article.
C - Subject cancel <message-id> (same as Control:)
O - Subject: header copied from the original article
N - none.
If N is specified, then Subject: MUST be provided in the file appended to
the header, or the cancel won't propagate.

4. cancel message-id prefix
normally cancel. or cn.

Most cancellation articles follow the so-called $alz convention:
Control: cancel <message.id>
Message-id: <cancel.message.id>
However this is not a requirement.

5. path constant (string to put in path). May be 'none'.
6. path copy # (number of elements to copy from the right, may be 0)

Explanation of these two parameters:
each Usenet article contains the "Path:" header with a list of hosts separated
by explanation marks. For example:
Path: ohost1!ohost2!ohost3!ohost4
If you specify path constant of "nhosta!nhostb" and path copy of 2
then the path written by cbcb will be
Path: nhosta!nhostb!ohost3!ohost4

7. Name of the file appended to the header or 'none'

Examples:

# should be supplied as a courtesy
X-Cancelled-By: Cancelbot
# if and only if target file field 3 contains 'N':
Subject: Cancelling a Usenet article
# only if posting via IHAVE:
NNTP-Posting-Host: usenet.cabal.org

8. Name of the file that will become the body of the cancel or 'none'

If 'none' is specified, the default will be
"Please cancel this article."

9. The string to be prepended to the newsgroups. Normally 'none',
but may be set to something like misc.test (or misc.test,alt.test).

Example of a target file:

# delete all articles that mention C++ (but not c++)
comp.lang.c.* C++ C cancel. cyberspam 3 can.hdr none none
# no sex in the sci hierarchy, and add misc.test to the cancel
sci.* sex C cn. plutonium 2 can1.hdr can.txt misc.test

argv[3] (optional) datestamp, YYMMDD. If not specified, default is 900101. Only
articles after this date are examined. This parameter is not processed by the
cancelbot, but passed on to the NNTP server. It should normally be specified
so as not to look at old Usenet articles.

argv[4] (optional) timestamp, digits HHMMSS, where HH is hours on the 24-hour
clock, MM is minutes 00-59, and SS is seconds 00-59. If not specified, default
is 000000. Note that both datestamp and timestamp are in Greenwich mean time.

---------------8<-------cut me loose!-------------->8--------------------------
ed-note:
To compile, you must define an OS type (under gcc, this is accomplished using
the -Dmacro directive). Under Unix, for example:
gcc -DCBCB_UNIX -o cancelbot cbcb.c

---------------8<-------cut me loose!-------------->8--------------------------

cbcb.c:
/*

Context-blind CancelBot 0.9 04/01/96

Description of operations:

Open socket connections to the hosts listed in the hosts file

loop on targets
{
loop on servers
{
if (newnews_flag=='Y')
{
send NEWNEWS newsgroups datestamp timestamp GMT to this socket
receive a list of message-ids and save them in a LIFO linked list
loop on message-ids
{
send HEADER message-id to this server's socket
receieve a header
if the header contains the watchword
{
compose a cancel according to the target file specifications
loop on servers
{
if post_flag is P or I
send the cancel to this server's socket using posting method
}
}
delete this message-id from the linked list
}
}
}
}

*/

#ifndef CBCB_UNIX
#ifndef CBCB_VMS
#ifndef CBCB_NT
#ifndef CBCB_OS2
#error One of (CBCB_UNIX, CBCB_VMS, CBCB_NT, CBCB_OS2) must be defined
#endif
#endif
#endif
#endif

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>

/* various flavors of Unix */

#ifdef CBCB_UNIX
/* gcc -DCBCB_UNIX cbcb.c -o cbcb */
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
/* perror to be called after failed socket calls */
#define perror_sock perror
/* how to close a socket */
#define close_sock close
#endif

/* Windows NT, /subsystem:console. The executable is supposed to work
under NT and Windows 95, but not under Win32s. */

#ifdef CBCB_NT
/* important note: when compiling on NT, say something like
cl /DCBCB_NT /Ogaityb1 /G5Fs /ML cbcb.c wsock32.lib */
#include <winsock.h>
/* regular perror doesn't work with WinSock under NT */
#define perror_sock(s) fprintf(stderr,"%s : WinSock error %dn",s,WSAGetLastError())
/* regular close doesn't work with WinSock under NT */
#define close_sock closesocket
/* NT doesn't understand unix-style sleep in seconds */
#define sleep(n) Sleep(n*1000)
#endif

/* DEC VAX/VMS */

#ifdef CBCB_VMS
/* important note: when compiling on VAX/VMS, say something like
cc/define=CBCB_VMS cbcb/nodebug/optimize=(disjoint,inline)
link cbcb/nouserlib/notraceback,sys$library:ucx$ipc.olb/lib,-
sys$library:vaxcrtl.olb/lib
(to link in shared routines)
*/
#include <types.h>
#include <socket.h>
#include <netdb.h>
#include <in.h>
#include <inet.h>
#include <time.h>
#include <unixio.h>
#define perror_sock perror
#define close_sock close
#endif

/* IBM OS/2 - link with tcpip.lib */

#ifdef CBCB_OS2
#define OS2
/* we will use a BSD-like select, not Oleg's hack */
#define BSD_SELECT
#define INCL_DOSPROCESS
#include <bsedos.h> /* DosSleep */
#include <systypes.h>
#include <syssocket.h>
#include <sysselect.h>
#include <netinetin.h>
/*#include <arpainet.h>*/
#include <netdb.h>
/* perror to be called after failed socket calls */
#define perror_sock fprintf(stderr,"%s : tcp error %dn",s,tcperrno())
/* how to close a socket */
#define close_sock soclose
#define sleep(n) DosSleep(n/1000)
#endif

/*

Future Macintosh notes: Need Apple's MPW (Macintosh Programmer's Workshop).
Build CBCB as an MPW tool. Set the Macintosh file type to MPST and the
Macintosh creator to MPS, so we can use stdout and stderr.

Sockets are supposed to be available on the Mac.

*/

#ifndef FD_ZERO
/* macros for select() not defined on VAX or HPUX
However they are defined to be something completely different
under NT WinSock, so we must use macros */
#define fd_set int
#define FD_ZERO(p) {*(p)=0;}
#define FD_SET(s,p) {*(p)|=(1<<(s));}
#define FD_ISSET(s,p) ((*(p)&(1<<(s)))!=0)
#endif

/* file pointers */
FILE *sptr, /* hosts file */
*tptr; /* target file*/

/* there's a reason for making all these variables static. If I weren't lazy,
I would have put them in their respective functions with 'static' */

#define MAXHOSTS 100

struct {
int cfd; /* socket handle */
char newnews_flag;
char post_flag;
int timeout;
} hosts[MAXHOSTS];
int nhosts;

short int port;

#define ASCII_CR 13
#define ASCII_LF 10

#define BUFFERSIZE 2048

#define BUFFERBIGSIZE 20480
char buffer_big[BUFFERBIGSIZE];

struct _msgidq {
char *msgid;
struct _msgidq *next;
};

struct _msgidq *msg_queue,*msg_t;

int parse_state, /* for parsing server responses */
h_flag,d_flag; /* shortcut for states when parsing headers */

char hostname[BUFFERSIZE];
char buffer[BUFFERSIZE];
char extra_header[BUFFERSIZE];
char extra_body[BUFFERSIZE];
int file_rec;
char newsgroups[BUFFERSIZE]; /* target field 1 */
char watchword[BUFFERSIZE]; /* target field 2 */
char subject_flag; /* target field 3 */
char cmsg_id_prefix[BUFFERSIZE]; /* target field 4 */
char path_const[BUFFERSIZE]; /* target field 5 */
int path_num; /* target field 6 */
char hdr_fname[BUFFERSIZE]; /* target field 7 */
char txt_fname[BUFFERSIZE]; /* target field 8 */
char extra_ngrp[BUFFERSIZE]; /* target field 9 */

char *datestamp,*timestamp; /* for the NEWNEWS command */
char *sznone="none";
char *szcabal=" Usenet@Cabal";
char *szsubject="Subject:";
char *szsubjectc="Subject: cmsg";
char *szendl="rn";
char *szempty="";

int nretry; /* number of retries in various places */
int nbytes;
int host1,host2,i,j; /* loop indices */

#define NOLDHEADERS 8
/* We're interested in 8 original headers :

Path: 0 (requires special handling)
From: 1
Sender: 2
Approved: 3
Newsgroups: 4
Date: 5
Subject: 6
Organization: 7

*/

char *h_ptr[NOLDHEADERS];
char *t_ptr[3];

/* ANSI function prototypes */
int cbcb_parse_hosts(void);
int cbcb_parse_targets(void);
int cbcb_process_target(void);
int cbcb_parse_message_ids(void);
int cbcb_process_article(char *);
int cbcb_get_headers(void);
void cbcb_save_headers(void);
void cbcb_save_header(int);
int cbcb_flush_sock(int);
int cbcb_test_sock(int);
int cbcb_recv_resp(int,char);
int cbcb_copy_buffer(char *);

int main(int argc,char*argv[])
{

/* process the arguments */

if (argc<3 || argc>5)
{
fprintf(stderr,"Usage: cbcb hostfile targetfile [datestamp] [timestamp]n");
return(1);
}

if (argc<4)
datestamp="900101";
else
datestamp=argv[3];

if (argc<5)
timestamp="000000";
else
timestamp=argv[4];

/* open the hosts file */

if (NULL==(sptr=fopen(argv[1],"r")))
{
perror("open()");
fprintf(stderr,"cbcb cannot open hosts file %sn",argv[1]);
return(0);
}

/* open the target file */

if (NULL==(tptr=fopen(argv[2],"r")))
{
perror("open()");
fprintf(stderr,"cbcb cannot open target file %sn",argv[2]);
return(0);
}

#ifdef SIGPIPE
signal(SIGPIPE,SIG_IGN); /* ignore broken pipes if this platform knows them */
#endif

/* establish the connections to the NNTP servers */

if (0==cbcb_parse_hosts())
{
fprintf(stderr,"cbcb unable to connect to any NNTP serversn");
return(1);
}

fclose(sptr);

if (!cbcb_parse_targets())
{
fprintf(stderr,"cbcb encountered an error processing targetsn");
return(1);
}

fclose(tptr);

/* final cleanup */
for (i=0; i<nhosts; i++)
close_sock(hosts[i].cfd);
#ifdef CBCB_NT
WSACleanup();
#endif

return(0);
}


int cbcb_parse_hosts(void)
{
unsigned long host_ip;
struct hostent *host_struct;
struct in_addr *host_node;
/*
struct servent *sp;
*/
struct sockaddr_in serverUaddr;
#ifdef CBCB_NT
WSADATA wsaData; /* needed for WSAStartup */
#endif

#ifdef CBCB_NT
if (WSAStartup(MAKEWORD(1,1),&wsaData))
{
perror_sock("WSAStartup()");
fprintf(stderr,"couldn't start up WinSockn");
return(0);
}
fprintf(stderr,"Found WinSock: %sn",wsaData.szDescription);
#endif

#ifdef CBCB_OS2
if (0!=sock_init())
{
perror_sock("sock_init()");
fprintf(stderr,"couldn't start up sockets - is inet.sys running?n");
return(0);
}
#endif

/*
if (NULL==(sp=getservbyname("nntp","tcp")))
{
fprintf(stderr,"Can't find the NNTP portn");
return(0);
}
...
serverUaddr.sin_port=(sp->s_port);
*/

/* loop on the hosts file */
nhosts=0;
file_rec=0;
while(NULL!=fgets(buffer,sizeof(buffer),sptr))
{
file_rec++;
if (*buffer=='#')
continue;
if (nhosts>=MAXHOSTS)
{
fprintf(stderr,"Please increase MAXHOSTSn");
break;
}
if (5!=sscanf(buffer,"%2048s %hd %c %c %d",
hostname,&port,&hosts[nhosts].newnews_flag,&hosts[nhosts].post_flag,
&hosts[nhosts].timeout))
{
fprintf(stderr,"Error parsing host file line %d "%s"n",file_rec,buffer);
continue;
}
/* verify that the newnews flag is Y or N */
if (hosts[nhosts].newnews_flag=='n')
hosts[nhosts].newnews_flag='N';
else if (hosts[nhosts].newnews_flag=='y')
hosts[nhosts].newnews_flag='Y';
else if (hosts[nhosts].newnews_flag!='Y'&&hosts[nhosts].newnews_flag!='N')
{
fprintf(stderr,"Newnews flag %c, must be Y or N on line %dn",
hosts[nhosts].newnews_flag,file_rec);
continue;
}
/* verify that the posting flag is P, or I, or N */
if (hosts[nhosts].post_flag=='i')
hosts[nhosts].post_flag='I';
else if (hosts[nhosts].post_flag=='p')
hosts[nhosts].post_flag='P';
else if (hosts[nhosts].post_flag=='n')
hosts[nhosts].post_flag='N';
else if (hosts[nhosts].post_flag!='I'&&hosts[nhosts].post_flag!='P'&&hosts[nhosts].post_flag!='N')
{
fprintf(stderr,"Posting flag %c, must be I, or P, or N on line %dn",
hosts[nhosts].post_flag,file_rec);
continue;
}
/* translate the hostname into an ip address. If it starts with a digit,
try to interpret it as a A.B.C.D address */
if (!isdigit(*hostname)||(0xFFFFFFFF==(host_ip=inet_addr(hostname))))
{
if (NULL==(host_struct=gethostbyname(hostname)))
{
perror("gethostbyname");
fprintf(stderr,"Can't resolve host name %s to ip on line %dn",
hostname,file_rec);
continue;
}
host_node=(struct in_addr*)host_struct->h_addr;
fprintf(stderr,"Note: Using NNTP server at %sn",inet_ntoa(*host_node));
host_ip=host_node->s_addr;
}

/* fill in the address to connect to */
memset(&serverUaddr,0,sizeof(serverUaddr));
serverUaddr.sin_family=PF_INET;
serverUaddr.sin_addr.s_addr=/*htonl*/(host_ip); /* already in net order */
serverUaddr.sin_port=htons(port);

/* try to create a socket */
if ((hosts[nhosts].cfd=socket(AF_INET,SOCK_STREAM,0))<0)
{
perror_sock("socket()");
continue;
}

conn1:
if (0>=connect(hosts[nhosts].cfd,(struct sockaddr*)&serverUaddr,sizeof(serverUaddr)))
goto conn2; /* we use goto so we can use continue */
if (nretry>10)
{
fprintf(stderr,"give up trying to connect to %s port %hd on line %dn",
hostname,port,file_rec);
close_sock(hosts[nhosts].cfd);
hosts[nhosts].newnews_flag=hosts[nhosts].post_flag='N';
continue;
}
perror_sock("connect()");
nretry++;
sleep(1);
goto conn1;
conn2:
if (!cbcb_recv_resp(nhosts,'2'))
{
fprintf(stderr,"NNTP problem after connecting to %s port %hd on line %dn",
hostname,port,file_rec);
close_sock(hosts[nhosts].cfd);
hosts[nhosts].newnews_flag=hosts[nhosts].post_flag='N';
continue;
}
nhosts++;
}

return(nhosts);
}

int cbcb_parse_targets(void)
{

file_rec=0;
while(fgets(buffer,sizeof(buffer),tptr)) /* read a target line */
{
file_rec++;
if (*buffer=='#') /* comment */
continue;
/* parse the buffer into the 8 fields */

if (9!=sscanf(buffer,"%2048s %2048s %c %2048s %2048s %d %2048s %2048s %2048s",
newsgroups, watchword, &subject_flag, cmsg_id_prefix, path_const,
&path_num, hdr_fname, txt_fname, extra_ngrp))
{
fprintf(stderr,"Error parsing 8 fields on line %d "%s"n",
file_rec,buffer);
continue;
}

/* verify that the subject flag is C, O, or N */

if (subject_flag=='c')
subject_flag='C';
else if (subject_flag=='o')
subject_flag='O';
else if (subject_flag=='n')
subject_flag='N';
else if (subject_flag!='C'&&subject_flag!='O'&&subject_flag!='N')
{
fprintf(stderr,"Subject flag %c, must be C, O, or N on line %dn",
subject_flag,file_rec);
continue;
}

if (0==strcmp(path_const,sznone)) /* if 'none' is specified */
{
if (path_num==0)
{
fprintf(stderr,"Can't have path_const none and path_num 0n");
continue;
}
path_const[0]=0;
}
else /* if not none, append bang if needed */
{
i=strlen(path_const);
if (path_const[i-1]!='!')
{
path_const[i]='!';
path_const[i+1]=0;
}
}

if (0==strcmp(extra_ngrp,sznone)) /* if 'none' is specified */
extra_ngrp[0]=0;
else /* if not none, append comma if needed */
{
i=strlen(extra_ngrp);
if (extra_ngrp[i-1]!=',')
{
extra_ngrp[i]=',';
extra_ngrp[i+1]=0;
}
}

/* read the extra header lines */

if (0==strcmp(hdr_fname,sznone)) /* if 'none' is specified */
*extra_header=0;
else
{
/* try to open the specified file */
if (NULL==(sptr=fopen(hdr_fname,"r")))
{
perror("open()");
fprintf(stderr,"cbcb cannot open extra-header file %sn",hdr_fname);
continue;
}
nbytes=fread(buffer,1,BUFFERSIZE,sptr);
fclose(sptr);
if (nbytes>=BUFFERSIZE)
fprintf(stderr,"extra-header file %s is too longn",hdr_fname);
if (!cbcb_copy_buffer(extra_header))
{
fprintf(stderr,"error in header filen");
continue;
}
}

/* read the body the same way */

if (0==strcmp(txt_fname,sznone)) /* if 'none' is specified */
strcpy(extra_body,"Please cancel this articlern");
else
{
/* try to open the specified file */
if (NULL==(sptr=fopen(txt_fname,"r")))
{
perror("open()");
fprintf(stderr,"cbcb cannot open body file %sn",txt_fname);
continue;
}
nbytes=fread(buffer,1,BUFFERSIZE,sptr);
fclose(sptr);
if (nbytes>=BUFFERSIZE)
fprintf(stderr,"body file %s is too longn",txt_fname);
if (!cbcb_copy_buffer(extra_body))
{
fprintf(stderr,"error in body filen");
continue;
}
}

if (!cbcb_process_target()) /* process otherwise. warn and go on if error */
fprintf(stderr,"cbcb encountered a problem processing target, line %dn",
file_rec);
}

return(1);
}

int cbcb_process_target(void)
{

/* loop on hosts */
for (host1=0; host1<nhosts; host1++)
if (hosts[host1].newnews_flag=='Y') /* if we want to get message-ids from it */
{
cbcb_flush_sock(hosts[host1].cfd);

/* compose the rfc 977 newnews command. Ansi C would let us write
nbytes=sprintf(..), but gcc has a non-compilant sprintf which return
buffer instead, so we must use strlen */
sprintf(buffer,"NEWNEWS %s %s %s GMTrn",
newsgroups,datestamp,timestamp);
nbytes=strlen(buffer);
/* send the command to the server */
if (nbytes!=send(hosts[host1].cfd,buffer,nbytes,0))
{
perror_sock("NEWNEWS send()");
continue;
}
/* the server is supposed to return a list of message-ids now */
if (!cbcb_parse_message_ids())
fprintf(stderr,"Problem parsing message-idsn");
/* no 'continue': even if we return a partial queue, try to process it */

/* loop through headers, newest first */
while (msg_queue)
{
msg_t=msg_queue;
if (!cbcb_process_article(msg_queue->msgid))
fprintf(stderr,"Problem processing article <%s>n",msg_queue->msgid);
msg_queue=msg_queue->next;
free(msg_t);
}

}

return(1);
}


int cbcb_parse_message_ids(void)
{

msg_queue=NULL;
parse_state=7;

nretry=0;
recv_msgids:
if (!cbcb_test_sock(hosts[host1].cfd)) /* nothing to read */
{
if (nretry>hosts[host1].timeout)
{
fprintf(stderr,"timeout waiting to recv message-idsn");
return(0);
}
fprintf(stderr,".");
nretry++;
sleep(1);
goto recv_msgids;
}
nbytes=recv(hosts[host1].cfd,buffer,sizeof(buffer),0);
if (nbytes<0) /* an error shouldn't happen here */
{
perror_sock("NEWNEWS recv()");
return(0);
}
#ifdef DEBUG
fwrite(buffer,1,nbytes,stdout); /* for debugging only!! */
#endif
/* now see if what we received makes sense */
for (i=0; i<nbytes; i++)
{
switch(parse_state)
{
case 0:
if (buffer[i]=='.')
parse_state=4;
else if (buffer[i]!='<')
goto recv_bad_msg_id;
else
{
j=0;
parse_state=1;
}
break;
case 1:
if (buffer[i]=='>')
{
/* add to the queue */
msg_t=(struct _msgidq*)malloc(sizeof(struct _msgidq));
if (msg_t==NULL)
{
fprintf(stderr,"malloc failedn");
return(0);
}
msg_t->msgid=(char*)malloc(j+1);
if (msg_t->msgid==NULL)
{
free(msg_t);
fprintf(stderr,"malloc failedn");
return(0);
}
memcpy(msg_t->msgid,buffer_big,j);
*(msg_t->msgid+j)=0;
msg_t->next=msg_queue;
msg_queue=msg_t;

parse_state=2;
}
else
{
if (j>=BUFFERBIGSIZE)
{
fprintf(stderr,"Please increase BUFFERBIGSIZEn");
return(0);
}
buffer_big[j]=buffer[i];
j++;
/* parse_state=1; */
}
break;
case 2:
if (buffer[i]==ASCII_CR)
parse_state=3;
else
goto recv_bad_msg_id;
break;
case 3:
if (buffer[i]==ASCII_LF)
parse_state=0;
else
goto recv_bad_msg_id;
break;
case 4:
if (buffer[i]==ASCII_CR)
parse_state=5;
else
goto recv_bad_msg_id;
break;
case 5:
if (buffer[i]==ASCII_LF)
parse_state=6;
else
goto recv_bad_msg_id;
break;
case 6: /* more data after final . */
goto recv_bad_msg_id;
case 7: /* initial, really */
if (buffer[i]=='2')
parse_state=8;
else
goto recv_bad_msg_id;
break;
case 8:
if (buffer[i]==ASCII_CR)
parse_state=3;
break;
}
}

if (parse_state!=6)
goto recv_msgids;
/* normal competion */
return(1);

recv_bad_msg_id:
fprintf(stderr,"Unexpected response (expected message-ids) ");
if (i)
{
fprintf(stderr,"after "");
fwrite(buffer,1,i,stderr);
fprintf(stderr,"" ");
}
if (i<nbytes)
{
fprintf(stderr,"before "");
fwrite(buffer+i,1,nbytes-i,stderr);
fprintf(stderr,""");
}
fprintf(stderr,"n");
return(0);
}

int cbcb_process_article(char *msgid)
{

/* if there is any leftover data in the socket, get it out */
cbcb_flush_sock(hosts[host1].cfd);

/* compose the rfc 977 head command */
sprintf(buffer,"HEAD <%s>rn",msgid);

/* send the command to the server */
nbytes=strlen(buffer);
if (nbytes!=send(hosts[host1].cfd,buffer,nbytes,0))
{
perror_sock("HEAD send()");
return(0);
}

/* the server is supposed to return the article headers now */

if (!cbcb_get_headers())
{
fprintf(stderr,"Problem retrieving headersn");
return(0);
}

if (!strstr(buffer_big,watchword))
return(1); /* no match, nothing to do */

/* found the watchword: let's cancel */
cbcb_save_headers();
sprintf(buffer_big,"
Path: %s%srn
From:%srn
Sender:%srn
Approved:%srn
Newsgroups: %s%srn
Date:%srn
%s%s%s
Organization:%srn
Control:%srn
Message-ID: <%s%s>rn
%s
rn
%s
.rn",
path_const,
h_ptr[0],h_ptr[1],h_ptr[2],h_ptr[3],extra_ngrp,h_ptr[4],h_ptr[5],
t_ptr[0],h_ptr[6],t_ptr[1],h_ptr[7],t_ptr[2],
cmsg_id_prefix,msgid,extra_header,extra_body);

fputs(buffer_big,stderr); /* to see what we're posting */

for (host2=0; host2<nhosts; host2++)
if (hosts[host2].post_flag=='P'||hosts[host2].post_flag=='I')
{
cbcb_flush_sock(hosts[host2].cfd);
if (hosts[host2].post_flag=='P')
{
/* send the command to the server */
if (6!=send(hosts[host2].cfd,"POSTrn",6,0))
{
perror_sock("POST send()");
continue;
}
}
else /*hosts[host2].post_flag=='I') */
{
sprintf(buffer,"IHAVE <%s%s>rn",cmsg_id_prefix,msgid);
nbytes=strlen(buffer);
/* send the command to the server */
if (nbytes!=send(hosts[host2].cfd,buffer,nbytes,0))
{
perror_sock("IHAVE send()");
continue;
}
}
if (!cbcb_recv_resp(host2,'3'))
{
fprintf(stderr,"NNTP problem while trying to postn");
continue;
}
nbytes=strlen(buffer_big);
if (nbytes!=send(hosts[host2].cfd,buffer_big,nbytes,0))
{
perror_sock("article send()");
continue;
}
if (!cbcb_recv_resp(host2,'2'))
{
fprintf(stderr,"NNTP problem after postingn");
continue;
}
}

return(1); /* all's well */
}

int cbcb_get_headers(void)
{

h_ptr[0]=h_ptr[1]=h_ptr[2]=h_ptr[3]=h_ptr[4]=h_ptr[5]=h_ptr[6]=h_ptr[7]=NULL;
h_flag=d_flag=parse_state=0;
nretry=0;
j=0;
/* recv */
recv_headers:

if (!cbcb_test_sock(hosts[host1].cfd)) /* nothing to read */
{
if (nretry>hosts[host1].timeout)
{
fprintf(stderr,"timeout waiting to recv article headersn");
return(0);
}
fprintf(stderr,".");
nretry++;
sleep(1);
goto recv_headers;
}

nbytes=recv(hosts[host1].cfd,buffer,sizeof(buffer),0);
if (nbytes<0) /* an error shouldn't happen here */
{
perror_sock("headers recv()");
return(0);
}
#ifdef DEBUG
fwrite(buffer,1,nbytes,stdout); /* for debugging only!! */
#endif
/* see if what we received makes sense */
for (i=0; i<nbytes; i++)
{
switch(parse_state)
{
case 0:
if (buffer[i]=='2')
parse_state=1;
else
goto recv_bad_header;
break;
case 1:
if (buffer[i]=='2')
parse_state=2;
else
goto recv_bad_header;
break;
case 2:
if (buffer[i]==ASCII_CR)
parse_state=3;
/*
else
parse_state=2;
*/
break;
case 3:
if (buffer[i]==ASCII_LF)
{
if (d_flag)
parse_state=5;
else
{
h_flag=1;
parse_state=4;
goto recv_header_save;
}
}
else
goto recv_bad_header;
break;
case 4:
if (buffer[i]==ASCII_CR) /* don't save cr's */
parse_state=3;
else
{
if (h_flag)
{
d_flag=0;
if (buffer[i]=='.')
d_flag=1;
else if (buffer[i]=='p'||buffer[i]=='P')
parse_state=10;
else if (buffer[i]=='f'||buffer[i]=='F')
parse_state=20;
else if (buffer[i]=='s'||buffer[i]=='S')
parse_state=30;
else if (buffer[i]=='a'||buffer[i]=='A')
parse_state=40;
else if (buffer[i]=='n'||buffer[i]=='N')
parse_state=50;
else if (buffer[i]=='d'||buffer[i]=='D')
parse_state=60;
else if (buffer[i]=='o'||buffer[i]=='O')
parse_state=70;
else if (buffer[i]==' '||buffer[i]=='t') /* space means continuation */
j--; /* backup over the lf */
h_flag=0;
}
else
d_flag=0;
goto recv_header_save;
}
break;
case 5: /* more data after the final . */
goto recv_bad_header;
/* we recognize these headers on the fly */
case 10:
if (buffer[i]=='a'||buffer[i]=='A')
parse_state=11;
else
parse_state=4;
goto recv_header_save;
case 11:
if (buffer[i]=='t'||buffer[i]=='t')
parse_state=12;
else
parse_state=4;
goto recv_header_save;
case 12:
if (buffer[i]=='h'||buffer[i]=='H')
parse_state=13;
else
parse_state=4;
goto recv_header_save;
case 13:
if (buffer[i]==':')
h_ptr[0]=buffer_big+j+1; /* Path: */
parse_state=4;
goto recv_header_save;
case 20:
if (buffer[i]=='r'||buffer[i]=='R')
parse_state=21;
else
parse_state=4;
goto recv_header_save;
case 21:
if (buffer[i]=='o'||buffer[i]=='O')
parse_state=22;
else
parse_state=4;
goto recv_header_save;
case 22:
if (buffer[i]=='m'||buffer[i]=='M')
parse_state=23;
else
parse_state=4;
goto recv_header_save;
case 23:
if (buffer[i]==':')
h_ptr[1]=buffer_big+j+1; /* From: */
parse_state=4;
goto recv_header_save;
case 30:
if (buffer[i]=='e'||buffer[i]=='E')
parse_state=31;
else if (buffer[i]=='u'||buffer[i]=='U')
parse_state=90;
else
parse_state=4;
goto recv_header_save;
case 31:
if (buffer[i]=='n'||buffer[i]=='N')
parse_state=32;
else
parse_state=4;
goto recv_header_save;
case 32:
if (buffer[i]=='d'||buffer[i]=='D')
parse_state=33;
else
parse_state=4;
goto recv_header_save;
case 33:
if (buffer[i]=='e'||buffer[i]=='E')
parse_state=34;
else
parse_state=4;
goto recv_header_save;
case 34:
if (buffer[i]=='r'||buffer[i]=='R')
parse_state=35;
else
parse_state=4;
goto recv_header_save;
case 35:
if (buffer[i]==':')
h_ptr[2]=buffer_big+j+1; /* Sender: */
parse_state=4;
goto recv_header_save;
case 40:
if (buffer[i]=='p'||buffer[i]=='P')
parse_state=41;
else
parse_state=4;
goto recv_header_save;
case 41:
if (buffer[i]=='p'||buffer[i]=='P')
parse_state=42;
else
parse_state=4;
goto recv_header_save;
case 42:
if (buffer[i]=='r'||buffer[i]=='R')
parse_state=43;
else
parse_state=4;
goto recv_header_save;
case 43:
if (buffer[i]=='o'||buffer[i]=='O')
parse_state=44;
else
parse_state=4;
goto recv_header_save;
case 44:
if (buffer[i]=='v'||buffer[i]=='V')
parse_state=45;
else
parse_state=4;
goto recv_header_save;
case 45:
if (buffer[i]=='e'||buffer[i]=='E')
parse_state=46;
else
parse_state=4;
goto recv_header_save;
case 46:
if (buffer[i]=='d'||buffer[i]=='D')
parse_state=47;
else
parse_state=4;
goto recv_header_save;
case 47:
if (buffer[i]==':')
h_ptr[3]=buffer_big+j+1; /* Approved: */
parse_state=4;
goto recv_header_save;
case 50:
if (buffer[i]=='e'||buffer[i]=='E')
parse_state=51;
else
parse_state=4;
goto recv_header_save;
case 51:
if (buffer[i]=='w'||buffer[i]=='W')
parse_state=52;
else
parse_state=4;
goto recv_header_save;
case 52:
if (buffer[i]=='s'||buffer[i]=='S')
parse_state=53;
else
parse_state=4;
goto recv_header_save;
case 53:
if (buffer[i]=='g'||buffer[i]=='G')
parse_state=54;
else
parse_state=4;
goto recv_header_save;
case 54:
if (buffer[i]=='r'||buffer[i]=='R')
parse_state=55;
else
parse_state=4;
goto recv_header_save;
case 55:
if (buffer[i]=='o'||buffer[i]=='O')
parse_state=56;
else
parse_state=4;
goto recv_header_save;
case 56:
if (buffer[i]=='u'||buffer[i]=='U')
parse_state=57;
else
parse_state=4;
goto recv_header_save;
case 57:
if (buffer[i]=='p'||buffer[i]=='P')
parse_state=58;
else
parse_state=4;
goto recv_header_save;
case 58:
if (buffer[i]=='s'||buffer[i]=='S')
parse_state=59;
else
parse_state=4;
goto recv_header_save;
case 59:
if (buffer[i]==':')
h_ptr[4]=buffer_big+j+2; /* Newsgroups:, skip space */
parse_state=4;
goto recv_header_save;
case 60:
if (buffer[i]=='a'||buffer[i]=='A')
parse_state=61;
else
parse_state=4;
goto recv_header_save;
case 61:
if (buffer[i]=='t'||buffer[i]=='T')
parse_state=62;
else
parse_state=4;
goto recv_header_save;
case 62:
if (buffer[i]=='e'||buffer[i]=='E')
parse_state=63;
else
parse_state=4;
goto recv_header_save;
case 63:
if (buffer[i]==':')
h_ptr[5]=buffer_big+j+1; /* Date: */
parse_state=4;
goto recv_header_save;
case 70:
if (buffer[i]=='r'||buffer[i]=='R')
parse_state=71;
else
parse_state=4;
goto recv_header_save;
case 71:
if (buffer[i]=='g'||buffer[i]=='G')
parse_state=72;
else
parse_state=4;
goto recv_header_save;
case 72:
if (buffer[i]=='a'||buffer[i]=='A')
parse_state=73;
else
parse_state=4;
goto recv_header_save;
case 73:
if (buffer[i]=='n'||buffer[i]=='N')
parse_state=74;
else
parse_state=4;
goto recv_header_save;
case 74:
if (buffer[i]=='i'||buffer[i]=='I')
parse_state=75;
else
parse_state=4;
goto recv_header_save;
case 75:
if (buffer[i]=='z'||buffer[i]=='Z')
parse_state=76;
else
parse_state=4;
goto recv_header_save;
case 76:
if (buffer[i]=='a'||buffer[i]=='A')
parse_state=77;
else
parse_state=4;
goto recv_header_save;
case 77:
if (buffer[i]=='t'||buffer[i]=='T')
parse_state=78;
else
parse_state=4;
goto recv_header_save;
case 78:
if (buffer[i]=='i'||buffer[i]=='I')
parse_state=79;
else
parse_state=4;
goto recv_header_save;
case 79:
if (buffer[i]=='o'||buffer[i]=='O')
parse_state=80;
else
parse_state=4;
goto recv_header_save;
case 80:
if (buffer[i]=='n'||buffer[i]=='N')
parse_state=81;
else
parse_state=4;
goto recv_header_save;
case 81:
if (buffer[i]==':')
h_ptr[7]=buffer_big+j+1; /* Organization: */
parse_state=4;
goto recv_header_save;
case 90:
if (buffer[i]=='b'||buffer[i]=='B')
parse_state=91;
else
parse_state=4;
goto recv_header_save;
case 91:
if (buffer[i]=='j'||buffer[i]=='J')
parse_state=92;
else
parse_state=4;
goto recv_header_save;
case 92:
if (buffer[i]=='e'||buffer[i]=='E')
parse_state=93;
else
parse_state=4;
goto recv_header_save;
case 93:
if (buffer[i]=='c'||buffer[i]=='C')
parse_state=94;
else
parse_state=4;
goto recv_header_save;
case 94:
if (buffer[i]=='t'||buffer[i]=='T')
parse_state=95;
else
parse_state=4;
goto recv_header_save;
case 95:
if (buffer[i]==':')
h_ptr[6]=buffer_big+j+1; /* Subject: */
parse_state=4;
goto recv_header_save;
default: /* how could we ever get here? */
goto recv_bad_header;
}
continue; /* ugly, branch around save */
recv_header_save:
if (j>=BUFFERBIGSIZE)
{
fprintf(stderr,"Please increase BUFFERBIGSIZEn");
return(0);
}
buffer_big[j++]=buffer[i];
} /* next i */
if (parse_state!=5)
goto recv_headers;

return(1);
recv_bad_header:
fprintf(stderr,"Unexpected response (expected headers) ");
if (i)
{
fprintf(stderr,"after "");
fwrite(buffer,1,i,stderr);
fprintf(stderr,"" ");
}
if (i<nbytes)
{
fprintf(stderr,"before "");
fwrite(buffer+i,1,nbytes-i,stderr);
fprintf(stderr,""");
}
fprintf(stderr,"n");
return(0);
}

void cbcb_save_headers(void)
{
/* now copy old headers to buffer for safekeeping */
/* only if buffer_big matched the pattern */

/* only Path: is special: no initial space */
if (h_ptr[0]==NULL) /* no path */
{
j=0;
h_ptr[0]=" ";
}
else
{
i=h_ptr[0]-buffer_big;
j=path_num;
while (buffer_big[i]!=ASCII_LF)
i++;
i--;
/* now go back and look for the last n bang-separated components, or the
beginning of path */
while (buffer_big[i]>' ' && j)
{
i--;
if (buffer_big[i]=='!')
j--;
}
i++;
j=0;
h_ptr[0]=buffer;
while (buffer_big[i]!=ASCII_LF)
buffer[j++]=buffer_big[i++];
buffer[j++]=0;
}

t_ptr[2]=buffer+j;
sprintf(t_ptr[2]," cancel <%s>",msg_queue->msgid);
j+=strlen(t_ptr[2])+1;

if (h_ptr[1]==NULL) /* no from? Highly unlikely */
h_ptr[1]=szcabal;
else
cbcb_save_header(1);
if (h_ptr[2]==NULL) /* sender */
h_ptr[2]=h_ptr[1];
else
cbcb_save_header(2);
if (h_ptr[3]==NULL) /* approved */
h_ptr[3]=h_ptr[2];
else
cbcb_save_header(3);
if (h_ptr[4]==NULL) /* no newsgroups? */
h_ptr[4]="control";
else
cbcb_save_header(4);
if (h_ptr[5]==NULL) /* no date??? */
h_ptr[5]=" 1 Jan 1990 00:00 GMT";
else
cbcb_save_header(5);
/* subject is special - must use flag */
if (subject_flag=='O')
{
if (h_ptr[6]==NULL)
h_ptr[6]=szcabal; /* no subject??? */
else
cbcb_save_header(6);
t_ptr[0]=szsubject;
t_ptr[1]=szendl;
}
else if (subject_flag=='C')
{
h_ptr[6]=t_ptr[2]; /* same as the Control: */
t_ptr[0]=szsubjectc;
t_ptr[1]=szendl;
}
else /* if (subject_flag=='N') */
{
t_ptr[0]=t_ptr[1]=h_ptr[6]=szempty;
}
if (h_ptr[7]==NULL) /* organization */
h_ptr[7]=szcabal;
else
cbcb_save_header(7);

#ifdef DEBUG
for (i=0; i<8; i++)
if (h_ptr[i])
printf("%d:%sn",i,h_ptr[i]);
#endif

}

void cbcb_save_header(int k)
{
i=h_ptr[k]-buffer_big;
h_ptr[k]=buffer+j;
while (buffer_big[i]!=ASCII_LF)
buffer[j++]=buffer_big[i++];
buffer[j++]=0;
}

int cbcb_flush_sock(int sock)
{
/* if there is any leftover data in the socket, get it out */
while (cbcb_test_sock(sock))
{
nbytes=recv(sock,buffer,sizeof(buffer),0);
if (nbytes<0)
perror_sock("flush recv()"); /* but don't abort */
else
fwrite(buffer,1,nbytes,stderr); /* display it, as it may be informative */
}
return(1);
}

/* use select to see if there's data here.
There don't seem to be any unixes left which understand poll and not select.*/
int cbcb_test_sock(int sock)
{
fd_set setm;
static struct timeval zerotime={0,0};

FD_ZERO(&setm);
FD_SET(sock,&setm);
if (select(sock+1,&setm,NULL,NULL,&zerotime)<0)
{
perror_sock("select()");
}
if (FD_ISSET(sock,&setm))
return(1);
else
return(0);
}

int cbcb_recv_resp(int host,char c)
{

parse_state=0;

nretry=0;
recv_resp:
if (!cbcb_test_sock(hosts[host].cfd)) /* nothing to read */
{
if (nretry>hosts[host].timeout)
{
fprintf(stderr,"timeout waiting to recv responsen");
return(0);
}
fprintf(stderr,".");
nretry++;
sleep(1);
goto recv_resp;
}
nbytes=recv(hosts[host].cfd,buffer,sizeof(buffer),0);
if (nbytes<0) /* an error shouldn't happen here */
{
perror_sock("response recv()");
return(0);
}
/* #ifdef DEBUG */
fwrite(buffer,1,nbytes,stdout); /* for debugging only!! */
/* #endif */
/* now see if what we received makes sense */
for (i=0; i<nbytes; i++)
{
switch(parse_state)
{
case 0:
if (buffer[i]==c)
parse_state=1;
else
goto recv_bad_resp;
break;
case 1:
if (buffer[i]==ASCII_CR)
parse_state=2;
break;
case 2:
if (buffer[i]==ASCII_LF)
parse_state=3;
else
goto recv_bad_resp;
break;
case 3: /* more data after final n */
goto recv_bad_resp;
}
}

if (parse_state!=3)
goto recv_resp;
/* normal competion */
return(1);

recv_bad_resp:
fprintf(stderr,"Unexpected response (expected %cxx message) ",c);
if (i)
{
fprintf(stderr,"after "");
fwrite(buffer,1,i,stderr);
fprintf(stderr,"" ");
}
if (i<nbytes)
{
fprintf(stderr,"before "");
fwrite(buffer+i,1,nbytes-i,stderr);
fprintf(stderr,""");
}
fprintf(stderr,"n");
return(0);
}

int cbcb_copy_buffer(char *s)
{
i=j=0;
if (nbytes>0&&buffer[nbytes-1]!='n')
buffer[nbytes++]='n';
buffer[nbytes]=0;

while (buffer[i])
{
if (j>=BUFFERSIZE)
{
fprintf(stderr,"File too bign");
return(0);
}
if (buffer[i]=='n')
*(s+(j++))='r';
*(s+(j++))=buffer[i++];
}
*(s+j)=0;
return(1);
}

---------------8<-------cut me loose!-------------->8--------------------------
896 Прочтений •  [[Phrack] A Content-Blind Cancelbot for Usenet (CBCB) (security news)] [08.05.2012] [Комментариев: 0]
Добавил: Ukraine Vova
Ссылки
HTML: 
[BB Url]: 
Похожие статьи
Название Добавил Добавлено
• [Phrack] A Content-Blind Cancelbot ... Ukraine Vova 08.05.2012
Ни одного комментария? Будешь первым :).
Пожалуйста, авторизуйтесь для добавления комментария.

Проект входит в сеть сайтов «8Gamers Network»

Все права сохранены. 8Gamers.NET © 2011 - 2025

Статьи
Рецензия на Pressure
Рецензия на Pressure
Чтобы обратить на себя внимание, начинающие маленькие разработчики, как правило, уходят в жанры, ...
Рецензия на Lost Chronicles of Zerzura
Рецензия на Lost Chron...
Игры, сделанные без любви и старания, похожи на воздушный шар – оболочка есть, а внутри пусто. Lo...
Рецензия на The Bridge
Рецензия на The Bridge
«Верх» и «низ» в The Bridge — понятия относительные. Прогуливаясь под аркой, можно запросто перей...
Рецензия на SimCity
Рецензия на SimCity
Когда месяц назад состоялся релиз SimCity, по Сети прокатилось цунами народного гнева – глупые ош...
Рецензия на Strategy & Tactics: World War 2
Рецензия на Strategy &...
Название Strategy & Tactics: World War II вряд ли кому-то знакомо. Зато одного взгляда на ее скри...
Рецензия на игру Scribblenauts Unlimited
Рецензия на игру Scrib...
По сложившейся традиции в информационной карточке игры мы приводим в пример несколько похожих игр...
Рецензия на игру Walking Dead: Survival Instinct, The
Рецензия на игру Walki...
Зомби и продукция-по-лицензии — которые и сами по себе не лучшие представители игровой биосферы —...
Обратная связь | RSS | Донейт | Статистика | Команда | Техническая поддержка