前面还有8个题,因为当时还没搭blog就写了,前面几个也比较简单,就不放在这里了
[OGeek2019]babyrop1
exp
1 | from pwn import * |
get_started_3dsctf_2016
通过rop以及shellcraft得到shell
mprotect可将内存段添加可执行权限是最主要的一点
vmmap查看可读可写内存
exp
1 | from pwn import * |
ciscn_2019_n_8
学到了int占4个字节
exp
1 | from pwn import * |
ciscn_2019_en_2/ciscn_2019_c_1
理解了pop rdi|ret,在64位系统中先用寄存器传参
如图
address:pop rdi|ret
address:puts_get
address:puts_plt
此时rsp指向puts_got,执行pop rdi及将puts_got的地址泄露,并且考虑到64位先用寄存传参,然后pop rdi后执行ret
此时rip指向puts_plt,程序跳转到puts,输出puts_got的地址
1 | from pwn import* |
jarvisoj_level2
没什么东西,只要看到/bin/sh就好了
exp
1 | from pwn import * |
not_the_same_3dsctf_2016
本题flag是存在bss段上的,和平常的题目不太一样,一开始看到了get_flag那个函数没有参数,没想到gadget都不用,看了wp才知道
第一种解
exp
1 | from pwn import * |
第二种解
通过mprotect函数修改段的权限写入shellcode,执行cat flag
exp
1 | from pwn import * |
bjdctf_2020_babystack
本地打不通,远程能打通,离谱,可能是环境的问题
exp
1 | from pwn import * |
[HarekazeCTF2019]baby_rop
注意64位先使用寄存器传参
exp
1 | from pwn import * |
jarvisoj_level2_x64
和上题一样的做法
1 | from pwn import * |
ciscn_2019_n_5
一开始想复杂了,想的是泄露libc版本,往bss段写/bin/sh,没想到可以直接写shellcode,然后栈溢出执行,题目没开NX······大意了,随便贴一个exp吧
exp
1 | from pwn import * |
ciscn_2019_ne_5
真的学到了sh可以替代/bin/sh,至于system的返回地址不能填p32(0),是我没想到的,确实也对,基本没遇到过strcpy可以溢出的情况,果然还是做题太少
exp
1 | from pwn import * |
铁人三项(第五赛区)2018_rop
做过类似的直接贴别的师傅的exp吧
1 | from pwn import * |
others_shellcode
nc node3.buuoj.cn 28745就有flag真签到题???
bjdctf_2020_babyrop
没什么东西,注意一下p.recv(6)就行了
exp
1 | from pwn import * |
babyheap_0ctf_2017
buu上做的第一道堆题,思路fastbinattack得到libc_base,然后再一次通过fastbinattack劫持mallochook指针为one_gadget
学到了fastbin attack以及当一个大于0x64的bin被释放后,fd会保存main_arena,而main_arena与libc_base存在固定偏移,
该固定偏移可以在malloc_trim中查看
exp
1 | from pwn import * |
pwn2_sctf_2016
思路:输入-1,整数溢出然后rop,注意printf的传参 return_addr+p32(fmstr)+p32(printf_got)
exp
1 | from pwn import * |
ciscn_2019_s_3
这个题目需要多使用gdb调试
第一种方法使用csu中的gadget
64位系统使用rdi,rsi,rdx,rcx,r8,r9来传参
此外这个题比较特殊一点,就是程序最后不需要push rbp,即不能只看ida,具体的偏移还是得看调试过程
思路:构造execve(“/bin/sh\x00”,0,0),系统调用号为59,先使用rax来存放,rdi存/bin/sh的地址,rsi为0,rdx为0,这时就能得到shell
syscall_addr=0x400517
rax_addr=0x4004E2 rdi_addr=0x4005a3 rsi_addr=0x4005a1 rdx_addr=0x400580
r12_addr=0x40059A
rax对应的指令为:
mov rax, 3Bh ; ‘;’
retn
rdi对应的指令为:
pop rdi ;
ret
rsi对应的指令为:
pop rsi ;
pop r15 ;
ret
rdx对应的指令为:
mov rdx, r13
mov rsi, r14
mov edi, r15d
call ds:(frame_dummy_init_array_entry - 600E10h)[r12+rbx* 8]
r12对应指令为:
pop rbx
pop rbp
pop r12
pop r13
pop r14
pop r15
retn
1 | from pwn import * |
第二种方法SROP
exp
1 | from pwn import * |
[HarekazeCTF2019]baby_rop2
流程:rop泄露libc+rop跳转system,一开始有个地方写错了,没写出来。。。。。。。。注意64为用寄存器传参数
exp
1 | from pwn import * |
jarvisoj_fm
格式化字符串漏洞
1 | from pwn import * |
ez_pz_hackover_2016
这个题主要的做法为通过程序给出的地址经过gdb调试算出偏移,然后rop即可,保护全没开
1 | from pwn import * |
ciscn_2019_es_2
主要思路是通过栈迁移来控制esp然后控制eip跳转到
system,/bin/sh的地址是通过第一部分泄露ebp的地址得到的
后面执行了两次(leave ret),通过这四步伪造了ebp,把esp改成我们想要的,然后控制程序运行到system
leave==mov esp,ebp ret=pop eip
exp
1 | from pwn import * |
jarvisoj_level3
思路泄露libc+栈溢出
1 | from pwn import * |
[Black Watch 入群题]PWN
第一次栈迁移泄露libc,第二次执行system
exp
1 | from pwn import * |
bjdctf_2020_babystack2
整数溢出+ret
exp
1 | from pwn import * |
输入-1也可以整数溢出,因为后面会将-1强制转化为无符号数
jarvisoj_tell_me_something
ret然后就会打印出flag
exp
1 | from pwn import * |
jarvisoj_level4
栈溢出泄露libc+ret
exp
1 | from pwn import * |
jarvisoj_level3_x64
和上一题类似只不过是64位的要考虑寄存器传参,先泄露地址,再ret
exp
1 | from pwn import * |
picoctf_2018_rop chain
一开始没做出来,看了题解之后发现挺简单的,只要一步步的满足flag函数中的条件,注意栈上的数据与函数参数的关系就行了
exp
1 | from pwn import * |
[ZJCTF 2019]EasyHeap
一道简单的堆题做了快三个小时,不过学到了挺多,也发现自己学的不好的地方,这个题目中edit函数部分存在堆溢出,并且给出了system_plt,所以无需泄露libc基地址,并且开了partial relro所以可以改写got表将free的got表改为system_plt,然后再free内容为/bin/sh的堆就可以了,我觉得其中最关键的部分是在0x6020a0部分伪造chunk,以及改写free之后chunk的fd指针
伪造的fastbinchunk需要满足的条件:大小位最后一位要为1(House of Spirit)
exp
1 | from pwn import * |
bjdctf_2020_babyrop2
思路先通过格式化字符串漏洞泄露canary,然后再通过rop泄露libc,一开始做的时候system和bin_sh的地址一直用的是addr加偏移,应该应用libc_base+偏移的,然后一直报timeout错误,浪费了好多时间,然后直接rop就行了
exp
1 | from pwn import * |
jarvisoj_test_your_memory
ret system,system函数后的返回地址需要为有效地址
exp
1 | from pwn import * |
bjdctf_2020_router
考察linux命令的使用:命令1+‘;’+命令2可以执行命令2处的命令nc之后1功能输入;cat flag即可
hitcontraining_uaf
简单uaf,这题中需要注意的地方
1.分配一个note之后,即使释放他之后,再分配一个note,index还是会+1
2.在分配用户控制大小的chunk之前,程序会分配一个固定大小为8的chunk,前4个字节放print_note的地址,当使用功能5时就会跳转到这里,当这里为system时,可以拿到权限
3.漏洞点uaf
exp
1 | from pwn import * |
picoctf_2018_buffer overflow 1
ret
exp
1 | from pwn import * |
pwnable_orw
orw即通过sys_open,sys_read,sys_write来读取flag文件
open
1 | push 0x0 #字符串结尾 |
read
1 | mov eax,0x3; |
write
1 | mov eax,0x4; |
exp
1 | from pwn import * |
shellcraft code
1 | shellcode = shellcraft.open('/flag') |
babyfengshui_33c3_2016
在该程序中,每次分配一个0x80的chunk,chunk中第一部分存放指向text的指针,第二部分存放des,
该程序通过bss段上的地址索引0x80的chunk的地址,且该地址中存放的时指向text的指针,程序中的第三个功能中
对分配大小的检测为addr:text+size>=addr:chunk-4 源代码为:(char *)(v3 + *(_DWORD )(&ptr + a1)) >= (char )(&ptr + a1) - 4
只要能绕过这个检测造成堆溢出,flag就近在眼前了,可以堆溢出之后,通过覆盖其他0x80chunk的第一部分为free_got,然后打印,就可以泄露libc,泄露libc之后,改写got表为system,然后再free掉一个有/bin/sh的chunk就行了
exp
1 | from pwn import * |
wustctf2020_getshell
exp
1 | from pwn import * |
cmcc_simplerop
做这道题真的学到了挺多东西,如system系统调用,当溢出空间不足时,pop掉调用过的函数的参数,调用read函数往已知的地址写/bin/sh\x00,还有
注意read函数中读入字符串的长度
exp
1 | from pwn import * |
picoctf_2018_buffer overflow 2
注意调用函数中参数的位置在返回地址后面就行,做这个题突然想起来picoctf_2018_rop chain,这个题和上面那个题的区别在于一个是全局变量,一个是参数,参数可以控制,全局变量需要程序提供的函数控制,更复杂一点
这个比picoctf_2018_buffer overflow 2更难的一点在于这里要传正确的参数
1 | from pwn import * |
[ZJCTF 2019]Login
这个题的反汇编很多都是c++,有点难看,这个题最核心的就是找到password与0x4000b4的偏移,然后将0x4000b4覆盖成后门函数的地址
,虽然看上去很简单,但是需要大量的调试
1 | a=1 |
xdctf2015_pwn200
栈溢出泄露libc,然后跳转到system
exp
1 | from pwn import * |
jarvisoj_level1
这个题本地和远程不太一样,本地是先告诉你一个栈地址再输入,远程是先输入再告诉你一个栈地址,因此本地可以用shellcraft,要简单很多
远程思路:泄露libc+ret
1 | from pwn import * |
bbys_tu_2016
偏移和ida里的不太一样,然后跳转到flag就可以了
1 | from pwn import * |
ciscn_2019_n_3
一个简单的uaf题,这个题最坑的地方就在于最后会追加一个回车,并且那个回车会改变堆的地址,一开始一直没注意……
结构1:
0xc print地址 free地址 堆地址
结构2:
size text
当这个函数执行free操作时,参数对应的地址时bss段上对应的内容,这也是那个sh\x00\x00的原因
exp
1 | from pwn import * |
inndy_rop
这个程序通过静态编译,泄露libc的方法失效、、、、、不过可以通过ropchain,ROPgadget可以直接生产ROPchain,命令为
ROPgadget –binary pwn –ropchain
exp
1 | from pwn import * |
mrctf2020_shellcode
未开nx,开了canary,以及pie,不能查看反汇编代码
输入shellcode就能得到shell
exp
1 | from pwn import * |
roarctf_2019_easy_pwn
这个题漏洞点在于单字节溢出,思路是通过溢出修改堆大小,并覆盖大堆,然后泄露main_arena,之后的思路和上面一样,然后改malloc_hook为og就可以了
但是,og不满足条件,这时可以修改realloc处的值来满足条件,这个题目对我来说,最大的难点在于如何修改大小并成功覆盖下一个small bin,
做了好久、、、、、、
1 | from pwn import * |
gyctf_2020_borrowstack
这个题是个简单的栈迁移,但是一开始还是没写出来(没注意64位,还忘了利用方式……)
1 | from pwn import * |
axb_2019_fmt32
思路先通过格式化字符串漏洞,往栈上写got,然后泄露地址,泄露libc之后,再将符合条件的函数的got表改为system,再输入’;/bin/sh\x00’(;改成&也可以)就可以了(因为str之前还有别的字符串会当成命令,直接输入/bin/sh执行不了)
exp
1 | from pwn import * |
others_babystack
挺简单的一道题,先泄露canary,然后栈溢出泄露libc,再ret system,只是我在做这个题的过程中忘记了覆盖 rip,之后要ret,也就是题目中
功能3的意义所在
exp
1 | from pwn import * |
mrctf2020_easyoverflow
保护全开,没什么好说的,只要找到fake_flag对应的字符串就行
1 | from pwn import * |
wustctf2020_getshell_2
这个题只能溢出eip后面四个字节,如果直接使用system_plt需要接放回地址,但是没有参数,而使用 call system后,后面的数据即为参数
exp
1 | from pwn import * |
pwnable_start
内联汇编
程序中没有main函数只有一个start,什么保护都没开,并且通过系统调用使用了write和read,不过可以溢出到ret,先ret到0x08048087
然后就可以泄露栈地址,然后再输入shellcode再跳转就能getshell了(shellcode有长度限制shellcraft生产的太长了)
后面为ad+20是因为ret中有pop eip,因此不是+24
exp
1 |
|
ciscn_2019_s_4
这题的exp用ciscn_2019_es_2也可以打通,都是栈迁移漏洞
exp
1 | from pwn import * |
hitcontraining_magicheap
第一次这么快做出一道堆题、、、、、、这个题目中edit部分存在堆溢出,同时这个程序中没有show,基本无法泄露libc,不过给了system(“/bin/sh”)
并且edit是通过heaparray上的地址来edit,如果heaparray上的内容为某个got表,那我们就可以将free的got表改为sys_ad,然后free一个chunk
就能getshell了
思路:先通过fastbinattack来实现任意地址写,然后再heaparray附近找到符合条件的地址,0x60208d出正好满足条件,于是,通过malloc得到
那个堆块,然后覆盖掉heaparray第一项为free的got表,然后再editfree的got表为0x400C50就能getshell
exp
1 | from pwn import * |
ciscn_2019_final_3
通过大量的调试,我算是整明白这个题了,整明白后本地打不通我也不知道为什么,这个题创建堆会返回堆的地址,没有别的
地方可以泄露libc,而根据大于0x400的堆杯free会放入unsorted bin中,且fd为main_arena+96,可以想办
法分配到main_arena,思路是伪造一个0x400的堆来泄露libc,通过tcache dup来分配到第一个堆,然后改他的大小为0x421,
改完之后在分配几个堆,使大堆的fd到别的堆的fd,然后再多分配几个大小相同的堆,就可以分配到main_arena,就可以泄露libc了
然后再通过tcache dup 分配到__free_hook 改为system 基本就可以了
附上别人的exp
1 |
|
hitcontraining_heapcreator
程序的有malloc,edit,show,free功能
本题中的两个结构题
大小0x10
struct1{
int size;
char * ptr->heap;
}
大小由用户控制
struct2{
char * content;
}
edit功能中存在off-by-one,可以先多创建几个chunk,然后通过off-by-one,修改一个chunk大小覆盖别的存放了ptr的chunk,然后修改ptr中的内容为got表,再通过show打印对应的heap,就可以泄露libc,之后就可以通过改free的got表
为system,再getshell
exp
1 | from pwn import * |
0ctf_2017_babyheap
本题保护全开,有4大功能alloc,fill,free,dump,allo中使用的是calloc,fill中存在堆溢出,思路为泄露libc+malloc_hook劫持,
泄露libc:
通过chunk extent和overlapping来得到一个覆盖了别的堆块的堆,然后
将被覆盖的堆快大小改为small bin,free再dump,即可泄露libc
malloc_hook劫持:
思路和前面差不多,fd改为malloc_hook-0x23就可以了
exp
1 | from pwn import * |
wustctf2020_closed
本题考的是linux命令相关的知识,见:https://www.cnblogs.com/chuj/p/14232142.html
close(1),关闭了标准输出,close(2),关闭了标准错误,输入的命令被执行,
但是由于close(1),看不到结果,通过exec 1>&0来把标准输出重定向到文件描述符0(标准输入),这个文件默认是开启的。这样我们就可以看到输出了。
ciscn_2019_es_7
做法和ciscn_2019_s_3一样,见ciscn_2019_s_3
jarvisoj_level5
64位,只开了NX保护,先通过rop调用write泄露libc,然后就可以乱写了
常规写法
exp
1 | from pwn import * |
mprotect写法转自pwnki师傅
1 | from pwn import * |
hitcontraining_bamboobox
第一种写法(未用magic)
这个题我用的是泄露libc+改got表的方法getshell,本题中的edit功能有溢出,不过结尾会加上’\0’,绕不过去,然后我发现bss段可以伪造堆块,接下来的流程就清晰了,先放个got表覆盖一个bss段的堆指针,然后打印得到libc,再放一个覆盖为system(最好覆盖atoi),然后输入/bin/sh\x00就能getshell
exp
1 | from pwn import * |
第二种写法(house of force)
待补充
hitcon2014_stkof
一道unlink的入门题,这个题的堆地址存放在bss段上,可以通过unlink来分配堆到bss段上来修改堆指针为got表
先是将free的got表改为puts的plt,然后泄露libc,接着将atoi的got表改为system
然后发送”/bin/sh\x00”就能getshell
exp
1 | from pwn import * |
pwnable_hacknote
这个题是个简单的uaf,名字和hitcon的一道uaf名字一样,思路也基本一样,只是没有magic函数,要复杂一点点,最后那里需要
用’;sh\x00’来进入shell
分配一个堆会分配一个0x8的功能堆,前四个字节用于输出,后四个记录堆地址
思路:通过uaf,来得到一个0x8的功能堆,然后覆盖,后四个字节为got表,再show一下,泄露libc,得到system,再使用同样的方法
得到一个功能堆,然后前四个字节填sys_ad,后四个填’;sh\x00’就能getshell(打远程用’sh\x00\x00’没打通于是就明白了)
1 | from pwn import * |
ciscn_2019_s_9
32位,保护都没开,可以通过写shellcode或者泄露libc然后ret system都可以get shell
ROP:
1 | from pwn import * |
使用shellcode
1 | from pwn import * |
actf_2019_babystack
栈迁移泄露libc+栈迁移retsystem,64位需要使用ret使栈对齐
1 | from pwn import * |
cmcc_pwnme2
思路栈溢出泄露libc,然后再ret system,需要注意的是ebp未变,ida上的偏移和实际偏移不一样,直接返回
1 | from pwn import * |
picoctf_2018_shellcode
32位,什么保护都没开,main不能反编译,不过能看懂,main函数中call 了eax,而此时eax
正好位get的参数
这个题是一个shellcode题,输入shellcode就能getshell,还是没理解call的意义,
call的地方应该是可执行代码
call指令:
第一步:先将call指令的下一条指令的CS和IP入栈(当然如果是段间转移就要将CS和IP入栈,如果是段内转移就只要将IP入栈)
第二步:就是操作与call对应的jmp指令
所有的call指令都是可以用上面的两步来确定的,这是个通用的法则。
1 | from pwn import * |
npuctf_2020_easyheap
这个题,edit功能中存在off-by-one,maloc功能中只能创建0x18,以及0x38的堆,并且每分配一个堆会先分配一个0x10的堆来存大小的内容的地址,
思路是通过chunk extend以及overlapping来覆盖一个0x10的堆的内容,从而泄露libc,并且修改got表
1 | from pwn import * |
picoctf_2018_can_you_gets_me
一道简单的栈溢出题,只有一个gets,使用ROPgadget的ROPchain即可
1 | from pwn import * |
picoctf_2018_got_shell
程序逻辑如下
1 | int __cdecl __noreturn main(int argc, const char **argv, const char **envp) |
见exp
1 | from pwn import * |
ciscn_2019_es_1
这个题是tcache dup感觉思想上理解了,实操不太行,本地环境打不通,只能打远程,就很难受
exp
1 | from pwn import * |
axb_2019_brop64
简单rop,64位注意寄存器传参
exp
1 | from pwn import * |
mrctf2020_easy_equation
等式:11 * judge * judge + 17 * judge * judge * judge * judge - 13 * judge * judge * judge - 7 * judge == 198
解出来judge 为 2,然后就是普通的格式字符串漏洞
exp
1 | from pwn import * |
gyctf_2020_some_thing_exceting
保护没开pie,一个简单的uaf,一开始没注意程序中有个地方读入了flag,就以为要先uaf泄露libc,然后再改malloc_hook为og,结果可以直接print flag
exp
1 | from pwn import * |
[极客大挑战 2019]Not Bad
这个题开了沙盒,system用不了,只能通过orw来读flag,这个题一开始给了提示,分配了一段空间可写可读,并且程序有jmp rsp,然后看exp就能明白了
exp
1 | from pwn import * |
hitcontraining_unlink
简单unlink,unlink的绕过为FD->bk=p,BK->fd=p,以及p->next-chunk-presize==p->size,绕过这两布,FD以及BK的值基本就确定了,然后通过FD->bk=BK,BK->fd=FD,这样就能改写bss段上的堆指针到bss段上从而修改bss段上的内容,然后就基本想干什么就干什么
exp
1 | from pwn import * |
axb_2019_fmt64
一个格式化字符串漏洞写了一上午,虽然用了很久,不过还是学到了一点东西,在printf的格式化字符串漏洞中,地址中含有’\x00’,当printf函数读取到这个后就会截断字符串,不管是泄露还是改got表中都应该注意这一点
exp
1 | from pwn import * |
axb_2019_heap
这个题有意思,保护全开,一开始给了个格式化字符串漏洞,还是%s输入泄露不了got表,还限制了长度
但是后面又只有一个off-by-one+unlink,所以这里肯定可以泄露libc以及程序的基地址,
通过gdb调试能得到%15$p处为libc_start_main+240,%19$p处为main+0x116a正好与ida中的一样,然后正常unlink就可以了
exp
1 | from pwn import * |
picoctf_2018_leak_me
看栈上面的s与v5相邻,可以想到输出v5的时候顺便把s输出就可以了,大意了,一开始没写出来
exp
1 | from pwn import * |
wdb_2018_2nd_easyfmt
这个题也是一个标准的格式化字符串漏洞,32位,思路是先通过格式化字符串漏洞泄露libc,然后再改printf的got表为system,并且如果一个字节一个字节的改got表的话,
应该注意大小顺序,如果使用pwntools的fmtstr就完全不用当心,这个题我没找到题目的libc,只能通过printf的地址来多找几个libc
exp
1 | from pwn import * |
cmcc_pwnme1
什么保护都没开,两种做法,一种是泄露libc,ret到system,另一种是通过shellcode
exp,一开始忘记要加返回地址了,一直没做对……,确实好久没做32位的了
1 | from pwn import * |
suctf_2018_basic pwn
简单rop
exp
1 | from pwn import * |
oneshot_tjctf_2016
根据程序流程做第一个scanf+%lld可以泄露地址,第二个可以调转到one_gadget,泄露地址那个地方最好用gdb调试一下
exp
1 | from pwn import * |
x_ctf_b0verfl0w
没什么,就输入shellcode然后通过jmp esp跳就可以了
exp
1 | from pwn import * |
inndy_echo
就格式化字符串漏洞就没了
1 | from pwn import * |
ciscn_2019_final_2
代解决,这个题知识点的主要是tcache attack+dup2函数+double free+house of spirit
exp
1 | from pwn import * |
wustctf2020_name_your_cat
数组越界没什么好说的
1 | from pwn import * |
gyctf_2020_force
保护全开,
House of force的经典题,这个题只有一个功能有用,分配内存那个函数,存在溢出,并且可以分配任意大小的堆,这个题的思路是先通过main_arena
来泄露libc,然后通过house of force 来改malloc_hook为og就可以了,不过要注意的一点是,要使用realloc来调整栈,来满足og的条件
exp
1 | from pwn import * |
wdb2018_guess
一个不常见的stack smash
程序可以运行的次数为三次,stack smash的原理是通过栈溢出覆盖argv,而程序报错信息会打印argv
得到程序flag的地址后,将argv改为flag的地址即可成功打印flag
第一次泄露libc,第二次泄露flag的地址(通过environ,__ environ中存放了
当前进程的环境变量,并且改环境变量在栈上,通过该环境变量与栈上flag的偏移,
就能得到flag的地址),第三次得到flag
exp
1 | from pwn import * |
zctf2016_note2
这个题是一个关于unlink的经典题,我从中确实学到了一点东西,strncat会被’\x00’截断
allo函数中有一个a2 - 1 > i,a2 为有符号int ,i为无符号int,这两者相比,有符号会被自动转
化为无符号,而-1转化为无符号会变成一个很大的数,可以任意溢出
然后就是常规unlink
1 | from pwn import * |
护网杯_2018_gettingstart
这个题就是考察小数在内存中的表示,用工具算一下,或者ida里面找一下就可以了
exp
1 | from pwn import * |
ciscn_2019_en_3
这个题思路非常简单,保护全开,开头有两个输入和输出,这个题,环境是搭在ubuntu18上的,一开始
我用的ubuntu16位调的发现两个输出都能泄露libc,当我换环境之后用的新的libc-2.27偏移又不对,
思路: 泄露libc+tcache double free
exp
1 | from pwn import * |
picoctf_2018_are you root
这个题真的有点东西,需要一些比较深入的思考,这个题最核心的部分就是get-flag与login那部分
get-flag的验证为** v5+2==5,还有个函数也值得提一下strdup内置malloc(大小由字符串的长度决定)
,返回的是堆地址,思路是先通过strdup创建一个内容为”a”* 8+p64(5)的堆,
通过reset,将这个堆free掉后(一开始每注意,以为是另一个堆),然后再login
第一次malloc得到的堆就是free掉的堆,就可以通过get-flag的验证了
exp
1 | from pwn import * |
wustctf2020_number_game
int的范围[-2147483648,2147483647],判断条件是if ( v1 >= 0 || (v1 = -v1, v1 >= 0) )
显然v12就是-2147483648exp
1 | from pwn import * |
picoctf_2018_buffer overflow 0
第一次做要用ssh的题
其中输出flag的程序signal(11, sigsegv_handler);
当内存出现错误时就会打印flag,比如溢出,以及访问非法内存
命令
ssh -p 27128 CTFMan@ node4.buuoj.cn
./vuln aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
或者通过rop的方式通过调用puts函数打印flag
为
./vuln aaaaaaaaaaaaaaaaaaaaaaaa\xc0\x84\x04\x08\x00\x00\x00\x00\x80\xa0\x04\x08
其中./vuln后面为argv[1]相当于参数
bjdctf_2020_YDSneedGrirlfriend
一个简单的uaf,给了后门函数,在allo中会创建一个0x10,第一部分存一个print函数的指针,将它覆盖成
后面函数的地址在输出对应的堆就可以getshell了
1 | from pwn import * |
judgement_mna_2016
一个简单的格式化字符串漏洞,一开始瞎了,没看到栈上有flag,想用地址+%s泄露flag,结果
有保护,泄露不出
偏移是28
1 | from pwn import * |
gyctf_2020_signin(18)
这个题在free函数中有个uaf,edit函数可以用一次,有getshell功能,只要ptr>0,就能getshell
需要用到的知识:tcache bin中满了7个后再free 的bin放在fastbin中
calloc从fastbin中分配,并且会将剩下的bin放到tcachebin中
这个题的思路是先分配8个0x70的堆,再依次free掉,堆8放在了fastbin中,此时fastbin中有一个堆,tcache中有7个堆,于是给tcachebin中留一个ptr-0x10的位置,allo一个堆,再修改free掉的那
fastbin中的堆的fd指针为ptr-0x10,然后使用backdoor函数就可以了
1 | from pwn import * |
wustctf2020_name_your_dog
这个题思路非常简单给了shell函数通过它的方式改got就可以了,一开始没注意改的printf的got,结果看错了,以为能改到,结果改不到,只能改scanf的,并且正好可以改到
1 | from pwn import * |
gyctf_2020_some_thing_interesting
格式化字符串漏洞+uaf,开头有一个长度为0xe字符串的验证,并且后续有一个和该字符串相关的
格式化字符串漏洞,可以输入的长度为0x13,还可以多输5个字符来泄露libc(一开始没注意长度,想绕
strncmp,结果绕不过去),uaf部分就写og就可以了,不过是0xf1147,交互写错了,调了一下午,太离谱了
1 | from pwn import * |
mrctf2020_shellcode_revenge
这个题是一个纯字符shellcode,需要使用工具:alpha3
安装:git clone https://github.com/TaQini/alpha3.git
使用先创建一个shellcode脚本
1 | from pwn import * |
1 | from pwn import * |
参考:http://taqini.space/2020/03/31/alpha-shellcode-gen/#AE64
starctf_2019_babyshell
这个题有一个shellcode的检查需要通过’\x00’绕过,即通过一个’\x00’开头的汇编指令就可以绕过了
有’\x00j\x00’,’\x00B3’,’\x00B\x22’,’\x00B\x00’,’\x00B’后面加上一个字符对应一个汇编语句
1 | from pwn import * |
actf_2019_babyheap
一个tcache的简单题 + uaf,这个题开了got表的保护,题目中给了system以及bin_sh的地址(我没看到,直接先泄露再getshell)
allo中会先创建一个0x10的堆,前一部分存堆指针,后一部分存print函数的指针,思路是 把一个自动创建的0x10的堆的前一部分改成bin_ad,后一部分改成system,然后show就可以了
1 | from pwn import * |
xman_2019_format
学到了学到了,堆上的格式化字符串漏洞,思路是劫持返回地址为system,一开始payload那里忘记加+=了,一直没打通,做这个题顺便知道了怎么一直爆破,学到了,这个题的payload只能输入一次,不过可以根据|多次执行,gdb调试中做题就两步,看图就能很明白了
第一步
结果
第二步改成system就可以了,只用改两个字节
exp
1 | from pwn import * |
强网杯2019 拟态 STKOF
第一次做拟态这种两个pwn文件的题目,学到了,静态编译,主要内容是ropchain
这个题中32位的偏移是0x110,而64位是0x118,在32位填充返回地址时,在64位填的是rbp,可以通过这一点
来调整32位的栈,于64位的栈分开将32位的栈太高,而64位正好可以正常执行,然后注意64位用寄存器传参,32位不破坏栈就可以了,shellcode部分可以用ropchain,不过要注意简化
应该还有别的做法,比如用mprotect
exp
1 | #coding:utf8 |
roarctf_2019_realloc_magic
关于realloc的用法
1 | size == 0 ,这个时候等同于free |
关于本题中利用到realloc的相关知识
假设现在有三个被free的chunk,大小分别为0x60,0x80,0x100,此时先分配一个大小为0x60的chunk,realloc得到的地址就是被free的那个0x60的堆的地址,然后再realloc 一个0xe0的堆,此时得到的堆就包括了0x60和0x80这两个堆,就可以快乐的改
0x80的fd了(太非了1/16的概率跑了十几次)
_ 2_1_stdout的最后3位可以确定是0x760,还有一位就需要爆破了(IO流)
1 | from pwn import * |
wustctf2020_easyfast
这个题思路很简单,只要把0x602090改为0就可以了,可以直接通过uaf和fastbinattack,在0x6020080处分配内存,但是这个地方理论上是分配不了的,因为大小为0x50,后一位是0,待解决
1 | from pwn import * |
ciscn_2019_final_5
这个题有点东西,从下午写到晚上才写出来,主要是犯的错太多了,一开始交互又写错了,浪费了好多时间
这个题中索引堆块是通过heap_array中堆地址的最后一位,edit函数中size则是根据idx
主要漏洞点在于
malloc函数
1 | if ( !result ) |
free函数
1 | if ( result == v2 ) |
思路:先分配一个0x10的堆,然后内容为伪造的堆块的内容,此时再分配一个大堆块(可以覆盖到heap_array的大小),然后free掉大的和伪造的,此时
再分配我们伪造的堆块的大小,就能得到伪造的堆块,此时再修改大堆块的fd为0x6020e0,后面的操作就比较常规了
1 | from pwn import * |
wdb_2018_3rd_soEasy
一个简单的shellcode题,给了栈地址,直接ret过去就可以了
1 | from pwn import * |
bcloud_bctf_2016
32位,有栈保护,可以改got表,没pie,后面还有个一模一样的bctf2016_bcloud,直接一起交了
这个题最主要的漏洞点在于这两个函数
1 | unsigned int sub_80487A1() |
这个函数中需要注意栈,s后面就是v2,我们在输入64个字符后,再创建的堆,又因为32位,在输出s的时候就可以泄露第一个堆的地址
第二个函数
1 | unsigned int sub_804884E() |
和第一个函数是一样的原理,v3可以覆盖top_chunk,之后就是比较常规的house of force
1 | from pwn import * |
hitcon_2018_children_tcache
这个题信息量有点大,保护全开,只有三个功能,allo,show,free,allo结束有个’\x00’,show使用的是puts,free
函数中会先将数据全部设置为垃圾数据,再free,allo中的off-by-null有点不好利用,不过也给了泄露libc的希望
1 | from pwn import * |
suctf_2018_stack
ret2libc没什么东西,给了system函数直接跳到那里就可以了(需要考虑栈平衡,不能直接跳到0x400676)
1 | from pwn import * |
qctf2018_stack2
这个题挺坑的,他给的system(“/bin/bash”)用不了,并且ida的偏移与gdb上的不一样,思路是通过数组下标
越界劫持ret(我本地用ubuntu16,偏移一直不对,结果一用18就行了)
1 | from pwn import * |
lctf2016_pwn200
这个题挺好写的,有两种做法,一种是劫持返回地址或者got表,然后跳到shellcode,另一种是
house of spirit(一开始没注意sendline和send,一直错)
劫持返回地址的做法
1 | from pwn import * |
house of spirit的做法
代补充
jarvisoj_level6_x64
这个题没开Full RELRO,再malloc函数中结尾处未加上\x00(一般题目中都用),这代表,可以先将chunk free到unsortbin中,然后修改它的fd,此时再show就能泄露出libc或者堆地址,
malloc函数中大小设置为128 - v3 % 128) % 128 + v3,因此,分配得到的chunk 再free都属于small chunk
或者large bin,free函数中存在uaf(没把堆指针置0),通过这一点可以利用堆的合并,将先前创建的堆
全都free掉,再relloc一个大小比前三个堆大小和起来大的堆,此时就能伪造堆,然后执行unlink操作
(不知道为什么,我本地打不通,远程通了)
1 | from pwn import * |
zctf_2016_note3
没有show功能(无效),大概能猜到是改free的got表为puts_plt,泄露libc
这个题主要的漏洞就是size为0的时候,0-1转化成无符号整数,产生溢出,知道这一点后,在bss段上有个0x000000000000007f,可以伪造fastbin,分配到这里就好说了,思路是先分配几个0x68大小的bin,free后,
利用size为0的chunk,修改fd为0x6028ad处,此时再直接修改堆指针为got,就差不多了
1 | from pwn import * |
gyctf_2020_document
这个题开了full relro,漏洞点是uaf,allo函数固定分配一个0x20和0x80的堆,这个题的思路是
allo两个堆,然后free第一个此时chunk中的内容就是main_arnea,然后show就可以泄露libc(不知道为什么,
打远程的时候有几次泄露地址是错的没打通),然后最重要的来了,因为这个题edit只能修改fd+0x10处,
就没办法直接修改fd,不过因为我们之前free了一个0x80的堆,而这个堆就放在unsortedbin中,此时再分配
内存,就会从unsorted中切下来,此时再通过uaf,修改某个0x20的堆的指针,就差不多了(堆风水)
1 | from pwn import * |
[BSidesCF 2019]Runit
一个简单的shellocde题,直接填shellcode,然后call,就能拿到权限了
1 | from pwn import * |
de1ctf_2019_weapon
这个题做了一天,改了一天脚本没做出来,tcl,每当allo到stdout附近的时候就signal kill(感觉是unsortedbin中的那个,
correpurt,太离谱了),总之就是非常离谱,贴一下大佬的exp,待补充
1 | #!/usr/bin/python2 |
pwnable.kr_asm
开了沙箱,直接使用64位orw就可以了,有时间自己写写(待补充)
1 | from pwn import * |
houseoforange_hitcon_2016
这个题是一个houseoforange + FSOP 的经典题,这个题真的可以好好记录一下
程序大致功能
1.add()函数中大小限制为0x1000
2.有show函数
3.有edit函数,并且存在溢出
4.没有free函数
思路是先溢出修改topchunk为0xf91,此时分配一个0x1000的堆,topchunk就会进入unsortedbin,
再分配一个largebin,largebin中的fd和bk为main_arnea + offset,而fd_nextsize和bk_nextsize为
自己的地址,如图
这样可以泄露libc和堆地址
然后就剩下unsortedbinattack 和 FSOP 部分
unsortedbinattack原理为
当malloc时,会执行如下代码
1 | unsorted_chunks (av)-bk = bck; |
如果修改bk = target - 0x10,target 就会填入main_arena上指向该unsortedbin的地址
可以看到本题中io_list_all中写入了指向topchunk的地址
malloc时,unsortedbinattack 将io_list_all写入main_arena+0x58,并且由于修改了unsortedbin的大小为0x61,
main_arena+0x58+0x68会写入unsortedbin的地址,而接下来会判断下一个unsortedbin即(io_list_all中的地址),而
此时那里写入的是main_arena+0x58,没有chunk,不满足条件
(补充当unsortedbin从链表拆下来时,main_arena上会根据unsortedbin的大小填入堆的地址)
如图main_arena + 0x58 + 0x68填入的就是unsortedbin的地址(因为大小为0x61,所以填在这里)
main_arena + 0x58指向的时unsortedbin的地址
io_list_all中存放的是io_list_all结构体的指针,结构如下
1 | struct _IO_list_all |
此时触发错误,于是通过_chain调用下一个_IO_list_all,即 main_arena + 0x58 + 0x68 = main_arena + 0xc0,而
main_arena + 0xc0 处对应的是idx为6的smallbin(将unsortedbin大小改为0x61的原因)
FSOP的最终目的是调用 IO_flush_all_lockp 函数中的 IO_overflow函数(IO_overflow写成system,struct开始填入/bin/sh)
IO_flush_all_lockp函数源码
1 | _IO_flush_all_lockp (int do_lock) |
IO_flush_all_lockp函数触发条件:
1.当libc执行abort流程时 abort可以通过触发malloc_printerr来触发
2.当执行exit函数时
3.当执行流从main函数返回时
需要绕过的条件
1 | 1.fp->_mode > 0 |
64位的_IO_FILE_plus构造模板:
1 | stream = "/bin/sh\x00"+p64(0x61) |
32位的
1 | stream = "sh\x00\x00"+p32(0x31) # system_call_parameter and link to small_bin[4] |
此时本题中main_arena + 0xc0正好就是我们伪造的数据如图
伪造数据形式如下
1 | def fake_file_struct(): |
vtable地址被伪造成了0x000055b84fe0b5e8,伪造的虚表如下
此时overflow的地址为system,/bin/sh\x00为参数,这样就能getshell了
vtable是_IO_jump_t类型的指针,如下
1 | struct _IO_jump_t |
总exp
1 | from pwn import * |
ciscn_2019_sw_1
这个题挺有趣的,32位没开relro(什么都可以改)
思路是通过格式化字符串漏洞将printf的got表改成system,然后再把fini_array改成main就可以了
主函数如下
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
exp
1 | from pwn import * |
ciscn_s_6
unsortedbin attack泄露libc,然后tcache dup改free_hook就可以了(这里要注意偏移)
1 | from pwn import * |
hgame2018_flag_server
这个题nc连接后,用-1绕过长度检测,然后”a”* 0x64 + 1就可以getshell了
payload = “AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAH1”
SWPUCTF_2019_p1KkHeap
题目环境ubuntu18,保护全开,开了沙箱,限制free次数3次,存在uaf漏洞,有show功能可以泄露libc或者堆地址,程序一开始分配了固定地址的orw段
这个题不能按常规思路做,通过overlap改大小泄露libc,或者塞满tcachebin 基本都实现不了,实现了也无法分配到malloc_hook
思路是doublefree,泄露堆地址,从而泄露heap的表头,然后通过修改表头可以控制分配堆的地址,先分配到表头,然后再分配到
orw段写shellcode,再分配到malloc_hook跳shellcode
1 | from pwn import * |
[2020 新春红包题]3
libc-2.29下的smallbin attack,思路比较简单,最后需要将栈迁移到堆上orw
1 | from pwn import * |
SWPUCTF_2019_login
这个题为32位bss段上格式化字符串漏洞,思路是借用输入的name在栈上的地址,来将printf_got+2和printf_got加载到栈上,
然后同时改,改为system后就可以getshell了,一开始早就打通了,结果打远程的时候被p.recvuntil卡住了(学到了,以后做格式化必加p.recvuntil)
1 | from pwn import * |
npuctf_2020_level2
开了pie和full relro保护,64位bss段上格式化字符串漏洞,链子藏的比较深,一开始没找到(看了wp才知道),直接打og就可以了
1 | from pwn import * |
sctf_2019_easy_heap
这个题挺好玩的,ubuntu18环境,程序开始给了个rwx段,没有show函数,分配的堆大小限制为0x1000,edit函数有
off-by-null
思路是先创建三个堆大小分别为0x418,0x68,0x4f8,0x68,如下图所示
free(1),然后off-by-null将堆2的presize设置为0x420+0x70,然后free(2),就会得到一个0x420+0x70的堆
,从堆0处开始分配,此时先add(0x418),再add(0x68)就能在bss段上得到两个指向堆1的指针,如图
然后攻击rwx段写入shellcode,再通过一样的方法,将main_arena写到堆1上,此时覆盖0xa0这个字节为
0x30,此时就能得到malloc_hook,再写rwx的地址就可以了
1 | from pwn import * |
ciscn_2019_s_1
ubuntu18,关了pie,思路挺简单的add中有off-by-null,并且给了堆地址,思路和前面那题差不多,先分到
控制show以及edit的0x6022B8,然后再free_hook改system就可以了
1 | from pwn import * |
gwctf_2019_easy_pwn
32位 + c++写的程序 + 开了partial relro 以及 nx,大意了,I替换成pretty没分析出来
1 | from pwn import * |
picoctf_2018_echooo
32位格式化字符串漏洞
1 | from pwn import * |
asis2016_b00ks
这个题有两种做法(因为申请堆的大小没被控制),有show功能和edit功能,进入菜单前要输入name,而name后放的就是堆的指针,
可以先输入32个字符填满,再创建堆,然后show就可以泄露堆的地址,本题中的堆是通过一个book结构的堆管理的
1 | struct books{ |
并通过指向book的指针控制其中的内容
思路是创建第一个堆,堆的des部分可以覆盖0x100-0x110(用于edit伪造堆),然后再分配第二个堆,并且为smallbin大小的堆,再free,放到unsortedbin中
,此时修改第一个堆的des伪造指针指向unsortedbin中那个堆的fd,再changname此时就可以泄露libc,然后再分配0x68的堆到0x100,那个结构控制的堆那里,就差不多了,最后再通过realloc+malloc_hook打og就可以了
1 | from pwn import * |
rootersctf_2019_srop
64位只开了nx,srop
1 | from pwn import * |
hitcontraining_playfmt
bss段上的格式化字符串漏洞,思路是泄露libc+改printf_got为system
1 | from pwn import * |
jarvisoj_typo
arm汇编,静态编译,需要找到system,以及/bin/sh,(arm中r0和rdi一样),system有点玄学,别人博客上和
do_system基本一样,我这里
1 | void sub_110B4() |
别人
1 | char * sub_110B4(int a1) |
1 | from pwn import * |
[OGeek2019]bookmanager
第一版exp
1 | from pwn import * |
第二版exp
1 | from pwn import * |
第三版exp
1 | from pwn import * |
几经周折,第二版和第三版exp能打通,最开始没打通是没用buu的libc……
sctf_2019_one_heap
本地环境太新了调不了这个题
参考exp一(https://surager.pub/_posts/2020-09-05-sctf_2019_one_heap/)
这个利用了堆的小tricks,需要对堆的构造非常非常熟悉
1 | from pwn import * |
参考exp二
1 | from pwn import * |
ciscn_2019_n_7
exit_hook,由于关闭了输出,需要exec 1>&0将输出重定向
1 | from pwn import * |
qctf_2018_stack2
简单题
1 | from pwn import * |
wdb_2018_1st_babyheap
unlink做法
1 | from pwn import * |
srop做法
待补充
hfctf_2020_marksman
思路非常清晰显然是exit_hook打one_gadget
1 | from pwn import* |
warmup
两种做法,一种orw,另一种execve,思路是通过read或者alarm来控制eax从而执行系统调用
(使用execve的做法需要用到一个小trick,即execve的第二个参数可以是0,也可以为指向0的地址)
1 | from pwn import * |
hitcon_ctf_2019_one_punch
环境为libc-2.29,保护全开,开了沙盒,这个题有点意思,add函数使用calloc(序号为0-2),存在uaf,
存在后门函数需要满足0x217的tcachebin数量大于6,思路是通过size不为0x217的堆的tcache stash unlink attack
1 | from pwn import * |
wustctf2020_babyfmt
学到很多,首先是scanf输入部分(%lld),输入读到的是字母,则输出原本的内容可以泄露pie和stack,还有将
bss段的stdout地址改为stderr,这样即使关闭输出也能通过stderr输出
1 | from pwn import * |
inndy_echo2
简单格式化字符串漏洞
1 | from pwn import * |
[OGeek2019 Final]OVM
本地脚本,远程再改几个值就可以了,第一次做vmpwn(有点意思),这个vmpwn的逻辑比较清晰,通过memory的
越界来修改sendcomment为free_hook(free_hook需要根据bss上的stderr得到)
1 | from pwn import * |
ciscn_2019_es_4
libc-2.27下的off-by-null,限制有点多,不过仅此而已
1 | from pwn import * |
0ctf_2018_heapstorm2
这个题是shrink chunk + house of storm(参考https://eternalsakura13.com/2018/04/03/heapstorm2)
1 | from pwn import * |
pwnable_simple_login
emmmm,仔细分析的话确实是简单题
1 | from pwn import * |
linkctf_2018.7_babypie
简单题,思路是给了system(“/bin/sh”),但是这个题开了pie需要覆盖一个有pie且会执行到的地址,1/16
1 | from pwn import * |
npuctf_2020_bad_guy
简单题,edit函数里有堆溢出,没有show功能思路是通过修改一个0x10的堆的大小,然后进unsortedbin中,此时再
free掉那个0x60的堆,将fd->stdout进而控制stdout泄露libc,最后malloc_hook改og实现利用,此时下面的脚本
不能直接拿到shell,需要手动malloc进行交互,从而触发og
1 | from pwn import * |
https://blog.csdn.net/qq_41202237/article/details/118518498
思路大概就是利用0x4008ac之后的gadget控制参数,然后执行mprotect=改bss的权限,然后getshell,装好库才能生成shellcode
,命令如下
1 | sudo apt-get install binutils-aarch64-linux-gnu |
1 | from pwn import * |
参考(https://blog.csdn.net/qq_41202237/article/details/118518498)
360chunqiu2017_smallest
经典srop,主程序只有sys_read,思路:先泄露栈地址,然后迁移栈到泄露的地址,然后再execve
1 | from pwn import * |
0ctf2015_freenote
学到很多,smallbin double + unlink
1 | from pwn import * |
ciscn_2019_final_4
相关条件:ubuntu16,有new,write,delete函数,存在uaf,程序开始处存在一处栈上的输入,主程序while(1),开了沙盒,
思路一般来说是使用setcontext来进行rop,但是free_hook前没有满足条件能够写入setcontext的地方(没开pie,不然
方法就很多了),于是思路就变成了使用堆布置栈,通过environ泄露栈地址。
(补充:需要先用ida将400F91处改为E9 99 00 00 00)
exp
1 | from pwn import * |
(参考:https://blog.csdn.net/seaaseesa/article/details/105855306)
gwctf_2019_jiandan_pwn1
简单题,最好多用几个send,
exp
1 | from pwn import * |
sleepyHolder_hitcon_2016
学到很多,fastbindouble的检查只是检查fastbin中的堆头是否于当前释放的堆相同,但是如果触发malloc_consolite,
此时,会取出fastbin中的堆,相邻的chunk进行合并,并且会设置下一个chunk的prev_inuse位为0。这题中可以使用
选项3分配一个特别大的堆,来触发,然后进行unlink操作就差不多了
1 | from pwn import * |
actf_2019_onerepeater
32位格式化字符串,partial relro,可以直接改got,没开NX,可以shellcode(原理都差不多还不如直接改got一步到位)
1 | from pwn import * |
[GKCTF 2021]checkin
这个题密码验证那里猜出来md5的加密方式,然后栈迁移,就差不多了
1 | from pwn import * |
roarctf_2019_easyheap
思路是double free + og(realloc),需要使用sleep(防止数据发送的时候出问题)
1 | from pwn import * |
starctf_2019_girlfriend
fastbin attack + realloc调整栈
1 | from pwn import * |
hctf2016_fheap
ubuntu16+uaf+格式化字符串
1 |
|
mrctf2020_easyrop
这个题思路是ret system,注意fflush(远程没有及时输出),以及退出主程序时,要注意下标
1 | from pwn import * |
hwb_2019_mergeheap
ubuntu18,利用strcpy来覆盖size
1 | from pwn import * |
nsctf_online_2019_pwn2
ubuntu16,利用update函数操作堆
1 | from pwn import * |
jarvisoj_itemboard
注意参数就差不多了
1 | from pwn import * |
bbctf_2020_fmt_me
控制好snprintf参数就可以了
1 | from pwn import * |
metasequoia_2020_summoner
简单题
1 | from pwn import * |
sctf2019_easy_heap
这个题有点绕,fill函数中存在off-by-null思路是通过shrink chunk来实现uaf,然后利用uaf,往bss上写main_arena
,然后再分配到bss上,修改main_arnea指向malloc_hook写入ad,并在ad处写入shellcode
1 | from pwn import * |
rootersctf_2019_babypwn
简单题
1 | from pwn import * |
ciscn_2019_c_5
简单题
1 | from pwn import * |
nsctf_online_2019_pwn1
ubuntu16,思路是利用off-by-null来uaf,然后攻击stdout泄露Libc,最后打malloc_hook
1 | from pwn import * |
bbctf_2020_write
exit_hook
1 | from pwn import * |
ciscn_2019_c_3
ubuntu18 + uaf + 大小限制为0x100,0x4f,0x60,有show,只能写heap + 0x10,有后门函数可以fd++,思路是通过fd++来修改
下个堆的fd到malloc_hook然后写og
1 | from pwn import * |
ciscn_2019_s_8
程序很复杂,可以看一下大致的流程,只知道要读入一段数据长度限制为0x200,然后验证,可以先试试输入0x200个”a”,然后你会发现
程序最后ret到了0x0404040404040404这个地址,此时再修改开始前8个字符,gdb调试可以得到一串对应的字符表,于是对应字母表
直接rop(补充:需要在本地建一个.txt,参考程序流程)
1 | from pwn import * |
rctf_2019_babyheap
ubuntu16+禁用fastbin,思路是house of storm + setcontext
1 | from pwn import * |
actf_2019_message
简单题
1 | from pwn import * |
[Black Watch 入群题]PWN2
参考新春红包题(libc-2.29下的tcache stash unlink attack)
1 | from pwn import * |
mrctf2020_spfa
一个spfa算法,构造0环,就能出
1 | from pwn import * |
huxiangbei_2019_hacknote
静态编译的ubuntu16下的堆,思路是找到malloc函数中的malloc_hook,然后通过edit函数的off-by-one来uaf分配到malloc_hook上
写shellcode
1 | from pwn import * |
2018_treasure
8字节shellcode,学到很多
1 | from pwn import * |
hitcontraining_secretgarden
fastbin attack+double free
1 | from pwn import * |
watevr_2019_voting_machine_1
签到题
1 | from pwn import * |
wdb_2018_3rd_pesp
简单堆题
1 | from pwn import * |
[中关村2019]one_string
静态编译ubuntu16+32位的堆题,一开始用fastbin失败了,于是unlink + malloc_hook
1 | from pwn import * |
axb_2019_mips
参考https://blog.csdn.net/seaaseesa/article/details/105281585
1 | #coding:utf8 |
ciscn_2019_es_5
需要用到realloc(0)free的小trick
1 | from pwn import * |
starctf2018_babystack
栈溢出修改tls结构,然后栈迁移到bss上使用orw来getflag(补充:使用system或者execve能获取到权限,但是会出现timeout错误)
1 | from pwn import * |
hctf2018_the_end
exit_hook + exec 1>&0(ubuntu-18)
1 | from pwn import * |
gyctf_2020_bfnote
tls+ret2al
1 | from pwn import * |
TWCTF_online_2019_asterisk_alloc
这里只要想到realloc(ptr,0)时会将ptr_r置零就可以了
1 | from pwn import * |
pwnable_seethefile
学到很多利用伪造FILE结构,以及fclose(fp)来getshell
1 | from pwn import * |
metasequoia_2020_samsara
简单题,ubuntu16 + uaf还给了后门函数cat flag
1 | from pwn import * |
x_nuca_2018_offbyone2
off-by-null + ubuntu18经典题
1 | from pwn import * |
gwctf_2019_chunk
off-by-null + ubuntu16
1 | from pwn import * |
安洵杯_2018_neko
基础栈溢出
1 | from pwn import * |
ciscn_2019_sw_5
ubuntu18,这个题只有new和delete函数,只有三次free的机会,思路大概就是double修改fd来实现多次任意地址写,最后hook改og
1 | from pwn import * |
pwnable_calc
32位静态编译,这个题挺有意思的,思路是利用+offset实现任意地址写(覆盖calc函数的栈,这样退出函数的时候就可以rop了)
1 | from pwn import * |
ciscn_2019_qual_virtual
save和load功能存在问题(参考https://www.anquanke.com/post/id/208450)
1 | from pwn import * |