a✳Aura's workspace好奇心永不休眠
我的文章GitHub
Aura Blog
记录 · 探索 · 分享
Aura2025帕鲁杯线上 WP
返回知识库

2025帕鲁杯线上 WP

应急响应主线

1

提交堡垒机中留下的flag

palu{2025_qiandao_flag}

2

提交WAF中隐藏的flag

palu{2025_waf}

3

提交Mysql中留下的flag

palu{Mysql_@2025}

4

提交攻击者的攻击IP

palu{192.168.20.107}

5

提交攻攻击者最早攻击时间flag格式为palu{xxxx-xx-xx-xx-xx-xx}

去看雷池 WAF 的面板。

palu{2025-05-05-00:04:40}

6

提交web服务泄露的关键文件名

palu{key.txt}

7

题解泄露的邮箱地址

palu{parloo@parloo.com}

8

提交立足点服务器ip地址

palu{192.168.20.108}

9

提交攻击者使用的提权的用户和密码

palu{parloo/parloo}

10

提交攻击者留下的的文件内容作为flag提交

palu{hi_2025_parloo_is_hack}

11

提交权限维持方法服务的名称

palu{rootset}

12

提交攻击者攻击恶意服务器连接地址作为flag提交

server 里面有一个 aa 程序。

palu{47.101.213.153}

13

找到系统中被劫持的程序程序名作为flag提交

按照修改时间排序,发现 id 很可疑。

palu{id}

14

找到系统中存在信息泄露的服务运行端口作为flag提交

palu{8081}

15

提交Parloo公司项目经理的身份证号作为flag提交

palu{310105198512123456}

18

提交攻击者留下的恶意账户名称md5后作为flag进行提交。 格式为palu{md5{xxxxx}}

进源机器开机可以选用户,发现一个 hack 用户。

palu{d78b6f30225cdc811adfe8d4e7c9fd34}

19

提交内部群中留下的flag并提交

palu{nbq_nbq_parloo}

20

请提交攻击者使用维护页面获取到的敏感内容作为flag进行提交

后门程序的源码在 gitea 里面,可以发现把日志放在了 command.log 里面。

palu{Server_Parloo_2025}

21

提交获取敏感内容IP的第一次执行命令时间作为flag进行提交。flag格式为palu{xxxx-xx-xx:xx:xx:xx}

palu{2025-05-04:15:30:38}

22

提交攻击者使用的恶意ip和端口flag格式为palu{xx.xx.xx.xx:xxxx}

palu{10.12.12.13:9999}

23

提交重要数据的名文内容作为flag提交

palu03 桌面有个重要的数据.txt,但是交了不对,被加密了。

之前 Gitea 里面还有一个 hack 用户,他的仓库里面有一个加密脚本,但只提供了一个加密函数:

def custom_encrypt(text, key):
    encrypted = []
    key_bytes = [ord(c) for c in key]

    for i, char in enumerate(text):
        shifted = ord(char) + (i % 5 + 1)

        xor_key = key_bytes[i % len(key_bytes)]
        xored = shifted ^ xor_key
        substituted = ((xored & 0x0F) << 4) | ((xored & 0xF0) >> 4)
        encrypted.append(f"{substituted:02x}")
    return "".join(encrypted)


自己传个参数进去,发现密文的格式和重要的数据.txt 的内容一致,尝试去解密。

