パスワードを誤って入力した場合-btmpパケット



より具体的な例を挙げると、sudopw入力が間違っている場合は、pwの再入力を求めるメッセージが表示されますが、linuxログイン用のgettyagettyはidからpwの再入力を要求します.何の考えもなく正しいパスワードを再入力すれば、コンソールに直接露出することができます.

再ログインに成功しても、さっきのことはログに残ります./var/log/btmpの権限はroot:utmpですが、私のパスワードはあるログにコメントを残していて、本当に不快です.
lastb is the same as last, except that by default it shows a log of the/var/log/btmp file, which contains all the bad login attempts.man 1 lastを参照.man 5 utmpでは、「警告:utmpは、多くのシステムプログラム(愚かに)その完全性に依存するため、ユーザクラス「other」によって書き込むことができません.utmp書き込み可能なファイルをファイルの所有者およびグループの所有者以外のユーザーに残した場合、Youriskはシステムログファイルを偽造し、システムファイルを変更します.」しかし、これは悪意のある目的で修正されたものではないので、/var/log/btmpで特定の行を修正することができますか?開けると...

やはり自分で修正するのは難しいようですが...グーグルゲームはやったことあるけど「あれはそんなにやったんじゃない」「全部消せばいいじゃないか」似たような質問と答えしかありません.wtmpではman pageに構造があるがbtmpにはないのでlastbのソースコードを参照することにした.lastbutil-linuxに含まれ、ソースコードはここです。で見つけることができます.
このソースは、lastbではなくlastを含む.私が望むlastb実現を見つけるために、末尾から遡ると...
  • fprintf(out, _(" -f, --file <file> use a specific file instead of %s\n"), ctl->lastb ? _PATH_BTMP : _PATH_WTMP);ctl->lastbはlastとlastbを区別するフラグのようです.

  • プロセスwtmp file関数ではctl->lastbが真である場合list(ctl, &ut, ut.ut_tv.tv_sec, R_NORMAL);が見られる.
  • static int list(const struct last_control *ctl, struct utmpx *p, time_t logout_time, int what)のコメントは画面上の1行の情報を表示しており、正しいようです.
  • しかしlastbで呼び出されたlist関数をよく見るとstruct utmpxをパラメータとして受け入れ、btmp、wtmp、utmpはutmpフォーマットと同じであるべきだと思います.次に示すように、man 5 utmpに移動してstruct utmpを表示します.
    #define UT_LINESIZE      32
    #define UT_NAMESIZE      32
    #define UT_HOSTSIZE     256
    
    struct exit_status {              /* Type for ut_exit, below */
        short int e_termination;      /* Process termination status */
        short int e_exit;             /* Process exit status */
    };
    
    struct utmp {
        short   ut_type;              /* Type of record */
        pid_t   ut_pid;               /* PID of login process */
        char    ut_line[UT_LINESIZE]; /* Device name of tty - "/dev/" */
        char    ut_id[4];             /* Terminal name suffix,
                                         or inittab(5) ID */
        char    ut_user[UT_NAMESIZE]; /* Username */
        char    ut_host[UT_HOSTSIZE]; /* Hostname for remote login, or
                                         kernel version for run-level
                                         messages */
        struct  exit_status ut_exit;  /* Exit status of a process
                                         marked as DEAD_PROCESS; not
                                         used by Linux init(1) */
        /* The ut_session and ut_tv fields must be the same size when
           compiled 32- and 64-bit.  This allows data files and shared
           memory to be shared between 32- and 64-bit applications. */
    #if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32
        int32_t ut_session;           /* Session ID (getsid(2)),
                                         used for windowing */
        struct {
            int32_t tv_sec;           /* Seconds */
            int32_t tv_usec;          /* Microseconds */
        } ut_tv;                      /* Time entry was made */
    #else
         long   ut_session;           /* Session ID */
         struct timeval ut_tv;        /* Time entry was made */
    #endif
    
        int32_t ut_addr_v6[4];        /* Internet address of remote
                                         host; IPv4 address uses
                                         just ut_addr_v6[0] */
        char __unused[20];            /* Reserved for future use */
    };
    pid tは/usr/include/bits/typesizeであることに注意してください.h以下signed 32 bit integer,timevalを以下に示す.
    struct timeval
    {
    #ifdef __USE_TIME_BITS64
      __time64_t tv_sec;		/* Seconds.  */
      __suseconds64_t tv_usec;	/* Microseconds.  */
    #else
      __time_t tv_sec;		/* Seconds.  */
      __suseconds_t tv_usec;	/* Microseconds.  */
    #endif
    };
    grep -Rwn __time64_t /usr/include/bits/と同様に、各タイプのサイズで動作する.
    1./usr/include/bits/types.h:223:__STD_TYPE __TIME64_T_TYPE __time64_t;2./usr/include/bits/time64.h:30:# define __TIME64_T_TYPE __TIME_T_TYPE 33:# define __TIME64_T_TYPE __SQUAD_TYPE3./usr/include/bits/typesizes.h:64:#define __TIME_T_TYPE __SYSCALL_SLONG_TYPE4./usr/include/bits/typesizes.h:31:# define __SYSCALL_SLONG_TYPE __SQUAD_TYPE 34:# define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE5./usr/include/bits/types.h:116:# define __SQUAD_TYPE __int64_t 128:# define __SQUAD_TYPE long int6./usr/include/bits/types.h:44:typedef signed long int __int64_t;7./usr/include/bits/types.h:113:#define __SLONGWORD_TYPE long int8./usr/include/bits/types.h:162:__STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds. */9./usr/include/bits/typesizes.h:66:#define __SUSECONDS_T_TYPE __SYSCALL_SLONG_TYPE10./usr/include/bits/types.h:163:__STD_TYPE __SUSECONDS64_T_TYPE __suseconds64_t;11./usr/include/bits/typesizes.h:67:#define __SUSECONDS64_T_TYPE __SQUAD_TYPE12./usr/include/bits/types.h:160:__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */
    フラグによって定義は異なるが、最終的には(signed)long intと見なすことができる.環境ごとに違うそうですが、私の環境ではgcc -dM -E - </dev/null | grep LONGで確認したサイズは8バイトです.
    本題に戻るとutmp構造体のoffset定義は以下のように理解できる.
  • 0~1 | short | ut_type | Type of record
  • 2~5 | int | ut_pid | PID of login process
  • 6~37 | char[32] | ut_line | Device name of tty - "/dev/"
  • 38~41 | char[4] | ut_id | Terminal name suffix, or inittab(5) ID
  • 42~73 | char[32] | ut_user | Username
  • 74~329 | char[256] | ut_host | Hostname for remote login, or kernel version for run-level messages
  • 330~331 | short | e_termination | Process termination status
  • 332~333 | short | e_exit | Process exit status
  • 334~337 | int | ut_session | Session ID (getsid(2)), used for windowing
  • 338~341 | int | tv_sec | Seconds
  • 342~345 | int | tv_usec | Microseconds
  • 346~361 | int[4] | ut_addr_v6 | Internet address of remote host; IPv4 address uses just ut_addr_v6[0]
  • 362~381 | char[20] | __unused | Reserved for future use
  • (utセッションから、WORDSIZE COMPAT 32およびWORDSIZE値に依存する.)
    現在、構造化モジュールを使用してPythonに分けることができます.
    xtmp = namedtuple('xtmp', ('ut_type', 'ut_pid', 'ut_line', 
                               'ut_id', 'ut_user', 'ut_host', 
                               'e_termination', 'e_exit', 'ut_session', 
                               'tv_sec', 'tv_usec', 'ut_addr_v6')
                     )
    
    xtmp_format = 'hi32s4s32s256shhiii16s20x'
    xtmp_size = struct.calcsize(xtmp_format)
    
    for offset in range(0, len(raw_btmp), xtmp_size):
        records = struct.unpack(xtmp_format, raw_btmp[offset:offset+xtmp_size])
        
        btmp = xtmp._make(_.strip(b'\00') if type(_) == bytes else _ for _ in records)
    
        print(f'offset: {offset} ~ {offset+xtmp_size}')
        print(btmp)
        print()
    出力は以下の通りです.
    offset: 0 ~ 384
    xtmp(ut_type=6, ut_pid=390, ut_line=b'tty1', ut_id=b'1', ut_user=b'dongho', ut_host=b'', e_termination=0, e_exit=0, ut_session=0, tv_sec=1647646529, tv_usec=358920, ut_addr_v6=b'')
    
    offset: 384 ~ 768
    xtmp(ut_type=6, ut_pid=390, ut_line=b'tty1', ut_id=b'1', ut_user=b'*****', ut_host=b'', e_termination=0, e_exit=0, ut_session=0, tv_sec=1647646534, tv_usec=2827, ut_addr_v6=b'')
    
    offset: 768 ~ 1152
    xtmp(ut_type=6, ut_pid=4012, ut_line=b'tty3', ut_id=b'3', ut_user=b'dongho', ut_host=b'', e_termination=0, e_exit=0, ut_session=0, tv_sec=1647647576, tv_usec=847132, ut_addr_v6=b'')
    
    offset: 1152 ~ 1536
    xtmp(ut_type=6, ut_pid=4012, ut_line=b'tty3', ut_id=b'3', ut_user=b'p4ssw0rd', ut_host=b'', e_termination=0, e_exit=0, ut_session=0, tv_sec=1647647604, tv_usec=267502, ut_addr_v6=b'')
    
    offset: 1536 ~ 1920
    xtmp(ut_type=6, ut_pid=4130, ut_line=b'tty3', ut_id=b'3', ut_user=b'dongho', ut_host=b'', e_termination=0, e_exit=0, ut_session=0, tv_sec=1647647936, tv_usec=629563, ut_addr_v6=b'')
    私の犯した過ちは*で隠した.要するに、この384-768を削除すれば、私が犯した間違いをログから削除することができます.
    with open('btmp_new', 'wb') as f:
        f.write(raw_btmp[0:384] + raw_btmp[768:1920])
    問題がある部分を除いて、再作成後に元のバックアップのbtmpを置き換えました.

    願いがかなう.今日はSystems Performanceを2枚整理する予定でしたが、一度登録を間違えてこんな文章を書きました実は以前もよくこのようなミスを犯していましたが、今回は整理する機会があって、心が落ち着いています.utmpとwtmpも同じ構造に従い,lastlogを別々にパーティション化するだけでよい.