成理工恐龙杯-PWN-WP
ezrop分析:
main函数中存在格式化字符串漏洞和栈溢出。但是这题开了PIE和canary,所以还需要leak canary和pie基址。
我是利用格式化字符串去读的__libc_csu_init+77这个地址,然后利用puts把canary带出来。
接下来的rop就没什么好说的了。
exp:12345678910111213141516171819202122232425262728293031323334from pwn import *context.log_level = 'debug'# p = process('./pwn')p = remote('47.109.18.98', 9128)elf = ELF('./pwn')# pay = b'AA.%8$s'pay = b'%15$p'p.recvline()p.send(pay)p.recvuntil('exit\n')p.sendline('3')p.rec ...
i-SOON_CTF_2021-PWN WP
#1 noleak这个题需要先通过secret()的检查才能进入到主程序。
可以看出来,就是一个简单的栅栏加密。
但是要注意的是,他用的是4个32bit的整数来存,程序使用小端字节序,所以要从最低位开始。
解密后的结果是
1buf = '\x4e\x30\x5f\x70\x79\x5f\x31\x6e\x5f\x74\x48\x65\x5f\x63\x74\x37'
然后分析每个功能,在edit()中发现了off by null
12v0 = read(0, (void *)chunks[2 * v2], LODWORD(chunks[2 * v2 + 1]));v3[v0] = 0;
所以可以利用这个溢出的\x00来修改下一个chunk的prev_inuse位,导致前面的chunk被合并,放进unsorted bin,可以leak libc。(house of einherjar)
(用三个chunk,chunk A, chunk B, chunk C,需要先把chunk A和chunk C的size的tcache装满,然后利用chunk B去o ...
heapcreator(off by one)
分析遇到的第一个off by one问题吧(之前有在ctf-wiki上看到过off by one的利用手法,所以就忍不住想实践一下)
菜单没什么特别的,设置了无缓冲
create_heap函数也很常规,每个内容都用了一个结构体来管理,size用来控制可写进去的长度,然后一个指针代表内容chunk的位置。(程序只开了Partial RELRO,所以got表是可以去改的)很容易联想到,要想办法来修改掉这个指针。
edit_heap函数可以发现,在读内容的时候,他读了(*(_QWORD *)heaparray[v1]+1LL)位,加了1,所以存在off by one,可以改掉后面chunk的size的最低位。
show_heap函数没什么好说的,用的是%s来打印chunk(一开始想用unlink来做,就是被这个输出方式给卡了hhh,不过现在的方法是比unlink简单许多的)
delete_heap函数也没什么好说的,清空了heaparray[v1],没有uaf。
分析完程序过后,思路基本上就已经出来了。
1.申请三个0x21的chunk,chunk 0去off by one改掉结构 ...
zctf2016_note2
unlink利用
这题自己写了一个read方法,代码如下
结束条件是传进来的第三个参数,这题一般传的都是0xa,也就是换行。
但是循环变量i是unsigned,所以当len-1为-1,即len为0时,差不多可以读0xffffffffffffffff个字符,能造成堆溢出。而len为0时,ptmalloc2还是会开出一个0x21的chunk(header+fd+bk)。
申请的时候会调用之前那个自己写的read函数来初始化content,然后会记录一个size到一个数组上,这个size在修改的时候会用来限制修改的长度。sub_400B10()会过滤掉’%’。
edit函数比较有意思,提供了覆写和添加两种修改方式,用的是strncat()和strcpy()来实现,这就需要注意了,在改写的时候如果有’\x00’应该是会打断修改的,所以如果要把某个地址写进去,只能写一个。
删除还是常规的清空了指针数组对应的位置,以及size数组对应的位置。
show的功能是用%s实现的。
一开始我是想用house of spirit去申请到指针数组前面一点的chunk的(fakechunk的siz ...
hitcon2014_stkof(unlink)
分析很经典的unlink入门题。
还是菜单题,没什么好说的。
4个函数,一个申请,一个编辑,一个free,一个意义不明(?)。
简单的来说,在sub_4009E8()里存在堆溢出漏洞,没有检查长度。然后在sub_400B07()里free掉chunk之后是会把bss段上那个数组相应的位置清0的。
还有一点就是,这题没有使用setvbuf()来关闭缓冲,所以在第一次输入和输出的时候都会malloc 0x411的chunk作为缓冲区(但是gdb调试的时候发现,输入的缓冲区会开到0x1011)
没有开FULL RELRO,所以got表还是可以改的。
由于没有打印堆块的功能,所以这题需要用到unlink来改写某个函数的got表指向puts@plt(没错,我又要改free的got表)
还是分为两步来做:
leak libc:
准备工作:申请一个chunk,把输入输出缓冲区的malloc给弄出来,保证后面的chunk都是连续的。
然后申请一个用来uaf的chunk和一个被free后能放进unsortedbin的chunk。再申请一个chunk保证要free进unsortedbin的chun ...
babyheap_0ctf_2017
分析一道很适合初学者的heap题,方法应该是特别多的。
ida x64反编译:
先看allocate函数:
大概可以还原出数据元素的结构:
12345struct Ele{ long long vis; //标记是否可用 long long size; //打印该chunk的时候的长度 malloc_chunk * chunk_addr; //chunk的地址};
值得注意的一点是,这里在申请内存的时候使用的是calloc(),也就是说,会把userdata都清空为’\x00’。
所以后面去制造堆块的重叠的时候需要修复chunkheader。
再分析一下fill函数:
很明显,只检查了越界,但是没有检查是否溢出。
free函数:
没有uaf。
最后看dump函数:
输出的长度是取决于创建heap的时候记下来的那个size。
没有看到system之类的函数,所以应该需要leak一下libc了。
那么做题可以分为两大步骤:
1.Leak libc
基本的思路就是利用被放到unsorted bin或small bin的双链表里时,只有一个chunk的时 ...
ZJCTF 2019-EasyHeap
分析还是在buu上找的题,应该算是heap入门级别的题吧。
ida x64分析代码:
简单的来看,还是一道菜单题,有创建,编辑,删除的功能,但是没有show之类的。
值得注意的一点是,当选择4869的时候,会去查看bss段的一个magic变量的值,如果不小于4869的话就能进到后门函数l33t()里。
不管这个路径对不对,反正不用leak libc来拿system函数了。(做过一遍表示,这个路径在buu确实不对)
简单看了一下几个功能,delete的时候清空了heaparray上对应的指针,很难uaf。
但是在edit的时候,重新输入了一个长度,并且这个长度没有检查大小,所以是存在堆溢出的。
这个时候就可以用到fastbin attack来实现一个任意内存的读取。
简单的来说,原理就是利用fastbin只用了单链表来维护,并且没有复杂的unlink机制,将fastbin里面某个fd改成目标fakechunk,然后再利用那个fakechunk的位置去edit,就能达到目的。
不管是想要改magic还是说在heaparray上改掉某个函数的got表,都必须去0x6020e8之前的位置 ...
time_formatter(uaf)
分析原题在adworld上。
ida x64反汇编代码如下(部分函数被我改了名):
选择4进到的函数里发现了程序是把time和fmt的内容拼接到了命令里运行
命令如下:
1/bin/date -d @%d +'%s'
不难发现,只需要在fmt这里动一动手脚,就能getshell
1/bin/date -d @%d +'' ; sh''
但是经过一番分析,发现在设置fmt的时候,这里是有一个字符白名单的,而常用的&;|这些都不能用,也没办法闭合单引号。
(当时就在想,能不能利用stack来覆写白名单,但这里显然不行)
再检查一下在读fmt和读timezone的时候都出现了的一个函数
在sub_400C26里发现了一个strdup(),这个函数的原型如下:
12345678char * __strdup(const char *s){ size_t len = strlen(s) +1; void *new = malloc(len); if (new == NULL) r ...
《计算机网络》笔记
e8496f79aa2ce6656f1170ed582153dbd7c889c5f92506d114457b6c1d59e4921ac8ace45239d43f5cd2afce40b7ec4961197d96961e93f4a7551a7786a7c7bc83b434360c8987196a4dd2559397e14e8f49bf4eb00f5077221bcff49e5a8d774d7c797905050b0760eb902a50ba2cfb56357b8484c8d0562ef7899bd9a3ba2f8074c88b3410555950255e902444cda3aa9672928f245ecf52caac555cf5107c428c64e6c676728358e2d3813bae8e2d2edb56305c7054bbecbde62b3da8c8bfebd7eb2e0c504b040f0f7286f9bfd662e700b11b2269c366bf87355bae9981018406d9a92b04e371bf84c99415c9ac5ca3d5860b8073bba3b ...
hitcontraining_uaf(UAF漏洞简单的利用)
分析(从9月底到现在经过了近3个月的学习,终于做到heap题了hhhhh)
整道题围绕着三个函数进行,直接上反编译的截图。
add_note
从这个函数可以大概的看出来整个程序只能存5个note(下标为0-4),然后对于每一个note都由两部分组成,第一部分是申请0x8bytes来存一个函数指针,第二部分是申请你指定大小的bytes来存自己输入的内容。申请成功过后让计数用的全局变量count自增1。
del_note
这个删除函数就是简单的检查了一下下标是否有越界,然后先去free掉写内容的那一块,再free掉前面开来存函数指针的那一块。比较有意思的就是,删除了之后,count并不会因此而减少(这就有意思了)。
print_note
这个print_note和删除写的类似,也是先检查下标是否越界,然后就去调用存放在第一部分的那个指针指向的函数。这个指针在add_note函数里是初始指向了一个能打印出后面内容的函数。
此外,程序还含有一个后门函数magic(),功能是执行”\bin\sh”。
分析至此,思路已经十分清晰了,就是去劫持print_note函数调用的那个函数指针 ...