티스토리 뷰

최초 작성일 : 2015 - 10 - 24 20:38

최종 주성일 : 2015 - 10 - 24 23:37


주의: 완성된 포스팅이 아닙니다. 사실확인이 되어 있지 않으며 잘못된 정보일 수 있습니다.



root@Ubuntu:~# ldd LIBC_RANDOM

linux-gate.so.1 =>  (0xb7718000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7540000)

/lib/ld-linux.so.2 (0xb7719000)

root@Ubuntu:~# ldd LIBC_RANDOM

linux-gate.so.1 =>  (0xb772b000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7553000)

/lib/ld-linux.so.2 (0xb772c000)

root@Ubuntu:~# ldd LIBC_RANDOM

linux-gate.so.1 =>  (0xb7700000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7528000)

/lib/ld-linux.so.2 (0xb7701000)


위와 같이, 기본적으로 Ubuntu 15.04 버전에서는 ASLR이 적용되어 있다.

하지만 우리가 익히 알고 있듯, 


ulimit -s unlimited


명령어를 사용하면 ASLR이 꺼지게 돼있다. 그렇다면 왜 그런지 알아보도록 하자.

reference : http://security.cs.pub.ro/hexcellents/wiki/kb/exploiting/home


Linux/arch/x86/mm/mmap.c에 이 부분에 관하여 정의하고 있다고 한다.

https://github.com/torvalds/linux/blob/master/arch/x86/mm/mmap.c



/*
* Flexible mmap layout support
*
* Based on code by Ingo Molnar and Andi Kleen, copyrighted
* as follows:
*
* Copyright 2003-2009 Red Hat Inc.
* All Rights Reserved.
* Copyright 2005 Andi Kleen, SUSE Labs.
* Copyright 2007 Jiri Kosina, SUSE Labs.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/personality.h>
#include <linux/mm.h>
#include <linux/random.h>
#include <linux/limits.h>
#include <linux/sched.h>
#include <asm/elf.h>
struct va_alignment __read_mostly va_align = {
.flags = -1,
};
static unsigned long stack_maxrandom_size(void)
{
unsigned long max = 0;
if ((current->flags & PF_RANDOMIZE) &&
!(current->personality & ADDR_NO_RANDOMIZE)) {
max = ((-1UL) & STACK_RND_MASK) << PAGE_SHIFT;
}
return max;
}
/*
* Top of mmap area (just below the process stack).
*
* Leave an at least ~128 MB hole with possible stack randomization.
*/
#define MIN_GAP (128*1024*1024UL + stack_maxrandom_size())
#define MAX_GAP (TASK_SIZE/6*5)
static int mmap_is_legacy(void)
{
if (current->personality & ADDR_COMPAT_LAYOUT)
return 1;
if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
return 1;
return sysctl_legacy_va_layout;
}
unsigned long arch_mmap_rnd(void)
{
unsigned long rnd;
/*
* 8 bits of randomness in 32bit mmaps, 20 address space bits
* 28 bits of randomness in 64bit mmaps, 40 address space bits
*/
if (mmap_is_ia32())
rnd = (unsigned long)get_random_int() % (1<<8);
else
rnd = (unsigned long)get_random_int() % (1<<28);
return rnd << PAGE_SHIFT;
}
static unsigned long mmap_base(unsigned long rnd)
{
unsigned long gap = rlimit(RLIMIT_STACK);
if (gap < MIN_GAP)
gap = MIN_GAP;
else if (gap > MAX_GAP)
gap = MAX_GAP;
return PAGE_ALIGN(TASK_SIZE - gap - rnd);
}
/*
* Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
* does, but not when emulating X86_32
*/
static unsigned long mmap_legacy_base(unsigned long rnd)
{
if (mmap_is_ia32())
return TASK_UNMAPPED_BASE;
else
return TASK_UNMAPPED_BASE + rnd;
}
/*
* This function, called very early during the creation of a new
* process VM image, sets up which VM layout function to use:
*/
void arch_pick_mmap_layout(struct mm_struct *mm)
{
unsigned long random_factor = 0UL;
if (current->flags & PF_RANDOMIZE)
random_factor = arch_mmap_rnd();
mm->mmap_legacy_base = mmap_legacy_base(random_factor);
if (mmap_is_legacy()) {
mm->mmap_base = mm->mmap_legacy_base;
mm->get_unmapped_area = arch_get_unmapped_area;
} else {
mm->mmap_base = mmap_base(random_factor);
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
}
const char *arch_vma_name(struct vm_area_struct *vma)
{
if (vma->vm_flags & VM_MPX)
return "[mpx]";
return NULL;
}
view raw mmap.c hosted with ❤ by GitHub



static int mmap_is_legacy(void)
{
if (current->personality & ADDR_COMPAT_LAYOUT)
return 1;
if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)
return 1;
return sysctl_legacy_va_layout;
}


