PDA

View Full Version : tty manipulation...


felix
10-18-2004, 05:00 PM
Hello,

I'm looking at tty manipulation. I tryed to figure out a application like screen (screen -x) where we can see what some user is making in other tty, but i tryed to do it without logged user confirmation (like screen require). This can be useful for me admin my server, maybe for others too. :)

I searched sources at internet, looked some man, but somethings isn't clean yet.. :(

The code is like that

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>

#define DEVICE "/dev/pts/3"

struct termios save_termios;
int ttysavefd = -1;
enum { RESET, DIRTY } ttystate = RESET;

int tty_dirtyterm (int fd);
int tty_reset (int fd);

int main(void){

char c;
char moo[2];

/* open device */
int fd = open(DEVICE,O_RDWR);
if(fd == -1)
{
perror("open DEVICE");
exit(1);
}

/* Unbuffered output */
setvbuf(stdout, NULL, _IONBF, 0);

/* Read input and write it to stdout */
while(1){

if(read(fd,&c,1) > 0){

c &= 255;
sprintf(moo, "%c", c);

if ( c == 127){

printf("\b \b");
fflush(stdout);
}

if ( c == 10 || c == 13){

printf("\n");
fflush(stdout);

}

putchar(c);
fflush(stdout);

//write(fd, &c, sizeof(c));
tty_dirtyterm(STDIN_FILENO);
ioctl(fd, TIOCSTI, moo);

}

else
usleep(1);

}

tty_reset(STDIN_FILENO);
close(fd);
return 0;
}

int tty_dirtyterm (int fd) {
struct termios buf;

if (tcgetattr(fd, &save_termios) < 0)
return(-1);

buf = save_termios;

buf.c_lflag &= ~(ECHO | ICANON);

buf.c_cc[VMIN] = 1;
buf.c_cc[VTIME] = 0;

if (tcsetattr(fd, TCSAFLUSH, &buf) <0)
return(-1);

ttystate = DIRTY;
ttysavefd = fd;

return(0);
}

int tty_reset (int fd) {
if (ttystate == RESET)
return(0);

if (tcsetattr(fd, TCSAFLUSH, &save_termios) < 0)
return(-1);

ttystate = RESET;
return(0);
}

Let's to the problems.. hehehe

1 - If I use ioctl() to send message to the original tty, it is send, but not printed in my tty as it should since i call printf() or putc() before it. If I comment ioctl() and uncomment write() then i see all that is typed at the user tty, but in the user tty only appear what he types in the some-line (overwriting what was wroten) and never executing this commands (only showing it). What i'm doing wrong ? How can i fix it ?

2 - How tty know that it should execute a command ? For example, if i send via write a "ls" it will not be executed, it will be only showed. But if i send via ioctl() it will be executed. I thinked that a \r\n that indicate that it should be executed (like a enter) but i'm wrong. How it works ?

3 - I looked at man ioctl and i couldn't find what does TIOCSTI! Someone know what it does ?

4 - Can i execute commands in the tty via write instead ioctl() ? How ?

Thks

Regards,

RobSeace
10-18-2004, 07:56 PM
I believe the STI in TIOCSTI stands for "Simulate Terminal Input"...
(And, the TIOC is "Terminal IOCtl", of course...) Documentation
on any of the ioctl()'s is very sparse, and you're pretty much
reduced to hunting for existing code that uses it... (But, sometimes
"man ioctl_list" gives SOME info, at least...)

Here is a quick and dirty example app that uses TIOCSTI:


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main (int argc, char *argv[])
{
char *cmd, *nl = "\n";
int i, fd = 0;

if (argc > 1) {
cmd = argv[1];
} else {
cmd = "ls";
}

for (i = 0; cmd[i]; i++)
ioctl (fd, TIOCSTI, cmd+i);

ioctl (fd, TIOCSTI, nl);

exit (0);
}


It will execute the given command, by outputing a newline after it...
It just uses FD 0 (stdin) to execute in your current tty, but you
should be able to open() any other tty and have it work on that
one, instead...

I suspect your problems stem from your messing with the tty
state via tcsetattr()... I'm unclear as to why you do that...

Anonymous
10-18-2004, 09:08 PM
Hi RobSeace,

Thks for you help me once again... ;)

I believe the STI in TIOCSTI stands for "Simulate Terminal Input"... (And, the TIOC is "Terminal IOCtl", of course...) Documentation on any of the ioctl()'s is very sparse, and you're pretty much reduced to hunting for existing code that uses it... (But, sometimes
"man ioctl_list" gives SOME info, at least...)

Humm.. at last now i know what means STI. But documentation in this subject really is bad.. :roll:

Here is a quick and dirty example app that uses TIOCSTI:


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main (int argc, char *argv[])
{
char *cmd, *nl = "\n";
int i, fd = 0;

if (argc > 1) {
cmd = argv[1];
} else {
cmd = "ls";
}

for (i = 0; cmd[i]; i++)
ioctl (fd, TIOCSTI, cmd+i);

ioctl (fd, TIOCSTI, nl);

exit (0);
}


It will execute the given command, by outputing a newline after it...

Correct, here is the point. In my example code I notted exactily it, I need to run this ioctl(), for example, if you write the \n with write() you will see that the command (ls for example) will not be executed. Exchange in your code the

ioctl (fd, TIOCSTI, nl);

by:

write (fd, nl, sizeof(nl));

And you will notice that the command ISN'T executed even with "\n". This ioctl() "make" something different that only "write" at a device...

What I trying to understand is, what it does ? Can I does it WITHOUT ioctl() (with write() for example) ?


It just uses FD 0 (stdin) to execute in your current tty, but you
should be able to open() any other tty and have it work on that
one, instead...

Yes, rigth my code above is able to send commands to other tty's too. But I want to be able to *spy* other shell, so I need open that and be able to get this commands (read()) and I need to write it to my stdout and execute it in the other tty (spyed). Understand my idea ? :)

I suspect your problems stem from your messing with the tty
state via tcsetattr()... I'm unclear as to why you do that...

Well, I commented the lines of tcsetattr() and the same yet happen... I want to do this, because it can be very useful for my administration. For example, if i setup a honeypot i can use it in all my shell's to spy what attackers are making at my machine, I can use it to administrate users in my server with strange actions, and more.. ;)

Regards,

RobSeace
10-18-2004, 11:46 PM
I need to run this ioctl(), for example, if you write the \n with write() you will see that the command (ls for example) will not be executed.


Right... Of course, that's correct... Just write()'ing to the tty will
simply output data to be displayed on it... What you're trying to do
is simulate input on the tty, as if they typed it... For that, the only
approach that I know about is stuff like ioctl(SIOCSTI)... You're
unlikely to find any method using simple write() that'd ever work...
But, I'm not sure why there's a problem using ioctl(), either... It
does seem to work just fine... I don't understand why you don't
want to use it... If there's some problem with displaying the chars
to your screen before sending them to the target tty, then I'd say
the problem lies somewhere other than the ioctl()...