Open Table of contents
It’s a thrilling intellectual puzzle, unlocking the secrets of a program from the inside out.
Description 你别吓我,万一我 IQ 没及格怎么办?那不是炸了??
玩点简单的 (probably)?智力游戏吧~泄漏/篡改数据神技,小子,是不是应该学透彻?
Use a format string exploit to reveal a string stored on the stack.
第一题,核心伪代码如上,会随机生成一串字符串到栈上某个位置,绿色部分会判断输入是否和栈上的随机字符串相符,成立则输出 flag。
红色部分直接把输入作为 printf()
的 const char *format
参数,是一个很明显的格式化字符串漏洞。
再简单计算一下随机字符串在栈上第几位,加上 6 (RDI
、RSI
、RDX
、RCX
、R8
、R9
) 就是我们需要泄漏的参数位了。
Flag: pwn.college{UGd_h1EnEGQDMhB1PSrD81fSSXs.dZTM0MDL5cTNxgzW}
Use a format string exploit to reveal a string stored on the stack.
参见 Level 1.0。
Flag: pwn.college{UQu4aFVleX5KV74QVvgMLBddqc-.ddTM0MDL5cTNxgzW}
Use a format string exploit to reveal a string stored on the stack.
这次我剑走偏锋,不用 %s
了,而是尝试用更麻烦一点的 %llx
输出栈上保存的随机字符串值,转换为 ASCII。因为小端序,所以还需要再反转一下。
Flag: pwn.college{QZG8MJMHwVhFNzjDx4guy6MBfEL.dhTM0MDL5cTNxgzW}
Use a format string exploit to reveal a string stored on the stack.
参见 Level 2.0。
Flag: pwn.college{MjTMloC44qXLBonimJ5i3Zq3ux-.dlTM0MDL5cTNxgzW}
Use a format string exploit to read the flag directly from the .bss section.
这题直接把 flag 读到 .bss
段了,所以思路很简单,就是把 .bss
的地址写到栈上某个位置,然后通过 %s
解引用输出这个地址的值。
注意一定是先输入 fmtstr 再接地址,这个应该不需要解释吧。
遇事别慌多调试,debugger 是你的 gf,你还不懂吗。
Flag: pwn.college{coYB13XxKYo3asb6os4GxIefmpC.dBjM0MDL5cTNxgzW}
Use a format string exploit to read the flag directly from the .bss section.
参见 Level 3.0。
睡了一天为什么还是好困,不写了,睡觉觉,在想明天或者以后要不要写一个技巧向专题?明天得学学 ret2csu
和 SROP
。
Flag: pwn.college{UtDc1WIH6qas-RrhigjZpPLWMUP.dFjM0MDL5cTNxgzW}
Use a format string exploit to set a global variable.
简单,通过逆向我们知道,check_win()
输出 flag 的条件是 .bss
段上的 qword_404160
变量值为 0xC2
,为了满足这一条件,我们直接用 %n
篡改即可。
Flag: pwn.college{MrJaEVG2FM1QGKYUbL8GjOyBkhg.dJjM0MDL5cTNxgzW}
Use a format string exploit to set a global variable.
参见 Level 4.0。
Flag: pwn.college{gYbZ_KMoDIuA2cpDPTK3F8hxiEo.dNjM0MDL5cTNxgzW}
Use a format string exploit to set a larger global variable.
WHAT CAN I SAY…WHAT U WANT ME TO SAY…
对于这种巨大的数值的策略是我们可以分组写,按 2 字节一组应该是不错的选项。第一组写起来应该是没有任何坑的,注意栈对齐加减字节即可;第二组开始则应该减去前一组写入的字节数再 % 0x10000
,这是为了回环到 [0x00, 0xFF]
这个区间,这样就确保了 %n
写入的是我们期望的值。
评价一下我的码风好不好看 1/31/2025。
Flag: pwn.college{wRZzRCQlIP6gytdVI6FYHhTLMom.dRjM0MDL5cTNxgzW}
Use a format string exploit to set a larger global variable.
参见 Level 5.0。
Flag: pwn.college{sjfLqAt2jCG0OYV91dJi9052Hf4.dVjM0MDL5cTNxgzW}
Use a format string exploit to copy a value and overwrite a global variable.
这题就是读了一个三字节的随机值到栈上,给 flag 的条件是我们 .bss
段中的 qword_404158
变量值必须等于这个随机值。思路是用格式化字符串中的 * (specifies a dynamic padding size)
来 ‘copy memory’. 举个栗子:%*10$c
会把第十个参数的值用作 padding size,输出大小为 padding size 的内容。所以我们只要把这个 padding size 通过 %n
写入就相当于实现了 ‘copy memory’ 了。
这个方法这对于比较小的值还好,太大了就不太友善了,cuz bunch of spaces.
Flag: pwn.college{ExgmxPb8JckvvOZvTLw9kufKyFP.dZjM0MDL5cTNxgzW}
Use a format string exploit to copy a value and overwrite a global variable.
参见 Level 6.0。
Flag: pwn.college{o3IDJsXjzJ3CBMBZz_66rdU2oQR.ddjM0MDL5cTNxgzW}
Use a format string exploit to overwrite a got entry.
并没有什么特别的地方,只要 read
返回 > 0
,并且输入中不包含 END
程序就可以无限次触发格式化字符串漏洞。而我们的目标是执行下面这个 win
函数。
检查保护措施,发现没开 PIE,看到这个就开心,因为之后利用起来会比较轻松……有 Canary,但因为格式化字符串漏洞的存在,我们可以直接忽略掉它。重点在于这个程序是 Partial RELRO 的,这个 RELRO 级别的 GOT 表是可写的,注意到我们触发格式化字符串漏洞之后程序返回到 main
还会调用一次 puts
函数(对于 7.1 是这样的,但对于 7.0 这个情况,事实上我们会在循环体内再次出发 puts
,所以 7.0 可以不输入 END
),那我们只要通过格式化字符串漏洞把 puts
的 GOT 表内容篡改为 win
的地址就好了,篡改后再次调用 puts
就会执行 win
。
需要注意的点是由于 win
内部还有一个 puts
,所以我们要跳过它。
所以这时候没 PIE 的爽就体现出来了,不需要想办法泄漏 GOT 表,已经被看光光了,指哪打哪 LOL
19:27,为什么我想睡觉?一定是被自己出的烂题折腾惨了……打完这题刷电影去~
20:49,啊啊啊啊啊写 0 真麻烦,不干了!
Flag: pwn.college{Ux3-i0zQW7ZkTY5X_RLl2eIH1Fb.dhjM0MDL5cTNxgzW}
Use a format string exploit to overwrite a got entry.
参见 Level 7.0。
Flag: pwn.college{s0yYpAm36BLU2Mp5PhbvBmPuc-3.dljM0MDL5cTNxgzW}