0x01 warmup_csaw_2016
1 | from pwn import * |
0x02 RIP覆盖一下
1 | from pwn import * |
0x03 babyfengshui_33c3_2016
1 | from pwn import * |
0x04 babyheap_0ctf_2017
1 | from pwn import * |
0x05 get_started_3dsctf_2016
1 | from pwn import * |
0x06 not_the_same_3dsctf_2016
1 | from pwn import * |
0x07 bugbug_codegate_2016
1 | from pwn import * |
另外附上随机数生成器
1 | #include<stdio.h> |
0x08 ez_pz_hackover_2016
1 | from pwn import * |
0x09 tiny_backdoor_v1_hackover_2016
1 | from pwn import * |
0x10 bbys_tu_2016
1 | from pwn import * |
0x11 oneshot_tjctf_2016
1 | from pwn import * |
0x12 pwn1_sctf_2016
1 | from pwn import * |
0x13 pwn2_sctf_2016
1 | from pwn import * |
0x14 ciscn_2019_c_1
1 | from pwn import * |
0x15 ciscn_2019_n_1
1 | from pwn import * |
0x16 ciscn_2019_n_8
1 | from pwn import * |
0x17 ciscn_2019_sw_7
1 | from pwn import * |
0x18 espcially_tu_2016
解法一:
1 | from pwn import * |
解法二:
1 | from roputils import * |
0x19 ciscn_2019_en_2
1 | #!/usr/bin/python2.7 |
0x20 ciscn_s_4
1 | from pwn import * |
0x21 ciscn_2019_n_3
1、利用unsorted bin attack知道libc地址
2、存在UAF漏洞,然后利用fastbin attack,实现堆块重叠,且通过利用unsorted bin在fd、bk不够放置时,一次性将剩余堆块全部申请回来的特性,使得可以填充进system地址和sh字符串
1 | #!/usr/bin/python2.7 |
0x22 ciscn_s_8
导入ida后,发现是一个异或算法,然后strcpy处存在栈溢出,但是会对输入的文本进行异或0x66的处理,我们可以预先先对payload异或0x66,然后在程序对它再次异或时就会复原回有攻击性的payload
另外这道题,我为了图方便,且程序是静态编译,ROPgadget往往是可以生成ROPchain的,可以考虑将add rax,1换成add rax,3,缩短ROPchain,达成攻击。注意不换成add rax,3会出现ROPchain被截断的情况
1 | #!/usr/bin/python2.7 |
0x23 ciscn_s_3
gadget处可以赋值rax为15,恰好为SYS_SigReturnFrame
那么思路如下:
1、先leak stack地址,然后顺带的传入/bin/sh\x00字符串,通过leak stack来定位binsh的位置,再跳回SYS_read处
2、赋值rax为15,跳到syscall上,成功popal sigframe,此时sigframe的数据由我们输入的数据控制,凑成可以拿shell的形式,即可拿到shell
1 | #!/usr/bin/python2.7 |
0x24 ciscn_2019_nw_6
程序没有任何保护,考虑shellcode
利用栈内两个栈空间的指针来改写ret地址,然后顺便最后写入shellcode到bss,然后ret跳过去
1 | from pwn import * |
0x25 judgement_mna_2016
导入IDA发现存在典型的格式化溢出漏洞,且栈内分布指向flag的指针,可以通过$xx%s来读取文本
1 | #!/usr/bin/python2.7 |
0x26 ciscn_nw_4
1、经过ida分析存在double free,且show没有check,所以可以leak heap_base和libc
2、通过fastbin attack修改unsorted bin’s bk,在__free_hook处伪造fake_chunk,然后再用double free fastbin attack修改__free_hook的值为system,然后释放content为/bin/sh\x00的chunk即可
最终因为ubuntu16.04的环境问题拿不到flag,经过分析发现,是因为system函数里存在sub rsp,0xNNN
,其中NNN很大,导致后面有一个cmp指令读取到了不可读区段导致程序崩溃
1 | #!/usr/bin/python2.7 |
0x27 checker_seccon_2016
首先这题开启了canary,且代码无法leak canary,导致无法溢出
考虑开启了canary,且存在无限输入,但是输入中遇到\x00会截断,所以考虑使用smash来leak任意地址数据
由于遇到\x00截断或遇到换行截断并替换为\x00,我们可以考虑先输入\xc0\x10\x60\x11\x11\x11,然后再输入\xc0\x10\x60\x11\x11,直到\xc0\x10\x60
如何找到argv[0],只需调试器附加运行的程序,然后找到./文件名
的字符串即可,比如我这里是./checker_seccon_2016
,然后将flag的地址覆盖进去即可
1 | from pwn import * |
0x28 ciscn_2019_ne_5
典型的ROP题,ret2text
1 | #!/usr/bin/python2.7 |
0x29 ciscn_2019_es_2
1 | from pwn import * |
0x30 ciscn_2019_final_3
这题总体不难,由于tcache attack的利用很方便,所以这题只要leak libc就可以轻而易举拿到shell
简单的思路:先合并堆块,合并后的堆块大于tcache的范围,然后free掉即可出现libc,接下来就是堆块重叠malloc一个堆块到libc空间,通过gift得到libc地址,接着tcache attack修改__free_hook拿到shell
1 | #!/usr/bin/python2.7 |
0x31 ciscn_2019_en_3
1 | #!/usr/bin/python2.7 |
0x32 ciscn_2019_c_5
1 | #!/usr/bin/python2.7 |
0x33 ciscn_2019_es_4
可以考虑用unlink来获得对chunk_list控制
将unlink攻击的堆块放到第32个位置,使得edit时可以改变key1和key2的值,进行解锁功能。
如果完成以上两行的攻击后,接下来只需要got leak,然后libc leak,然后写__free_hook为system即可
1 | #!/usr/bin/python2.7 |
0x34 ciscn_2019_es_1
由于题目要求是2.29,但是环境是2.23,所以解法会有较大差别,但是按环境为主
由于只能申请12个堆块,而且一次add会申请两个堆块,对我们的堆块利用会造成干扰,所以我们需要在最后一次add的时候,同时完成unsorted bin attack和fastbin attack的组合式攻击
1、leak libc和heap_base这个攻击手法就不用多说了
2、先两次double free和fastbin attack把被攻击堆块放入bins中,然后修改unsorted bin的bk,使得__free_hook的低位地址写入0x7f开头的大数,然后在最后一次add,通过malloc(0x18)完成unsorted bin attack,写入大数,然后同时malloc(0x68)fastbin attack,覆盖__free_hook为system
然后free一个内容为/bin/sh\x00的堆块即可,推荐使用double free之后,第二次add的堆块的内容设置为/bin/sh\x00
1 | #!/usr/bin/python2.7 |
0x35 ciscn_2019_sw_6
简单看一下程序的功能,发现是归并排序,然后会输出逆序数
漏洞在输入数组的时候,可以无限输入,所以可以考虑利用ROPgadget构造ROP链,但是开启了canary,需要leak canary
考虑到canary末尾两位为0,所以只需要爆破6位即可,想了一下程序只能输出逆序数,所以可以利用逆序数的特点进行攻击
1、输入一串有序数列,然后在canary的上方输入0,即可开始排序,由于我们输入的是一个有序数列,然后末尾为0和canary,进行排序之后输出的逆序数,可以让我们定位canary的区间
2、有数列一开始根据0x10000000-0xFFFFFFFF,由于有299个数量(因为301是canary,300是0用于停止输入),所以一个区间大小为(0xFFFFFFFF - 0x10000000) / 299,由于canary十分大,所以误差可以忽略不计,一次定位可以缩小三个数量级
3、一次定位可以确定第一位的大小,二次定位可以确定前4位的大小,第三次定位可以唯一确定一个canary或两个canary,多跑几次就好了
4、跑出canary之后,利用ROPgadget生成ROP链,然后覆盖eip即可拿到shell
但是buuoj的交互好像有一定的限制,导致我交互到60多次就EOF了,而拿到shell需要交互1200+,且50%的概率。buuoj两分钟重置一次环境,我觉得2分钟好像跑不完1200+次,哈哈哈,没事本地拿到shell就好了,说明思路没有错
这里介绍一个jly大师傅的解法,scanf("%ud"),如果输入带符号的数,则不会改变欲写入地址的数据,就可以越过canary直接写ropchain,这不得不膜一下jly师傅
1 | from pwn import * |
0x36 ping_gnop_hackover_2016
我将这题称为ROPgadget --ropchain人工版
题目中存在过滤字符,所以要一个一个尝试gadget,然后再利用可用的gadget构造ROP链,最后通过int 0x80
拿到shell
1 | #!/usr/bin/python2.7 |
0x37 warmup
这题要配好各个寄存器参数,然后利用read将读入字符数写入eax,从而将函数序列号变成execve的序列号,然后再确保寄存器内的指针都是正确的,即可拿到shell
1 | #!/usr/bin/python2.7 |
0x38 fixedpoint_plaid_2016
这题就是典型的shellcode,找数字吧小伙子~~
1 | #!/usr/bin/python2.7 |
0x39 ciscn_2019_final_2
典型的UAF和tcache attack,但是dup2函数需要我们将stdin的fileno替换为666,然后再输入一次数据(即功能4退出里的scanf),就可以输出flag
1 | #!/usr/bin/python2.7 |
0x40 强网杯2019 拟态 STKOF
1 | #!/usr/bin/python2.7 |
0x41 ciscn_2019_ne_3
1 | #!/usr/bin/python2.7 |
0x42 bcloud_bctf_2016
典型的house of force
1 | #!/usr/bin/python2.7 |
0x43 web_of_sci_volga_2016
leak canary,然后普通的ROP
1 | #!/usr/bin/python2.7 |
0x44 ciscn_2019_sw_1
printf花式溢出漏洞,无限循环
1 | #!/usr/bin/python2.7 |
0x45 [中关村2019]one_string
orw
1 | #!/usr/bin/python2.7 |
0x46 bjdctf_2020_babyrop
1 | # -*- coding: utf-8 -*- |
0x47 bamboobox
1 | # -*- coding: utf-8 -*- |
0x48 poke_naxtos_sthack_2016
1 | #!/usr/bin/python2.7 |
0x49 ciscn_2019_final_4
和ciscn_sw_10类似
1 | #!/usr/bin/python2.7 |
0x50 ciscn_2019_s_6
1 | #!/usr/bin/python2.7 |
0x51 ciscn_nw_4
1 | #!/usr/bin/python2.7 |
0x52 [第五空间2019 决赛]PWN5
1 | #!/usr/bin/python2.7 |
0x53 [ZJCTF 2019]EasyHeap
1 | #!/usr/bin/python2.7 |
0x54 [ZJCTF 2019]login
1 | #!/usr/bin/python2.7 |
0x55 ciscn_2019_n_5
1 | #!/usr/bin/python2.7 |
0x56 ciscn_2019_s_1
1 | #!/usr/bin/python2.7 |
0x57 fl0ppy_codegate_2016
经过黑盒测试,发现strcpy的漏洞,然后多次黑盒测试发现leak了libc和stack_addr,然后通过strcpy实现栈溢出,然后在main函数执行完毕时,进行栈迁移,迁移到rop处,从而执行system("/bin/sh\x00")
1 | #!/usr/bin/python2.7 |
0x58 nsctf_online_2019_pwn1
覆盖__malloc_hook为one_gadget
1 | from pwn import * |
0x59 nsctf_online_2019_pwn2
1 | from pwn import * |
0x60 ciscn_2019_sw_5
Ubuntu 18.04
1 | #!/usr/bin/python2.7 |
0x61 ciscn_nw_2
Ubuntu 18.04
1 | #!/usr/bin/python2.7 |
0x62 ciscn_2019_en_1
标准的arm pwn rop,很适合新手
1 | #!/usr/bin/python2.7 |
0x63 ciscn_2019_n_2
Ubuntu 18.04
1 | from pwn import * |
0x64 TWCTF_online_2019_asterisk_alloc
1 | #!/usr/bin/python2.7 |
0x65 other_babystack
1 | # -*- coding: utf-8 -*- |
0x66 ciscn_2019_es_5
0堆块和realloc函数之间的冲突导致double free
1 | #!/usr/bin/python2.7 |
0x67 roarctf_2019_realloc_magic
realloc可以实现堆重叠,然后覆盖fd低位为tcache头,然后控制到tcache头,造出libc地址,然后覆盖低位地址为stdout,然后覆盖数据实现libc leak,然后执行magic清空指针,然后申请堆块回到tcache头,通过tcache attack控制__free_hook - 8的地址数据为/bin/sh\x00,然后向下覆盖__free_hook地址为system,然后直接free就可以拿到shell。
非预期:另外可以使用超大堆块漏洞来实现控制tcache头,但是方法较上面方法复杂,且使用存在使用条件(目标靶机必须要有足够大的内存,如果靶机内存很小,还有另一种非预期解,此方法针对可以申请大内存块的靶机),所以我一开始使用非预期解打BUUOJ平台的时候,发现打不通,但是本地却可以打通,应该也是内存申请过大的原因导致的。
Ubuntu18
常规解
1 | #!/usr/bin/python2.7 |
Ubuntu18
非常规解
1 | #!/usr/bin/python2.7 |
0x68 roarctf_2019_easy_pwn
堆块重叠即可
1 | #!/usr/bin/python2.7 |
0x69 [极客大挑战 2019]Not Bad
1 | #!/usr/bin/python2.7 |
0x70 axb_2019_fmt32
1 | ##coding=utf8 |
0x71 axb_2019_heap
1 | #!/usr/bin/python2.7 |
0x72 axb_2019_fmt64
1 | from pwn import * |
0x73 bytectf_2019_vip
1 | #!/usr/bin/python2.7 |
0x74 SWPUCTF_2019_login
1 | #!/usr/bin/python2.7 |
0x75 SWPUCTF_2019_p1KkHeap
1 | #!/usr/bin/python2.7 |
0x76 axb_2019_final_blindHeap
1 | from pwn import * |
0x77 axb_2019_brop64
1 | #!/usr/bin/python2.7 |
0x78 jarvisoj_tell_me_something
1 | from pwn import * |
0x79 jarvisoj_level3_x64
1 | #!/usr/bin/env python |
0x80 jarvisoj_level0
1 | from pwn import * |
0x81 jarvisoj_level1
1 | #!/usr/bin/python2.7 |
0x82 jarvisoj_level2
1 | from pwn import * |
0x83 jarvisoj_level2(x64)
1 | from pwn import * |
0x84 jarvisoj_leve3
1 | from pwn import * |
0x85 jarvisoj_level4
1 | #!/usr/bin/python2.7 |
0x86 jarvisoj_level5
1 | from pwn import * |
0x87 jarvisoj_level6
1 | from pwn import * |
0x88 jarvisoj_level6(x64)
1 | from pwn import * |
0x89 jarvisoj_test_your_memory
1 | from pwn import * |
0x90 jarvisoj_itemboard
1 | from pwn import * |
0x91 jarvisoj_fm
1 | from pwn import * |
0x92 pwnable_orw
1 | #!/usr/bin/python2.7 |
0x93 jarvisoj_typo
1 | from pwn import * |
0x94 others_shellcode
1 | 连接就出flag 有点水 |
0x95 huxiangbei_2019_hacknote
1 | #!/usr/bin/python2.7 |
0x96 shanghai2019_boringheap
该exp是真实比赛的exp,ubuntu16,Buuoj为Ubuntu18
1 | #!/usr/bin/python2.7 |
0x97 shanghai2019_login
该exp是真实比赛的exp,ubuntu16,Buuoj为Ubuntu18
爆破libc
1 | #!/usr/bin/python2.7 |
0x98 xdctf2015_pwn200
1 | from pwn import * |
0x99 bctf2016_bcloud
1 | #!/usr/bin/python2.7 |
0x100 cmcc_pwn2
1 | from pwn import * |
感想:
2019年底了,我还是单身(゚Д゚≡゚д゚)!?,一天天看着0202年的到来~~(划重点)
啦啦啦 完结撒花 今年的任务算是完成了~( ̄▽ ̄~)
这100个EXP算是对得起我今年努力和学习,同时巩固了自己的知识(`・ω・´)
祝BUUOJ越来越好!( ̄▽ ̄) 赵总越来越rich
南梦小剧场:
神秘人:BUUOJ刷题之旅续作还有吗,还有木有100个EXP吗?←_←
南梦:之后的刷题之旅不再公开了,但是当前这篇刷题之旅会一直公开,至于之后有木有100个EXP,那就看我明年的学习成果了(你竟然想让我进一步秃头??? (´;ω;`) 100个EXP,瞧瞧这是人说的话吗?)
神秘人:你天天喊着找女朋友,有女朋友了还会继续刷题吗?
南梦:有女朋友还打什么CTF,陪女朋友不好吗?(立即打开BUUOJ开始刷题,女朋友什么的最烦了)
更新与维护
后续可能会进一步更新x64和x32的解法(如果存在解的话)
EXP解释之后可能会进一步完善( 就看我有没有女朋友了(°∀°)ノ )
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 咲夜南梦's 博客!
评论