NahamCon CTF 2024
NAHAMCON CTF 2024
CRYPTOGRAPHY WRITEUP
Author:
Pham Quoc Trung
Used Language:
Python3
Problem Solving:
MagicRSA
Description:
Here's an RSA challenge using the most magical number of all.
Attachment:
rsa_with_a_magic_number.py
from secrets import randbits
from sympy import nextprime
e = 3
def encrypt(inp):
p = nextprime(randbits(2048))
q = nextprime(randbits(2048))
n = p * q
enc = [pow(ord(c), e, n) for c in inp]
return [n, enc]
plaintext = open('flag.txt').read()
with open('output.txt', 'w') as f:
data = encrypt(plaintext)
f.write(f'Semiprime:\nN: {data[0]}\nCiphertext:\n')
f.write(''.join(f'{b} ' for b in data[1]))
f.write('\n\n')
output.txt
Semiprime:
N: 292661735803169078279687796534368733968232055929694715453717384181208539846645017378459508481927733219065809706996972833902743250671173212610674572380079245835772007065919936022084401497853611610920914306013040436502207047619016113234947051878549793269852855316328078769491183468515501156324665790842023112309668506350354977653838139155232422868462129041940364012648613391176971689126513558396465218392059219609662829793402841289708970576750698757213264731256720405308346659459733504680423032430634001779369250142543104703669906030549585514247663929431837546466696121103600101025434247152431200408744676625328330247569014313252820778269086840631297075563756934662979588351413726196027845505808290890109883253252054958997436359016852222176230489468164288277709046892991459049248340800616885136366469783271661343653314539194467688757972713531491290238432270971346559967725437118531023032768463200227986539449334624183071042562539584305305367245588508498775214112729500313280502474837332653452065755426475638743763861804587979560695676963674789819860296303566053542883415223272958687917330474367563315425617320128680682444959701586681495270336801802382200546403246134181793704030611664095075430115127507174884551339452808218398863888817
Ciphertext:
1061208 1259712 912673 1092727 1860867 175616 166375 941192 185193 1030301 941192 185193 912673 140608 175616 185193 140608 941192 970299 1061208 175616 912673 117649 912673 185193 148877 912673 125000 110592 1030301 132651 132651 1061208 117649 117649 1061208 166375 1953125
Solution:
Đây là một bài liên quan tới RSA. Với e = 3
và việc mã hóa từng kí tự một của flag (m
rất nhỏ) thì đây là đặc điểm của lỗ hổng small e, small n
điển hình. Để giải thì ta chỉ cần lấy căn bậc 3 của từng c
để ra được flag.
from sage.all import *
from Crypto.Util.number import *
N = 292661735803169078279687796534368733968232055929694715453717384181208539846645017378459508481927733219065809706996972833902743250671173212610674572380079245835772007065919936022084401497853611610920914306013040436502207047619016113234947051878549793269852855316328078769491183468515501156324665790842023112309668506350354977653838139155232422868462129041940364012648613391176971689126513558396465218392059219609662829793402841289708970576750698757213264731256720405308346659459733504680423032430634001779369250142543104703669906030549585514247663929431837546466696121103600101025434247152431200408744676625328330247569014313252820778269086840631297075563756934662979588351413726196027845505808290890109883253252054958997436359016852222176230489468164288277709046892991459049248340800616885136366469783271661343653314539194467688757972713531491290238432270971346559967725437118531023032768463200227986539449334624183071042562539584305305367245588508498775214112729500313280502474837332653452065755426475638743763861804587979560695676963674789819860296303566053542883415223272958687917330474367563315425617320128680682444959701586681495270336801802382200546403246134181793704030611664095075430115127507174884551339452808218398863888817
c = [1061208,1259712,912673,1092727,1860867,175616,166375,941192,185193,1030301,941192,185193,912673,140608,175616,185193,140608,941192,970299,1061208,175616,912673,117649,912673,185193,148877,912673,125000,110592,1030301,132651,132651,1061208,117649,117649,1061208,166375,1953125]
flag = b''
for i in c:
m = int(i**(1/3))
flag += chr(m).encode()
print(flag)
Flag: flag{87b9eb9a4894bcf8a1a95a20e33f11f7}
Encryption Server
Description:
I read online it's bad to re-use the prime numbers in RSA. So, I made this server that randomly generates them for me.
Attachment:
RSA_Encryption_Server.py
#!/usr/bin/python3
from secrets import randbits
from sympy import nextprime
import random
e = random.randint(500,1000)
def encrypt(inp):
p = nextprime(randbits(1024))
q = nextprime(randbits(1024))
n = p * q
c = [pow(ord(m), e, n) for m in inp]
return [n, c]
def main():
while True:
print('Welcome to the Really Shotty Asymmetric (RSA) Encryption Server!')
print('1: Encrypt a message')
print('2: View the encrypted flag')
print('3: Exit')
inp = ''
while (not ('1' in inp or '2' in inp or '3' in inp)):
inp = input('> ')
if('3' in inp):
print('Goodbye!')
exit()
elif('1' in inp):
plain = input('Enter a message, and the server will encrypt it with a random N!\n> ')
encrypted = encrypt(plain)
elif('2' in inp):
data = open('flag.txt', 'r').read()
data = data.strip()
encrypted = encrypt(data)
print('Your randomly chosen N:')
print(f'> {encrypted[0]}')
print('Your encrypted message:')
print(f'> {encrypted[1]}')
print('\n')
if(__name__ == '__main__'):
main()
Recon:
Ở bài này, trước tiên, một số e
sẽ được lấy random từ 500-1000 thông qua dòng này:
e = random.randint(500,1000)
Hàm encrypt
thực hiện mã hóa RSA từng kí tự của input truyền vào giống bài trước:
def encrypt(inp):
p = nextprime(randbits(1024))
q = nextprime(randbits(1024))
n = p * q
c = [pow(ord(m), e, n) for m in inp]
return [n, c]
Đến với hàm main
, ta sẽ có các chức năng như sau:
Chức năng 1: Tiến hành mã hóa input người dùng, in ra
ciphertext
vàN
sử dụng để mã hóa.Chức năng 2: Tiến hành mã hóa flag, in ra
ciphertext
vàN
sử dụng để mã hóa.Chức năng 3: Thoát chương trình.
Solution:
Ban đầu thì mình cũng chưa nghĩ ra cách giải, chỉ là mình thấy từ chức năng 1, mình có thể khôi phục được e
nên mình đã tiến hành tìm luôn.
Cụ thể, mình sẽ truyền input là \x02
. Khi đó, c = pow(2, e, n)
và do e chỉ nằm trong khoảng 500-1000, mình có thể dễ dàng factor c
để ra được lũy thừa của 2. Và số mũ đó chính là e
.
Giờ thì đã có e
. Sau khi nghĩ mất một khoảng thời gian, mình nhận ra từ chức năng số 2 mình có thể lấy ra nhiều cặp c
, n
tùy ý, và đặc điểm của chúng là đều có chung số mũ e. Từ đó, mình nghĩ ra việc sử dụng Hastad Broadcast Attack. Về kĩ thuật thì các bạn có thể xem ở đây: link.
Nôm na là ở đây mình sẽ lấy ra 3 cặp c, n
. Khi đó, mình sẽ có 3 phương trình như sau:
Sử dụng Định lý thặng dư Trung Hoa, mình sẽ tìm ra được giá trị m^e mod(n1*n2*n3)
. Nếu m
đủ nhỏ và tích của n1, n2, n3 đủ lớn (do m
chỉ là một kí tự nên mình đã test và khi e < 800 thì vẫn vô tư), ta có thể tìm được m
bằng cách lấy căn bậc e
của m
.
Vậy ta sẽ kết nối tới server, tìm e
, nếu e < 800
thì sẽ tiến hành tấn công Hastad Broadcast Attack trên từng kí tự để tìm được flag
from pwn import *
from sage.all import *
from Crypto.Util.number import *
while(True):
conn = remote('challenge.nahamcon.com', 31880)
#conn = process(['RSA_Encryption_Server.py'])
def recvLine(n):
for _ in range(n):
conn.recvline()
recvLine(4)
conn.sendline(b'1')
conn.sendline(b'\x02')
recvLine(4)
c = int(conn.recvline().decode().strip()[3:-1])
e = int(str(factor(c))[2:])
print("e = ", e)
if e > 800:
continue
recvLine(6)
print("[*] Getting Cs and Ns for Hastad Broadcast Attack")
Cs = []
Ns = []
for _ in range(3):
conn.sendline(b'2')
recvLine(1)
N = int(conn.recvline().decode().strip()[2:])
print("N = ", N)
Ns.append(N)
recvLine(1)
C = eval(conn.recvline().decode().strip()[2:])
Cs.append(C)
recvLine(6)
assert len(Cs[0]) == len(Cs[1])
flag = b''
print("[*] Getting Flag...")
for i in range(len(Cs[0])):
c1 = Cs[0][i]
c2 = Cs[1][i]
c3 = Cs[2][i]
m_e = crt([c1, c2, c3], Ns)
m = m_e.nth_root(e)
flag += long_to_bytes(int(m))
break
print(flag)
Flag: flag{29070b0688f398587d41041f4b25d8a3}
Another way:
Cả 2 bước là lấy e
và tìm ra m
đều có thể được thực hiện bằng cách brute-force.
Đối với e
, chỉ cần brute pow(m, e, n)
với m là các kí tự đã biết "f, l, a, g, {", so sánh với ciphertext
lấy được từ 2 để tìm được e
đúng.
Tương tự với flag, chỉ cần brute pow(m, e, n)
nhưng lần này là brute m
. Nếu kết quả giống với trong ciphertext
thì đó là kí tự đúng.
ciphertext_fl = [2845861777458711081285915326988338985743730999527118107203218292590482876126771640993767744378673311759111413636605606110421394748830107061641906596339045188086747491073274955252868760300906325061420000738148492330291196037401909122962683278381547408836248978852015904394621683658372934817194028530518446825031802525512682521353842074195961755512222666780207118946427171769618919880561426997137552992847684761319604713638803640694937665502650731213697070140308882556747092629301392850673735397904412530235046672784407389499493156368119349908716924754714857345990831342313207232004416498280804945586113762383026554002, 2805890269333072470208591258487553989034795359432421658708582474905413969103487472537071097034153838789167985283484253874142182991932492834999818617883543786579827593374012249984010887241145323385899009615612729724056742625273578099692560459861700063220691619145025109412244898326635121438617464353869114646077011853606382618463503786557216721930629983595460760523841730608693268027816793601411324981497931693365448703519732050192341945516118443772492022854842354042986850969724665267705856595076039273464728269983181692054073602833109503351924218720512878251360136970290247408724719952603560425934514843665385462474]
N = 3189114686224168527832331594922454956130813095678500091837003591252581589062448982723246876196017944847100818244381832468383363405845911023963060518988016928538755279709811123903342192509780913173428723886393253482859769115568498425217420047666488898487353815066472059082290797546861177320701802469167877671417071641160054157961123316709837879746006591255937485506228981534802657551533225645035775724152887077617722220015769980939338494248274632855471433642146347951726131771323868101240008040640059677232340041423789617615705270452301423174772159475723086187149237364733296047140690284751569807669233727054962069009
plaintext = ['f', 'l']
for i in range(0,2):
for j in range(500,1000):
if(pow(ord(plaintext[i]),j,N) == ciphertext_fl[i]):
print("e = ", j)
ciphertext = [2845861777458711081285915326988338985743730999527118107203218292590482876126771640993767744378673311759111413636605606110421394748830107061641906596339045188086747491073274955252868760300906325061420000738148492330291196037401909122962683278381547408836248978852015904394621683658372934817194028530518446825031802525512682521353842074195961755512222666780207118946427171769618919880561426997137552992847684761319604713638803640694937665502650731213697070140308882556747092629301392850673735397904412530235046672784407389499493156368119349908716924754714857345990831342313207232004416498280804945586113762383026554002, 2805890269333072470208591258487553989034795359432421658708582474905413969103487472537071097034153838789167985283484253874142182991932492834999818617883543786579827593374012249984010887241145323385899009615612729724056742625273578099692560459861700063220691619145025109412244898326635121438617464353869114646077011853606382618463503786557216721930629983595460760523841730608693268027816793601411324981497931693365448703519732050192341945516118443772492022854842354042986850969724665267705856595076039273464728269983181692054073602833109503351924218720512878251360136970290247408724719952603560425934514843665385462474, 345049340451699554007948763472893858069411074537199267556380516213734827871614442990536926350227584616252255045051744656658724729921391320513975448747866674731393989824816278253531731559615988365176956553948361741230399671929627311399657205635358188611855896981664987554010070048005180840005056436207539387449042369726304130418877417881364189259973633455724018939019191261925159303420250412390007010119147742488855420323873249301367316063804185927827524896427158951883596368737320448679598208240720659999317773937210898039147175668295346147218816545703112535909878232871373805727402265504548979315089528552745595697, 951163298345106231474965268208628957560219827343318469058594011214334907230708192966701434830239592607901230972125289759116778952718867152714673055156978415240844637092217615193683643441644710454365038159550862939209430473121277046234408508854805432587143690283399051889768700057669176809672637598759051517189918283013574918656032509526960299262696076915519384365007763770641009908429501397555619670029586938706763117479503165045356713874312445207595800339533912979658929330131578873516177465080105547702507295249779825666736757137298102812985083322667530164240990764773702433458491924992074240962884982274564568042, 2479740182999776804236008771087148553401180682610638938146084980344936940119492223862551282276185760469838774084821912305124124460275464842954477157399928256728277919043903943283684790617368819888418898754386175589677609172316868328189627957990265910903124804013463273031433067144372013213246768872278204181654312859179538915959094078445808285939843228263076180534914063668466731115577912318534413682290450045060127045330214188441581955638321469296811020710362645547033091994820234286586177226310069842056675435949953801865401798723082728308585082466783600901592974673165385121898944298025808889394130914931944174229, 1689648263690978778280170131450402539775056061067679151878561766159974416266729509392796827284280021114585143550272850553055947734392514548158687802346790714671470092057937163907789464017686363954964313625028846561605112921624275653838037238634867350561640932180755566024487316152259454353638830953487690089823845294888935653243560336802066211749736208394089320838051100685395305339300589018398810678283489041640663014789560080276320746223393434143652293446825746170769913805390960532534009682085721943696669610692920491082604004553026481265980479989159102201997507755264683603620375248250900657077159135913451475885, 1366265827726126356918913585024756485780435967256934245227562733065480167819880351305246951658964544613584070695752446892678824755899460089833139021634748263140167813790154552259800633189983090549953889604223027803342384439274709345584697554533577244637989592702173073532674527198681364164503021195270185894343355477553262666249315566674897748952144566851726429761160447044620354972047592165189091120374972648855042489789434055288450746687672289055011436685398085713382399844263579889952627226779408321023445016879555892307400296333734534585309043169678564257735058793357233406805237328776527846600882076903331621597, 1880986832723421995542331916276862609832710080821311021126193135130466468781046737384926415171473223417033002143569057118735414797058210868444342450451998472450675991431920644445767093008895225775331188675006434091188583890544406559752931519322823526034317979433859471268682724992239124339743776093619711411904783199970153237719782718807980965232535516306426899265343685689616945036774619408517193964770529813106017816818171225102814472420096407054689765934355621632742197439866839107501574533427757596992555703030987509779785289344475334209600587720610173392201510433795814155974605297309697094057625010692237992916, 447082459991133744898907089075375352292647403135626491589460690183256508370824774284013192023078727444876061065103019989794749220777810120216238379257625151547210011508048571858695019024528903607306443511742130484786824482766215774084738884759134952438739435418555890671646396282187515454410798071217424747025416582198003938572360105929490369879128733445529876133449964023814061929288535292138174771469414176930488932687917478017771230431142811940300118764993211347452731125058983435131302934226927647160815537980274550652722924832989338994546715962312554567887655175806262610551488067005093143845165595351011535046, 1880986832723421995542331916276862609832710080821311021126193135130466468781046737384926415171473223417033002143569057118735414797058210868444342450451998472450675991431920644445767093008895225775331188675006434091188583890544406559752931519322823526034317979433859471268682724992239124339743776093619711411904783199970153237719782718807980965232535516306426899265343685689616945036774619408517193964770529813106017816818171225102814472420096407054689765934355621632742197439866839107501574533427757596992555703030987509779785289344475334209600587720610173392201510433795814155974605297309697094057625010692237992916, 657531892116865015142394761686088155049562374838297052228520378422680338587486406531979861057659734879903815233207708117380133428703716981680650285276224325322438187176524500130763964760465650615713803716318611821687689852199541790168405701892817077531322995908823672231046818763668024654790829827656211534313826615071273919270061272218257895216173068084980116013395247872977107781645683609941220716456301742125138182120724068859552216850363822565319506568992865360794905224578157391381472852393192349908122159934353098111521293102108708455823289990396357737686400482466929223352252310227462412425488002625451459616, 1880986832723421995542331916276862609832710080821311021126193135130466468781046737384926415171473223417033002143569057118735414797058210868444342450451998472450675991431920644445767093008895225775331188675006434091188583890544406559752931519322823526034317979433859471268682724992239124339743776093619711411904783199970153237719782718807980965232535516306426899265343685689616945036774619408517193964770529813106017816818171225102814472420096407054689765934355621632742197439866839107501574533427757596992555703030987509779785289344475334209600587720610173392201510433795814155974605297309697094057625010692237992916, 931252500634441514616497679620051626217605365233679725051001206600034724152803746687940344729566093531275725080374938709126325168920365222032779304110863268497748886886843887387483633987124058566767668905862301341451661011482425906905418463431445584026807512410307727260551923867715741887504764424483991456831860134171099554794290686427452074841226324156456225827039952387715243745898645798191821048476456977943872538420959086785932613424632169412971609634657649512551652299626480695988623445043341380977574013519984162449844026080767169098052768982064746292758195314327865381760093388486686866860285907899797262088, 1516108394291563581129402757918441429103374282540273242535574001686808809056278753069427188395830088378688414390073229867838020209913041172365104049292611891822922405699792228824982320081408133615649588115855890512325779090710043445082538224451754606617750503661325473727213169075371602269467764343908061812510109618078253018279688326849900067366848210517579848333960452975012649436612670651848997870043639151181860894641518880479989748538477173553953687103113277529109777027218496246543551681896161811075929695362823665844770413650851610700668138703783542611069459838985646311963152663040630742739994022184468951693, 1516108394291563581129402757918441429103374282540273242535574001686808809056278753069427188395830088378688414390073229867838020209913041172365104049292611891822922405699792228824982320081408133615649588115855890512325779090710043445082538224451754606617750503661325473727213169075371602269467764343908061812510109618078253018279688326849900067366848210517579848333960452975012649436612670651848997870043639151181860894641518880479989748538477173553953687103113277529109777027218496246543551681896161811075929695362823665844770413650851610700668138703783542611069459838985646311963152663040630742739994022184468951693, 2845861777458711081285915326988338985743730999527118107203218292590482876126771640993767744378673311759111413636605606110421394748830107061641906596339045188086747491073274955252868760300906325061420000738148492330291196037401909122962683278381547408836248978852015904394621683658372934817194028530518446825031802525512682521353842074195961755512222666780207118946427171769618919880561426997137552992847684761319604713638803640694937665502650731213697070140308882556747092629301392850673735397904412530235046672784407389499493156368119349908716924754714857345990831342313207232004416498280804945586113762383026554002, 2310127393424955205107098753990740358616986137235523761428262577027025221085993167331127781046303783394387937006140407932458365609661360072106720211912369678829021097399331475604691187882409665300952366321289612227771815985404013084073477199260101972484084154567987647887377325483499340128094102430928953352662945461142995341584089062204341970339034221703457214832763736835220434547067732740206252238614354577428802536954307484724292316946308032286724679045981289044117505581194462938042596730344914183773705642632211684448859729662063800386303640529418370614292346515567013769130105736509067539211154067603076086189, 1366265827726126356918913585024756485780435967256934245227562733065480167819880351305246951658964544613584070695752446892678824755899460089833139021634748263140167813790154552259800633189983090549953889604223027803342384439274709345584697554533577244637989592702173073532674527198681364164503021195270185894343355477553262666249315566674897748952144566851726429761160447044620354972047592165189091120374972648855042489789434055288450746687672289055011436685398085713382399844263579889952627226779408321023445016879555892307400296333734534585309043169678564257735058793357233406805237328776527846600882076903331621597, 1516108394291563581129402757918441429103374282540273242535574001686808809056278753069427188395830088378688414390073229867838020209913041172365104049292611891822922405699792228824982320081408133615649588115855890512325779090710043445082538224451754606617750503661325473727213169075371602269467764343908061812510109618078253018279688326849900067366848210517579848333960452975012649436612670651848997870043639151181860894641518880479989748538477173553953687103113277529109777027218496246543551681896161811075929695362823665844770413650851610700668138703783542611069459838985646311963152663040630742739994022184468951693, 2825042302849856182284872811744811851303458709453114059362272060068512267538225413672354029466562884251929086090506718793766519094780957785264121916464366198247607907977936981194431588706166261133311195088312650094024949559791378239797230300129221749262929881181940740248368825139119795735889170215292788056972581404694082220855455649236193628823860271638426760590881522270205098323115629369841602830473153490864105692494513874244443421117783300861975364144568599970418552392058660723035379863919183943374528199975123570861634795494088933270814595952418757886991216069017712289797754734682455842143958305877491065308, 1516108394291563581129402757918441429103374282540273242535574001686808809056278753069427188395830088378688414390073229867838020209913041172365104049292611891822922405699792228824982320081408133615649588115855890512325779090710043445082538224451754606617750503661325473727213169075371602269467764343908061812510109618078253018279688326849900067366848210517579848333960452975012649436612670651848997870043639151181860894641518880479989748538477173553953687103113277529109777027218496246543551681896161811075929695362823665844770413650851610700668138703783542611069459838985646311963152663040630742739994022184468951693, 447082459991133744898907089075375352292647403135626491589460690183256508370824774284013192023078727444876061065103019989794749220777810120216238379257625151547210011508048571858695019024528903607306443511742130484786824482766215774084738884759134952438739435418555890671646396282187515454410798071217424747025416582198003938572360105929490369879128733445529876133449964023814061929288535292138174771469414176930488932687917478017771230431142811940300118764993211347452731125058983435131302934226927647160815537980274550652722924832989338994546715962312554567887655175806262610551488067005093143845165595351011535046, 911952661268613740583322997565412200914100502692357718437769466553003571267254639495161904160210650878940573803570850454621528713203365998436143695790546494901722250097991645848066686529879779990669014240227068002247584740881790026584221414251618906534958486397391687640947173344606419090340298923474444182516380607114649841952081489454956417542971671362961862642629115262583713292974344395338435404501794644438854646632565285640653797991087106823104952723282567247576478901710217187696256883106377762131777502200827895165209409875271987670024104226318541141456416006467124909526742250444801039181096325252980787937, 404953586124003713338094403824158076005487244392998242685509201327153305278954249039089984119775592321546283058278853313006332417730624875758884377551900046823033187266935812650505269250683845308747958368228419508173793699342704392907950014556812234110901800665251816896866317438756274009173828660344643880065244670967241154994170561756893223405112315769965926671415121445324858529519864795021415136180118485244749112441409398878171724578073635858057757284866247813421619605117907554732297911373096632500385347174349766094732800236684128079209645166435698882303614752359575832337798752667862475104063845009162911123, 905685771497468383707579661844517741131510146624065231016488522358591867392805435992637943183729559574110814536030841880160952126265038473173024062448851717036910638420337304168080133588944925865114215245944974991705439823897729116691937883749053899858403745246985614768892782108588241187122190260786564856012774733521266154949552017246439829318354606757306096013302253546964428485920620447844988938649711057865207734651104360867713093742305925508951994576164468480597387880351900638406381052307766144060496369997796375270344203820789125077580002531993616040845690994618971720151149188440949809688479761737824788097, 1880986832723421995542331916276862609832710080821311021126193135130466468781046737384926415171473223417033002143569057118735414797058210868444342450451998472450675991431920644445767093008895225775331188675006434091188583890544406559752931519322823526034317979433859471268682724992239124339743776093619711411904783199970153237719782718807980965232535516306426899265343685689616945036774619408517193964770529813106017816818171225102814472420096407054689765934355621632742197439866839107501574533427757596992555703030987509779785289344475334209600587720610173392201510433795814155974605297309697094057625010692237992916, 404953586124003713338094403824158076005487244392998242685509201327153305278954249039089984119775592321546283058278853313006332417730624875758884377551900046823033187266935812650505269250683845308747958368228419508173793699342704392907950014556812234110901800665251816896866317438756274009173828660344643880065244670967241154994170561756893223405112315769965926671415121445324858529519864795021415136180118485244749112441409398878171724578073635858057757284866247813421619605117907554732297911373096632500385347174349766094732800236684128079209645166435698882303614752359575832337798752667862475104063845009162911123, 905685771497468383707579661844517741131510146624065231016488522358591867392805435992637943183729559574110814536030841880160952126265038473173024062448851717036910638420337304168080133588944925865114215245944974991705439823897729116691937883749053899858403745246985614768892782108588241187122190260786564856012774733521266154949552017246439829318354606757306096013302253546964428485920620447844988938649711057865207734651104360867713093742305925508951994576164468480597387880351900638406381052307766144060496369997796375270344203820789125077580002531993616040845690994618971720151149188440949809688479761737824788097, 2845861777458711081285915326988338985743730999527118107203218292590482876126771640993767744378673311759111413636605606110421394748830107061641906596339045188086747491073274955252868760300906325061420000738148492330291196037401909122962683278381547408836248978852015904394621683658372934817194028530518446825031802525512682521353842074195961755512222666780207118946427171769618919880561426997137552992847684761319604713638803640694937665502650731213697070140308882556747092629301392850673735397904412530235046672784407389499493156368119349908716924754714857345990831342313207232004416498280804945586113762383026554002, 404953586124003713338094403824158076005487244392998242685509201327153305278954249039089984119775592321546283058278853313006332417730624875758884377551900046823033187266935812650505269250683845308747958368228419508173793699342704392907950014556812234110901800665251816896866317438756274009173828660344643880065244670967241154994170561756893223405112315769965926671415121445324858529519864795021415136180118485244749112441409398878171724578073635858057757284866247813421619605117907554732297911373096632500385347174349766094732800236684128079209645166435698882303614752359575832337798752667862475104063845009162911123, 657531892116865015142394761686088155049562374838297052228520378422680338587486406531979861057659734879903815233207708117380133428703716981680650285276224325322438187176524500130763964760465650615713803716318611821687689852199541790168405701892817077531322995908823672231046818763668024654790829827656211534313826615071273919270061272218257895216173068084980116013395247872977107781645683609941220716456301742125138182120724068859552216850363822565319506568992865360794905224578157391381472852393192349908122159934353098111521293102108708455823289990396357737686400482466929223352252310227462412425488002625451459616, 1689648263690978778280170131450402539775056061067679151878561766159974416266729509392796827284280021114585143550272850553055947734392514548158687802346790714671470092057937163907789464017686363954964313625028846561605112921624275653838037238634867350561640932180755566024487316152259454353638830953487690089823845294888935653243560336802066211749736208394089320838051100685395305339300589018398810678283489041640663014789560080276320746223393434143652293446825746170769913805390960532534009682085721943696669610692920491082604004553026481265980479989159102201997507755264683603620375248250900657077159135913451475885, 2825042302849856182284872811744811851303458709453114059362272060068512267538225413672354029466562884251929086090506718793766519094780957785264121916464366198247607907977936981194431588706166261133311195088312650094024949559791378239797230300129221749262929881181940740248368825139119795735889170215292788056972581404694082220855455649236193628823860271638426760590881522270205098323115629369841602830473153490864105692494513874244443421117783300861975364144568599970418552392058660723035379863919183943374528199975123570861634795494088933270814595952418757886991216069017712289797754734682455842143958305877491065308, 911952661268613740583322997565412200914100502692357718437769466553003571267254639495161904160210650878940573803570850454621528713203365998436143695790546494901722250097991645848066686529879779990669014240227068002247584740881790026584221414251618906534958486397391687640947173344606419090340298923474444182516380607114649841952081489454956417542971671362961862642629115262583713292974344395338435404501794644438854646632565285640653797991087106823104952723282567247576478901710217187696256883106377762131777502200827895165209409875271987670024104226318541141456416006467124909526742250444801039181096325252980787937, 1516108394291563581129402757918441429103374282540273242535574001686808809056278753069427188395830088378688414390073229867838020209913041172365104049292611891822922405699792228824982320081408133615649588115855890512325779090710043445082538224451754606617750503661325473727213169075371602269467764343908061812510109618078253018279688326849900067366848210517579848333960452975012649436612670651848997870043639151181860894641518880479989748538477173553953687103113277529109777027218496246543551681896161811075929695362823665844770413650851610700668138703783542611069459838985646311963152663040630742739994022184468951693, 345049340451699554007948763472893858069411074537199267556380516213734827871614442990536926350227584616252255045051744656658724729921391320513975448747866674731393989824816278253531731559615988365176956553948361741230399671929627311399657205635358188611855896981664987554010070048005180840005056436207539387449042369726304130418877417881364189259973633455724018939019191261925159303420250412390007010119147742488855420323873249301367316063804185927827524896427158951883596368737320448679598208240720659999317773937210898039147175668295346147218816545703112535909878232871373805727402265504548979315089528552745595697, 2310127393424955205107098753990740358616986137235523761428262577027025221085993167331127781046303783394387937006140407932458365609661360072106720211912369678829021097399331475604691187882409665300952366321289612227771815985404013084073477199260101972484084154567987647887377325483499340128094102430928953352662945461142995341584089062204341970339034221703457214832763736835220434547067732740206252238614354577428802536954307484724292316946308032286724679045981289044117505581194462938042596730344914183773705642632211684448859729662063800386303640529418370614292346515567013769130105736509067539211154067603076086189, 260103909934101734536962369349227910737941229676355629033234214156269594943514773423475990016988081886527609702651915199269149400381634311486797884863469442738377631198605297328240657294126185806275220201520185922158666416638929182005650012419901316367524983201785784243504188316736709689328878602689716382200845553376605467447386204662988107092580795936646455346850407094699708770087824573768242252865671229952401642055406014325968496131314289528932191878614864330913120994685365723644918001169807548626702912355139857537404378099007036012070824841803771589907014266992233954712642256908443894447198510324151722807]
e = 629
N = 3189114686224168527832331594922454956130813095678500091837003591252581589062448982723246876196017944847100818244381832468383363405845911023963060518988016928538755279709811123903342192509780913173428723886393253482859769115568498425217420047666488898487353815066472059082290797546861177320701802469167877671417071641160054157961123316709837879746006591255937485506228981534802657551533225645035775724152887077617722220015769980939338494248274632855471433642146347951726131771323868101240008040640059677232340041423789617615705270452301423174772159475723086187149237364733296047140690284751569807669233727054962069009
possiblechr = "{}abcdefghijklmnopqrstuvwxyz0123456789"
plaintext = ""
for i in ciphertext:
for j in possiblechr:
if(pow(ord(j),e,N) == i):
plaintext += j
print(plaintext)
Rigged Lottery
Description:
I found out that somebody has been able to guarantee to win a prize everytime in this lottery. I can't figure it out how they were able to do that. Can you?
Attachment:
server.py
from inputimeout import inputimeout, TimeoutOccurred
import random, sys
with open('flag.txt') as f:
flag = f.read()
def main():
print("Here is how the lottery works:")
print("- Players purchase tickets comprising their choices of six different numbers between 1 and 70")
print("- During the draw, six balls are randomly selected without replacement from a set numbered from 1 to 70")
print("- A prize is awarded to any player who matches at least two of the six drawn numbers.")
print("- More matches = higher prize!")
while True:
print("\n********************\nHow many tickets would you like to buy? There is a limit of 50 tickets per person")
try:
reply = int(inputimeout(prompt='>> ', timeout=60))
except ValueError:
reply = 0
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
if reply > 50 or reply < 1:
print("That is an invalid choice!\n")
else:
break
tickets = []
for x in range(reply):
ticket = []
print(f"\n********************\nPlease give the numbers for ticket {x+1}:")
for _ in range(6):
while True:
try:
number = int(inputimeout(prompt='>> ', timeout=60))
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
except ValueError:
number = 0
if number > 70 or number < 1:
print("That is an invalid choice!\n")
else:
break
ticket.append(number)
tickets.append(ticket)
winnings = [0, 0, 1, 100, 1000, 100000, 10000000]
print(f"\n********************\nLet's see if you can win in {10**6} consecutive rounds of the lottery and make a profit at the end of it!")
profit = 0
for i in range(10**6):
draw = set([])
while len(draw) != 6:
draw.add(random.randint(1,70))
won_prize = False
for ticket in tickets:
profit -= 1
matches = len(draw.intersection(set(ticket)))
if matches > 1:
won_prize = True
profit += winnings[matches]
if won_prize:
if (i+1)%(10**5) == 0:
print(f"You made it through {i+1} rounds! Profit so far is ${profit}")
else:
print(f"Draw {i+i}: {draw}, profit: ${profit}")
print(f"\n********************\nAh shucks! Look's like you did not win any prizes this round. Better luck next time")
sys.exit()
if profit > 0:
print(f"\n********************\nWow! You broke the lottery system! Here's the well-deserved flag --> {flag}")
if __name__ == "__main__":
main()
Solution:
Bài này..., thôi bỏ đi :v. All you need is here: link
from pwn import *
tickets = ((1, 2, 3, 26, 27, 28),
(1, 4, 26, 30, 31, 34),
(3, 4, 28, 29, 30, 33),
(2, 4, 5, 27, 30, 32),
(3, 5, 28, 31, 32, 34),
(1, 5, 26, 29, 32, 33),
(2, 27, 29, 31, 33, 34),
(6, 35, 36, 42, 7, 37),
(6, 35, 41, 43, 9, 39),
(7, 37, 8, 38, 9, 39),
(6, 35, 10, 40, 8, 38),
(7, 37, 10, 40, 41, 43),
(9, 39, 10, 40, 36, 42),
(36, 42, 8, 38, 41, 43),
(11, 44, 49, 51, 12, 47),
(11, 44, 14, 45, 13, 46),
(12, 47, 50, 52, 13, 46),
(12, 47, 15, 48, 14, 45),
(11, 44, 15, 48, 50, 52),
(13, 46, 15, 48, 49, 51),
(49, 51, 50, 52, 14, 45),
(16, 53, 17, 54, 18, 55),
(16, 53, 58, 61, 20, 59),
(16, 53, 57, 60, 19, 56),
(18, 55, 57, 60, 58, 61),
(18, 55, 19, 56, 20, 59),
(20, 59, 57, 60, 17, 54),
(17, 54, 19, 56, 58, 61),
(21, 62, 63, 69, 25, 64),
(21, 62, 24, 65, 67, 70),
(21, 62, 22, 68, 23, 66),
(25, 64, 67, 70, 22, 68),
(25, 64, 24, 65, 23, 66),
(23, 66, 67, 70, 63, 69),
(63, 69, 24, 65, 22, 68))
if __name__ == '__main__':
#server = process(['python3','server.py'])
server = remote("challenge.nahamcon.com", 30392)
server.recvuntil(b'>> ')
server.sendline(str(len(tickets)).encode())
for ticket in tickets:
for x in ticket:
server.recvuntil(b'>> ')
server.sendline(str(x).encode())
for _ in range(16):
print(server.recvline())
Flag: <ditme tat me server roi>
Blackjack
Description:
Can you make a killing by playing blackjack?
Attachment:
server.py
# A lot of this code is taken from https://github.com/rishimule/blackjack-python
from inputimeout import inputimeout, TimeoutOccurred
import os, sys
suits = ("Hearts", "Clubs", "Diamonds", "Spades")
ranks = ("Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace")
values = {"Two" : 2, "Three" : 3, "Four" : 4, "Five" : 5, "Six" : 6, "Seven" :7, "Eight" : 8, "Nine" : 9, "Ten" : 10, "Jack" : 10, "Queen" : 10, "King" : 10, "Ace" : 11}
class PRNG:
def __init__(self, seed = int(os.urandom(8).hex(),16)):
self.seed = seed
self.state = [self.seed]
self.index = 52
for i in range(51):
self.state.append((3 * (self.state[i] ^ (self.state[i-1] >> 6)) + i+1)%512)
def __str__(self):
return f"{self.state}"
def getnum(self):
if self.index >= 52:
for i in range(52):
y = (self.state[i] & 0x40) + (self.state[(i+1)%52] & 0x3f)
val = y >> 1
val = val ^ self.state[(i+9)%52]
if y & 1:
val = val ^ 69
self.state[i] = val
self.index = 0
seed = self.state[self.index]
self.index += 1
return (seed*13 + 17)%(2**7)
class Card:
def __init__(self,rank,suit):
self.rank = rank
self.suit = suit
self.value = values[rank]
def __str__(self):
return self.rank + " of " + self.suit
class Deck:
def __init__(self):
self.cardlist = []
for suit in suits:
for rank in ranks:
current_card = Card(rank,suit)
self.cardlist.append(current_card)
def __str__(self):
deck_cards = ''
for x in range(len(self.cardlist)):
deck_cards += str(self.cardlist[x]) + "\n"
return f"This Deck has {str(len(self.cardlist))} Cards.\n" + deck_cards
def shuffle_deck(self):
new_deck = []
for i in range(len(self.cardlist)):
x = rng.getnum() % 52
if self.cardlist[x] not in new_deck:
new_deck.append(self.cardlist[x])
elif self.cardlist[i] not in new_deck:
new_deck.append(self.cardlist[i])
else:
for card in self.cardlist:
if card not in self.cardlist:
new_deck.append(card)
break
self.cardlist = new_deck
def deal_one(self):
return self.cardlist.pop(0)
class Player:
def __init__(self,name,chips):
self.name = name
self.chips = chips
self.bet = 0
def __str__(self):
return 'Player {} has {} chips\n'.format(self.name,self.chips)
def add_chips(self,chips):
self.chips += chips
def remove_chips(self,chips):
if chips > self.chips or chips < 1:
print("Invalid amount of Chips.")
print("Current balance = {}".format(self.chips))
else:
self.chips -= chips
print("Current balance = {}".format(self.chips))
class Hand:
def __init__(self):
self.cards = []
self.value = 0
self.ace_count = 0
def __str__(self):
cards_in_hand = ''
for x in range(len(self.cards)):
cards_in_hand += " " + str(self.cards[x]) + "\n"
return cards_in_hand + "This hand has a value of {}.".format(self.value)
def add_card(self,card):
self.cards.append(card)
self.value += card.value
if card.rank == "Ace":
self.ace_count += 1
while self.value > 21 and self.ace_count > 0:
self.value -= 10
self.ace_count -= 1
def take_bet(player):
while True:
try:
current_bet = int(inputimeout(prompt="Amount of chips to bet: ", timeout=60))
if current_bet > player.chips or current_bet < 1:
print("Invalid amount. Please try again\n")
else:
player.bet += current_bet
player.chips -= current_bet
break
except ValueError:
print("That is an invalid option! Please try again\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
def create_player():
global player
while True:
try:
player_name = inputimeout("Please enter your name: ", timeout=60)
if player_name != '':
break
else:
print("Please enter a valid name\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
player = Player(player_name,1000)
def adjust_winnings(winner):
if winner == "player":
player.chips += int(player.bet*1.5)
player.bet = 0
elif winner == "tie" :
player.chips += player.bet
player.bet = 0
else:
player.bet = 0
def hit_or_stand(player_hand,deck_1):
while True:
try:
temp = inputimeout(prompt="HIT OR STAND? : ", timeout=60)
if temp == '':
print("Please choose a valid option\n")
elif temp[0].lower() == 'h':
player_hand.add_card(deck_1.deal_one())
break
elif temp[0].lower() == 's':
break
else:
print("Please choose a valid option\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
if temp[0].lower() == 'h':
return "h"
else:
return "s"
def player_busted():
global winner
print("\nPlayer Busted.")
print("Dealer Wins!\n")
winner = "dealer"
def dealer_busted():
global winner
print("\nDealer Busted.")
print("Player Wins!\n")
winner = "player"
def player_dealer_tie():
global winner
print("IT'S A TIE!!\n")
winner = "tie"
def player_wins():
global winner
print("Player Wins!\n")
winner = "player"
def dealer_wins():
global winner
print("Dealer Wins!\n")
winner = "dealer"
def show_some_cards(player_hand, dealer_hand):
print("\nPlayer Cards are : ")
print(str(player_hand))
print("\nDealer Cards are : ")
print(" " + str(dealer_hand.cards[0]))
print("**Card is Hidden.**")
print(50*'*')
def show_all_cards(player_hand, dealer_hand):
print("\nPlayer Cards are : ")
print(str(player_hand))
print("\nDealer Cards are : ")
print(str(dealer_hand))
print(50*'*')
def main(player):
deck_1=Deck()
deck_1.shuffle_deck()
player_hand = Hand()
dealer_hand = Hand()
print(50*'*')
print(player)
take_bet(player)
player_hand.add_card(deck_1.deal_one())
player_hand.add_card(deck_1.deal_one())
dealer_hand.add_card(deck_1.deal_one())
dealer_hand.add_card(deck_1.deal_one())
show_some_cards(player_hand, dealer_hand)
while True:
if player_hand.value == 21:
break
elif player_hand.value > 21:
player_busted()
break
req = hit_or_stand(player_hand, deck_1)
if req == 's':
break
show_some_cards(player_hand, dealer_hand)
show_all_cards(player_hand, dealer_hand)
dealer_playing = True
while dealer_playing:
if player_hand.value <= 21:
while dealer_hand.value < 17 :
print("\nDealer Hits......")
dealer_hand.add_card(deck_1.deal_one())
show_all_cards(player_hand, dealer_hand)
dealer_playing = False
if dealer_hand.value > 21:
dealer_busted()
break
elif player_hand.value == dealer_hand.value:
player_dealer_tie()
break
elif player_hand.value > dealer_hand.value:
player_wins()
break
else:
dealer_wins()
break
else:
break
adjust_winnings(winner)
print("\n" + str(player))
def play_again():
while True:
print(50*'*')
try:
temp = inputimeout(prompt="\nWant to play again? : ", timeout=60)
if temp[0].lower() == 'y':
return True
elif temp[0].lower() == 'n':
print(50*'*')
print("\nThank you for playing...\n")
print(50*'*')
return False
else:
print("Please choose a valid option\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
if __name__ == '__main__':
playing = True
create_player()
global rng
rng = PRNG()
while playing:
main(player)
if player.chips >= 1000000:
print(50*'*')
print("Congratulations on winning this big! Here's a special reward for that...")
with open('flag.txt', 'r') as f:
print(f.read())
print("\nThank you for playing...\n")
print(50*'*')
break
elif player.chips == 0:
print(50*'*')
print("Sorry for losing everything. Better luck next time!")
print(50*'*')
break
playing=play_again()
Recon:
Bài này thì nó chính là một code game Blackjack luôn. Mục tiêu là ta phải thắng đủ 1.000.000 chips để có thể lấy đươc flag. Có một số điểm cần lưu ý:
Nếu nhà cái có số điểm >= 17 thì sẽ auto STAND.
Mỗi lần thắng, nếu all in ta sẽ lãi 50% vốn.
Bộ bài được shuffle sẽ là thứ tự bốc, mình sẽ được phát 2 con đầu và nhà cái là 2 con sau (cái này cứ print ra là thấy chứ đọc code chết)
=> Chỉ cần biết trước được bộ bài đã shuffle, ta có thể HIT or STAND một cách thuận lợi để lời nhiều nhất và lỗ ít nhất. Đơn giản là nếu không thắng được, ta sẽ biết trước và cược 1 chips only.
Solution:
Ý tưởng giải bài này: link
Nôm na thì state thực sự chỉ dựa vào 15 bit cuối của seed nên mình có thể bruteforce seed trong khoảng 2**15. Sau đó mình hoàn toàn có thể lấy được shuffled desk của từng ván, từ đó quyết định HIT or STAND.
Bằng cách đầu hàng ván đầu (dùng 1 chips), mình hoàn toàn có thể lấy được tối thiểu 4 lá bài đầu của bộ shuffled (sẽ cho vào file input.txt
). Nếu seed nào cho ra outputs có 4 lá đó liền nhau, đó chính là seed đúng. Đây là code để lấy ra seed và hiển thị bộ bài (mình không hiển thị các bài đã trên tay để cho mục đích cá nhân: chơi cho dễ).
from inputimeout import inputimeout, TimeoutOccurred
import os
import sys
from tqdm import tqdm
from pwn import *
suits = ("Hearts", "Clubs", "Diamonds", "Spades")
ranks = ("Two", "Three", "Four", "Five", "Six", "Seven",
"Eight", "Nine", "Ten", "Jack", "Queen", "King", "Ace")
values = {"Two": 2, "Three": 3, "Four": 4, "Five": 5, "Six": 6, "Seven": 7,
"Eight": 8, "Nine": 9, "Ten": 10, "Jack": 10, "Queen": 10, "King": 10, "Ace": 11}
class PRNG:
def __init__(self, seed=int(os.urandom(8).hex(), 16)):
self.seed = seed
self.state = [self.seed]
self.index = 52
for i in range(51):
self.state.append(
(3 * (self.state[i] ^ (self.state[i-1] >> 6)) + i+1) % 512)
def __str__(self):
return f"{self.state}"
def getnum(self):
if self.index >= 52:
for i in range(52):
y = (self.state[i] & 0x40) + (self.state[(i+1) % 52] & 0x3f)
val = y >> 1
val = val ^ self.state[(i+9) % 52]
if y & 1:
val = val ^ 69
self.state[i] = val
self.index = 0
seed = self.state[self.index]
self.index += 1
return (seed*13 + 17) % (2**7)
class Card:
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
self.value = values[rank]
def __str__(self):
return self.rank + " of " + self.suit
class Deck:
def __init__(self):
self.cardlist = []
for suit in suits:
for rank in ranks:
current_card = Card(rank, suit)
self.cardlist.append(current_card)
def __str__(self):
deck_cards = ''
for x in range(9):
deck_cards += str(self.cardlist[x]) + "\n"
return f"This Deck has {str(len(self.cardlist))} Cards.\n" + deck_cards
def shuffle_deck(self):
new_deck = []
for i in range(len(self.cardlist)):
x = rng.getnum() % 52
if self.cardlist[x] not in new_deck:
new_deck.append(self.cardlist[x])
elif self.cardlist[i] not in new_deck:
new_deck.append(self.cardlist[i])
else:
for card in self.cardlist:
if card not in self.cardlist:
new_deck.append(card)
break
self.cardlist = new_deck
def deal_one(self):
return self.cardlist.pop(0)
class Player:
def __init__(self, name, chips):
self.name = name
self.chips = chips
self.bet = 0
def __str__(self):
return 'Player {} has {} chips\n'.format(self.name, self.chips)
def add_chips(self, chips):
self.chips += chips
def remove_chips(self, chips):
if chips > self.chips or chips < 1:
print("Invalid amount of Chips.")
print("Current balance = {}".format(self.chips))
else:
self.chips -= chips
print("Current balance = {}".format(self.chips))
class Hand:
def __init__(self):
self.cards = []
self.value = 0
self.ace_count = 0
def __str__(self):
cards_in_hand = ''
for x in range(len(self.cards)):
cards_in_hand += " " + str(self.cards[x]) + "\n"
return cards_in_hand + "This hand has a value of {}.".format(self.value)
def add_card(self, card):
self.cards.append(card)
self.value += card.value
if card.rank == "Ace":
self.ace_count += 1
while self.value > 21 and self.ace_count > 0:
self.value -= 10
self.ace_count -= 1
def take_bet(player):
while True:
try:
current_bet = int(inputimeout(
prompt="Amount of chips to bet: ", timeout=60))
if current_bet > player.chips or current_bet < 1:
print("Invalid amount. Please try again\n")
else:
player.bet += current_bet
player.chips -= current_bet
break
except ValueError:
print("That is an invalid option! Please try again\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
def create_player():
global player
while True:
try:
player_name = "TrungPQ"
if player_name != '':
break
else:
print("Please enter a valid name\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
player = Player(player_name, 1000)
def adjust_winnings(winner):
if winner == "player":
player.chips += int(player.bet*1.5)
player.bet = 0
elif winner == "tie":
player.chips += player.bet
player.bet = 0
else:
player.bet = 0
def hit_or_stand(player_hand, deck_1):
while True:
try:
temp = inputimeout(prompt="HIT OR STAND? : ", timeout=60)
if temp == '':
print("Please choose a valid option\n")
elif temp[0].lower() == 'h':
player_hand.add_card(deck_1.deal_one())
break
elif temp[0].lower() == 's':
break
else:
print("Please choose a valid option\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
if temp[0].lower() == 'h':
return "h"
else:
return "s"
def player_busted():
global winner
print("\nPlayer Busted.")
print("Dealer Wins!\n")
winner = "dealer"
def dealer_busted():
global winner
print("\nDealer Busted.")
print("Player Wins!\n")
winner = "player"
def player_dealer_tie():
global winner
print("IT'S A TIE!!\n")
winner = "tie"
def player_wins():
global winner
print("Player Wins!\n")
winner = "player"
def dealer_wins():
global winner
print("Dealer Wins!\n")
winner = "dealer"
def show_some_cards(player_hand, dealer_hand):
print("\nPlayer Cards are : ")
print(str(player_hand))
print("\nDealer Cards are : ")
print(" " + str(dealer_hand.cards[0]))
print("**Card is Hidden.**")
print(50*'*')
def show_all_cards(player_hand, dealer_hand):
print("\nPlayer Cards are : ")
print(str(player_hand))
print("\nDealer Cards are : ")
print(str(dealer_hand))
print(50*'*')
def main(player):
deck_1 = Deck()
deck_1.shuffle_deck()
return deck_1
def play_again():
while True:
print(50*'*')
try:
temp = inputimeout(prompt="\nWant to play again? : ", timeout=60)
if temp[0].lower() == 'y':
return True
elif temp[0].lower() == 'n':
print(50*'*')
print("\nThank you for playing...\n")
print(50*'*')
return False
else:
print("Please choose a valid option\n")
except TimeoutOccurred:
print("Oof! Not fast enough!\n")
sys.exit()
with open('input.txt', 'r') as file:
lines = file.readlines()
c = ''
for line in lines:
c += line
print(c)
for i in tqdm(range(2**15)):
create_player()
rng = PRNG(seed=i)
m = str(main(player))
if c in m:
print("Found seed = ", i)
print(m)
break
while True:
deck_1 = Deck()
deck_1.shuffle_deck()
player_hand = Hand()
dealer_hand = Hand()
player_hand.add_card(deck_1.deal_one())
player_hand.add_card(deck_1.deal_one())
dealer_hand.add_card(deck_1.deal_one())
dealer_hand.add_card(deck_1.deal_one())
print("Shuffled")
print("You: ", player_hand.value)
print("Dealer: ", dealer_hand.value)
print(deck_1)
c = input()
Dựa trên việc số chips sau khi all in sẽ bằng 1.5 lần số chips gốc, chỉ cần mình thắng all in khoảng 18 lần là sẽ thừa tiền lấy flag.
Do đếu viết được code solve bằng pwntools vì output mỗi lần đều khác và logic hơi phức tạp với mình để code, nên mình sẽ chơi bằng tay (18 lần bọ)
Flag: flag{49bfe61dce46fc826814208e020f58f3}
© 2024,Pham Quoc Trung. All rights reserved.
Last updated