Twi1ight / impacket

Automatically exported from code.google.com/p/impacket
Other
1 stars 4 forks source link

No way to read from pipe in psexec without blocking. #28

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.  If you modify the time outs in psexec, sometimes psexec doesn't come back 
after throwing a netbiostimeout exception and catching the exception. Of course 
because it is timing out.
2. However, Looking to  run select directly on the socket won't work because a 
packet needs to be sent in order to be able to recieve a response from the smb 
server.
3.  There is no function implimented to be able to scan a file on the smb 
server to see if the file has new data ready to read.

in short, if you are running psexec as an object instead of a stand alone 
script, threads will never be able to be collected because they will run until 
the timeout is exceeded, a very long time.

What is the expected output? What do you see instead?
There should be a function to be able to check if the remote file has data to 
be read or throwing a net bios timeout shouldn't necisarily result in a loss of 
connection..  Maybe attempting to read 0 bytes should be the norm of checking 
to see if the remote file handle has something to be read. Either way, seamless 
non blocking reads from the remote smb should be possible.
example:
            try:
                #if there is something to read read it
                #following funciont doesn't exist, but it probably should.
                if self.server.File_ready(self.tid,self.fid):
                    ans = self.server.readFile(self.tid,self.fid, 0, 1024)
                else:
                    #maybe we want to close the session and say good bye
                    #or maybe we want to continue asking if there is any
                    #thing to be read.  Either way, I should be able to
                    #ask the question
                    continue
            except Exception, e:
                import traceback
                traceback.print_exc()
                pass

What version of the product are you using? On what operating system?
0.9.10

Please provide any additional information below.

Original issue reported on code.google.com by rustysto...@gmail.com on 7 Jun 2013 at 6:22

GoogleCodeExporter commented 9 years ago
Hey mate...

Interesting finding.. honestly I never thought about using psexec as an object. 
I know there's a way to set pipes in non blocking mode for SMB version 2/3, I 
should figure out how to do it in SMB version 1. If so, we could change the 
behavior in the way you described it.

beto

Original comment by bet...@gmail.com on 14 Jun 2013 at 7:52

GoogleCodeExporter commented 9 years ago
I am making a slave driver interface combined with python's paramiko to give me 
universal access to any machine and run remote commands on them. :)
I the case where there is a non blocking read, the exact usage may not be the 
same, but the end goal is achieved.  Maybe None is returned if the pipe had 
nothing to write after a given timeout. I don't know too much about smb, but 
maybe the new usage could be like the following:
ans = self.server.readFile_nonblocked(self.tid,self.fid, 0, 1024, 
read_timeout=5)
if ans is None:
    continue
But I guess that would totally dedend on how the SMB parts are setup...

Original comment by rustysco...@gmail.com on 15 Jun 2013 at 12:20

GoogleCodeExporter commented 9 years ago
After inspecting impacket a little more on the nmb layer. it looks like there 
could be a way to make a non blocking read of the socket on that level.  Then 
there would be no need to modify the SMB layer to be non blocking.

Original comment by rustysco...@gmail.com on 18 Jun 2013 at 10:56

GoogleCodeExporter commented 9 years ago
Good point.. the select_poll argument..

You can give it a try yourself.. change the select_poll to True in 
NetBIOSTCPSession().__init__ and give it a try.. let me know how it goes.

I'm still trying to understand what's the benefit for you tho :-o

let me know!
beto

Original comment by bet...@gmail.com on 18 Jun 2013 at 11:03

GoogleCodeExporter commented 9 years ago
The benefit is that the pipes, which are subclasses of threads in psexec, will 
eventually go back into motion after being stopped on an attempted read of a 
remote named pipe; or at least not attempt a blocking read if it is going to 
wait forever by checking to see if there is anything to read.  Currently, 
execution in the thread stops at 
>ans = self.server.readFile(self.tid,self.fid, 0, 1024)
and will block indefinitely.  At this point, not even using ctypes to kill the 
thread will work.  This is fine, if you are killing the process and don't 
really care if you are leaking threads which will be collected by the OS.  
However, let's say that I am not going to kill the process, because I want to 
integrate psexec into a higher structure called a connection which can be 
imported into other scripts and be instantiated as an object.  In this case, I 
can't really leak threads because I want to be able to run many commands one 
after another like one might do with an ssh console. 
in short
ans = self.server.readFile(self.tid,self.fid, 0, 1024)
makes a thread unjoinable which is never a good idea.  Either you waste memory 
and processes with a zombie thread or you deadlock attempting to join the 
thread.

Original comment by rustysco...@gmail.com on 19 Jun 2013 at 8:00

GoogleCodeExporter commented 9 years ago
Excellent explanation mate.. thanks!

Did you try the sellect_poll option in nmb.py?

cheers
beto

Original comment by bet...@gmail.com on 19 Jun 2013 at 8:05