리눅스에서는 프로세스의 메모리를 적재되는 데이터의 용도별로 총 5가지의 세그먼트로 구분합니다.크게 코드 세크먼트, 데이터 세그먼트, BSS 세그먼트, 힙 세그먼트, 스택 세그먼트가 있습니다.운영체제가 메모리를 용도별로 나누면, 각 용도에 맞게 적절한 권한(읽기, 쓰기,
Q1. "d_str"이 위치하는 세그먼트는 어디인가?정답 : 문자열 "d_str"은 읽기 전용 데이터(rodata) 세그먼트에 저장됩니다.Q2. b가 위치하는 세그먼트는 어디인가?정답 : b는 전역상수이기 때문에 데이터 세그먼트에 위치합니다.Q3. e는 어느 세그먼트의
범용 레지스터
Q1. rax = 0x0123456789abcdef 일 때, ax의 값은?ax 레지스터 → 2 Byte정답 : 0xcdefQ2. rax에서 rbx를 뺐을 때, ZF가 설정되었다. rax와 rbx의 대소를 비교하시오.ZF (Zero Flag) → 연산 결과가 0일 경우
어셈블리 언어는 기계어와 치환되는 언어입니다.기본 구조는 명령어(Opcode)와 피연산자(Operand)로 구성됩니다.상수레지스터메모리메모리 피연산자는 로 둘러싸인 것으로 표현되며, 앞에 크기 지정자는 TYPE PTR이 추가될 수 있습니다.타입에는 BYTE, WORD
end로 점프하면 프로그램이 종료된다고 가정하자. 프로그램이 종료됐을 때, 0x400000 부터 0x400019까지의 데이터를 대응되는 아스키 문자로 변환하면 어느 문자열이 나오는가?코드를 한 줄 한 줄 해석하며 Memory에 값을 수정해보면.....rcx가 0x19보
Opcode: stack push val : val를 스택 최상단에 쌓음 연산 rsp = rsp - 8 [rsp] = val pop reg : 스택 최상단의 값을 꺼내서 reg에 대입 연산 rsp = rsp + 8 reg = [rsp-8] Opcode: 프로시
로컬 바이너리 대상 익스플로잇에 사용원격 서버를 대상으로 할 때 사용데이터를 프로세스에 전송p32() : 32 bit 리틀 엔디안 방식으로 packing 해주는 함수p64() : 64 bit 리틀 엔디안 방식으로 packing 해주는 함수어셈블리어를 기계어로 변환할 때
로컬 바이너리 대상 익스플로잇에 사용원격 서버를 대상으로 할 때 사용데이터를 프로세스에 전송p32() : 32 bit 리틀 엔디안 방식으로 packing 해주는 함수p64() : 64 bit 리틀 엔디안 방식으로 packing 해주는 함수어셈블리어를 기계어로 변환할 때
익스플로잇을 위해 제작된 어셈블리 코드 조각, 일반적으로 쉘을 획득하기 위한 목적으로 사용합니다.syscall 요청 : rax인자 순서 : rdi → rsi → rdx → rcx → r8 → r9 → stackint fd = open("/tmp/flag", RD_ONL
함수의 호출 및 반환에 대한 약속입니다.함수를 호출할 때는 반환된 이후를 위해 호출자(Caller)의 상태(Stack frame)및 반환 주소(Return Addresss)를 저장해야 합니다. 또한 호출자는 피호출자(Callee)가 요구하는 인자를 전달해 줘야 하며,
함수를 호출할 때 넘겨줄 인자를 push 할 때는 뒤에서부터 push 합니다.(a) push 0x3(b) push 0x2(c) push 0x11, 2, 3 총 3개의 정수형 인자를 정리하는 것이기 때문에, 4 \* 3 = 12 = 0xc(d) add esp, 0xcSY
스택의 버퍼에서 발생하는 오버플로우를 뜻합니다.버퍼 : 컴퓨터 과학에서 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소의 의미로 쓰였으나 현대에는 데이터가 저장될 수 있는 모든 단위로 쓰이기도 합니다.오버플로우 : 넘쳐 흐르다 라는 뜻으로 10 바이트 크기의 버퍼
<취약점 분석>main함수에서 scanf("%s", buf)를 보면 입력 길이에 제한 없이 입력을 받고 있습니다. 그래서 오버플로우 공격이 가능합니다.크기가 0x28 바이트인 버퍼에 입력을 받고 있기 때문에, 0x28 바이트 이상의 데이터를 입력하면 버퍼 오버플로
스택 카나리함수 프롤로그에서 스택 버퍼와 반환 주소 사이에 임의의 값을 삽입하고 에필로그에서 해당 값의 변조를 확인하는 보호 기법입니다.스택 버퍼 오버플로우로 반환 주소를 덮으려면 먼저 카나리 값을 덮어야 하기 때문에, 카나리 값을 모르는 공격자는 카나리 값을 변조하게
보호 기법 탐지checksec 명령어를 입력하면 바이너리 적용된 보호 기법을 확인할 수 있습니다.취약점 탐색buf의 주소와 buf~rbp까지의 거리를 출력해주고 있습니다.read와 gets 함수에 의해 두번의 버퍼 오버플로우가 발생합니다.익스플로잇 시나리오첫번째 입력값
Address Space Layout Randomization(ASLR)은 바이너리가 실행될 때마다 스택, 힙, 공유 라이브러리 등을 임의의 주소에 할당하는 보호 기법입니다.예시 코드로 주소가 어떻게 바뀌는지 봐보면main 함수를 제외한 다른 영역의 주소는 모두 실행할
컴퓨터 시스템에서, 프로그램들이나 함수나, 변수를 공유해서 사용할 수 있게 합니다.예를 들어 C 프로그래밍을 할 때 공통적으로 printf, scanf, streln, memcpy, malloc 등의 함수들을 많이 사용하는데, C언어를 포함한 많은 언어들은 자주 사용되
답 : O정적 링크된 바이너리는 라이브러리의 모든 함수를 포함하고 있어서 용량이 100배 정도 큽니다.답 : X답 : X정적 링크된 바이너리는 자신의 함수를 호출하는 것처럼 함수를 호출할 수 있습니다.답 : XPLT에서 GOT를 참조하여 실행 흐름을 옮길 때, GOT의
버퍼 오버플로우 취약점으로 반환 주소를 덮을 때, NX 방어기법을 우회하기 위해 system이나 execve 같은 libc 함수들을 이용하는 공격 기법입니다.실습 코드보호 기법Canary와 NX 보호 기법이 걸려있습니다. 그리고 최신 리눅스 커널이기 때문에 ASLR이
ROP는 리턴 가젯을 사용해서 복잡한 실행 흐름을 구현하는 기법입니다. 공격자는 이를 이용해서 문제 상황에 맞춰 return to library, return to dl-resolve, GOT overwrite 등의 페이로드를 구성할 수 있습니다.보호 기법ASLR, C
쓰기 권한이 불필요한 데이터 세그먼트에서 쓰기 권한을 제거합니다.RELRO는 범위에 따라 부분적으로 적용하는 Partial RELRO와 가장 넓은 영역에 적용하는 Full RELRO가 있습니다.쓰기 권한이 할당되어 있는 주소를 찾아보면 0x404000-0x405000에
답 : O답 : X.bss, .data, .got.plt 영역에만 쓰기 권한이 남아있다.답 : X.bss, .data 영역에만 쓰기 권한이 남아있다.답 : O
ASLR이 코드 영역에도 적용되게 해주는 기술입니다.코드 베이스 우회코드 영역의 임의의 주소를 읽고, 그 주소에서 오프셋을 빼면 됩니다.Partial OverwriteASLR 특성 상, 코드 영역의 주소도 하위 12비트 값은 항상 같기 때문에, 코드 가젯의 주소가 반환
C언어에서 메모리의 동적 할당과 해제를 담당하는 함수에는 대표적으로 malloc, free, realloc이 있습니다.이 함수들은 libc.so에 구현되어 있고 libc 에는 이 함수들의 디버깅 편의를 위해 훅 변수가 저장되어 있습니다.malloc 함수를 봐보면\_\_
배열의 크기 : 요소의 개수와 자료형의 크기를 곱한 것배열의 참조 : 배열의 주소, 인덱스, 자료형의 크기를 이용하여 계산배열 요소를 참조할 때, 인덱스 값이 음수이거나 배열의 길이를 벗어났을 때 발생합니다.사용자가 인덱스 값을 임의로 설정하여 특정 오프셋에 있는 메모
OOB 취약점을 방어하기 위해 A 위치에 들어갈 올바른 검증 코드는?A : if (index < 0x10) {exit(-1);}B : if (index > 0x10) {exit(-1);}C : if (index <= 0x10) {exit(-1);}D : if
인자를 어떻게 사용할지 지정최소 너비를 지정. 치환되는 문자열이 이 값보다 짧으면 공백 문자 패딩참조할 인자의 인덱스를 지정하고 필드의 끝을 $로 표기.인덱스의 범위를 전달된 인자의 개수와 비교하지 않음.인덱스를 지정하여 두 번째 첫 번째 순서로 출력하게 해서 1, 2
printf(buf) 부분에서 포맷 스트링 버그가 발생합니다.Canary를 제외한 모든 방어기법이 걸려있습니다.1\. changeme 주소 구하기changeme 변수 값을 조작하려면 주소를 알아야 하는데, PIE 방어기법이 걸려 있어서 주소가 실행할 때 마다 바뀝니다.
Use After Free Dangling Pointer : 유효하지 않은 메모리 영역을 가리키는 포인터 malloc() → 할당된 메모리 주소 반환 메모리 동적 할당 1\. 포인터를 선언 2\. 포인터에 malloc() 함수가 할당한 메모리 주소 저장 3\
보호 기법모든 보호 기법이 적용되어 있습니다.Full RELRO 보호 기법으로 인해 GOT Overwrite는 힘듭니다. 그래서 라이브러리에 존재하는 훅 또는 코드에서 사용하는 함수 포인터를 덮는 방법을 생각해 볼 수 있습니다.코드 분석1\. Human과 Robot이라
ptmalloc2(pthread malloc 2)는 dlmalloc을 개선한 ptmalloc의 두번째 버전 Memory Allocator입니다.ptmalloc의 구현 목표는 메모리의 효율적인 관리입니다.핵심1\. 메모리의 낭비 방지2\. 빠른 메모리 재사용3\. 메모리
Double Free Bug (DFB)는 같은 청크를 두 번 해제할 수 있는 버그를 말합니다. ptmalloc2에서 발생하는 버그 중 하나이며, 공격자에게 임의 주소 쓰기, 임의 주소 읽기, 임의 코드 실행, 서비스 거부 등의 수단으로 활용될 수 있습니다.Danglin
Tcache Poisoning Tcache Poisoning은 tcache를 조작하여 임의 주소에 청크를 할당시키는 공격 기법을 말합니다. 원리 중복으로 연결된 청크를 재할당하면, 그 청크는 할당된 청크이면서, 동시에 해제된 청크가 됩니다. 이때 할당된 청크에서
변수의 자료형을 선언할 때는 변수를 활용하는 동안 담게 될 값의 크기, 용도, 부호, 여부를 고려해야 합니다. Type error는 이러한 고려 없이 부적절한 자료형을 사용했을 때 발생합니다.int res에 unsigned long long factorial의 값을 반
인젝션은 악의적인 데이터를 프로그램에 입력하여 이를 시스템 명령어, 코드, 데이터베이스 쿼리 등으로 실행되게 하는 기법을 말합니다. 이중 시스템 명령어로 실행하게 하는 것을 command injection이라고 부릅니다.Command injection은 명령어를 실행하
사용자에게 각자의 디렉터리를 생성해주고, 그 디렉터리를 자유롭게 활용할 수 있게 해주는 서비스가 있다면, 당연히 사용자는 자신의 디렉터리만 접근할 수 있도록 해야 합니다.Path Traversal은 위와 같은 서비스가 있을 때, 사용자가 허용하지 않은 경로에 접근할 수
샌드박스(sandbox)는 외부의 공격으로부터 시스템을 보호하기 위해 설게된 기법입니다.샌드박스는 Allow List와 Deny List 두 가지를 선택해 적용할 수 있으며, 꼭 필요한 시스템 콜 실행, 파일의 접근만 허용합니다.다음 장에서 Sandbox 메커니즘 중
같은 기능을 하는 다른 시스템 콜을 호출합니다.Ex) open syscall과 openat syscall다양한 아키텍처가 존재하고 아키텍처 별로 명령어 세트와 기능, 크기 등이 다르기 때문에 애플리케이션 운영 목적에 따라 알맞은 아키텍처를 선택해 사용합니다. 따라서 커
Thread Local Storage (TLS)는 스레드의 전역 변수를 저장하기 위한 공간으로, 로더(Loader)에 의해서 할당됩니다.\_dl_allocate_tls_storage 함수에서 TLS 영역을 할당하고 이를 tcbp에 저장한 뒤 TLS_INIT_TP 매크로
스레드 함수에서 선언된 변수는 일반적인 함수와 달리 TLS와 인접한 영역에 할당됩니다. 그러나 버퍼를 할당을 때 TLS 영역에 존재하는 마스터 카나리 값을 참조한다는 점은 동일합니다.스레드에서 할당한 변수는 마스터 카나리가 위치하는 주소보다 낮은 주소에 있기 때문에 버
main 함수 ret에 breakpoint를 걸고 step into를 통해 다음 코드를 살펴보면 libc_start_main+231의 코드가 실행되고, GI_exit 함수가 호출됩니다.step into로 \_\_GI_exit 함수 내부를 봐보면또 다른 \_\_run_e
들어가며 rtldglobal 덮어쓰기 실습 예제
한경변수는 매번 변할 수 있는 동적인 값들의 모임으로, 시스템의 정보를 갖고 있는 변수입니다.
시그널은 프로세스에 특정 정보를 전달하는 매개체로, 우리가 프로그램을 공격할때 보았던 SIGSEGV 또한 시그널에 포함됩니다. 시그널이 발생하면 시그널에 해당하는 코드가 커널 모드에서 실행되고, 다시 유저 모드로 복귀합니다.다음은 5초 후에 sig_handler를 호출
16 바이트 크기의 버퍼에 1024 바이트를 입력할 수 있기 때문에 버퍼 오버플로우가 발생합니다. 주어진 gadget 함수의 코드를 이용해서 sigreturn 시스템 콜을 호출하여 레지스터를 조작하고 쉘을 흭득할 수 있습니다.1\. sigreturn 호출gadget 함
파일에 데이터를 쓰기 위한 함수는 대표적으로 fwrite, fputs가 있습니다. 해당 함수는 라이브러리 내부에서 \_IO_sputn 함수를 호출합니다. 코드를 봐보면 해당 함수는 \_IO_XSPUTN 함수의 매크로이며 \_IO_new_file_xsputn 함수를 실행
파일 읽기 함수는 대표적으로 fread, fgets가 있는데, 해당 함수는 라이브러리 내부에서 \_IO_file_xsgetn 함수를 호출합니다.해당 함수는 인자로 전달된 n이 \_IO_buf_end - \_IO_buf_base 값보다 작은지를 검사하고 \_\_under
해당 기법은 glibc 2.29 버전 이상에서 더 이상 사용할 수 없기 때문에 드림핵 워게임 문제에서 제공하는 파일을 다운 받아 실습해야 합니다.Bypass IO_validate_vtablevtable은 \_\_libc_IO_vtables 섹션에 할당됩니다.해당 섹션의