mmap_is_legacy() 함수를 보면 


if (rlimit(RLIMIT_STACK) == RLIM_INFINITY)

return 1;


이런 부분을 볼 수 있다. unlimited 로돼 있으면 return 1;을 해준다.

그리고 같은 파일에서 mmap_is_legacy 함수를 참조하는 다른 함수들을 확인해보자.


*return 1이 실행 안됐을 시에 리턴 해주는 sysctl_legacy_va_layout은 아래 파일에서 0으로 정의 되어 있음

*http://lxr.free-electrons.com/source/include/linux/mm.h



/*
* This function, called very early during the creation of a new
* process VM image, sets up which VM layout function to use:
*/
void arch_pick_mmap_layout(struct mm_struct *mm)
{
unsigned long random_factor = 0UL;
if (current->flags & PF_RANDOMIZE)
random_factor = arch_mmap_rnd();
mm->mmap_legacy_base = mmap_legacy_base(random_factor);
if (mmap_is_legacy()) {
mm->mmap_base = mm->mmap_legacy_base;
mm->get_unmapped_area = arch_get_unmapped_area;
} else {
mm->mmap_base = mmap_base(random_factor);
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
}

*arch_pick_mmap_layout에서 참조함


mmap_is_legacy 함수를 실행하여 참이면 mm->mmap_base를 mmap_legacy_base()함수를 사용하여

대입해준다. mmap_legacy_base() 함수안에서 32비트인지 확인해주는 코드가 있고 

32비트이면 그냥 TASK_UNMAPPED_BASE를 리턴해주고 64비트이면 TASK_UNMAPPED_BASE에 랜덤한 값을 더해준 

값을 리턴해준다.


/*
* Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64
* does, but not when emulating X86_32
*/
static unsigned long mmap_legacy_base(unsigned long rnd)
{
if (mmap_is_ia32())
return TASK_UNMAPPED_BASE;
else
return TASK_UNMAPPED_BASE + rnd;
}


mmap_is_ia32는 32비트인지 확인하는 함수이며, 이부분을 통해 왜 64비트에서는 ASLR이 풀리지 않는지 알 수 있다.

(이 부분은 mmap_legacy_base 함수의 주석부분에서도 확인 할 수 있다.)

/*

 * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64

 * does, but not when emulating X86_32

 */

* 수정되었습니다.

(mmap_is_ia32() 함수는 elf.h에서 확인 할 수 있습니다.)

https://github.com/torvalds/linux/blob/097f70b3c4d84ffccca15195bdfde3a37c0a7c0f/arch/x86/include/asm/elf.h

주석으로 보아 32비트이거나 64비트에서 32비트 에뮬레이션일 경우 true를 반환해주는 것 같습니다.


대충 요약해보자면,

1. unlimited인지 mmap_is_legacy() 함수에서 확인함.

2. mmap_is_legacy 함수를 arch_pick_mmap_layout 함수에서 사용하여 참이면 mmap_base를 mmap_legacy_base() 함수를

  이용하여 대입해줌

3. mmap_legacy_base() 함수는 32비트인지 64비트인지 확인하고 32비트면 랜덤을 적용하지 않고 base를 설정하고

  64비트면 mmap_rnd(); 함수를 통하여 랜덤적용을 해줌.



root@Ubuntu:~# ulimit -s unlimited

root@Ubuntu:~# ldd LIBC_RANDOM

linux-gate.so.1 =>  (0x40026000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x40042000)

/lib/ld-linux.so.2 (0x40000000)

root@Ubuntu:~# ldd LIBC_RANDOM

linux-gate.so.1 =>  (0x40026000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x40042000)

/lib/ld-linux.so.2 (0x40000000)

root@Ubuntu:~# ldd LIBC_RANDOM

linux-gate.so.1 =>  (0x40026000)

libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x40042000)

/lib/ld-linux.so.2 (0x40000000)




REFERENCES

http://security.cs.pub.ro/hexcellents/wiki/kb/exploiting/home

http://lxr.free-electrons.com/source/include/linux/mm.h

https://github.com/torvalds/linux/blob/master/arch/x86/mm/mmap.c\

https://github.com/torvalds/linux/blob/097f70b3c4d84ffccca15195bdfde3a37c0a7c0f/arch/x86/include/asm/elf.h

'Pwnable > System 잡지식' 카테고리의 다른 글

Pwnable 워게임 사이트, 문서 정리  (2) 2015.01.28
ASLR 활성/비활성  (2) 2014.10.04
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함