CRYPTO
Vigenere
题目信息
key CYLAB
cipher: rgnoDVD{O0NU_WQ3_G1G3O3T3_A1AH3S_cc82272b}
题目给了密文和密钥,用随波逐流打开,解密,发现是维吉尼亚加密

flag:picoCTF{D0NT_US3_V1G3N3R3_C1PH3R_ae82272q}
basic-mod1
题目信息
描述: 我们发现这个奇怪的消息在服务器上传递,我们认为我们有一个有效的 decrpytion 方案。取每个数字 mod 37 并将其映射到以下字符集:0-25 是字母表(大写),26-35 是十进制数字,36 是下划线。以 picoCTF 标志格式包装解密的消息(即 picoCTF{decrypted_message})
数字:350 63 353 198 114 369 346 184 202 322 94 235 114 110 185 188 225 212 366 374 261 213
按照题目信息对取模厚的数字根据其ASCLL码修改,并转化为字符输出
1 | def simplify_numbers(numbers): |
flag:picoCTF{R0UND_N_R0UND_ADD17EC2}
substitution0
题目信息
描述:
一条消息进来了,但似乎全都乱七八糟。幸运的是,它似乎一开始就有钥匙。你能破解这个替换密码吗?
密文:
OHNFUMWSVZLXEGCPTAJDYIRKQB
Suauypcg Xuwaogf oacju, rvds o waoiu ogf jdoduxq ova, ogf hacywsd eu dsu huudxumace o wxojj noju vg rsvns vd roj ugnxcjuf. Vd roj o huoydvmyx jnoaohouyj, ogf, oddsod dveu, yglgcrg dc godyaoxvjdj—cm ncyaju o wauod pavbu vg o jnvugdvmvn pcvgdcm ivur. Dsuau ruau drc acygf hxonl jpcdj guoa cgu ukdauevdq cm dsu honl, ogf oxcgw cgu guoa dsu cdsua. Dsu jnoxuj ruau uknuufvgwxq soaf ogf wxcjjq, rvds oxx dsuoppuoaognu cm hyagvjsuf wcxf. Dsu ruvwsd cm dsu vgjund roj iuaq aueoalohxu, ogf,dolvgw oxx dsvgwj vgdc ncgjvfuaodvcg, V ncyxf soafxq hxoeu Zypvdua mca svj cpvgvcgaujpundvgw vd.
Dsu mxow vj: pvncNDM{5YH5717Y710G_3I0XY710G_03055505}
解密
猜测密钥凯撒密码加密,把第一句作为密钥
flag; picoCTF{5UB5717U710N_3V0LU710N_03055505}
RE
Safe Opener
题目信息
描述:你能打开这个保险箱吗?我忘记了保险箱的钥匙,但这个程序应该可以帮助我找回丢失的钥匙。你能帮我打开保险箱吗?将您恢复的密码放入 picoCTF 标志格式,例如:picoCTF{password}
代码
1 | import java.io.*; |
正如代码中的注释一样,用户输入密码,进行Base64编码,调用函数检验编码厚的数值是否符合指定字符,所以密码就是指定字符Base64解码

flag:picoCTF{pl3as3_l3t_m3_1nt0_th3_saf3}
GDB test
题目信息
你能得到这面旗帜吗?
以下是试用说明:
1 | $ chmod +x gdbme |
解密
按照给的命令进行操作

flag: picoCTF{d3bugg3r_dr1v3_7776d758}
fresh-java
题目信息
你能得到这面旗帜吗?对这个 Java 程序进行逆向工程
用jad-gui打开这个文件,发现该密文已将被定义好了

flag:picoCTF{700l1ng_r3qu1r3d_738cac89}
file-run1
题目信息
已为您提供一个程序,如果您尝试在命令行上运行它会发生什么?
解密
首先要为程序赋权限 chmod +x ru
运行该程序并且执行命令./run

flag:picoCTF{U51N6_Y0Ur_F1r57_F113_9bc52b6b}
file-run2
题目信息
另一个程序,但这一次,它似乎需要一些输入。如果您尝试在命令行上运行它并输入 “Hello!”会发生什么情况?
解密
首先要为程序赋权限 chmod +x ru
运行该程序并且执行命令./run Hello!

flag:picoCTF{F1r57_4rgum3n7_f65ed63e}
Bbbbloat
题目信息
你能得到这面旗帜吗?对这个二进制文件进行逆向工程。
解密

分析得到,最喜欢的是数字应该为549255
为文件赋权限 chmod +x Bbbbloat
运行程序./Bbbbloat

flag:picoCTF{cu7_7h3_bl047_44f74a60}
unpackme
题目描述
你能得到这面旗帜吗?对这个二进制文件进行逆向工程。
解密
文件以upx结尾,尝试upx脱壳

之后拖入ida中

发现最喜爱的数字是754635