这里不知道密钥,我们猜测解密出来的内容的头部是 palu{,由于明文和密钥是一位一位进行加密的,我们可以进行明文攻击,反推出密钥,最后手动试出来密钥是 MySecretKey。

def custom_decrypt(ciphertext, key):
    decrypted = []
    key_bytes = [ord(c) for c in key]
    for i in range(0, len(ciphertext), 2):
        hex_byte = ciphertext[i:i+2]
        substituted = int(hex_byte, 16)
        xored = ((substituted & 0x0F) << 4) | ((substituted & 0xF0) >> 4)

        xor_key = key_bytes[(i // 2) % len(key_bytes)]
        shifted = xored ^ xor_key

        original_char_code = shifted - ((i // 2) % 5 + 1)
        decrypted.append(chr(original_char_code))

    return ''.join(decrypted)

key = "MySecretKey"
ciphertext = "c3a1c3c13e326020c3919093e1260525045e"
plaintext = custom_decrypt(ciphertext, key)
print(plaintext)

palu{Password-000}

24

提交恶意维权软件的名称作为flag进行提交

palu{svhost}

25

提交恶意程序的外联地址

这个程序在 palu03 里面,叫 ipconfig.exe,python 写的。

palu{88.173.90.103}

26

提交攻击这使用的恶意dnslog域名作为flag进行提交

palu{np85qqde.requestrepo.com}

27

提交寻找反序列化漏洞的端口作为flag进行提交

palu{9999}

28

提交web服务泄露的密钥作为flag进行提交

palu{QZYysgMYhG6/CzIJlVpR2g==}

30

提交攻击者在server中留下的账户密码作为flag进行提交。flag格式为palu{username/password}

爆出来密码是 123456

palu{parloohack/123456}

32

提交攻击者留下的木马md5后作为flag进行提交

在 parloohack 的用户文件夹里面,有一个叫 aa 的文件。

palu{4123940b3911556d4bf79196cc008bf4}

33

提交攻击者留下的溯源信息作为flag进行提交

神人题。

先做的 46 题,想了想发现不对劲,还有一个保存的用户。

用户名就是 QQ 号,去看他的空间。

不过 flag 不在这里,还是在保存的密码里面。

palu{X5E1yklz1oAdyHBZ}

34

提交攻击者的githubID作为flag进行提交

palu{ParlooSEc}

35

提交攻击者在github下留下的的内容作为flag进行提交

palu{s5o3WkX33hptyJjk}

36

提交恶意用户的数量作为flag进行提交

看 palu01,在登录系统的时候有一堆用户,除了 Parloo 以外还有 99 个账户。

palu{99}

37

提交恶意用户的默认密码作为flag进行提交

palu{123456}

39

提交私人git仓库中留下的内容作为flag进行提交

连接 gitea 的数据库。

新建一个用户,然后覆盖 admin 的数据。

发现 base64 编码的 flag。

palu{FO65SruuTukdpBS5}

40

提交存在在mysql服务器中的恶意程序的MD5作为flag进行提交

palu{ba7c9fc1ff58b48d0df5c88d2fcc5cd1}

41

提交恶意程序中模拟c2通信的函数名称作为flag进行提交

palu{simulate_network_communication}

42

提交恶意程序创建隐藏文件的名称作为flag提交

palu{.malware_log.txt}

43

提交恶意程序中模拟权限提升的函数作为flag进行提交

palu{simulate_privilege_escalation}

44

提交被钓鱼上线的用户名作为flag进行提交

palu{Parloo-子怡}

45

提交恶意程序的所在路径作为flag进行提交

palu{C:\Users\Public\Nwt\cache\recv\Parloo-沉沉}

46

分析恶意程序的反连地址作为flag进行提交

palu{47.101.213.153}

47

提交恶意c2的服务器登录的账号密码作为flag进行提交。flag格式为palu{username/password}

在 palu02 里面,看谷歌浏览器保存的密码。

palu{admin/admin@qwer}

畸形的爱

WebServer
root/root
webserver/webserver

SQL服务器
sql/sql
 
Windows7 PC 1 
administrator/wmx666

Windows10 PC2 
administrator/zjl@123

1

提交攻击者使用的攻击ip地址1

flag格式为:palu{xxxx}

看 webserver 的 nginx 日志。

palu{192.168.31.240}

2

提交攻击者使用的攻击ip地址2.

flag格式为:palu{xxxx}

palu{192.168.31.11}

4

提交攻击者留下的flag1

格式为palu{xxx}

palu{pc3_zgsfqwerlkssaw}

5

提交攻击者留下的flag2

格式为:palu{xxxx}

palu{nizhidaowoyouduoainima}

6

提交攻击者留下的flag3

提交格式为:palu{xxxx}

palu{sqlaabbccsbwindows}

7

提交钓鱼文件的哈希32位大写

回收站里面,捡出来解压,有个简历.exe。

palu{2977CDAB8F3EE5EFDDAE61AD9F6CF203}

8

提交攻击者留下的webshell-1密码

格式为:palu{xxxx}

palu{hack}

10

提交攻击者留下的webshell密码2

格式为:palu{xxxx}

palu{00232}

11

去看一下历史命令,没找到.....

13

提交溯源后得到的flag

flag格式为:palu{xxx}

palu{loveyouibiejv}

Reverse

PositionalXOR

Flag 被一种基于位置的异或加密算法混淆。加密后数据保存在 encrypted.bin 中,每个字符的加密方式与其在字符串中的位置相关。你需要逆向加密逻辑,恢复原始 Flag。

PaluFlat

帕鲁不是死肥宅,帕鲁不胖!帕鲁头晕目眩绝对不是炫多了

附件是个 7z 压缩包,解压后拿到一个 1G 的 exe,010 查看发现末尾都是 0x00,删去后用 IDA 打开分析。

def reverse_shift(byte):
    for x in range(256):
        if ((16 * x) | (x >> 4)) & 0xFF == byte:
            return x
    raise ValueError(f"No match found for byte: {byte}")

def decrypt(data_hex: str) -> str:
    data = bytes.fromhex(data_hex)
    str_key = b"palu"
    alt_key = b"flat"
    result = []

    for i, b in enumerate(data):
        b = ~b & 0xFF
        b = (b + 85) & 0xFF
        b = reverse_shift(b)
        key = alt_key if (i % 2) else str_key
        k = key[i % len(key)]
        b ^= k
        result.append(b)

    return bytes(result).decode('utf-8', errors='ignore')

# 示例用法
if __name__ == "__main__":
    hex_input = input("Enter hex-encoded encrypted data: ").strip()
    print("Decrypted output:", decrypt(hex_input))

PaluGOGOGO

帕鲁该走了,要去当苦命打工人了,GOGOGO!

有个反调试,jnz 改成 jz 绕过。

打个断点,动调把 value 取出来。

main_complexEncrypt 函数其实就是一个类似凯撒的函数,直接写脚本解密。

def decrypt(cipher_bytes: bytes, key: int) -> str:
    cipher_text = cipher_bytes
    plain_chars = []
    for i, ch in enumerate(cipher_text):
        orig = ch - key - (i % 5)
        orig &= 0x10FFFF
        plain_chars.append(chr(orig))
    return ''.join(plain_chars)
cipher_hex = [
    0xbf, 0xb1, 0xbd, 0xc7, 0xce, 0x96, 0x80, 0x98,
    0x82, 0x9a, 0x7f, 0xaf, 0xc1, 0xb3, 0xbf, 0xc4, 0xcd
]
cipher_bytes = bytes(cipher_hex)
key = 0x4F
plain = decrypt(cipher_bytes, key)
print("解密结果:", plain)

palu{G0G0G0_palu}

CatchPalu

主人给了帕鲁好多花花,帕鲁好开心呀!可是主人骗帕鲁,还把帕鲁抓了起来...

先去花指令,就是一堆 jz 和 jnz 互补跳转这种结构,把下面 jmp 的第一个字节 NOP 掉即可。

然后 UCP,把所有的处理好即可,接下来逆向程序。

直接下个断点,输入一个假 flag,可以进到解密的地方,直接取出来最终的真 flag。

palu{G00d_P1au_Kn0w_H00K}

帕鲁迷宫

贪玩的帕鲁来走迷宫啦,主人要求我以最短路径完成全部出口!太难了...

flag格式:palu{md5(最短路径步骤)}

Eg:awsd是最短路径 则计算其MD5值得到palu{2f724716d49d79e1fd0d71d57d451de0}

最短路径使用BFS算法,flag唯一,核对最后四步为ssds

懒得写脚本了,直接手动走。

无语了......有多解,多试几次。

最后走出来这条路径是对的:

ssssddssddwwddwwddddddddssssssssddssaaaaaaaaaawwddddwwddwwaaaassaaaaaaaassddssssasadsdssssddssddssaassddssaaaaasadwdddddddwwddssddwwwwddddddwwaaaaaaaaaawwwwddssddwwddssddwwwwaawwddddwwwwddddddddddwwwwaawwddwwaawwdddaaassddssaassddssssssssaawwaaaaaassssssssssssssssaaaasadwddddddddddwwddssds

palu{990fd7773f450f1f13bf08a367fe95ea}

PaluArray

帕鲁有自己的数组,帕鲁有自己的字典,帕鲁就是帕鲁!帕鲁不要996!

魔改 UPX,改回去。

脱壳后直接问 GPT,有一个表是 Palu_996!?,要求输入一个字符串,对应的索引是 1145141919810。

flag 的内容就是最后输入的字符串的 md5,当然如果字符串输对的话,也会弹出来一个带有 flag 的提示框。

手动构造,最后的字符串是 aa_9a_a?a?!aP。

palu{1b501325fc96d5a845cbdd2ba4f01cd7}
✳

感谢阅读,下一个线索见。

一方小小的桌面,一些慢慢积累的想法。
中

搜索文章

输入关键词,寻找一段记录。