Arab Security Cyber Wargames 2022 Qualifications && corCTF 部分题解


周末找了两个国外的比赛,做了几个题。

ASCWQ 2022

(这个比赛的源码忘保存了。。。现在想写博客发现官网把challenges关了,只能随便写点思路QAQ

Crypto

Rsa In The Wild

审查源码可以知道调用密钥生成函数时使用的p是固定的,对于每个接入的用户,系统会单独生成一个q,然后计算n进行RSA。因此求用户key的最大公因数就可以拿到p。
四个人key的gcd等于1,猜测分组了,遍历发现第一个人和第三个人使用一组p,第二个人和第四个人使用另一组p。
将四个人的key分解掉,分别求解即可。

import json
from math import gcd
from libnum import invmod

with open('output.json', 'r') as f:
    info = json.load(f)

k = []
c = []
APT = ['John', 'Sara', 'Y4mm1', 'Gary']
for i in range(4):
    k.append(info[i][APT[i]]['key'])
    c.append(info[i][APT[i]]['msg'])
    
e = 0x10001
p1 = gcd(k[0],k[2])
p2 = gcd(k[1],k[3])
q1 = k[0] // p1
q2 = k[1] // p2
q3 = k[2] // p1
q4 = k[3] // p2

d1 = invmod(e,(p1-1)*(q1-1))
d2 = invmod(e,(p2-1)*(q2-1))
d3 = invmod(e,(p1-1)*(q3-1))
d4 = invmod(e,(p2-1)*(q4-1))

m1 = n2s(int(pow(c[0],d1,k[0])))
m2 = n2s(int(pow(c[1],d2,k[1])))
m3 = n2s(int(pow(c[2],d3,k[2])))
m4 = n2s(int(pow(c[3],d4,k[3])))

print(m1)
print(m2)
print(m3)
print(m4)

# b'\x0cX\x08\x0b\xc4)\xcd\xcd\x8f<\xb0]\x87\x03\xcd\xf0\x0e\xac\xbd9\x079\x86$\'ej\xdfl\xa2\xf7\xa8)\x15\xe3\xef3\x9e\xd9\x89\xd9&\x99"\x03[\x83\x12\xb8\x0b\xa9WEm\x9a\x80\'\x9bHB\x03\x12\xb6?\xf5$\xec\x10\xdc\xa8P\x8f\x88\x06\xad"\xe6\xe1\xa5\xb0*\xac\xd3\xf4\x9c\x03\xf9\xd1\xc3\xd6[X\xc2\xb4T\xe0<\xbc\x8cF.5?\x11\x14<\xe8\x9dN\xbd9\xc9\xe0\xf9b\xbd\xbc\x05\x0e\xa1\x9b\xc7~\x94\xcb\xd7\xa2\x04'
# b"Hello, friend! It's me again. I can cipher things with my mind! ASCWG{7h3_c0mM0n_9re4t_P0W3r_0f_6r0k3N_R$A}"
# b'a{\x8c\xcb=\xe8\xe5$z\xb2\x08\xa50fz\xc6\x96\x9e\xc8@RP\x18\x01V\x85N\x80\xa7A\x03\xfa\xbbhxw\xa3\xbc\x9d\x85\xcb\x85{"\xa5\xf8-\xf7\xb8\x96\xbc\xcc\x04\xb0\xfa{u:\xa5h\xc2j\xba\x96\x02\x81\xa4\x10\x0c7p\\\xf2\xbc\xa5u\xc5\xf9r\xac/\xe4U\xe3\xcc\xcb\xb7\xe8\xa3\xedO\x91\x89\x15\x9e\x11G9\xff\xea>\xb3\x94\x11\xc4\x9b\xa4eC\x93\x12\xe5[\x15u\xae5\xbb\xe2&\xca!\xf5\xf2\xa3KM'
# b"\x17\xfe&\x9c.\\e\xb6\x91\xdc7\xcf\xf0UA\x10(\x915}4\x05\x1d\xf23\x17\x0co\x1d\xa5\xccO\t\x89\x98\x12\xe4\x06\xaa\xc2B\xbe#v9\xa5[m\x96\x91\xfe\xef\x1f{\xf3\xd8\x06\x9c\x05\x18zW\x01\xda(\xac3\x8f\xa1\x02\x92F\x96\xe0\xf9\x8c+\xb0\xb2\x9be\x0e1\x97\xd6\xec%\xf8\x16\xf6\xf0\xb3Y\xcb\xeb\xc4\xc8\xa4Y\x0bWy\xff\xc4IDw\\\xa7\x9b\xf5P\xb4\xd9\xdaM\xca\xb4\x9b\x8a\x95'\r\x08\xa9\xe1n%"

OSP

一次一密,生成了一个与flag等长的字节流secret,对flag中的每个字符做如下处理(十六进制值):

flag[i] = flag[i] * p + secret[i]

其中p和secret均未知,但是我们知道flag格式肯定是"ASCWQ{XXX}",而且字节流串每个字节最大的值是0xff,完全可以爆破。因此我们尝试先把p爆出来。
A的ascii是65,S的ascii是83,本身是互素的,只需要爆破256*256即可:

with open('output.txt', 'r') as f:
    c = f.read().splitlines()

for i in range(256):
	mul1 = c[0] - i
	for j in range(256):
		mul2 = c[1] - j
		if gcd(mul1,mul2) > 1:
			print(gcd(mul1,mul2))

结果有个很明显的大素数就是p。
这样我们就可以爆破所有字符:

for i in range(len(c)):
	for j in range(256):
		if (c[i] - j) % p == 0:
			print(chr((c[i] - j) // p),end='')
			
# ASCWG{Wh47_1f_17's_N07_@_Pr1M3!-f0ffa3657e}

Misc

Weird FS

给了一个img镜像,但是用Linux尝试挂载时会报/dev/loop0的经典错误,估计是数据块识别错误。
先看看里面藏没藏东西,binwalk一下发现里面有个Flag.zip。分离出来发现有密码。strings看一下时间戳,没找到密钥。猜测压缩包是个弱口令加密,用Kit爆一下得到口令:juelma。解压就可以拿到flag了。

ASCWG{M4C_4N6_1$_Co0l}

corCTF 2022

Crypto的几个跟LCG有关的题还不错。

Crypto

tadpole

f ( 31337 ) ≡ a × 31337 + b   ( m o d   p ) f ( f ( 31337 ) ) ≡ a × f ( 31337 ) + b   ( m o d   p ) ⇒ g = g c d ( f ( 31337 ) − ( a × 31337 + b ) , f ( f ( 31337 ) ) − ( a × f ( 31337 ) + b ) ) = k p i f   i s P r i m e ( g ) ⇒ g = p f(31337) \equiv a \times 31337 + b \space (mod \space p) \\ f(f(31337)) \equiv a \times f(31337) + b \space (mod \space p) \\ \Rightarrow g = gcd(f(31337)-(a \times 31337 + b),f(f(31337))-(a \times f(31337) + b)) =kp \\ if \space isPrime(g) \Rightarrow g = p f(31337)a×31337+b (mod p)f(f(31337))a×f(31337)+b (mod p)g=gcd(f(31337)(a×31337+b),f(f(31337))(a×f(31337)+b))=kpif isPrime(g)g=p

from Crypto.Util.number import *
from math import gcd
from libnum import n2s

a = 7904681699700731398014734140051852539595806699214201704996640156917030632322659247608208994194840235514587046537148300460058962186080655943804500265088604049870276334033409850015651340974377752209566343260236095126079946537115705967909011471361527517536608234561184232228641232031445095605905800675590040729
b = 16276123569406561065481657801212560821090379741833362117064628294630146690975007397274564762071994252430611109538448562330994891595998956302505598671868738461167036849263008183930906881997588494441620076078667417828837239330797541019054284027314592321358909551790371565447129285494856611848340083448507929914
f = 52926479498929750044944450970022719277159248911867759992013481774911823190312079157541825423250020665153531167070545276398175787563829542933394906173782217836783565154742242903537987641141610732290449825336292689379131350316072955262065808081711030055841841406454441280215520187695501682433223390854051207100
ff = 65547980822717919074991147621216627925232640728803041128894527143789172030203362875900831296779973655308791371486165705460914922484808659375299900737148358509883361622225046840011907835671004704947767016613458301891561318029714351016012481309583866288472491239769813776978841785764693181622804797533665463949

g = gcd(ff - (a * f + b),f - (a * 31337 + b))
if isPrime(g):
	print(n2s(g))
	
# b'corctf{1n_m4th3m4t1c5,_th3_3ucl1d14n_4lg0r1thm_1s_4n_3ff1c13nt_m3th0d_f0r_c0mput1ng_th3_GCD_0f_tw0_1nt3g3rs} <- this is flag adm'

luckyguess

p已知,LCG内置参数a、b未知。用户可以输入LCG的初始值x,x被放入生成器转r轮后输出,要求用户给出输出值,r未知。
求解方程 a x + b ≡ x   ( m o d   p ) ax+b \equiv x \space(mod \space p) ax+bx (mod p),提交x,此时无论r为多少,LCG中始终只有一个值。

from pwn import *
import re
from libnum import invmod

p = remote("be.ax", 31800)

prime = 2**521 - 1
s = str(p.recv())
a,b = int(re.findall(r'\d+',s)[0]),int(re.findall(r'\d+',s)[1])
print(a,b)
payload = (invmod(a-1,prime)*(-b)) % prime
print(payload)
p.sendline(str(payload).encode())
print(p.recv())
p.sendline(str(payload).encode())
print(p.recv())

# corctf{r34l_psych1c5_d0nt_n33d_f1x3d_p01nt5_t0_tr1ck_th15_lcg!}

exchanged

考点其实很基础,不过很好的解释了为什么plainLCG不能用来设计密钥交换算法。
LCG的p和内置参数a、b已知。定义:
f ( s ) ≡ a × s + b   ( m o d   p ) f n ( s ) ≡ f ( f ( f ( . . . f ( f ( s ) ) . . . ) ) ) ⏟ n 次   ( m o d   p ) f(s) \equiv a \times s+b \space (mod \space p) \\ f^n(s) \equiv \underbrace{f(f(f(...f(f(s))...)))}_{n次} \space (mod \space p) f(s)a×s+b (mod p)fn(s)n f(f(f(...f(f(s))...))) (mod p)
假设A与B要利用这个基础的LCG,共享密钥,二者商定一个基础的公共值s,满足s小于p即可。
此时A生成一个小于p的随机数 a p r i v a_{priv} apriv作为私钥,计算公钥 P K A = f a p r i v ( s ) PK_A=f^{a_{priv}}(s) PKA=fapriv(s);B生成一个小于p的随机数 b p r i v b_{priv} bpriv作为私钥,计算公钥 P K B = f b p r i v ( s ) PK_B=f^{b_{priv}}(s) PKB=fbpriv(s)。A和B把公钥 P K A PK_A PKA P K B PK_B PKB公开至共享信道,随后A计算 f a p r i v ( P K B ) f^{a_{priv}}(PK_B) fapriv(PKB),B计算 f b p r i v ( P K A ) f^{b_{priv}}(PK_A) fbpriv(PKA),由于定义 f f f函数满足性质:
f a ( f b ( s ) ) = f a + b ( s ) f^a(f^b(s))=f^{a+b}(s) fa(fb(s))=fa+b(s)
故有:
f a p r i v ( P K B ) = f a p r i v ( f b p r i v ( s ) ) = f a p r i v + b p r i v ( s ) = f b p r i v ( P K A ) f^{a_{priv}}(PK_B)=f^{a_{priv}}(f^{b_{priv}}(s))=f^{a_{priv}+b_{priv}}(s)=f^{b_{priv}}(PK_A) fapriv(PKB)=fapriv(fbpriv(s))=fapriv+bpriv(s)=fbpriv(PKA)
此时二者完成密钥共享, K = f a p r i v + b p r i v ( s ) K=f^{a_{priv}+b_{priv}}(s) K=fapriv+bpriv(s)
由于 a p r i v a_{priv} apriv b p r i v b_{priv} bpriv都非常大,因此在CTF环境下无法采取暴力破解的手段计算二者的私钥,但是可以发现这个过程存在一个最大的问题:LCG采用的线性算法具有同构性。
f n ( s ) ≡ f ( f ( f ( . . . f ( f ( s ) ) . . . ) ) ) ⏟ n 次   ( m o d   p ) ≡ a ( . . . a ( a ( a s + b ) + b ) + b . . . ) + b   ( m o d   p ) ≡ a n s + ( a n − 1 + a n − 2 + . . . + 1 ) b   ( m o d   p ) ≡ a ′ s + b ′   ( m o d   p ) f^n(s) \equiv \underbrace{f(f(f(...f(f(s))...)))}_{n次} \space (mod \space p) \\ \equiv a(...a(a(as+b)+b)+b...)+b \space (mod \space p)\\ \equiv a^ns +(a^{n-1}+a^{n-2}+...+1)b \space (mod \space p) \\ \equiv a's+b' \space (mod \space p) fn(s)n f(f(f(...f(f(s))...))) (mod p)a(...a(a(as+b)+b)+b...)+b (mod p)ans+(an1+an2+...+1)b (mod p)as+b (mod p)
可以发现,迭代n次 f f f函数得到的结果仍可以写成 a ′ s + b ′ a's+b' as+b的形式,如果我们定义一个内置参数为 a ′ a' a b ′ b' b的LCG,及其相关的计算函数 f ′ f' f,则有:
f ′ ( s ) ≡ a ′ × s + b ′   ( m o d   p ) f n ( s ) ≡ f ′ ( s )   ( m o d   p ) f'(s) \equiv a' \times s+b' \space (mod \space p) \\ f^n(s) \equiv f'(s) \space (mod \space p) f(s)a×s+b (mod p)fn(s)f(s) (mod p)
其中 a ′ = a n a'=a^n a=an b ′ = ( a n − 1 + a n − 2 + . . . + 1 ) b = ( a − 1 ) − 1 ( a n − 1 ) b b'=(a^{n-1}+a^{n-2}+...+1)b=(a-1)^{-1}(a^n-1)b b=(an1+an2+...+1)b=(a1)1(an1)b
从以上推导回到LCG密钥交换问题,可以发现:
f a p r i v ( s ) ≡ a a p r i v × s + ( a − 1 ) − 1 ( a a p r i v − 1 ) b   ( m o d   p ) ⇒ ( a − 1 ) f a p r i v ( s ) ≡ ( a − 1 ) × a a p r i v × s + ( a a p r i v − 1 ) b   ( m o d   p ) ⇒ [ ( a − 1 ) s + b ] × a a p r i v ≡ ( a − 1 ) f a p r i v ( s ) + b   ( m o d   p ) ⇒ a a p r i v ≡ [ ( a − 1 ) s + b ] − 1 [ ( a − 1 ) f a p r i v ( s ) + b ]   ( m o d   p ) f^{a_{priv}}(s) \equiv a^{a_{priv}} \times s + (a-1)^{-1}(a^{a_{priv}}-1)b\space (mod \space p) \\ \Rightarrow (a-1)f^{a_{priv}}(s)\equiv (a-1) \times a^{a_{priv}} \times s +(a^{a_{priv}}-1)b\space (mod \space p) \\ \Rightarrow [(a-1)s+b] \times a^{a_{priv}}\equiv (a-1)f^{a_{priv}}(s)+b\space (mod \space p) \\ \Rightarrow a^{a_{priv}}\equiv[(a-1)s+b]^{-1}[(a-1)f^{a_{priv}}(s)+b]\space (mod \space p) fapriv(s)aapriv×s+(a1)1(aapriv1)b (mod p)(a1)fapriv(s)(a1)×aapriv×s+(aapriv1)b (mod p)[(a1)s+b]×aapriv(a1)fapriv(s)+b (mod p)aapriv[(a1)s+b]1[(a1)fapriv(s)+b] (mod p)
同理可知:
a b p r i v ≡ [ ( a − 1 ) s + b ] − 1 [ ( a − 1 ) f b p r i v ( s ) + b ]   ( m o d   p ) a^{b_{priv}}\equiv[(a-1)s+b]^{-1}[(a-1)f^{b_{priv}}(s)+b]\space (mod \space p) abpriv[(a1)s+b]1[(a1)fbpriv(s)+b] (mod p)
此时可以破解共享密钥:
K = f a p r i v ( P K B ) = f a p r i v ( f b p r i v ( s ) ) = a a p r i v × f b p r i v ( s ) + ( a − 1 ) − 1 ( a a p r i v − 1 ) b K=f^{a_{priv}}(PK_B)=f^{a_{priv}}(f^{b_{priv}}(s)) \\ =a^{a_{priv}} \times f^{b_{priv}}(s) + (a-1)^{-1}(a^{a_{priv}}-1)b K=fapriv(PKB)=fapriv(fbpriv(s))=aapriv×fbpriv(s)+(a1)1(aapriv1)b
或者:
K = f b p r i v ( P K A ) = f b p r i v ( f a p r i v ( s ) ) = a b p r i v × f a p r i v ( s ) + ( a − 1 ) − 1 ( a b p r i v − 1 ) b K=f^{b_{priv}}(PK_A)=f^{b_{priv}}(f^{a_{priv}}(s)) \\ =a^{b_{priv}} \times f^{a_{priv}}(s) + (a-1)^{-1}(a^{b_{priv}}-1)b K=fbpriv(PKA)=fbpriv(fapriv(s))=abpriv×fapriv(s)+(a1)1(abpriv1)b
题中给出了p、a、b、s和 f a p r i v ( s ) f^{a_{priv}}(s) fapriv(s) f b p r i v ( s ) f^{b_{priv}}(s) fbpriv(s),求解共享密钥。共享密钥被用作AES-CBC中的key加密flag,解密一下即可。

p = 142031099029600410074857132245225995042133907174773113428619183542435280521982827908693709967174895346639746117298434598064909317599742674575275028013832939859778024440938714958561951083471842387497181706195805000375824824688304388119038321175358608957437054475286727321806430701729130544065757189542110211847
a = 118090659823726532118457015460393501353551257181901234830868805299366725758012165845638977878322282762929021570278435511082796994178870962500440332899721398426189888618654464380851733007647761349698218193871563040337609238025971961729401986114391957513108804134147523112841191971447906617102015540889276702905
b = 57950149871006152434673020146375196555892205626959676251724410016184935825712508121123309360222777559827093965468965268147720027647842492655071706063669328135127202250040935414836416360350924218462798003878266563205893267635176851677889275076622582116735064397099811275094311855310291134721254402338711815917

def f(s):
    return (a * s + b) % p

def mult(s, n):
    for _ in range(n):
        s = f(s)
    return s

s = 35701581351111604654913348867007078339402691770410368133625030427202791057766853103510974089592411344065769957370802617378495161837442670157827768677411871042401500071366317439681461271483880858007469502453361706001973441902698612564888892738986839322028935932565866492285930239231621460094395437739108335763
A = 27055699502555282613679205402426727304359886337822675232856463708560598772666004663660052528328692282077165590259495090388216629240053397041429587052611133163886938471164829537589711598253115270161090086180001501227164925199272064309777701514693535680247097233110602308486009083412543129797852747444605837628
B = 132178320037112737009726468367471898242195923568158234871773607005424001152694338993978703689030147215843125095282272730052868843423659165019475476788785426513627877574198334376818205173785102362137159225281640301442638067549414775820844039938433118586793458501467811405967773962568614238426424346683176754273

m = (invmod((a-1) * s + b, p) * (B * (a-1) + b)) % p
k = (invmod((a-1) * s + b, p) * (A * (a-1) + b)) % p
shared1 = (m * A + invmod(a-1, p) * (m-1) * b) % p
shared2 = (k * B + invmod(a-1, p) * (k-1) * b) % p
assert shared1 == shared2
shared = 86382471144674987516192390676739968790606018844855369676663312319897424264589519056860582366433954661923689613455950996957073708730586503567240461427068073600946731416068482076340126294642483394238838801798961052802865121895198819944744990914204503217602305639165324158861726404756338767093146109002421799336
key = sha256(long_to_bytes(shared)).digest()[:16]
c = long_to_bytes(0x482eae28750eaba12f4f76091b099b01fdb64212f66caa6f366934c3b9929bad37997b3f9d071ce3c74d3e36acb26d6efc9caa2508ed023828583a236400d64e)
iv = long_to_bytes(0xe0364f9f55fc27fc46f3ab1dc9db48fa)
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
print(cipher.decrypt(c))

# b'corctf{th1s_lcg_3xch4ng3_1s_4_l1ttl3_1ns3cur3_f0r_n0w}\n\n\n\n\n\n\n\n\n\n'

hidE

这个题比赛时没搞出来。等大佬wp。。。

def encrypt(msg):
    e = random.randint(1, n)
    while math.gcd(e, phi) != 1:
        e = random.randint(1, n)
    pt = bytes_to_long(msg)
    ct = pow(pt, e, n)
    return binascii.hexlify(long_to_bytes(ct)).decode()

通过加密源码可以发现每次调用encrypt函数加密的时候都会新生成一个e,相当于e不可知。远程允许用户拿到加密的flag或者提请内容进行加密。
明显e不能直接解出来(离散对数难度)。
回顾代码发现系统设置了random的种子数:

random.seed(int(time.time()))

这句代码是在加密模块以外的。因此推测可以攻击系统时间,泄露seed后自行构造random.randint,这样便可以预言e。申请得到两个加密的flag然后共模就行。
然而获取系统时间失败了。。。telnetlib也不行。寄。
先贴上一个脚本,以后再看:

from pwn import *
import re
import random
from math import log,floor
from Crypto.Util.number import isPrime

def bit_to_list(t, n):
    s = [0 for i in range(n)]    
    i = -1
    while t != 0:
        s[i] = t % 2 
        t >>= 1
        i -= 1 
    return s

def fast_power(a, b, p):
    if b == 0:
        return 1
    n = 1
    if b != 0:
        blist = bit_to_list(b,floor(log(b,2)+1))
        n = 1
        for i in range(len(blist)-1,-1,-1):
            if blist[i] == 1:
                n = ((a % p) * (n % p)) % p
            a = ((a % p) ** 2) % p
    return n

def euclidean_extended(e1, e2):
    a1 = 0
    a2 = 1
    b1 = 1
    b2 = 0
    while e1 != 0 and e2 != 0:
        if e1 < 0:
            e1 = -e1
            a1 = -a1
            b1 = -b1
        if e2 < 0:
            e2 = -e2
            a2 = -a2
            b2 = -b2
        if e1 >= e2:
            s = e1 // e2
            e1 = e1 - e2 * s
            a1 = a1 - a2 * s
            b1 = b1 - b2 * s
        else:
            s = e2 // e1
            e2 = e2 - e1 * s
            a2 = a2 - a1 * s
            b2 = b2 - b1 * s
    if e1 != 0:
        e1 += e2
        b1 += b2
        a1 += a2
        return b1,a1,e1
    else:
        e2 += e1
        b2 += b1
        a2 += a1
        return b2,a2,e2

p = remote("be.ax", 31124)

random.seed(int(time.time()))


N = int(re.findall(r'\d+',str(p.recv()))[0])
e1 = random.randint(1, N)
while not isPrime(e1):
    e1 = random.randint(1, N)
e2 = random.randint(1, N)
while not isPrime(e1):
    e2 = random.randint(1, N)

p.sendline('1'.encode())
s1 = str(p.recv())
c1 = ""
flag = 0
for i in s1:
    if flag == 1:
        c1 += i
    if i == ':':
        flag = 1
    if i == '\n':
        flag = 0
c1 = int('0x'+c1[1:-88],16)

p.sendline('1'.encode())
s2 = str(p.recv())
c2 = ""
flag = 0
for i in s2:
    if flag == 1:
        c2 += i
    if i == ':':
        flag = 1
    if i == '\n':
        flag = 0
c2 = int('0x'+c2[1:-88],16)

a1,b1,g = euclidean_extended(e1,e2)
if a1 < 0:
    c1,b,g = euclidean_extended(c1,N)
    a1 = -a1
if b1 < 0:
    c2,b,g = euclidean_extended(c2,N)
    b1 = -b1
m = fast_power(fast_power(c1,a1,N)*fast_power(c2,b1,N),1,N)
print(m)

更新:一个很神奇的做法
远程提供了功能,用户可以提交任意消息进行加密。直接提交0x02,利用2的幂次泄露e,获取多组执行CommonMod。
よっちんのブログ corCTF 2022 Writeup

Forensics

whack-a-frog

HTML流量导出,发现文件夹下所有的文件名格式统一:

anticheat%3fx=8&y=14&event=mousemove

典型的鼠标流量,脚本遍历文件名提取坐标绘图:

import os
import re
from PIL import Image

filePath = 'D:\\out\\'
k = os.listdir(filePath)
point = []
for i in k:
    point.append([int(j) for j in re.findall(r'\d+', i)])


res = Image.new('RGB', (520, 68), 255)
k = 0
for i in range(520):
    for j in range(68):
        flag = 0
        for m in point:
            if i == m[1] and j == m[2]:
                res.putpixel((i,j), (0,0,0))
                k += 1
                flag = 1
                break
        if flag == 0:
            res.putpixel((i,j), (255,255,255))
    

res.save('out.png')
res.show()

# corctf{LILYXOX}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值