flag: picoCTF{up><_m3_f7w_e510a27f}
PWN
RPS
题目描述
这是一个对你玩石头剪刀布的程序。我听说如果你连续赢了 5 次,就会发生好事。可以下载带有标记已编辑的程序源代码 这里 。
解密
主函数
1 |
|
判断胜负
1 | //判断胜负 |
所以我们要经过5次循环,且每次循环都要向程序输出rock/paper/scissors的结合
脚本
1 | from pwn import * |
basic-file-exploit 漏洞
题目信息
提供的程序允许您写入文件并从中读取您写入的内容。试着玩弄它,看看你是否能打破它!可以下载带有标记已编辑的程序源代码 这里
解密
有分析可得tgetinput用来校验空输入等基本校验工作,data_write数据输入,data_read数据读取,且其中包含flag的输出
由main可以知道。首先选择要进行的模式,且第一次必须先存入,否则无法调用data_read函数
1 | static void data_read() { |
所以重点就是((entry_number = strtol(entry, NULL, 10)) == 0)的输出结果为0


flag:picoCTF{M4K3_5UR3_70_CH3CK_Y0UR_1NPU75_68466E2F}
buffer overflow 0
题目信息
让我们从简单的开始,你能溢出正确的缓冲区吗?该程序可在此处获得。您可以查看源代码 这里 。
解密
主函数

signal(11, sigsegv_handler)当程序发生段错误(即收到信号 11,也就是 SIGSEGV)时,不执行默认操作(崩溃),而是跳转到你定义的 sigsegv_handler 函数进行处理。
- 当你的程序试图访问非法内存地址(如未分配的内存、只读内存、已释放的内存等)时,操作系统会发送这个信号给程序。
- 默认情况下,收到
SIGSEGV会导致程序崩溃(段错误)。
示例触发原因:
- 解引用空指针:
*NULL - 写入常量字符串:
strcpy("hello", "world") - 越界访问栈数组、堆数组
- 使用未初始化的指针
这个对flag.txt文件的操作 相当于bin/sh后门函数
它包含了读取flag,并把flag输出在终端
而在 Linux/Unix 系统中,/bin/sh 是一个指向系统默认 shell(如 Bash)的可执行文件
sigsegv_handler函数

该函数会输出flag
所以只需要实现就可以输出flag

脚本
1 | from pwn import * |
buffer overflow 1
题目描述
控制退货地址现在我们开始烹饪了!您可以溢出缓冲区并返回到程序中的 flag 函数。你可以在这里查看源代码。
解密


var_4 是什么?
- 在汇编或反编译工具(如 IDA Pro)中,
var_4是一个由工具自动生成的名称,用于表示一个位于栈上的局部变量。它通常是原始C代码中没有明确命名的变量,或者是编译器为了优化或内部使用而创建的栈空间。 - 从图片中可以看到,
var_4位于s数组的下方(在栈帧中,局部变量通常从EBP往下分配)。
var_4 有多大?
- 图片中
var_4对应的汇编指令是dd ?。 dd在汇编中是 “Define Doubleword” 的缩写。在 32 位系统中,一个 Doubleword 是 4 字节。- 因此,
var_4的大小是 4 字节。
所以垃圾字节要填充36+4+4=44个字节

win是后门函数
填充它的地址
脚本
1 | from pwn import * |
buffer overflow 2
题目描述
控制返回地址和参数这一次,您需要控制您返回的函数的参数!您可以从此程序中获取标志吗?你可以在这里查看源代码
解密

s距离返回地址是6C+4个字节

要传参,32位是参数从右到左依次压入栈中
win的地址

gdb动调查看
python wp.py

执行的函数列表
脚本
1 | from pwn import * |
x-sixty-what
题目描述
溢出 x64 代码在此之前的大多数问题是 32 位 x86。现在我们考虑 64 位 x86,它 只是有点不同!使缓冲区溢出,并将返回地址更改为 flag 函数。 下载源代码 。
解密
这一题我错了很久,最后发现考了堆栈平衡:crying_cat_face:
但是也学到了一些gdb调试获取信息的方法



gdb调试获得相关信息
readelf -s vuln显示所有函数的信息(在gdb调试之前)

p flag:显示函数flag的信息

(gdb)disassemble vuln:找要填充的字节数()
64位时是0x40+8
32位时是0x40+4

堆栈平衡
同一个程序的每一个 call 指令执行时,rsp(栈指针)的绝对值不一定相同,但其对齐状态是保持一致的。
当 vuln 函数通过 ret 指令跳转到 flag 函数时,flag 函数的入口处 rsp (栈指针) 可能满足 rsp % 16 == 0 (即 16 字节对齐)。但是,flag 函数的序言 (prologue) 通常会 push rbp (将 rbp 压栈),这会使 rsp 减去 8 字节,导致 rsp % 16 == 8 (8 字节不对齐)。
问题就出在这里:在执行任何 call 指令之前,rsp 必须是 16 字节对齐的。
所以该函数到flag之前要先到ret小工具
使用 ROPgadget (推荐): 在终端中运行(确保你的 vuln 可执行文件在当前目录):
Bash
1 | ROPgadget --binary ./vuln --only "ret" |
它会列出所有独立的 ret 指令地址。通常你可以选择其中一个地址最小的,或者你觉得“独立”的地址(例如,不在任何重要函数的中间)。0x0040101a 是一个非常常见的备选。
在 GDB/pwndbg 中手动查找: 启动 GDB 调试 ./vuln,然后使用 search-pattern 命令查找 ret 指令的机器码 \xc3:
Code snippet
1 | search-pattern '\xc3' |
你也可以使用 disassemble <section_start_address>, <section_end_address> 来反汇编整个代码段,然后手动查找 ret。
直接看出堆栈不平衡
该函数是flag被调用函数输出flag,所以在flag函数中的第一个call的地方下断点
python 你的脚本文件名.py:运行脚本
info registers rsp:查看rsp的寄存器信息

看最后两位
0x48可以整除16,所以现在堆栈平衡了
脚本
1 | from pwn import * |