Future Advent Calendar 2019 This is the article on the 17th day.
I'm addicted to Go these days, but this time I'll change my mind. I would like to introduce a tool called ttycopy that shares a terminal, which I used occasionally in the previous project.
There is a scene like ~~ I want to hack the screen ~~ I want to see ...! When the super engineer is sshing on the server and doing something. After that, check the screen by double-checking whether the command is entered correctly on the server. If there is a physical distance, it is difficult to display the screen on the monitor. [^ 1]
[^ 1]: Of course, when using it, decline it before using it.
One way is to show the screen, but it would be smart if you could refer to it with a little tool. In Perl, there is a tool called ttylog. Inspired by ttylog, I created a shell-powered ttycopy. It works in the shell, so you can copy and paste the ttycopy implementation and run it casually.
It works as follows. It's a bit confusing, but I'm logged in to a server as the root and tsuji users and running ttycopy as the root user. You can see that the terminal logged in as the tsuji user is displayed from the middle of the terminal.
How ttylog works is also introduced in Share the terminal screen without permission and take a peek at the work of others. , The basic processing flow is as follows.
In ttycopy, I implemented it in the shell according to the above procedure.
The implementation in the shell is as follows.
pid=`ps fauwwx | grep sshd.*${tty} | grep -v grep | sed -e 's/^[a-zA-Z0-9]\+[ \n\r\f\t]\+\([0-9]\+\).*/\1/'`
It captures the PID of the process tree, which can be obtained by grep, using a regular expression. It's refreshing with regular expressions.
[tsuji@localhost ~]$ ps fauwwx | grep sshd.
root 1531 0.0 0.1 82568 6236 ? Ss 15:29 0:00 /usr/sbin/sshd -D
root 2830 0.0 0.2 149824 8916 ? Ss 15:29 0:01 \_ sshd: root@pts/0
root 13315 0.0 0.2 158980 10280 ? Ss 18:58 0:00 \_ sshd: root@notty
root 14956 0.0 0.2 154512 9352 ? Ss 20:10 0:00 \_ sshd: tsuji [priv]
tsuji 14959 0.0 0.1 154512 4092 ? S 20:10 0:00 \_ sshd: tsuji@pts/1
tsuji 15012 0.0 0.0 112672 2268 pts/1 S+ 20:11 0:00 \_ grep --color=auto sshd.
The implementation in the shell is the following part.
strace -e read -s16384 -q -xx -p ${pid} 2>&1
What we are doing is using strace to make a read system call issued by the PID associated with the tty we got earlier. Get it. Since various system calls are called in addition to the read system call, only the read system call is extracted with the strace option -e read
.
The read system call was the system call defined below. The results that can be obtained with strace are also as follows.
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
For example, suppose you issue the following command in the referenced terminal.
--Obtaining terminal
[tsuji@localhost gomi]$ hoge
bash: hoge:The command was not found...
[tsuji@localhost gomi]$
At this time, if you refer to the read system call with strace -p $ {PID} -e read
, the following output will be output.
--Strace terminal
[root@localhost ttycopy]# strace -p 14959 -e read
strace: Process 14959 attached
read(3, "\0\0\0\20\356\202\375C&&\357q\276\210pZ)\300\26M\357T\313\303k\6p\232\351\263\32\224"..., 16384) = 36
read(11, "h", 16384) = 1
read(3, "\0\0\0\20\235\230\204Ud\36)\370\266\233\362\305\2219\253g\335M\23\212\374h\250i@\235/\216"..., 16384) = 36
read(11, "o", 16384) = 1
read(3, "\0\0\0\20\324\357\304\vn\357BbW\241m\220yS\236\362\301\337\337\237c\203\245\223\221\253;,"..., 16384) = 36
read(11, "g", 16384) = 1
read(3, "\0\0\0\20\344\215\235\300\226\236\0\323\376\r\217,\257\322\326w\323R\264\3}\266\7q\315\215\344\346"..., 16384) = 36
read(11, "e", 16384) = 1
read(3, "\0\0\0\20^``\333\263h\372Z\336\335Y2\250\203\335\221\372faj\177\260f\302Sb\35\354"..., 16384) = 36
read(11, "\r\n", 16384) = 2
read(11, "bash: hoge: \343\202\263\343\203\236\343\203\263\343\203\211\343\201\214\350\246\213\343\201"..., 16384) = 62
read(11, "\33]0;tsuji@localhost:~/gomi\7[tsuj"..., 16384) = 51
^Cstrace: Process 14959 detached
In the above example, the strings strace: Process 14959 attached
and strace: Process 14959 detached
are displayed, but the strace option -q
is used to suppress this output. Also, the -x
option converts the string to hexadecimal for ease of display.
The goal is to display the contents of the second argument of the read system call obtained in step 2. The implementation in the shell is as follows.
sed -une "s/^read([0-9]\+, \"\(.*\)\".*/echo -n \$'\1'/p" | bash
The first half is sed -une" s / ^ read ([0-9] \ +, \ "\ (. * \) \". * / Echo -n \ $'\ 1'/ p "
. The expression captures the second argument of the read system call and gives it the strings ʻecho -nand
$''`, so you can get a string like this:
--Character string output to the acquisition source terminal
[tsuji@localhost gomi]$ cat hoge
hoge
[tsuji@localhost gomi]$
--Terminal character string output after processing by strace
echo -n $'\x00\x00\x00\x10\xc6\x1e\x56\xc6\x1f\x11\x7e\x57\x11\xaf\xdb\x2a\x91\x32\x84\x8e\x6e\x5b\x12\xc1\x72\x94\x36\x17\x12\xbb\x7c\xab\x4b\xdd\x19\x33'
echo -n $'c'
echo -n $'\x00\x00\x00\x10\x5d\x68\x72\x7c\x74\xca\x3c\xd1\x57\xfc\x14\x7d\x55\x34\x66\x15\x03\xcb\x26\x7c\x17\xbc\x7f\x7a\xf5\x25\x40\xed\xa8\x21\x39\xb3'
echo -n $'a'
echo -n $'\x00\x00\x00\x10\x05\x3d\x4a\xc2\x76\x1c\xd4\x23\x2a\x17\xc6\xa1\x1c\xf2\xdb\x14\x75\x1c\x7d\xb7\x21\xfb\xfc\xcd\x2d\x5c\xef\x06\x6c\x97\x01\x28'
echo -n $'t'
echo -n $'\x00\x00\x00\x10\x66\xb0\x8c\x40\x10\xa6\xf3\x9b\x36\x75\xd5\xc1\x65\x63\x94\x4f\x77\xd9\x10\x6d\xcf\xbb\x48\xed\x8b\x43\x58\x20\x54\x08\xde\x9b'
echo -n $' '
echo -n $'\x00\x00\x00\x10\x60\x6e\xb6\x06\x43\x16\xf5\x75\x89\x90\xb6\x42\x2c\xfe\x8b\x97\xae\xad\x47\x26\xf9\x39\xfc\xd2\x84\x37\xde\x0d\xe5\x32\xbc\x80'
echo -n $'h'
echo -n $'\x00\x00\x00\x10\x00\xe4\x3d\xb7\xd9\x79\x2e\x46\x80\xd5\xa5\xc2\xa7\x9a\xc7\x0c\xe1\x58\x7b\xd5\x97\xff\x00\xab\x72\x51\xa4\xbb\xab\x7d\xd1\xaf'
echo -n $'o'
echo -n $'\x00\x00\x00\x10\xf8\x1d\xce\xe6\x7f\x1a\x43\x94\xa2\xde\x3d\x3c\xb5\xe9\xb9\x94\x39\x43\x63\xfd\xa9\x1f\x45\x83\x64\x5c\x3a\xdf\xa8\x1a\xa4\x86'
echo -n $'g'
echo -n $'\x00\x00\x00\x10\x90\x69\x42\xa9\x48\x99\x0c\x52\xe9\x49\xbd\x4e\xa5\x17\x01\xff\xac\xec\x29\x75\x2c\xc0\x2b\x7c\x07\x85\xf2\x2f\xce\x71\x8f\x46'
echo -n $'e'
echo -n $'\x00\x00\x00\x10\xd9\x91\x38\x08\x0b\x95\x78\xd4\x80\x51\xa2\xe8\xef\x20\x06\x45\xa9\x3c\xf0\xa3\x10\x7d\x06\x32\x2d\x31\x53\x57\x40\x77\x1b\x29'
echo -n $'\r\n'
echo -n $'\x68\x6f\x67\x65\x0d\x0a\x1b\x5d\x30\x3b\x74\x73\x75\x6a\x69\x40\x6c\x6f\x63\x61\x6c\x68\x6f\x73\x74\x3a\x7e\x2f\x67\x6f\x6d\x69\x07'
echo -n $'[tsuji@localhost gomi]$ '
The -n
option of ʻecho -nis to prevent line breaks when interpreting. The Bash
$''` format has the following effects: Excerpt from the Man page. [^ 2]
Words of the form $'string' are treated specially. This word expands to a string and is then replaced with a backslash-escaped character as specified by the ANSI C standard. The backslash escape sequence is decoded (if any) as follows:
By using this, it is possible to expand to the meaning that the character string holds.
After that, you can display the string by letting the shell interpret the string ʻecho with
| bash`.
I was able to casually share the terminal by getting the string of the read system call argument with strace and restoring it in real time. I think it's an educational tool because you can see the work of other people in real time. If you want to hack the terminal, please use it.
If you like, you can get motivated by adding a star to ttycopy: v:
Recommended Posts